refactor(sdk): musicSdk 全量迁移至 TypeScript
This commit is contained in:
1 parent
f289df4cd7
commit
1dfb7a59ca
83 files changed
+924
-732
No files matched your search
@@ -0,0 +1,296 @@
|
||||
import type { HttpRequestObject } from '../types.ts'
|
||||
import { httpFetch } from '../request.ts'
|
||||
import getMusicInfo from './musicInfo.ts'
|
||||
import { rendererInvoke } from '../../src/common/rendererIpc.ts'
|
||||
import { WIN_MAIN_RENDERER_EVENT_NAME } from '../../src/common/ipcNames.ts'
|
||||
|
||||
const songIdMap = new Map()
|
||||
const promises = new Map()
|
||||
export const decodeLyric = (lrc, tlrc, rlrc) => rendererInvoke(WIN_MAIN_RENDERER_EVENT_NAME.handle_tx_decode_lyric, { lrc, tlrc, rlrc })
|
||||
|
||||
|
||||
const parseTools = {
|
||||
rxps: {
|
||||
info: /^{"/,
|
||||
lineTime: /^\[(\d+),\d+\]/,
|
||||
lineTime2: /^\[([\d:.]+)\]/,
|
||||
wordTime: /\(\d+,\d+\)/,
|
||||
wordTimeAll: /(\(\d+,\d+\))/g,
|
||||
timeLabelFixRxp: /(?:\.0+|0+)$/,
|
||||
},
|
||||
msFormat(timeMs) {
|
||||
if (Number.isNaN(timeMs)) return ''
|
||||
let ms = timeMs % 1000
|
||||
timeMs /= 1000
|
||||
let m = Math.floor(timeMs / 60).toString().padStart(2, '0')
|
||||
timeMs %= 60
|
||||
let s = Math.floor(timeMs).toString().padStart(2, '0')
|
||||
return `[${m}:${s}.${String(ms).padStart(3, '0')}]`
|
||||
},
|
||||
parseLyric(lrc) {
|
||||
lrc = lrc.trim()
|
||||
lrc = lrc.replace(/\r/g, '')
|
||||
if (!lrc) return { lyric: '', lxlyric: '' }
|
||||
const lines = lrc.split('\n')
|
||||
|
||||
const lxlrcLines: string[] = []
|
||||
const lrcLines: string[] = []
|
||||
|
||||
for (let line of lines) {
|
||||
line = line.trim()
|
||||
let result = this.rxps.lineTime.exec(line)
|
||||
if (!result) {
|
||||
if (line.startsWith('[offset')) {
|
||||
lxlrcLines.push(line)
|
||||
lrcLines.push(line)
|
||||
}
|
||||
if (this.rxps.lineTime2.test(line)) {
|
||||
// lxlrcLines.push(line)
|
||||
lrcLines.push(line)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
const startMsTime = parseInt(result[1])
|
||||
const startTimeStr = this.msFormat(startMsTime)
|
||||
if (!startTimeStr) continue
|
||||
|
||||
let words = line.replace(this.rxps.lineTime, '')
|
||||
|
||||
lrcLines.push(`${startTimeStr}${words.replace(this.rxps.wordTimeAll, '')}`)
|
||||
|
||||
let times = words.match(this.rxps.wordTimeAll)
|
||||
if (!times) continue
|
||||
times = times.map(time => {
|
||||
const result = /\((\d+),(\d+)\)/.exec(time)!
|
||||
return `<${Math.max(parseInt(result[1]) - startMsTime, 0)},${result[2]}>`
|
||||
})
|
||||
const wordArr = words.split(this.rxps.wordTime)
|
||||
const newWords = times.map((time, index) => `${time}${wordArr[index]}`).join('')
|
||||
lxlrcLines.push(`${startTimeStr}${newWords}`)
|
||||
}
|
||||
return {
|
||||
lyric: lrcLines.join('\n'),
|
||||
lxlyric: lxlrcLines.join('\n'),
|
||||
}
|
||||
},
|
||||
parseRlyric(lrc) {
|
||||
lrc = lrc.trim()
|
||||
lrc = lrc.replace(/\r/g, '')
|
||||
if (!lrc) return { lyric: '', lxlyric: '' }
|
||||
const lines = lrc.split('\n')
|
||||
|
||||
const lrcLines: string[] = []
|
||||
|
||||
for (let line of lines) {
|
||||
line = line.trim()
|
||||
let result = this.rxps.lineTime.exec(line)
|
||||
if (!result) continue
|
||||
|
||||
const startMsTime = parseInt(result[1])
|
||||
const startTimeStr = this.msFormat(startMsTime)
|
||||
if (!startTimeStr) continue
|
||||
|
||||
let words = line.replace(this.rxps.lineTime, '')
|
||||
|
||||
lrcLines.push(`${startTimeStr}${words.replace(this.rxps.wordTimeAll, '')}`)
|
||||
}
|
||||
return lrcLines.join('\n')
|
||||
},
|
||||
removeTag(str) {
|
||||
return str.replace(/^[\S\s]*?LyricContent="/, '').replace(/"\/>[\S\s]*?$/, '')
|
||||
},
|
||||
getIntv(interval) {
|
||||
if (!interval) return 0
|
||||
if (!interval.includes('.')) interval += '.0'
|
||||
let arr = interval.split(/:|\./)
|
||||
while (arr.length < 3) arr.unshift('0')
|
||||
const [m, s, ms] = arr
|
||||
return parseInt(m) * 3600000 + parseInt(s) * 1000 + parseInt(ms)
|
||||
},
|
||||
fixRlrcTimeTag(rlrc, lrc) {
|
||||
// console.log(lrc)
|
||||
// console.log(rlrc)
|
||||
const rlrcLines = rlrc.split('\n')
|
||||
let lrcLines = lrc.split('\n')
|
||||
// let temp: string[] = []
|
||||
let newLrc: string[] = []
|
||||
rlrcLines.forEach((line) => {
|
||||
const result = this.rxps.lineTime2.exec(line)
|
||||
if (!result) return
|
||||
const words = line.replace(this.rxps.lineTime2, '')
|
||||
if (!words.trim()) return
|
||||
const t1 = this.getIntv(result[1])
|
||||
|
||||
while (lrcLines.length) {
|
||||
const lrcLine = lrcLines.shift()
|
||||
const lrcLineResult = this.rxps.lineTime2.exec(lrcLine)
|
||||
if (!lrcLineResult) continue
|
||||
const t2 = this.getIntv(lrcLineResult[1])
|
||||
if (Math.abs(t1 - t2) < 100) {
|
||||
newLrc.push(line.replace(this.rxps.lineTime2, lrcLineResult[0]))
|
||||
break
|
||||
}
|
||||
// temp.push(line)
|
||||
}
|
||||
// lrcLines = [...temp, ...lrcLines]
|
||||
// temp = []
|
||||
})
|
||||
return newLrc.join('\n')
|
||||
},
|
||||
fixTlrcTimeTag(tlrc, lrc) {
|
||||
// console.log(lrc)
|
||||
// console.log(tlrc)
|
||||
const tlrcLines = tlrc.split('\n')
|
||||
let lrcLines = lrc.split('\n')
|
||||
// let temp: string[] = []
|
||||
let newLrc: string[] = []
|
||||
tlrcLines.forEach((line) => {
|
||||
const result = this.rxps.lineTime2.exec(line)
|
||||
if (!result) return
|
||||
const words = line.replace(this.rxps.lineTime2, '')
|
||||
if (!words.trim()) return
|
||||
let time = result[1]
|
||||
if (time.includes('.')) {
|
||||
time += ''.padStart(3 - time.split('.')[1].length, '0')
|
||||
}
|
||||
const t1 = this.getIntv(time)
|
||||
|
||||
while (lrcLines.length) {
|
||||
const lrcLine = lrcLines.shift()
|
||||
const lrcLineResult = this.rxps.lineTime2.exec(lrcLine)
|
||||
if (!lrcLineResult) continue
|
||||
const t2 = this.getIntv(lrcLineResult[1])
|
||||
if (Math.abs(t1 - t2) < 100) {
|
||||
newLrc.push(line.replace(this.rxps.lineTime2, lrcLineResult[0]))
|
||||
break
|
||||
}
|
||||
// temp.push(line)
|
||||
}
|
||||
// lrcLines = [...temp, ...lrcLines]
|
||||
// temp = []
|
||||
})
|
||||
return newLrc.join('\n')
|
||||
},
|
||||
parse(lrc, tlrc, rlrc) {
|
||||
const info = {
|
||||
lyric: '',
|
||||
tlyric: '',
|
||||
rlyric: '',
|
||||
lxlyric: '',
|
||||
}
|
||||
if (lrc) {
|
||||
let { lyric, lxlyric } = this.parseLyric(this.removeTag(lrc))
|
||||
info.lyric = lyric
|
||||
info.lxlyric = lxlyric
|
||||
// console.log(lyric)
|
||||
// console.log(lxlyric)
|
||||
}
|
||||
if (rlrc) info.rlyric = this.fixRlrcTimeTag(this.parseRlyric(this.removeTag(rlrc)), info.lyric)
|
||||
if (tlrc) info.tlyric = this.fixTlrcTimeTag(tlrc, info.lyric)
|
||||
// console.log(info.lyric)
|
||||
// console.log(info.tlyric)
|
||||
// console.log(info.rlyric)
|
||||
|
||||
return info
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
successCode: 0,
|
||||
async getSongId({ songId, songmid }) {
|
||||
if (songId) return songId
|
||||
if (songIdMap.has(songmid)) return songIdMap.get(songmid)
|
||||
if (promises.has(songmid)) return (await promises.get(songmid)).songId
|
||||
const promise = getMusicInfo(songmid)
|
||||
promises.set(songmid, promise)
|
||||
const info = await promise
|
||||
if (!info) throw new Error('获取歌曲信息失败')
|
||||
songIdMap.set(songmid, info.songId)
|
||||
promises.delete(songmid)
|
||||
return info.songId
|
||||
},
|
||||
async parseLyric(lrc, tlrc, rlrc) {
|
||||
const { lyric, tlyric, rlyric } = await decodeLyric(lrc, tlrc, rlrc)
|
||||
// return {
|
||||
|
||||
// }
|
||||
// console.log(lyric)
|
||||
// console.log(tlyric)
|
||||
// console.log(rlyric)
|
||||
return parseTools.parse(lyric, tlyric, rlyric)
|
||||
},
|
||||
getLyric(mInfo, retryNum = 0) {
|
||||
if (retryNum > 3) return Promise.reject(new Error('Get lyric failed'))
|
||||
|
||||
return {
|
||||
cancelHttp() {
|
||||
|
||||
},
|
||||
promise: this.getSongId(mInfo).then(songId => {
|
||||
const requestObj = httpFetch('https://u.y.qq.com/cgi-bin/musicu.fcg', {
|
||||
method: 'post',
|
||||
headers: {
|
||||
referer: 'https://y.qq.com',
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
|
||||
},
|
||||
body: {
|
||||
comm: {
|
||||
ct: '19',
|
||||
cv: '1859',
|
||||
uin: '0',
|
||||
},
|
||||
req: {
|
||||
method: 'GetPlayLyricInfo',
|
||||
module: 'music.musichallSong.PlayLyricInfo',
|
||||
param: {
|
||||
format: 'json',
|
||||
crypt: 1,
|
||||
ct: 19,
|
||||
cv: 1873,
|
||||
interval: 0,
|
||||
lrc_t: 0,
|
||||
qrc: 1,
|
||||
qrc_t: 0,
|
||||
roma: 1,
|
||||
roma_t: 0,
|
||||
songID: songId,
|
||||
trans: 1,
|
||||
trans_t: 0,
|
||||
type: -1,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
return requestObj.promise.then(({ body }) => {
|
||||
// console.log(body)
|
||||
if (body.code != this.successCode || body.req.code != this.successCode) return this.getLyric(songId, ++retryNum)
|
||||
const data = body.req.data
|
||||
return this.parseLyric(data.lyric, data.trans, data.roma)
|
||||
})
|
||||
}),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// export default {
|
||||
// regexps: {
|
||||
// matchLrc: /.+"lyric":"([\w=+/]*)".+/,
|
||||
// },
|
||||
// getLyric(songmid) {
|
||||
// const requestObj = httpFetch(`https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?songmid=${songmid}&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&platform=yqq`, {
|
||||
// headers: {
|
||||
// Referer: 'https://y.qq.com/portal/player.html',
|
||||
// },
|
||||
// })
|
||||
// requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||
// if (body.code != 0 || !body.lyric) return Promise.reject(new Error('Get lyric failed'))
|
||||
// return {
|
||||
// lyric: decodeName(b64DecodeUnicode(body.lyric)),
|
||||
// tlyric: decodeName(b64DecodeUnicode(body.trans)),
|
||||
// }
|
||||
// })
|
||||
// return requestObj
|
||||
// },
|
||||
// }
|
||||
Reference in new issue
Block a user