增加歌词分类

This commit is contained in:
2023-02-10 15:49:33 +08:00
parent 20ea76cb1a
commit e899fd6563
9 changed files with 82 additions and 61 deletions

View File

@ -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':

View File

@ -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':

View File

@ -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: [] }

View File

@ -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,
}
}

View File

@ -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))
}
})
}