refactor(sdk): tipSearch 全删、歌词解码器归位、IPC 桥移除、api-source 层拆除

- 四平台 tipSearch 全部删除(永不做搜索联想),types 同步去掉 tipSearch 字段
- 歌词解码器归位:kg/krcDecode、tx/qrcDecode、kw/lyricDecode(原 common/ 下三处)
- rendererIpc/ipcNames IPC 桥删除,SDK 纯服务端化
- supportQuality 由各平台 apis 内联导出(sdk/index 汇总),kg/kw/tx/wy 改直连 apis/*,api-source 旧层移除
This commit is contained in:
snowy-yang committed 2026-10-01 16:33:53 +08:00
1 parent 3c51e4d06a
commit 66d06ef48a
25 files changed
+42 -342

No files matched your search

-36
View File
@@ -1,36 +0,0 @@
// 接口源声明:id 与 api-source.ts 中 allApi 的 `<id>_<source>` 键对应
// Support qualitys: 128k 320k flac wav
interface ApiSourceInfo {
id: string
name: string
disabled: boolean
supportQualitys: Partial<Record<'kw' | 'kg' | 'tx' | 'wy', string[]>>
}
const sources: ApiSourceInfo[] = [
// {
// id: 'test',
// name: '测试接口',
// disabled: false,
// supportQualitys: {
// kw: ['128k'],
// kg: ['128k'],
// tx: ['128k'],
// wy: ['128k'],
// },
// },
{
id: 'source',
name: '外部聚合音源',
disabled: false,
supportQualitys: {
kw: ['128k', '320k', 'flac'],
kg: ['128k', '320k', 'flac'],
tx: ['128k', '320k', 'flac'],
wy: ['128k', '320k', 'flac'],
},
},
]
export default sources
-54
View File
@@ -1,54 +0,0 @@
// 接口选择层:按 apiSource 配置把请求路由到外部聚合音源或服务器内置直连接口
import apiSourceInfo from './api-source-info.ts'
// 接口模式开关(替代原 lx-music 渲染进程 store 的服务器端替身):
// 默认 internal 使用内置直连接口;设置 SOURCE_ENABLED(任意非 0/false 值)启用外部聚合音源
const enabled = process.env.SOURCE_ENABLED
export const apiSource = {
value: enabled && enabled !== '0' && enabled !== 'false' ? 'source' : 'internal',
}
export const userApi = {
apis: {},
}
import internalApi from './apis/index.ts'
import { createApi as createSourceApi } from './apis/source.ts'
interface SourceApi {
getMusicUrl(songInfo: any, type: string): { promise: Promise<any>; cancelHttp(): void }
[key: string]: any
}
const allApi: Record<string, SourceApi> = {
source_kw: createSourceApi('kw'),
source_kg: createSourceApi('kg'),
source_tx: createSourceApi('tx'),
source_wy: createSourceApi('wy'),
}
const apiList: Record<string, SourceApi | undefined> = {}
const supportQuality: Record<string, any> = {}
for (const api of apiSourceInfo) {
supportQuality[api.id] = api.supportQualitys
for (const source of Object.keys(api.supportQualitys)) {
apiList[`${api.id}_api_${source}`] = allApi[`${api.id}_${source}`]
}
}
const getAPI = (source: string): SourceApi | undefined => apiList[`${apiSource.value}_api_${source}`]
export const apis = (source: string): SourceApi => {
if (/^user_api/.test(apiSource.value)) return userApi.apis[source]
// 服务器内置直连接口
if (apiSource.value == 'internal') {
const api = internalApi[source]
if (api) return api
throw new Error('Api is not found')
}
const api = getAPI(source)
if (api) return api
throw new Error('Api is not found')
}
export { supportQuality }
-33
View File
@@ -1,33 +0,0 @@
// 各平台 URL 直连接口汇总
// 服务器环境固定使用内置直连接口(apiSource.value === 'internal')
// 外部聚合音源(sources/ 目录脚本)不走这里,由 sdk/api-source.ts 直接接入 source.ts
// 注意:index.js 为 tsc 就地发射产物(不入库);改逻辑只改本文件,然后 pnpm build
import kw from './kw.ts'
import kg from './kg.ts'
import tx from './tx.ts'
import wy from './wy.ts'
interface SongInfo {
songmid?: string
hash?: string
copyrightId?: string
[key: string]: any
}
interface MusicUrlResult {
type: string
url: string
}
interface ApiModule {
getMusicUrl?(songInfo: SongInfo, type: string): { promise: Promise<MusicUrlResult>; cancelHttp: () => void }
[key: string]: any
}
export default {
kw: kw as ApiModule,
kg: kg as ApiModule,
tx: tx as ApiModule,
wy: wy as ApiModule,
}
+3
View File
@@ -17,6 +17,9 @@ const CLIENTVER = 11430
const qualityMap = { '128k': '128', '320k': '320', flac: 'flac', flac24bit: 'high' } const qualityMap = { '128k': '128', '320k': '320', flac: 'flac', flac24bit: 'high' }
// 官方直连接口支持的音质(sdk/index.ts 汇总为 supportQuality)
export const supportQualitys = Object.keys(qualityMap)
export const getMusicUrl = (songInfo, type) => { export const getMusicUrl = (songInfo, type) => {
const requestObj = { cancelHttp() {}, promise: null as any } const requestObj = { cancelHttp() {}, promise: null as any }
const hash = (songInfo._types?.[type]?.hash || songInfo.hash || '').toLowerCase() const hash = (songInfo._types?.[type]?.hash || songInfo.hash || '').toLowerCase()
+3
View File
@@ -25,6 +25,9 @@ const qualityMap = {
flac24bit: { br: 'flac', format: 'flac' }, flac24bit: { br: 'flac', format: 'flac' },
} }
// 官方直连接口支持的音质(sdk/index.ts 汇总为 supportQuality)
export const supportQualitys = Object.keys(qualityMap)
let token = '' let token = ''
let tokenPromise: Promise<string> | null = null let tokenPromise: Promise<string> | null = null
+2
View File
@@ -19,6 +19,8 @@ const prefixMap = {
flac: ['F000', 'flac'], flac: ['F000', 'flac'],
flac24bit: ['F000', 'flac'], flac24bit: ['F000', 'flac'],
} }
// 官方直连接口支持的音质(sdk/index.ts 汇总为 supportQuality)
export const supportQualitys = Object.keys(prefixMap)
// 降级链:高音质无版权/VIP 受限时逐级回退 // 降级链:高音质无版权/VIP 受限时逐级回退
const chainMap = { const chainMap = {
'128k': ['128k'], '128k': ['128k'],
+3
View File
@@ -16,6 +16,9 @@ const levelMap = {
flac24bit: 'hires', flac24bit: 'hires',
} }
// 官方直连接口支持的音质(sdk/index.ts 汇总为 supportQuality)
export const supportQualitys = Object.keys(levelMap)
export const getMusicUrl = (songInfo, type) => { export const getMusicUrl = (songInfo, type) => {
const requestObj = { cancelHttp() {}, promise: null as any } const requestObj = { cancelHttp() {}, promise: null as any }
const data = { const data = {
-8
View File
@@ -1,8 +0,0 @@
// IPC 事件名
export const WIN_MAIN_RENDERER_EVENT_NAME = {
handle_kw_decode_lyric: 'handle_kw_decode_lyric',
handle_tx_decode_lyric: 'handle_tx_decode_lyric',
}
export default { WIN_MAIN_RENDERER_EVENT_NAME }
-33
View File
@@ -1,33 +0,0 @@
// 渲染器 IPC 桥(替代 Electron ipcRenderer.invoke)
// 服务器环境下 IPC 调用直接映射到本地实现:
// handle_kw_decode_lyric → 酷我歌词解码(见 lyricDecode.js)
// handle_tx_decode_lyric → QQ音乐歌词解码(见 lyricDecode.js)
import { handleKwDecodeLyric, handleTxDecodeLyric } from './lyricDecode.ts'
const localHandlers = {
[WIN_MAIN_RENDERER_EVENT_NAME.handle_kw_decode_lyric]: handleKwDecodeLyric,
[WIN_MAIN_RENDERER_EVENT_NAME.handle_tx_decode_lyric]: handleTxDecodeLyric,
}
/**
* 调用主进程能力(本地直调)
* @param {string} name 事件名
* @param {*} params 参数
*/
export const rendererInvoke = async(name, params) => {
const handler = localHandlers[name]
if (!handler) throw new Error(`Unsupported invoke: ${name}`)
return handler(params)
}
export const rendererSend = () => {}
export const rendererOn = () => {}
export const rendererOnce = () => {}
export const rendererOff = () => {}
export const rendererOffAll = () => {}
export const rendererSendSync = () => {}
import { WIN_MAIN_RENDERER_EVENT_NAME } from './ipcNames.ts'
export default { rendererInvoke, rendererSend, rendererOn, rendererOnce, rendererOff, rendererOffAll, rendererSendSync }
+12 -2
View File
@@ -2,7 +2,10 @@ import kw from './kw/index.ts'
import kg from './kg/index.ts' import kg from './kg/index.ts'
import tx from './tx/index.ts' import tx from './tx/index.ts'
import wy from './wy/index.ts' import wy from './wy/index.ts'
import { supportQuality } from './api-source.ts' import { supportQualitys as kwQualitys } from './apis/kw.ts'
import { supportQualitys as kgQualitys } from './apis/kg.ts'
import { supportQualitys as txQualitys } from './apis/tx.ts'
import { supportQualitys as wyQualitys } from './apis/wy.ts'
import type { PlatformModule, SearchResult, SongInfo } from './types.ts' import type { PlatformModule, SearchResult, SongInfo } from './types.ts'
import { import {
sizeFormate, sizeFormate,
@@ -31,7 +34,14 @@ export const sources = SUPPORTED_SOURCES.map(({ id, name }) => ({ id, name }))
export const init = (): Promise<unknown[]> => export const init = (): Promise<unknown[]> =>
Promise.all(SUPPORTED_SOURCES.map((s) => s.module.init?.()).filter(Boolean)) Promise.all(SUPPORTED_SOURCES.map((s) => s.module.init?.()).filter(Boolean))
export { supportQuality } // 各平台官方直连接口支持的音质(由取流接口的音质映射推导;
// 外部音源模式下实际可用音质取决于 sources/ 脚本,另行运行时表现)
export const supportQuality: Record<string, string[]> = {
kw: kwQualitys,
kg: kgQualitys,
tx: txQualitys,
wy: wyQualitys,
}
const trimStr = (str: unknown): string => (typeof str === 'string' ? str.trim() : str as string) const trimStr = (str: unknown): string => (typeof str === 'string' ? str.trim() : str as string)
+2 -10
View File
@@ -1,5 +1,5 @@
import leaderboard from './leaderboard.ts' import leaderboard from './leaderboard.ts'
import { apis } from '../api-source.ts' import kgApi from '../apis/kg.ts'
import songList from './songList.ts' import songList from './songList.ts'
import musicSearch from './musicSearch.ts' import musicSearch from './musicSearch.ts'
import pic from './pic.ts' import pic from './pic.ts'
@@ -8,10 +8,8 @@ import hotSearch from './hotSearch.ts'
import comment from './comment.ts' import comment from './comment.ts'
import singer from './singer.ts' import singer from './singer.ts'
import album from './album.ts' import album from './album.ts'
// import tipSearch from './tipSearch.ts'
const kg = { const kg = {
// tipSearch,
leaderboard, leaderboard,
songList, songList,
musicSearch, musicSearch,
@@ -20,23 +18,17 @@ const kg = {
singer, singer,
album, album,
getMusicUrl(songInfo, type) { getMusicUrl(songInfo, type) {
return apis('kg').getMusicUrl!(songInfo, type) return kgApi.getMusicUrl(songInfo, type)
}, },
getLyric(songInfo) { getLyric(songInfo) {
return lyric.getLyric(songInfo) return lyric.getLyric(songInfo)
}, },
// getLyric(songInfo) {
// return apis('kg').getLyric(songInfo)
// },
getPic(songInfo) { getPic(songInfo) {
return pic.getPic(songInfo) return pic.getPic(songInfo)
}, },
getMusicDetailPageUrl(songInfo) { getMusicDetailPageUrl(songInfo) {
return `https://www.kugou.com/song/#hash=${songInfo.hash}&album_id=${songInfo.albumId}` return `https://www.kugou.com/song/#hash=${songInfo.hash}&album_id=${songInfo.albumId}`
}, },
// getPic(songInfo) {
// return apis('kg').getPic(songInfo)
// },
} }
export default kg export default kg
@@ -1,7 +1,7 @@
// 酷狗 krc 歌词解码 // 酷狗 krc 歌词解码
import zlib from 'node:zlib' import zlib from 'node:zlib'
import { decodeName } from '../utils.ts' import { decodeName } from '../common/utils.ts'
// 基于社区通用的 krc 解析思路 // 基于社区通用的 krc 解析思路
const enc_key = Buffer.from([0x40, 0x47, 0x61, 0x77, 0x5e, 0x32, 0x74, 0x47, 0x51, 0x36, 0x31, 0x2d, 0xce, 0xd2, 0x6e, 0x69]) const enc_key = Buffer.from([0x40, 0x47, 0x61, 0x77, 0x5e, 0x32, 0x74, 0x47, 0x51, 0x36, 0x31, 0x2d, 0xce, 0xd2, 0x6e, 0x69])
+1 -1
View File
@@ -1,5 +1,5 @@
import { httpFetch } from '../request.ts' import { httpFetch } from '../request.ts'
import { decodeKrc } from '../common/lyricUtils/kg.ts' import { decodeKrc } from './krcDecode.ts'
export default { export default {
getIntv(interval) { getIntv(interval) {
-25
View File
@@ -1,25 +0,0 @@
import { createHttpFetch } from './util.ts'
export default {
requestObj: null as any,
cancelTipSearch() {
if (this.requestObj && this.requestObj.cancelHttp) this.requestObj.cancelHttp()
},
tipSearchBySong(str) {
this.cancelTipSearch()
this.requestObj = createHttpFetch(`https://searchtip.kugou.com/getSearchTip?MusicTipCount=10&keyword=${encodeURIComponent(str)}`, {
headers: {
referer: 'https://www.kugou.com/',
},
})
return this.requestObj.then(body => {
return body[0].RecordDatas
})
},
handleResult(rawData) {
return rawData.map(info => info.HintInfo)
},
async search(str) {
return this.tipSearchBySong(str).then(result => this.handleResult(result))
},
}
+2 -4
View File
@@ -1,11 +1,10 @@
import { httpFetch } from '../request.ts' import { httpFetch } from '../request.ts'
import tipSearch from './tipSearch.ts'
import musicSearch from './musicSearch.ts' import musicSearch from './musicSearch.ts'
import { formatSinger } from './util.ts' import { formatSinger } from './util.ts'
import leaderboard from './leaderboard.ts' import leaderboard from './leaderboard.ts'
import lyric from './lyric.ts' import lyric from './lyric.ts'
import pic from './pic.ts' import pic from './pic.ts'
import { apis } from '../api-source.ts' import kwApi from '../apis/kw.ts'
import songList from './songList.ts' import songList from './songList.ts'
import hotSearch from './hotSearch.ts' import hotSearch from './hotSearch.ts'
import comment from './comment.ts' import comment from './comment.ts'
@@ -35,7 +34,6 @@ const kw = {
// // }) // // })
// }, // },
tipSearch,
musicSearch, musicSearch,
leaderboard, leaderboard,
songList, songList,
@@ -63,7 +61,7 @@ const kw = {
}, },
getMusicUrl(songInfo, type) { getMusicUrl(songInfo, type) {
return apis('kw').getMusicUrl!(songInfo, type) return kwApi.getMusicUrl(songInfo, type)
}, },
getMusicInfo(songInfo) { getMusicInfo(songInfo) {
@@ -1,14 +1,10 @@
// 歌词解码(原主进程 IPC 处理器的纯 JS 实现) // 酷我歌词解码(原主进程 IPC 处理器的纯 JS 实现)
// - handle_kw_decode_lyric: 酷我歌词(inflate + yeelion XOR + gb18030) // - 酷我歌词(inflate + yeelion XOR + gb18030)
// 算法来源: kw 桌面端歌词解码实现 // 算法来源: kw 桌面端歌词解码实现
// - handle_tx_decode_lyric: QQ音乐歌词(qrc 解码:hex → XOR 偏移 → deflate)
// qrc 算法来源: 开源 qrc 解码器(ZhuYiQing/qrcDecode 纯 JS 版)
import zlib from 'node:zlib' import zlib from 'node:zlib'
import iconv from 'iconv-lite' import iconv from 'iconv-lite'
// ==================== 酷我 ====================
const handleInflate = (data: Buffer): Promise<Buffer> => new Promise((resolve, reject) => { const handleInflate = (data: Buffer): Promise<Buffer> => new Promise((resolve, reject) => {
zlib.inflate(data, (err, result) => { zlib.inflate(data, (err, result) => {
if (err) return reject(err) if (err) return reject(err)
@@ -50,17 +46,3 @@ export const handleKwDecodeLyric = async({ lrcBase64, isGetLyricx }) => {
const lrc = await decodeKwLyric(Buffer.from(lrcBase64, 'base64'), isGetLyricx) const lrc = await decodeKwLyric(Buffer.from(lrcBase64, 'base64'), isGetLyricx)
return Buffer.from(lrc).toString('base64') return Buffer.from(lrc).toString('base64')
} }
// ==================== QQ音乐(qrc) ====================
import { decodeQrc } from './qrcDecode.ts'
/**
* QQ音乐歌词解码
* @param {{ lrc: string, tlrc: string, rlrc: string }} params 均为十六进制字符串
* @returns {Promise<{lyric: string, tlyric: string, rlyric: string}>}
*/
export const handleTxDecodeLyric = async({ lrc, tlrc, rlrc }) => {
const [lyric, tlyric, rlyric] = await Promise.all([decodeQrc(lrc), decodeQrc(tlrc), decodeQrc(rlrc)])
return { lyric, tlyric, rlyric }
}
-35
View File
@@ -1,35 +0,0 @@
// import { decodeName } from '../index.ts'
// import { tokenRequest } from './util.ts'
import { httpFetch } from '../request.ts'
import type { HttpRequestObject } from '../types.ts'
export default {
regExps: {
relWord: /RELWORD=(.+)/,
},
requestObj: null as HttpRequestObject | null,
async tipSearchBySong(str: string) {
// 报错403,加了referer还是有问题(直接换一个
// this.requestObj = await tokenRequest(`http://www.kuwo.cn/api/www/search/searchKey?key=${encodeURIComponent(str)}`)
this.cancelTipSearch()
this.requestObj = httpFetch(`https://tips.kuwo.cn/t.s?corp=kuwo&newver=3&p2p=1&notrace=0&c=mbox&w=${encodeURIComponent(str)}&encoding=utf8&rformat=json`, {
headers: {
Referer: 'http://www.kuwo.cn/',
},
})
return this.requestObj!.promise.then(({ body, statusCode }) => {
if (statusCode != 200 || !body.WORDITEMS) return Promise.reject(new Error('请求失败'))
return body.WORDITEMS
})
},
handleResult(rawData: any) {
return rawData.map(item => item.RELWORD)
},
cancelTipSearch() {
if (this.requestObj && this.requestObj.cancelHttp) this.requestObj.cancelHttp()
},
async search(str: string) {
return this.tipSearchBySong(str).then(result => this.handleResult(result))
},
}
+2 -4
View File
@@ -1,6 +1,5 @@
// import { httpGet, httpFetch } from '../request.ts' // import { httpGet, httpFetch } from '../request.ts'
import { WIN_MAIN_RENDERER_EVENT_NAME } from '../common/ipcNames.ts' import { handleKwDecodeLyric } from './lyricDecode.ts'
import { rendererInvoke } from '../common/rendererIpc.ts'
import { createCipheriv, createDecipheriv } from 'crypto' import { createCipheriv, createDecipheriv } from 'crypto'
import { toMD5 } from '../utils.ts' import { toMD5 } from '../utils.ts'
@@ -63,8 +62,7 @@ export const matchToken = (headers: Record<string, any>): string | null => {
// }) // })
// }) // })
export const decodeLyric = (base64Data: { lrcBase64: string; isGetLyricx: boolean }): Promise<any> => export const decodeLyric = handleKwDecodeLyric
rendererInvoke(WIN_MAIN_RENDERER_EVENT_NAME.handle_kw_decode_lyric, base64Data)
// export const tokenRequest = async(url, options = {}) => { // export const tokenRequest = async(url, options = {}) => {
// let token = kw_token.token // let token = kw_token.token
+2 -4
View File
@@ -2,15 +2,13 @@ import leaderboard from './leaderboard.ts'
import lyric from './lyric.ts' import lyric from './lyric.ts'
import songList from './songList.ts' import songList from './songList.ts'
import musicSearch from './musicSearch.ts' import musicSearch from './musicSearch.ts'
import { apis } from '../api-source.ts' import txApi from '../apis/tx.ts'
import hotSearch from './hotSearch.ts' import hotSearch from './hotSearch.ts'
import comment from './comment.ts' import comment from './comment.ts'
import singer from './singer.ts' import singer from './singer.ts'
import album from './album.ts' import album from './album.ts'
// import tipSearch from './tipSearch.ts'
const tx = { const tx = {
// tipSearch,
leaderboard, leaderboard,
songList, songList,
musicSearch, musicSearch,
@@ -20,7 +18,7 @@ const tx = {
album, album,
getMusicUrl(songInfo, type) { getMusicUrl(songInfo, type) {
return apis('tx')!.getMusicUrl(songInfo, type) return txApi.getMusicUrl(songInfo, type)
}, },
getLyric(songInfo) { getLyric(songInfo) {
// let singer = songInfo.singer.indexOf('、') > -1 ? songInfo.singer.split('、')[0] : songInfo.singer // let singer = songInfo.singer.indexOf('、') > -1 ? songInfo.singer.split('、')[0] : songInfo.singer
+5 -3
View File
@@ -1,12 +1,14 @@
import type { HttpRequestObject } from '../types.ts' import type { HttpRequestObject } from '../types.ts'
import { httpFetch } from '../request.ts' import { httpFetch } from '../request.ts'
import getMusicInfo from './musicInfo.ts' import getMusicInfo from './musicInfo.ts'
import { rendererInvoke } from '../common/rendererIpc.ts' import { decodeQrc } from './qrcDecode.ts'
import { WIN_MAIN_RENDERER_EVENT_NAME } from '../common/ipcNames.ts'
const songIdMap = new Map() const songIdMap = new Map()
const promises = new Map() const promises = new Map()
export const decodeLyric = (lrc: any, tlrc?: any, rlrc?: any): Promise<any> => rendererInvoke(WIN_MAIN_RENDERER_EVENT_NAME.handle_tx_decode_lyric, { lrc, tlrc, rlrc }) export const decodeLyric = async(lrc: any, tlrc?: any, rlrc?: any) => {
const [lyric, tlyric, rlyric] = await Promise.all([decodeQrc(lrc), decodeQrc(tlrc), decodeQrc(rlrc)])
return { lyric, tlyric, rlyric }
}
const parseTools = { const parseTools = {
File renamed without changes.
-30
View File
@@ -1,30 +0,0 @@
import type { HttpRequestObject } from '../types.ts'
import { httpFetch } from '../request.ts'
export default {
// regExps: {
// relWord: /RELWORD=(.+)/,
// },
requestObj: null as HttpRequestObject | null,
tipSearch(str) {
this.cancelTipSearch()
this.requestObj = httpFetch(`https://c.y.qq.com/splcloud/fcgi-bin/smartbox_new.fcg?is_xml=0&format=json&key=${encodeURIComponent(str)}&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq&needNewCode=0`, {
headers: {
Referer: 'https://y.qq.com/portal/player.html',
},
})
return this.requestObj.promise.then(({ statusCode, body }) => {
if (statusCode != 200 || body.code != 0) return Promise.reject(new Error('请求失败'))
return body.data
})
},
handleResult(rawData) {
return rawData.map(info => `${info.name} - ${info.singer}`)
},
cancelTipSearch() {
if (this.requestObj && this.requestObj.cancelHttp) this.requestObj.cancelHttp()
},
async search(str) {
return this.tipSearch(str).then(result => this.handleResult(result.song.itemlist))
},
}
-1
View File
@@ -136,7 +136,6 @@ export interface PlatformModule {
songList?: any songList?: any
hotSearch?: HotSearchModule hotSearch?: HotSearchModule
comment?: CommentModule comment?: CommentModule
tipSearch?: any
getMusicUrl?(songInfo: SongInfo, type: Quality): HttpRequestObject getMusicUrl?(songInfo: SongInfo, type: Quality): HttpRequestObject
getLyric?(songInfo: SongInfo, ...rest: unknown[]): HttpRequestObject getLyric?(songInfo: SongInfo, ...rest: unknown[]): HttpRequestObject
getPic?(songInfo: SongInfo, ...rest: unknown[]): HttpRequestObject | Promise<any> getPic?(songInfo: SongInfo, ...rest: unknown[]): HttpRequestObject | Promise<any>
+2 -4
View File
@@ -1,5 +1,5 @@
import leaderboard from './leaderboard.ts' import leaderboard from './leaderboard.ts'
import { apis } from '../api-source.ts' import wyApi from '../apis/wy.ts'
import getLyric from './lyric.ts' import getLyric from './lyric.ts'
import getMusicInfo from './musicInfo.ts' import getMusicInfo from './musicInfo.ts'
import musicSearch from './musicSearch.ts' import musicSearch from './musicSearch.ts'
@@ -7,10 +7,8 @@ import songList from './songList.ts'
import hotSearch from './hotSearch.ts' import hotSearch from './hotSearch.ts'
import comment from './comment.ts' import comment from './comment.ts'
import singer from './singer.ts' import singer from './singer.ts'
// import tipSearch from './tipSearch.ts'
const wy = { const wy = {
// tipSearch,
leaderboard, leaderboard,
musicSearch, musicSearch,
songList, songList,
@@ -18,7 +16,7 @@ const wy = {
comment, comment,
singer, singer,
getMusicUrl(songInfo, type) { getMusicUrl(songInfo, type) {
return apis('wy').getMusicUrl!(songInfo, type) return wyApi.getMusicUrl(songInfo, type)
}, },
getLyric(songInfo) { getLyric(songInfo) {
return getLyric(songInfo.songmid) return getLyric(songInfo.songmid)
-34
View File
@@ -1,34 +0,0 @@
import { httpFetch } from '../request.ts'
import { weapi } from './utils/crypto.ts'
import { formatSingerName } from '../utils.ts'
import type { HttpRequestObject } from '../types.ts'
export default {
requestObj: null as HttpRequestObject | null,
cancelTipSearch() {
if (this.requestObj && this.requestObj.cancelHttp) this.requestObj.cancelHttp()
},
tipSearchBySong(str) {
this.cancelTipSearch()
this.requestObj = httpFetch('https://music.163.com/weapi/search/suggest/web', {
method: 'POST',
headers: {
referer: 'https://music.163.com/',
origin: 'https://music.163.com/',
},
form: weapi({
s: str,
}),
})
return this.requestObj!.promise.then(({ statusCode, body }) => {
if (statusCode != 200 || body.code != 200) return Promise.reject(new Error('请求失败'))
return body.result.songs
})
},
handleResult(rawData) {
return rawData.map(info => `${info.name} - ${formatSingerName(info.artists, 'name')}`)
},
async search(str) {
return this.tipSearchBySong(str).then(result => this.handleResult(result))
},
}