新增咪咕源搜索、歌单、排行榜

pull/96/head
lyswhut 2019-10-07 21:51:16 +08:00
parent ed12aac7d8
commit f7546b0090
14 changed files with 569 additions and 4 deletions

View File

@ -3,6 +3,9 @@
- 新增“我的收藏”本地播放列表
- 新增缓存清理功能,可到**设置-其他**查看与清理软件缓存
- 新增QQ音乐源搜索
- 新增咪咕源搜索
- 新增咪咕源歌单
- 新增咪咕源排行榜
#### 优化

View File

@ -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')
}

View File

@ -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,
}

View File

@ -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
}

View File

@ -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' }))
},
}

View File

@ -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

View File

@ -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

View File

@ -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',
}
})
},
}

View File

@ -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
}
},
}

View File

@ -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',
})
})
},
}

View File

@ -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
},
}

View File

@ -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: /<li><div class="thumb">.+?<\/li>/g,
listInfo: /.+data-original="(.+?)".*data-id="(\d+)".*<div class="song-list-name"><a\s.*?>(.+?)<\/a>.+<i class="iconfont cf-bofangliang"><\/i>(.+?)<\/div>/,
},
tagsUrl: 'https://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/indexTagPage.do?needAll=0',
getSongListUrl(sortId, tagId, page) {
// if (tagId == null) {
// return sortId == 'recommend'
// ? `http://music.migu.cn/v3/music/playlist?page=${page}&from=migu`
// : `http://music.migu.cn/v3/music/playlist?sort=${sortId}&page=${page}&from=migu`
// }
// return `http://music.migu.cn/v3/music/playlist?tagId=${tagId}&page=${page}&from=migu`
if (tagId == null) {
return `http://m.music.migu.cn/migu/remoting/playlist_bycolumnid_tag?playListType=2&type=1&columnId=${sortId}&startIndex=${(page - 1) * 10}`
}
return `http://m.music.migu.cn/migu/remoting/playlist_bycolumnid_tag?playListType=2&type=1&tagId=${tagId}&startIndex=${(page - 1) * 10}`
},
getSongListDetailUrl(id, page) {
return `https://app.c.nf.migu.cn/MIGUM2.0/v1.0/user/queryMusicListSongs.do?musicListId=${id}&pageNo=${page}&pageSize=${this.limit_song}`
},
defaultHeaders: {
language: 'Chinese',
ua: 'Android_migu',
mode: 'android',
version: '6.8.5',
},
/**
* 格式化播放数量
* @param {*} num
*/
formatPlayCount(num) {
if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿'
if (num > 10000) return parseInt(num / 1000) / 10 + '万'
return num
},
getListDetail(id, page) { // 获取歌曲列表内的音乐
if (this._requestObj_listDetail) this._requestObj_listDetail.cancelHttp()
this._requestObj_listDetail = httpFetch(this.getSongListDetailUrl(id, page), { headers: this.defaultHeaders })
return this._requestObj_listDetail.promise.then(({ body }) => {
if (body.code !== this.successCode) return this.getListDetail(id, page)
return {
list: this.filterListDetail(body.list),
page,
limit: this.limit_song,
total: body.totalCount,
source: 'mg',
}
})
},
filterListDetail(rawList) {
// console.log(rawList)
let ids = new Set()
const list = []
rawList.forEach(item => {
if (ids.has(item.songId)) return
ids.add(item.songId)
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
}
})
list.push({
singer: item.singer,
name: item.songName,
albumName: item.album,
albumId: item.albumId,
songmid: item.songId,
copyrightId: item.copyrightId,
source: 'mg',
interval: null,
img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null,
lrc: null,
lrcUrl: item.lrcUrl,
types,
_types,
typeUrl: {},
})
})
return list
},
// 获取列表数据
getList(sortId, tagId, page) {
if (this._requestObj_list) this._requestObj_list.cancelHttp()
this._requestObj_list = httpFetch(this.getSongListUrl(sortId, tagId, page))
// 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)
// if (!list) return Promise.reject('获取列表失败')
// return list.map(item => {
// let info = item.match(this.regExps.listInfo)
// return {
// play_count: info[4],
// id: info[2],
// author: '',
// name: info[3],
// time: '',
// img: info[1],
// grade: 0,
// desc: '',
// source: 'mg',
// }
// })
// })
return this._requestObj_list.promise.then(({ body }) => {
if (body.retCode !== '100000' || body.retMsg.code !== this.successCode) return this.getList(sortId, tagId, page)
return {
list: this.filterList(body.retMsg.playlist),
total: parseInt(body.retMsg.countSize),
page,
limit: this.limit_list,
source: 'mg',
}
})
},
filterList(rawData) {
return rawData.map(item => ({
play_count: this.formatPlayCount(item.playCount),
id: item.playListId,
author: item.createName,
name: item.playListName,
time: item.createTime,
img: item.image,
grade: item.grade,
desc: item.summary,
source: 'mg',
}))
},
// 获取标签
getTag() {
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
this._requestObj_tags = httpFetch(this.tagsUrl, { headers: this.defaultHeaders })
return this._requestObj_tags.promise.then(({ body }) => {
if (body.code !== this.successCode) return this.getTag()
return this.filterTagInfo(body.columnInfo.contents)
})
},
filterTagInfo(rawList) {
return {
hotTag: rawList[0].objectInfo.contents.map(item => ({
id: item.objectInfo.tagId,
name: item.objectInfo.tagName,
source: 'mg',
})),
tags: rawList.slice(1).map(({ objectInfo }) => ({
name: objectInfo.columnTitle,
list: objectInfo.contents.map(item => ({
parent_id: objectInfo.columnId,
parent_name: objectInfo.columnTitle,
id: item.objectInfo.tagId,
name: item.objectInfo.tagName,
source: 'mg',
})),
})),
source: 'mg',
}
},
getTags() {
return this.getTag()
},
}
// getList
// getTags
// getListDetail

View File

@ -33,7 +33,7 @@
:play-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
:download-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
@btn-click="handleListBtnClick")
td(style="width: 10%;") {{item.interval}}
td(style="width: 10%;") {{item.interval || '--/--'}}
div(:class="$style.pagination")
material-pagination(:count="listInfo.total" :limit="listInfo.limit" :page="page" @btn-click="handleTogglePage")
div(v-else :class="$style.noitem")

View File

@ -288,6 +288,7 @@ export default {
.songListContent {
display: flex;
flex-flow: column nowrap;
height: 100%;
// position: relative;
}