From 935dff81f9855d071bd3b25944552a0165957dfe Mon Sep 17 00:00:00 2001 From: yizhi <946185759@qq.com> Date: Fri, 10 Feb 2023 13:16:59 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dlrcx=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E5=92=8C=E8=A7=A3=E6=9E=90=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/lyric/lrcx.ts | 23 +++++++++++++++++------ src/net/download.ts | 42 +++++++++++++++++++++++++++++++++++++++--- src/test/index.ts | 4 ++-- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 347493e..f98ffaf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "smart-lyric", - "version": "1.0.1", + "version": "1.0.2", "description": "", "main": "dist/index.js", "types": "typing/index.d.ts", diff --git a/src/lyric/lrcx.ts b/src/lyric/lrcx.ts index e67b4ad..1d6af53 100644 --- a/src/lyric/lrcx.ts +++ b/src/lyric/lrcx.ts @@ -2,6 +2,7 @@ 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') @@ -22,13 +23,20 @@ function cryptLRCX(buffer: Buffer) { export function decrypt(buffer: Buffer) { try { //解压 - const b64Str = zlib.inflateSync(buffer).toString() - //取得内容 - const content = Buffer.from(b64Str, 'base64') - //解密 - cryptLRCX(content) + 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') + } //完成 - return iconv.decode(content, 'gb18030') } catch (err) { return null } @@ -54,6 +62,9 @@ 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: [] } diff --git a/src/net/download.ts b/src/net/download.ts index 91e1fa2..5e2e157 100644 --- a/src/net/download.ts +++ b/src/net/download.ts @@ -149,8 +149,18 @@ export async function downloadKugouLyric(option: IKugouLyricDownloadOption) { /** 酷我音乐歌词下载选项 */ interface IKuwoLyricDownloadOption { - /** 歌词KEY */ - key: string + /** + * 歌曲ID + * + * 可以是数字组成的ID,也可以是`MUSIC_\d+` + */ + musicID: string | number + /** + * 是否加载lrcx歌词, 默认`true` + * + * 如果没有lrcx歌词,返回的将是lrc歌词,可以通过判断歌词中是否有`[kuwo:\d+]`来检测是不是lrcx歌词 + */ + lrcx?: boolean } /** @@ -158,8 +168,34 @@ interface IKuwoLyricDownloadOption { * @param option 下载选项 */ export async function downloadKuwoLyric(option: IKuwoLyricDownloadOption) { + + const KUWO_KEY = Buffer.from('yeelion') + //加密歌词参数 + const buildParams = (id: string | number, lrcx: boolean) => { + const rid = (typeof id == 'number' || /^\d+$/.test(id)) ? `MUSIC_${id}` : id + let params = `user=313928,MUSIC_9.1.1.8_W6,kwmusic_web_6 (1).exe,KwMusic&requester=localhost&req=1&rid=${rid}` + if (lrcx) params += '&lrcx=1&olrc=1' + const pBuffer = Buffer.from(params) + const output = new Uint16Array(pBuffer.byteLength) + for (let i = 0; i < pBuffer.byteLength; ++i) { + output[i] = KUWO_KEY[i % KUWO_KEY.length] ^ pBuffer[i] + } + return Buffer.from(output).toString('base64') + } + + //测试解码 + // const test = (buf: Buffer) => { + // const src = Uint16Array.from(buf) + // const out = Buffer.alloc(src.length) + // for (let i = 0; i < src.length; ++i) { + // out[i] = KUWO_KEY[i % KUWO_KEY.length] ^ src[i] + // } + // console.log(out + '') + // } + // test(Buffer.from(option.key, 'base64')) + //请求歌词 - let buffer = await request({ url: `http://newlyric.kuwo.cn/newlyric.lrc?${option.key}`, method: 'get' }) + let buffer = await request({ url: `http://newlyric.kuwo.cn/newlyric.lrc?${buildParams(option.musicID, option.lrcx ?? true)}`, method: 'get' }) //读取基本信息(其实没有用),并得到歌词内容 const baseInfo: any = {} diff --git a/src/test/index.ts b/src/test/index.ts index cd3dd11..d3689be 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -13,7 +13,6 @@ async function test() { // } console.log('==============================测试qrc==========================================') - await utils.downloadQQMusicLyric({ songID: 102878776 }).then(data => { const lyric = qrc.parse(data!) console.log(lyric) @@ -29,7 +28,8 @@ async function test() { console.log('==============================测试lrcx==========================================') await utils.downloadKuwoLyric({ - key: 'DBYAHlRcX0pcV1RFIjsqLCYzUEFfV1RLVDY4WFUOEgEcHAcaOhIJCzBYWU1URUcKFhxJLhskGh0QBkMeDB4bHBYRCRtSAhYGBAABAB0NQxcJGFJfWUMWAwcIABgIAFG9ra+40Z/dhKG8zKG1qE8OHA0MFhhU2qW5k9uRTx0HHVgoOTomLSZTUl9dX1tJU0MAGwwWRFRDAwUdDURU', + musicID: 'MUSIC_67340506', + lrcx: true, }).then(txt => { const lyric = lrcx.parse(txt!) console.log(lyric)