更新API

This commit is contained in:
Folltoshe 2023-04-25 00:38:31 +08:00
parent f383f132e7
commit b3dc8214e0
4 changed files with 170 additions and 174 deletions

View File

@ -1,4 +1,5 @@
import { decodeName, formatPlayTime, sizeFormate } from '../../index'
import { createHttpFetch } from './util'
const createGetMusicInfoTask = (hashs) => {
let data = {
@ -20,7 +21,7 @@ const createGetMusicInfoTask = (hashs) => {
list = list.slice(100)
}
let url = 'http://kmr.service.kugou.com/v2/album_audio/audio'
return tasks.map(task => this.createHttp(url, {
return tasks.map(task => createHttpFetch(url, {
method: 'POST',
body: task,
headers: {

View File

@ -1,15 +1,12 @@
// import '../../polyfill/array.find'
import { httpFetch } from '../../request'
import { decodeName, formatPlayTime, sizeFormate } from '../../index'
import { signatureParams } from './util'
// import { debug } from '../../utils/env'
// import { formatSinger } from './util'
const searchParams = (params, keyword) => {
let signature = signatureParams(params.replace('{keyword}', keyword))
return `${params.replace('{keyword}', encodeURIComponent(keyword))}&signature=${signature}`
}
// const searchParams = (params, keyword) => {
// let signature = signatureParams(params.replace('{keyword}', keyword))
// return `${params.replace('{keyword}', encodeURIComponent(keyword))}&signature=${signature}`
// }
export default {
limit: 30,
@ -17,78 +14,75 @@ export default {
page: 0,
allPage: 1,
musicSearch(str, page, limit) {
let params = `userid=0&area_code=1&appid=1005&dopicfull=1&page=${page}&token=0&privilegefilter=0&requestid=0&pagesize=${limit}&user_labels=&clienttime=0&sec_aggre=1&iscorrection=1&uuid=0&mid=0&keyword={keyword}&dfid=-&clientver=11409&platform=AndroidFilter&tag=`
const searchRequest = httpFetch(`https://gateway.kugou.com/complexsearch/v3/search/song?${searchParams(params, str)}`)
const sign = signatureParams(`userid=0&area_code=1&appid=1005&dopicfull=1&page=${page}&token=0&privilegefilter=0&requestid=0&pagesize=${limit}&user_labels=&clienttime=0&sec_aggre=1&iscorrection=1&uuid=0&mid=0&keyword=${str}&dfid=-&clientver=11409&platform=AndroidFilter&tag=`, 3)
const searchRequest = httpFetch(`https://gateway.kugou.com/complexsearch/v3/search/song?userid=0&area_code=1&appid=1005&dopicfull=1&page=${page}&token=0&privilegefilter=0&requestid=0&pagesize=${limit}&user_labels=&clienttime=0&sec_aggre=1&iscorrection=1&uuid=0&mid=0&dfid=-&clientver=11409&platform=AndroidFilter&tag=&keyword=${encodeURIComponent(str)}&signature=${sign}`)
return searchRequest.promise.then(({ body }) => body)
},
filterData(rawData) {
const types = []
const _types = {}
if (rawData.FileSize !== 0) {
let size = sizeFormate(rawData.FileSize)
types.push({ type: '128k', size, hash: rawData.FileHash })
_types['128k'] = {
size,
hash: rawData.FileHash,
}
}
if (rawData.HQFileSize !== 0) {
let size = sizeFormate(rawData.HQFileSize)
types.push({ type: '320k', size, hash: rawData.HQFileHash })
_types['320k'] = {
size,
hash: rawData.HQFileHash,
}
}
if (rawData.SQFileSize !== 0) {
let size = sizeFormate(rawData.SQFileSize)
types.push({ type: 'flac', size, hash: rawData.SQFileHash })
_types.flac = {
size,
hash: rawData.SQFileHash,
}
}
if (rawData.ResFileSize !== 0) {
let size = sizeFormate(rawData.ResFileSize)
types.push({ type: 'flac24bit', size, hash: rawData.ResFileHash })
_types.flac24bit = {
size,
hash: rawData.ResFileHash,
}
}
return {
singer: decodeName(rawData.SingerName),
name: decodeName(rawData.SongName),
albumName: decodeName(rawData.AlbumName),
albumId: rawData.AlbumID,
songmid: rawData.Audioid,
source: 'kg',
interval: formatPlayTime(rawData.Duration),
_interval: rawData.Duration,
img: null,
lrc: null,
otherSource: null,
hash: rawData.FileHash,
types,
_types,
typeUrl: {},
}
},
handleResult(rawData) {
filterSongData(rawData) {
let ids = new Set()
const list = []
rawData.forEach(item => {
const key = item.Audioid + item.FileHash
if (ids.has(key)) return
ids.add(key)
list.push(this.filterData(item))
for (const childItem of item.Grp) {
const key = item.Audioid + item.FileHash
if (ids.has(key)) continue
ids.add(key)
list.push(this.filterData(childItem))
const filterList = (raw) => {
if (ids.has(raw.Audioid)) return
ids.add(raw.Audioid)
const types = []
const _types = {}
if (raw.FileSize !== 0) {
let size = sizeFormate(raw.FileSize)
types.push({ type: '128k', size, hash: raw.FileHash })
_types['128k'] = {
size,
hash: raw.FileHash,
}
}
if (raw.HQ) {
let size = sizeFormate(raw.HQ.FileSize)
types.push({ type: '320k', size, hash: raw.HQ.Hash })
_types['320k'] = {
size,
hash: raw.HQ.Hash,
}
}
if (raw.SQ) {
let size = sizeFormate(raw.SQ.FileSize)
types.push({ type: 'flac', size, hash: raw.SQ.Hash })
_types.flac = {
size,
hash: raw.SQ.Hash,
}
}
if (raw.Res) {
let size = sizeFormate(raw.Res.FileSize)
types.push({ type: 'flac24bit', size, hash: raw.Res.Hash })
_types.flac24bit = {
size,
hash: raw.Res.Hash,
}
}
list.push({
singer: decodeName(raw.SingerName),
name: decodeName(raw.OriSongName),
albumName: decodeName(raw.AlbumName),
albumId: raw.AlbumID,
songmid: raw.Audioid,
source: 'kg',
interval: formatPlayTime(raw.Duration),
_interval: raw.Duration,
img: null,
lrc: null,
otherSource: null,
hash: raw.FileHash,
types,
_types,
typeUrl: {},
})
}
rawData.forEach(item => {
filterList(item)
if (item.Grp) item.Grp.forEach(e => filterList(e))
})
return list
},
search(str, page = 1, limit, retryNum = 0) {
@ -97,7 +91,8 @@ export default {
// http://newlyric.kuwo.cn/newlyric.lrc?62355680
return this.musicSearch(str, page, limit).then(result => {
if (!result || result.error_code !== 0) return this.search(str, page, limit, retryNum)
let list = this.handleResult(result.data.lists)
// console.log(result)
let list = this.filterSongData(result.data.lists)
if (list == null) return this.search(str, page, limit, retryNum)

View File

@ -1,6 +1,6 @@
import { httpFetch } from '../../request'
import { decodeName, formatPlayTime, sizeFormate, dateFormat } from '../../index'
import { signatureParams } from './util'
import { signatureParams, createHttpFetch } from './util'
import { getMusicInfosByList } from './musicInfo'
// import infSign from './vendors/infSign.min'
@ -47,6 +47,7 @@ export default {
},
],
cache: new Map(),
CollectionIdListInfoCache: new Map(),
regExps: {
listData: /global\.data = (\[.+\]);/,
listInfo: /global = {[\s\S]+?name: "(.+)"[\s\S]+?pic: "(.+)"[\s\S]+?};/,
@ -54,40 +55,19 @@ export default {
listDetailLink: /^.+\/(\d+)\.html(?:\?.*|&.*$|#.*$|$)/,
},
async createHttp(url, options, retryNum = 0) {
if (retryNum > 2) throw new Error('try max num')
let result
try {
result = await httpFetch(url, options).promise
} catch (err) {
console.log(err)
return this.createHttp(url, options, ++retryNum)
}
// console.log(result.statusCode, result.body)
if (result.statusCode !== 200 ||
(
(result.body.error_code !== undefined
? result.body.error_code
: result.body.errcode !== undefined
? result.body.errcode
: result.body.err_code
) !== 0)
) return this.createHttp(url, options, ++retryNum)
if (result.body.data) return result.body.data
if (Array.isArray(result.body.info)) return result.body
return result.body.info
},
/**
* 获取SpecialId歌单详情
* 获取SpecialId歌单
* @param {*} id
*/
async getListInfoBySpecialId(id, tryNum = 0) {
async getUserListDetailBySpecialId(id, page, tryNum = 0) {
if (tryNum > 2) throw new Error('try max num')
const { body } = await httpFetch(this.getSongListDetailUrl(id)).promise
let listData = body.match(this.regExps.listData)
let listInfo = body.match(this.regExps.listInfo)
if (!listInfo) return this.getListDetailBySpecialId(id, ++tryNum)
if (!listData) return this.getListDetailBySpecialId(id, page, ++tryNum)
let list = await getMusicInfosByList(JSON.parse(listData[1]))
// listData = this.filterData(JSON.parse(listData[1]))
let name
let pic
if (listInfo) {
@ -96,12 +76,20 @@ export default {
}
let desc = this.parseHtmlDesc(body)
return {
name,
image: pic,
desc,
// author: body.result.info.userinfo.username,
// play_count: this.formatPlayCount(body.result.listen_num),
list,
page: 1,
limit: 10000,
total: list.length,
source: 'kg',
info: {
name,
img: pic,
desc,
// author: body.result.info.userinfo.username,
// play_count: this.formatPlayCount(body.result.listen_num),
},
}
},
parseHtmlDesc(html) {
@ -256,43 +244,16 @@ export default {
})
},
createTask(hashs) {
let data = {
appid: 1001,
clienttime: 639437935,
clientver: 9020,
fields:
'album_info,author_name,audio_info,ori_audio_name',
is_publish: '1',
key: '0475af1457cd3363c7b45b871e94428a',
mid: '21511157a05844bd085308bc76ef3342',
show_privilege: 1,
}
let list = hashs
let tasks = []
while (list.length) {
tasks.push(Object.assign({ data: list.slice(0, 100) }, data))
if (list.length < 100) break
list = list.slice(100)
}
let url = 'http://kmr.service.kugou.com/v2/album_audio/audio'
return tasks.map(task => this.createHttp(url, {
method: 'POST',
body: task,
headers: {
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
},
}).then(data => data.map(s => s[0])))
},
/**
* 通过CollectionId获取歌单详情
* @param {*} id
*/
async getUserListInfoByCollectionId(id) {
if (!id || id.length > 1000) return Promise.reject(new Error('get list error'))
if (this.CollectionIdListInfoCache.has(id)) return this.CollectionIdListInfoCache.get(id)
const params = `appid=1058&specialid=0&global_specialid=${id}&format=jsonp&srcappid=2919&clientver=20000&clienttime=1586163242519&mid=1586163242519&uuid=1586163242519&dfid=-`
return this.createHttp(`https://mobiles.kugou.com/api/v5/special/info_v2?${params}&signature=${signatureParams(params, 5)}`, {
return createHttpFetch(`https://mobiles.kugou.com/api/v5/special/info_v2?${params}&signature=${signatureParams(params, 5)}`, {
headers: {
mid: '1586163242519',
Referer: 'https://m3ws.kugou.com/share/index.php',
@ -301,7 +262,7 @@ export default {
clienttime: '1586163242519',
},
}).then(body => {
return {
let info = {
type: body.type,
userName: body.nickname,
userAvatar: body.user_avatar,
@ -312,41 +273,44 @@ export default {
total: body.songcount,
playCount: body.playcount,
}
this.CollectionIdListInfoCache.set(id, info)
return info
})
},
/**
* 通过SpecialId获取歌单
* @param {*} id
*/
async getUserListDetailBySpecialId(id, page = 1, limit = 300) {
if (!id || id.length > 1000) return Promise.reject(new Error('get list error.'))
const listInfo = await this.getListInfoBySpecialId(id)
// async getUserListDetailBySpecialId(id, page = 1, limit = 300) {
// if (!id || id.length > 1000) return Promise.reject(new Error('get list error.'))
// const listInfo = await this.getListInfoBySpecialId(id)
const params = `specialid=${id}&need_sort=1&module=CloudMusic&clientver=11589&pagesize=${limit}&userid=0&page=${page}&type=0&area_code=1&appid=1005`
return this.createHttp(`http://pubsongs.kugou.com/v2/get_other_list_file?${params}&signature=${signatureParams(params, 2)}`, {
headers: {
'User-Agent': 'Android10-AndroidPhone-11589-201-0-playlist-wifi',
},
}).then(body => {
if (!body.info) return Promise.reject(new Error('Get list failed.'))
const songList = this.filterCollectionIdList(body.info)
// const params = `specialid=${id}&need_sort=1&module=CloudMusic&clientver=11589&pagesize=${limit}&userid=0&page=${page}&type=0&area_code=1&appid=1005`
// return createHttpFetch(`http://pubsongs.kugou.com/v2/get_other_list_file?${params}&signature=${signatureParams(params, 2)}`, {
// headers: {
// 'User-Agent': 'Android10-AndroidPhone-11589-201-0-playlist-wifi',
// },
// }).then(body => {
// if (!body.info) return Promise.reject(new Error('Get list failed.'))
// const songList = this.filterCollectionIdList(body.info)
return {
list: songList || [],
page,
limit,
total: songList.length,
source: 'kg',
info: {
name: listInfo.name,
img: listInfo.image,
desc: listInfo.desc,
// author: listInfo.userName,
// play_count: this.formatPlayCount(listInfo.playCount),
},
}
})
},
// return {
// list: songList || [],
// page,
// limit,
// total: body.count,
// source: 'kg',
// info: {
// name: listInfo.name,
// img: listInfo.image,
// desc: listInfo.desc,
// // author: listInfo.userName,
// // play_count: this.formatPlayCount(listInfo.playCount),
// },
// }
// })
// },
/**
* 通过CollectionId获取歌单
* @param {*} id
@ -356,7 +320,7 @@ export default {
const listInfo = await this.getUserListInfoByCollectionId(id)
const params = `need_sort=1&module=CloudMusic&clientver=11589&pagesize=${limit}&global_collection_id=${id}&userid=0&page=${page}&type=0&area_code=1&appid=1005`
return this.createHttp(`http://pubsongs.kugou.com/v2/get_other_list_file?${params}&signature=${signatureParams(params, 2)}`, {
return createHttpFetch(`http://pubsongs.kugou.com/v2/get_other_list_file?${params}&signature=${signatureParams(params, 2)}`, {
headers: {
'User-Agent': 'Android10-AndroidPhone-11589-201-0-playlist-wifi',
},
@ -455,7 +419,7 @@ export default {
*/
async getUserListDetailByCode(id, page = 1) {
// type 1单曲2歌单3电台4酷狗码5别人的播放队列
const codeData = await this.createHttp('http://t.kugou.com/command/', {
const codeData = await createHttpFetch('http://t.kugou.com/command/', {
method: 'POST',
headers: {
'KG-RC': 1,
@ -477,7 +441,7 @@ export default {
if (codeInfo.global_collection_id) return this.getUserListDetailByCollectionId(codeInfo.global_collection_id, page)
if (codeInfo.userid != null) {
const songList = await this.createHttp('http://www2.kugou.kugou.com/apps/kucodeAndShare/app/', {
const songList = await createHttpFetch('http://www2.kugou.kugou.com/apps/kucodeAndShare/app/', {
method: 'POST',
headers: {
'KG-RC': 1,
@ -506,7 +470,7 @@ export default {
},
async getUserListDetail3(chain, page) {
const songInfo = await this.createHttp(`http://m.kugou.com/schain/transfer?pagesize=${this.listDetailLimit}&chain=${chain}&su=1&page=${page}&n=0.7928855356604456`, {
const songInfo = await createHttpFetch(`http://m.kugou.com/schain/transfer?pagesize=${this.listDetailLimit}&chain=${chain}&su=1&page=${page}&n=0.7928855356604456`, {
headers: {
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
},
@ -542,7 +506,7 @@ export default {
const limit = total > 90 ? 90 : total
total -= limit
page += 1
tasks.push(this.createHttp(link.replace(/pagesize=\d+/, 'pagesize=' + limit).replace(/page=\d+/, 'page=' + page), {
tasks.push(createHttpFetch(link.replace(/pagesize=\d+/, 'pagesize=' + limit).replace(/page=\d+/, 'page=' + page), {
headers: {
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
Referer: link,
@ -575,7 +539,7 @@ export default {
total -= limit
page += 1
const params = 'appid=1058&global_specialid=' + id + '&specialid=0&plat=0&version=8000&page=' + page + '&pagesize=' + limit + '&srcappid=2919&clientver=20000&clienttime=1586163263991&mid=1586163263991&uuid=1586163263991&dfid=-'
tasks.push(this.createHttp(`https://mobiles.kugou.com/api/v5/special/song_v2?${params}&signature=${signatureParams(params, 5)}`, {
tasks.push(createHttpFetch(`https://mobiles.kugou.com/api/v5/special/song_v2?${params}&signature=${signatureParams(params, 5)}`, {
headers: {
mid: '1586163263991',
Referer: 'https://m3ws.kugou.com/share/index.php',
@ -591,7 +555,7 @@ export default {
let id = global_collection_id
if (id.length > 1000) throw new Error('get list error')
const params = 'appid=1058&specialid=0&global_specialid=' + id + '&format=jsonp&srcappid=2919&clientver=20000&clienttime=1586163242519&mid=1586163242519&uuid=1586163242519&dfid=-'
let info = await this.createHttp(`https://mobiles.kugou.com/api/v5/special/info_v2?${params}&signature=${signatureParams(params, 5)}`, {
let info = await createHttpFetch(`https://mobiles.kugou.com/api/v5/special/info_v2?${params}&signature=${signatureParams(params, 5)}`, {
headers: {
mid: '1586163242519',
Referer: 'https://m3ws.kugou.com/share/index.php',
@ -883,7 +847,7 @@ export default {
search(text, page, limit = 20) {
const params = `userid=1384394652&req_custom=1&appid=1005&req_multi=1&version=11589&page=${page}&filter=0&pagesize=${limit}&order=0&clienttime=1681779443&iscorrection=1&searchsong=0&keyword=${text}&mid=288799920684148686226285199951543865551&dfid=3eSBsO1u97EY1zeIZd40hH4p&clientver=11589&platform=AndroidFilter`
const url = encodeURI(`http://complexsearchretry.kugou.com/v1/search/special?${params}&signature=${signatureParams(params, 1)}`)
return this.createHttp(url).then(body => {
return createHttpFetch(url).then(body => {
// console.log(body)
return {
list: body.lists.map(item => {

View File

@ -1,5 +1,6 @@
import { inflate } from 'zlib'
import { toMD5 } from '../utils'
import { httpFetch } from '../../request'
// https://github.com/lyswhut/lx-music-desktop/issues/296#issuecomment-683285784
const enc_key = Buffer.from([0x40, 0x47, 0x61, 0x77, 0x5e, 0x32, 0x74, 0x47, 0x51, 0x36, 0x31, 0x2d, 0xce, 0xd2, 0x6e, 0x69], 'binary')
@ -19,6 +20,11 @@ export const decodeLyric = str => new Promise((resolve, reject) => {
// console.log(str)
// })
/**
* 签名
* @param {*} params
* @param {*} apiver
*/
export const signatureParams = (params, apiver = 9) => {
let keyparam = 'OIlwieks28dk2k092lksi2UIkp'
if (apiver === 5) keyparam = 'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt'
@ -27,3 +33,33 @@ export const signatureParams = (params, apiver = 9) => {
let sign_params = `${keyparam}${param_list.join('')}${keyparam}`
return toMD5(sign_params)
}
/**
* 创建一个Http请求
* @param {*} url
* @param {*} options
* @param {*} retryNum
*/
export const createHttpFetch = async(url, options, retryNum = 0) => {
if (retryNum > 2) throw new Error('try max num')
let result
try {
result = await httpFetch(url, options).promise
} catch (err) {
console.log(err)
return createHttpFetch(url, options, ++retryNum)
}
// console.log(result.statusCode, result.body)
if (result.statusCode !== 200 ||
(
(result.body.error_code !== undefined
? result.body.error_code
: result.body.errcode !== undefined
? result.body.errcode
: result.body.err_code
) !== 0)
) return createHttpFetch(url, options, ++retryNum)
if (result.body.data) return result.body.data
if (Array.isArray(result.body.info)) return result.body
return result.body.info
}