Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

更新kw源API #1460

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/renderer/utils/musicSdk/kw/album.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { httpFetch } from '../../request'
import { decodeName } from '../../index'
import { formatSinger, objStr2JSON } from './util'
import { formatSinger, objStr2JSON } from './utils'

// let requestObj_list
export default {
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/utils/musicSdk/kw/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { httpFetch } from '../../request'
import tipSearch from './tipSearch'
import musicSearch from './musicSearch'
import { formatSinger } from './util'
import { formatSinger } from './utils'
import leaderboard from './leaderboard'
import lyric from './lyric'
import pic from './pic'
Expand Down
110 changes: 54 additions & 56 deletions src/renderer/utils/musicSdk/kw/leaderboard.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { httpFetch } from '../../request'
import { formatPlayTime, decodeName } from '../../index'
import { formatSinger } from './util'
import { sortQualityArray } from '../utils'
import { formatSinger } from './utils'
import { wbdCrypto } from './utils/crypto'

const boardList = [{ id: 'kw__93', name: '飙升榜', bangid: '93' }, { id: 'kw__17', name: '新歌榜', bangid: '17' }, { id: 'kw__16', name: '热歌榜', bangid: '16' }, { id: 'kw__158', name: '抖音热歌榜', bangid: '158' }, { id: 'kw__292', name: '铃声榜', bangid: '292' }, { id: 'kw__284', name: '热评榜', bangid: '284' }, { id: 'kw__290', name: 'ACG新歌榜', bangid: '290' }, { id: 'kw__286', name: '台湾KKBOX榜', bangid: '286' }, { id: 'kw__279', name: '冬日暖心榜', bangid: '279' }, { id: 'kw__281', name: '巴士随身听榜', bangid: '281' }, { id: 'kw__255', name: 'KTV点唱榜', bangid: '255' }, { id: 'kw__280', name: '家务进行曲榜', bangid: '280' }, { id: 'kw__282', name: '熬夜修仙榜', bangid: '282' }, { id: 'kw__283', name: '枕边轻音乐榜', bangid: '283' }, { id: 'kw__278', name: '古风音乐榜', bangid: '278' }, { id: 'kw__264', name: 'Vlog音乐榜', bangid: '264' }, { id: 'kw__242', name: '电音榜', bangid: '242' }, { id: 'kw__187', name: '流行趋势榜', bangid: '187' }, { id: 'kw__204', name: '现场音乐榜', bangid: '204' }, { id: 'kw__186', name: 'ACG神曲榜', bangid: '186' }, { id: 'kw__185', name: '最强翻唱榜', bangid: '185' }, { id: 'kw__26', name: '经典怀旧榜', bangid: '26' }, { id: 'kw__104', name: '华语榜', bangid: '104' }, { id: 'kw__182', name: '粤语榜', bangid: '182' }, { id: 'kw__22', name: '欧美榜', bangid: '22' }, { id: 'kw__184', name: '韩语榜', bangid: '184' }, { id: 'kw__183', name: '日语榜', bangid: '183' }, { id: 'kw__145', name: '会员畅听榜', bangid: '145' }, { id: 'kw__153', name: '网红新歌榜', bangid: '153' }, { id: 'kw__64', name: '影视金曲榜', bangid: '64' }, { id: 'kw__176', name: 'DJ嗨歌榜', bangid: '176' }, { id: 'kw__106', name: '真声音', bangid: '106' }, { id: 'kw__12', name: 'Billboard榜', bangid: '12' }, { id: 'kw__49', name: 'iTunes音乐榜', bangid: '49' }, { id: 'kw__180', name: 'beatport电音榜', bangid: '180' }, { id: 'kw__13', name: '英国UK榜', bangid: '13' }, { id: 'kw__164', name: '百大DJ榜', bangid: '164' }, { id: 'kw__246', name: 'YouTube音乐排行榜', bangid: '246' }, { id: 'kw__265', name: '韩国Genie榜', bangid: '265' }, { id: 'kw__14', name: '韩国M-net榜', bangid: '14' }, { id: 'kw__8', name: '香港电台榜', bangid: '8' }, { id: 'kw__15', name: '日本公信榜', bangid: '15' }, { id: 'kw__151', name: '腾讯音乐人原创榜', bangid: '151' }]

Expand Down Expand Up @@ -62,9 +64,9 @@ export default {
bangid: 183,
},
],
getUrl: (p, l, id) => `http://kbangserver.kuwo.cn/ksong.s?from=pc&fmt=json&pn=${p - 1}&rn=${l}&type=bang&data=content&id=${id}&show_copyright_off=0&pcmp4=1&isbang=1`,
// getUrl: (p, l, id) => `http://kbangserver.kuwo.cn/ksong.s?from=pc&fmt=json&pn=${p - 1}&rn=${l}&type=bang&data=content&id=${id}&show_copyright_off=0&pcmp4=1&isbang=1`,
regExps: {

mInfo: /level:(\w+),bitrate:(\d+),format:(\w+),size:([\w.]+)/,
},
limit: 100,
_requestBoardsObj: null,
Expand All @@ -74,62 +76,51 @@ export default {
this._requestBoardsObj = httpFetch('http://qukudata.kuwo.cn/q.k?op=query&cont=tree&node=2&pn=0&rn=1000&fmt=json&level=2')
return this._requestBoardsObj.promise
},
getData(url) {
const requestDataObj = httpFetch(url)
return requestDataObj.promise
},
filterData(rawList) {
// console.log(rawList)
// console.log(rawList.length, rawList2.length)
return rawList.map((item, inedx) => {
let formats = item.formats.split('|')
return rawList.map(item => {
let types = []
let _types = {}
if (formats.includes('MP3128')) {
types.push({ type: '128k', size: null })
_types['128k'] = {
size: null,
}
}
// if (formats.includes('MP3192')) {
// types.push({ type: '192k', size: null })
// _types['192k'] = {
// size: null,
// }
// }
if (formats.includes('MP3H')) {
types.push({ type: '320k', size: null })
_types['320k'] = {
size: null,
}
}
// if (formats.includes('AL')) {
// types.push({ type: 'ape', size: null })
// _types.ape = {
// size: null,
// }
// }
if (formats.includes('ALFLAC')) {
types.push({ type: 'flac', size: null })
_types.flac = {
size: null,
}
}
if (formats.includes('HIRFLAC')) {
types.push({ type: 'flac24bit', size: null })
_types.flac24bit = {
size: null,
const _types = {}
const qualitys = new Set()

item.n_minfo.split(';').forEach(i => {
const info = i.match(this.regExps.mInfo)
if (!info) return

const quality = info[2]
const size = info[4].toLocaleUpperCase()

if (qualitys.has(quality)) return
qualitys.add(quality)

switch (quality) {
case '4000':
types.push({ type: 'flac24bit', size })
_types.flac24bit = { size }
break
case '2000':
types.push({ type: 'flac', size })
_types.flac = { size }
break
case '320':
types.push({ type: '320k', size })
_types['320k'] = { size }
break
case '128':
types.push({ type: '128k', size })
_types['128k'] = { size }
break
}
}
// types.reverse()
})
types = sortQualityArray(types)

return {
singer: formatSinger(decodeName(item.artist)),
name: decodeName(item.name),
albumName: decodeName(item.album),
albumId: item.albumid,
albumId: item.albumId,
songmid: item.id,
source: 'kw',
interval: formatPlayTime(parseInt(item.song_duration)),
interval: formatPlayTime(parseInt(item.duration)),
img: item.pic,
lrc: null,
otherSource: null,
Expand Down Expand Up @@ -180,12 +171,19 @@ export default {

getList(id, page, retryNum = 0) {
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
return this.getData(this.getUrl(page, this.limit, id)).then(({ statusCode, body }) => {
// console.log(body)
if (statusCode !== 200 || !body.musiclist) return this.getList(id, page, retryNum)
// console.log(data1.musiclist, data2.data)
let total = parseInt(body.num)
let list = this.filterData(body.musiclist)

const requestBody = { uid: '', devId: '', sFrom: 'kuwo_sdk', user_type: 'AP', carSource: 'kwplayercar_ar_6.0.1.0_apk_keluze.apk', id, pn: page - 1, rn: this.limit }
const requestUrl = `https://wbd.kuwo.cn/api/bd/bang/bang_info?${wbdCrypto.buildParam(requestBody)}`
const request = httpFetch(requestUrl).promise

return request.then(({ statusCode, body }) => {
const rawData = wbdCrypto.decodeData(body)
const data = rawData.data
if (statusCode !== 200 || rawData.code != 200 || !data.musiclist) return this.getList(id, page, retryNum)

const total = parseInt(data.total)
const list = this.filterData(data.musiclist)

return {
total,
list,
Expand Down
18 changes: 9 additions & 9 deletions src/renderer/utils/musicSdk/kw/lyric.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { httpFetch } from '../../request'
import { decodeLyric, lrcTools } from './util'
import lyricTools from './utils/lrc'
import { decodeName } from '../../index'

/*
Expand Down Expand Up @@ -198,7 +198,7 @@ export default {
time,
text,
})
} else if (lrcTools.rxps.tagLine.test(line)) {
} else if (lyricTools.rxps.tagLine.test(line)) {
tags.push(line)
}
}
Expand All @@ -212,16 +212,16 @@ export default {
// const requestObj = httpFetch(`http://newlyric.kuwo.cn/newlyric.lrc?${buildParams(musicInfo.songmid, isGetLyricx)}`)
// requestObj.promise = requestObj.promise.then(({ statusCode, body, raw }) => {
// if (statusCode != 200) return Promise.reject(new Error(JSON.stringify(body)))
// return decodeLyric({ lrcBase64: raw.toString('base64'), isGetLyricx }).then(base64Data => {
// return lyricTools.decodeLyric({ lrcBase64: raw.toString('base64'), isGetLyricx }).then(base64Data => {
// let lrcInfo
// console.log(Buffer.from(base64Data, 'base64').toString())
// try {
// lrcInfo = this.parseLrc(Buffer.from(base64Data, 'base64').toString())
// } catch {
// return Promise.reject(new Error('Get lyric failed'))
// }
// if (lrcInfo.tlyric) lrcInfo.tlyric = lrcInfo.tlyric.replace(lrcTools.rxps.wordTimeAll, '')
// lrcInfo.lxlyric = lrcTools.parse(lrcInfo.lyric)
// if (lrcInfo.tlyric) lrcInfo.tlyric = lrcInfo.tlyric.replace(lyricTools.rxps.wordTimeAll, '')
// lrcInfo.lxlyric = lyricTools.parse(lrcInfo.lyric)
// // console.log(lrcInfo.lyric)
// // console.log(lrcInfo.tlyric)
// // console.log(lrcInfo.lxlyric)
Expand All @@ -235,7 +235,7 @@ export default {
const requestObj = httpFetch(`http://newlyric.kuwo.cn/newlyric.lrc?${buildParams(musicInfo.songmid, isGetLyricx)}`)
requestObj.promise = requestObj.promise.then(({ statusCode, body, raw }) => {
if (statusCode != 200) return Promise.reject(new Error(JSON.stringify(body)))
return decodeLyric({ lrcBase64: raw.toString('base64'), isGetLyricx }).then(base64Data => {
return lyricTools.decodeLyric({ lrcBase64: raw.toString('base64'), isGetLyricx }).then(base64Data => {
// let lrcInfo
// try {
// lrcInfo = this.parseLrc(Buffer.from(base64Data, 'base64').toString())
Expand All @@ -250,13 +250,13 @@ export default {
return Promise.reject(new Error('Get lyric failed'))
}
// console.log(lrcInfo)
if (lrcInfo.tlyric) lrcInfo.tlyric = lrcInfo.tlyric.replace(lrcTools.rxps.wordTimeAll, '')
if (lrcInfo.tlyric) lrcInfo.tlyric = lrcInfo.tlyric.replace(lyricTools.rxps.wordTimeAll, '')
try {
lrcInfo.lxlyric = lrcTools.parse(lrcInfo.lyric)
lrcInfo.lxlyric = lyricTools.parse(lrcInfo.lyric)
} catch {
lrcInfo.lxlyric = ''
}
lrcInfo.lyric = lrcInfo.lyric.replace(lrcTools.rxps.wordTimeAll, '')
lrcInfo.lyric = lrcInfo.lyric.replace(lyricTools.rxps.wordTimeAll, '')
if (!existTimeExp.test(lrcInfo.lyric)) return Promise.reject(new Error('Get lyric failed'))
// console.log(lrcInfo)
return lrcInfo
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/utils/musicSdk/kw/musicSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { httpFetch } from '../../request'
import { formatPlayTime, decodeName } from '../../index'
// import { debug } from '../../utils/env'
import { formatSinger } from './util'
import { formatSinger } from './utils'

export default {
regExps: {
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/utils/musicSdk/kw/songList.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { httpFetch } from '../../request'
import { formatPlayTime, decodeName } from '../../index'
import { formatSinger, objStr2JSON } from './util'
import { formatSinger, objStr2JSON } from './utils'
import album from './album'

export default {
Expand Down
48 changes: 48 additions & 0 deletions src/renderer/utils/musicSdk/kw/utils/crypto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { createCipheriv, createDecipheriv, createHash } from 'crypto'

const createAesEncrypt = (buffer, mode, key, iv) => {
const cipher = createCipheriv(mode, key, iv)
return Buffer.concat([cipher.update(buffer), cipher.final()])
}

const createAesDecrypt = (buffer, mode, key, iv) => {
const cipher = createDecipheriv(mode, key, iv)
return Buffer.concat([cipher.update(buffer), cipher.final()])
}

const createMD5 = str => createHash('md5').update(str).digest('hex')

const strToUint8Array = str => {
const length = Math.floor(str.length / 2)
const bArr = new Uint8Array(length)
for (let i = 0; i < length; i++) {
const i2 = i * 2
bArr[i] = parseInt(str.substring(i2, i2 + 2), 16)
}
return bArr
}

export const wbdCrypto = {
aesMode: 'aes-128-ecb',
aesKey: strToUint8Array('7057273DC7FA29BF39442D72DD5E8CE4'),
aesIv: '',
appId: 'y67sprxhhpws',
decodeData(base64Result) {
const data = Buffer.from(decodeURIComponent(base64Result), 'base64')
return JSON.parse(createAesDecrypt(data, this.aesMode, this.aesKey, this.aesIv).toString())
},
createSign(data, time) {
const str = `${this.appId}${data}${time}`
return createMD5(str).toUpperCase()
},
buildParam(jsonData) {
const data = Buffer.from(JSON.stringify(jsonData))
const time = Date.now()

const encodeData = createAesEncrypt(data, this.aesMode, this.aesKey, this.aesIv).toString('base64')
const sign = this.createSign(encodeData, time)

return `data=${encodeURIComponent(encodeData)}&time=${time}&appId=${this.appId}&sign=${sign}`
},
}

73 changes: 73 additions & 0 deletions src/renderer/utils/musicSdk/kw/utils/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
export const objStr2JSON = str => JSON.parse(str.replace(/('(?=(,\s*')))|('(?=:))|((?<=([:,]\s*))')|((?<={)')|('(?=}))/g, '"'))

export const formatSinger = rawData => rawData.replace(/&/g, '、')

export const matchToken = headers => {
try {
return headers['set-cookie'][0].match(/kw_token=(\w+)/)[1]
} catch (err) {
return null
}
}

// const kw_token = {
// token: null,
// isGetingToken: false,
// }

// export const getToken = (retryNum = 0) => new Promise((resolve, reject) => {
// if (retryNum > 2) return Promise.reject(new Error('try max num'))

// if (kw_token.isGetingToken) return wait(1000).then(() => getToken(retryNum).then(token => resolve(token)))
// if (kw_token.token) return resolve(kw_token.token)
// kw_token.isGetingToken = true
// httpGet('http://www.kuwo.cn/', (err, resp) => {
// kw_token.isGetingToken = false
// if (err) return getToken(++retryNum)
// if (resp.statusCode != 200) return reject(new Error('获取失败'))
// const token = kw_token.token = matchToken(resp.headers)
// resolve(token)
// })
// })

// export const tokenRequest = async(url, options = {}) => {
// let token = kw_token.token
// if (!token) token = await getToken()
// if (!options.headers) {
// options.headers = {
// Referer: 'http://www.kuwo.cn/',
// csrf: token,
// cookie: 'kw_token=' + token,
// }
// }
// const requestObj = httpFetch(url, options)
// requestObj.promise = requestObj.promise.then(resp => {
// // console.log(resp)
// if (resp.statusCode == 200) {
// kw_token.token = matchToken(resp.headers)
// }
// return resp
// })
// return requestObj
// }

// const translationMap = {
// "{'": '{"',
// "'}\n": '"}',
// "'}": '"}',
// "':'": '":"',
// "','": '","',
// "':{'": '":{"',
// "':['": '":["',
// "'}],'": '"}],"',
// "':[{'": '":[{"',
// "'},'": '"},"',
// "'},{'": '"},{"',
// "':[],'": '":[],"',
// "':{},'": '":{},"',
// "'}]}": '"}]}',
// }

// export const objStr2JSON = str => {
// return JSON.parse(str.replace(/(^{'|'}\n$|'}$|':'|','|':\[{'|'}\],'|':{'|'},'|'},{'|':\['|':\[\],'|':{},'|'}]})/g, s => translationMap[s]))
// }
Loading