diff --git a/publish/changeLog.md b/publish/changeLog.md index 2e5aecd7..b4ce8b20 100644 --- a/publish/changeLog.md +++ b/publish/changeLog.md @@ -3,6 +3,9 @@ - 新增“我的收藏”本地播放列表 - 新增缓存清理功能,可到**设置-其他**查看与清理软件缓存 - 新增QQ音乐源搜索 +- 新增咪咕源搜索 +- 新增咪咕源歌单 +- 新增咪咕源排行榜 #### 优化 diff --git a/src/renderer/utils/music/api-source.js b/src/renderer/utils/music/api-source.js index bcf67b7d..e1163037 100644 --- a/src/renderer/utils/music/api-source.js +++ b/src/renderer/utils/music/api-source.js @@ -4,6 +4,7 @@ import tx_api_test from './tx/api-test' import kg_api_test from './kg/api-test' import wy_api_test from './wy/api-test' import bd_api_test from './bd/api-test' +import mg_api_test from './mg/api-test' // import kw_api_internal from './kw/api-internal' // import tx_api_internal from './tx/api-internal' // import kg_api_internal from './kg/api-internal' @@ -16,6 +17,7 @@ const apis = { kg_api_test, wy_api_test, bd_api_test, + mg_api_test, // kw_api_internal, // tx_api_internal, // kg_api_internal, @@ -46,6 +48,8 @@ export default source => { return getAPI('wy') case 'bd': return getAPI('bd') + case 'mg': + return getAPI('mg') default: return getAPI('kw') } diff --git a/src/renderer/utils/music/index.js b/src/renderer/utils/music/index.js index 57fa475b..108c3abd 100644 --- a/src/renderer/utils/music/index.js +++ b/src/renderer/utils/music/index.js @@ -2,6 +2,7 @@ import kw from './kw' import kg from './kg' import tx from './tx' import wy from './wy' +import mg from './mg' import bd from './bd' export default { sources: [ @@ -21,6 +22,10 @@ export default { name: '网易音乐', id: 'wy', }, + { + name: '咪咕音乐', + id: 'mg', + }, { name: '百度音乐', id: 'bd', @@ -30,5 +35,6 @@ export default { kg, tx, wy, + mg, bd, } diff --git a/src/renderer/utils/music/kg/lyric.js b/src/renderer/utils/music/kg/lyric.js index 3b3bb45e..dab3fc00 100644 --- a/src/renderer/utils/music/kg/lyric.js +++ b/src/renderer/utils/music/kg/lyric.js @@ -11,7 +11,7 @@ export default { } return parseInt(intv) }, - getLyric(songInfo, tryNum) { + getLyric(songInfo, tryNum = 0) { let requestObj = httpFetch(`http://m.kugou.com/app/i/krc.php?cmd=100&keyword=${encodeURIComponent(songInfo.name)}&hash=${songInfo.hash}&timelength=${songInfo._interval || this.getIntv(songInfo.interval)}&d=0.38664927426725626`, { headers: { 'KG-RC': 1, @@ -22,7 +22,7 @@ export default { requestObj.promise = requestObj.promise.then(({ body, statusCode }) => { if (statusCode !== 200) { if (tryNum > 5) return Promise.reject('歌词获取失败') - let tryRequestObj = this.getLyric(songInfo, tryNum) + let tryRequestObj = this.getLyric(songInfo, ++tryNum) requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) return tryRequestObj.promise } diff --git a/src/renderer/utils/music/kw/songList.js b/src/renderer/utils/music/kw/songList.js index 6bb23cb9..5559d1fe 100644 --- a/src/renderer/utils/music/kw/songList.js +++ b/src/renderer/utils/music/kw/songList.js @@ -211,7 +211,7 @@ export default { }) }, getTags() { - return Promise.all([this.getTag(), this.getHotTag()]).then(([tags, hotTag]) => ({ tags, hotTag })) + return Promise.all([this.getTag(), this.getHotTag()]).then(([tags, hotTag]) => ({ tags, hotTag, source: 'kw' })) }, } diff --git a/src/renderer/utils/music/mg/api-test.js b/src/renderer/utils/music/mg/api-test.js new file mode 100644 index 00000000..02446db5 --- /dev/null +++ b/src/renderer/utils/music/mg/api-test.js @@ -0,0 +1,20 @@ +import { httpFetch } from '../../request' +import { requestMsg } from '../../message' +import { headers, timeout } from '../options' + +const api_test = { + getMusicUrl(songInfo, type) { + const requestObj = httpFetch(`http://ts.tempmusic.tk/url/mg/${songInfo.copyrightId}/${type}`, { + method: 'get', + timeout, + headers, + family: 4, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + return body.code === 0 ? Promise.resolve({ type, url: encodeURI(body.data) }) : Promise.reject(new Error(requestMsg.fail)) + }) + return requestObj + }, +} + +export default api_test diff --git a/src/renderer/utils/music/mg/index.js b/src/renderer/utils/music/mg/index.js new file mode 100644 index 00000000..dda6d214 --- /dev/null +++ b/src/renderer/utils/music/mg/index.js @@ -0,0 +1,23 @@ +import api_source from '../api-source' +import leaderboard from './leaderboard' +import songList from './songList' +import musicSearch from './musicSearch' +import pic from './pic' +import lyric from './lyric' + +const mg = { + songList, + musicSearch, + leaderboard, + getMusicUrl(songInfo, type) { + return api_source('mg').getMusicUrl(songInfo, type) + }, + getLyric(songInfo) { + return lyric.getLyric(songInfo) + }, + getPic(songInfo) { + return pic.getPic(songInfo) + }, +} + +export default mg diff --git a/src/renderer/utils/music/mg/leaderboard.js b/src/renderer/utils/music/mg/leaderboard.js new file mode 100644 index 00000000..3c45f661 --- /dev/null +++ b/src/renderer/utils/music/mg/leaderboard.js @@ -0,0 +1,130 @@ +import { httpFetch } from '../../request' +// import { formatPlayTime } from '../../index' +// import jshtmlencode from 'js-htmlencode' + +export default { + limit: 200, + list: [ + { + id: 'mgyyb', + name: '音乐榜', + bangid: '23603703', + }, + { + id: 'mgysb', + name: '影视榜', + bangid: '23603721', + }, + { + id: 'mghybnd', + name: '华语内地榜', + bangid: '23603926', + }, + { + id: 'mghyjqbgt', + name: '华语港台榜', + bangid: '23603954', + }, + { + id: 'mgomb', + name: '欧美榜', + bangid: '23603974', + }, + { + id: 'mgrhb', + name: '日韩榜', + bangid: '23603982', + }, + { + id: 'mgwlb', + name: '网络榜', + bangid: '23604058', + }, + { + id: 'mgclb', + name: '彩铃榜', + bangid: '23604023', + }, + { + id: 'mgktvb', + name: 'KTV榜', + bangid: '23604040', + }, + { + id: 'mgrcb', + name: '原创榜', + bangid: '23604032', + }, + ], + getUrl(id, page) { + return `http://m.music.migu.cn/migu/remoting/cms_list_tag?nid=${id}&pageSize=${this.limit}&pageNo=${page - 1}` + }, + requestObj: null, + getData(url) { + if (this.requestObj) this.requestObj.cancelHttp() + this.requestObj = httpFetch(url) + return this.requestObj.promise + }, + filterData(rawList) { + // console.log(rawList) + const list = [] + rawList.forEach(({ songData }) => { + if (!songData) return + + 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, + } + } + 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, + source: 'mg', + interval: null, + songmid: songData.songId, + copyrightId: songData.copyrightId, + img: songData.picL || songData.M || songData.picS, + lrc: null, + 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) + return { + total: body.result.totalCount, + list, + limit: body.result.pageSize, + page, + source: 'mg', + } + }) + }, +} diff --git a/src/renderer/utils/music/mg/lyric.js b/src/renderer/utils/music/mg/lyric.js new file mode 100644 index 00000000..65191f79 --- /dev/null +++ b/src/renderer/utils/music/mg/lyric.js @@ -0,0 +1,36 @@ +import { httpFetch } from '../../request' + +export default { + getLyric(songInfo, tryNum = 0) { + console.log(songInfo.copyrightId) + if (songInfo.lrcUrl) { + let requestObj = httpFetch(songInfo.lrcUrl) + requestObj.promise = requestObj.promise.then(({ body, statusCode }) => { + if (statusCode !== 200) { + if (tryNum > 5) return Promise.reject('歌词获取失败') + let tryRequestObj = this.getLyric(songInfo, ++tryNum) + requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) + return tryRequestObj.promise + } + return body + }) + return requestObj + } else { + let requestObj = httpFetch(`http://music.migu.cn/v3/api/music/audioPlayer/getLyric?copyrightId=${songInfo.copyrightId}`, { + headers: { + Referer: 'http://music.migu.cn/v3/music/player/audio?from=migu', + }, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + if (body.returnCode !== '000000') { + if (tryNum > 5) return Promise.reject('歌词获取失败') + let tryRequestObj = this.getLyric(songInfo, ++tryNum) + requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) + return tryRequestObj.promise + } + return body.lyric + }) + return requestObj + } + }, +} diff --git a/src/renderer/utils/music/mg/musicSearch.js b/src/renderer/utils/music/mg/musicSearch.js new file mode 100644 index 00000000..81a0b008 --- /dev/null +++ b/src/renderer/utils/music/mg/musicSearch.js @@ -0,0 +1,108 @@ +// import '../../polyfill/array.find' +// import jshtmlencode from 'js-htmlencode' +import { httpFetch } from '../../request' +import { sizeFormate } from '../../index' +// import { debug } from '../../utils/env' +// import { formatSinger } from './util' + +let searchRequest +export default { + limit: 30, + total: 0, + page: 0, + allPage: 1, + musicSearch(str, page) { + if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp() + searchRequest = httpFetch(`https://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/search_all.do?isCopyright=1&isCorrect=1&pageNo=${page}&pageSize=${this.limit}&searchSwitch={%22song%22:1,%22album%22:0,%22singer%22:0,%22tagSong%22:0,%22mvSong%22:0,%22songlist%22:0,%22bestShow%22:0}&sort=0&text=${encodeURIComponent(str)}`) + return searchRequest.promise.then(({ body }) => body) + }, + getSinger(singers) { + let arr = [] + singers.forEach(singer => { + arr.push(singer.name) + }) + return arr.join('、') + }, + handleResult(rawData) { + // console.log(rawData) + let ids = new Set() + const list = [] + rawData.forEach(item => { + if (ids.has(item.id)) return + ids.add(item.id) + const types = [] + const _types = {} + item.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 + } + }) + + const albumNInfo = item.albums && item.albums.length ? { + id: item.albums[0].id, + name: item.albums[0].name, + } : {} + + list.push({ + singer: this.getSinger(item.singers), + name: item.name, + albumName: albumNInfo.name, + albumId: albumNInfo.id, + songmid: item.id, + copyrightId: item.copyrightId, + source: 'mg', + interval: null, + img: item.imgItems && item.imgItems.length ? item.imgItems[0].img : null, + lrc: null, + lrcUrl: item.lyricUrl, + types, + _types, + typeUrl: {}, + }) + }) + return list + }, + search(str, page = 1, { limit } = {}) { + if (limit != null) this.limit = limit + // http://newlyric.kuwo.cn/newlyric.lrc?62355680 + return this.musicSearch(str, page).then(result => { + if (!result || result.code !== '000000') return this.search(str, page, { limit }) + let list = this.handleResult(result.songResultData.resultList.flat()) + + if (list == null) return this.search(str, page, { limit }) + + this.total = parseInt(result.songResultData.totalCount) + this.page = page + this.allPage = Math.ceil(this.total / this.limit) + + return Promise.resolve({ + list, + allPage: this.allPage, + limit: this.limit, + total: this.total, + source: 'mg', + }) + }) + }, +} diff --git a/src/renderer/utils/music/mg/pic.js b/src/renderer/utils/music/mg/pic.js new file mode 100644 index 00000000..46a40461 --- /dev/null +++ b/src/renderer/utils/music/mg/pic.js @@ -0,0 +1,21 @@ +import { httpFetch } from '../../request' + +export default { + getPic(songInfo, tryNum = 0) { + let requestObj = httpFetch(`http://music.migu.cn/v3/api/music/audioPlayer/getSongPic?songId=${songInfo.songmid}`, { + headers: { + Referer: 'http://music.migu.cn/v3/music/player/audio?from=migu', + }, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + if (body.returnCode !== '000000') { + if (tryNum > 5) return Promise.reject('图片获取失败') + let tryRequestObj = this.getPic(songInfo, ++tryNum) + requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) + return tryRequestObj.promise + } + return body.largePic || body.mediumPic || body.smallPic + }) + return requestObj + }, +} diff --git a/src/renderer/utils/music/mg/songList.js b/src/renderer/utils/music/mg/songList.js new file mode 100644 index 00000000..5419192e --- /dev/null +++ b/src/renderer/utils/music/mg/songList.js @@ -0,0 +1,213 @@ +import { httpFetch } from '../../request' +import { sizeFormate } from '../../index' + +export default { + _requestObj_tags: null, + _requestObj_list: null, + _requestObj_listDetail: null, + limit_list: 10, + limit_song: 100, + successCode: '000000', + sortList: [ + { + name: '推荐', + id: '15127315', + }, + { + name: '最新', + id: '15127272', + }, + ], + regExps: { + list: /