lx-music-desktop/src/renderer/core/music/local.ts
2024-03-08 11:54:00 +08:00

166 lines
5.6 KiB
TypeScript

import { encodePath } from '@common/utils/common'
import { updateListMusics } from '@renderer/store/list/action'
import { saveLyric, saveMusicUrl } from '@renderer/utils/ipc'
import { getLocalFilePath } from '@renderer/utils/music'
import {
buildLyricInfo,
getCachedLyricInfo,
getOnlineOtherSourceLyricByLocal,
getOnlineOtherSourceLyricInfo,
getOnlineOtherSourceMusicUrl,
getOnlineOtherSourceMusicUrlByLocal,
getOnlineOtherSourcePicByLocal,
getOnlineOtherSourcePicUrl,
getOtherSource,
} from './utils'
const getOtherSourceByLocal = async<T>(musicInfo: LX.Music.MusicInfoLocal, handler: (infos: LX.Music.MusicInfoOnline[]) => Promise<T>) => {
let result: LX.Music.MusicInfoOnline[] = []
result = await getOtherSource(musicInfo)
if (result.length) try { return await handler(result) } catch {}
if (musicInfo.name.includes('-')) {
const [name, singer] = musicInfo.name.split('-').map(val => val.trim())
result = await getOtherSource({
...musicInfo,
name,
singer,
}, true)
if (result.length) try { return await handler(result) } catch {}
result = await getOtherSource({
...musicInfo,
name: singer,
singer: name,
}, true)
if (result.length) try { return await handler(result) } catch {}
}
let fileName = musicInfo.meta.filePath.split(/\/|\\/).at(-1)
if (fileName) {
fileName = fileName.substring(0, fileName.lastIndexOf('.'))
if (fileName != musicInfo.name) {
if (fileName.includes('-')) {
const [name, singer] = fileName.split('-').map(val => val.trim())
result = await getOtherSource({
...musicInfo,
name,
singer,
}, true)
if (result.length) try { return await handler(result) } catch {}
result = await getOtherSource({
...musicInfo,
name: singer,
singer: name,
}, true)
} else {
result = await getOtherSource({
...musicInfo,
name: fileName,
singer: '',
}, true)
}
if (result.length) try { return await handler(result) } catch {}
}
}
throw new Error('source not found')
}
export const getMusicUrl = async({ musicInfo, isRefresh, onToggleSource = () => {} }: {
musicInfo: LX.Music.MusicInfoLocal
isRefresh: boolean
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
}): Promise<string> => {
if (!isRefresh) {
const path = await getLocalFilePath(musicInfo)
if (path) return encodePath(path)
}
try {
return await getOnlineOtherSourceMusicUrlByLocal(musicInfo, isRefresh).then(({ url, quality, isFromCache }) => {
if (!isFromCache) void saveMusicUrl(musicInfo, quality, url)
return url
})
} catch {}
onToggleSource()
return getOtherSourceByLocal(musicInfo, async(otherSource) => {
return getOnlineOtherSourceMusicUrl({ musicInfos: [...otherSource], onToggleSource, isRefresh }).then(({ url, quality: targetQuality, musicInfo: targetMusicInfo, isFromCache }) => {
// saveLyric(musicInfo, data.lyricInfo)
if (!isFromCache) void saveMusicUrl(targetMusicInfo, targetQuality, url)
// TODO: save url ?
return url
})
})
}
export const getPicUrl = async({ musicInfo, listId, isRefresh, onToggleSource = () => {} }: {
musicInfo: LX.Music.MusicInfoLocal
listId?: string | null
isRefresh: boolean
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
}): Promise<string> => {
if (!isRefresh) {
const pic = await window.lx.worker.main.getMusicFilePic(musicInfo.meta.filePath)
if (pic) return pic
if (musicInfo.meta.picUrl) return musicInfo.meta.picUrl
}
try {
return await getOnlineOtherSourcePicByLocal(musicInfo).then(({ url }) => {
return url
})
} catch {}
onToggleSource()
return getOtherSourceByLocal(musicInfo, async(otherSource) => {
return getOnlineOtherSourcePicUrl({ musicInfos: [...otherSource], onToggleSource, isRefresh }).then(({ url, musicInfo: targetMusicInfo, isFromCache }) => {
if (listId) {
musicInfo.meta.picUrl = url
void updateListMusics([{ id: listId, musicInfo }])
}
return url
})
})
}
export const getLyricInfo = async({ musicInfo, isRefresh, onToggleSource = () => {} }: {
musicInfo: LX.Music.MusicInfoLocal
isRefresh: boolean
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
}): Promise<LX.Player.LyricInfo> => {
if (!isRefresh) {
const [lyricInfo, fileLyricInfo] = await Promise.all([getCachedLyricInfo(musicInfo), window.lx.worker.main.getMusicFileLyric(musicInfo.meta.filePath)])
if (lyricInfo?.lyric && lyricInfo.lyric != lyricInfo.rawlrcInfo.lyric) {
// 存在已编辑歌词
return buildLyricInfo({ ...lyricInfo, rawlrcInfo: fileLyricInfo ?? lyricInfo.rawlrcInfo })
}
if (fileLyricInfo) return buildLyricInfo(fileLyricInfo)
if (lyricInfo?.lyric) return buildLyricInfo(lyricInfo)
}
try {
// eslint-disable-next-line @typescript-eslint/promise-function-async
return await getOnlineOtherSourceLyricByLocal(musicInfo, isRefresh).then(({ lyricInfo, isFromCache }) => {
if (!isFromCache) void saveLyric(musicInfo, lyricInfo)
return buildLyricInfo(lyricInfo)
})
} catch {}
onToggleSource()
return getOtherSourceByLocal(musicInfo, async(otherSource) => {
return getOnlineOtherSourceLyricInfo({ musicInfos: [...otherSource], onToggleSource, isRefresh }).then(async({ lyricInfo, musicInfo: targetMusicInfo, isFromCache }) => {
void saveLyric(musicInfo, lyricInfo)
if (isFromCache) return buildLyricInfo(lyricInfo)
void saveLyric(targetMusicInfo, lyricInfo)
return buildLyricInfo(lyricInfo)
})
})
}