This commit is contained in:
lyswhut 2023-04-13 12:03:19 +08:00
parent 03af3be7cd
commit 552307bda8
9 changed files with 168 additions and 221 deletions

View File

@ -2,12 +2,17 @@
- 优化对系统Media Session的支持现在切歌不会再会导致信息丢失的问题了
- 启用桌面歌词时,取消对歌词窗口的聚焦
- 增加kg歌单歌曲flac24bit显示@helloplhm-qwq
- 增加tx源热门评论图片显示@Folltoshe
### 修复
- 修复启用全局快捷键时与Media Session注册冲突的问题启用全局快捷键时不再注册媒体控制快捷键
- 修复搜索不显示时长的问题(@Folltoshe
- 修复评论加载失败的问题(@Folltoshe
### 其他
- 自定义源API utils对象新增`zlib.inflate`与`zlib.deflate`方法API版本更新到 v1.3.0
- 更新kg、tx、wy等平台排行榜列表
- 更新 electron 到 v22.3.5

View File

@ -253,7 +253,7 @@ contextBridge.exposeInMainWorld('lx', {
},
},
},
version: '1.2.1',
version: '1.3.0',
// removeEvent(eventName, handler) {
// if (!eventNames.includes(eventName)) return Promise.reject(new Error('The event is not supported: ' + eventName))
// let handlers

View File

@ -1,5 +1,5 @@
import { httpFetch } from '../../request'
import { getSongId } from './songId'
import getSongId from './songId'
import { dateFormat2 } from '../../index'
export default {

View File

@ -1,5 +1,5 @@
import { httpFetch } from '../../request'
import { sizeFormate } from '../../index'
import { filterMusicInfoData } from './musicInfo'
// 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' }]
@ -81,82 +81,6 @@ export default {
const requestObj = httpFetch(url)
return requestObj.promise
},
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 = []
rawData.forEach(({ objectInfo: item }) => {
if (ids.has(item.copyrightId)) return
ids.add(item.copyrightId)
const types = []
const _types = {}
item.newRateFormats && item.newRateFormats.forEach(type => {
let size
switch (type.formatType) {
case 'PQ':
size = sizeFormate(type.size ?? type.androidSize)
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
break
case 'HQ':
size = sizeFormate(type.size ?? type.androidSize)
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
break
case 'SQ':
size = sizeFormate(type.size ?? type.androidSize)
types.push({ type: 'flac', size })
_types.flac = {
size,
}
break
case 'ZQ':
size = sizeFormate(type.size ?? type.androidSize)
types.push({ type: 'flac24bit', size })
_types.flac24bit = {
size,
}
break
}
})
const intervalTest = /(\d\d:\d\d)$/.test(item.length)
list.push({
singer: this.getSinger(item.artists),
name: item.songName,
albumName: item.album,
albumId: item.albumId,
songmid: item.songId,
copyrightId: item.copyrightId,
source: 'mg',
interval: intervalTest ? RegExp.$1 : null,
img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null,
lrc: null,
lrcUrl: item.lrcUrl,
mrcUrl: item.mrcUrl,
trcUrl: item.trcUrl,
otherSource: null,
types,
_types,
typeUrl: {},
})
})
return list
},
filterBoardsData(rawList) {
// console.log(rawList)
let list = []
@ -204,7 +128,7 @@ export default {
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.columnInfo.contents)
const list = filterMusicInfoData(body.columnInfo.contents.map(m => m.objectInfo))
return {
total: list.length,
list,

View File

@ -1,5 +1,5 @@
import { httpFetch } from '../../request'
import musicSearch from './musicSearch'
import { getMusicInfo } from './musicInfo'
import { decrypt } from './mrc'
const mrcTools = {
@ -75,11 +75,8 @@ const mrcTools = {
},
getMusicInfo(songInfo) {
return songInfo.mrcUrl == null
? musicSearch.search(`${songInfo.name} ${songInfo.singer || ''}`.trim(), 1, 25).then(({ list }) => {
const targetSong = list.find(s => s.copyrightId == songInfo.copyrightId)
return targetSong ? { lrcUrl: targetSong.lrcUrl, mrcUrl: targetSong.mrcUrl, trcUrl: targetSong.trcUrl } : Promise.reject('获取歌词失败')
})
: Promise.resolve({ lrcUrl: songInfo.lrcUrl, mrcUrl: songInfo.mrcUrl, trcUrl: songInfo.trcUrl })
? getMusicInfo(songInfo.copyrightId)
: songInfo
},
getLyric(songInfo) {
return {

View File

@ -0,0 +1,100 @@
import { httpFetch } from '../../request'
import { sizeFormate } from '../../index'
const getSinger = (singers) => {
let arr = []
singers.forEach(singer => {
arr.push(singer.name)
})
return arr.join('、')
}
export const filterMusicInfoData = (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.newRateFormats?.forEach(type => {
let size
switch (type.formatType) {
case 'PQ':
size = sizeFormate(type.size ?? type.androidSize)
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
break
case 'HQ':
size = sizeFormate(type.size ?? type.androidSize)
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
break
case 'SQ':
size = sizeFormate(type.size ?? type.androidSize)
types.push({ type: 'flac', size })
_types.flac = {
size,
}
break
case 'ZQ':
size = sizeFormate(type.size ?? type.androidSize)
types.push({ type: 'flac24bit', size })
_types.flac24bit = {
size,
}
break
}
})
const intervalTest = /(\d\d:\d\d)$/.test(item.length)
list.push({
singer: getSinger(item.artists),
name: item.songName,
albumName: item.album,
albumId: item.albumId,
songmid: item.songId,
copyrightId: item.copyrightId,
source: 'mg',
interval: intervalTest ? RegExp.$1 : null,
img: item.albumImgs?.length ? item.albumImgs[0].img : null,
lrc: null,
lrcUrl: item.lrcUrl,
mrcUrl: item.mrcUrl,
trcUrl: item.trcUrl,
otherSource: null,
types,
_types,
typeUrl: {},
})
})
// console.log(list)
return list
}
export const getMusicInfos = (copyrightIds, retry = 0) => {
if (++retry > 2) return Promise.reject(new Error('Failed to get music info try max'))
return httpFetch('https://c.musicapp.migu.cn/MIGUM2.0/v1.0/content/resourceinfo.do?resourceType=2', {
method: 'POST',
form: {
resourceId: copyrightIds.join('|'),
},
}).promise.then(({ body }) => {
if (!body) return getMusicInfos(copyrightIds, retry)
if (body.code !== '000000') return Promise.reject(new Error('Failed to get music info'))
return filterMusicInfoData(body.resource)
})
}
export const getMusicInfo = (copyrightId) => {
return getMusicInfos([copyrightId]).then(([musicInfo]) => {
if (musicInfo) return musicInfo
throw new Error('failed')
})
}

View File

@ -2,6 +2,13 @@ import { httpFetch } from '../../request'
import { sizeFormate, formatPlayTime } from '../../index'
import { toMD5 } from '../utils'
const sign = (time, str) => {
const deviceId = '963B7AA0D21511ED807EE5846EC87D20'
const signatureMd5 = '6cdc72a439cef99a3418d2a78aa28c73'
const sign = toMD5(`${str}${signatureMd5}yyapp2d16148780a1dcc7408e06336b98cfd50${deviceId}${time}`)
return { sign, deviceId }
}
export default {
limit: 20,
total: 0,
@ -11,6 +18,9 @@ export default {
// 旧版API
// musicSearch(str, page, limit) {
// const searchRequest = httpFetch(`http://pd.musicapp.migu.cn/MIGUM2.0/v1.0/content/search_all.do?ua=Android_migu&version=5.0.1&text=${encodeURIComponent(str)}&pageNo=${page}&pageSize=${limit}&searchSwitch=%7B%22song%22%3A1%2C%22album%22%3A0%2C%22singer%22%3A0%2C%22tagSong%22%3A0%2C%22mvSong%22%3A0%2C%22songlist%22%3A0%2C%22bestShow%22%3A1%7D`, {
// searchRequest = httpFetch(`http://pd.musicapp.migu.cn/MIGUM2.0/v1.0/content/search_all.do?ua=Android_migu&version=5.0.1&text=${encodeURIComponent(str)}&pageNo=${page}&pageSize=${limit}&searchSwitch=%7B%22song%22%3A1%2C%22album%22%3A0%2C%22singer%22%3A0%2C%22tagSong%22%3A0%2C%22mvSong%22%3A0%2C%22songlist%22%3A0%2C%22bestShow%22%3A1%7D`, {
// searchRequest = httpFetch(`http://jadeite.migu.cn:7090/music_search/v2/search/searchAll?sid=4f87090d01c84984a11976b828e2b02c18946be88a6b4c47bcdc92fbd40762db&isCorrect=1&isCopyright=1&searchSwitch=%7B%22song%22%3A1%2C%22album%22%3A0%2C%22singer%22%3A0%2C%22tagSong%22%3A1%2C%22mvSong%22%3A0%2C%22bestShow%22%3A1%2C%22songlist%22%3A0%2C%22lyricSong%22%3A0%7D&pageSize=${limit}&text=${encodeURIComponent(str)}&pageNo=${page}&sort=0`, {
// searchRequest = httpFetch(`https://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/search_all.do?isCopyright=1&isCorrect=1&pageNo=${page}&pageSize=${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)}`)
// // searchRequest = httpFetch(`http://jadeite.migu.cn:7090/music_search/v2/search/searchAll?sid=4f87090d01c84984a11976b828e2b02c18946be88a6b4c47bcdc92fbd40762db&isCorrect=1&isCopyright=1&searchSwitch=%7B%22song%22%3A1%2C%22album%22%3A0%2C%22singer%22%3A0%2C%22tagSong%22%3A1%2C%22mvSong%22%3A0%2C%22bestShow%22%3A1%2C%22songlist%22%3A0%2C%22lyricSong%22%3A0%7D&pageSize=${limit}&text=${encodeURIComponent(str)}&pageNo=${page}&sort=0`, {
// headers: {
// // sign: 'c3b7ae985e2206e97f1b2de8f88691e2',
@ -101,8 +111,8 @@ export default {
musicSearch(str, page, limit) {
const time = Date.now().toString()
const signData = this.signWithSearch(time, str)
const searchRequest = httpFetch(`https://jadeite.migu.cn/music_search/v3/search/searchAll?pageNo=${page}&pageSize=${limit}&sort=0&text=${encodeURI(str)}&searchSwitch={"song":1}&isCopyright=1&isCorrect=1`, {
const signData = sign(time, str)
const searchRequest = httpFetch(`https://jadeite.migu.cn/music_search/v3/search/searchAll?isCorrect=1&isCopyright=1&searchSwitch=%7B%22song%22%3A1%2C%22album%22%3A0%2C%22singer%22%3A0%2C%22tagSong%22%3A1%2C%22mvSong%22%3A0%2C%22bestShow%22%3A1%2C%22songlist%22%3A0%2C%22lyricSong%22%3A0%7D&pageSize=${limit}&text=${encodeURIComponent(str)}&pageNo=${page}&sort=0`, {
headers: {
uiVersion: 'A_music_3.6.1',
deviceId: signData.deviceId,
@ -121,29 +131,14 @@ export default {
})
return arr.join('、')
},
async getMusicInfo(copyrightIds) {
return httpFetch('https://c.musicapp.migu.cn/MIGUM2.0/v1.0/content/resourceinfo.do?resourceType=2', {
method: 'POST',
formData: { resourceId: copyrightIds },
}).promise.then(({ body }) => {
if (body.code !== '000000') return Promise.reject(new Error('Failed to get music info.'))
return body.resource
})
},
signWithSearch(time, str) {
const deviceId = '963B7AA0D21511ED807EE5846EC87D16'
const signatureMd5 = '6cdc72a439cef99a3418d2a78aa28c73'
const sign = toMD5(`${str}${signatureMd5}yyapp2d16148780a1dcc7408e06336b98cfd50${deviceId}${time}`)
return { sign, deviceId }
},
filterData(rawData) {
// console.log(rawData)
const list = new Map()
const list = []
const ids = new Set()
rawData.forEach(item => {
item.forEach(data => {
if (ids.has(data.copyrightId) || !data.songId || !data.copyrightId) return
if (!data.songId || !data.copyrightId || ids.has(data.copyrightId)) return
ids.add(data.copyrightId)
const types = []
@ -182,22 +177,23 @@ export default {
}
})
list.set(data.songId, {
let img = data.img3 || data.img2 || data.img1 || null
if (img && !/https?:/.test(data.img3)) img = 'http://d.musicapp.migu.cn' + img
list.push({
singer: this.getSinger(data.singerList),
name: data.name,
albumName: data.album,
albumId: data.albumId,
songmid: data.copyrightId,
songId: data.songId,
songmid: data.songId,
copyrightId: data.copyrightId,
source: 'mg',
interval: formatPlayTime(data.duration),
img: /https?:/.test(data.img3) ? data.img3 : 'http://d.musicapp.migu.cn' + data.img3,
img,
lrc: null,
lrcUrl: data.lrcUrl,
mrcUrl: data.mrcurl,
trcUrl: data.trcUrl,
otherSource: null,
types,
_types,
typeUrl: {},
@ -206,47 +202,29 @@ export default {
})
return list
},
async handleResult(rawData) {
// console.log(rawData)
const list = []
const datas = this.filterData(rawData)
if (!datas) throw new Error('Failed to filter data')
const songInfo = await this.getMusicInfo([...datas.keys()].join('|'))
songInfo.forEach(item => {
let data = datas.get(item.songId)
if (!data) return
list.push({
...data,
lrcUrl: item.lrcUrl,
mrcUrl: item.mrcUrl,
trcUrl: item.trcUrl,
})
})
return list
},
search(str, page = 1, limit, retryNum = 0) {
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
if (limit == null) limit = this.limit
// http://newlyric.kuwo.cn/newlyric.lrc?62355680
return this.musicSearch(str, page, limit).then(async result => {
return this.musicSearch(str, page, limit).then(result => {
// console.log(result)
if (!result || result.code !== '000000') return Promise.reject(new Error(result ? result.info : '搜索失败'))
const songResultData = result.songResultData || { result: [], totalCount: 0 }
const songResultData = result.songResultData || { resultList: [], totalCount: 0 }
let list = await this.handleResult(songResultData.resultList)
let list = this.filterData(songResultData.resultList)
if (list == null) return this.search(str, page, limit, retryNum)
this.total = parseInt(songResultData.totalCount)
this.page = page
this.allPage = Math.ceil(this.total / limit)
return Promise.resolve({
return {
list,
allPage: this.allPage,
limit,
total: this.total,
source: 'mg',
})
}
})
},
}

View File

@ -1,22 +1,31 @@
import { httpFetch } from '../../request'
// import { httpFetch } from '../../request'
import { getMusicInfo } from './musicInfo'
export const getSongId = async(musicInfo, retry = 0) => {
if (musicInfo.songmid != musicInfo.copyrightId) return musicInfo.songmid
if (++retry > 2) return Promise.reject(new Error('max retry'))
const requestObj = httpFetch(`https://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/listen-url?netType=00&resourceType=2&songId=${musicInfo.copyrightId}&toneFlag=PQ`, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
channel: '0146921',
},
})
return requestObj.promise.then(({ body }) => {
console.log(body)
if (!body || body.code !== '000000') return this.getSongId(musicInfo, retry)
const id = body.data.songItem.songId
if (!id) throw new Error('failed')
return id
})
const getSongId = async(mInfo) => {
if (mInfo.songmid != mInfo.copyrightId) return mInfo.songmid
const musicInfo = await getMusicInfo(mInfo.copyrightId)
return musicInfo.songmid
}
// export const getSongId = async(musicInfo, retry = 0) => {
// if (musicInfo.songmid != musicInfo.copyrightId) return musicInfo.songmid
// if (++retry > 2) return Promise.reject(new Error('max retry'))
// const requestObj = httpFetch(`https://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/listen-url?netType=00&resourceType=2&songId=${musicInfo.copyrightId}&toneFlag=PQ`, {
// headers: {
// 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
// channel: '0146921',
// },
// })
// return requestObj.promise.then(({ body }) => {
// console.log(body)
// if (!body || body.code !== '000000') return this.getSongId(musicInfo, retry)
// const id = body.data.songItem.songId
// if (!id) throw new Error('failed')
// return id
// })
// }
export default getSongId

File diff suppressed because one or more lines are too long