From 94403be9a87a2b155a05008f93db4d359ad5c50b Mon Sep 17 00:00:00 2001 From: Folltoshe Date: Sat, 10 Jun 2023 20:33:21 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A2=84=E7=95=99=E6=AD=8C=E6=89=8BAPI=20(#140?= =?UTF-8?q?7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 更新歌手API --------- Co-authored-by: lyswhut Co-authored-by: 彭狸花喵 --- src/renderer/utils/musicSdk/kg/singer.js | 122 ++++++----- src/renderer/utils/musicSdk/tx/singer.js | 249 +++++++++++++++++++++++ src/renderer/utils/musicSdk/wy/singer.js | 150 ++++++++++++++ 3 files changed, 473 insertions(+), 48 deletions(-) create mode 100644 src/renderer/utils/musicSdk/tx/singer.js create mode 100644 src/renderer/utils/musicSdk/wy/singer.js diff --git a/src/renderer/utils/musicSdk/kg/singer.js b/src/renderer/utils/musicSdk/kg/singer.js index b2f9394e..d0ec7c29 100644 --- a/src/renderer/utils/musicSdk/kg/singer.js +++ b/src/renderer/utils/musicSdk/kg/singer.js @@ -1,59 +1,85 @@ -import { httpFetch } from '../../request' -// import { decodeName, formatPlayTime, sizeFormate } from '../../index' -// import { signatureParams } from './util' import { getMusicInfosByList } from './musicInfo' +import { createHttpFetch } from './util' export default { - filterAlbum(rawList) { - let returnList = [] - rawList.forEach((albumInfo) => { - returnList.push({ - name: albumInfo.albumname, - author: albumInfo.singername, - img: albumInfo.replaceAll('{size}', '480'), - album_id: albumInfo.albumid, - }) + /** + * 获取歌手信息 + * @param {*} id + */ + getInfo(id) { + if (id == 0) throw new Error('歌手不存在') // kg源某些歌曲在歌手没被kg收录时返回的歌手id为0 + return createHttpFetch(`http://mobiles.kugou.com/api/v5/singer/info?singerid=${id}`).then(body => { + if (!body) throw new Error('get singer info faild.') + + return { + source: 'kg', + id: body.singerid, + info: { + name: body.singername, + desc: body.intro, + avatar: body.imgurl.replace('{size}', 480), + gender: body.grade === 1 ? 'man' : 'woman', + }, + count: { + music: body.songcount, + album: body.albumcount, + }, + } }) }, - async getSingerInfo(singerid) { - if (singerid == 0) throw new Error('歌手不存在') // kg源某些歌曲在歌手没被kg收录时返回的歌手id为0 - const requestObj = httpFetch(`http://mobiles.kugou.com/api/v5/singer/info?singerid=${singerid}`) - let { body, statusCode } = await requestObj.promise - if (statusCode !== 200) throw new Error('获取歌手信息失败') + /** + * 获取歌手专辑列表 + * @param {*} id + * @param {*} page + * @param {*} limit + */ + getAlbumList(id, page = 1, limit = 10) { + if (id == 0) throw new Error('歌手不存在') + return createHttpFetch(`http://mobiles.kugou.com/api/v5/singer/album?singerid=${id}&page=${page}&pagesize=${limit}`).then(body => { + if (!body.info) throw new Error('get singer album list faild.') + + const list = this.filterAlbumList(body.info) + return { + source: 'kg', + list, + limit, + page, + total: body.total, + } + }) + }, + /** + * 获取歌手歌曲列表 + * @param {*} id + * @param {*} page + * @param {*} limit + */ + async getSongList(id, page = 1, limit = 100) { + if (id == 0) throw new Error('歌手不存在') + const body = await createHttpFetch(`http://mobiles.kugou.com/api/v5/singer/song?singerid=${id}&page=${page}&pagesize=${limit}`) + if (!body.info) throw new Error('get singer song list faild.') + + const list = await getMusicInfosByList(body.info) return { source: 'kg', - singerid, - info: { - name: body.data.singername, - desc: body.data.intro, - img: body.data.imgurl.replace('{size}', '480'), - }, + list, + limit, + page, + total: body.total, } }, - async getSingerSongList(singerid, page, limit) { - if (singerid == 0) throw new Error('歌手不存在') // kg源某些歌曲在歌手没被kg收录时返回的歌手id为0 - const requestObj = httpFetch(`http://mobiles.kugou.com/api/v5/singer/song?singerid=${singerid}&page=${page}&pagesize=${limit}`) - let { body, statusCode } = await requestObj.promise - if (statusCode !== 200) throw new Error('获取歌手歌曲列表失败') - let listData = await getMusicInfosByList(body.data.info) - return { - source: 'kg', - list: listData, - id: `kg__singer_${singerid}`, - singerid, - total: body.data.total, - allPage: Math.ceil(body.data.total / limit), - } - }, - async getSingerAlbumList(singerid, page, limit) { - if (singerid == 0) throw new Error('歌手不存在') // kg源某些歌曲在歌手没被kg收录时返回的歌手id为0 - const requestObj = httpFetch(`http://mobiles.kugou.com/api/v5/singer/song?singerid=${singerid}&page=${page}&pagesize=${limit}`) - let { body, statusCode } = await requestObj.promise - if (statusCode !== 200) throw new Error('获取歌手专辑列表失败') - return { - source: 'kg', - albums: this.filterAlbum(body.data.info), - singerid, - } + filterAlbumList(raw) { + return raw.map(item => { + return { + id: item.albumid, + count: item.songcount, + info: { + name: item.albumname, + author: item.singername, + img: item.replaceAll('{size}', '480'), + desc: item.intro, + }, + } + }) }, } diff --git a/src/renderer/utils/musicSdk/tx/singer.js b/src/renderer/utils/musicSdk/tx/singer.js new file mode 100644 index 00000000..3e66a4d1 --- /dev/null +++ b/src/renderer/utils/musicSdk/tx/singer.js @@ -0,0 +1,249 @@ +import { httpFetch } from '../../request' + +import { formatPlayTime, sizeFormate } from '../../index' +import { formatSingerName } from '../utils' + +export const filterMusicInfoItem = item => { + const types = [] + const _types = {} + if (item.file.size_128mp3 != 0) { + let size = sizeFormate(item.file.size_128mp3) + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + } + if (item.file.size_320mp3 !== 0) { + let size = sizeFormate(item.file.size_320mp3) + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + } + if (item.file.size_flac !== 0) { + let size = sizeFormate(item.file.size_flac) + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + } + if (item.file.size_hires !== 0) { + let size = sizeFormate(item.file.size_hires) + types.push({ type: 'flac24bit', size }) + _types.flac24bit = { + size, + } + } + + const albumId = item.album.id ?? '' + const albumMid = item.album.mid ?? '' + const albumName = item.album.name ?? '' + return { + source: 'tx', + singer: formatSingerName(item.singer, 'name'), + name: item.name, + albumName, + albumId, + albumMid, + interval: formatPlayTime(item.interval), + songId: item.id, + songmid: item.mid, + strMediaMid: item.file.media_mid, + img: (albumId === '' || albumId === '空') + ? item.singer?.length ? `https://y.gtimg.cn/music/photo_new/T001R500x500M000${item.singer[0].mid}.jpg` : '' + : `https://y.gtimg.cn/music/photo_new/T002R500x500M000${albumMid}.jpg`, + types, + _types, + typeUrl: {}, + } +} + + +/** + * 创建一个适用于TX的Http请求 + * @param {*} url + * @param {*} options + * @param {*} retryNum + */ +const createMusicuFetch = async(data, options, retryNum = 0) => { + if (retryNum > 2) throw new Error('try max num') + + let result + try { + result = await httpFetch('https://u.y.qq.com/cgi-bin/musicu.fcg', { + method: 'POST', + body: { + comm: { + cv: 4747474, + ct: 24, + format: 'json', + inCharset: 'utf-8', + outCharset: 'utf-8', + uin: 0, + }, + ...data, + }, + headers: { + 'User-Angent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)', + }, + }).promise + } catch (err) { + console.log(err) + return createMusicuFetch(data, options, ++retryNum) + } + if (result.statusCode !== 200 || result.body.code != 0) return createMusicuFetch(data, options, ++retryNum) + + return result.body +} + +export default { + /** + * 获取歌手信息 + * @param {*} id + */ + getInfo(id) { + return createMusicuFetch({ + req_1: { + module: 'music.musichallSinger.SingerInfoInter', + method: 'GetSingerDetail', + param: { + singer_mid: [id], + ex_singer: 1, + wiki_singer: 1, + group_singer: 0, + pic: 1, + photos: 0, + }, + }, + req_2: { + module: 'music.musichallAlbum.AlbumListServer', + method: 'GetAlbumList', + param: { + singerMid: id, + order: 0, + begin: 0, + num: 1, + songNumTag: 0, + singerID: 0, + }, + }, + req_3: { + module: 'musichall.song_list_server', + method: 'GetSingerSongList', + param: { + singerMid: id, + order: 1, + begin: 0, + num: 1, + }, + }, + }).then(body => { + if (body.req_1.code != 0 || body.req_2 != 0 || body.req_3 != 0) throw new Error('get singer info faild.') + + const info = body.req_1.data.singer_list[0] + const music = body.req_3.data + const album = body.req_3.data + return { + source: 'tx', + id: info.basic_info.singer_mid, + info: { + name: info.basic_info.name, + desc: info.ex_info.desc, + avatar: info.pic.pic, + gender: info.ex_info.genre === 1 ? 'man' : 'woman', + }, + count: { + music: music.totalNum, + album: album.total, + }, + } + }) + }, + /** + * 获取歌手专辑列表 + * @param {*} id + * @param {*} page + * @param {*} limit + */ + getAlbumList(id, page = 1, limit = 10) { + if (page === 1) page = 0 + return createMusicuFetch({ + req: { + module: 'music.musichallAlbum.AlbumListServer', + method: 'GetAlbumList', + param: { + singerMid: id, + order: 0, + begin: page * limit, + num: limit, + songNumTag: 0, + singerID: 0, + }, + }, + }).then(body => { + if (body.req.code != 0) throw new Error('get singer album faild.') + + const list = this.filterAlbumList(body.req.data.albumList) + return { + source: 'tx', + list, + limit, + page, + total: body.req.data.total, + } + }) + }, + /** + * 获取歌手歌曲列表 + * @param {*} id + * @param {*} page + * @param {*} limit + */ + async getSongList(id, page = 1, limit = 100) { + if (page === 1) page = 0 + return createMusicuFetch({ + req: { + module: 'musichall.song_list_server', + method: 'GetSingerSongList', + param: { + singerMid: id, + order: 1, + begin: page * limit, + num: limit, + }, + }, + }).then(body => { + if (body.req.code != 0) throw new Error('get singer song list faild.') + + const list = this.filterSongList(body.req.data.songList) + return { + source: 'tx', + list, + limit, + page, + total: body.req.data.totalNum, + } + }) + }, + filterAlbumList(raw) { + return raw.map(item => { + return { + id: item.albumID, + mid: item.albumMid, + count: item.totalNum, + info: { + name: item.albumName, + author: item.singerName, + img: `https://y.gtimg.cn/music/photo_new/T002R500x500M000${item.albumMid}.jpg`, + desc: null, + }, + } + }) + }, + filterSongList(raw) { + raw.map(item => { + return filterMusicInfoItem(item.songInfo) + }) + }, +} + diff --git a/src/renderer/utils/musicSdk/wy/singer.js b/src/renderer/utils/musicSdk/wy/singer.js new file mode 100644 index 00000000..fc7f5949 --- /dev/null +++ b/src/renderer/utils/musicSdk/wy/singer.js @@ -0,0 +1,150 @@ +import { eapiRequest } from './utils/index' +import { formatPlayTime, sizeFormate } from '../../index' +import { formatSingerName } from '../utils' + +export default { + /** + * 获取歌手信息 + * @param {*} id + */ + getInfo(id) { + return eapiRequest('/api/artist/head/info/get', { id }).then(({ body }) => { + if (!body || body.code != 200) throw new Error('get singer info faild.') + return { + source: 'wy', + id: body.artist.id, + info: { + name: body.artist.name, + desc: body.artist.briefDesc, + avatar: body.user.avatarUrl, + gender: body.user.gender === 1 ? 'man' : 'woman', + }, + count: { + music: body.artist.musicSize, + album: body.artist.albumSize, + }, + } + }) + }, + /** + * 获取歌手歌曲列表 + * @param {*} id + * @param {*} page + * @param {*} limit + */ + getSongList(id, page = 1, limit = 100) { + if (page === 1) page = 0 + return eapiRequest('/api/v2/artist/songs', { + id, + limit, + offset: limit * page, + }).then(({ body }) => { + if (!body.songs || body.code != 200) throw new Error('get singer song list faild.') + + const list = this.filterSongList(body.songs) + return { + list, + limit, + page, + total: body.total, + source: 'wy', + } + }) + }, + /** + * 获取歌手专辑列表 + * @param {*} id + * @param {*} page + * @param {*} limit + */ + getAlbumList(id, page = 1, limit = 10) { + if (page === 1) page = 0 + return eapiRequest(`/api/artist/albums/${id}`, { + limit, + offset: limit * page, + }).then(({ body }) => { + if (!body.hotAlbums || body.code != 200) throw new Error('get singer album list faild.') + + const list = this.filterAlbumList(body.hotAlbums) + return { + source: 'wy', + list, + limit, + page, + total: body.artist.albumSize, + } + }) + }, + filterAlbumList(raw) { + const list = [] + raw.forEach(item => { + if (!item.id) return + list.push({ + id: item.id, + count: item.size, + info: { + name: item.name, + author: formatSingerName(item.artists), + img: item.picUrl, + desc: null, + }, + }) + }) + return list + }, + filterSongList(raw) { + const list = [] + raw.forEach(item => { + if (!item.id) return + + const types = [] + const _types = {} + let size + item.privilege.chargeInfoList.forEach(i => { + switch (i.rate) { + case 128000: + size = item.lMusic ? sizeFormate(item.lMusic.size) : null + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + case 320000: + size = item.hMusic ? sizeFormate(item.hMusic.size) : null + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + case 999000: + size = item.sqMusic ? sizeFormate(item.sqMusic.size) : null + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + case 1999000: + size = item.hrMusic ? sizeFormate(item.hrMusic.size) : null + types.push({ type: 'flac24bit', size }) + _types.flac24bit = { + size, + } + } + }) + + list.push({ + singer: formatSingerName(item.artists), + name: item.name, + albumName: item.album.name, + albumId: item.album.id, + songmid: item.id, + source: 'wy', + interval: formatPlayTime(item.duration), + img: null, + lrc: null, + otherSource: null, + types, + _types, + typeUrl: {}, + }) + }) + return list + }, +}