增加kg专辑
This commit is contained in:
parent
b3dc8214e0
commit
4cb3ec9086
63
src/renderer/utils/musicSdk/kg/album.js
Normal file
63
src/renderer/utils/musicSdk/kg/album.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { getMusicInfosByList } from './musicInfo'
|
||||||
|
import { createHttpFetch } from './util'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
/**
|
||||||
|
* 通过AlbumId获取专辑信息
|
||||||
|
* @param {*} id
|
||||||
|
*/
|
||||||
|
async getAlbumInfo(id) {
|
||||||
|
const albumInfoRequest = await createHttpFetch('http://kmrserviceretry.kugou.com/container/v1/album?dfid=1tT5He3kxrNC4D29ad1MMb6F&mid=22945702112173152889429073101964063697&userid=0&appid=1005&clientver=11589', {
|
||||||
|
method: 'POST',
|
||||||
|
body: {
|
||||||
|
appid: 1005,
|
||||||
|
clienttime: 1681833686,
|
||||||
|
clientver: 11589,
|
||||||
|
data: [{ album_id: id }],
|
||||||
|
fields: 'language,grade_count,intro,mix_intro,heat,category,sizable_cover,cover,album_name,type,quality,publish_company,grade,special_tag,author_name,publish_date,language_id,album_id,exclusive,is_publish,trans_param,authors,album_tag',
|
||||||
|
isBuy: 0,
|
||||||
|
key: 'e6f3306ff7e2afb494e89fbbda0becbf',
|
||||||
|
mid: '22945702112173152889429073101964063697',
|
||||||
|
show_album_tag: 0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if (!albumInfoRequest) return Promise.reject(new Error('get album info failed.'))
|
||||||
|
const albumInfo = albumInfoRequest[0]
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: albumInfo.album_name,
|
||||||
|
image: albumInfo.sizable_cover.replace('{size}', 240),
|
||||||
|
desc: albumInfo.intro,
|
||||||
|
authorName: albumInfo.author_name,
|
||||||
|
// play_count: this.formatPlayCount(info.count),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 通过AlbumId获取专辑
|
||||||
|
* @param {*} id
|
||||||
|
* @param {*} page
|
||||||
|
*/
|
||||||
|
async getAlbumDetail(id, page = 1, limit = 200) {
|
||||||
|
const info = await this.getAlbumInfo(id)
|
||||||
|
|
||||||
|
const albumList = await createHttpFetch(`http://mobiles.kugou.com/api/v3/album/song?version=9108&albumid=${id}&plat=0&pagesize=${limit}&area_code=0&page=${page}&with_res_tag=0`)
|
||||||
|
if (!albumList.info) return Promise.reject(new Error('Get album list failed.'))
|
||||||
|
|
||||||
|
let result = await getMusicInfosByList(albumList.info)
|
||||||
|
|
||||||
|
return {
|
||||||
|
list: result || [],
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
total: albumList.total,
|
||||||
|
source: 'kg',
|
||||||
|
info: {
|
||||||
|
name: info.name,
|
||||||
|
img: info.image,
|
||||||
|
desc: info.desc,
|
||||||
|
author: info.authorName,
|
||||||
|
// play_count: this.formatPlayCount(info.count),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
@ -1,12 +1,5 @@
|
|||||||
import { httpFetch } from '../../request'
|
|
||||||
import { decodeName, formatPlayTime, sizeFormate } from '../../index'
|
import { decodeName, formatPlayTime, sizeFormate } from '../../index'
|
||||||
import { signatureParams } from './util'
|
import { signatureParams, createHttpFetch } from './util'
|
||||||
// import { debug } from '../../utils/env'
|
|
||||||
|
|
||||||
// const searchParams = (params, keyword) => {
|
|
||||||
// let signature = signatureParams(params.replace('{keyword}', keyword))
|
|
||||||
// return `${params.replace('{keyword}', encodeURIComponent(keyword))}&signature=${signature}`
|
|
||||||
// }
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
limit: 30,
|
limit: 30,
|
||||||
@ -15,8 +8,8 @@ export default {
|
|||||||
allPage: 1,
|
allPage: 1,
|
||||||
musicSearch(str, page, limit) {
|
musicSearch(str, page, limit) {
|
||||||
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 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}`)
|
const searchRequest = createHttpFetch(`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)
|
return searchRequest.then(body => body)
|
||||||
},
|
},
|
||||||
filterSongData(rawData) {
|
filterSongData(rawData) {
|
||||||
let ids = new Set()
|
let ids = new Set()
|
||||||
@ -85,28 +78,27 @@ export default {
|
|||||||
|
|
||||||
return list
|
return list
|
||||||
},
|
},
|
||||||
search(str, page = 1, limit, retryNum = 0) {
|
async search(str, page = 1, limit, retryNum = 0) {
|
||||||
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
|
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
|
||||||
if (limit == null) limit = this.limit
|
if (limit == null) limit = this.limit
|
||||||
|
|
||||||
// http://newlyric.kuwo.cn/newlyric.lrc?62355680
|
// http://newlyric.kuwo.cn/newlyric.lrc?62355680
|
||||||
return this.musicSearch(str, page, limit).then(result => {
|
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)
|
||||||
if (!result || result.error_code !== 0) return this.search(str, page, limit, retryNum)
|
const searchResult = await createHttpFetch(`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}`)
|
||||||
// console.log(result)
|
|
||||||
let list = this.filterSongData(result.data.lists)
|
|
||||||
|
|
||||||
if (list == null) return this.search(str, page, limit, retryNum)
|
let list = this.filterSongData(searchResult.lists)
|
||||||
|
if (!list) return this.search(str, page, limit, retryNum)
|
||||||
|
|
||||||
this.total = result.data.total
|
this.total = searchResult.total
|
||||||
this.page = page
|
this.page = page
|
||||||
this.allPage = Math.ceil(this.total / limit)
|
this.allPage = Math.ceil(this.total / limit)
|
||||||
|
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
list,
|
list,
|
||||||
allPage: this.allPage,
|
allPage: this.allPage,
|
||||||
limit,
|
limit,
|
||||||
total: this.total,
|
total: this.total,
|
||||||
source: 'kg',
|
source: 'kg',
|
||||||
})
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { httpFetch } from '../../request'
|
import { httpFetch } from '../../../request'
|
||||||
import { decodeName, formatPlayTime, sizeFormate, dateFormat } from '../../index'
|
import { decodeName, formatPlayTime, sizeFormate, dateFormat } from '../../../index'
|
||||||
import infSign from './vendors/infSign.min'
|
import infSign from '../vendors/infSign.min'
|
||||||
import { signatureParams } from './util'
|
import { signatureParams } from '../util'
|
||||||
|
|
||||||
const handleSignature = (id, page, limit) => new Promise((resolve, reject) => {
|
const handleSignature = (id, page, limit) => new Promise((resolve, reject) => {
|
||||||
infSign({ appid: 1058, type: 0, module: 'playlist', page, pagesize: limit, specialid: id }, null, {
|
infSign({ appid: 1058, type: 0, module: 'playlist', page, pagesize: limit, specialid: id }, null, {
|
||||||
@ -2,6 +2,7 @@ import { httpFetch } from '../../request'
|
|||||||
import { decodeName, formatPlayTime, sizeFormate, dateFormat } from '../../index'
|
import { decodeName, formatPlayTime, sizeFormate, dateFormat } from '../../index'
|
||||||
import { signatureParams, createHttpFetch } from './util'
|
import { signatureParams, createHttpFetch } from './util'
|
||||||
import { getMusicInfosByList } from './musicInfo'
|
import { getMusicInfosByList } from './musicInfo'
|
||||||
|
import album from './album'
|
||||||
|
|
||||||
// import infSign from './vendors/infSign.min'
|
// import infSign from './vendors/infSign.min'
|
||||||
// const handleSignature = (id, page, limit) => new Promise((resolve, reject) => {
|
// const handleSignature = (id, page, limit) => new Promise((resolve, reject) => {
|
||||||
@ -55,6 +56,39 @@ export default {
|
|||||||
listDetailLink: /^.+\/(\d+)\.html(?:\?.*|&.*$|#.*$|$)/,
|
listDetailLink: /^.+\/(\d+)\.html(?:\?.*|&.*$|#.*$|$)/,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取歌曲列表内的音乐
|
||||||
|
* @param {*} id
|
||||||
|
* @param {*} page
|
||||||
|
*/
|
||||||
|
async getListDetail(id, page) {
|
||||||
|
id = id.toString()
|
||||||
|
|
||||||
|
if (id.includes('special/single/')) id = id.replace(this.regExps.listDetailLink, '$1')
|
||||||
|
// fix https://www.kugou.com/songlist/xxx/?uid=xxx&chl=qq_client&cover=http%3A%2F%2Fimge.kugou.com%xxx.jpg&iszlist=1
|
||||||
|
if (/https?:/.test(id)) {
|
||||||
|
if (id.includes('#')) id = id.replace(/#.*$/, '')
|
||||||
|
if (id.includes('global_collection_id')) return this.getUserListDetailByCollectionId(id.replace(/^.*?global_collection_id=(\w+)(?:&.*$|#.*$|$)/, '$1'), page)
|
||||||
|
if (id.includes('chain=')) return this.getUserListDetail3(id.replace(/^.*?chain=(\w+)(?:&.*$|#.*$|$)/, '$1'), page)
|
||||||
|
if (id.includes('.html')) {
|
||||||
|
if (id.includes('zlist.html')) {
|
||||||
|
id = id.replace(/^(.*)zlist\.html/, 'https://m3ws.kugou.com/zlist/list')
|
||||||
|
if (id.includes('pagesize')) {
|
||||||
|
id = id.replace('pagesize=30', 'pagesize=' + this.listDetailLimit).replace('page=1', 'page=' + page)
|
||||||
|
} else {
|
||||||
|
id += `&pagesize=${this.listDetailLimit}&page=${page}`
|
||||||
|
}
|
||||||
|
} else if (!id.includes('song.html')) return this.getUserListDetail3(id.replace(/.+\/(\w+).html(?:\?.*|&.*$|#.*$|$)/, '$1'), page)
|
||||||
|
}
|
||||||
|
return this.getUserListDetail(id.replace(/^.*?http/, 'http'), page)
|
||||||
|
}
|
||||||
|
if (/^\d+$/.test(id)) return this.getUserListDetailByCode(id, page)
|
||||||
|
if (id.startsWith('gid_')) return this.getUserListDetailByCollectionId(id.replace('gid_', ''), page)
|
||||||
|
if (id.startsWith('id_')) return this.getUserListDetailBySpecialId(id.replace('id_', ''), page)
|
||||||
|
|
||||||
|
return new Error('Failed.')
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取SpecialId歌单
|
* 获取SpecialId歌单
|
||||||
* @param {*} id
|
* @param {*} id
|
||||||
@ -67,7 +101,6 @@ export default {
|
|||||||
let listInfo = body.match(this.regExps.listInfo)
|
let listInfo = body.match(this.regExps.listInfo)
|
||||||
if (!listData) return this.getListDetailBySpecialId(id, page, ++tryNum)
|
if (!listData) return this.getListDetailBySpecialId(id, page, ++tryNum)
|
||||||
let list = await getMusicInfosByList(JSON.parse(listData[1]))
|
let list = await getMusicInfosByList(JSON.parse(listData[1]))
|
||||||
// listData = this.filterData(JSON.parse(listData[1]))
|
|
||||||
let name
|
let name
|
||||||
let pic
|
let pic
|
||||||
if (listInfo) {
|
if (listInfo) {
|
||||||
@ -293,7 +326,7 @@ export default {
|
|||||||
// },
|
// },
|
||||||
// }).then(body => {
|
// }).then(body => {
|
||||||
// if (!body.info) return Promise.reject(new Error('Get list failed.'))
|
// if (!body.info) return Promise.reject(new Error('Get list failed.'))
|
||||||
// const songList = this.filterCollectionIdList(body.info)
|
// const songList = this.filterListByCollectionId(body.info)
|
||||||
|
|
||||||
// return {
|
// return {
|
||||||
// list: songList || [],
|
// list: songList || [],
|
||||||
@ -326,7 +359,7 @@ export default {
|
|||||||
},
|
},
|
||||||
}).then(body => {
|
}).then(body => {
|
||||||
if (!body.info) return Promise.reject(new Error('Get list failed.'))
|
if (!body.info) return Promise.reject(new Error('Get list failed.'))
|
||||||
const songList = this.filterCollectionIdList(body.info)
|
const songList = this.filterListByCollectionId(body.info)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
list: songList || [],
|
list: songList || [],
|
||||||
@ -348,7 +381,7 @@ export default {
|
|||||||
* 过滤GlobalSpecialId歌单数据
|
* 过滤GlobalSpecialId歌单数据
|
||||||
* @param {*} rawData
|
* @param {*} rawData
|
||||||
*/
|
*/
|
||||||
filterCollectionIdList(rawData) {
|
filterListByCollectionId(rawData) {
|
||||||
let ids = new Set()
|
let ids = new Set()
|
||||||
let list = []
|
let list = []
|
||||||
rawData.forEach(item => {
|
rawData.forEach(item => {
|
||||||
@ -436,7 +469,7 @@ export default {
|
|||||||
if (!codeInfo.global_collection_id) return this.getUserListDetailBySpecialId(codeInfo.id, page)
|
if (!codeInfo.global_collection_id) return this.getUserListDetailBySpecialId(codeInfo.id, page)
|
||||||
break
|
break
|
||||||
case 3:
|
case 3:
|
||||||
return this.getListDetailByAlbumId(codeInfo.id, page)
|
return album.getAlbumDetail(codeInfo.id, page)
|
||||||
}
|
}
|
||||||
if (codeInfo.global_collection_id) return this.getUserListDetailByCollectionId(codeInfo.global_collection_id, page)
|
if (codeInfo.global_collection_id) return this.getUserListDetailByCollectionId(codeInfo.global_collection_id, page)
|
||||||
|
|
||||||
@ -658,19 +691,6 @@ export default {
|
|||||||
|
|
||||||
async getUserListDetail(link, page, retryNum = 0) {
|
async getUserListDetail(link, page, retryNum = 0) {
|
||||||
if (retryNum > 3) return Promise.reject(new Error('link try max num'))
|
if (retryNum > 3) return Promise.reject(new Error('link try max num'))
|
||||||
if (link.includes('#')) link = link.replace(/#.*$/, '')
|
|
||||||
if (link.includes('global_collection_id')) return this.getUserListDetailByCollectionId(link.replace(/^.*?global_collection_id=(\w+)(?:&.*$|#.*$|$)/, '$1'), page)
|
|
||||||
if (link.includes('chain=')) return this.getUserListDetail3(link.replace(/^.*?chain=(\w+)(?:&.*$|#.*$|$)/, '$1'), page)
|
|
||||||
if (link.includes('.html')) {
|
|
||||||
if (link.includes('zlist.html')) {
|
|
||||||
link = link.replace(/^(.*)zlist\.html/, 'https://m3ws.kugou.com/zlist/list')
|
|
||||||
if (link.includes('pagesize')) {
|
|
||||||
link = link.replace('pagesize=30', 'pagesize=' + this.listDetailLimit).replace('page=1', 'page=' + page)
|
|
||||||
} else {
|
|
||||||
link += `&pagesize=${this.listDetailLimit}&page=${page}`
|
|
||||||
}
|
|
||||||
} else if (!link.includes('song.html')) return this.getUserListDetail3(link.replace(/.+\/(\w+).html(?:\?.*|&.*$|#.*$|$)/, '$1'), page)
|
|
||||||
}
|
|
||||||
|
|
||||||
const requestLink = httpFetch(link, {
|
const requestLink = httpFetch(link, {
|
||||||
headers: {
|
headers: {
|
||||||
@ -684,9 +704,9 @@ export default {
|
|||||||
if (statusCode > 400) return this.getUserListDetail(link, page, ++retryNum)
|
if (statusCode > 400) return this.getUserListDetail(link, page, ++retryNum)
|
||||||
if (typeof body == 'string') {
|
if (typeof body == 'string') {
|
||||||
if (body.includes('"global_collection_id":')) return this.getUserListDetailByCollectionId(body.replace(/^[\s\S]+?"global_collection_id":"(\w+)"[\s\S]+?$/, '$1'), page)
|
if (body.includes('"global_collection_id":')) return this.getUserListDetailByCollectionId(body.replace(/^[\s\S]+?"global_collection_id":"(\w+)"[\s\S]+?$/, '$1'), page)
|
||||||
if (body.includes('"albumid":')) return this.getListDetailByAlbumId(body.replace(/^[\s\S]+?"albumid":(\w+)[\s\S]+?$/, '$1'), page)
|
if (body.includes('"albumid":')) return album.getAlbumDetail(body.replace(/^[\s\S]+?"albumid":(\w+)[\s\S]+?$/, '$1'), page)
|
||||||
if (body.includes('"album_id":') && link.includes('album/info')) return this.getListDetailByAlbumId(body.replace(/^[\s\S]+?"album_id":(\w+)[\s\S]+?$/, '$1'), page)
|
if (body.includes('"album_id":') && link.includes('album/info')) return album.getAlbumDetail(body.replace(/^[\s\S]+?"album_id":(\w+)[\s\S]+?$/, '$1'), page)
|
||||||
if (body.includes('list_id = "') && link.includes('album/info')) return this.getListDetailByAlbumId(body.replace(/^[\s\S]+?list_id = "(\w+)"[\s\S]+?$/, '$1'), page)
|
if (body.includes('list_id = "') && link.includes('album/info')) return album.getAlbumDetail(body.replace(/^[\s\S]+?list_id = "(\w+)"[\s\S]+?$/, '$1'), page)
|
||||||
}
|
}
|
||||||
if (location) {
|
if (location) {
|
||||||
// 概念版分享链接 https://t1.kugou.com/xxx
|
// 概念版分享链接 https://t1.kugou.com/xxx
|
||||||
@ -710,79 +730,6 @@ export default {
|
|||||||
return this.getUserListDetailByLink(body, link)
|
return this.getUserListDetailByLink(body, link)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取歌曲列表内的音乐
|
|
||||||
* @param {*} id
|
|
||||||
* @param {*} page
|
|
||||||
*/
|
|
||||||
async getListDetail(id, page) {
|
|
||||||
id = id.toString()
|
|
||||||
|
|
||||||
if (id.includes('special/single/')) id = id.replace(this.regExps.listDetailLink, '$1')
|
|
||||||
// fix https://www.kugou.com/songlist/xxx/?uid=xxx&chl=qq_client&cover=http%3A%2F%2Fimge.kugou.com%xxx.jpg&iszlist=1
|
|
||||||
if (/https?:/.test(id)) return this.getUserListDetail(id.replace(/^.*?http/, 'http'), page)
|
|
||||||
if (/^\d+$/.test(id)) return this.getUserListDetailByCode(id, page)
|
|
||||||
if (id.startsWith('gid_')) return this.getUserListDetailByCollectionId(id.replace('gid_', ''), page)
|
|
||||||
if (id.startsWith('id_')) return this.getUserListDetailBySpecialId(id.replace('id_', ''), page)
|
|
||||||
|
|
||||||
return new Error('Failed.')
|
|
||||||
},
|
|
||||||
|
|
||||||
filterData(rawList) {
|
|
||||||
// console.log(rawList)
|
|
||||||
return rawList.map(item => {
|
|
||||||
const types = []
|
|
||||||
const _types = {}
|
|
||||||
if (item.filesize !== 0) {
|
|
||||||
let size = sizeFormate(item.filesize)
|
|
||||||
types.push({ type: '128k', size, hash: item.hash })
|
|
||||||
_types['128k'] = {
|
|
||||||
size,
|
|
||||||
hash: item.hash,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (item.filesize_320 !== 0) {
|
|
||||||
let size = sizeFormate(item.filesize_320)
|
|
||||||
types.push({ type: '320k', size, hash: item.hash_320 })
|
|
||||||
_types['320k'] = {
|
|
||||||
size,
|
|
||||||
hash: item.hash_320,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (item.filesize_ape !== 0) {
|
|
||||||
let size = sizeFormate(item.filesize_ape)
|
|
||||||
types.push({ type: 'ape', size, hash: item.hash_ape })
|
|
||||||
_types.ape = {
|
|
||||||
size,
|
|
||||||
hash: item.hash_ape,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (item.filesize_flac !== 0) {
|
|
||||||
let size = sizeFormate(item.filesize_flac)
|
|
||||||
types.push({ type: 'flac', size, hash: item.hash_flac })
|
|
||||||
_types.flac = {
|
|
||||||
size,
|
|
||||||
hash: item.hash_flac,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
singer: decodeName(item.singername),
|
|
||||||
name: decodeName(item.songname),
|
|
||||||
albumName: decodeName(item.album_name),
|
|
||||||
albumId: item.album_id,
|
|
||||||
songmid: item.audio_id,
|
|
||||||
source: 'kg',
|
|
||||||
interval: formatPlayTime(item.duration / 1000),
|
|
||||||
img: null,
|
|
||||||
lrc: null,
|
|
||||||
hash: item.hash,
|
|
||||||
types,
|
|
||||||
_types,
|
|
||||||
typeUrl: {},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取列表信息
|
// 获取列表信息
|
||||||
getListInfo(tagId, tryNum = 0) {
|
getListInfo(tagId, tryNum = 0) {
|
||||||
if (this._requestObj_listInfo) this._requestObj_listInfo.cancelHttp()
|
if (this._requestObj_listInfo) this._requestObj_listInfo.cancelHttp()
|
||||||
|
|||||||
@ -35,7 +35,7 @@ export const signatureParams = (params, apiver = 9) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建一个Http请求
|
* 创建一个适用于KG的Http请求
|
||||||
* @param {*} url
|
* @param {*} url
|
||||||
* @param {*} options
|
* @param {*} options
|
||||||
* @param {*} retryNum
|
* @param {*} retryNum
|
||||||
|
|||||||
@ -1,6 +1,107 @@
|
|||||||
import { httpFetch } from '../../request'
|
import { httpFetch } from '../../request'
|
||||||
import { getMusicInfo } from './musicInfo'
|
import { getMusicInfo } from './musicInfo'
|
||||||
import { decrypt } from './mrc'
|
|
||||||
|
// const key = 'karakal@123Qcomyidongtiantianhaoting'
|
||||||
|
const DELTA = 2654435769n
|
||||||
|
const MIN_LENGTH = 32
|
||||||
|
// const SPECIAL_CHAR = '0'
|
||||||
|
const keyArr = [
|
||||||
|
27303562373562475n,
|
||||||
|
18014862372307051n,
|
||||||
|
22799692160172081n,
|
||||||
|
34058940340699235n,
|
||||||
|
30962724186095721n,
|
||||||
|
27303523720101991n,
|
||||||
|
27303523720101998n,
|
||||||
|
31244139033526382n,
|
||||||
|
28992395054481524n,
|
||||||
|
]
|
||||||
|
|
||||||
|
const teaDecrypt = (data, key) => {
|
||||||
|
const length = data.length
|
||||||
|
const lengthBitint = BigInt(length)
|
||||||
|
if (length >= 1) {
|
||||||
|
// let j = data[data.length - 1];
|
||||||
|
let j2 = data[0]
|
||||||
|
let j3 = toLong((6n + (52n / lengthBitint)) * DELTA)
|
||||||
|
while (true) {
|
||||||
|
let j4 = j3
|
||||||
|
if (j4 == 0n) break
|
||||||
|
let j5 = toLong(3n & toLong(j4 >> 2n))
|
||||||
|
let j6 = lengthBitint
|
||||||
|
while (true) {
|
||||||
|
j6--
|
||||||
|
if (j6 > 0n) {
|
||||||
|
let j7 = data[(j6 - 1n)]
|
||||||
|
let i = j6
|
||||||
|
j2 = toLong(data[i] - (toLong(toLong(j2 ^ j4) + toLong(j7 ^ key[toLong(toLong(3n & j6) ^ j5)])) ^ toLong(toLong(toLong(j7 >> 5n) ^ toLong(j2 << 2n)) + toLong(toLong(j2 >> 3n) ^ toLong(j7 << 4n)))))
|
||||||
|
data[i] = j2
|
||||||
|
} else break
|
||||||
|
}
|
||||||
|
let j8 = data[lengthBitint - 1n]
|
||||||
|
j2 = toLong(data[0n] - toLong(toLong(toLong(key[toLong(toLong(j6 & 3n) ^ j5)] ^ j8) + toLong(j2 ^ j4)) ^ toLong(toLong(toLong(j8 >> 5n) ^ toLong(j2 << 2n)) + toLong(toLong(j2 >> 3n) ^ toLong(j8 << 4n)))))
|
||||||
|
data[0] = j2
|
||||||
|
j3 = toLong(j4 - DELTA)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
const longArrToString = (data) => {
|
||||||
|
const arrayList = []
|
||||||
|
for (const j of data) arrayList.push(longToBytes(j).toString('utf16le'))
|
||||||
|
return arrayList.join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/29132118
|
||||||
|
const longToBytes = (l) => {
|
||||||
|
const result = Buffer.alloc(8)
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
result[i] = parseInt(l & 0xFFn)
|
||||||
|
l >>= 8n
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const toBigintArray = (data) => {
|
||||||
|
const length = Math.floor(data.length / 16)
|
||||||
|
const jArr = Array(length)
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
jArr[i] = toLong(data.substring(i * 16, (i * 16) + 16))
|
||||||
|
}
|
||||||
|
return jArr
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/lyswhut/lx-music-desktop/issues/445#issuecomment-1139338682
|
||||||
|
const MAX = 9223372036854775807n
|
||||||
|
const MIN = -9223372036854775808n
|
||||||
|
const toLong = str => {
|
||||||
|
const num = typeof str == 'string' ? BigInt('0x' + str) : str
|
||||||
|
if (num > MAX) return toLong(num - (1n << 64n))
|
||||||
|
else if (num < MIN) return toLong(num + (1n << 64n))
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
|
||||||
|
const mrcDecrypt = (data) => {
|
||||||
|
// console.log(data.length)
|
||||||
|
// -3551594764563790630
|
||||||
|
// console.log(toLongArrayFromArr(Buffer.from(key)))
|
||||||
|
// console.log(teaDecrypt(toBigintArray(data), keyArr))
|
||||||
|
// console.log(longArrToString(teaDecrypt(toBigintArray(data), keyArr)))
|
||||||
|
// console.log(toByteArray(teaDecrypt(toBigintArray(data), keyArr)))
|
||||||
|
return (data == null || data.length < MIN_LENGTH)
|
||||||
|
? data
|
||||||
|
: longArrToString(teaDecrypt(toBigintArray(data), keyArr))
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log(14895149309145760986n - )
|
||||||
|
// console.log(toLong('14895149309145760986'))
|
||||||
|
// console.log(mrcDecrypt(str))
|
||||||
|
// console.log(mrcDecrypt(str))
|
||||||
|
// console.log(toByteArray([6048138644744000495n]))
|
||||||
|
// console.log(toByteArray([16325999628386395n]))
|
||||||
|
// console.log(toLong(90994076459972177136n))
|
||||||
|
|
||||||
const mrcTools = {
|
const mrcTools = {
|
||||||
rxps: {
|
rxps: {
|
||||||
@ -63,7 +164,7 @@ const mrcTools = {
|
|||||||
},
|
},
|
||||||
getMrc(url) {
|
getMrc(url) {
|
||||||
return this.getText(url).then(text => {
|
return this.getText(url).then(text => {
|
||||||
return this.parseLyric(decrypt(text))
|
return this.parseLyric(mrcDecrypt(text))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getLrc(url) {
|
getLrc(url) {
|
||||||
|
|||||||
@ -1,104 +0,0 @@
|
|||||||
|
|
||||||
// const key = 'karakal@123Qcomyidongtiantianhaoting'
|
|
||||||
const DELTA = 2654435769n
|
|
||||||
const MIN_LENGTH = 32
|
|
||||||
// const SPECIAL_CHAR = '0'
|
|
||||||
const keyArr = [
|
|
||||||
27303562373562475n,
|
|
||||||
18014862372307051n,
|
|
||||||
22799692160172081n,
|
|
||||||
34058940340699235n,
|
|
||||||
30962724186095721n,
|
|
||||||
27303523720101991n,
|
|
||||||
27303523720101998n,
|
|
||||||
31244139033526382n,
|
|
||||||
28992395054481524n,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
const teaDecrypt = (data, key) => {
|
|
||||||
const length = data.length
|
|
||||||
const lengthBitint = BigInt(length)
|
|
||||||
if (length >= 1) {
|
|
||||||
// let j = data[data.length - 1];
|
|
||||||
let j2 = data[0]
|
|
||||||
let j3 = toLong((6n + (52n / lengthBitint)) * DELTA)
|
|
||||||
while (true) {
|
|
||||||
let j4 = j3
|
|
||||||
if (j4 == 0n) break
|
|
||||||
let j5 = toLong(3n & toLong(j4 >> 2n))
|
|
||||||
let j6 = lengthBitint
|
|
||||||
while (true) {
|
|
||||||
j6--
|
|
||||||
if (j6 > 0n) {
|
|
||||||
let j7 = data[(j6 - 1n)]
|
|
||||||
let i = j6
|
|
||||||
j2 = toLong(data[i] - (toLong(toLong(j2 ^ j4) + toLong(j7 ^ key[toLong(toLong(3n & j6) ^ j5)])) ^ toLong(toLong(toLong(j7 >> 5n) ^ toLong(j2 << 2n)) + toLong(toLong(j2 >> 3n) ^ toLong(j7 << 4n)))))
|
|
||||||
data[i] = j2
|
|
||||||
} else break
|
|
||||||
}
|
|
||||||
let j8 = data[lengthBitint - 1n]
|
|
||||||
j2 = toLong(data[0n] - toLong(toLong(toLong(key[toLong(toLong(j6 & 3n) ^ j5)] ^ j8) + toLong(j2 ^ j4)) ^ toLong(toLong(toLong(j8 >> 5n) ^ toLong(j2 << 2n)) + toLong(toLong(j2 >> 3n) ^ toLong(j8 << 4n)))))
|
|
||||||
data[0] = j2
|
|
||||||
j3 = toLong(j4 - DELTA)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
const longArrToString = (data) => {
|
|
||||||
const arrayList = []
|
|
||||||
for (const j of data) arrayList.push(longToBytes(j).toString('utf16le'))
|
|
||||||
return arrayList.join('')
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/a/29132118
|
|
||||||
const longToBytes = (l) => {
|
|
||||||
const result = Buffer.alloc(8)
|
|
||||||
for (let i = 0; i < 8; i++) {
|
|
||||||
result[i] = parseInt(l & 0xFFn)
|
|
||||||
l >>= 8n
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const toBigintArray = (data) => {
|
|
||||||
const length = Math.floor(data.length / 16)
|
|
||||||
const jArr = Array(length)
|
|
||||||
for (let i = 0; i < length; i++) {
|
|
||||||
jArr[i] = toLong(data.substring(i * 16, (i * 16) + 16))
|
|
||||||
}
|
|
||||||
return jArr
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/lyswhut/lx-music-desktop/issues/445#issuecomment-1139338682
|
|
||||||
const MAX = 9223372036854775807n
|
|
||||||
const MIN = -9223372036854775808n
|
|
||||||
const toLong = str => {
|
|
||||||
const num = typeof str == 'string' ? BigInt('0x' + str) : str
|
|
||||||
if (num > MAX) return toLong(num - (1n << 64n))
|
|
||||||
else if (num < MIN) return toLong(num + (1n << 64n))
|
|
||||||
return num
|
|
||||||
}
|
|
||||||
|
|
||||||
export const decrypt = (data) => {
|
|
||||||
// console.log(data.length)
|
|
||||||
// -3551594764563790630
|
|
||||||
// console.log(toLongArrayFromArr(Buffer.from(key)))
|
|
||||||
// console.log(teaDecrypt(toBigintArray(data), keyArr))
|
|
||||||
// console.log(longArrToString(teaDecrypt(toBigintArray(data), keyArr)))
|
|
||||||
// console.log(toByteArray(teaDecrypt(toBigintArray(data), keyArr)))
|
|
||||||
return (data == null || data.length < MIN_LENGTH)
|
|
||||||
? data
|
|
||||||
: longArrToString(teaDecrypt(toBigintArray(data), keyArr))
|
|
||||||
}
|
|
||||||
|
|
||||||
// console.log(14895149309145760986n - )
|
|
||||||
// console.log(toLong('14895149309145760986'))
|
|
||||||
// console.log(decrypt(str))
|
|
||||||
// console.log(decrypt(str))
|
|
||||||
// console.log(toByteArray([6048138644744000495n]))
|
|
||||||
// console.log(toByteArray([16325999628386395n]))
|
|
||||||
// console.log(toLong(90994076459972177136n))
|
|
||||||
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { httpFetch } from '../../request'
|
import { httpFetch } from '../../../request'
|
||||||
import { formatPlayTime } from '../../index'
|
import { formatPlayTime } from '../../../index'
|
||||||
// import { sizeFormate } from '../../index'
|
// import { sizeFormate } from '../../index'
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user