diff --git a/package-lock.json b/package-lock.json index d91798b1..069fd136 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2262,74 +2262,6 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, - "autoprefixer": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.0.tgz", - "integrity": "sha512-D96ZiIHXbDmU02dBaemyAg53ez+6F5yZmapmgKcjm35yEe1uVDYI8hGW3VYoGRaG290ZFf91YxHrR518vC0u/A==", - "dev": true, - "requires": { - "browserslist": "^4.12.0", - "caniuse-lite": "^1.0.30001061", - "chalk": "^2.4.2", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^7.0.30", - "postcss-value-parser": "^4.1.0" - }, - "dependencies": { - "caniuse-lite": { - "version": "1.0.30001062", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001062.tgz", - "integrity": "sha512-ei9ZqeOnN7edDrb24QfJ0OZicpEbsWxv7WusOiQGz/f2SfvBgHHbOEwBJ8HKGVSyx8Z6ndPjxzR6m0NQq+0bfw==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "postcss": { - "version": "7.0.30", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.30.tgz", - "integrity": "sha512-nu/0m+NtIzoubO+xdAlwZl/u5S5vi/y6BCsoL8D+8IxsD3XvBS8X4YEADNIVXKVuQvduiucnRv+vPIqj56EGMQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -10568,12 +10500,6 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, "normalize-url": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", @@ -10617,12 +10543,6 @@ "boolbase": "~1.0.0" } }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", diff --git a/package.json b/package.json index 43a9fc3f..83514f19 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-formatter-friendly --fix src" }, "browserslist": [ - "Electron 8.2.5" + "Electron 9.0.0" ], "engines": { "node": ">= 12" @@ -158,7 +158,6 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/polyfill": "^7.8.7", "@babel/preset-env": "^7.9.6", - "autoprefixer": "^9.8.0", "babel-eslint": "^10.1.0", "babel-loader": "^8.1.0", "babel-minify-webpack-plugin": "^0.3.1", diff --git a/postcss.config.js b/postcss.config.js index 260098a9..7dd1e990 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,4 +1,4 @@ -const autoprefixer = require('autoprefixer') +// const autoprefixer = require('autoprefixer') const pxtorem = require('postcss-pxtorem') module.exports = { @@ -28,6 +28,6 @@ module.exports = { minPixelValue: 0, exclude: [/node_modules/i], }), - autoprefixer(), + // autoprefixer(), ], } diff --git a/publish/changeLog.md b/publish/changeLog.md index 118e68ed..89312420 100644 --- a/publish/changeLog.md +++ b/publish/changeLog.md @@ -4,6 +4,7 @@ - 新增当前音频输出设备改变时是否暂停播放的设置,默认关闭 - 新增歌曲列表右键菜单 - 新增自定义列表,创建列表的按钮在表头`#`左侧,鼠标移上去才会显示;编辑列表名字时,按`ESC`键可快速取消编辑,按回车键或使输入框失去焦点即可保存列表名字,右击列表可编辑已创建的列表,“试听列表”与“我的收藏”两个列表固定不可编辑 +- 改变排行榜布局,新增更多排行榜 ### 优化 @@ -18,8 +19,14 @@ - 修复某些情况下无法开始下载任务的问题 - 修复 tab 组件边框溢出问题 - 修复错误更新试听列表外的歌曲时间的问题 +- 修复网易音乐源歌单、排行榜歌曲列表加载显示的数量与实际不对的问题 +- 修复歌曲图片链接没有扩展名的情况下无法嵌入图片的问题 ### 更变 - 修改设置-列表-是否显示歌曲源的默认设置为选中(该变更不影响之前的设置) - 移除浮动按钮,现在在多选完成后可鼠标右击随意一项在弹出的右键菜单中进行原来悬浮按钮的操作 + +### 其他 + +- 更新 Electron 到 9.0.0 diff --git a/src/main/index.dev.js b/src/main/index.dev.js index 9851a56c..b75acc2a 100644 --- a/src/main/index.dev.js +++ b/src/main/index.dev.js @@ -16,7 +16,7 @@ electronDebug({ // Install `vue-devtools` electron.app.on('ready', () => { installExtension(VUEJS_DEVTOOLS) - .then(name => console.log(`Added Extension: ${name}`)) + .then(info => console.log(`Added Extension: ${info.name}`)) .catch(err => console.log('An error occurred: ', err)) }) diff --git a/src/main/rendererEvents/index.js b/src/main/rendererEvents/index.js index 29d12ecf..669ea6aa 100644 --- a/src/main/rendererEvents/index.js +++ b/src/main/rendererEvents/index.js @@ -15,3 +15,5 @@ require('./tray') require('./updateSetting') require('./xm_verify') + +require('./kw_decodeLyric') diff --git a/src/main/rendererEvents/kw_decodeLyric.js b/src/main/rendererEvents/kw_decodeLyric.js new file mode 100644 index 00000000..c8ead46d --- /dev/null +++ b/src/main/rendererEvents/kw_decodeLyric.js @@ -0,0 +1,45 @@ +const { inflate } = require('zlib') +const iconv = require('iconv-lite') +const { mainHandle } = require('../../common/ipc') + +const handleInflate = data => new Promise((resolve, reject) => { + inflate(data, (err, result) => { + if (err) return reject(err) + resolve(result) + }) +}) + +const buf_key = Buffer.from('yeelion') +const buf_key_len = buf_key.length + +const decodeLyric = async(buf, isGetLyricx) => { + // const info = buf.slice(0, index).toString() + // if (!info.startsWith('tp=content')) return null + // const isLyric = info.includes('\r\nlrcx=0\r\n') + if (buf.toString('utf8', 0, 10) != 'tp=content') return '' + // const index = buf.indexOf('\r\n\r\n') + 4 + const lrcData = await handleInflate(buf.slice(buf.indexOf('\r\n\r\n') + 4)) + + if (!isGetLyricx) return iconv.decode(lrcData, 'gb18030') + + const buf_str = Buffer.from(lrcData.toString(), 'base64') + const buf_str_len = buf_str.length + const output = new Uint16Array(buf_str_len) + let i = 0 + while (i < buf_str_len) { + let j = 0 + while (j < buf_key_len && i < buf_str_len) { + output[i] = buf_str[i] ^ buf_key[j] + i++ + j++ + } + } + + return iconv.decode(Buffer.from(output), 'gb18030') +} + +mainHandle('kw_decodeLyric', async(event, { lrcBase64, isGetLyricx }) => { + if (!global.mainWindow) throw new Error('mainwindow is undefined') + const lrc = await decodeLyric(Buffer.from(lrcBase64, 'base64'), isGetLyricx) + return Buffer.from(lrc).toString('base64') +}) diff --git a/src/main/utils/flacMeta.js b/src/main/utils/flacMeta.js index 9be44505..ab9a18ba 100644 --- a/src/main/utils/flacMeta.js +++ b/src/main/utils/flacMeta.js @@ -64,7 +64,8 @@ module.exports = (filePath, meta) => { if (!/^http/.test(picUrl)) { return writeMeta(filePath, meta) } - let picPath = filePath.replace(/\.flac$/, '') + path.extname(picUrl).replace(extReg, '$1') + let ext = path.extname(picUrl) + let picPath = filePath.replace(/\.flac$/, '') + (ext ? ext.replace(extReg, '$1') : '.jpg') request(picUrl) .on('response', respones => { diff --git a/src/main/utils/mp3Meta.js b/src/main/utils/mp3Meta.js index bded0892..2405a49d 100644 --- a/src/main/utils/mp3Meta.js +++ b/src/main/utils/mp3Meta.js @@ -10,7 +10,8 @@ module.exports = (filePath, meta) => { delete meta.APIC return NodeID3.write(meta, filePath) } - let picPath = filePath.replace(/\.mp3$/, '') + path.extname(meta.APIC).replace(extReg, '$1') + let ext = path.extname(meta.APIC) + let picPath = filePath.replace(/\.mp3$/, '') + (ext ? ext.replace(extReg, '$1') : '.jpg') request(meta.APIC) .on('response', respones => { if (respones.statusCode !== 200 && respones.statusCode != 206) { diff --git a/src/renderer/lang/cns/view/setting.json b/src/renderer/lang/cns/view/setting.json index aa5adcf1..a45fbfad 100644 --- a/src/renderer/lang/cns/view/setting.json +++ b/src/renderer/lang/cns/view/setting.json @@ -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": "是否显示歌曲源", diff --git a/src/renderer/lang/cnt/view/setting.json b/src/renderer/lang/cnt/view/setting.json index 7668b2aa..5b0089fc 100644 --- a/src/renderer/lang/cnt/view/setting.json +++ b/src/renderer/lang/cnt/view/setting.json @@ -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": "是否顯示歌曲源(僅對我的音樂分類有效)", diff --git a/src/renderer/lang/en/view/setting.json b/src/renderer/lang/en/view/setting.json index 2e94bccb..077fbb14 100644 --- a/src/renderer/lang/en/view/setting.json +++ b/src/renderer/lang/en/view/setting.json @@ -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", diff --git a/src/renderer/store/modules/leaderboard.js b/src/renderer/store/modules/leaderboard.js index df99c24c..a497c3e4 100644 --- a/src/renderer/store/modules/leaderboard.js +++ b/src/renderer/store/modules/leaderboard.js @@ -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 diff --git a/src/renderer/store/modules/songList.js b/src/renderer/store/modules/songList.js index ff516871..1bf8dd93 100644 --- a/src/renderer/store/modules/songList.js +++ b/src/renderer/store/modules/songList.js @@ -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) { diff --git a/src/renderer/utils/music/bd/leaderboard.js b/src/renderer/utils/music/bd/leaderboard.js index 63832aae..af7c257b 100644 --- a/src/renderer/utils/music/bd/leaderboard.js +++ b/src/renderer/utils/music/bd/leaderboard.js @@ -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 { diff --git a/src/renderer/utils/music/bd/songList.js b/src/renderer/utils/music/bd/songList.js index 63bbdce1..7907c755 100644 --- a/src/renderer/utils/music/bd/songList.js +++ b/src/renderer/utils/music/bd/songList.js @@ -8,7 +8,7 @@ export default { _requestObj_listRecommend: null, _requestObj_listDetail: null, limit_list: 20, - limit_song: 1000, + limit_song: 10000, successCode: 22000, sortList: [ { diff --git a/src/renderer/utils/music/kg/leaderboard.js b/src/renderer/utils/music/kg/leaderboard.js index 76e4342a..26839c15 100644 --- a/src/renderer/utils/music/kg/leaderboard.js +++ b/src/renderer/utils/music/kg/leaderboard.js @@ -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) diff --git a/src/renderer/utils/music/kg/songList.js b/src/renderer/utils/music/kg/songList.js index 3f11b479..3c17f9e6 100644 --- a/src/renderer/utils/music/kg/songList.js +++ b/src/renderer/utils/music/kg/songList.js @@ -8,7 +8,7 @@ export default { _requestObj_list: null, _requestObj_listRecommend: null, _requestObj_listDetail: null, - listDetailLimit: 100, + listDetailLimit: 10000, currentTagInfo: { id: undefined, info: undefined, diff --git a/src/renderer/utils/music/kw/index.js b/src/renderer/utils/music/kw/index.js index a6321fd0..21d69b8e 100644 --- a/src/renderer/utils/music/kw/index.js +++ b/src/renderer/utils/music/kw/index.js @@ -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 => { diff --git a/src/renderer/utils/music/kw/leaderboard.js b/src/renderer/utils/music/kw/leaderboard.js index d0373b84..3ca926dc 100644 --- a/src/renderer/utils/music/kw/leaderboard.js +++ b/src/renderer/utils/music/kw/leaderboard.js @@ -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, diff --git a/src/renderer/utils/music/kw/lyric.js b/src/renderer/utils/music/kw/lyric.js index a5753ebe..191253e2 100644 --- a/src/renderer/utils/music/kw/lyric.js +++ b/src/renderer/utils/music/kw/lyric.js @@ -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>[\s\S]+(.+?)<\/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 }, diff --git a/src/renderer/utils/music/kw/songList.js b/src/renderer/utils/music/kw/songList.js index f507bc03..fe2f6daa 100644 --- a/src/renderer/utils/music/kw/songList.js +++ b/src/renderer/utils/music/kw/songList.js @@ -8,7 +8,7 @@ export default { _requestObj_list: null, _requestObj_listDetail: null, limit_list: 25, - limit_song: 1000, + limit_song: 10000, successCode: 200, sortList: [ { diff --git a/src/renderer/utils/music/kw/util.js b/src/renderer/utils/music/kw/util.js index 0d9f34ac..c923455f 100644 --- a/src/renderer/utils/music/kw/util.js +++ b/src/renderer/utils/music/kw/util.js @@ -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) diff --git a/src/renderer/utils/music/mg/leaderboard.js b/src/renderer/utils/music/mg/leaderboard.js index 4a938de9..32602ffb 100644 --- a/src/renderer/utils/music/mg/leaderboard.js +++ b/src/renderer/utils/music/mg/leaderboard.js @@ -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', } diff --git a/src/renderer/utils/music/mg/songList.js b/src/renderer/utils/music/mg/songList.js index e09959e8..0fa8ec33 100644 --- a/src/renderer/utils/music/mg/songList.js +++ b/src/renderer/utils/music/mg/songList.js @@ -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 => ({ diff --git a/src/renderer/utils/music/tx/leaderboard.js b/src/renderer/utils/music/tx/leaderboard.js index f2e5d4ad..78fdb525 100644 --- a/src/renderer/utils/music/tx/leaderboard.js +++ b/src/renderer/utils/music/tx/leaderboard.js @@ -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¬ice=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), diff --git a/src/renderer/utils/music/tx/songList.js b/src/renderer/utils/music/tx/songList.js index 092a5a91..bfa1525b 100644 --- a/src/renderer/utils/music/tx/songList.js +++ b/src/renderer/utils/music/tx/songList.js @@ -9,7 +9,7 @@ export default { _requestObj_listDetail: null, _requestObj_listDetailLink: null, limit_list: 36, - limit_song: 10000000, + limit_song: 100000, successCode: 0, sortList: [ { diff --git a/src/renderer/utils/music/wy/leaderboard.js b/src/renderer/utils/music/wy/leaderboard.js index fb291529..02a9218e 100644 --- a/src/renderer/utils/music/wy/leaderboard.js +++ b/src/renderer/utils/music/wy/leaderboard.js @@ -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: /