import type { HttpRequestObject, SongType, Quality, QualityInfo } from '../types.ts' import { httpFetch } from '../request.ts' import { formatPlayTime, sizeFormate } from '../index.ts' import { formatSingerName } from '../utils.ts' export const filterMusicInfoItem = item => { const types: SongType[] = [] const _types: Partial> = {} 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.title, 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) }) }, }