修复 tx 偶现搜索失败的问题

This commit is contained in:
lyswhut
2026-04-10 09:11:29 +08:00
parent e35895d752
commit ba62ae27af
3 changed files with 107 additions and 57 deletions
+63 -57
View File
@@ -1,6 +1,6 @@
import { httpFetch } from '../../request'
import { formatPlayTime, sizeFormate } from '../../index'
import { formatSingerName } from '../utils'
import { signRequest } from './utils'
export default {
limit: 50,
@@ -10,71 +10,77 @@ export default {
successCode: 0,
musicSearch(str, page, limit, retryNum = 0) {
if (retryNum > 5) return Promise.reject(new Error('搜索失败'))
// searchRequest = httpFetch(`https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=sizer.yqq.song_next&searchid=49252838123499591&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=${page}&n=${limit}&w=${encodeURIComponent(str)}&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq&needNewCode=0`)
// const searchRequest = httpFetch(`https://shc.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&remoteplace=txt.yqq.top&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=${page}&n=${limit}&w=${encodeURIComponent(str)}&cv=4747474&ct=24&format=json&inCharset=utf-8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&uin=0&hostUin=0&loginUin=0`)
const searchRequest = httpFetch('https://u.y.qq.com/cgi-bin/musicu.fcg', {
method: 'post',
headers: {
'User-Agent': 'QQMusic 14090508(android 12)',
const searchRequest = signRequest({
comm: {
ct: '11',
cv: '14090508',
v: '14090508',
tmeAppID: 'qqmusic',
phonetype: 'EBG-AN10',
deviceScore: '553.47',
devicelevel: '50',
newdevicelevel: '20',
rom: 'HuaWei/EMOTION/EmotionUI_14.2.0',
os_ver: '12',
OpenUDID: '0',
OpenUDID2: '0',
QIMEI36: '0',
udid: '0',
chid: '0',
aid: '0',
oaid: '0',
taid: '0',
tid: '0',
wid: '0',
uid: '0',
sid: '0',
modeSwitch: '6',
teenMode: '0',
ui_mode: '2',
nettype: '1020',
v4ip: '',
},
body: {
comm: {
ct: '11',
cv: '14090508',
v: '14090508',
tmeAppID: 'qqmusic',
phonetype: 'EBG-AN10',
deviceScore: '553.47',
devicelevel: '50',
newdevicelevel: '20',
rom: 'HuaWei/EMOTION/EmotionUI_14.2.0',
os_ver: '12',
OpenUDID: '0',
OpenUDID2: '0',
QIMEI36: '0',
udid: '0',
chid: '0',
aid: '0',
oaid: '0',
taid: '0',
tid: '0',
wid: '0',
uid: '0',
sid: '0',
modeSwitch: '6',
teenMode: '0',
ui_mode: '2',
nettype: '1020',
v4ip: '',
},
req: {
module: 'music.search.SearchCgiService',
method: 'DoSearchForQQMusicMobile',
param: {
search_type: 0,
query: str,
page_num: page,
num_per_page: limit,
highlight: 0,
nqc_flag: 0,
multi_zhida: 0,
cat: 2,
grp: 1,
sin: 0,
sem: 0,
},
req: {
module: 'music.search.SearchCgiService',
method: 'DoSearchForQQMusicMobile',
param: {
search_type: 0,
searchid: Math.random().toString().slice(2),
query: str,
page_num: page,
num_per_page: limit,
highlight: 0,
nqc_flag: 0,
multi_zhida: 0,
cat: 2,
grp: 1,
sin: 0,
sem: 0,
},
},
})
// searchRequest = httpFetch(`http://ioscdn.kugou.com/api/v3/search/song?keyword=${encodeURIComponent(str)}&page=${page}&pagesize=${this.limit}&showtype=10&plat=2&version=7910&tag=1&correct=1&privilege=1&sver=5`)
return searchRequest.promise.then(({ body }) => {
return searchRequest.then(({ body }) => {
// console.log(body)
if (body.code != this.successCode || body.req.code != this.successCode) return this.musicSearch(str, page, limit, ++retryNum)
if (!body || !body.req || body.code != this.successCode || body.req.code != this.successCode) {
return this.musicSearch(str, page, limit, ++retryNum)
}
return body.req.data
})
},
// randomInt(min, max) {
// return Math.floor(Math.random() * (max - min + 1)) + min
// },
// getSearchId() {
// const e = BigInt(this.randomInt(1, 20))
// const t = e * 18014398509481984n
// const n = BigInt(this.randomInt(0, 4194304)) * 4294967296n
// const a = BigInt(Date.now())
// const r = (a * 1000n) % (24n * 60n * 60n * 1000n)
// return String(t + n + r)
// },
handleResult(rawList) {
console.log(rawList)
// console.log(rawList)
if (!rawList || !Array.isArray(rawList)) return []
const list = []
rawList.forEach(item => {
if (!item.file?.media_mid) return
@@ -0,0 +1,28 @@
import crypto from 'node:crypto'
const PART_1_INDEXES = [23, 14, 6, 36, 16, 40, 7, 19]
const PART_2_INDEXES = [16, 1, 32, 12, 19, 27, 8, 5]
const SCRAMBLE_VALUES = [89, 39, 179, 150, 218, 82, 58, 252, 177, 52, 186, 123, 120, 64, 242, 133, 143, 161, 121, 179]
async function hashSHA1(data) {
return crypto.createHash('sha1').update(data).digest('hex')
}
function pickHashByIdx(hash, indexes) {
return indexes.map((idx) => hash[idx]).join('')
}
function base64Encode(data) {
return Buffer.from(data)
.toString('base64')
.replace(/[\\/+=]/g, '')
}
export async function zzcSign(text) {
const hash = await hashSHA1(text)
const part1 = pickHashByIdx(hash, PART_1_INDEXES)
const part2 = pickHashByIdx(hash, PART_2_INDEXES)
const part3 = SCRAMBLE_VALUES.map((value, i) => value ^ parseInt(hash.slice(i * 2, i * 2 + 2), 16))
const b64Part = base64Encode(part3).replace(/[\\/+=]/g, '')
return `zzc${part1}${b64Part}${part2}`.toLowerCase()
}
@@ -0,0 +1,16 @@
import { httpFetch } from '../../../request'
import { zzcSign } from './crypto'
export const signRequest = async(data) => {
// console.log(data)
const sign = await zzcSign(JSON.stringify(data))
// console.log('sign', sign)
return httpFetch(`https://u.y.qq.com/cgi-bin/musics.fcg?sign=${sign}`, {
method: 'post',
headers: {
'User-Agent': 'QQMusic 14090508(android 12)',
},
body: data,
}).promise
}