新增酷狗歌词翻译

pull/389/head
lyswhut 2020-09-05 03:50:30 +08:00
parent f3c2d7e43a
commit 4be5bcc979
3 changed files with 120 additions and 6 deletions

View File

@ -2,6 +2,7 @@
- 在歌单详情界面新增播放当前歌单按钮、收藏歌单按钮,注:播放歌单不会将歌曲添加到试听列表
- 新增`不允许将歌词窗口拖出主屏幕之外`的设置项,默认开启,在连接多个屏幕时想要拖动到其他屏幕时可关闭此设置
- 新增大部分平台的歌词翻译,感谢 @InoriHimea 提供的[krc解码算法](https://github.com/lyswhut/lx-music-desktop/issues/296#issuecomment-683285784)
- 新增`显示歌词翻译`设置,默认开启,仅支持某些平台,注:无论该设置是否开启,嵌入或下载歌词时都不会带上翻译
- 新增`显示切换动画`设置,默认开启,关闭时将基本禁用软件内的所有切换动画

View File

@ -1,4 +1,41 @@
import { httpFetch } from '../../request'
import { decodeLyric } from './util'
const parseLyric = str => {
str = str.replace(/(?:<\d+,\d+,\d+>|\r)/g, '')
let trans = str.match(/\[language:([\w=\\/+]+)\]/)
let tlyric
if (trans) {
str = str.replace(/\[language:[\w=\\/+]+\]\n/, '')
let json = JSON.parse(Buffer.from(trans[1], 'base64').toString())
for (const item of json.content) {
if (item.type == 1) {
tlyric = item.lyricContent
break
}
}
}
let i = 0
let lyric = str.replace(/\[((\d+),\d+)\].*/g, str => {
let result = str.match(/\[((\d+),\d+)\].*/)
let time = parseInt(result[2])
let ms = time % 1000
time /= 1000
let h = parseInt(time / 3600).toString().padStart(2, '0')
time %= 3600
let m = parseInt(time / 60).toString().padStart(2, '0')
time %= 60
let s = parseInt(time).toString().padStart(2, '0')
time = `${h}:${m}:${s}.${ms}`
if (tlyric) tlyric[i] = `[${time}]${tlyric[i++][0]}`
return str.replace(result[1], time)
})
tlyric = tlyric ? tlyric.join('\n') : ''
return {
lyric,
tlyric,
}
}
export default {
getIntv(interval) {
@ -11,8 +48,30 @@ export default {
}
return parseInt(intv)
},
getLyric(songInfo, tryNum = 0) {
let requestObj = httpFetch(`http://m.kugou.com/app/i/krc.php?cmd=100&keyword=${encodeURIComponent(songInfo.name)}&hash=${songInfo.hash}&timelength=${songInfo._interval || this.getIntv(songInfo.interval)}&d=0.38664927426725626`, {
// getLyric(songInfo, tryNum = 0) {
// let requestObj = httpFetch(`http://m.kugou.com/app/i/krc.php?cmd=100&keyword=${encodeURIComponent(songInfo.name)}&hash=${songInfo.hash}&timelength=${songInfo._interval || this.getIntv(songInfo.interval)}&d=0.38664927426725626`, {
// headers: {
// 'KG-RC': 1,
// 'KG-THash': 'expand_search_manager.cpp:852736169:451',
// 'User-Agent': 'KuGou2012-9020-ExpandSearchManager',
// },
// })
// requestObj.promise = requestObj.promise.then(({ body, statusCode }) => {
// if (statusCode !== 200) {
// if (tryNum > 5) return Promise.reject('歌词获取失败')
// let tryRequestObj = this.getLyric(songInfo, ++tryNum)
// requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
// return tryRequestObj.promise
// }
// return {
// lyric: body,
// tlyric: '',
// }
// })
// return requestObj
// },
searchLyric(name, hash, time, tryNum = 0) {
let requestObj = httpFetch(`http://lyrics.kugou.com/search?ver=1&man=yes&client=pc&keyword=${encodeURIComponent(name)}&hash=${hash}&timelength=${time}`, {
headers: {
'KG-RC': 1,
'KG-THash': 'expand_search_manager.cpp:852736169:451',
@ -22,14 +81,49 @@ export default {
requestObj.promise = requestObj.promise.then(({ body, statusCode }) => {
if (statusCode !== 200) {
if (tryNum > 5) return Promise.reject('歌词获取失败')
let tryRequestObj = this.getLyric(songInfo, ++tryNum)
let tryRequestObj = this.searchLyric(name, hash, time, ++tryNum)
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
return tryRequestObj.promise
}
return {
lyric: body,
tlyric: '',
if (body.candidates.length) {
let info = body.candidates[0]
return { id: info.id, accessKey: info.accesskey }
}
return null
})
return requestObj
},
getLyricDownload(id, accessKey, tryNum = 0) {
let requestObj = httpFetch(`http://lyrics.kugou.com/download?ver=1&client=pc&id=${id}&accesskey=${accessKey}&fmt=krc&charset=utf8`, {
headers: {
'KG-RC': 1,
'KG-THash': 'expand_search_manager.cpp:852736169:451',
'User-Agent': 'KuGou2012-9020-ExpandSearchManager',
},
})
requestObj.promise = requestObj.promise.then(({ body, statusCode }) => {
if (statusCode !== 200) {
if (tryNum > 5) return Promise.reject('歌词获取失败')
let tryRequestObj = this.getLyric(id, accessKey, ++tryNum)
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
return tryRequestObj.promise
}
return decodeLyric(body.content).then(result => parseLyric(result))
})
return requestObj
},
getLyric(songInfo, tryNum = 0) {
let requestObj = this.searchLyric(songInfo.name, songInfo.hash, songInfo._interval || this.getIntv(songInfo.interval))
requestObj.promise = requestObj.promise.then(result => {
if (!result) return { lyric: '', tlyric: '' }
let requestObj2 = this.getLyricDownload(result.id, result.accessKey)
requestObj.cancelHttp = requestObj2.cancelHttp.bind(requestObj2)
return requestObj2.promise
})
return requestObj
},

View File

@ -0,0 +1,19 @@
import { inflate } from 'zlib'
// https://github.com/lyswhut/lx-music-desktop/issues/296#issuecomment-683285784
const enc_key = Buffer.from([0x40, 0x47, 0x61, 0x77, 0x5e, 0x32, 0x74, 0x47, 0x51, 0x36, 0x31, 0x2d, 0xce, 0xd2, 0x6e, 0x69], 'binary')
export const decodeLyric = str => new Promise((resolve, reject) => {
if (!str.length) return
const buf_str = Buffer.from(str, 'base64').slice(4)
for (let i = 0, len = buf_str.length; i < len; i++) {
buf_str[i] = buf_str[i] ^ enc_key[i % 16]
}
inflate(buf_str, (err, result) => {
if (err) return reject(err)
resolve(result.toString())
})
})
// s.content[0].lyricContent.forEach(([str]) => {
// console.log(str)
// })