新增自动换源下载功能

This commit is contained in:
lyswhut
2021-04-22 16:01:47 +08:00
parent cd1a55652f
commit 3efd6867d8
10 changed files with 284 additions and 121 deletions
+113 -14
View File
@@ -3,7 +3,15 @@ import fs from 'fs'
import path from 'path'
import music from '../../utils/music'
import { getMusicType } from '../../utils/music/utils'
import { setMeta, saveLrc, getLyric, setLyric, getMusicUrl, setMusicUrl } from '../../utils'
import {
setMeta,
saveLrc,
getLyric as getLyricFromStorage,
setLyric,
getMusicUrl as getMusicUrlFormStorage,
setMusicUrl,
assertApiSupport,
} from '../../utils'
// state
const state = {
@@ -147,8 +155,33 @@ const pauseTasks = async(store, list, runs = []) => {
await pauseTasks(store, list, runs)
}
const getUrl = async(downloadInfo, isRefresh) => {
const cachedUrl = await getMusicUrl(downloadInfo.musicInfo, downloadInfo.type)
const handleGetMusicUrl = function(musicInfo, type, retryedSource = [], originMusic) {
// console.log(musicInfo.source)
if (!originMusic) originMusic = musicInfo
let reqPromise
try {
reqPromise = music[musicInfo.source].getMusicUrl(musicInfo, type).promise
} catch (err) {
reqPromise = Promise.reject(err)
}
return reqPromise.catch(err => {
if (!retryedSource.includes(musicInfo.source) || !assertApiSupport(musicInfo.source)) retryedSource.push(musicInfo.source)
return this.dispatch('list/getOtherSource', originMusic).then(otherSource => {
console.log('find otherSource', otherSource)
if (otherSource.length) {
for (const item of otherSource) {
if (retryedSource.includes(item.source)) continue
console.log('try toggle to: ', item.source, item.name, item.singer, item.interval)
return handleGetMusicUrl.call(this, item, type, retryedSource, originMusic)
}
}
return Promise.reject(err)
})
})
}
const getMusicUrl = async function(downloadInfo, isUseOtherSource, isRefresh) {
const cachedUrl = await getMusicUrlFormStorage(downloadInfo.musicInfo, downloadInfo.type)
if (!downloadInfo.musicInfo._types[downloadInfo.type]) {
// 兼容旧版酷我源搜索列表过滤128k音质的bug
if (!(downloadInfo.musicInfo.source == 'kw' && downloadInfo.type == '128k')) throw new Error('该歌曲没有可下载的音频')
@@ -157,11 +190,62 @@ const getUrl = async(downloadInfo, isRefresh) => {
}
return cachedUrl && !isRefresh
? cachedUrl
: music[downloadInfo.musicInfo.source].getMusicUrl(downloadInfo.musicInfo, downloadInfo.type).promise.then(({ url }) => {
: (
isUseOtherSource
? handleGetMusicUrl.call(this, downloadInfo.musicInfo, downloadInfo.type)
: music[downloadInfo.musicInfo.source].getMusicUrl(downloadInfo.musicInfo, downloadInfo.type).promise
).then(({ url }) => {
setMusicUrl(downloadInfo.musicInfo, downloadInfo.type, url)
return url
})
}
const getPic = function(musicInfo, retryedSource = [], originMusic) {
// console.log(musicInfo.source)
if (!originMusic) originMusic = musicInfo
let reqPromise
try {
reqPromise = music[musicInfo.source].getPic(musicInfo).promise
} catch (err) {
reqPromise = Promise.reject(err)
}
return reqPromise.catch(err => {
if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source)
return this.dispatch('list/getOtherSource', originMusic).then(otherSource => {
console.log('find otherSource', otherSource)
if (otherSource.length) {
for (const item of otherSource) {
if (retryedSource.includes(item.source)) continue
console.log('try toggle to: ', item.source, item.name, item.singer, item.interval)
return getPic.call(this, item, retryedSource, originMusic)
}
}
return Promise.reject(err)
})
})
}
const getLyric = function(musicInfo, retryedSource = [], originMusic) {
if (!originMusic) originMusic = musicInfo
let reqPromise
try {
reqPromise = music[musicInfo.source].getLyric(musicInfo).promise
} catch (err) {
reqPromise = Promise.reject(err)
}
return reqPromise.catch(err => {
if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source)
return this.dispatch('list/getOtherSource', originMusic).then(otherSource => {
console.log('find otherSource', otherSource)
if (otherSource.length) {
for (const item of otherSource) {
if (retryedSource.includes(item.source)) continue
console.log('try toggle to: ', item.source, item.name, item.singer, item.interval)
return getLyric.call(this, item, retryedSource, originMusic)
}
}
return Promise.reject(err)
})
})
}
// 修复 1.1.x版本 酷狗源歌词格式
const fixKgLyric = lrc => /\[00:\d\d:\d\d.\d+\]/.test(lrc) ? lrc.replace(/(?:\[00:(\d\d:\d\d.\d+\]))/gm, '[$1') : lrc
@@ -172,22 +256,30 @@ const fixKgLyric = lrc => /\[00:\d\d:\d\d.\d+\]/.test(lrc) ? lrc.replace(/(?:\[0
* @param {*} filePath
* @param {*} isEmbedPic // 是否嵌入图片
*/
const saveMeta = (downloadInfo, filePath, isEmbedPic, isEmbedLyric) => {
const saveMeta = function(downloadInfo, filePath, isUseOtherSource, isEmbedPic, isEmbedLyric) {
if (downloadInfo.type === 'ape') return
const tasks = [
isEmbedPic
? downloadInfo.musicInfo.img
? Promise.resolve(downloadInfo.musicInfo.img)
: music[downloadInfo.musicInfo.source].getPic(downloadInfo.musicInfo).promise.catch(err => {
: (
isUseOtherSource
? getPic.call(this, downloadInfo.musicInfo)
: music[downloadInfo.musicInfo.source].getPic(downloadInfo.musicInfo).promise
).catch(err => {
console.log(err)
return null
})
: Promise.resolve(),
isEmbedLyric
? getLyric(downloadInfo.musicInfo).then(lrcInfo => {
? getLyricFromStorage(downloadInfo.musicInfo).then(lrcInfo => {
return lrcInfo.lyric
? Promise.resolve({ lyric: lrcInfo.lyric, tlyric: lrcInfo.tlyric || '' })
: music[downloadInfo.musicInfo.source].getLyric(downloadInfo.musicInfo).promise.then(({ lyric, tlyric, lxlyric }) => {
: (
isUseOtherSource
? getLyric.call(this, downloadInfo.musicInfo)
: music[downloadInfo.musicInfo.source].getLyric(downloadInfo.musicInfo).promise
).then(({ lyric, tlyric, lxlyric }) => {
setLyric(downloadInfo.musicInfo, { lyric, tlyric, lxlyric })
return { lyric, tlyric, lxlyric }
}).catch(err => {
@@ -231,9 +323,9 @@ const downloadLyric = (downloadInfo, filePath) => {
})
}
const refreshUrl = function(commit, downloadInfo) {
const refreshUrl = function(commit, downloadInfo, isUseOtherSource) {
commit('setStatusText', { downloadInfo, text: '链接失效,正在刷新链接' })
getUrl(downloadInfo, true).then(url => {
getMusicUrl.call(this, downloadInfo, isUseOtherSource, true).then(url => {
commit('updateUrl', { downloadInfo, url })
commit('setStatusText', { downloadInfo, text: '链接刷新成功' })
const dl = dls[downloadInfo.key]
@@ -341,7 +433,7 @@ const actions = {
commit('onCompleted', downloadInfo)
dispatch('startTask')
saveMeta(downloadInfo, downloadInfo.filePath, rootState.setting.download.isEmbedPic, rootState.setting.download.isEmbedLyric)
saveMeta.call(_this, downloadInfo, downloadInfo.filePath, rootState.setting.download.isUseOtherSource, rootState.setting.download.isEmbedPic, rootState.setting.download.isEmbedLyric)
if (rootState.setting.download.isDownloadLrc) downloadLyric(downloadInfo, downloadInfo.filePath)
console.log('on complate')
},
@@ -358,7 +450,8 @@ const actions = {
return
}
if (err.code == 'ENOTFOUND') {
refreshUrl.call(_this, commit, downloadInfo)
commit('onError', { downloadInfo, errorMsg: '链接失效' })
refreshUrl.call(_this, commit, downloadInfo, rootState.setting.download.isUseOtherSource)
} else {
console.log('Download failed, Attempting Retry')
dls[downloadInfo.key].start()
@@ -375,7 +468,13 @@ const actions = {
case 401:
case 403:
case 410:
refreshUrl.call(_this, commit, downloadInfo)
commit('onError', { downloadInfo, errorMsg: '链接失效' })
refreshUrl.call(_this, commit, downloadInfo, rootState.setting.download.isUseOtherSource)
break
default:
dls[downloadInfo.key].start()
commit('setStatusText', { downloadInfo, text: '正在重试' })
break
}
},
onStart() {
@@ -394,7 +493,7 @@ const actions = {
commit('setStatusText', { downloadInfo, text: '获取URL中...' })
let p = options.url
? Promise.resolve()
: getUrl(downloadInfo).then(url => {
: getMusicUrl.call(this, downloadInfo, rootState.setting.download.isUseOtherSource).then(url => {
commit('updateUrl', { downloadInfo, url })
if (!url) return Promise.reject(new Error('获取URL失败'))
options.url = url
+6 -6
View File
@@ -68,16 +68,16 @@ const filterList = async({ playedList, listInfo, savePath, commit }) => {
const getPic = function(musicInfo, retryedSource = [], originMusic) {
// console.log(musicInfo.source)
if (!originMusic) originMusic = musicInfo
let reqPromise
try {
reqPromise = music[musicInfo.source].getPic(musicInfo).promise
} catch (err) {
reqPromise = Promise.reject(err)
}
return reqPromise.promise.catch(err => {
return reqPromise.catch(err => {
if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source)
return this.dispatch('list/getOtherSource', musicInfo).then(otherSource => {
if (!originMusic) originMusic = musicInfo
return this.dispatch('list/getOtherSource', originMusic).then(otherSource => {
console.log('find otherSource', otherSource)
if (otherSource.length) {
for (const item of otherSource) {
@@ -91,16 +91,16 @@ const getPic = function(musicInfo, retryedSource = [], originMusic) {
})
}
const getLyric = function(musicInfo, retryedSource = [], originMusic) {
if (!originMusic) originMusic = musicInfo
let reqPromise
try {
reqPromise = music[musicInfo.source].getLyric(musicInfo).promise
} catch (err) {
reqPromise = Promise.reject(err)
}
return reqPromise.promise.catch(err => {
return reqPromise.catch(err => {
if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source)
return this.dispatch('list/getOtherSource', musicInfo).then(otherSource => {
if (!originMusic) originMusic = musicInfo
return this.dispatch('list/getOtherSource', originMusic).then(otherSource => {
console.log('find otherSource', otherSource)
if (otherSource.length) {
for (const item of otherSource) {