diff --git a/src/renderer/components/layout/Toolbar/SearchInput.vue b/src/renderer/components/layout/Toolbar/SearchInput.vue
index 24da7200..ac2ef4e7 100644
--- a/src/renderer/components/layout/Toolbar/SearchInput.vue
+++ b/src/renderer/components/layout/Toolbar/SearchInput.vue
@@ -48,12 +48,12 @@ export default {
const tipSearch = debounce(async() => {
if (searchText.value === '' && prevTempSearchSource) {
tipList.value = []
- music[prevTempSearchSource].tempSearch.cancelTempSearch()
+ music[prevTempSearchSource].tipSearch.cancelTipSearch()
return
}
const { temp_source } = await getSearchSetting()
prevTempSearchSource = temp_source
- music[prevTempSearchSource].tempSearch.search(searchText.value).then(list => {
+ music[prevTempSearchSource].tipSearch.search(searchText.value).then(list => {
tipList.value = list
}).catch(() => {})
}, 50)
diff --git a/src/renderer/utils/index.ts b/src/renderer/utils/index.ts
index 4332dc18..fe4adf76 100644
--- a/src/renderer/utils/index.ts
+++ b/src/renderer/utils/index.ts
@@ -9,10 +9,10 @@ export * from '@common/utils/tools'
* 格式化播放数量
* @param {*} num 数字
*/
-export const formatPlayCount = (num: number): { count: number, lang: string } => {
- if (num > 100000000) return {count: parseInt((num / 10000000).toString()) / 10, lang: 'play_count_billion'}
- if (num > 10000) return {count: parseInt((num / 1000).toString()) / 10, lang: 'play_count_million'}
- return { count: num, lang: 'play_count_none' }
+export const formatPlayCount = (num: number): string => {
+ if (num > 100000000) return `${Math.trunc(num / 10000000) / 10}亿`
+ if (num > 10000) return `${Math.trunc(num / 1000) / 10}万`
+ return String(num)
}
diff --git a/src/renderer/utils/musicSdk/kg/album.js b/src/renderer/utils/musicSdk/kg/album.js
index 2250c08e..1d9642f8 100644
--- a/src/renderer/utils/musicSdk/kg/album.js
+++ b/src/renderer/utils/musicSdk/kg/album.js
@@ -38,13 +38,13 @@ export default {
* @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)
+ const info = await this.getAlbumInfo(id)
+
return {
list: result || [],
page,
diff --git a/src/renderer/utils/musicSdk/kg/index.js b/src/renderer/utils/musicSdk/kg/index.js
index 142dd9b1..5d41846c 100644
--- a/src/renderer/utils/musicSdk/kg/index.js
+++ b/src/renderer/utils/musicSdk/kg/index.js
@@ -6,10 +6,10 @@ import pic from './pic'
import lyric from './lyric'
import hotSearch from './hotSearch'
import comment from './comment'
-import tipSearch from './tipSearch'
+// import tipSearch from './tipSearch'
const kg = {
- tipSearch,
+ // tipSearch,
leaderboard,
songList,
musicSearch,
diff --git a/src/renderer/utils/musicSdk/kg/musicSearch.js b/src/renderer/utils/musicSdk/kg/musicSearch.js
index 2e62267d..ee60a694 100644
--- a/src/renderer/utils/musicSdk/kg/musicSearch.js
+++ b/src/renderer/utils/musicSdk/kg/musicSearch.js
@@ -1,5 +1,6 @@
import { httpFetch } from '../../request'
import { decodeName, formatPlayTime, sizeFormate } from '../../index'
+import { formatSingerName } from '@renderer/utils/musicSdk/utils'
export default {
limit: 30,
@@ -10,80 +11,76 @@ export default {
const searchRequest = httpFetch(`https://songsearch.kugou.com/song_search_v2?keyword=${encodeURIComponent(str)}&page=${page}&pagesize=${limit}&userid=0&clientver=&platform=WebFilter&filter=2&iscorrection=1&privilege_filter=0`)
return searchRequest.promise.then(({ body }) => body)
},
- filterList(raw) {
+ 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(formatSingerName(rawData.Singers, 'name')),
+ 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) {
let ids = new Set()
const list = []
-
- raw.forEach(item => {
- if (ids.has(item.Audioid) || !item.Audioid) return
- ids.add(item.Audioid)
-
- const types = []
- const _types = {}
- if (item.FileSize !== 0) {
- let size = sizeFormate(item.FileSize)
- types.push({ type: '128k', size, hash: item.FileHash })
- _types['128k'] = {
- size,
- hash: item.FileHash,
- }
+ 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))
}
- if (item.HQFileSize !== 0) {
- let size = sizeFormate(item.HQFileSize)
- types.push({ type: '320k', size, hash: item.HQFileHash })
- _types['320k'] = {
- size,
- hash: item.HQFileHash,
- }
- }
- if (item.SQFileSize !== 0) {
- let size = sizeFormate(item.SQFileSize)
- types.push({ type: 'flac', size, hash: item.SQFileHash })
- _types.flac = {
- size,
- hash: item.SQFileHash,
- }
- }
- if (item.ResFileSize !== 0) {
- let size = sizeFormate(item.ResFileSize)
- types.push({ type: 'flac24bit', size, hash: item.ResFileHash })
- _types.flac24bit = {
- size,
- hash: item.ResFileHash,
- }
- }
- list.push({
- singer: decodeName(item.SingerName),
- name: decodeName(item.SongName),
- albumName: decodeName(item.AlbumName),
- albumId: item.AlbumID,
- songmid: item.Audioid,
- source: 'kg',
- interval: formatPlayTime(item.Duration),
- _interval: item.Duration,
- img: null,
- lrc: null,
- otherSource: null,
- hash: item.FileHash,
- types,
- _types,
- typeUrl: {},
- })
})
return list
},
- handleResult(raw) {
- const handleList = []
-
- raw.forEach(item => {
- handleList.push(item)
- if (item.Grp.length === 0) return
- for (const e in item.Grp) {
- handleList.push(e)
- }
- })
- return this.filterList(handleList)
- },
search(str, page = 1, limit, retryNum = 0) {
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
if (limit == null) limit = this.limit
diff --git a/src/renderer/utils/musicSdk/kg/songList.js b/src/renderer/utils/musicSdk/kg/songList.js
index 65dc7f05..f06163dd 100644
--- a/src/renderer/utils/musicSdk/kg/songList.js
+++ b/src/renderer/utils/musicSdk/kg/songList.js
@@ -1,9 +1,17 @@
import { httpFetch } from '../../request'
-import { formatSingerName } from '../utils'
import { decodeName, formatPlayTime, sizeFormate, dateFormat, formatPlayCount } from '../../index'
-import { signatureParams, createHttpFetch } from './util'
-import { getMusicInfosByList } from './musicInfo'
-import album from './album'
+import infSign from './vendors/infSign.min'
+import { signatureParams } from './util'
+
+const handleSignature = (id, page, limit) => new Promise((resolve, reject) => {
+ infSign({ appid: 1058, type: 0, module: 'playlist', page, pagesize: limit, specialid: id }, null, {
+ useH5: !0,
+ isCDN: !0,
+ callback(i) {
+ resolve(i.signature)
+ },
+ })
+})
export default {
_requestObj_tags: null,
@@ -38,59 +46,75 @@ export default {
},
],
cache: new Map(),
- CollectionIdListInfoCache: new Map(),
regExps: {
listData: /global\.data = (\[.+\]);/,
listInfo: /global = {[\s\S]+?name: "(.+)"[\s\S]+?pic: "(.+)"[\s\S]+?};/,
// https://www.kugou.com/yy/special/single/1067062.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.')
+ // async getGlobalSpecialId(specialId) {
+ // return httpFetch(`http://mobilecdnbj.kugou.com/api/v5/special/info?specialid=${specialId}`, {
+ // headers: {
+ // 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; HLK-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Mobile Safari/537.36 EdgA/104.0.1293.70',
+ // },
+ // }).promise.then(({ body }) => {
+ // // console.log(body)
+ // if (!body.data.global_specialid) Promise.reject(new Error('Failed to get global collection id.'))
+ // return body.data.global_specialid
+ // })
+ // },
+ // async getListInfoBySpecialId(special_id, retry = 0) {
+ // if (++retry > 2) throw new Error('failed')
+ // return httpFetch(`https://m.kugou.com/plist/list/${special_id}/?json=true`, {
+ // headers: {
+ // 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; HLK-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Mobile Safari/537.36 EdgA/104.0.1293.70',
+ // },
+ // follow_max: 2,
+ // }).promise.then(({ body }) => {
+ // // console.log(body)
+ // if (!body.info.list) return this.getListInfoBySpecialId(special_id, retry)
+ // let listinfo = body.info.list
+ // return {
+ // listInfo: {
+ // name: listinfo.specialname,
+ // image: listinfo.imgurl.replace('{size}', '150'),
+ // intro: listinfo.intro,
+ // author: listinfo.nickname,
+ // playcount: listinfo.playcount,
+ // total: listinfo.songcount,
+ // },
+ // globalSpecialId: listinfo.global_specialid,
+ // }
+ // })
+ // },
+ // async getSongListDetailByGlobalSpecialId(id, page, limit = 100, retry = 0) {
+ // if (++retry > 2) throw new Error('failed')
+ // console.log(id)
+ // const params = `specialid=0&need_sort=1&module=CloudMusic&clientver=11409&pagesize=${limit}&global_collection_id=${id}&userid=0&page=${page}&type=1&area_code=1&appid=1005`
+ // return httpFetch(`http://pubsongscdn.tx.kugou.com/v2/get_other_list_file?${params}&signature=${signatureParams(params)}`).promise.then(({ body }) => {
+ // // console.log(body)
+ // if (body.data?.info == null) return this.getSongListDetailByGlobalSpecialId(id, page, limit, retry)
+ // return body.data.info
+ // })
+ // },
+ parseHtmlDesc(html) {
+ const prefix = '
'
+ let index = html.indexOf(prefix)
+ if (index < 0) return null
+ const afterStr = html.substring(index + prefix.length)
+ index = afterStr.indexOf('
')
+ if (index < 0) return null
+ return decodeName(afterStr.substring(0, index))
},
-
- /**
- * 获取SpecialId歌单
- * @param {*} id
- */
- async getUserListDetailBySpecialId(id, page, tryNum = 0) {
+ async getListDetailBySpecialId(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 (!listData) return this.getListDetailBySpecialId(id, page, ++tryNum)
- let list = await getMusicInfosByList(JSON.parse(listData[1]))
+ let list = await this.getMusicInfos(JSON.parse(listData[1]))
+ // listData = this.filterData(JSON.parse(listData[1]))
let name
let pic
if (listInfo) {
@@ -114,48 +138,36 @@ export default {
// play_count: formatPlayCount(body.result.listen_num),
},
}
- },
- parseHtmlDesc(html) {
- const prefix = ''
- let index = html.indexOf(prefix)
- if (index < 0) return null
- const afterStr = html.substring(index + prefix.length)
- index = afterStr.indexOf('
')
- if (index < 0) return null
- return decodeName(afterStr.substring(0, index))
- },
- /**
- * 使用SpecialId获取CollectionId
- * @param {*} specialId
- */
- async getCollectionIdBySpecialId(specialId) {
- return httpFetch(`http://mobilecdnbj.kugou.com/api/v5/special/info?specialid=${specialId}`, {
- headers: {
- 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; HLK-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Mobile Safari/537.36 EdgA/104.0.1293.70',
- },
- }).promise.then(({ body }) => {
- // console.log('getCollectionIdBySpecialId', body)
- if (!body.data.global_specialid) return Promise.reject(new Error('Failed to get global collection id.'))
- return body.data.global_specialid
- })
- },
-
- /**
- * 获取歌单URL
- * @param {*} sortId
- * @param {*} tagId
- * @param {*} page
- */
- getSongListUrl(sortId, tagId, page) {
- if (tagId == null) tagId = ''
- return `http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_ajax=1&cdn=cdn&t=${sortId}&c=${tagId}&p=${page}`
+ // const globalSpecialId = await this.getGlobalSpecialId(id)
+ // const limit = 100
+ // const listData = await this.getSongListDetailByGlobalSpecialId(globalSpecialId, page, limit)
+ // if (!Array.isArray(listData))
+ // return this.getUserListDetail2(globalSpecialId)
+ // return {
+ // list: this.filterDatav9(listData),
+ // page,
+ // limit,
+ // total: listInfo.total,
+ // source: 'kg',
+ // info: {
+ // name: listInfo.name,
+ // img: listInfo.image,
+ // desc: listInfo.intro,
+ // author: listInfo.author,
+ // play_count: formatPlayCount(listInfo.playcount),
+ // },
+ // }
},
getInfoUrl(tagId) {
return tagId
? `http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_smarty=1&cdn=cdn&t=5&c=${tagId}`
: 'http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_smarty=1&'
},
+ getSongListUrl(sortId, tagId, page) {
+ if (tagId == null) tagId = ''
+ return `http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_ajax=1&cdn=cdn&t=${sortId}&c=${tagId}&p=${page}`
+ },
getSongListDetailUrl(id) {
return `http://www2.kugou.kugou.com/yueku/v9/special/single/${id}-5-9999.html`
},
@@ -173,7 +185,6 @@ export default {
}
return result
},
-
filterTagInfo(rawData) {
const result = []
for (const name of Object.keys(rawData)) {
@@ -190,20 +201,6 @@ export default {
}
return result
},
- filterSongList(rawData) {
- return rawData.map(item => ({
- play_count: item.total_play_count || formatPlayCount(item.play_count),
- id: 'id_' + item.specialid,
- author: item.nickname,
- name: item.specialname,
- time: dateFormat(item.publish_time || item.publishtime, 'Y-M-D'),
- img: item.img || item.imgurl,
- total: item.songcount,
- grade: item.grade,
- desc: item.intro,
- source: 'kg',
- }))
- },
getSongList(sortId, tagId, page, tryNum = 0) {
if (this._requestObj_list) this._requestObj_list.cancelHttp()
@@ -213,7 +210,7 @@ export default {
)
return this._requestObj_list.promise.then(({ body }) => {
if (!body || body.status !== 1) return this.getSongList(sortId, tagId, page, ++tryNum)
- return this.filterSongList(body.special_db)
+ return this.filterList(body.special_db)
})
},
getSongListRecommend(tryNum = 0) {
@@ -241,185 +238,88 @@ export default {
)
return this._requestObj_listRecommend.promise.then(({ body }) => {
if (body.status !== 1) return this.getSongListRecommend(++tryNum)
- return this.filterSongList(body.data.special_list)
+ return this.filterList(body.data.special_list)
})
},
+ filterList(rawData) {
+ return rawData.map(item => ({
+ play_count: item.total_play_count || formatPlayCount(item.play_count),
+ id: 'id_' + item.specialid,
+ author: item.nickname,
+ name: item.specialname,
+ time: dateFormat(item.publish_time || item.publishtime, 'Y-M-D'),
+ img: item.img || item.imgurl,
+ total: item.songcount,
+ grade: item.grade,
+ desc: item.intro,
+ source: 'kg',
+ }))
+ },
- /**
- * 通过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)
+ 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
+ },
- const params = `appid=1058&specialid=0&global_specialid=${id}&format=jsonp&srcappid=2919&clientver=20000&clienttime=1586163242519&mid=1586163242519&uuid=1586163242519&dfid=-`
- return createHttpFetch(`https://mobiles.kugou.com/api/v5/special/info_v2?${params}&signature=${signatureParams(params, 5)}`, {
+ 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: {
- mid: '1586163242519',
- Referer: 'https://m3ws.kugou.com/share/index.php',
- 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
- dfid: '-',
- clienttime: '1586163242519',
+ '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(body => {
- let info = {
- type: body.type,
- userName: body.nickname,
- userAvatar: body.user_avatar,
- imageUrl: body.imgurl,
- desc: body.intro,
- name: body.specialname,
- globalSpecialid: body.global_specialid,
- total: body.songcount,
- playCount: body.playcount,
- }
-
- this.CollectionIdListInfoCache.set(id, info)
- return info
- })
+ }).then(data => data.map(s => s[0])))
},
- /**
- * 通过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)
-
- // 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.filterListByCollectionId(body.info)
-
- // 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: formatPlayCount(listInfo.playCount),
- // },
- // }
- // })
- // },
- /**
- * 通过CollectionId获取歌单
- * @param {*} id
- */
- async getUserListDetailByCollectionId(id, page = 1, limit = 300) {
- if (!id || id.length > 1000) return Promise.reject(new Error('ID error.'))
- 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 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.filterListByCollectionId(body.info)
-
- return {
- list: songList || [],
- page,
- limit,
- total: listInfo.total,
- source: 'kg',
- info: {
- name: listInfo.name,
- img: listInfo.imageUrl && listInfo.imageUrl.replace('{size}', 240),
- desc: listInfo.desc,
- author: listInfo.userName,
- play_count: formatPlayCount(listInfo.playCount),
- },
- }
- })
+ async getMusicInfos(list) {
+ return this.filterData2(
+ await Promise.all(
+ this.createTask(
+ this.deDuplication(list)
+ .map(item => ({ hash: item.hash })),
+ ))
+ .then(([...datas]) => datas.flat()))
},
- /**
- * 过滤GlobalSpecialId歌单数据
- * @param {*} rawData
- */
- filterListByCollectionId(rawData) {
- let ids = new Set()
- let list = []
- rawData.forEach(item => {
- if (!item) return
- if (ids.has(item.hash)) return
- ids.add(item.hash)
- const types = []
- const _types = {}
- item.relate_goods.forEach(data => {
- let size = sizeFormate(data.size)
- switch (data.level) {
- case 2:
- types.push({ type: '128k', size, hash: data.hash })
- _types['128k'] = {
- size,
- hash: data.hash,
- }
- break
- case 4:
- types.push({ type: '320k', size, hash: data.hash })
- _types['320k'] = {
- size,
- hash: data.hash,
- }
- break
- case 5:
- types.push({ type: 'flac', size, hash: data.hash })
- _types.flac = {
- size,
- hash: data.hash,
- }
- break
- case 6:
- types.push({ type: 'flac24bit', size, hash: data.hash })
- _types.flac24bit = {
- size,
- hash: data.hash,
- }
- break
- }
- })
-
- list.push({
- singer: formatSingerName(item.singerinfo, 'name') || decodeName(item.name).split(' - ')[0].replace(/&/g, '、'),
- name: decodeName(item.name).split(' - ')[1],
- albumName: decodeName(item.albuminfo.name),
- albumId: item.albuminfo.id,
- songmid: item.audio_id,
- source: 'kg',
- interval: formatPlayTime(parseInt(item.timelen) / 1000),
- img: null,
- lrc: null,
- hash: item.hash,
- otherSource: null,
- types,
- _types,
- typeUrl: {},
- })
- })
- return list
- },
- /**
- * 通过酷狗码获取歌单
- * @param {*} id
- * @param {*} page
- */
- async getUserListDetailByCode(id, page = 1) {
- // type 1单曲,2歌单,3电台,4酷狗码,5别人的播放队列
- const codeData = await createHttpFetch('http://t.kugou.com/command/', {
+ async getUserListDetailByCode(id) {
+ const songInfo = await this.createHttp('http://t.kugou.com/command/', {
method: 'POST',
headers: {
'KG-RC': 1,
@@ -428,58 +328,59 @@ export default {
},
body: { appid: 1001, clientver: 9020, mid: '21511157a05844bd085308bc76ef3343', clienttime: 640612895, key: '36164c4015e704673c588ee202b9ecb8', data: id },
})
- if (!codeData) return Promise.reject(new Error('Get list failed.'))
- const codeInfo = codeData.info
-
- switch (codeInfo.type) {
+ // console.log(songInfo)
+ // type 1单曲,2歌单,3电台,4酷狗码,5别人的播放队列
+ let songList
+ let info = songInfo.info
+ switch (info.type) {
case 2:
- if (!codeInfo.global_collection_id) return this.getUserListDetailBySpecialId(codeInfo.id, page)
+ if (!info.global_collection_id) return this.getListDetailBySpecialId(info.id)
break
- case 3:
- return album.getAlbumDetail(codeInfo.id, page)
- }
- if (codeInfo.global_collection_id) return this.getUserListDetailByCollectionId(codeInfo.global_collection_id, page)
- if (codeInfo.userid != null) {
- const songList = await createHttpFetch('http://www2.kugou.kugou.com/apps/kucodeAndShare/app/', {
+ default:
+ break
+ }
+ if (info.global_collection_id) return this.getUserListDetail2(info.global_collection_id)
+ if (info.userid != null) {
+ songList = await this.createHttp('http://www2.kugou.kugou.com/apps/kucodeAndShare/app/', {
method: 'POST',
headers: {
'KG-RC': 1,
'KG-THash': 'network_super_call.cpp:3676261689:379',
'User-Agent': '',
},
- body: { appid: 1001, clientver: 9020, mid: '21511157a05844bd085308bc76ef3343', clienttime: 640612895, key: '36164c4015e704673c588ee202b9ecb8', data: { id: codeInfo.id, type: 3, userid: codeInfo.userid, collect_type: 0, page: 1, pagesize: codeInfo.count } },
+ body: { appid: 1001, clientver: 9020, mid: '21511157a05844bd085308bc76ef3343', clienttime: 640612895, key: '36164c4015e704673c588ee202b9ecb8', data: { id: info.id, type: 3, userid: info.userid, collect_type: 0, page: 1, pagesize: info.count } },
})
// console.log(songList)
- let list = await getMusicInfosByList(songList || codeInfo.list)
- return {
- list,
- page: 1,
- limit: codeInfo.count,
- total: list.length,
- source: 'kg',
- info: {
- name: codeInfo.name,
- img: (codeInfo.img_size && codeInfo.img_size.replace('{size}', 240)) || codeInfo.img,
- // desc: body.result.info.list_desc,
- author: codeInfo.username,
- // play_count: formatPlayCount(info.count),
- },
- }
+ }
+ let list = await this.getMusicInfos(songList || songInfo.list)
+ return {
+ list,
+ page: 1,
+ limit: info.count,
+ total: list.length,
+ source: 'kg',
+ info: {
+ name: info.name,
+ img: (info.img_size && info.img_size.replace('{size}', 240)) || info.img,
+ // desc: body.result.info.list_desc,
+ author: info.username,
+ // play_count: formatPlayCount(info.count),
+ },
}
},
async getUserListDetail3(chain, page) {
- const songInfo = await createHttpFetch(`http://m.kugou.com/schain/transfer?pagesize=${this.listDetailLimit}&chain=${chain}&su=1&page=${page}&n=0.7928855356604456`, {
+ const songInfo = await this.createHttp(`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',
},
})
if (!songInfo.list) {
- if (songInfo.global_collection_id) return this.getUserListDetailByCollectionId(songInfo.global_collection_id, page)
+ if (songInfo.global_collection_id) return this.getUserListDetail2(songInfo.global_collection_id)
else return this.getUserListDetail4(songInfo, chain, page).catch(() => this.getUserListDetail5(chain))
}
- let list = await getMusicInfosByList(songInfo.list)
+ let list = await this.getMusicInfos(songInfo.list)
// console.log(info, songInfo)
return {
list,
@@ -497,6 +398,15 @@ export default {
}
},
+ deDuplication(datas) {
+ let ids = new Set()
+ return datas.filter(({ hash }) => {
+ if (ids.has(hash)) return false
+ ids.add(hash)
+ return true
+ })
+ },
+
async getUserListDetailByLink({ info }, link) {
let listInfo = info['0']
let total = listInfo.count
@@ -506,7 +416,7 @@ export default {
const limit = total > 90 ? 90 : total
total -= limit
page += 1
- tasks.push(createHttpFetch(link.replace(/pagesize=\d+/, 'pagesize=' + limit).replace(/page=\d+/, 'page=' + page), {
+ tasks.push(this.createHttp(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,
@@ -514,7 +424,7 @@ export default {
}).then(data => data.list.info))
}
let result = await Promise.all(tasks).then(([...datas]) => datas.flat())
- result = await getMusicInfosByList(result)
+ result = await this.getMusicInfos(result)
// console.log(result)
return {
list: result,
@@ -539,7 +449,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(createHttpFetch(`https://mobiles.kugou.com/api/v5/special/song_v2?${params}&signature=${signatureParams(params, 5)}`, {
+ tasks.push(this.createHttp(`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',
@@ -555,7 +465,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 createHttpFetch(`https://mobiles.kugou.com/api/v5/special/info_v2?${params}&signature=${signatureParams(params, 5)}`, {
+ let info = await this.createHttp(`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',
@@ -565,7 +475,7 @@ export default {
},
})
const songInfo = await this.createGetListDetail2Task(id, info.songcount)
- let list = await getMusicInfosByList(songInfo)
+ let list = await this.getMusicInfos(songInfo)
// console.log(info, songInfo, list)
return {
list,
@@ -590,7 +500,6 @@ export default {
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1',
},
}).promise
- // console.log(body)
let result = body.match(/var\sphpParam\s=\s({.+?});/)
if (result) result = JSON.parse(result[1])
this.cache.set(chain, result)
@@ -608,7 +517,7 @@ export default {
let result = body.match(/var\sdataFromSmarty\s=\s(\[.+?\])/)
if (result) result = JSON.parse(result[1])
this.cache.set(chain, result)
- result = await getMusicInfosByList(result)
+ result = await this.getMusicInfos(result)
// console.log(info, songInfo)
return result
},
@@ -617,7 +526,7 @@ export default {
const limit = 100
const [listInfo, list] = await Promise.all([
this.getListInfoByChain(chain),
- this.getUserListDetailBySpecialId(songInfo.id, page, limit),
+ this.getUserListDetailById(songInfo.id, page, limit),
])
return {
list: list || [],
@@ -656,29 +565,50 @@ export default {
}
},
+ async getUserListDetailById(id, page, limit) {
+ const signature = await handleSignature(id, page, limit)
+ let info = await this.createHttp(`https://pubsongscdn.kugou.com/v2/get_other_list_file?srcappid=2919&clientver=20000&appid=1058&type=0&module=playlist&page=${page}&pagesize=${limit}&specialid=${id}&signature=${signature}`, {
+ headers: {
+ Referer: 'https://m3ws.kugou.com/share/index.php',
+ 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
+ dfid: '-',
+ },
+ })
+
+ // console.log(info)
+ let result = await this.getMusicInfos(info.info)
+ // console.log(info, songInfo)
+ return result
+ },
+
async getUserListDetail(link, page, retryNum = 0) {
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.getUserListDetail2(link.replace(/^.*?global_collection_id=(\w+)(?:&.*$|#.*$|$)/, '$1'))
+ 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 requestObj_listDetailLink = httpFetch(link, {
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,
},
- follow_max: 2,
})
- const { headers: { location }, statusCode, body } = await requestLink.promise
- // console.log(body, location, statusCode)
+ const { headers: { location }, statusCode, body } = await requestObj_listDetailLink.promise
+ // console.log(body, location)
if (statusCode > 400) return this.getUserListDetail(link, page, ++retryNum)
- 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('"albumid":')) return album.getAlbumDetail(body.replace(/^[\s\S]+?"albumid":(\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 album.getAlbumDetail(body.replace(/^[\s\S]+?list_id = "(\w+)"[\s\S]+?$/, '$1'), page)
- }
if (location) {
- // 概念版分享链接 https://t1.kugou.com/xxx
- if (location.includes('global_specialid')) return this.getUserListDetailByCollectionId(location.replace(/^.*?global_specialid=(\w+)(?:&.*$|#.*$|$)/, '$1'), page)
- if (location.includes('global_collection_id')) return this.getUserListDetailByCollectionId(location.replace(/^.*?global_collection_id=(\w+)(?:&.*$|#.*$|$)/, '$1'), page)
+ // console.log(location)
+ if (location.includes('global_collection_id')) return this.getUserListDetail2(location.replace(/^.*?global_collection_id=(\w+)(?:&.*$|#.*$|$)/, '$1'))
if (location.includes('chain=')) return this.getUserListDetail3(location.replace(/^.*?chain=(\w+)(?:&.*$|#.*$|$)/, '$1'), page)
if (location.includes('.html')) {
if (location.includes('zlist.html')) {
@@ -691,12 +621,210 @@ export default {
return this.getUserListDetail(link, page, ++retryNum)
} else return this.getUserListDetail3(location.replace(/.+\/(\w+).html(?:\?.*|&.*$|#.*$|$)/, '$1'), page)
}
+ // console.log('location', location)
return this.getUserListDetail(location, page, ++retryNum)
}
+ if (typeof body == 'string') return this.getUserListDetail2(body.replace(/^[\s\S]+?"global_collection_id":"(\w+)"[\s\S]+?$/, '$1'))
if (body.errcode !== 0) return this.getUserListDetail(link, page, ++retryNum)
return this.getUserListDetailByLink(body, link)
},
+ async getListDetail(id, page) { // 获取歌曲列表内的音乐
+ id = id.toString()
+ if (id.includes('special/single/')) {
+ id = id.replace(this.regExps.listDetailLink, '$1')
+ } else if (/https?:/.test(id)) {
+ // fix https://www.kugou.com/songlist/xxx/?uid=xxx&chl=qq_client&cover=http%3A%2F%2Fimge.kugou.com%xxx.jpg&iszlist=1
+ return this.getUserListDetail(id.replace(/^.*?http/, 'http'), page)
+ } else if (/^\d+$/.test(id)) {
+ return this.getUserListDetailByCode(id)
+ } else if (id.startsWith('id_')) {
+ id = id.replace('id_', '')
+ }
+ // if ((/[?&:/]/.test(id))) id = id.replace(this.regExps.listDetailLink, '$1')
+
+ return this.getListDetailBySpecialId(id, page)
+ },
+ 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: {},
+ }
+ })
+ },
+ // getSinger(singers) {
+ // let arr = []
+ // singers?.forEach(singer => {
+ // arr.push(singer.name)
+ // })
+ // return arr.join('、')
+ // },
+ // v9 API
+ // filterDatav9(rawList) {
+ // console.log(rawList)
+ // return rawList.map(item => {
+ // const types = []
+ // const _types = {}
+ // item.relate_goods.forEach(qualityObj => {
+ // if (qualityObj.level === 2) {
+ // let size = sizeFormate(qualityObj.size)
+ // types.push({ type: '128k', size, hash: qualityObj.hash })
+ // _types['128k'] = {
+ // size,
+ // hash: qualityObj.hash,
+ // }
+ // } else if (qualityObj.level === 4) {
+ // let size = sizeFormate(qualityObj.size)
+ // types.push({ type: '320k', size, hash: qualityObj.hash })
+ // _types['320k'] = {
+ // size,
+ // hash: qualityObj.hash,
+ // }
+ // } else if (qualityObj.level === 5) {
+ // let size = sizeFormate(qualityObj.size)
+ // types.push({ type: 'flac', size, hash: qualityObj.hash })
+ // _types.flac = {
+ // size,
+ // hash: qualityObj.hash,
+ // }
+ // } else if (qualityObj.level === 6) {
+ // let size = sizeFormate(qualityObj.size)
+ // types.push({ type: 'flac24bit', size, hash: qualityObj.hash })
+ // _types.flac24bit = {
+ // size,
+ // hash: qualityObj.hash,
+ // }
+ // }
+ // })
+ // const nameInfo = item.name.split(' - ')
+ // return {
+ // singer: this.getSinger(item.singerinfo),
+ // name: decodeName((nameInfo[1] ?? nameInfo[0]).trim()),
+ // albumName: decodeName(item.albuminfo.name),
+ // albumId: item.albuminfo.id,
+ // songmid: item.audio_id,
+ // source: 'kg',
+ // interval: formatPlayTime(item.timelen / 1000),
+ // img: null,
+ // lrc: null,
+ // hash: item.hash,
+ // types,
+ // _types,
+ // typeUrl: {},
+ // }
+ // })
+ // },
+
+ // hash list filter
+ filterData2(rawList) {
+ // console.log(rawList)
+ let ids = new Set()
+ let list = []
+ rawList.forEach(item => {
+ if (!item) return
+ if (ids.has(item.audio_info.audio_id)) return
+ ids.add(item.audio_info.audio_id)
+ const types = []
+ const _types = {}
+ if (item.audio_info.filesize !== '0') {
+ let size = sizeFormate(parseInt(item.audio_info.filesize))
+ types.push({ type: '128k', size, hash: item.audio_info.hash })
+ _types['128k'] = {
+ size,
+ hash: item.audio_info.hash,
+ }
+ }
+ if (item.audio_info.filesize_320 !== '0') {
+ let size = sizeFormate(parseInt(item.audio_info.filesize_320))
+ types.push({ type: '320k', size, hash: item.audio_info.hash_320 })
+ _types['320k'] = {
+ size,
+ hash: item.audio_info.hash_320,
+ }
+ }
+ if (item.audio_info.filesize_flac !== '0') {
+ let size = sizeFormate(parseInt(item.audio_info.filesize_flac))
+ types.push({ type: 'flac', size, hash: item.audio_info.hash_flac })
+ _types.flac = {
+ size,
+ hash: item.audio_info.hash_flac,
+ }
+ }
+ if (item.audio_info.filesize_high !== '0') {
+ let size = sizeFormate(parseInt(item.audio_info.filesize_high))
+ types.push({ type: 'flac24bit', size, hash: item.audio_info.hash_high })
+ _types.flac24bit = {
+ size,
+ hash: item.audio_info.hash_high,
+ }
+ }
+ list.push({
+ singer: decodeName(item.author_name),
+ name: decodeName(item.ori_audio_name),
+ albumName: decodeName(item.album_info.album_name),
+ albumId: item.album_info.album_id,
+ songmid: item.audio_info.audio_id,
+ source: 'kg',
+ interval: formatPlayTime(parseInt(item.audio_info.timelength) / 1000),
+ img: null,
+ lrc: null,
+ hash: item.audio_info.hash,
+ otherSource: null,
+ types,
+ _types,
+ typeUrl: {},
+ })
+ })
+ return list
+ },
+
// 获取列表信息
getListInfo(tagId, tryNum = 0) {
if (this._requestObj_listInfo) this._requestObj_listInfo.cancelHttp()
@@ -759,33 +887,32 @@ 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 createHttpFetch(url).then(body => {
- // console.log(body)
- return {
- list: body.lists.map(item => {
- return {
- play_count: formatPlayCount(item.total_play_count),
- id: item.gid ? `gid_${item.gid}` : `id_${item.specialid}`,
- author: item.nickname,
- name: item.specialname,
- time: dateFormat(item.publish_time, 'Y-M-D'),
- img: item.img,
- grade: item.grade,
- desc: item.intro,
- total: item.song_count,
- source: 'kg',
- }
- }),
- limit,
- total: body.total,
- source: 'kg',
- }
- })
// http://msearchretry.kugou.com/api/v3/search/special?version=9209&keyword=%E5%91%A8%E6%9D%B0%E4%BC%A6&pagesize=20&filter=0&page=1&sver=2&with_res_tag=0
- // http://ioscdn.kugou.com/api/v3/search/special?keyword=${encodeURIComponent(text)}&page=${page}&pagesize=${limit}&showtype=10&plat=2&version=7910&correct=1&sver=5
- // http://msearchretry.kugou.com/api/v3/search/special?keyword=${encodeURIComponent(text)}&page=${page}&pagesize=${limit}&showtype=10&filter=0&version=7910&sver=2
+ // return httpFetch(`http://ioscdn.kugou.com/api/v3/search/special?keyword=${encodeURIComponent(text)}&page=${page}&pagesize=${limit}&showtype=10&plat=2&version=7910&correct=1&sver=5`)
+ return httpFetch(`http://msearchretry.kugou.com/api/v3/search/special?keyword=${encodeURIComponent(text)}&page=${page}&pagesize=${limit}&showtype=10&filter=0&version=7910&sver=2`)
+ .promise.then(({ body }) => {
+ if (body.errcode != 0) throw new Error('filed')
+ // console.log(body.data.info)
+ return {
+ list: body.data.info.map(item => {
+ return {
+ play_count: formatPlayCount(item.playcount),
+ id: 'id_' + item.specialid,
+ author: item.nickname,
+ name: item.specialname,
+ time: dateFormat(item.publishtime, 'Y-M-D'),
+ img: item.imgurl,
+ grade: item.grade,
+ desc: item.intro,
+ total: item.songcount,
+ source: 'kg',
+ }
+ }),
+ limit,
+ total: body.data.total,
+ source: 'kg',
+ }
+ })
},
}
diff --git a/src/renderer/utils/musicSdk/kg/temp/musicSearch-new.js b/src/renderer/utils/musicSdk/kg/temp/musicSearch-new.js
index d293ca24..535fc790 100644
--- a/src/renderer/utils/musicSdk/kg/temp/musicSearch-new.js
+++ b/src/renderer/utils/musicSdk/kg/temp/musicSearch-new.js
@@ -1,3 +1,4 @@
+import { formatSingerName } from '@renderer/utils/musicSdk/utils'
import { decodeName, formatPlayTime, sizeFormate } from '../../index'
import { signatureParams, createHttpFetch } from './util'
@@ -58,8 +59,8 @@ export default {
}
}
list.push({
- singer: decodeName(item.SingerName),
- name: decodeName(item.OriSongName),
+ singer: decodeName(formatSingerName(item.Singers)),
+ name: decodeName(item.SongName),
albumName: decodeName(item.AlbumName),
albumId: item.AlbumID,
songmid: item.Audioid,
diff --git a/src/renderer/utils/musicSdk/kg/temp/songList-old.js b/src/renderer/utils/musicSdk/kg/temp/songList-new.js
similarity index 51%
rename from src/renderer/utils/musicSdk/kg/temp/songList-old.js
rename to src/renderer/utils/musicSdk/kg/temp/songList-new.js
index 6557a578..389e93c1 100644
--- a/src/renderer/utils/musicSdk/kg/temp/songList-old.js
+++ b/src/renderer/utils/musicSdk/kg/temp/songList-new.js
@@ -1,17 +1,9 @@
import { httpFetch } from '../../../request'
-import { decodeName, formatPlayTime, sizeFormate, dateFormat } from '../../../index'
-import infSign from '../vendors/infSign.min'
-import { signatureParams } from '../util'
-
-const handleSignature = (id, page, limit) => new Promise((resolve, reject) => {
- infSign({ appid: 1058, type: 0, module: 'playlist', page, pagesize: limit, specialid: id }, null, {
- useH5: !0,
- isCDN: !0,
- callback(i) {
- resolve(i.signature)
- },
- })
-})
+import { formatSingerName } from '../../utils'
+import { decodeName, formatPlayTime, sizeFormate, dateFormat, formatPlayCount } from '../../../index'
+import { signatureParams, createHttpFetch } from './../util'
+import { getMusicInfosByList } from '../musicInfo'
+import album from '../album'
export default {
_requestObj_tags: null,
@@ -46,75 +38,59 @@ export default {
},
],
cache: new Map(),
+ collectionIdListInfoCache: new Map(),
regExps: {
listData: /global\.data = (\[.+\]);/,
listInfo: /global = {[\s\S]+?name: "(.+)"[\s\S]+?pic: "(.+)"[\s\S]+?};/,
// https://www.kugou.com/yy/special/single/1067062.html
listDetailLink: /^.+\/(\d+)\.html(?:\?.*|&.*$|#.*$|$)/,
},
- async getGlobalSpecialId(specialId) {
- return httpFetch(`http://mobilecdnbj.kugou.com/api/v5/special/info?specialid=${specialId}`, {
- headers: {
- 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; HLK-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Mobile Safari/537.36 EdgA/104.0.1293.70',
- },
- }).promise.then(({ body }) => {
- // console.log(body)
- if (!body.data.global_specialid) Promise.reject(new Error('Failed to get global collection id.'))
- return body.data.global_specialid
- })
+
+ /**
+ * 获取歌曲列表内的音乐
+ * @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.')
},
- // async getListInfoBySpecialId(special_id, retry = 0) {
- // if (++retry > 2) throw new Error('failed')
- // return httpFetch(`https://m.kugou.com/plist/list/${special_id}/?json=true`, {
- // headers: {
- // 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; HLK-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Mobile Safari/537.36 EdgA/104.0.1293.70',
- // },
- // follow_max: 2,
- // }).promise.then(({ body }) => {
- // // console.log(body)
- // if (!body.info.list) return this.getListInfoBySpecialId(special_id, retry)
- // let listinfo = body.info.list
- // return {
- // listInfo: {
- // name: listinfo.specialname,
- // image: listinfo.imgurl.replace('{size}', '150'),
- // intro: listinfo.intro,
- // author: listinfo.nickname,
- // playcount: listinfo.playcount,
- // total: listinfo.songcount,
- // },
- // globalSpecialId: listinfo.global_specialid,
- // }
- // })
- // },
- // async getSongListDetailByGlobalSpecialId(id, page, limit = 100, retry = 0) {
- // if (++retry > 2) throw new Error('failed')
- // console.log(id)
- // const params = `specialid=0&need_sort=1&module=CloudMusic&clientver=11409&pagesize=${limit}&global_collection_id=${id}&userid=0&page=${page}&type=1&area_code=1&appid=1005`
- // return httpFetch(`http://pubsongscdn.tx.kugou.com/v2/get_other_list_file?${params}&signature=${signatureParams(params)}`).promise.then(({ body }) => {
- // // console.log(body)
- // if (body.data?.info == null) return this.getSongListDetailByGlobalSpecialId(id, page, limit, retry)
- // return body.data.info
- // })
- // },
- parseHtmlDesc(html) {
- const prefix = ''
- let index = html.indexOf(prefix)
- if (index < 0) return null
- const afterStr = html.substring(index + prefix.length)
- index = afterStr.indexOf('
')
- if (index < 0) return null
- return decodeName(afterStr.substring(0, index))
- },
- async getListDetailBySpecialId(id, page, tryNum = 0) {
+
+ /**
+ * 获取SpecialId歌单
+ * @param {*} id
+ */
+ 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 (!listData) return this.getListDetailBySpecialId(id, page, ++tryNum)
- let list = await this.getMusicInfos(JSON.parse(listData[1]))
- // listData = this.filterData(JSON.parse(listData[1]))
+ let list = await getMusicInfosByList(JSON.parse(listData[1]))
let name
let pic
if (listInfo) {
@@ -135,52 +111,55 @@ export default {
img: pic,
desc,
// author: body.result.info.userinfo.username,
- // play_count: this.formatPlayCount(body.result.listen_num),
+ // play_count: formatPlayCount(body.result.listen_num),
},
}
+ },
+ parseHtmlDesc(html) {
+ const prefix = ''
+ let index = html.indexOf(prefix)
+ if (index < 0) return null
+ const afterStr = html.substring(index + prefix.length)
+ index = afterStr.indexOf('
')
+ if (index < 0) return null
+ return decodeName(afterStr.substring(0, index))
+ },
- // const globalSpecialId = await this.getGlobalSpecialId(id)
- // const limit = 100
- // const listData = await this.getSongListDetailByGlobalSpecialId(globalSpecialId, page, limit)
- // if (!Array.isArray(listData))
- // return this.getUserListDetail2(globalSpecialId)
- // return {
- // list: this.filterDatav9(listData),
- // page,
- // limit,
- // total: listInfo.total,
- // source: 'kg',
- // info: {
- // name: listInfo.name,
- // img: listInfo.image,
- // desc: listInfo.intro,
- // author: listInfo.author,
- // play_count: this.formatPlayCount(listInfo.playcount),
- // },
- // }
+ /**
+ * 使用SpecialId获取CollectionId
+ * @param {*} specialId
+ */
+ async getCollectionIdBySpecialId(specialId) {
+ return httpFetch(`http://mobilecdnbj.kugou.com/api/v5/special/info?specialid=${specialId}`, {
+ headers: {
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; HLK-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Mobile Safari/537.36 EdgA/104.0.1293.70',
+ },
+ }).promise.then(({ body }) => {
+ // console.log('getCollectionIdBySpecialId', body)
+ if (!body.data.global_specialid) return Promise.reject(new Error('Failed to get global collection id.'))
+ return body.data.global_specialid
+ })
+ },
+
+ /**
+ * 获取歌单URL
+ * @param {*} sortId
+ * @param {*} tagId
+ * @param {*} page
+ */
+ getSongListUrl(sortId, tagId, page) {
+ if (tagId == null) tagId = ''
+ return `http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_ajax=1&cdn=cdn&t=${sortId}&c=${tagId}&p=${page}`
},
getInfoUrl(tagId) {
return tagId
? `http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_smarty=1&cdn=cdn&t=5&c=${tagId}`
: 'http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_smarty=1&'
},
- getSongListUrl(sortId, tagId, page) {
- if (tagId == null) tagId = ''
- return `http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_ajax=1&cdn=cdn&t=${sortId}&c=${tagId}&p=${page}`
- },
getSongListDetailUrl(id) {
return `http://www2.kugou.kugou.com/yueku/v9/special/single/${id}-5-9999.html`
},
- /**
- * 格式化播放数量
- * @param {*} num
- */
- formatPlayCount(num) {
- if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿'
- if (num > 10000) return parseInt(num / 1000) / 10 + '万'
- return num
- },
filterInfoHotTag(rawData) {
const result = []
if (rawData.status !== 1) return result
@@ -194,6 +173,7 @@ export default {
}
return result
},
+
filterTagInfo(rawData) {
const result = []
for (const name of Object.keys(rawData)) {
@@ -210,6 +190,20 @@ export default {
}
return result
},
+ filterSongList(rawData) {
+ return rawData.map(item => ({
+ play_count: item.total_play_count || formatPlayCount(item.play_count),
+ id: 'id_' + item.specialid,
+ author: item.nickname,
+ name: item.specialname,
+ time: dateFormat(item.publish_time || item.publishtime, 'Y-M-D'),
+ img: item.img || item.imgurl,
+ total: item.songcount,
+ grade: item.grade,
+ desc: item.intro,
+ source: 'kg',
+ }))
+ },
getSongList(sortId, tagId, page, tryNum = 0) {
if (this._requestObj_list) this._requestObj_list.cancelHttp()
@@ -219,7 +213,7 @@ export default {
)
return this._requestObj_list.promise.then(({ body }) => {
if (!body || body.status !== 1) return this.getSongList(sortId, tagId, page, ++tryNum)
- return this.filterList(body.special_db)
+ return this.filterSongList(body.special_db)
})
},
getSongListRecommend(tryNum = 0) {
@@ -247,88 +241,185 @@ export default {
)
return this._requestObj_listRecommend.promise.then(({ body }) => {
if (body.status !== 1) return this.getSongListRecommend(++tryNum)
- return this.filterList(body.data.special_list)
+ return this.filterSongList(body.data.special_list)
})
},
- filterList(rawData) {
- return rawData.map(item => ({
- play_count: item.total_play_count || this.formatPlayCount(item.play_count),
- id: 'id_' + item.specialid,
- author: item.nickname,
- name: item.specialname,
- time: dateFormat(item.publish_time || item.publishtime, 'Y-M-D'),
- img: item.img || item.imgurl,
- total: item.songcount,
- grade: item.grade,
- desc: item.intro,
- source: 'kg',
- }))
- },
- 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
- },
+ /**
+ * 通过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)
- 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,
+ const params = `appid=1058&specialid=0&global_specialid=${id}&format=jsonp&srcappid=2919&clientver=20000&clienttime=1586163242519&mid=1586163242519&uuid=1586163242519&dfid=-`
+ return createHttpFetch(`https://mobiles.kugou.com/api/v5/special/info_v2?${params}&signature=${signatureParams(params, 5)}`, {
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',
+ mid: '1586163242519',
+ Referer: 'https://m3ws.kugou.com/share/index.php',
+ 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
+ dfid: '-',
+ clienttime: '1586163242519',
},
- }).then(data => data.map(s => s[0])))
- },
- async getMusicInfos(list) {
- return this.filterData2(
- await Promise.all(
- this.createTask(
- this.deDuplication(list)
- .map(item => ({ hash: item.hash })),
- ))
- .then(([...datas]) => datas.flat()))
- },
+ }).then(body => {
+ let info = {
+ type: body.type,
+ userName: body.nickname,
+ userAvatar: body.user_avatar,
+ imageUrl: body.imgurl,
+ desc: body.intro,
+ name: body.specialname,
+ globalSpecialid: body.global_specialid,
+ total: body.songcount,
+ playCount: body.playcount,
+ }
- async getUserListDetailByCode(id) {
- const songInfo = await this.createHttp('http://t.kugou.com/command/', {
+ 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)
+
+ // 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.filterListByCollectionId(body.info)
+
+ // 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: formatPlayCount(listInfo.playCount),
+ // },
+ // }
+ // })
+ // },
+ /**
+ * 通过CollectionId获取歌单
+ * @param {*} id
+ */
+ async getUserListDetailByCollectionId(id, page = 1, limit = 300) {
+ if (!id || id.length > 1000) return Promise.reject(new Error('ID error.'))
+ 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 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.filterListByCollectionId(body.info)
+
+ return {
+ list: songList || [],
+ page,
+ limit,
+ total: listInfo.total,
+ source: 'kg',
+ info: {
+ name: listInfo.name,
+ img: listInfo.imageUrl && listInfo.imageUrl.replace('{size}', 240),
+ desc: listInfo.desc,
+ author: listInfo.userName,
+ play_count: formatPlayCount(listInfo.playCount),
+ },
+ }
+ })
+ },
+ /**
+ * 过滤GlobalSpecialId歌单数据
+ * @param {*} rawData
+ */
+ filterListByCollectionId(rawData) {
+ let ids = new Set()
+ let list = []
+ rawData.forEach(item => {
+ if (!item) return
+ if (ids.has(item.hash)) return
+ ids.add(item.hash)
+ const types = []
+ const _types = {}
+
+ item.relate_goods.forEach(data => {
+ let size = sizeFormate(data.size)
+ switch (data.level) {
+ case 2:
+ types.push({ type: '128k', size, hash: data.hash })
+ _types['128k'] = {
+ size,
+ hash: data.hash,
+ }
+ break
+ case 4:
+ types.push({ type: '320k', size, hash: data.hash })
+ _types['320k'] = {
+ size,
+ hash: data.hash,
+ }
+ break
+ case 5:
+ types.push({ type: 'flac', size, hash: data.hash })
+ _types.flac = {
+ size,
+ hash: data.hash,
+ }
+ break
+ case 6:
+ types.push({ type: 'flac24bit', size, hash: data.hash })
+ _types.flac24bit = {
+ size,
+ hash: data.hash,
+ }
+ break
+ }
+ })
+
+ list.push({
+ singer: formatSingerName(item.singerinfo, 'name') || decodeName(item.name).split(' - ')[0].replace(/&/g, '、'),
+ name: decodeName(item.name).split(' - ')[1],
+ albumName: decodeName(item.albuminfo.name),
+ albumId: item.albuminfo.id,
+ songmid: item.audio_id,
+ source: 'kg',
+ interval: formatPlayTime(parseInt(item.timelen) / 1000),
+ img: null,
+ lrc: null,
+ hash: item.hash,
+ otherSource: null,
+ types,
+ _types,
+ typeUrl: {},
+ })
+ })
+ return list
+ },
+ /**
+ * 通过酷狗码获取歌单
+ * @param {*} id
+ * @param {*} page
+ */
+ async getUserListDetailByCode(id, page = 1) {
+ // type 1单曲,2歌单,3电台,4酷狗码,5别人的播放队列
+ const codeData = await createHttpFetch('http://t.kugou.com/command/', {
method: 'POST',
headers: {
'KG-RC': 1,
@@ -337,59 +428,58 @@ export default {
},
body: { appid: 1001, clientver: 9020, mid: '21511157a05844bd085308bc76ef3343', clienttime: 640612895, key: '36164c4015e704673c588ee202b9ecb8', data: id },
})
- // console.log(songInfo)
- // type 1单曲,2歌单,3电台,4酷狗码,5别人的播放队列
- let songList
- let info = songInfo.info
- switch (info.type) {
- case 2:
- if (!info.global_collection_id) return this.getListDetailBySpecialId(info.id)
- break
+ if (!codeData) return Promise.reject(new Error('Get list failed.'))
+ const codeInfo = codeData.info
- default:
+ switch (codeInfo.type) {
+ case 2:
+ if (!codeInfo.global_collection_id) return this.getUserListDetailBySpecialId(codeInfo.id, page)
break
+ case 3:
+ return album.getAlbumDetail(codeInfo.id, page)
}
- if (info.global_collection_id) return this.getUserListDetail2(info.global_collection_id)
- if (info.userid != null) {
- songList = await this.createHttp('http://www2.kugou.kugou.com/apps/kucodeAndShare/app/', {
+ if (codeInfo.global_collection_id) return this.getUserListDetailByCollectionId(codeInfo.global_collection_id, page)
+
+ if (codeInfo.userid != null) {
+ const songList = await createHttpFetch('http://www2.kugou.kugou.com/apps/kucodeAndShare/app/', {
method: 'POST',
headers: {
'KG-RC': 1,
'KG-THash': 'network_super_call.cpp:3676261689:379',
'User-Agent': '',
},
- body: { appid: 1001, clientver: 9020, mid: '21511157a05844bd085308bc76ef3343', clienttime: 640612895, key: '36164c4015e704673c588ee202b9ecb8', data: { id: info.id, type: 3, userid: info.userid, collect_type: 0, page: 1, pagesize: info.count } },
+ body: { appid: 1001, clientver: 9020, mid: '21511157a05844bd085308bc76ef3343', clienttime: 640612895, key: '36164c4015e704673c588ee202b9ecb8', data: { id: codeInfo.id, type: 3, userid: codeInfo.userid, collect_type: 0, page: 1, pagesize: codeInfo.count } },
})
// console.log(songList)
- }
- let list = await this.getMusicInfos(songList || songInfo.list)
- return {
- list,
- page: 1,
- limit: info.count,
- total: list.length,
- source: 'kg',
- info: {
- name: info.name,
- img: (info.img_size && info.img_size.replace('{size}', 240)) || info.img,
- // desc: body.result.info.list_desc,
- author: info.username,
- // play_count: this.formatPlayCount(info.count),
- },
+ let list = await getMusicInfosByList(songList || codeInfo.list)
+ return {
+ list,
+ page: 1,
+ limit: codeInfo.count,
+ total: list.length,
+ source: 'kg',
+ info: {
+ name: codeInfo.name,
+ img: (codeInfo.img_size && codeInfo.img_size.replace('{size}', 240)) || codeInfo.img,
+ // desc: body.result.info.list_desc,
+ author: codeInfo.username,
+ // play_count: formatPlayCount(info.count),
+ },
+ }
}
},
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',
},
})
if (!songInfo.list) {
- if (songInfo.global_collection_id) return this.getUserListDetail2(songInfo.global_collection_id)
+ if (songInfo.global_collection_id) return this.getUserListDetailByCollectionId(songInfo.global_collection_id, page)
else return this.getUserListDetail4(songInfo, chain, page).catch(() => this.getUserListDetail5(chain))
}
- let list = await this.getMusicInfos(songInfo.list)
+ let list = await getMusicInfosByList(songInfo.list)
// console.log(info, songInfo)
return {
list,
@@ -402,20 +492,11 @@ export default {
img: songInfo.info.img,
// desc: body.result.info.list_desc,
author: songInfo.info.username,
- // play_count: this.formatPlayCount(info.count),
+ // play_count: formatPlayCount(info.count),
},
}
},
- deDuplication(datas) {
- let ids = new Set()
- return datas.filter(({ hash }) => {
- if (ids.has(hash)) return false
- ids.add(hash)
- return true
- })
- },
-
async getUserListDetailByLink({ info }, link) {
let listInfo = info['0']
let total = listInfo.count
@@ -425,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,
@@ -433,7 +514,7 @@ export default {
}).then(data => data.list.info))
}
let result = await Promise.all(tasks).then(([...datas]) => datas.flat())
- result = await this.getMusicInfos(result)
+ result = await getMusicInfosByList(result)
// console.log(result)
return {
list: result,
@@ -446,7 +527,7 @@ export default {
img: listInfo.pic && listInfo.pic.replace('{size}', 240),
// desc: body.result.info.list_desc,
author: listInfo.list_create_username,
- // play_count: this.formatPlayCount(listInfo.count),
+ // play_count: formatPlayCount(listInfo.count),
},
}
},
@@ -458,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',
@@ -474,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',
@@ -484,7 +565,7 @@ export default {
},
})
const songInfo = await this.createGetListDetail2Task(id, info.songcount)
- let list = await this.getMusicInfos(songInfo)
+ let list = await getMusicInfosByList(songInfo)
// console.log(info, songInfo, list)
return {
list,
@@ -497,7 +578,7 @@ export default {
img: info.imgurl && info.imgurl.replace('{size}', 240),
desc: info.intro,
author: info.nickname,
- play_count: this.formatPlayCount(info.playcount),
+ play_count: formatPlayCount(info.playcount),
},
}
},
@@ -509,6 +590,7 @@ export default {
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1',
},
}).promise
+ // console.log(body)
let result = body.match(/var\sphpParam\s=\s({.+?});/)
if (result) result = JSON.parse(result[1])
this.cache.set(chain, result)
@@ -526,7 +608,7 @@ export default {
let result = body.match(/var\sdataFromSmarty\s=\s(\[.+?\])/)
if (result) result = JSON.parse(result[1])
this.cache.set(chain, result)
- result = await this.getMusicInfos(result)
+ result = await getMusicInfosByList(result)
// console.log(info, songInfo)
return result
},
@@ -535,7 +617,7 @@ export default {
const limit = 100
const [listInfo, list] = await Promise.all([
this.getListInfoByChain(chain),
- this.getUserListDetailById(songInfo.id, page, limit),
+ this.getUserListDetailBySpecialId(songInfo.id, page, limit),
])
return {
list: list || [],
@@ -548,7 +630,7 @@ export default {
img: listInfo.imgurl && listInfo.imgurl.replace('{size}', 240),
// desc: body.result.info.list_desc,
author: listInfo.nickname,
- // play_count: this.formatPlayCount(info.count),
+ // play_count: formatPlayCount(info.count),
},
}
},
@@ -569,55 +651,34 @@ export default {
img: listInfo.imgurl && listInfo.imgurl.replace('{size}', 240),
// desc: body.result.info.list_desc,
author: listInfo.nickname,
- // play_count: this.formatPlayCount(info.count),
+ // play_count: formatPlayCount(info.count),
},
}
},
- async getUserListDetailById(id, page, limit) {
- const signature = await handleSignature(id, page, limit)
- let info = await this.createHttp(`https://pubsongscdn.kugou.com/v2/get_other_list_file?srcappid=2919&clientver=20000&appid=1058&type=0&module=playlist&page=${page}&pagesize=${limit}&specialid=${id}&signature=${signature}`, {
- headers: {
- Referer: 'https://m3ws.kugou.com/share/index.php',
- 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
- dfid: '-',
- },
- })
-
- // console.log(info)
- let result = await this.getMusicInfos(info.info)
- // console.log(info, songInfo)
- return result
- },
-
async getUserListDetail(link, page, retryNum = 0) {
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.getUserListDetail2(link.replace(/^.*?global_collection_id=(\w+)(?:&.*$|#.*$|$)/, '$1'))
- 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 requestObj_listDetailLink = httpFetch(link, {
+ const requestLink = httpFetch(link, {
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,
},
+ follow_max: 2,
})
- const { headers: { location }, statusCode, body } = await requestObj_listDetailLink.promise
- // console.log(body, location)
+ const { headers: { location }, statusCode, body } = await requestLink.promise
+ // console.log(body, location, statusCode)
if (statusCode > 400) return this.getUserListDetail(link, page, ++retryNum)
+ 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('"albumid":')) return album.getAlbumDetail(body.replace(/^[\s\S]+?"albumid":(\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 album.getAlbumDetail(body.replace(/^[\s\S]+?list_id = "(\w+)"[\s\S]+?$/, '$1'), page)
+ }
if (location) {
- // console.log(location)
- if (location.includes('global_collection_id')) return this.getUserListDetail2(location.replace(/^.*?global_collection_id=(\w+)(?:&.*$|#.*$|$)/, '$1'))
+ // 概念版分享链接 https://t1.kugou.com/xxx
+ if (location.includes('global_specialid')) return this.getUserListDetailByCollectionId(location.replace(/^.*?global_specialid=(\w+)(?:&.*$|#.*$|$)/, '$1'), page)
+ if (location.includes('global_collection_id')) return this.getUserListDetailByCollectionId(location.replace(/^.*?global_collection_id=(\w+)(?:&.*$|#.*$|$)/, '$1'), page)
if (location.includes('chain=')) return this.getUserListDetail3(location.replace(/^.*?chain=(\w+)(?:&.*$|#.*$|$)/, '$1'), page)
if (location.includes('.html')) {
if (location.includes('zlist.html')) {
@@ -630,210 +691,12 @@ export default {
return this.getUserListDetail(link, page, ++retryNum)
} else return this.getUserListDetail3(location.replace(/.+\/(\w+).html(?:\?.*|&.*$|#.*$|$)/, '$1'), page)
}
- // console.log('location', location)
return this.getUserListDetail(location, page, ++retryNum)
}
- if (typeof body == 'string') return this.getUserListDetail2(body.replace(/^[\s\S]+?"global_collection_id":"(\w+)"[\s\S]+?$/, '$1'))
if (body.errcode !== 0) return this.getUserListDetail(link, page, ++retryNum)
return this.getUserListDetailByLink(body, link)
},
- async getListDetail(id, page) { // 获取歌曲列表内的音乐
- id = id.toString()
- if (id.includes('special/single/')) {
- id = id.replace(this.regExps.listDetailLink, '$1')
- } else if (/https?:/.test(id)) {
- // fix https://www.kugou.com/songlist/xxx/?uid=xxx&chl=qq_client&cover=http%3A%2F%2Fimge.kugou.com%xxx.jpg&iszlist=1
- return this.getUserListDetail(id.replace(/^.*?http/, 'http'), page)
- } else if (/^\d+$/.test(id)) {
- return this.getUserListDetailByCode(id)
- } else if (id.startsWith('id_')) {
- id = id.replace('id_', '')
- }
- // if ((/[?&:/]/.test(id))) id = id.replace(this.regExps.listDetailLink, '$1')
-
- return this.getListDetailBySpecialId(id, page)
- },
- 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: {},
- }
- })
- },
- // getSinger(singers) {
- // let arr = []
- // singers?.forEach(singer => {
- // arr.push(singer.name)
- // })
- // return arr.join('、')
- // },
- // v9 API
- // filterDatav9(rawList) {
- // console.log(rawList)
- // return rawList.map(item => {
- // const types = []
- // const _types = {}
- // item.relate_goods.forEach(qualityObj => {
- // if (qualityObj.level === 2) {
- // let size = sizeFormate(qualityObj.size)
- // types.push({ type: '128k', size, hash: qualityObj.hash })
- // _types['128k'] = {
- // size,
- // hash: qualityObj.hash,
- // }
- // } else if (qualityObj.level === 4) {
- // let size = sizeFormate(qualityObj.size)
- // types.push({ type: '320k', size, hash: qualityObj.hash })
- // _types['320k'] = {
- // size,
- // hash: qualityObj.hash,
- // }
- // } else if (qualityObj.level === 5) {
- // let size = sizeFormate(qualityObj.size)
- // types.push({ type: 'flac', size, hash: qualityObj.hash })
- // _types.flac = {
- // size,
- // hash: qualityObj.hash,
- // }
- // } else if (qualityObj.level === 6) {
- // let size = sizeFormate(qualityObj.size)
- // types.push({ type: 'flac24bit', size, hash: qualityObj.hash })
- // _types.flac24bit = {
- // size,
- // hash: qualityObj.hash,
- // }
- // }
- // })
- // const nameInfo = item.name.split(' - ')
- // return {
- // singer: this.getSinger(item.singerinfo),
- // name: decodeName((nameInfo[1] ?? nameInfo[0]).trim()),
- // albumName: decodeName(item.albuminfo.name),
- // albumId: item.albuminfo.id,
- // songmid: item.audio_id,
- // source: 'kg',
- // interval: formatPlayTime(item.timelen / 1000),
- // img: null,
- // lrc: null,
- // hash: item.hash,
- // types,
- // _types,
- // typeUrl: {},
- // }
- // })
- // },
-
- // hash list filter
- filterData2(rawList) {
- // console.log(rawList)
- let ids = new Set()
- let list = []
- rawList.forEach(item => {
- if (!item) return
- if (ids.has(item.audio_info.audio_id)) return
- ids.add(item.audio_info.audio_id)
- const types = []
- const _types = {}
- if (item.audio_info.filesize !== '0') {
- let size = sizeFormate(parseInt(item.audio_info.filesize))
- types.push({ type: '128k', size, hash: item.audio_info.hash })
- _types['128k'] = {
- size,
- hash: item.audio_info.hash,
- }
- }
- if (item.audio_info.filesize_320 !== '0') {
- let size = sizeFormate(parseInt(item.audio_info.filesize_320))
- types.push({ type: '320k', size, hash: item.audio_info.hash_320 })
- _types['320k'] = {
- size,
- hash: item.audio_info.hash_320,
- }
- }
- if (item.audio_info.filesize_flac !== '0') {
- let size = sizeFormate(parseInt(item.audio_info.filesize_flac))
- types.push({ type: 'flac', size, hash: item.audio_info.hash_flac })
- _types.flac = {
- size,
- hash: item.audio_info.hash_flac,
- }
- }
- if (item.audio_info.filesize_high !== '0') {
- let size = sizeFormate(parseInt(item.audio_info.filesize_high))
- types.push({ type: 'flac24bit', size, hash: item.audio_info.hash_high })
- _types.flac24bit = {
- size,
- hash: item.audio_info.hash_high,
- }
- }
- list.push({
- singer: decodeName(item.author_name),
- name: decodeName(item.ori_audio_name),
- albumName: decodeName(item.album_info.album_name),
- albumId: item.album_info.album_id,
- songmid: item.audio_info.audio_id,
- source: 'kg',
- interval: formatPlayTime(parseInt(item.audio_info.timelength) / 1000),
- img: null,
- lrc: null,
- hash: item.audio_info.hash,
- otherSource: null,
- types,
- _types,
- typeUrl: {},
- })
- })
- return list
- },
-
// 获取列表信息
getListInfo(tagId, tryNum = 0) {
if (this._requestObj_listInfo) this._requestObj_listInfo.cancelHttp()
@@ -896,32 +759,33 @@ 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 createHttpFetch(url).then(body => {
+ // console.log(body)
+ return {
+ list: body.lists.map(item => {
+ return {
+ play_count: formatPlayCount(item.total_play_count),
+ id: item.gid ? `gid_${item.gid}` : `id_${item.specialid}`,
+ author: item.nickname,
+ name: item.specialname,
+ time: dateFormat(item.publish_time, 'Y-M-D'),
+ img: item.img,
+ grade: item.grade,
+ desc: item.intro,
+ total: item.song_count,
+ source: 'kg',
+ }
+ }),
+ limit,
+ total: body.total,
+ source: 'kg',
+ }
+ })
// http://msearchretry.kugou.com/api/v3/search/special?version=9209&keyword=%E5%91%A8%E6%9D%B0%E4%BC%A6&pagesize=20&filter=0&page=1&sver=2&with_res_tag=0
- // return httpFetch(`http://ioscdn.kugou.com/api/v3/search/special?keyword=${encodeURIComponent(text)}&page=${page}&pagesize=${limit}&showtype=10&plat=2&version=7910&correct=1&sver=5`)
- return httpFetch(`http://msearchretry.kugou.com/api/v3/search/special?keyword=${encodeURIComponent(text)}&page=${page}&pagesize=${limit}&showtype=10&filter=0&version=7910&sver=2`)
- .promise.then(({ body }) => {
- if (body.errcode != 0) throw new Error('filed')
- // console.log(body.data.info)
- return {
- list: body.data.info.map(item => {
- return {
- play_count: this.formatPlayCount(item.playcount),
- id: 'id_' + item.specialid,
- author: item.nickname,
- name: item.specialname,
- time: dateFormat(item.publishtime, 'Y-M-D'),
- img: item.imgurl,
- grade: item.grade,
- desc: item.intro,
- total: item.songcount,
- source: 'kg',
- }
- }),
- limit,
- total: body.data.total,
- source: 'kg',
- }
- })
+ // http://ioscdn.kugou.com/api/v3/search/special?keyword=${encodeURIComponent(text)}&page=${page}&pagesize=${limit}&showtype=10&plat=2&version=7910&correct=1&sver=5
+ // http://msearchretry.kugou.com/api/v3/search/special?keyword=${encodeURIComponent(text)}&page=${page}&pagesize=${limit}&showtype=10&filter=0&version=7910&sver=2
},
}
diff --git a/src/renderer/utils/musicSdk/kg/util.js b/src/renderer/utils/musicSdk/kg/util.js
index 5bfbe2ff..955bac98 100644
--- a/src/renderer/utils/musicSdk/kg/util.js
+++ b/src/renderer/utils/musicSdk/kg/util.js
@@ -20,25 +20,18 @@ export const decodeLyric = str => new Promise((resolve, reject) => {
// console.log(str)
// })
-
-const signatureKey = { app: 'OIlwieks28dk2k092lksi2UIkp', web: 'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt' }
/**
* 签名
* @param {*} params
* @param {*} apiver
*/
export const signatureParams = (params, apiver = 9) => {
- let key = signatureKey.app
- if (apiver === 5) key = signatureKey.web
-
- if (typeof params === 'object') {
- if (!Array.isArray(params)) throw new Error('params error.')
- params = params.sort()
- } else if (typeof params === 'string') {
- params = params.split('&').sort()
- } else throw new Error('params error.')
-
- return toMD5(`${key}${params.join('')}${key}`)
+ let keyparam = 'OIlwieks28dk2k092lksi2UIkp'
+ if (apiver === 5) keyparam = 'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt'
+ let param_list = params.split('&')
+ param_list.sort()
+ let sign_params = `${keyparam}${param_list.join('')}${keyparam}`
+ return toMD5(sign_params)
}
/**
@@ -59,12 +52,9 @@ export const createHttpFetch = async(url, options, retryNum = 0) => {
// 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)
+ result.body.error_code ??
+ 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
diff --git a/src/renderer/utils/musicSdk/mg/album.js b/src/renderer/utils/musicSdk/mg/album.js
index 4223ecbb..b9b4435a 100644
--- a/src/renderer/utils/musicSdk/mg/album.js
+++ b/src/renderer/utils/musicSdk/mg/album.js
@@ -27,7 +27,7 @@ export default {
desc: listInfo.desc,
author: listInfo.author,
play_count: listInfo.play_count,
- }
+ },
}
},
/**
@@ -46,6 +46,6 @@ export default {
author: info.singer,
play_count: formatPlayCount(info.opNumItem.playNum),
total: info.totalCount,
- }
+ }
},
-}
\ No newline at end of file
+}
diff --git a/src/renderer/utils/musicSdk/mg/index.js b/src/renderer/utils/musicSdk/mg/index.js
index 8cd3aa63..6fec7987 100644
--- a/src/renderer/utils/musicSdk/mg/index.js
+++ b/src/renderer/utils/musicSdk/mg/index.js
@@ -6,10 +6,10 @@ import pic from './pic'
import lyric from './lyric'
import hotSearch from './hotSearch'
import comment from './comment'
-import tipSearch from './tipSearch'
+// import tipSearch from './tipSearch'
const mg = {
- tipSearch,
+ // tipSearch,
songList,
musicSearch,
leaderboard,
diff --git a/src/renderer/utils/musicSdk/mg/musicInfo.js b/src/renderer/utils/musicSdk/mg/musicInfo.js
index 01109c16..99aeeebc 100644
--- a/src/renderer/utils/musicSdk/mg/musicInfo.js
+++ b/src/renderer/utils/musicSdk/mg/musicInfo.js
@@ -2,7 +2,7 @@ import { sizeFormate } from '../../index'
import { createHttpFetch } from './utils'
import { formatSingerName } from '../utils'
-const createGetMusicInfosTask = (ids, resType = 2) => {
+const createGetMusicInfosTask = (ids) => {
let list = ids
let tasks = []
while (list.length) {
@@ -10,13 +10,13 @@ const createGetMusicInfosTask = (ids, resType = 2) => {
if (list.length < 100) break
list = list.slice(100)
}
- let url = `https://c.musicapp.migu.cn/MIGUM2.0/v1.0/content/resourceinfo.do?resourceType=${resType}`
- return tasks.map(task => createHttpFetch(url, {
+ let url = 'https://c.musicapp.migu.cn/MIGUM2.0/v1.0/content/resourceinfo.do?resourceType=2'
+ return Promise.all(tasks.map(task => createHttpFetch(url, {
method: 'POST',
form: {
resourceId: task.join('|'),
},
- }).then(data => data.resource))
+ }).then(data => data.resource)))
}
export const filterMusicInfoList = (rawList) => {
@@ -92,5 +92,5 @@ export const getMusicInfo = async(copyrightId) => {
}
export const getMusicInfos = async(copyrightIds) => {
- return filterMusicInfoList(await Promise.all(createGetMusicInfosTask(copyrightIds)).then(data => data))
+ return filterMusicInfoList(await Promise.all(createGetMusicInfosTask(copyrightIds)).then(data => data.flat()))
}
diff --git a/src/renderer/utils/musicSdk/mg/musicSearch.js b/src/renderer/utils/musicSdk/mg/musicSearch.js
index 635f6b56..3cb1b7df 100644
--- a/src/renderer/utils/musicSdk/mg/musicSearch.js
+++ b/src/renderer/utils/musicSdk/mg/musicSearch.js
@@ -1,10 +1,13 @@
+import { httpFetch } from '../../request'
import { sizeFormate, formatPlayTime } from '../../index'
-import { createHttpFetch } from './utils'
-import { formatSingerName, toMD5 } from '../utils'
+import { toMD5 } from '../utils'
+import { formatSingerName } from '@renderer/utils/musicSdk/utils'
-const searchSign = (timeStr, str, deviceId) => {
- const key = '6cdc72a439cef99a3418d2a78aa28c73'
- return toMD5(`${str}${key}yyapp2d16148780a1dcc7408e06336b98cfd50${deviceId}${timeStr}`)
+const sign = (time, str) => {
+ const deviceId = '963B7AA0D21511ED807EE5846EC87D20'
+ const signatureMd5 = '6cdc72a439cef99a3418d2a78aa28c73'
+ const sign = toMD5(`${str}${signatureMd5}yyapp2d16148780a1dcc7408e06336b98cfd50${deviceId}${time}`)
+ return { sign, deviceId }
}
export default {
@@ -12,115 +15,210 @@ export default {
total: 0,
page: 0,
allPage: 1,
- deviceId: '963B7AA0D21511ED807EE5846EC87D20',
+
+ // 旧版API
+ // musicSearch(str, page, limit) {
+ // const searchRequest = httpFetch(`http://pd.musicapp.migu.cn/MIGUM2.0/v1.0/content/search_all.do?ua=Android_migu&version=5.0.1&text=${encodeURIComponent(str)}&pageNo=${page}&pageSize=${limit}&searchSwitch=%7B%22song%22%3A1%2C%22album%22%3A0%2C%22singer%22%3A0%2C%22tagSong%22%3A0%2C%22mvSong%22%3A0%2C%22songlist%22%3A0%2C%22bestShow%22%3A1%7D`, {
+ // searchRequest = httpFetch(`http://pd.musicapp.migu.cn/MIGUM2.0/v1.0/content/search_all.do?ua=Android_migu&version=5.0.1&text=${encodeURIComponent(str)}&pageNo=${page}&pageSize=${limit}&searchSwitch=%7B%22song%22%3A1%2C%22album%22%3A0%2C%22singer%22%3A0%2C%22tagSong%22%3A0%2C%22mvSong%22%3A0%2C%22songlist%22%3A0%2C%22bestShow%22%3A1%7D`, {
+ // searchRequest = httpFetch(`http://jadeite.migu.cn:7090/music_search/v2/search/searchAll?sid=4f87090d01c84984a11976b828e2b02c18946be88a6b4c47bcdc92fbd40762db&isCorrect=1&isCopyright=1&searchSwitch=%7B%22song%22%3A1%2C%22album%22%3A0%2C%22singer%22%3A0%2C%22tagSong%22%3A1%2C%22mvSong%22%3A0%2C%22bestShow%22%3A1%2C%22songlist%22%3A0%2C%22lyricSong%22%3A0%7D&pageSize=${limit}&text=${encodeURIComponent(str)}&pageNo=${page}&sort=0`, {
+ // searchRequest = httpFetch(`https://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/search_all.do?isCopyright=1&isCorrect=1&pageNo=${page}&pageSize=${limit}&searchSwitch={%22song%22:1,%22album%22:0,%22singer%22:0,%22tagSong%22:0,%22mvSong%22:0,%22songlist%22:0,%22bestShow%22:0}&sort=0&text=${encodeURIComponent(str)}`)
+ // // searchRequest = httpFetch(`http://jadeite.migu.cn:7090/music_search/v2/search/searchAll?sid=4f87090d01c84984a11976b828e2b02c18946be88a6b4c47bcdc92fbd40762db&isCorrect=1&isCopyright=1&searchSwitch=%7B%22song%22%3A1%2C%22album%22%3A0%2C%22singer%22%3A0%2C%22tagSong%22%3A1%2C%22mvSong%22%3A0%2C%22bestShow%22%3A1%2C%22songlist%22%3A0%2C%22lyricSong%22%3A0%7D&pageSize=${limit}&text=${encodeURIComponent(str)}&pageNo=${page}&sort=0`, {
+ // headers: {
+ // // sign: 'c3b7ae985e2206e97f1b2de8f88691e2',
+ // // timestamp: 1578225871982,
+ // // appId: 'yyapp2',
+ // // mode: 'android',
+ // // ua: 'Android_migu',
+ // // version: '6.9.4',
+ // osVersion: 'android 7.0',
+ // 'User-Agent': 'okhttp/3.9.1',
+ // },
+ // })
+ // // searchRequest = httpFetch(`https://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/search_all.do?isCopyright=1&isCorrect=1&pageNo=${page}&pageSize=${limit}&searchSwitch={%22song%22:1,%22album%22:0,%22singer%22:0,%22tagSong%22:0,%22mvSong%22:0,%22songlist%22:0,%22bestShow%22:0}&sort=0&text=${encodeURIComponent(str)}`)
+ // return searchRequest.promise.then(({ body }) => body)
+ // },
+ // handleResult(rawData) {
+ // // console.log(rawData)
+ // let ids = new Set()
+ // const list = []
+ // rawData.forEach(item => {
+ // if (ids.has(item.id)) return
+ // ids.add(item.id)
+ // const types = []
+ // const _types = {}
+ // item.newRateFormats && item.newRateFormats.forEach(type => {
+ // let size
+ // switch (type.formatType) {
+ // case 'PQ':
+ // size = sizeFormate(type.size ?? type.androidSize)
+ // types.push({ type: '128k', size })
+ // _types['128k'] = {
+ // size,
+ // }
+ // break
+ // case 'HQ':
+ // size = sizeFormate(type.size ?? type.androidSize)
+ // types.push({ type: '320k', size })
+ // _types['320k'] = {
+ // size,
+ // }
+ // break
+ // case 'SQ':
+ // size = sizeFormate(type.size ?? type.androidSize)
+ // types.push({ type: 'flac', size })
+ // _types.flac = {
+ // size,
+ // }
+ // break
+ // case 'ZQ':
+ // size = sizeFormate(type.size ?? type.androidSize)
+ // types.push({ type: 'flac24bit', size })
+ // _types.flac24bit = {
+ // size,
+ // }
+ // break
+ // }
+ // })
+
+ // const albumNInfo = item.albums && item.albums.length
+ // ? {
+ // id: item.albums[0].id,
+ // name: item.albums[0].name,
+ // }
+ // : {}
+
+ // list.push({
+ // singer: this.getSinger(item.singers),
+ // name: item.name,
+ // albumName: albumNInfo.name,
+ // albumId: albumNInfo.id,
+ // songmid: item.songId,
+ // copyrightId: item.copyrightId,
+ // source: 'mg',
+ // interval: null,
+ // img: item.imgItems && item.imgItems.length ? item.imgItems[0].img : null,
+ // lrc: null,
+ // lrcUrl: item.lyricUrl,
+ // mrcUrl: item.mrcurl,
+ // trcUrl: item.trcUrl,
+ // otherSource: null,
+ // types,
+ // _types,
+ // typeUrl: {},
+ // })
+ // })
+ // return list
+ // },
+
musicSearch(str, page, limit) {
- // searchRequest = httpFetch(`https://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/search_all.do?isCopyright=1&isCorrect=1&pageNo=${page}&pageSize=${limit}&searchSwitch={%22song%22:1,%22album%22:0,%22singer%22:0,%22tagSong%22:0,%22mvSong%22:0,%22songlist%22:0,%22bestShow%22:0}&sort=0&text=${encodeURIComponent(str)}`)
- const timeStr = Date.now().toString()
- const signResult = searchSign(timeStr, str, this.deviceId)
- return createHttpFetch(`https://jadeite.migu.cn/music_search/v3/search/searchAll?isCorrect=1&isCopyright=1&searchSwitch=%7B%22song%22%3A1%2C%22album%22%3A0%2C%22singer%22%3A0%2C%22tagSong%22%3A1%2C%22mvSong%22%3A0%2C%22bestShow%22%3A1%2C%22songlist%22%3A0%2C%22lyricSong%22%3A0%7D&pageSize=${limit}&text=${encodeURIComponent(str)}&pageNo=${page}&sort=0`, {
+ const time = Date.now().toString()
+ const signData = sign(time, str)
+ const searchRequest = httpFetch(`https://jadeite.migu.cn/music_search/v3/search/searchAll?isCorrect=1&isCopyright=1&searchSwitch=%7B%22song%22%3A1%2C%22album%22%3A0%2C%22singer%22%3A0%2C%22tagSong%22%3A1%2C%22mvSong%22%3A0%2C%22bestShow%22%3A1%2C%22songlist%22%3A0%2C%22lyricSong%22%3A0%7D&pageSize=${limit}&text=${encodeURIComponent(str)}&pageNo=${page}&sort=0`, {
headers: {
uiVersion: 'A_music_3.6.1',
- deviceId: this.deviceId,
- timestamp: timeStr,
- sign: signResult,
+ deviceId: signData.deviceId,
+ timestamp: time,
+ sign: signData.sign,
channel: '0146921',
'User-Agent': 'Mozilla/5.0 (Linux; U; Android 11.0.0; zh-cn; MI 11 Build/OPR1.170623.032) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30',
},
- }).then(body => body)
+ })
+ return searchRequest.promise.then(({ body }) => body)
},
- filterList(raw) {
- const ids = new Set()
+ filterData(rawData) {
+ // console.log(rawData)
const list = []
+ const ids = new Set()
- raw.forEach(item => {
- if (!item.songId || !item.copyrightId || ids.has(item.copyrightId)) return
- ids.add(item.copyrightId)
+ rawData.forEach(item => {
+ item.forEach(data => {
+ if (!data.songId || !data.copyrightId || ids.has(data.copyrightId)) return
+ ids.add(data.copyrightId)
- const types = []
- const _types = {}
- item.audioFormats && item.audioFormats.forEach(type => {
- let size
- switch (type.formatType) {
- case 'PQ':
- size = sizeFormate(type.asize ?? type.isize)
- types.push({ type: '128k', size })
- _types['128k'] = {
- size,
- }
- break
- case 'HQ':
- size = sizeFormate(type.asize ?? type.isize)
- types.push({ type: '320k', size })
- _types['320k'] = {
- size,
- }
- break
- case 'SQ':
- size = sizeFormate(type.asize ?? type.isize)
- types.push({ type: 'flac', size })
- _types.flac = {
- size,
- }
- break
- case 'ZQ24':
- size = sizeFormate(type.asize ?? type.isize)
- types.push({ type: 'flac24bit', size })
- _types.flac24bit = {
- size,
- }
- break
- }
- })
+ const types = []
+ const _types = {}
+ data.audioFormats && data.audioFormats.forEach(type => {
+ let size
+ switch (type.formatType) {
+ case 'PQ':
+ size = sizeFormate(type.asize ?? type.isize)
+ types.push({ type: '128k', size })
+ _types['128k'] = {
+ size,
+ }
+ break
+ case 'HQ':
+ size = sizeFormate(type.asize ?? type.isize)
+ types.push({ type: '320k', size })
+ _types['320k'] = {
+ size,
+ }
+ break
+ case 'SQ':
+ size = sizeFormate(type.asize ?? type.isize)
+ types.push({ type: 'flac', size })
+ _types.flac = {
+ size,
+ }
+ break
+ case 'ZQ24':
+ size = sizeFormate(type.asize ?? type.isize)
+ types.push({ type: 'flac24bit', size })
+ _types.flac24bit = {
+ size,
+ }
+ break
+ }
+ })
- let img = item.img3 || item.img2 || item.img1 || null
- if (img && !/https?:/.test(item.img3)) img = 'http://d.musicapp.migu.cn' + img
+ let img = data.img3 || data.img2 || data.img1 || null
+ if (img && !/https?:/.test(data.img3)) img = 'http://d.musicapp.migu.cn' + img
- list.push({
- singer: formatSingerName(item.singerList, 'name'),
- name: item.name,
- albumName: item.album,
- albumId: item.albumId,
- songmid: item.songId,
- copyrightId: item.copyrightId,
- source: 'mg',
- interval: formatPlayTime(item.duration),
- img,
- lrc: null,
- lrcUrl: item.lrcUrl,
- mrcUrl: item.mrcurl,
- trcUrl: item.trcUrl,
- types,
- _types,
- typeUrl: {},
+ list.push({
+ singer: formatSingerName(data.singerList),
+ name: data.name,
+ albumName: data.album,
+ albumId: data.albumId,
+ songmid: data.songId,
+ copyrightId: data.copyrightId,
+ source: 'mg',
+ interval: formatPlayTime(data.duration),
+ img,
+ lrc: null,
+ lrcUrl: data.lrcUrl,
+ mrcUrl: data.mrcurl,
+ trcUrl: data.trcUrl,
+ types,
+ _types,
+ typeUrl: {},
+ })
})
})
-
return list
},
- handleResult(rawData) {
- return this.filterList(rawData.flat())
- },
search(str, page = 1, limit, retryNum = 0) {
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
if (limit == null) limit = this.limit
+ // http://newlyric.kuwo.cn/newlyric.lrc?62355680
+ return this.musicSearch(str, page, limit).then(result => {
+ // console.log(result)
+ if (!result || result.code !== '000000') return Promise.reject(new Error(result ? result.info : '搜索失败'))
+ const songResultData = result.songResultData || { resultList: [], totalCount: 0 }
- return this.musicSearch(str, page, limit).then(data => {
- const songResultData = data.songResultData || { resultList: [], totalCount: 0 }
-
- let list = this.handleResult(songResultData.resultList)
+ let list = this.filterData(songResultData.resultList)
if (list == null) return this.search(str, page, limit, retryNum)
this.total = parseInt(songResultData.totalCount)
this.page = page
this.allPage = Math.ceil(this.total / limit)
- return Promise.resolve({
+ return {
list,
allPage: this.allPage,
limit,
total: this.total,
source: 'mg',
- })
+ }
})
},
}
diff --git a/src/renderer/utils/musicSdk/tx/index.js b/src/renderer/utils/musicSdk/tx/index.js
index 1a5bcc1d..beb52af0 100644
--- a/src/renderer/utils/musicSdk/tx/index.js
+++ b/src/renderer/utils/musicSdk/tx/index.js
@@ -5,10 +5,10 @@ import musicSearch from './musicSearch'
import { apis } from '../api-source'
import hotSearch from './hotSearch'
import comment from './comment'
-import tipSearch from './tipSearch'
+// import tipSearch from './tipSearch'
const tx = {
- tipSearch,
+ // tipSearch,
leaderboard,
songList,
musicSearch,
diff --git a/src/renderer/utils/musicSdk/tx/tipSearch.js b/src/renderer/utils/musicSdk/tx/tipSearch.js
index bd3506f8..a844da9e 100644
--- a/src/renderer/utils/musicSdk/tx/tipSearch.js
+++ b/src/renderer/utils/musicSdk/tx/tipSearch.js
@@ -1,27 +1,29 @@
import { httpFetch } from '../../request'
export default {
+ // regExps: {
+ // relWord: /RELWORD=(.+)/,
+ // },
requestObj: null,
- cancelTipSearch() {
- if (this.requestObj && this.requestObj.cancelHttp) this.requestObj.cancelHttp()
- },
- tipSearchBySong(str) {
+ tipSearch(str) {
this.cancelTipSearch()
- this.requestObj = httpFetch(`https://c.y.qq.com/splcloud/fcgi-bin/smartbox_new.fcg?&format=json&inCharset=utf-8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=1&uin=0&hostUin=0&is_xml=0&key=${encodeURIComponent(str)}`, {
+ this.requestObj = httpFetch(`https://c.y.qq.com/splcloud/fcgi-bin/smartbox_new.fcg?is_xml=0&format=json&key=${encodeURIComponent(str)}&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0`, {
headers: {
- origin: 'https://y.qq.com/',
- referer: 'https://y.qq.com/',
+ Referer: 'https://y.qq.com/portal/player.html',
},
})
return this.requestObj.promise.then(({ statusCode, body }) => {
if (statusCode != 200 || body.code != 0) return Promise.reject(new Error('请求失败'))
- return body.data.song.itemlist
+ return body.data
})
},
handleResult(rawData) {
return rawData.map(info => `${info.name} - ${info.singer}`)
},
+ cancelTipSearch() {
+ if (this.requestObj && this.requestObj.cancelHttp) this.requestObj.cancelHttp()
+ },
async search(str) {
- return this.tipSearchBySong(str).then(result => this.handleResult(result))
+ return this.tipSearch(str).then(result => this.handleResult(result.song.itemlist))
},
}
diff --git a/src/renderer/utils/musicSdk/utils.js b/src/renderer/utils/musicSdk/utils.js
index 1b90b593..756cf880 100644
--- a/src/renderer/utils/musicSdk/utils.js
+++ b/src/renderer/utils/musicSdk/utils.js
@@ -22,7 +22,6 @@ export const getHostIp = hostname => {
})
}
-
export const dnsLookup = (hostname, options, callback) => {
const result = getHostIp(hostname)
if (result) return callback(null, result.address, result.family)
@@ -34,24 +33,24 @@ export const dnsLookup = (hostname, options, callback) => {
/**
* 格式化歌手
* @param singers 歌手数组
- * @param obj 读取的数据
- * @param join 插入的字符
+ * @param nameKey 歌手名键值
+ * @param join 歌手分割字符
*/
-export const formatSingerName = (singers, obj = 'name', join = '、') => {
- if (typeof singers === 'string') {
+export const formatSingerName = (singers, nameKey = 'name', join = '、') => {
+ if (typeof singers == 'string') {
try {
singers = JSON.parse(singers)
} catch (err) {
return decodeName(singers)
}
+ } else if (Array.isArray(singers)) {
+ const singer = []
+ singers.forEach(item => {
+ let name = item[nameKey]
+ if (!name) return
+ singer.push(name)
+ })
+ return decodeName(singer.join(join))
}
- if (!Array.isArray(singers)) return decodeName(singers)
-
- const singer = []
- singers.forEach(item => {
- let name = item[obj]
- if (!name) return
- singer.push(name)
- })
- return decodeName(singer.join(join))
+ return decodeName(String(singers ?? ''))
}
diff --git a/src/renderer/utils/musicSdk/wy/index.js b/src/renderer/utils/musicSdk/wy/index.js
index 95217c9c..a28295f5 100644
--- a/src/renderer/utils/musicSdk/wy/index.js
+++ b/src/renderer/utils/musicSdk/wy/index.js
@@ -6,10 +6,10 @@ import musicSearch from './musicSearch'
import songList from './songList'
import hotSearch from './hotSearch'
import comment from './comment'
-import tipSearch from './tipSearch'
+// import tipSearch from './tipSearch'
const wy = {
- tipSearch,
+ // tipSearch,
leaderboard,
musicSearch,
songList,