改变排行榜布局,新增更多排行榜

This commit is contained in:
lyswhut
2020-05-23 22:24:20 +08:00
parent a47be148c8
commit fe833033df
33 changed files with 815 additions and 368 deletions
+1 -1
View File
@@ -47,7 +47,7 @@
"search_history_title": "是否显示历史搜索记录",
"search_history": "搜索历史",
"search_focus_search_box_title": "启动时是否自动聚焦搜索框",
"search_focus_search_box": "聚焦搜索框",
"search_focus_search_box": "启动时是否聚焦搜索框",
"list": "列表设置",
"list_source_title": "是否显示歌曲源",
+1 -1
View File
@@ -45,7 +45,7 @@
"search_history_title": "是否顯示歷史搜索記錄",
"search_history": "搜索歷史",
"search_focus_search_box_title": "啟動時是否自動聚焦搜索框",
"search_focus_search_box": "聚焦搜索框",
"search_focus_search_box": "啟動時是否聚焦搜索框",
"list": "列表設置",
"list_source_title": "是否顯示歌曲源",
"list_source": "是否顯示歌曲源(僅對我的音樂分類有效)",
+1 -1
View File
@@ -47,7 +47,7 @@
"search_history_title": "Select whether to show search history",
"search_history": "Search history",
"search_focus_search_box_title": "Whether the search box is automatically focused on startup",
"search_focus_search_box": "Focus Search Box",
"search_focus_search_box": "Whether the search box is focused on startup",
"list": "List",
"list_source_title": "Select whether to show music source",
+24 -6
View File
@@ -3,13 +3,14 @@ const sourceList = {}
const sources = []
for (const source of music.sources) {
const leaderboard = music[source.id].leaderboard
if (!leaderboard) continue
sourceList[source.id] = leaderboard.list
if (!leaderboard || !leaderboard.getBoards) continue
sourceList[source.id] = []
sources.push(source)
}
// state
const state = {
boards: sourceList,
list: [],
total: 0,
page: 1,
@@ -19,8 +20,11 @@ const state = {
// getters
const getters = {
sourceInfo(state, getters, rootState, { sourceNames }) {
return { sources: sources.map(item => ({ id: item.id, name: sourceNames[item.id] })), sourceList }
sources(state, getters, rootState, { sourceNames }) {
return sources.map(item => ({ id: item.id, name: sourceNames[item.id] }))
},
boards(state) {
return state.boards
},
list(state) {
return state.list
@@ -36,18 +40,32 @@ const getters = {
// actions
const actions = {
getList({ state, rootState, commit }, page) {
getBoardsList({ state, rootState, commit }) {
// if (state.boards.length)
let source = rootState.setting.leaderboard.source
// let tabId = rootState.setting.leaderboard.tabId
// let key = `${source}${tabId}${page}`
// if (state.list.length && state.key == key) return true
// commit('clearList')
if (state.boards[source].length) return
return music[source].leaderboard.getBoards().then(result => commit('setBoardsList', { boards: result, source }))
},
getList({ state, rootState, commit }, page) {
// let source = rootState.setting.leaderboard.source
let tabId = rootState.setting.leaderboard.tabId
let [source, bangId] = tabId.split('__')
let key = `${source}${tabId}${page}`
if (state.list.length && state.key == key) return true
commit('clearList')
return music[source].leaderboard.getList(tabId, page).then(result => commit('setList', { result, key }))
return music[source].leaderboard.getList(bangId, page).then(result => commit('setList', { result, key }))
},
}
// mitations
const mutations = {
setBoardsList(state, { boards, source }) {
state.boards[source] = boards.list
},
setList(state, { result, key }) {
state.list = result.list
state.total = result.total
+7 -1
View File
@@ -135,7 +135,13 @@ const mutations = {
state.listDetail.limit = result.limit
state.listDetail.page = page
state.listDetail.key = key
state.listDetail.info = result.info || {}
state.listDetail.info = result.info || {
name: state.selectListInfo.name,
img: state.selectListInfo.img,
desc: state.selectListInfo.desc,
author: state.selectListInfo.author,
play_count: state.selectListInfo.play_count,
}
cache.set(key, result)
},
setVisibleListDetail(state, bool) {
+28 -6
View File
@@ -2,6 +2,22 @@ import { httpFetch } from '../../request'
// import { formatPlayTime } from '../../index'
// import jshtmlencode from 'js-htmlencode'
const boardList = [
// { id: 'bd__601', name: '歌单榜', bangid: '601' },
{ id: 'bd__2', name: '热歌榜', bangid: '2' },
{ id: 'bd__20', name: '华语金曲榜', bangid: '20' },
{ id: 'bd__25', name: '网络歌曲榜', bangid: '25' },
{ id: 'bd__1', name: '新歌榜', bangid: '1' },
{ id: 'bd__21', name: '欧美金曲榜', bangid: '21' },
{ id: 'bd__200', name: '原创音乐榜', bangid: '200' },
{ id: 'bd__22', name: '经典老歌榜', bangid: '22' },
{ id: 'bd__24', name: '影视金曲榜', bangid: '24' },
{ id: 'bd__23', name: '情歌对唱榜', bangid: '23' },
{ id: 'bd__11', name: '摇滚榜', bangid: '11' },
{ id: 'bd__105', name: '好童星榜', bangid: '105' },
{ id: 'bd__106', name: '雅克•藏羌彝原创音乐榜', bangid: '106' },
]
export default {
limit: 20,
list: [
@@ -111,14 +127,20 @@ export default {
// return rawData.map(item => JSON.parse(item.replace(this.regExps.item, '$1').replace(/"/g, '"').replace(/\\\//g, '/').replace(/(@s_1,w_)\d+(,h_)\d+/, '$1500$2500')))
return rawData.map(item => JSON.parse(item.replace(this.regExps.item, '$1').replace(/"/g, '"').replace(/\\\//g, '/')))
},
getList(id, page) {
let type = this.list.find(s => s.id === id)
if (!type) return Promise.reject()
return this.getData(this.getUrl(type.bangid, page)).then(({ body }) => {
async getBoards(retryNum = 0) {
this.list = boardList
return {
list: boardList,
source: 'bd',
}
},
getList(bangid, page, retryNum = 0) {
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
return this.getData(this.getUrl(bangid, page)).then(({ body }) => {
let result = body.match(this.regExps.item)
if (!result) return Promise.reject(new Error('匹配list失败'))
if (!result) return this.getList(bangid, page, retryNum)
let info = body.match(this.regExps.info)
if (!info) return Promise.reject(new Error('匹配info失败'))
if (!info) return this.getList(bangid, page, retryNum)
const list = this.filterData(this.parseData(result))
this.limit = parseInt(info[2])
return {
+1 -1
View File
@@ -8,7 +8,7 @@ export default {
_requestObj_listRecommend: null,
_requestObj_listDetail: null,
limit_list: 20,
limit_song: 1000,
limit_song: 10000,
successCode: 22000,
sortList: [
{
+53 -10
View File
@@ -1,6 +1,8 @@
import { httpGet, cancelHttp } from '../../request'
import { httpGet, cancelHttp, httpFetch } from '../../request'
import { formatPlayTime, sizeFormate } from '../../index'
let boardList = [{ id: 'kg__6666', name: '酷狗飙升榜', bangid: '6666' }, { id: 'kg__8888', name: '酷狗TOP500', bangid: '8888' }, { id: 'kg__37361', name: '酷狗雷达榜', bangid: '37361' }, { id: 'kg__23784', name: '网络红歌榜', bangid: '23784' }, { id: 'kg__24971', name: 'DJ热歌榜', bangid: '24971' }, { id: 'kg__35811', name: '会员专享热歌榜', bangid: '35811' }, { id: 'kg__31308', name: '华语新歌榜', bangid: '31308' }, { id: 'kg__31310', name: '欧美新歌榜', bangid: '31310' }, { id: 'kg__31311', name: '韩国新歌榜', bangid: '31311' }, { id: 'kg__31312', name: '日本新歌榜', bangid: '31312' }, { id: 'kg__31313', name: '粤语新歌榜', bangid: '31313' }, { id: 'kg__33162', name: 'ACG新歌榜', bangid: '33162' }, { id: 'kg__21101', name: '酷狗分享榜', bangid: '21101' }, { id: 'kg__30972', name: '腾讯音乐人原创榜', bangid: '30972' }, { id: 'kg__22603', name: '5sing音乐榜', bangid: '22603' }, { id: 'kg__33160', name: '电音热歌榜', bangid: '33160' }, { id: 'kg__21335', name: '繁星音乐榜', bangid: '21335' }, { id: 'kg__33161', name: '古风新歌榜', bangid: '33161' }, { id: 'kg__33163', name: '影视金曲榜', bangid: '33163' }, { id: 'kg__33166', name: '欧美金曲榜', bangid: '33166' }, { id: 'kg__33165', name: '粤语金曲榜', bangid: '33165' }, { id: 'kg__36107', name: '小语种热歌榜', bangid: '36107' }, { id: 'kg__4681', name: '美国BillBoard榜', bangid: '4681' }, { id: 'kg__4680', name: '英国单曲榜', bangid: '4680' }, { id: 'kg__4673', name: '日本公信榜', bangid: '4673' }, { id: 'kg__38623', name: '韩国Melon音乐榜', bangid: '38623' }, { id: 'kg__42807', name: 'joox本地热歌榜', bangid: '42807' }, { id: 'kg__42808', name: '台湾KKBOX风云榜', bangid: '42808' }]
export default {
list: [
{
@@ -53,11 +55,11 @@ export default {
name: 'DJ热歌榜',
bangid: '24971',
},
// {
// id: 'kghyxgb',
// name: '华语新歌榜',
// bangid: '31308',
// },
{
id: 'kghyxgb',
name: '华语新歌榜',
bangid: '31308',
},
],
getUrl(p, id) {
return `http://www2.kugou.kugou.com/yueku/v9/rank/home/${p}-${id}.html`
@@ -68,8 +70,14 @@ export default {
limit: /pagesize: '(\d+)',/,
listData: /global\.features = (\[.+\]);/,
},
_requestBoardsObj: null,
_requestObj: null,
_cancelPromiseCancelFn: null,
getBoardsData() {
if (this._requestBoardsObj) this._requestBoardsObj.cancelHttp()
this._requestBoardsObj = httpFetch('http://mobilecdnbj.kugou.com/api/v3/rank/list?version=9108&plat=0&showtype=2&parentid=0&apiver=6&area_code=1&withsong=1')
return this._requestBoardsObj.promise
},
getData(url) {
if (this._requestObj != null) {
cancelHttp(this._requestObj)
@@ -142,10 +150,45 @@ export default {
}
})
},
getList(id, page) {
let type = this.list.find(s => s.id === id)
if (!type) return Promise.reject()
return this.getData(this.getUrl(page, type.bangid)).then(html => {
filterBoardsData(rawList) {
// console.log(rawList)
let list = []
for (const board of rawList) {
if (board.isvol != 1) continue
list.push({
id: 'kg__' + board.rankid,
name: board.rankname,
bangid: String(board.rankid),
})
}
return list
},
async getBoards(retryNum = 0) {
// if (++retryNum > 3) return Promise.reject(new Error('try max num'))
// let response
// try {
// response = await this.getBoardsData()
// } catch (error) {
// return this.getBoards(retryNum)
// }
// // console.log(response.body)
// if (response.statusCode !== 200 || response.body.errcode !== 0) return this.getBoards(retryNum)
// const list = this.filterBoardsData(response.body.data.info)
// // console.log(list)
// this.list = list
// return {
// list,
// source: 'kg',
// }
this.list = boardList
return {
list: boardList,
source: 'kg',
}
},
getList(bangid, page) {
return this.getData(this.getUrl(page, bangid)).then(html => {
let total = html.match(this.regExps.total)
if (total) total = parseInt(RegExp.$1)
page = html.match(this.regExps.page)
+1 -1
View File
@@ -8,7 +8,7 @@ export default {
_requestObj_list: null,
_requestObj_listRecommend: null,
_requestObj_listDetail: null,
listDetailLimit: 100,
listDetailLimit: 10000,
currentTagInfo: {
id: undefined,
info: undefined,
+2 -2
View File
@@ -36,9 +36,9 @@ const kw = {
leaderboard,
songList,
hotSearch,
getLyric(songInfo) {
getLyric(songInfo, isGetLyricx) {
// let singer = songInfo.singer.indexOf('、') > -1 ? songInfo.singer.split('、')[0] : songInfo.singer
return lyric.getLyric(songInfo.songmid)
return lyric.getLyric(songInfo.songmid, isGetLyricx)
},
handleMusicInfo(songInfo) {
return this.getMusicInfo(songInfo).then(info => {
+61 -58
View File
@@ -1,6 +1,8 @@
import { httpGet, cancelHttp } from '../../request'
import { httpGet, cancelHttp, httpFetch } from '../../request'
import { formatPlayTime, decodeName } from '../../index'
import { formatSinger, getToken, matchToken } from './util'
import { formatSinger } from './util'
const boardList = [{ id: 'kw__93', name: '酷我飙升榜', bangid: '93' }, { id: 'kw__17', name: '酷我新歌榜', bangid: '17' }, { id: 'kw__16', name: '酷我热歌榜', bangid: '16' }, { id: 'kw__158', name: '抖音热歌榜', bangid: '158' }, { id: 'kw__284', name: '酷我热评榜', bangid: '284' }, { id: 'kw__290', name: 'ACG新歌榜', bangid: '290' }, { id: 'kw__286', name: '台湾KKBOX榜', bangid: '286' }, { id: 'kw__279', name: '春日浅唱榜', bangid: '279' }, { id: 'kw__281', name: '巴士随身听榜', bangid: '281' }, { id: 'kw__255', name: 'KTV点唱榜', bangid: '255' }, { id: 'kw__280', name: '家务进行曲榜', bangid: '280' }, { id: 'kw__282', name: '熬夜修仙榜', bangid: '282' }, { id: 'kw__283', name: '枕边轻音乐榜', bangid: '283' }, { id: 'kw__278', name: '古风音乐榜', bangid: '278' }, { id: 'kw__264', name: 'Vlog音乐榜', bangid: '264' }, { id: 'kw__242', name: '酷我电音榜', bangid: '242' }, { id: 'kw__187', name: '流行趋势榜', bangid: '187' }, { id: 'kw__204', name: '现场音乐榜', bangid: '204' }, { id: 'kw__186', name: 'ACG神曲榜', bangid: '186' }, { id: 'kw__185', name: '最强翻唱榜', bangid: '185' }, { id: 'kw__26', name: '经典怀旧榜', bangid: '26' }, { id: 'kw__104', name: '酷我华语榜', bangid: '104' }, { id: 'kw__182', name: '酷我粤语榜', bangid: '182' }, { id: 'kw__22', name: '酷我欧美榜', bangid: '22' }, { id: 'kw__184', name: '酷我韩语榜', bangid: '184' }, { id: 'kw__183', name: '酷我日语榜', bangid: '183' }, { id: 'kw__145', name: '会员畅听榜', bangid: '145' }, { id: 'kw__153', name: '网红新歌榜', bangid: '153' }, { id: 'kw__64', name: '影视金曲榜', bangid: '64' }, { id: 'kw__176', name: 'DJ嗨歌榜', bangid: '176' }, { id: 'kw__106', name: '酷我真声音', bangid: '106' }, { id: 'kw__12', name: 'Billboard榜', bangid: '12' }, { id: 'kw__49', name: 'iTunes音乐榜', bangid: '49' }, { id: 'kw__180', name: 'beatport电音榜', bangid: '180' }, { id: 'kw__13', name: '英国UK榜', bangid: '13' }, { id: 'kw__164', name: '百大DJ榜', bangid: '164' }, { id: 'kw__246', name: 'YouTube音乐排行榜', bangid: '246' }, { id: 'kw__265', name: '韩国Genie榜', bangid: '265' }, { id: 'kw__14', name: '韩国M-net榜', bangid: '14' }, { id: 'kw__8', name: '香港电台榜', bangid: '8' }, { id: 'kw__15', name: '日本公信榜', bangid: '15' }, { id: 'kw__151', name: '腾讯音乐人原创榜', bangid: '151' }]
export default {
list: [
@@ -61,15 +63,19 @@ export default {
},
],
getUrl: (p, l, id) => `http://kbangserver.kuwo.cn/ksong.s?from=pc&fmt=json&pn=${p - 1}&rn=${l}&type=bang&data=content&id=${id}&show_copyright_off=0&pcmp4=1&isbang=1`,
getUrl2: (p, l, id) => `http://www.kuwo.cn/api/www/bang/bang/musicList?bangId=${id}&pn=${p}&rn=${l}`,
regExps: {
},
limit: 30,
limit: 100,
_requestBoardsObj: null,
_cancelRequestObj: null,
_cancelPromiseCancelFn: null,
_cancelRequestObj2: null,
_cancelPromiseCancelFn2: null,
getBoardsData() {
if (this._requestBoardsObj) this._requestBoardsObj.cancelHttp()
this._requestBoardsObj = httpFetch('http://qukudata.kuwo.cn/q.k?op=query&cont=tree&node=2&pn=0&rn=1000&fmt=json&level=2')
return this._requestBoardsObj.promise
},
getData(url) {
if (this._cancelRequestObj != null) {
cancelHttp(this._cancelRequestObj)
@@ -77,45 +83,18 @@ export default {
}
return new Promise((resolve, reject) => {
this._cancelPromiseCancelFn = reject
this._cancelRequestObj = httpGet(url, (err, resp, body) => {
this._cancelRequestObj = httpGet(url, (err, resp) => {
this._cancelRequestObj = null
this._cancelPromiseCancelFn = null
if (err) {
console.log(err)
reject(err)
}
resolve(body)
resolve(resp)
})
})
},
async getData2(url) {
if (this._cancelRequestObj2 != null) {
cancelHttp(this._cancelRequestObj2)
this._cancelPromiseCancelFn2(new Error('取消http请求'))
}
let token = window.kw_token.token
if (!token) token = await getToken()
return new Promise((resolve, reject) => {
this._cancelPromiseCancelFn2 = reject
this._cancelRequestObj2 = httpGet(url, {
headers: {
Referer: 'http://www.kuwo.cn/',
csrf: token,
cookie: 'kw_token=' + token,
},
}, (err, resp, body) => {
this._cancelRequestObj2 = null
this._cancelPromiseCancelFn2 = null
if (err) {
console.log(err)
return reject(err)
}
window.kw_token.token = matchToken(resp.headers)
resolve(body)
})
})
},
filterData(rawList, rawList2) {
filterData(rawList) {
// console.log(rawList)
// console.log(rawList.length, rawList2.length)
return rawList.map((item, inedx) => {
@@ -160,7 +139,7 @@ export default {
albumId: item.albumid,
songmid: item.id,
source: 'kw',
interval: rawList2[inedx] && formatPlayTime(rawList2[inedx].duration),
interval: formatPlayTime(parseInt(item.song_duration)),
img: item.pic,
lrc: null,
types,
@@ -169,29 +148,53 @@ export default {
}
})
},
loadData(p1, p2, page, bangid, retryNum = 0) {
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
return Promise.all([p1, p2]).then(([data1, data2]) => {
// console.log(data1, data2)
if (!data1.musiclist.length) {
return this.loadData(this.getData(this.getUrl(page, this.limit, bangid)),
data2.data.musicList.length
? Promise.resolve(data2)
: this.getData2(this.getUrl2(page, this.limit, bangid)), page, bangid, retryNum)
}
if (!data2.data.musicList.length) {
return this.loadData(Promise.resolve(data1), this.getData2(this.getUrl2(page, this.limit, bangid)), page, bangid, retryNum)
}
return Promise.resolve([data1, data2])
})
filterBoardsData(rawList) {
// console.log(rawList)
let list = []
for (const board of rawList) {
if (board.source != '1') continue
list.push({
id: 'kw__' + board.sourceid,
name: board.name,
bangid: String(board.sourceid),
})
}
return list
},
getList(id, page) {
let type = this.list.find(s => s.id === id)
if (!type) return Promise.reject()
return this.loadData(this.getData(this.getUrl(page, this.limit, type.bangid)), this.getData2(this.getUrl2(page, this.limit, type.bangid)), page, type.bangid).then(([data1, data2]) => {
async getBoards(retryNum = 0) {
// if (++retryNum > 3) return Promise.reject(new Error('try max num'))
// let response
// try {
// response = await this.getBoardsData()
// } catch (error) {
// return this.getBoards(retryNum)
// }
// console.log(response.body)
// if (response.statusCode !== 200 || !response.body.child) return this.getBoards(retryNum)
// const list = this.filterBoardsData(response.body.child)
// // console.log(list)
// console.log(JSON.stringify(list))
// this.list = list
// return {
// list,
// source: 'kw',
// }
this.list = boardList
return {
list: boardList,
source: 'kw',
}
},
getList(id, page, retryNum = 0) {
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
return this.getData(this.getUrl(page, this.limit, id)).then(({ statusCode, body }) => {
// console.log(body)
if (statusCode !== 200 || !body.musiclist) return this.getList(id, page, retryNum)
// console.log(data1.musiclist, data2.data)
let total = parseInt(data1.num)
let list = this.filterData(data1.musiclist, data2.data.musicList)
let total = parseInt(body.num)
let list = this.filterData(body.musiclist)
return {
total,
list,
+19 -12
View File
@@ -1,19 +1,26 @@
import { httpFetch } from '../../request'
import { decodeName } from '../../index'
import { decodeLyric } from './util'
export default {
formatTime(time) {
let m = parseInt(time / 60)
let s = (time % 60).toFixed(2)
return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s)
lrcInfoRxp: /<lyric>(.+?)<\/lyric>[\s\S]+<lyric_zz>(.+?)<\/lyric_zz>/,
parseLyricInfo(str) {
let result = str.match(this.lrcInfoRxp)
if (!result) return null
return result ? { lyric: result[1], lyric_zz: result[2] } : null
},
transformLrc({ songinfo, lrclist }) {
return `[ti:${songinfo.songName}]\n[ar:${songinfo.artist}]\n[al:${songinfo.album}]\n[by:]\n[offset:0]\n${lrclist ? lrclist.map(l => `[${this.formatTime(l.time)}]${l.lineLyric}\n`).join('') : '暂无歌词'}`
},
getLyric(songId) {
const requestObj = httpFetch(`http://m.kuwo.cn/newh5/singles/songinfoandlrc?musicId=${songId}`)
requestObj.promise = requestObj.promise.then(({ body }) => {
return decodeName(this.transformLrc(body.data))
getLyric(songId, isGetLyricx = false) {
const requestObj = httpFetch(`http://player.kuwo.cn/webmusic/st/getNewMuiseByRid?rid=MUSIC_${songId}`)
requestObj.promise = requestObj.promise.then(({ statusCode, body }) => {
if (statusCode != 200) return Promise.reject(new Error(JSON.stringify(body)))
let info = this.parseLyricInfo(body)
if (!info) return Promise.reject(new Error(JSON.stringify(body)))
Object.assign(requestObj, httpFetch(`http://newlyric.kuwo.cn/newlyric.lrc?${isGetLyricx ? info.lyric_zz : info.lyric}`))
return requestObj.promise.then(({ statusCode, body, raw }) => {
if (statusCode != 200) return Promise.reject(new Error(JSON.stringify(body)))
return decodeLyric({ lrcBase64: raw.toString('base64'), isGetLyricx }).then(base64 => {
return Buffer.from(base64, 'base64').toString()
})
})
})
return requestObj
},
+1 -1
View File
@@ -8,7 +8,7 @@ export default {
_requestObj_list: null,
_requestObj_listDetail: null,
limit_list: 25,
limit_song: 1000,
limit_song: 10000,
successCode: 200,
sortList: [
{
+3
View File
@@ -1,4 +1,5 @@
import { httpGet } from '../../request'
import { rendererInvoke } from '../../../../common/ipc'
if (!window.kw_token) {
window.kw_token = {
@@ -32,3 +33,5 @@ export const getToken = () => new Promise((resolve, reject) => {
resolve(token)
})
})
export const decodeLyric = base64Data => rendererInvoke('kw_decodeLyric', base64Data)
+120 -43
View File
@@ -1,14 +1,16 @@
import { httpFetch } from '../../request'
// import { formatPlayTime } from '../../index'
import { sizeFormate } from '../../index'
// import jshtmlencode from 'js-htmlencode'
const boardList = [{ id: 'mg__27553319', name: '咪咕尖叫新歌榜', bangid: '27553319' }, { id: 'mg__27186466', name: '咪咕尖叫热歌榜', bangid: '27186466' }, { id: 'mg__27553408', name: '咪咕尖叫原创榜', bangid: '27553408' }, { id: 'mg__23189800', name: '咪咕港台榜', bangid: '23189800' }, { id: 'mg__23189399', name: '咪咕内地榜', bangid: '23189399' }, { id: 'mg__19190036', name: '咪咕欧美榜', bangid: '19190036' }, { id: 'mg__23189813', name: '咪咕日韩榜', bangid: '23189813' }, { id: 'mg__23190126', name: '咪咕彩铃榜', bangid: '23190126' }, { id: 'mg__15140045', name: '咪咕KTV榜', bangid: '15140045' }, { id: 'mg__15140034', name: '咪咕网络榜', bangid: '15140034' }, { id: 'mg__23217754', name: 'MV榜', bangid: '23217754' }, { id: 'mg__23218151', name: '新专辑榜', bangid: '23218151' }, { id: 'mg__21958042', name: 'iTunes榜', bangid: '21958042' }, { id: 'mg__21975570', name: 'billboard榜', bangid: '21975570' }, { id: 'mg__22272815', name: '台湾Hito中文榜', bangid: '22272815' }, { id: 'mg__22272904', name: '中国TOP排行榜', bangid: '22272904' }, { id: 'mg__22272943', name: '韩国Melon榜', bangid: '22272943' }, { id: 'mg__22273437', name: '英国UK榜', bangid: '22273437' }]
export default {
limit: 200,
list: [
{
id: 'mgyyb',
name: '音乐榜',
bangid: '23603703',
bangid: '27553319',
},
{
id: 'mgysb',
@@ -57,74 +59,149 @@ export default {
},
],
getUrl(id, page) {
return `http://m.music.migu.cn/migu/remoting/cms_list_tag?nid=${id}&pageSize=${this.limit}&pageNo=${page - 1}`
return `https://app.c.nf.migu.cn/MIGUM3.0/v1.0/template/rank-detail/release?columnId=${id}`
// return `http://m.music.migu.cn/migu/remoting/cms_list_tag?nid=${id}&pageSize=${this.limit}&pageNo=${page - 1}`
},
successCode: '000000',
requestBoardsObj: null,
requestObj: null,
getBoardsData() {
if (this.requestBoardsObj) this._requestBoardsObj.cancelHttp()
this.requestBoardsObj = httpFetch('https://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/indexrank.do?templateVersion=8', {
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',
},
})
return this.requestBoardsObj.promise
},
getData(url) {
if (this.requestObj) this.requestObj.cancelHttp()
this.requestObj = httpFetch(url)
return this.requestObj.promise
},
filterData(rawList) {
// console.log(rawList)
getSinger(singers) {
let arr = []
singers.forEach(singer => {
arr.push(singer.name)
})
return arr.join('、')
},
filterData(rawData) {
// console.log(JSON.stringify(rawData))
// console.log(rawData)
let ids = new Set()
const list = []
rawList.forEach(({ songData }) => {
if (!songData) return
if (ids.has(songData.copyrightId)) return
ids.add(songData.copyrightId)
rawData.forEach(item => {
if (ids.has(item.copyrightId)) return
ids.add(item.copyrightId)
const types = []
const _types = {}
let size = null
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
if (songData.hasHQqq === '1') {
types.push({ type: '320k', size })
_types['320k'] = {
size,
item.rateFormats && item.rateFormats.forEach(type => {
let size
switch (type.formatType) {
case 'PQ':
size = sizeFormate(type.size)
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
break
case 'HQ':
size = sizeFormate(type.size)
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
break
case 'SQ':
size = sizeFormate(type.size)
types.push({ type: 'flac', size })
_types.flac = {
size,
}
break
}
}
if (songData.hasSQqq === '1') {
types.push({ type: 'flac', size })
_types.flac = {
size,
}
}
// types.reverse()
})
list.push({
singer: songData.singerName.join('、'),
name: songData.songName,
// albumName: songData.album_title,
// albumId: songData.album_id,
singer: this.getSinger(item.artists),
name: item.songName,
albumName: item.album,
albumId: item.albumId,
songmid: item.copyrightId,
copyrightId: item.copyrightId,
source: 'mg',
interval: null,
songmid: songData.copyrightId,
copyrightId: songData.copyrightId,
img: songData.picL || songData.M || songData.picS,
img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null,
lrc: null,
lrcUrl: item.lrcUrl,
types,
_types,
typeUrl: {},
})
})
return list
},
getList(id, page) {
let type = this.list.find(s => s.id === id)
if (!type) return Promise.reject()
return this.getData(this.getUrl(type.bangid, page)).then(({ statusCode, body }) => {
if (statusCode !== 200) return Promise.reject(new Error('获取列表失败'))
const list = this.filterData(body.result.results)
filterBoardsData(rawList) {
// console.log(rawList)
let list = []
for (const board of rawList) {
if (board.template != 'group1') continue
for (const item of board.itemList) {
if ((item.template != 'row1' && item.template != 'grid1' && !item.actionUrl) || !item.actionUrl.includes('rank-info')) continue
let data = item.displayLogId.param
list.push({
id: 'mg__' + data.rankId,
name: data.rankName,
bangid: String(data.rankId),
})
}
}
return list
},
async getBoards(retryNum = 0) {
// if (++retryNum > 3) return Promise.reject(new Error('try max num'))
// let response
// try {
// response = await this.getBoardsData()
// } catch (error) {
// return this.getBoards(retryNum)
// }
// // console.log(response.body.data.contentItemList)
// if (response.statusCode !== 200 || response.body.code !== this.successCode) return this.getBoards(retryNum)
// const list = this.filterBoardsData(response.body.data.contentItemList)
// // console.log(list)
// // console.log(JSON.stringify(list))
// this.list = list
// return {
// list,
// source: 'mg',
// }
this.list = boardList
return {
list: boardList,
source: 'mg',
}
},
getList(bangid, page, retryNum = 0) {
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
return this.getData(this.getUrl(bangid, page)).then(({ statusCode, body }) => {
// console.log(body)
if (statusCode !== 200 || body.code !== this.successCode) return this.getList(bangid, page, retryNum)
const list = this.filterData(body.data.columnInfo.dataList)
return {
total: body.result.totalCount,
total: list.length,
list,
limit: body.result.pageSize,
limit: this.limit,
page,
source: 'mg',
}
+40 -9
View File
@@ -6,16 +6,18 @@ export default {
_requestObj_list: null,
_requestObj_listDetail: null,
limit_list: 10,
limit_song: 1000,
limit_song: 10000,
successCode: '000000',
sortList: [
{
name: '推荐',
id: '15127315',
// id: '1',
},
{
name: '最新',
id: '15127272',
// id: '2',
},
],
regExps: {
@@ -34,8 +36,12 @@ export default {
// }
// return `http://music.migu.cn/v3/music/playlist?tagId=${tagId}&page=${page}&from=migu`
if (tagId == null) {
// return `http://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?count=${this.limit_list}&start=${page}&templateVersion=5&type=1`
// return `https://c.musicapp.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?count=${this.limit_list}&start=${page}&templateVersion=5&type=${sortId}`
// http://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?count=50&start=2&templateVersion=5&type=1
return `http://m.music.migu.cn/migu/remoting/playlist_bycolumnid_tag?playListType=2&type=1&columnId=${sortId}&startIndex=${(page - 1) * 10}`
}
// return `https://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?area=2&count=${this.limit_list}&start=${page}&tags=${tagId}&templateVersion=5&type=3`
return `http://m.music.migu.cn/migu/remoting/playlist_bycolumnid_tag?playListType=2&type=1&tagId=${tagId}&startIndex=${(page - 1) * 10}`
},
getSongListDetailUrl(id, page) {
@@ -68,19 +74,20 @@ export default {
return this._requestObj_listDetail.promise.then(({ body }) => {
if (body.code !== this.successCode) return this.getListDetail(id, page, ++tryNum)
// console.log(JSON.stringify(body))
console.log(body)
return {
list: this.filterListDetail(body.list),
page,
limit: this.limit_song,
total: body.totalCount,
source: 'mg',
info: {
// name: body.result.info.list_title,
// img: body.result.info.list_pic,
// desc: body.result.info.list_desc,
// author: body.result.info.userinfo.username,
// play_count: this.formatPlayCount(body.result.listen_num),
},
// info: {
// // name: body.result.info.list_title,
// // img: body.result.info.list_pic,
// // desc: body.result.info.list_desc,
// // author: body.result.info.userinfo.username,
// // play_count: this.formatPlayCount(body.result.listen_num),
// },
}
})
},
@@ -145,7 +152,18 @@ export default {
getList(sortId, tagId, page, tryNum = 0) {
if (this._requestObj_list) this._requestObj_list.cancelHttp()
if (tryNum > 2) return Promise.reject(new Error('try max num'))
this._requestObj_list = httpFetch(this.getSongListUrl(sortId, tagId, page))
this._requestObj_list = httpFetch(this.getSongListUrl(sortId, tagId, page), {
// 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',
// },
})
// return this._requestObj_list.promise.then(({ statusCode, body }) => {
// if (statusCode !== 200) return this.getList(sortId, tagId, page)
// let list = body.replace(/[\r\n]/g, '').match(this.regExps.list)
@@ -167,6 +185,7 @@ export default {
// })
return this._requestObj_list.promise.then(({ body }) => {
if (body.retCode !== '100000' || body.retMsg.code !== this.successCode) return this.getList(sortId, tagId, page, ++tryNum)
// console.log(body)
return {
list: this.filterList(body.retMsg.playlist),
total: parseInt(body.retMsg.countSize),
@@ -175,6 +194,18 @@ export default {
source: 'mg',
}
})
// return this._requestObj_list.promise.then(({ body }) => {
// if (body.retCode !== '100000') return this.getList(sortId, tagId, page, ++tryNum)
// // if (body.code !== '000000') return this.getList(sortId, tagId, page, ++tryNum)
// console.log(body)
// // return {
// // list: this.filterList(body.data.contentItemList[0].itemList),
// // total: parseInt(body.retMsg.countSize),
// // page,
// // limit: this.limit_list,
// // source: 'mg',
// // }
// })
},
filterList(rawData) {
return rawData.map(item => ({
+63 -13
View File
@@ -1,6 +1,8 @@
import { httpGet, cancelHttp } from '../../request'
import { httpGet, cancelHttp, httpFetch } from '../../request'
import { formatPlayTime, sizeFormate } from '../../index'
let boardList = [{ id: 'tx__4', name: '流行指数榜', bangid: '4' }, { id: 'tx__26', name: '热歌榜', bangid: '26' }, { id: 'tx__27', name: '新歌榜', bangid: '27' }, { id: 'tx__62', name: '飙升榜', bangid: '62' }, { id: 'tx__58', name: '说唱榜', bangid: '58' }, { id: 'tx__57', name: '电音榜', bangid: '57' }, { id: 'tx__28', name: '网络歌曲榜', bangid: '28' }, { id: 'tx__5', name: '内地榜', bangid: '5' }, { id: 'tx__3', name: '欧美榜', bangid: '3' }, { id: 'tx__59', name: '香港地区榜', bangid: '59' }, { id: 'tx__16', name: '韩国榜', bangid: '16' }, { id: 'tx__60', name: '抖音排行榜', bangid: '60' }, { id: 'tx__29', name: '影视金曲榜', bangid: '29' }, { id: 'tx__17', name: '日本榜', bangid: '17' }, { id: 'tx__52', name: '腾讯音乐人原创榜', bangid: '52' }, { id: 'tx__36', name: 'K歌金曲榜', bangid: '36' }, { id: 'tx__61', name: '台湾地区榜', bangid: '61' }, { id: 'tx__63', name: 'DJ舞曲榜', bangid: '63' }, { id: 'tx__64', name: '综艺新歌榜', bangid: '64' }, { id: 'tx__65', name: '国风热歌榜', bangid: '65' }, { id: 'tx__66', name: 'ACG新歌榜', bangid: '66' }, { id: 'tx__67', name: '听歌识曲榜', bangid: '67' }, { id: 'tx__70', name: '达人音乐榜', bangid: '70' }]
export default {
limit: 300,
list: [
@@ -54,11 +56,11 @@ export default {
name: '日本榜',
bangid: 17,
},
// {
// id: 'txtybb',
// name: 'YouTube榜',
// bangid: 128,
// },
{
id: 'txtybb',
name: 'YouTube榜',
bangid: 128,
},
],
getUrl(id, period, limit) {
return `https://u.y.qq.com/cgi-bin/musicu.fcg?format=json&inCharset=utf8&outCharset=utf-8&platform=yqq.json&needNewCode=0&data=${encodeURIComponent(JSON.stringify({
@@ -83,8 +85,14 @@ export default {
},
periods: {},
periodUrl: 'https://c.y.qq.com/node/pc/wk_v15/top.html',
_requestBoardsObj: null,
_cancelRequestObj: null,
_cancelPromiseCancelFn: null,
getBoardsData() {
if (this._requestBoardsObj) this._requestBoardsObj.cancelHttp()
this._requestBoardsObj = httpFetch('https://c.y.qq.com/v8/fcg-bin/fcg_myqq_toplist.fcg?g_tk=1928093487&inCharset=utf-8&outCharset=utf-8&notice=0&format=json&uin=0&needNewCode=1&platform=h5')
return this._requestBoardsObj.promise
},
getData(url) {
if (this._cancelRequestObj != null) {
cancelHttp(this._cancelRequestObj)
@@ -182,15 +190,57 @@ export default {
return info && info.period
})
},
getList(id, page) {
let type = this.list.find(s => s.id === id)
if (!type) return Promise.reject()
let info = this.periods[type.bangid]
let p = info ? Promise.resolve(info.period) : this.getPeriods(type.bangid)
filterBoardsData(rawList) {
// console.log(rawList)
let list = []
for (const board of rawList) {
// 排除 MV榜
if (board.id == 201) continue
if (board.topTitle.startsWith('巅峰榜·')) {
board.topTitle = board.topTitle.substring(4, board.topTitle.length)
}
if (!board.topTitle.endsWith('榜')) board.topTitle += '榜'
list.push({
id: 'tx__' + board.id,
name: board.topTitle,
bangid: String(board.id),
})
}
return list
},
async getBoards(retryNum = 0) {
// if (++retryNum > 3) return Promise.reject(new Error('try max num'))
// let response
// try {
// response = await this.getBoardsData()
// } catch (error) {
// return this.getBoards(retryNum)
// }
// // console.log(response.body)
// if (response.statusCode !== 200 || response.body.code !== 0) return this.getBoards(retryNum)
// const list = this.filterBoardsData(response.body.data.topList)
// // console.log(list)
// this.list = list
// return {
// list,
// source: 'tx',
// }
this.list = boardList
return {
list: boardList,
source: 'tx',
}
},
getList(bangid, page, retryNum = 0) {
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
bangid = parseInt(bangid)
let info = this.periods[bangid]
let p = info ? Promise.resolve(info.period) : this.getPeriods(bangid)
return p.then(period => {
return this.getData(this.getUrl(type.bangid, period, this.limit)).then(data => {
return this.getData(this.getUrl(bangid, period, this.limit)).then(data => {
// console.log(data)
if (data.code !== 0) return Promise.reject()
if (data.code !== 0) return this.getList(bangid, page, retryNum)
return {
total: data.toplist.data.songInfoList.length,
list: this.filterData(data.toplist.data.songInfoList),
+1 -1
View File
@@ -9,7 +9,7 @@ export default {
_requestObj_listDetail: null,
_requestObj_listDetailLink: null,
limit_list: 36,
limit_song: 10000000,
limit_song: 100000,
successCode: 0,
sortList: [
{
+133 -93
View File
@@ -1,8 +1,50 @@
import { httpGet, cancelHttp } from '../../request'
import { formatPlayTime } from '../../index'
import { weapi } from './utils/crypto'
import { httpFetch } from '../../request'
import musicDetailApi from './musicDetail'
const topList = [
{ id: 'wy__19723756', bangid: '19723756', name: '云音乐飙升榜' },
{ id: 'wy__3778678', bangid: '3778678', name: '云音乐热歌榜' },
{ id: 'wy__3779629', bangid: '3779629', name: '云音乐新歌榜' },
{ id: 'wy__2884035', bangid: '2884035', name: '云音乐原创榜' },
{ id: 'wy__2250011882', bangid: '2250011882', name: '抖音排行榜' },
{ id: 'wy__1978921795', bangid: '1978921795', name: '云音乐电音榜' },
{ id: 'wy__4395559', bangid: '4395559', name: '华语金曲榜' },
{ id: 'wy__71384707', bangid: '71384707', name: '云音乐古典音乐榜' },
{ id: 'wy__10520166', bangid: '10520166', name: '云音乐国电榜' },
{ id: 'wy__2006508653', bangid: '2006508653', name: '电竞音乐榜' },
{ id: 'wy__991319590', bangid: '991319590', name: '云音乐说唱榜' },
{ id: 'wy__180106', bangid: '180106', name: 'UK排行榜周榜' },
{ id: 'wy__60198', bangid: '60198', name: '美国Billboard周榜' },
{ id: '21845217', bangid: '21845217', name: 'KTV嗨榜' },
{ id: 'wy__11641012', bangid: '11641012', name: 'iTunes榜' },
{ id: 'wy__120001', bangid: '120001', name: 'Hit FM Top榜' },
{ id: 'wy__60131', bangid: '60131', name: '日本Oricon周榜' },
{ id: 'wy__3733003', bangid: '3733003', name: '韩国Melon排行榜周榜' },
{ id: 'wy__60255', bangid: '60255', name: '韩国Mnet排行榜周榜' },
{ id: 'wy__46772709', bangid: '46772709', name: '韩国Melon原声周榜' },
{ id: 'wy__64016', bangid: '64016', name: '中国TOP排行榜(内地榜)' },
{ id: 'wy__112504', bangid: '112504', name: '中国TOP排行榜(港台榜)' },
{ id: 'wy__3112516681', bangid: '3112516681', name: '中国新乡村音乐排行榜' },
{ id: 'wy__10169002', bangid: '10169002', name: '香港电台中文歌曲龙虎榜' },
{ id: 'wy__27135204', bangid: '27135204', name: '法国 NRJ EuroHot 30周榜' },
{ id: 'wy__1899724', bangid: '1899724', name: '中国嘻哈榜' },
{ id: 'wy__112463', bangid: '112463', name: '台湾Hito排行榜' },
{ id: 'wy__3812895', bangid: '3812895', name: 'Beatport全球电子舞曲榜' },
{ id: 'wy__2617766278', bangid: '2617766278', name: '新声榜' },
{ id: 'wy__745956260', bangid: '745956260', name: '云音乐韩语榜' },
{ id: 'wy__2847251561', bangid: '2847251561', name: '说唱TOP榜' },
{ id: 'wy__2023401535', bangid: '2023401535', name: '英国Q杂志中文版周榜' },
{ id: 'wy__2809513713', bangid: '2809513713', name: '云音乐欧美热歌榜' },
{ id: 'wy__2809577409', bangid: '2809577409', name: '云音乐欧美新歌榜' },
{ id: 'wy__71385702', bangid: '71385702', name: '云音乐ACG音乐榜' },
{ id: 'wy__3001835560', bangid: '3001835560', name: '云音乐ACG动画榜' },
{ id: 'wy__3001795926', bangid: '3001795926', name: '云音乐ACG游戏榜' },
{ id: 'wy__3001890046', bangid: '3001890046', name: '云音乐ACG VOCALOID榜' },
]
export default {
limit: 300,
limit: 100000,
list: [
{
id: 'wybsb',
@@ -61,102 +103,100 @@ export default {
regExps: {
list: /<textarea id="song-list-pre-data" style="display:none;">(.+?)<\/textarea>/,
},
_cancelRequestObj: null,
_cancelPromiseCancelFn: null,
getData(url) {
if (this._cancelRequestObj != null) {
cancelHttp(this._cancelRequestObj)
this._cancelPromiseCancelFn(new Error('取消http请求'))
}
return new Promise((resolve, reject) => {
this._cancelPromiseCancelFn = reject
this._cancelRequestObj = httpGet(url, (err, resp, body) => {
this._cancelRequestObj = null
this._cancelPromiseCancelFn = null
if (err) {
console.log(err)
reject(err)
}
resolve(body)
})
_requestBoardsObj: null,
_requestBoardsDetailObj: null,
getBoardsData() {
if (this._requestBoardsObj) this._requestBoardsObj.cancelHttp()
this._requestBoardsObj = httpFetch('https://music.163.com/weapi/toplist', {
method: 'post',
form: weapi({}),
})
return this._requestBoardsObj.promise
},
getSinger(singers) {
let arr = []
singers.forEach(singer => {
arr.push(singer.name)
getData(id) {
if (this._requestBoardsDetailObj) this._requestBoardsDetailObj.cancelHttp()
this._requestBoardsDetailObj = httpFetch('https://music.163.com/weapi/v3/playlist/detail', {
method: 'post',
form: weapi({
id,
n: 100000,
p: 1,
}),
})
return arr.join('、')
return this._requestBoardsDetailObj.promise
},
filterData(rawList) {
filterBoardsData(rawList) {
// console.log(rawList)
return rawList.map(item => {
const types = []
const _types = {}
let size
switch (item.privilege.maxbr) {
case 999000:
size = null
types.push({ type: 'flac', size })
_types.flac = {
size,
}
case 320000:
size = null
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
// case 192000:
// case 190000:
// size = null
// types.push({ type: '192k', size })
// _types['192k'] = {
// size,
// }
// case '160000':
default:
size = null
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
break
}
types.reverse()
return {
singer: this.getSinger(item.artists),
name: item.name,
albumName: item.album.name,
albumId: item.album.id,
source: 'wy',
interval: formatPlayTime(item.duration / 1000),
songmid: item.id,
img: item.album.picUrl,
lrc: null,
types,
_types,
typeUrl: {},
}
})
let list = []
for (const board of rawList) {
// 排除 MV榜
// if (board.id == 201) continue
list.push({
id: 'wy__' + board.id,
name: board.name,
bangid: String(board.id),
})
}
return list
},
getList(id, page) {
let type = this.list.find(s => s.id === id)
if (!type) return Promise.reject()
return this.getData(this.getUrl(type.bangid)).then(html => {
let result = html.match(this.regExps.list)
if (!result) return Promise.reject()
const list = this.filterData(JSON.parse(RegExp.$1))
return {
total: list.length,
list,
limit: this.limit,
page,
source: 'tx',
async getBoards(retryNum = 0) {
// if (++retryNum > 3) return Promise.reject(new Error('try max num'))
// let response
// try {
// response = await this.getBoardsData()
// } catch (error) {
// return this.getBoards(retryNum)
// }
// console.log(response.body)
// if (response.statusCode !== 200 || response.body.code !== 200) return this.getBoards(retryNum)
// const list = this.filterBoardsData(response.body.list)
// console.log(list)
// console.log(JSON.stringify(list))
// this.list = list
// return {
// list,
// source: 'wy',
// }
this.list = topList
return {
list: topList,
source: 'wy',
}
},
async getList(bangid, page, retryNum = 0) {
if (++retryNum > 6) return Promise.reject(new Error('try max num'))
// console.log(bangid)
let resp
try {
resp = await this.getData(bangid)
} catch (err) {
if (err.message == 'try max num') {
throw err
} else {
return this.getList(bangid, page, retryNum)
}
})
}
if (resp.statusCode !== 200 || resp.body.code !== 200) return this.getList(bangid, page, retryNum)
// console.log(resp.body)
let musicDetail
try {
musicDetail = await musicDetailApi.getList(resp.body.playlist.trackIds.map(trackId => trackId.id))
} catch (err) {
console.log(err)
if (err.message == 'try max num') {
throw err
} else {
return this.getList(bangid, page, retryNum)
}
}
// console.log(musicDetail)
return {
total: musicDetail.list.length,
list: musicDetail.list,
limit: this.limit,
page,
source: 'wy',
}
},
}
@@ -0,0 +1,90 @@
import { httpFetch } from '../../request'
import { weapi } from './utils/crypto'
import { formatPlayTime, sizeFormate } from '../../.'
// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/song_detail.js
export default {
_requestObj: null,
getSinger(singers) {
let arr = []
singers.forEach(singer => {
arr.push(singer.name)
})
return arr.join('、')
},
filterList({ songs, privileges }) {
// console.log(tracks, privileges)
const list = []
songs.forEach((item, index) => {
const types = []
const _types = {}
let size
let privilege = privileges[index]
if (privilege.id !== item.id) privilege = privileges.find(p => p.id === item.id)
if (!privilege) return
switch (privilege.maxbr) {
case 999000:
size = null
types.push({ type: 'flac', size })
_types.flac = {
size,
}
case 320000:
if (item.h) {
size = sizeFormate(item.h.size)
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
}
case 128000:
if (item.l) {
size = sizeFormate(item.l.size)
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
}
}
types.reverse()
list.push({
singer: this.getSinger(item.ar),
name: item.name,
albumName: item.al.name,
albumId: item.al.id,
source: 'wy',
interval: formatPlayTime(item.dt / 1000),
songmid: item.id,
img: item.al.picUrl,
lrc: null,
types,
_types,
typeUrl: {},
})
})
return list
},
async getList(ids = [], retryNum = 0) {
if (this._requestObj) this._requestObj.cancelHttp()
if (retryNum > 2) return Promise.reject(new Error('try max num'))
const _requestObj = httpFetch('https://music.163.com/weapi/v3/song/detail', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36',
origin: 'https://music.163.com',
},
form: weapi({
c: '[' + ids.map(id => ('{"id":' + id + '}')).join(',') + ']',
ids: '[' + ids.join(',') + ']',
}),
})
const { body, statusCode } = await _requestObj.promise
if (statusCode != 200 || body.code !== 200) throw new Error('获取歌曲详情失败')
// console.log(body)
return { source: 'wy', list: this.filterList(body) }
},
}
+18 -4
View File
@@ -6,6 +6,7 @@
import { weapi, linuxapi } from './utils/crypto'
import { httpFetch } from '../../request'
import { formatPlayTime, sizeFormate } from '../../index'
import musicDetailApi from './musicDetail'
export default {
_requestObj_tags: null,
@@ -80,13 +81,26 @@ export default {
},
}),
})
const { body } = await this._requestObj_listDetail.promise
if (body.code !== this.successCode) return this.getListDetail(id, page, ++tryNum)
const { statusCode, body } = await this._requestObj_listDetail.promise
if (statusCode !== 200 || body.code !== this.successCode) return this.getListDetail(id, page, ++tryNum)
console.log(body)
let musicDetail
try {
musicDetail = await musicDetailApi.getList(body.playlist.trackIds.map(trackId => trackId.id))
} catch (err) {
console.log(err)
if (err.message == 'try max num') {
throw err
} else {
return this.getListDetail(id, page, ++tryNum)
}
}
console.log(musicDetail)
return {
list: this.filterListDetail(body),
list: musicDetail.list,
page,
limit: this.limit_song,
total: body.playlist.tracks.length,
total: musicDetail.list.length,
source: 'wy',
info: {
play_count: this.formatPlayCount(body.playlist.playCount),
+67 -5
View File
@@ -2,6 +2,8 @@ import { xmRequest } from './util'
import { formatPlayTime, sizeFormate } from '../../index'
// import jshtmlencode from 'js-htmlencode'
let boardList = [{ id: 'xm__102', name: '新歌榜', bangid: '102' }, { id: 'xm__103', name: '热歌榜', bangid: '103' }, { id: 'xm__104', name: '原创榜', bangid: '104' }, { id: 'xm__306', name: 'K歌榜', bangid: '306' }, { id: 'xm__332', name: '抖音热歌榜', bangid: '332' }, { id: 'xm__305', name: '歌单收录榜', bangid: '305' }, { id: 'xm__327', name: '趴间热歌榜', bangid: '327' }, { id: 'xm__324', name: '影视原声榜', bangid: '324' }, { id: 'xm__204', name: '美国Billboard单曲榜', bangid: '204' }, { id: 'xm__206', name: '韩国MNET音乐排行榜', bangid: '206' }, { id: 'xm__201', name: 'Hito 中文排行榜', bangid: '201' }, { id: 'xm__203', name: '英国UK单曲榜', bangid: '203' }, { id: 'xm__205', name: 'oricon公信单曲榜', bangid: '205' }, { id: 'xm__328', name: '美国iTunes榜', bangid: '328' }, { id: 'xm__329', name: 'Beatport电音榜', bangid: '329' }, { id: 'xm__330', name: '香港商业电台榜', bangid: '330' }]
export default {
limit: 200,
list: [
@@ -56,7 +58,13 @@ export default {
bangid: '324',
},
],
requestBoardsObj: null,
requestObj: null,
getBoardsData() {
if (this.requestBoardsObj) this.requestBoardsObj.cancelHttp()
this.requestBoardsObj = xmRequest('/api/billboard/getBillboards')
return this.requestBoardsObj.promise
},
getData(id) {
if (this.requestObj) this.requestObj.cancelHttp()
this.requestObj = xmRequest('/api/billboard/getBillboardDetail', { billboardId: id })
@@ -126,12 +134,66 @@ export default {
return list
},
getList(id, page, retryNum = 0) {
filterBoardsData(rawList) {
// console.log(rawList)
let list = []
if (rawList.xiamiBillboards) {
for (const board of rawList.xiamiBillboards) {
if (board.itemType != 1) continue
list.push({
id: 'xm__' + board.billboardId,
name: board.name,
bangid: String(board.billboardId),
})
}
}
if (rawList.spBillboards) {
for (const board of rawList.spBillboards) {
if (board.itemType != 1) continue
list.push({
id: 'xm__' + board.billboardId,
name: board.name,
bangid: String(board.billboardId),
})
}
}
if (rawList.globalBillboards) {
for (const board of rawList.globalBillboards) {
if (board.itemType != 1) continue
list.push({
id: 'xm__' + board.billboardId,
name: board.name,
bangid: String(board.billboardId),
})
}
}
return list
},
async getBoards(retryNum = 0) {
// if (++retryNum > 3) return Promise.reject(new Error('try max num'))
// let response
// try {
// response = await this.getBoardsData()
// } catch (error) {
// return this.getBoards(retryNum)
// }
// if (response.statusCode !== 200 || response.body.code !== 'SUCCESS') return this.getBoards(retryNum)
// const list = this.filterBoardsData(response.body.result.data)
// this.list = list
// return {
// list,
// source: 'xm',
// }
this.list = boardList
return {
list: boardList,
source: 'xm',
}
},
getList(bangid, page, retryNum = 0) {
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
let type = this.list.find(s => s.id === id)
if (!type) return Promise.reject()
return this.getData(type.bangid).then(({ statusCode, body }) => {
if (statusCode !== 200 || body.code !== 'SUCCESS') return this.getList(id, page, retryNum)
return this.getData(bangid).then(({ statusCode, body }) => {
if (statusCode !== 200 || body.code !== 'SUCCESS') return this.getList(bangid, page, retryNum)
// console.log(body)
const list = this.filterData(body.result.data.billboard.songs)
+2 -2
View File
@@ -67,11 +67,11 @@ const buildHttpPromose = (url, options) => {
})
obj.cancelHttp = () => {
if (!obj.requestObj) return obj.isCancelled = true
obj.cancelFn(new Error(requestMsg.cancelRequest))
cancelHttp(obj.requestObj)
obj.requestObj = null
obj.cancelFn = null
obj.promise = obj.cancelHttp = null
obj.cancelFn(new Error(requestMsg.cancelRequest))
obj.cancelFn = null
}
return obj
}
+16 -10
View File
@@ -1,17 +1,17 @@
<template lang="pug">
div(:class="$style.leaderboard")
//- div(:class="$style.header")
material-tab(:class="$style.tab" :list="types" align="left" item-key="id" item-name="name" v-model="tabId")
material-select(:class="$style.select" :list="sourceInfo.sources" item-key="id" item-name="name" v-model="source")
material-tab(:class="$style.tab" :list="boards" align="left" item-key="id" item-name="name" v-model="tabId")
material-select(:class="$style.select" :list="sources.sources" item-key="id" item-name="name" v-model="source")
div(:class="$style.lists" ref="dom_lists")
div(:class="$style.listsSelect")
//- h2(:class="$style.listsTitle") {{$t('core.aside.my_list')}}
material-selection(:class="$style.select" :list="sourceInfo.sources" item-key="id" item-name="name" v-model="source")
material-selection(:class="$style.select" :list="sources" item-key="id" item-name="name" v-model="source")
//- button(:class="$style.listsAdd" @click="handleShowNewList" :title="$t('view.list.lists_new_list_btn')")
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='70%' viewBox='0 0 24 24' space='preserve')
use(xlink:href='#icon-list-add')
ul.scroll(:class="$style.listsContent" ref="dom_lists_list")
li(:class="[$style.listsItem, item.id == tabId ? $style.active : null]" :title="item.name" v-for="item in types" :key="item.id" @click="handleToggleList(item.id)")
li(:class="[$style.listsItem, item.id == tabId ? $style.active : null]" :title="item.name" v-for="item in boardList" :key="item.id" @click="handleToggleList(item.id)")
span(:class="$style.listsLabel") {{item.name}}
div(:class="$style.list")
material-song-list(v-model="selectdData" :rowWidth="{r1: '5%', r2: 'auto', r3: '22%', r4: '22%', r5: '9%', r6: '15%'}" @action="handleSongListAction" :source="source" :page="page" :limit="info.limit" :total="info.total" :noItem="$t('material.song_list.loding_list')" :list="list")
@@ -40,23 +40,29 @@ export default {
},
computed: {
...mapGetters(['setting']),
...mapGetters('leaderboard', ['sourceInfo', 'list', 'info']),
...mapGetters('leaderboard', ['sources', 'boards', 'list', 'info']),
...mapGetters('list', ['defaultList']),
types() {
return this.source ? this.sourceInfo.sourceList[this.source] : []
boardList() {
return this.source && this.boards[this.source] ? this.boards[this.source] : []
},
},
watch: {
tabId(n, o) {
this.setLeaderboard({ tabId: n })
if (!o && this.page !== 1) return
if (!n || (!o && this.page !== 1)) return
this.getList(1).then(() => {
this.page = this.info.page
})
},
source(n, o) {
this.setLeaderboard({ source: n })
if (o) this.tabId = this.types[0] && this.types[0].id
if (o) this.tabId = null
this.getBoardsList().then(() => {
if (this.tabId != null) return
this.$nextTick(() => {
this.tabId = this.boardList[0] && this.boardList[0].id
})
})
},
},
mounted() {
@@ -66,7 +72,7 @@ export default {
},
methods: {
...mapMutations(['setLeaderboard']),
...mapActions('leaderboard', ['getList']),
...mapActions('leaderboard', ['getBoardsList', 'getList']),
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
...mapMutations('list', ['listAdd', 'listAddMultiple']),
...mapMutations('player', ['setList']),