增加歌词分类
This commit is contained in:
@ -56,6 +56,9 @@ export function request<T = any>(option: IRequestOption) {
|
||||
case 'deflate':
|
||||
data = zlib.inflateSync(data)
|
||||
break
|
||||
case 'br':
|
||||
data = zlib.brotliDecompressSync(data)
|
||||
break
|
||||
}
|
||||
switch (option.type) {
|
||||
case 'text':
|
||||
|
@ -17,7 +17,7 @@ function toInt(v: string | number) {
|
||||
* @param line 歌词行
|
||||
*/
|
||||
export function parseLyricTag(lyric: ILyric, line: string) {
|
||||
const match = line.match(/^\[([a-zA-Z][a-zA-Z0-9_]*):(.*)\]$/)
|
||||
const match = line.match(/^\[([a-zA-Z#][a-zA-Z0-9_]*):(.*)\]$/)
|
||||
if (!match) return false
|
||||
switch (match[1]) {
|
||||
case 'ti':
|
||||
|
@ -2,7 +2,6 @@ import zlib from 'zlib'
|
||||
import iconv from 'iconv-lite'
|
||||
import { IKaraokeWord, ILyric, ILyricLine, LyricType } from './declare'
|
||||
import { genLyricTag, parseLyricTag } from './common'
|
||||
import { parse as parseLrc } from './lrc'
|
||||
|
||||
|
||||
const KUWO_LYRIC_KEY = Buffer.from('yeelion')
|
||||
@ -23,19 +22,13 @@ function cryptLRCX(buffer: Buffer) {
|
||||
export function decrypt(buffer: Buffer) {
|
||||
try {
|
||||
//解压
|
||||
const b64Buffer = zlib.inflateSync(buffer)
|
||||
const b64Str = b64Buffer.toString()
|
||||
//不需要解码
|
||||
if (/\s*\[[a-z0-9A-z]+:/.test(b64Str)) return iconv.decode(b64Buffer, 'gb18030')
|
||||
//进行解码
|
||||
else {
|
||||
//取得内容
|
||||
const content = Buffer.from(b64Str, 'base64')
|
||||
//解密
|
||||
cryptLRCX(content)
|
||||
//return
|
||||
return iconv.decode(content, 'gb18030')
|
||||
}
|
||||
const b64Str = zlib.inflateSync(buffer).toString()
|
||||
//取得内容
|
||||
const content = Buffer.from(b64Str, 'base64')
|
||||
//解密
|
||||
cryptLRCX(content)
|
||||
//return
|
||||
return iconv.decode(content, 'gb18030')
|
||||
//完成
|
||||
} catch (err) {
|
||||
return null
|
||||
@ -62,9 +55,6 @@ export function encrypt(content: string | Buffer) {
|
||||
* @param lrcxText LRCX歌词文本内容
|
||||
*/
|
||||
export function parse(lrcxText: string) {
|
||||
//如果不是lrcx则按照lrc解析
|
||||
if (!/^\[kuwo:\d+\]$/im.test(lrcxText)) return parseLrc(lrcxText)
|
||||
|
||||
//结果
|
||||
const result: ILyric = { type: LyricType.KARA, content: [] }
|
||||
|
||||
|
@ -1,9 +1,17 @@
|
||||
import crypto from 'crypto'
|
||||
import iconv from 'iconv-lite'
|
||||
import zlib from 'zlib'
|
||||
import * as qrcUtil from '../lyric/qrc'
|
||||
import * as krcUtil from '../lyric/krc'
|
||||
import * as lrcxUtil from '../lyric/lrcx'
|
||||
import { request } from '../lib/request'
|
||||
|
||||
interface IDownloadResult {
|
||||
/** 卡拉OK歌词 */
|
||||
karaok: string | null
|
||||
/** 常规歌词 */
|
||||
regular: string | null
|
||||
}
|
||||
|
||||
/** QQ音乐歌词下载选项 */
|
||||
interface IQQMusicLyricDownloadOption {
|
||||
@ -15,13 +23,15 @@ interface IQQMusicLyricDownloadOption {
|
||||
songName?: string
|
||||
/** 指定歌手名称 */
|
||||
singerName?: string | string[]
|
||||
/** 是否下载QRC歌词,默认`true` */
|
||||
qrc?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* 从QQ音乐API下载歌词
|
||||
* @param option 下载选项
|
||||
*/
|
||||
export async function downloadQQMusicLyric(option: IQQMusicLyricDownloadOption) {
|
||||
export async function downloadQQMusicLyric(option: IQQMusicLyricDownloadOption): Promise<IDownloadResult> {
|
||||
//创建一个参数
|
||||
const createParam = (paranName: string, value: string | undefined | string[]) => {
|
||||
if (value && typeof value === 'string') return { [paranName]: Buffer.from(value).toString('base64') }
|
||||
@ -53,8 +63,7 @@ export async function downloadQQMusicLyric(option: IQQMusicLyricDownloadOption)
|
||||
// "cv": 1906,
|
||||
// "interval": 304,
|
||||
// "lrc_t": 0,
|
||||
qrc: 1,
|
||||
// "qrc": (option.qrc ?? true) ? 1 : 0,
|
||||
qrc: (option.qrc ?? true) ? 1 : 0,
|
||||
// "qrc_t": 0,
|
||||
// "roma": option.roma ? 1 : 0,
|
||||
// "roma_t": 0,
|
||||
@ -80,8 +89,11 @@ export async function downloadQQMusicLyric(option: IQQMusicLyricDownloadOption)
|
||||
else return Buffer.from(str, 'base64').toString()
|
||||
}
|
||||
|
||||
if (lyricInfo?.qrc) return parseLyric(lyricInfo.lyric, 'hex')
|
||||
return null
|
||||
if (lyricInfo.lyric) {
|
||||
if (lyricInfo?.qrc) return { karaok: parseLyric(lyricInfo.lyric, 'hex'), regular: null }
|
||||
else return { karaok: null, regular: Buffer.from(lyricInfo.lyric, 'base64').toString() }
|
||||
}
|
||||
return { karaok: null, regular: null }
|
||||
|
||||
// let result: IQQMusicDownloadResult | null = null
|
||||
// //内容为qrc
|
||||
@ -123,7 +135,7 @@ interface IKugouLyricDownloadOption {
|
||||
* @param option 下载选项
|
||||
* @returns krc歌词文本内容
|
||||
*/
|
||||
export async function downloadKugouLyric(option: IKugouLyricDownloadOption) {
|
||||
export async function downloadKugouLyric(option: IKugouLyricDownloadOption): Promise<IDownloadResult> {
|
||||
//请求数据
|
||||
const resp = await request<any>({
|
||||
url: `http://lyrics.kugou.com/download?ver=1&client=pc&id=${option.id}&accesskey=${option.accesskey}&fmt=${option.fmt ?? 'krc'}&charset=utf8`,
|
||||
@ -131,9 +143,11 @@ export async function downloadKugouLyric(option: IKugouLyricDownloadOption) {
|
||||
type: 'json',
|
||||
})
|
||||
|
||||
if (resp.status !== 200 || !resp.content) return null
|
||||
|
||||
return krcUtil.decrypt(Buffer.from(resp.content, 'base64'))
|
||||
if (resp.status === 200 && resp.content) {
|
||||
if (resp.fmt === 'krc') return { karaok: krcUtil.decrypt(Buffer.from(resp.content, 'base64')), regular: null }
|
||||
else if (resp.fmt === 'lrc') return { karaok: null, regular: Buffer.from(resp.content, 'base64').toString() }
|
||||
}
|
||||
return { karaok: null, regular: null }
|
||||
}
|
||||
|
||||
/** 酷我音乐歌词下载选项 */
|
||||
@ -156,7 +170,7 @@ interface IKuwoLyricDownloadOption {
|
||||
* 下载酷我音乐歌词
|
||||
* @param option 下载选项
|
||||
*/
|
||||
export async function downloadKuwoLyric(option: IKuwoLyricDownloadOption) {
|
||||
export async function downloadKuwoLyric(option: IKuwoLyricDownloadOption): Promise<IDownloadResult> {
|
||||
|
||||
const KUWO_KEY = Buffer.from('yeelion')
|
||||
//加密歌词参数
|
||||
@ -224,8 +238,11 @@ export async function downloadKuwoLyric(option: IKuwoLyricDownloadOption) {
|
||||
}
|
||||
}
|
||||
|
||||
//解码歌词
|
||||
return lrcxUtil.decrypt(buffer)
|
||||
if (buffer.byteLength && baseInfo.lrc_length) {
|
||||
if (baseInfo.lrcx) return { karaok: lrcxUtil.decrypt(buffer), regular: null }
|
||||
else return { karaok: null, regular: iconv.decode(zlib.inflateSync(buffer), 'gb18030') }
|
||||
}
|
||||
return { karaok: null, regular: null }
|
||||
}
|
||||
|
||||
|
||||
@ -241,7 +258,7 @@ interface IDownloadNeteasyLyric {
|
||||
* 下载网易云音乐歌词
|
||||
* @param option 下载选项
|
||||
*/
|
||||
export async function downloadNeteasyLyric(option: IDownloadNeteasyLyric) {
|
||||
export async function downloadNeteasyLyric(option: IDownloadNeteasyLyric): Promise<IDownloadResult> {
|
||||
|
||||
const encryptData = (paramData: any) => {
|
||||
const text = JSON.stringify(paramData);
|
||||
@ -270,15 +287,13 @@ export async function downloadNeteasyLyric(option: IDownloadNeteasyLyric) {
|
||||
}),
|
||||
headers: {
|
||||
'Accept': '*/*',
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
// 'Origin': 'orpheus://orpheus',
|
||||
// 'Cookie': 'os=pc; deviceId=9E6E85D4C25B23CD18B4781301BF5AA8C83A260E525400485AC4; osver=Microsoft-Windows-10-Professional-build-22000-64bit; appver=2.10.6.200601; NMTID=00OxyKBYOYjYuWko0YsqwDxN_KA3-kAAAGGFcYW_g; channel=netease; WEVNSM=1.0.0; mode=Standard%20PC%20(Q35%20%2B%20ICH9%2C%202009); __csrf=98ba68b228a2c0065e9820245d7c3605; MUSIC_A=e177342ffaa63031618420730fe7c83bd0d668d4476a15687eb986f8c79eeb1c062890f94ac493a999e7ad1570fb37952038bc2b7b0dc759fd95a411e59159fe033fad747150c42ddd2c085dbd859f914156aea54e160355b25a13460616b0f319145b139d7e79695bdffc390ee188a1f246a3151047f27c4212382188fe1965; ntes_kaola_ad=1; WNMCID=qbecdc.1675402548248.01.0',
|
||||
// 'MConfig-Info': '{"IuRPVVmc3WWul9fT":{"version":288768,"appver":"2.10.6.200601"}}',
|
||||
// 'MG-Product-Name': 'music',
|
||||
// 'Nm-GCore-Status': 1,
|
||||
'Accept-Encoding': 'gzip, deflate,br',
|
||||
},
|
||||
type: 'json',
|
||||
})
|
||||
|
||||
return (res.yrc.lyric as string | null) || null
|
||||
return {
|
||||
karaok: ((res?.klyric?.lyric ?? '') + (res?.yrc?.lyric ?? '')) || null,
|
||||
regular: ((res?.klyric?.lyric ?? '') + (res?.lrc?.lyric ?? '')) || null,
|
||||
}
|
||||
}
|
||||
|
@ -13,34 +13,39 @@ async function test() {
|
||||
// }
|
||||
|
||||
console.log('==============================测试qrc==========================================')
|
||||
await utils.downloadQQMusicLyric({ songID: 102878776 }).then(data => {
|
||||
const lyric = qrc.parse(data!)
|
||||
console.log(lyric)
|
||||
console.log(qrc.stringify(lyric))
|
||||
await utils.downloadQQMusicLyric({ songID: 102878776, qrc: true }).then(res => {
|
||||
if (res.karaok) {
|
||||
const lyric = qrc.parse(res.karaok)
|
||||
console.log(lyric)
|
||||
console.log(qrc.stringify(lyric))
|
||||
}
|
||||
})
|
||||
|
||||
console.log('==============================测试krc==========================================')
|
||||
await utils.downloadKugouLyric({ id: 10515303, accesskey: '3A20F6A1933DE370EBA0187297F5477D' }).then(data => {
|
||||
const lyric = krc.parse(data!)
|
||||
console.log(lyric)
|
||||
console.log(lrcx.stringify(lyric))
|
||||
await utils.downloadKugouLyric({ id: 10515303, accesskey: '3A20F6A1933DE370EBA0187297F5477D', fmt: 'lrc' }).then(res => {
|
||||
if (res.karaok) {
|
||||
const lyric = krc.parse(res.karaok)
|
||||
console.log(lyric)
|
||||
console.log(lrcx.stringify(lyric))
|
||||
}
|
||||
})
|
||||
|
||||
console.log('==============================测试lrcx==========================================')
|
||||
await utils.downloadKuwoLyric({
|
||||
musicID: 'MUSIC_67340506',
|
||||
lrcx: true,
|
||||
}).then(txt => {
|
||||
const lyric = lrcx.parse(txt!)
|
||||
console.log(lyric)
|
||||
console.log(lrcx.stringify(lyric))
|
||||
await utils.downloadKuwoLyric({ musicID: 'MUSIC_67340506', lrcx: true }).then(res => {
|
||||
if (res.karaok) {
|
||||
const lyric = lrcx.parse(res.karaok)
|
||||
console.log(lyric)
|
||||
console.log(lrcx.stringify(lyric))
|
||||
}
|
||||
})
|
||||
|
||||
console.log('==============================测试nrc==========================================')
|
||||
await utils.downloadNeteasyLyric({ musicID: '210049' }).then(data => {
|
||||
const lyric = nrc.parse(data!)
|
||||
console.log(lyric)
|
||||
console.log(nrc.stringify(lyric))
|
||||
await utils.downloadNeteasyLyric({ musicID: '210049' }).then(res => {
|
||||
if (res.karaok) {
|
||||
const lyric = nrc.parse(res.karaok)
|
||||
console.log(lyric)
|
||||
console.log(nrc.stringify(lyric))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user