修复 tx 偶现搜索失败的问题
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { httpFetch } from '../../request'
|
|
||||||
import { formatPlayTime, sizeFormate } from '../../index'
|
import { formatPlayTime, sizeFormate } from '../../index'
|
||||||
import { formatSingerName } from '../utils'
|
import { formatSingerName } from '../utils'
|
||||||
|
import { signRequest } from './utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
limit: 50,
|
limit: 50,
|
||||||
@@ -10,71 +10,77 @@ export default {
|
|||||||
successCode: 0,
|
successCode: 0,
|
||||||
musicSearch(str, page, limit, retryNum = 0) {
|
musicSearch(str, page, limit, retryNum = 0) {
|
||||||
if (retryNum > 5) return Promise.reject(new Error('搜索失败'))
|
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¬ice=0&platform=yqq&needNewCode=0`)
|
const searchRequest = signRequest({
|
||||||
// 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¬ice=0&platform=yqq.json&needNewCode=0&uin=0&hostUin=0&loginUin=0`)
|
comm: {
|
||||||
const searchRequest = httpFetch('https://u.y.qq.com/cgi-bin/musicu.fcg', {
|
ct: '11',
|
||||||
method: 'post',
|
cv: '14090508',
|
||||||
headers: {
|
v: '14090508',
|
||||||
'User-Agent': 'QQMusic 14090508(android 12)',
|
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: {
|
req: {
|
||||||
comm: {
|
module: 'music.search.SearchCgiService',
|
||||||
ct: '11',
|
method: 'DoSearchForQQMusicMobile',
|
||||||
cv: '14090508',
|
param: {
|
||||||
v: '14090508',
|
search_type: 0,
|
||||||
tmeAppID: 'qqmusic',
|
searchid: Math.random().toString().slice(2),
|
||||||
phonetype: 'EBG-AN10',
|
query: str,
|
||||||
deviceScore: '553.47',
|
page_num: page,
|
||||||
devicelevel: '50',
|
num_per_page: limit,
|
||||||
newdevicelevel: '20',
|
highlight: 0,
|
||||||
rom: 'HuaWei/EMOTION/EmotionUI_14.2.0',
|
nqc_flag: 0,
|
||||||
os_ver: '12',
|
multi_zhida: 0,
|
||||||
OpenUDID: '0',
|
cat: 2,
|
||||||
OpenUDID2: '0',
|
grp: 1,
|
||||||
QIMEI36: '0',
|
sin: 0,
|
||||||
udid: '0',
|
sem: 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,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
// 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.then(({ body }) => {
|
||||||
return searchRequest.promise.then(({ body }) => {
|
|
||||||
// console.log(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
|
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) {
|
handleResult(rawList) {
|
||||||
console.log(rawList)
|
// console.log(rawList)
|
||||||
|
if (!rawList || !Array.isArray(rawList)) return []
|
||||||
const list = []
|
const list = []
|
||||||
rawList.forEach(item => {
|
rawList.forEach(item => {
|
||||||
if (!item.file?.media_mid) return
|
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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user