新增虾米音源
parent
7bd4002f09
commit
ccf362db41
|
@ -17,7 +17,7 @@ module.exports = {
|
|||
'top', 'left', 'bottom', 'right',
|
||||
'border-radius',
|
||||
],
|
||||
selectorBlackList: ['html'],
|
||||
selectorBlackList: ['html', 'ignore-to-rem'],
|
||||
replace: true,
|
||||
mediaQuery: false,
|
||||
minPixelValue: 0,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
- 新增托盘设置,默认关闭,可到设置开启,感谢@LasyIsLazy提交的PR
|
||||
- 新增打开酷狗源用户歌单
|
||||
- 新增使用协议
|
||||
- 新增虾米音源
|
||||
|
||||
### 优化
|
||||
|
||||
|
|
|
@ -36,4 +36,7 @@ module.exports = {
|
|||
fontSize: '18px',
|
||||
},
|
||||
],
|
||||
navigationUrlWhiteList: [
|
||||
/^https:\/\/www\.xiami\.com/,
|
||||
],
|
||||
}
|
||||
|
|
|
@ -2,4 +2,4 @@ global.lx_event = {}
|
|||
|
||||
const Tray = require('./tray')
|
||||
|
||||
if (!global.lx_event.setting) global.lx_event.tray = new Tray()
|
||||
if (!global.lx_event.tray) global.lx_event.tray = new Tray()
|
||||
|
|
|
@ -21,11 +21,13 @@ app.on('second-instance', (event, argv, cwd) => {
|
|||
})
|
||||
|
||||
const isDev = global.isDev = process.env.NODE_ENV !== 'production'
|
||||
const { navigationUrlWhiteList } = require('../common/config')
|
||||
|
||||
app.on('web-contents-created', (event, contents) => {
|
||||
contents.on('will-navigate', (event, navigationUrl) => {
|
||||
if (isDev) return console.log('navigation to url:', navigationUrl)
|
||||
event.preventDefault()
|
||||
if (!navigationUrlWhiteList.some(url => url.test(navigationUrl))) return event.preventDefault()
|
||||
console.log('navigation to url:', navigationUrl)
|
||||
})
|
||||
contents.on('new-window', async(event, navigationUrl) => {
|
||||
event.preventDefault()
|
||||
|
@ -33,6 +35,19 @@ app.on('web-contents-created', (event, contents) => {
|
|||
console.log(navigationUrl)
|
||||
await shell.openExternal(navigationUrl)
|
||||
})
|
||||
contents.on('will-attach-webview', (event, webPreferences, params) => {
|
||||
// Strip away preload scripts if unused or verify their location is legitimate
|
||||
delete webPreferences.preload
|
||||
delete webPreferences.preloadURL
|
||||
|
||||
// Disable Node.js integration
|
||||
webPreferences.nodeIntegration = false
|
||||
|
||||
// Verify URL being loaded
|
||||
if (!navigationUrlWhiteList.some(url => url.test(params.src))) {
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// https://github.com/electron/electron/issues/22691
|
||||
|
|
|
@ -12,3 +12,6 @@ require('./getCacheSize')
|
|||
require('./setIgnoreMouseEvent')
|
||||
require('./getEnvParams')
|
||||
require('./tray')
|
||||
require('./updateSetting')
|
||||
|
||||
require('./xm_verify')
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
const { mainOn } = require('../../common/ipc')
|
||||
|
||||
|
||||
mainOn('updateAppSetting', (event, setting) => {
|
||||
if (!setting) return
|
||||
global.appSetting = setting
|
||||
})
|
|
@ -0,0 +1,43 @@
|
|||
const { BrowserView } = require('electron')
|
||||
const { mainHandle } = require('../../common/ipc')
|
||||
const { getWindowSizeInfo } = require('../utils')
|
||||
|
||||
let view
|
||||
|
||||
const closeView = async() => {
|
||||
if (!view) return
|
||||
// await view.webContents.session.clearCache()
|
||||
if (global.mainWindow) global.mainWindow.removeBrowserView(view)
|
||||
await view.webContents.session.clearStorageData()
|
||||
view.destroy()
|
||||
view = null
|
||||
}
|
||||
|
||||
mainHandle('xm_verify_open', (event, url) => new Promise((resolve, reject) => {
|
||||
if (!global.mainWindow) return reject(new Error('mainwindow is undefined'))
|
||||
if (view) view.destroy()
|
||||
|
||||
view = new BrowserView()
|
||||
view.webContents.on('did-finish-load', () => {
|
||||
if (/punish\?/.test(view.webContents.getURL())) return
|
||||
let ses = view.webContents.session
|
||||
ses.cookies.get({ name: 'x5sec' })
|
||||
.then(async([x5sec]) => {
|
||||
await closeView()
|
||||
if (!x5sec) return reject(new Error('get x5sec failed'))
|
||||
resolve(x5sec.value)
|
||||
}).catch(async err => {
|
||||
await closeView()
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
global.mainWindow.setBrowserView(view)
|
||||
const windowSizeInfo = getWindowSizeInfo(global.appSetting)
|
||||
view.setBounds({ x: (windowSizeInfo.width - 360) / 2, y: ((windowSizeInfo.height - 320 + 52) / 2), width: 360, height: 320 })
|
||||
view.webContents.loadURL(url)
|
||||
}))
|
||||
|
||||
mainHandle('xm_verify_close', async() => {
|
||||
await closeView()
|
||||
})
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
core-icons
|
||||
material-pact-modal(v-show="!setting.isAgreePact || globalObj.isShowPact")
|
||||
material-version-modal(v-show="version.showModal")
|
||||
material-xm-verify-modal(v-show="globalObj.xm.isShowVerify" :show="globalObj.xm.isShowVerify" :bg-close="false" @close="handleXMVerifyModalClose")
|
||||
#container(v-else :class="theme")
|
||||
core-aside#left
|
||||
#right
|
||||
|
@ -17,6 +18,7 @@
|
|||
core-icons
|
||||
material-pact-modal(v-show="!setting.isAgreePact || globalObj.isShowPact")
|
||||
material-version-modal(v-show="version.showModal")
|
||||
material-xm-verify-modal(v-show="globalObj.xm.isShowVerify" :show="globalObj.xm.isShowVerify" :bg-close="false" @close="handleXMVerifyModalClose")
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -42,6 +44,9 @@ export default {
|
|||
apiSource: 'test',
|
||||
proxy: {},
|
||||
isShowPact: false,
|
||||
xm: {
|
||||
isShowVerify: false,
|
||||
},
|
||||
},
|
||||
updateTimeout: null,
|
||||
envParams: {
|
||||
|
@ -63,6 +68,7 @@ export default {
|
|||
created() {
|
||||
this.saveSetting = throttle(n => {
|
||||
window.electronStore_config.set('setting', n)
|
||||
rendererSend('updateAppSetting', n)
|
||||
})
|
||||
this.saveDefaultList = throttle(n => {
|
||||
window.electronStore_list.set('defaultList', n)
|
||||
|
@ -286,6 +292,9 @@ export default {
|
|||
})
|
||||
}
|
||||
},
|
||||
handleXMVerifyModalClose() {
|
||||
music.xm.closeVerifyModal()
|
||||
},
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.clearUpdateTimeout()
|
||||
|
|
|
@ -434,14 +434,14 @@ export default {
|
|||
switch (songInfo.source) {
|
||||
case 'wy':
|
||||
case 'tx':
|
||||
// case 'kg':
|
||||
return '128k'
|
||||
// case 'kg':
|
||||
}
|
||||
let type = '128k'
|
||||
if (highQuality && songInfo._types['320k']) type = '320k'
|
||||
return type
|
||||
},
|
||||
setUrl(targetSong, isRefresh) {
|
||||
setUrl(targetSong, isRefresh, isRetryed = false) {
|
||||
let type = this.getPlayType(this.setting.player.highQuality, targetSong)
|
||||
this.musicInfo.url = targetSong.typeUrl[type]
|
||||
this.status = this.$t('core.player.geting_url')
|
||||
|
@ -450,6 +450,7 @@ export default {
|
|||
this.audio.src = this.musicInfo.url = targetSong.typeUrl[type]
|
||||
}).catch(err => {
|
||||
if (err.message == requestMsg.cancelRequest) return
|
||||
if (!isRetryed) return this.setUrl(targetSong, isRefresh, true)
|
||||
this.status = err.message
|
||||
this.addDelayNextTimeout()
|
||||
return Promise.reject(err)
|
||||
|
|
|
@ -41,6 +41,7 @@ export default {
|
|||
switch (type) {
|
||||
case 'flac':
|
||||
case 'ape':
|
||||
case 'wav':
|
||||
return this.$t('material.download_modal.lossless')
|
||||
case '320k':
|
||||
return this.$t('material.download_modal.high_quality')
|
||||
|
@ -54,6 +55,8 @@ export default {
|
|||
case 'wy':
|
||||
case 'tx':
|
||||
return type == '128k'
|
||||
case 'xm':
|
||||
return type == '128k' || type == '320k'
|
||||
|
||||
default:
|
||||
return true
|
||||
|
|
|
@ -8,7 +8,7 @@ material-modal(:show="show" :bg-close="bgClose" @close="handleClose")
|
|||
material-btn(:class="$style.btn" @click="handleClick('128k')") {{$t('material.download_multiple_modal.normal')}} - 128K
|
||||
material-btn(:class="$style.btn" @click="handleClick('320k')") {{$t('material.download_multiple_modal.high_quality')}} - 320K
|
||||
//- material-btn(:class="$style.btn" @click="handleClick('ape')") 无损音质 - APE
|
||||
material-btn(:class="$style.btn" @click="handleClick('flac')") {{$t('material.download_multiple_modal.lossless')}} - FLAC
|
||||
material-btn(:class="$style.btn" @click="handleClick('flac')") {{$t('material.download_multiple_modal.lossless')}} - FLAC/WAV
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -134,7 +134,7 @@ export default {
|
|||
border-radius: 5px;
|
||||
box-shadow: 0 0 3px rgba(0, 0, 0, .3);
|
||||
overflow: hidden;
|
||||
max-height: 70%;
|
||||
max-height: 80%;
|
||||
max-width: 70%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
|
|
@ -22,7 +22,7 @@ div(:class="$style.songList")
|
|||
material-checkbox(:id="index.toString()" v-model="selectdList" @change="handleChangeSelect" :value="item")
|
||||
td.break(style="width: 25%;")
|
||||
span.select {{item.name}}
|
||||
span.badge.badge-theme-success(:class="$style.labelQuality" v-if="item._types.ape || item._types.flac") {{$t('material.song_list.lossless')}}
|
||||
span.badge.badge-theme-success(:class="$style.labelQuality" v-if="item._types.ape || item._types.flac || item._types.wav") {{$t('material.song_list.lossless')}}
|
||||
span.badge.badge-theme-info(:class="$style.labelQuality" v-else-if="item._types['320k']") {{$t('material.song_list.high_quality')}}
|
||||
td.break(style="width: 20%;")
|
||||
span.select {{item.singer}}
|
||||
|
|
|
@ -112,6 +112,7 @@ export default {
|
|||
cursor: pointer;
|
||||
padding: 0 10px;
|
||||
font-size: 12px;
|
||||
min-width: 56px;
|
||||
// color: @color-btn;
|
||||
outline: none;
|
||||
transition: background-color @transition-theme;
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<template lang="pug">
|
||||
material-modal(:show="show" :bg-close="bgClose" @close="handleClose")
|
||||
main.ignore-to-rem(:class="$style.main")
|
||||
h2 {{$t('material.xm_verify_modal.title')}}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
bgClose: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleClose() {
|
||||
this.$emit('close')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="less" module>
|
||||
@import '../../assets/styles/layout.less';
|
||||
|
||||
.main {
|
||||
background: #fff !important;
|
||||
&:global(.ignore-to-rem) {
|
||||
padding: 15px;
|
||||
width: 360px;
|
||||
height: 330px;
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 13px;
|
||||
color: @color-theme_2-font;
|
||||
line-height: 1.3;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"btn_tip": "腾讯、网易音源仅支持下载128k音质",
|
||||
"btn_tip": "腾讯、网易音源仅支持下载128k音质\n虾米音源不支持下载无损音质",
|
||||
"lossless": "无损音质",
|
||||
"high_quality": "高品音质",
|
||||
"normal": "普通音质"
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"title": "虾米音乐校验"
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
"source_tx": "企鹅音乐",
|
||||
"source_wy": "网易音乐",
|
||||
"source_mg": "咪咕音乐",
|
||||
"source_xm": "虾米音乐",
|
||||
"source_bd": "百度音乐",
|
||||
|
||||
"source_all": "聚合搜索",
|
||||
|
@ -24,6 +25,7 @@
|
|||
"source_alias_tx": "小秋音乐",
|
||||
"source_alias_wy": "小芸音乐",
|
||||
"source_alias_mg": "小蜜音乐",
|
||||
"source_alias_xm": "小霞音乐",
|
||||
"source_alias_bd": "小杜音乐",
|
||||
|
||||
"source_alias_all": "聚合大会"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"btn_tip": "騰訊、網易音源僅支持下載128k音質",
|
||||
"btn_tip": "騰訊、網易、音源僅支持下載128k音質\n蝦米音源不支持下載無損音質",
|
||||
"lossless": "無損音質",
|
||||
"high_quality": "高品音質",
|
||||
"normal": "普通音質"
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"title": "蝦米音樂校驗"
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
"source_tx": "企鵝音樂",
|
||||
"source_wy": "網易音樂",
|
||||
"source_mg": "咪咕音樂",
|
||||
"source_xm": "蝦米音樂",
|
||||
"source_bd": "百度音樂",
|
||||
"source_all": "聚合搜索",
|
||||
"source_alias_kw": "小蝸音樂",
|
||||
|
@ -22,5 +23,6 @@
|
|||
"source_alias_wy": "小芸音樂",
|
||||
"source_alias_mg": "小蜜音樂",
|
||||
"source_alias_bd": "小杜音樂",
|
||||
"source_alias_xm": "小霞音樂",
|
||||
"source_alias_all": "聚合大會"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"btn_tip": "Tencent and NetEase sources only support 128k audio quality",
|
||||
"btn_tip": "Tencent and NetEase only support 128k audio quality\nXiami sources does not support 128k audio quality",
|
||||
"lossless": "Lossless",
|
||||
"high_quality": "High Quality",
|
||||
"normal": "Normal"
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"title": "Xiami music verify"
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
"source_tx": "Tencent",
|
||||
"source_wy": "Netease",
|
||||
"source_mg": "Migu",
|
||||
"source_xm": "Xiami",
|
||||
"source_bd": "Baidu",
|
||||
"source_all": "Aggregated",
|
||||
|
||||
|
@ -23,6 +24,7 @@
|
|||
"source_alias_tx": "TX Music",
|
||||
"source_alias_wy": "WY Music",
|
||||
"source_alias_mg": "MG Music",
|
||||
"source_alias_xm": "XM Music",
|
||||
"source_alias_bd": "BD Music",
|
||||
|
||||
"source_alias_all": "Aggregated"
|
||||
|
|
|
@ -123,7 +123,7 @@ const downloadLyric = (downloadInfo, filePath) => {
|
|||
? Promise.resolve(downloadInfo.musicInfo.lrc)
|
||||
: music[downloadInfo.musicInfo.source].getLyric(downloadInfo.musicInfo).promise
|
||||
promise.then(lrc => {
|
||||
if (lrc) saveLrc(filePath.replace(/(mp3|flac|ape)$/, 'lrc'), lrc)
|
||||
if (lrc) saveLrc(filePath.replace(/(mp3|flac|ape|wav)$/, 'lrc'), lrc)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ 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 xm_api_test from './xm/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'
|
||||
|
@ -18,6 +19,7 @@ const apis = {
|
|||
wy_api_test,
|
||||
bd_api_test,
|
||||
mg_api_test,
|
||||
xm_api_test,
|
||||
// kw_api_internal,
|
||||
// tx_api_internal,
|
||||
// kg_api_internal,
|
||||
|
@ -50,6 +52,8 @@ export default source => {
|
|||
return getAPI('bd')
|
||||
case 'mg':
|
||||
return getAPI('mg')
|
||||
case 'xm':
|
||||
return getAPI('xm')
|
||||
default:
|
||||
return getAPI('kw')
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import tx from './tx'
|
|||
import wy from './wy'
|
||||
import mg from './mg'
|
||||
import bd from './bd'
|
||||
import xm from './xm'
|
||||
const sources = {
|
||||
sources: [
|
||||
{
|
||||
|
@ -26,6 +27,10 @@ const sources = {
|
|||
name: '咪咕音乐',
|
||||
id: 'mg',
|
||||
},
|
||||
{
|
||||
name: '虾米音乐',
|
||||
id: 'xm',
|
||||
},
|
||||
{
|
||||
name: '百度音乐',
|
||||
id: 'bd',
|
||||
|
@ -37,6 +42,7 @@ const sources = {
|
|||
wy,
|
||||
mg,
|
||||
bd,
|
||||
xm,
|
||||
}
|
||||
export default {
|
||||
...sources,
|
||||
|
|
|
@ -6,13 +6,15 @@ import crypto from 'crypto'
|
|||
* @param {*} type
|
||||
*/
|
||||
|
||||
const types = ['flac', 'ape', '320k', '192k', '128k']
|
||||
const types = ['flac', 'wav', 'ape', '320k', '192k', '128k']
|
||||
export const getMusicType = (info, type) => {
|
||||
switch (info.source) {
|
||||
// case 'kg':
|
||||
case 'wy':
|
||||
case 'tx':
|
||||
return '128k'
|
||||
case 'xm':
|
||||
if (type == 'wav') type = '320k'
|
||||
}
|
||||
const rangeType = types.slice(types.indexOf(type))
|
||||
for (const type of rangeType) {
|
||||
|
|
|
@ -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/xm/${songInfo.songmid}/${type}`, {
|
||||
method: 'get',
|
||||
timeout,
|
||||
headers,
|
||||
family: 4,
|
||||
})
|
||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||
return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))
|
||||
})
|
||||
return requestObj
|
||||
},
|
||||
}
|
||||
|
||||
export default api_test
|
|
@ -0,0 +1,19 @@
|
|||
import { xmRequest } from './util'
|
||||
|
||||
export default {
|
||||
_requestObj: null,
|
||||
async getList(retryNum = 0) {
|
||||
if (this._requestObj) this._requestObj.cancelHttp()
|
||||
if (retryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
|
||||
const _requestObj = xmRequest('/api/search/getHotSearchWords')
|
||||
const { body, statusCode } = await _requestObj.promise
|
||||
// console.log(body)
|
||||
if (statusCode != 200 || body.code !== 'SUCCESS') return this.getList(++retryNum)
|
||||
// // console.log(body, statusCode)
|
||||
return { source: 'xm', list: this.filterList(body.result.data.hotWords) }
|
||||
},
|
||||
filterList(rawList) {
|
||||
return rawList.map(item => item.word)
|
||||
},
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
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'
|
||||
import hotSearch from './hotSearch'
|
||||
import { closeVerifyModal } from './util'
|
||||
|
||||
const xm = {
|
||||
songList,
|
||||
musicSearch,
|
||||
leaderboard,
|
||||
hotSearch,
|
||||
closeVerifyModal,
|
||||
getMusicUrl(songInfo, type) {
|
||||
return api_source('xm').getMusicUrl(songInfo, type)
|
||||
},
|
||||
getLyric(songInfo) {
|
||||
return lyric.getLyric(songInfo)
|
||||
},
|
||||
getPic(songInfo) {
|
||||
return Promise.reject(new Error('fail'))
|
||||
// return pic.getPic(songInfo)
|
||||
},
|
||||
// init() {
|
||||
// getToken()
|
||||
// },
|
||||
}
|
||||
|
||||
export default xm
|
|
@ -0,0 +1,147 @@
|
|||
import { xmRequest } from './util'
|
||||
import { formatPlayTime, sizeFormate } from '../../index'
|
||||
// import jshtmlencode from 'js-htmlencode'
|
||||
|
||||
export default {
|
||||
limit: 200,
|
||||
list: [
|
||||
{
|
||||
id: 'xmrgb',
|
||||
name: '热歌榜',
|
||||
bangid: '103',
|
||||
},
|
||||
{
|
||||
id: 'xmxgb',
|
||||
name: '新歌榜',
|
||||
bangid: '102',
|
||||
},
|
||||
{
|
||||
id: 'xmrcb',
|
||||
name: '原创榜',
|
||||
bangid: '104',
|
||||
},
|
||||
{
|
||||
id: 'xmdyb',
|
||||
name: '抖音榜',
|
||||
bangid: '332',
|
||||
},
|
||||
{
|
||||
id: 'xmkgb',
|
||||
name: 'K歌榜',
|
||||
bangid: '306',
|
||||
},
|
||||
{
|
||||
id: 'xmfxb',
|
||||
name: '分享榜',
|
||||
bangid: '307',
|
||||
},
|
||||
{
|
||||
id: 'xmrdtlb',
|
||||
name: '讨论榜',
|
||||
bangid: '331',
|
||||
},
|
||||
{
|
||||
id: 'xmgdslb',
|
||||
name: '歌单榜',
|
||||
bangid: '305',
|
||||
},
|
||||
{
|
||||
id: 'xmpjrgb',
|
||||
name: '趴间榜',
|
||||
bangid: '327',
|
||||
},
|
||||
{
|
||||
id: 'xmysysb',
|
||||
name: '影视榜',
|
||||
bangid: '324',
|
||||
},
|
||||
],
|
||||
requestObj: null,
|
||||
getData(id) {
|
||||
if (this.requestObj) this.requestObj.cancelHttp()
|
||||
this.requestObj = xmRequest('/api/billboard/getBillboardDetail', { billboardId: id })
|
||||
return this.requestObj.promise
|
||||
},
|
||||
getSinger(singers) {
|
||||
let arr = []
|
||||
singers.forEach(singer => {
|
||||
arr.push(singer.artistName)
|
||||
})
|
||||
return arr.join('、')
|
||||
},
|
||||
filterData(rawList) {
|
||||
// console.log(rawList)
|
||||
let ids = new Set()
|
||||
const list = []
|
||||
rawList.forEach(songData => {
|
||||
if (!songData) return
|
||||
if (ids.has(songData.songId)) return
|
||||
ids.add(songData.songId)
|
||||
|
||||
const types = []
|
||||
const _types = {}
|
||||
let size = null
|
||||
for (const item of songData.purviewRoleVOs) {
|
||||
if (!item.filesize) continue
|
||||
size = sizeFormate(item.filesize)
|
||||
switch (item.quality) {
|
||||
case 's':
|
||||
types.push({ type: 'wav', size })
|
||||
_types.wav = {
|
||||
size,
|
||||
}
|
||||
break
|
||||
case 'h':
|
||||
types.push({ type: '320k', size })
|
||||
_types['320k'] = {
|
||||
size,
|
||||
}
|
||||
break
|
||||
case 'l':
|
||||
types.push({ type: '128k', size })
|
||||
_types['128k'] = {
|
||||
size,
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
types.reverse()
|
||||
|
||||
list.push({
|
||||
singer: this.getSinger(songData.singerVOs),
|
||||
name: songData.songName,
|
||||
albumName: songData.albumName,
|
||||
albumId: songData.albumId,
|
||||
source: 'xm',
|
||||
interval: formatPlayTime(parseInt(songData.length / 1000)),
|
||||
songmid: songData.songId,
|
||||
img: songData.albumLogo || songData.albumLogoS,
|
||||
lrc: null,
|
||||
lrcUrl: songData.lyricInfo && songData.lyricInfo.lyricFile,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
})
|
||||
})
|
||||
|
||||
return list
|
||||
},
|
||||
getList(id, page, retryNum = 0) {
|
||||
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
|
||||
let type = this.list.find(s => s.id === id)
|
||||
if (!type) return Promise.reject()
|
||||
return this.getData(type.bangid).then(({ statusCode, body }) => {
|
||||
if (statusCode !== 200 || body.code !== 'SUCCESS') return this.getList(id, page, retryNum)
|
||||
// console.log(body)
|
||||
const list = this.filterData(body.result.data.billboard.songs)
|
||||
|
||||
return {
|
||||
total: parseInt(body.result.data.billboard.attributeMap.item_size),
|
||||
list,
|
||||
limit: this.limit,
|
||||
page,
|
||||
source: 'xm',
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
import { httpGet, httpFetch } from '../../request'
|
||||
import { xmRequest } from './util'
|
||||
|
||||
export default {
|
||||
failTime: 0,
|
||||
expireTime: 60 * 1000 * 1000,
|
||||
getLyricFile_1(url, retryNum = 0) {
|
||||
if (retryNum > 5) return Promise.reject('歌词获取失败')
|
||||
let requestObj = httpFetch(url)
|
||||
requestObj.promise = requestObj.promise.then(({ body, statusCode }) => {
|
||||
if (statusCode !== 200) {
|
||||
let tryRequestObj = this.getLyric(url, ++retryNum)
|
||||
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
|
||||
return tryRequestObj.promise
|
||||
}
|
||||
return body
|
||||
})
|
||||
return requestObj
|
||||
},
|
||||
getLyricFile_2(url, retryNum = 0) {
|
||||
if (retryNum > 5) return Promise.reject('歌词获取失败')
|
||||
return new Promise((resolve, reject) => {
|
||||
httpGet(url, {
|
||||
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',
|
||||
referer: 'https://www.xiami.com',
|
||||
},
|
||||
}, function(err, resp, body) {
|
||||
if (err || resp.statusCode !== 200) return this.getLyricFile(url, ++retryNum).then(resolve).catch(reject)
|
||||
return resolve(body)
|
||||
})
|
||||
})
|
||||
},
|
||||
getLyricUrl_1(songInfo, retryNum = 0) {
|
||||
if (retryNum > 2) return Promise.reject('歌词获取失败')
|
||||
let requestObj = xmRequest('/api/lyric/getSongLyrics', { songId: songInfo.songmid })
|
||||
requestObj.promise = requestObj.promise.then(({ statusCode, body }) => {
|
||||
if (statusCode !== 200) {
|
||||
let tryRequestObj = this.getLyricUrl_1(songInfo, ++retryNum)
|
||||
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
|
||||
return tryRequestObj.promise
|
||||
}
|
||||
if (body.code !== 'SUCCESS') {
|
||||
this.failTime = Date.now()
|
||||
let tryRequestObj = this.getLyricUrl_2(songInfo)
|
||||
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
|
||||
return tryRequestObj.promise
|
||||
}
|
||||
if (!body.result.data.lyrics.length) return Promise.reject(new Error('未找到歌词'))
|
||||
let lrc = body.result.data.lyrics.find(lyric => /\.lrc$/.test(lyric.lyricUrl))
|
||||
return lrc ? lrc.content : Promise.reject(new Error('未找到歌词'))
|
||||
})
|
||||
return requestObj
|
||||
},
|
||||
getLyricUrl_2(songInfo, retryNum = 0) {
|
||||
if (retryNum > 2) return Promise.reject('歌词获取失败')
|
||||
// https://github.com/listen1/listen1_chrome_extension/blob/2587e627d23a85e490628acc0b3c9b534bc8323d/js/provider/xiami.js#L149
|
||||
let requestObj = httpFetch(`https://emumo.xiami.com/song/playlist/id/${songInfo.songmid}/object_name/default/object_id/0/cat/json`, {
|
||||
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',
|
||||
referer: 'https://www.xiami.com',
|
||||
},
|
||||
})
|
||||
requestObj.promise = requestObj.promise.then(({ statusCode, body }) => {
|
||||
if (statusCode !== 200 || !body.status) {
|
||||
let tryRequestObj = this.getLyricUrl_2(songInfo, ++retryNum)
|
||||
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
|
||||
return tryRequestObj.promise
|
||||
}
|
||||
let url = body.data.trackList[0].lyric_url
|
||||
if (!url) return Promise.reject(new Error('未找到歌词'))
|
||||
return this.getLyricFile_2(/^http:/.test(url) ? url : ('http:' + url))
|
||||
})
|
||||
return requestObj
|
||||
},
|
||||
getLyric(songInfo) {
|
||||
if (songInfo.lrcUrl && /\.lrc$/.test(songInfo.lrcUrl)) return this.getLyricFile_1(songInfo.lrcUrl)
|
||||
return Date.now() - this.failTime > this.expireTime ? this.getLyricUrl_1(songInfo) : this.getLyricUrl_2(songInfo)
|
||||
},
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
// import '../../polyfill/array.find'
|
||||
// import jshtmlencode from 'js-htmlencode'
|
||||
import { xmRequest } from './util'
|
||||
import { formatPlayTime, sizeFormate } from '../../index'
|
||||
// import { debug } from '../../utils/env'
|
||||
// import { formatSinger } from './util'
|
||||
// "cdcb72dc3eba41cb5bc4267f09183119_xmMain_/api/list/collect_{"pagingVO":{"page":1,"pageSize":60},"dataType":"system"}"
|
||||
let searchRequest
|
||||
export default {
|
||||
limit: 30,
|
||||
total: 0,
|
||||
page: 0,
|
||||
allPage: 1,
|
||||
musicSearch(str, page) {
|
||||
if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp()
|
||||
searchRequest = xmRequest('/api/search/searchSongs', {
|
||||
key: str,
|
||||
pagingVO: {
|
||||
page: page,
|
||||
pageSize: this.limit,
|
||||
},
|
||||
})
|
||||
return searchRequest.promise.then(({ body }) => body)
|
||||
},
|
||||
getSinger(singers) {
|
||||
let arr = []
|
||||
singers.forEach(singer => {
|
||||
arr.push(singer.artistName)
|
||||
})
|
||||
return arr.join('、')
|
||||
},
|
||||
handleResult(rawData) {
|
||||
// console.log(rawData)
|
||||
let ids = new Set()
|
||||
const list = []
|
||||
rawData.forEach(songData => {
|
||||
if (!songData) return
|
||||
if (ids.has(songData.songId)) return
|
||||
ids.add(songData.songId)
|
||||
|
||||
const types = []
|
||||
const _types = {}
|
||||
let size = null
|
||||
for (const item of songData.purviewRoleVOs) {
|
||||
if (!item.filesize) continue
|
||||
size = sizeFormate(item.filesize)
|
||||
switch (item.quality) {
|
||||
case 's':
|
||||
types.push({ type: 'wav', size })
|
||||
_types.wav = {
|
||||
size,
|
||||
}
|
||||
break
|
||||
case 'h':
|
||||
types.push({ type: '320k', size })
|
||||
_types['320k'] = {
|
||||
size,
|
||||
}
|
||||
break
|
||||
case 'l':
|
||||
types.push({ type: '128k', size })
|
||||
_types['128k'] = {
|
||||
size,
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
types.reverse()
|
||||
|
||||
list.push({
|
||||
singer: this.getSinger(songData.singerVOs),
|
||||
name: songData.songName,
|
||||
albumName: songData.albumName,
|
||||
albumId: songData.albumId,
|
||||
source: 'xm',
|
||||
interval: formatPlayTime(parseInt(songData.length / 1000)),
|
||||
songmid: songData.songId,
|
||||
img: songData.albumLogo || songData.albumLogoS,
|
||||
lrc: null,
|
||||
lrcUrl: songData.lyricInfo && songData.lyricInfo.lyricFile,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
})
|
||||
})
|
||||
return list
|
||||
},
|
||||
search(str, page = 1, { limit } = {}, retryNum = 0) {
|
||||
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
|
||||
if (limit != null) this.limit = limit
|
||||
// http://newlyric.kuwo.cn/newlyric.lrc?62355680
|
||||
return this.musicSearch(str, page).then(result => {
|
||||
// console.log(result)
|
||||
if (!result) return this.search(str, page, { limit }, retryNum)
|
||||
if (result.code !== 'SUCCESS') return this.search(str, page, { limit }, retryNum)
|
||||
// const songResultData = result.data || { songs: [], total: 0 }
|
||||
|
||||
let list = this.handleResult(result.result.data.songs)
|
||||
if (list == null) return this.search(str, page, { limit }, retryNum)
|
||||
|
||||
this.total = parseInt(result.result.data.pagingVO.count)
|
||||
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: 'xm',
|
||||
})
|
||||
}).catch(() => this.search(str, page, { limit }, retryNum))
|
||||
},
|
||||
}
|
|
@ -0,0 +1,219 @@
|
|||
import { xmRequest } from './util'
|
||||
import { sizeFormate, formatPlayTime } from '../../index'
|
||||
|
||||
export default {
|
||||
_requestObj_tags: null,
|
||||
_requestObj_list: null,
|
||||
_requestObj_listDetail: null,
|
||||
limit_list: 36,
|
||||
limit_song: 100000,
|
||||
successCode: 'SUCCESS',
|
||||
sortList: [
|
||||
{
|
||||
name: '推荐',
|
||||
id: 'system',
|
||||
},
|
||||
{
|
||||
name: '精选',
|
||||
id: 'recommend',
|
||||
},
|
||||
{
|
||||
name: '最热',
|
||||
id: 'hot',
|
||||
},
|
||||
{
|
||||
name: '最新',
|
||||
id: 'new',
|
||||
},
|
||||
],
|
||||
regExps: {
|
||||
// https://www.xiami.com/collect/1138092824?action=play
|
||||
listDetailLink: /^.+\/collect\/(\d+)(?:\s\(.*|\?.*|&.*$|#.*$|$)/,
|
||||
},
|
||||
tagsUrl: '/api/collect/getRecommendTags',
|
||||
songListUrl: '/api/list/collect',
|
||||
songListDetailUrl: '/api/collect/initialize',
|
||||
getSongListData(sortId, tagId, page) {
|
||||
if (tagId == null) {
|
||||
return { pagingVO: { page, pageSize: this.limit_list }, dataType: sortId }
|
||||
}
|
||||
switch (sortId) {
|
||||
case 'system':
|
||||
case 'recommend':
|
||||
sortId = 'hot'
|
||||
}
|
||||
return { pagingVO: { page, pageSize: this.limit_list }, dataType: sortId, key: tagId }
|
||||
},
|
||||
|
||||
/**
|
||||
* 格式化播放数量
|
||||
* @param {*} num
|
||||
*/
|
||||
formatPlayCount(num) {
|
||||
if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿'
|
||||
if (num > 10000) return parseInt(num / 1000) / 10 + '万'
|
||||
return num
|
||||
},
|
||||
getSinger(singers) {
|
||||
let arr = []
|
||||
singers.forEach(singer => {
|
||||
arr.push(singer.artistName)
|
||||
})
|
||||
return arr.join('、')
|
||||
},
|
||||
|
||||
getListDetail(id, page, tryNum = 0) { // 获取歌曲列表内的音乐
|
||||
if (this._requestObj_listDetail) this._requestObj_listDetail.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
|
||||
if ((/[?&:/]/.test(id))) id = id.replace(this.regExps.listDetailLink, '$1')
|
||||
|
||||
this._requestObj_listDetail = xmRequest('/api/collect/getCollectStaticUrl', { listId: id })
|
||||
return this._requestObj_listDetail.promise.then(({ body }) => {
|
||||
if (body.code !== this.successCode) return this.getListDetail(id, page, ++tryNum)
|
||||
this._requestObj_listDetail = xmRequest(body.result.data.data.data.url)
|
||||
return this._requestObj_listDetail.promise.then(({ body }) => {
|
||||
if (!body.status) return this.getListDetail(id, page, ++tryNum)
|
||||
// console.log(JSON.stringify(body))
|
||||
return {
|
||||
list: this.filterListDetail(body.resultObj.songs),
|
||||
page,
|
||||
limit: this.limit_song,
|
||||
total: body.resultObj.songCount,
|
||||
source: 'xm',
|
||||
info: {
|
||||
name: body.resultObj.collectName,
|
||||
img: body.resultObj.collectLogo,
|
||||
desc: body.resultObj.description,
|
||||
author: body.resultObj.userName,
|
||||
play_count: this.formatPlayCount(body.resultObj.playCount),
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
filterListDetail(rawList) {
|
||||
// console.log(rawList)
|
||||
let ids = new Set()
|
||||
const list = []
|
||||
rawList.forEach(songData => {
|
||||
if (!songData) return
|
||||
if (ids.has(songData.songId)) return
|
||||
ids.add(songData.songId)
|
||||
|
||||
const types = []
|
||||
const _types = {}
|
||||
let size = null
|
||||
for (const item of songData.purviewRoleVOs) {
|
||||
if (!item.filesize) continue
|
||||
size = sizeFormate(item.filesize)
|
||||
switch (item.quality) {
|
||||
case 's':
|
||||
types.push({ type: 'wav', size })
|
||||
_types.wav = {
|
||||
size,
|
||||
}
|
||||
break
|
||||
case 'h':
|
||||
types.push({ type: '320k', size })
|
||||
_types['320k'] = {
|
||||
size,
|
||||
}
|
||||
break
|
||||
case 'l':
|
||||
types.push({ type: '128k', size })
|
||||
_types['128k'] = {
|
||||
size,
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
types.reverse()
|
||||
|
||||
list.push({
|
||||
singer: this.getSinger(songData.singerVOs),
|
||||
name: songData.songName,
|
||||
albumName: songData.albumName,
|
||||
albumId: songData.albumId,
|
||||
source: 'xm',
|
||||
interval: formatPlayTime(parseInt(songData.length / 1000)),
|
||||
songmid: songData.songId,
|
||||
img: songData.albumLogo || songData.albumLogoS,
|
||||
lrc: null,
|
||||
lrcUrl: songData.lyricInfo && songData.lyricInfo.lyricFile,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
})
|
||||
})
|
||||
return list
|
||||
},
|
||||
|
||||
// 获取列表数据
|
||||
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 = xmRequest(this.songListUrl, this.getSongListData(sortId, tagId, page))
|
||||
return this._requestObj_list.promise.then(({ body }) => {
|
||||
if (body.code !== this.successCode) return this.getList(sortId, tagId, page, ++tryNum)
|
||||
return {
|
||||
list: this.filterList(body.result.data.collects),
|
||||
total: body.result.data.pagingVO.count,
|
||||
page,
|
||||
limit: body.result.data.pagingVO.pageSize,
|
||||
source: 'xm',
|
||||
}
|
||||
})
|
||||
},
|
||||
filterList(rawData) {
|
||||
return rawData.map(item => ({
|
||||
play_count: this.formatPlayCount(item.playCount),
|
||||
id: item.listId,
|
||||
author: item.userName,
|
||||
name: item.collectName,
|
||||
time: null,
|
||||
img: item.collectLogo,
|
||||
grade: null,
|
||||
desc: null,
|
||||
source: 'xm',
|
||||
}))
|
||||
},
|
||||
|
||||
// 获取标签
|
||||
getTag(tryNum = 0) {
|
||||
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_tags = xmRequest(this.tagsUrl, { recommend: 1 })
|
||||
return this._requestObj_tags.promise.then(({ body }) => {
|
||||
if (body.code !== this.successCode) return this.getTag(++tryNum)
|
||||
return this.filterTagInfo(body.result.data.recommendTags)
|
||||
})
|
||||
},
|
||||
filterTagInfo(rawList) {
|
||||
return {
|
||||
hotTag: rawList[0].items.map(item => ({
|
||||
id: item.name,
|
||||
name: item.name,
|
||||
source: 'xm',
|
||||
})),
|
||||
tags: rawList.slice(1).map(item => ({
|
||||
name: item.title,
|
||||
list: item.items.map(tag => ({
|
||||
parent_id: item.title,
|
||||
parent_name: item.title,
|
||||
id: tag.name,
|
||||
name: tag.name,
|
||||
source: 'xm',
|
||||
})),
|
||||
})),
|
||||
source: 'xm',
|
||||
}
|
||||
},
|
||||
getTags() {
|
||||
return this.getTag()
|
||||
},
|
||||
}
|
||||
|
||||
// getList
|
||||
// getTags
|
||||
// getListDetail
|
|
@ -0,0 +1,119 @@
|
|||
import { httpGet, httpFetch } from '../../request'
|
||||
import { toMD5 } from '../../index'
|
||||
// import crateIsg from './isg'
|
||||
import { rendererInvoke } from '../../../../common/ipc'
|
||||
|
||||
if (!window.xm_token) {
|
||||
let data = window.localStorage.getItem('xm_token')
|
||||
window.xm_token = data ? JSON.parse(data) : {
|
||||
cookies: {},
|
||||
cookie: null,
|
||||
token: null,
|
||||
isGetingToken: false,
|
||||
}
|
||||
window.xm_token.isGetingToken = false
|
||||
}
|
||||
|
||||
export const formatSinger = rawData => rawData.replace(/&/g, '、')
|
||||
|
||||
const matchToken = headers => {
|
||||
let cookies = {}
|
||||
let token
|
||||
for (const item of headers['set-cookie']) {
|
||||
const [key, value] = item.substring(0, item.indexOf(';')).split('=')
|
||||
cookies[key] = value
|
||||
if (key == 'xm_sg_tk') token = value.substring(0, value.indexOf('_'))
|
||||
}
|
||||
// console.log(cookies)
|
||||
return { token, cookies }
|
||||
}
|
||||
|
||||
const wait = time => new Promise(resolve => setTimeout(() => resolve(), time))
|
||||
|
||||
const createToken = (token, path, params) => toMD5(`${token}_xmMain_${path}_${params}`)
|
||||
|
||||
const handleSaveToken = ({ token, cookies }) => {
|
||||
Object.assign(window.xm_token.cookies, cookies)
|
||||
// window.xm_token.cookies.isg = crateIsg()
|
||||
window.xm_token.cookie = Object.keys(window.xm_token.cookies).map(k => `${k}=${window.xm_token.cookies[k]};`).join(' ')
|
||||
if (token) window.xm_token.token = token
|
||||
|
||||
window.localStorage.setItem('xm_token', JSON.stringify(window.xm_token))
|
||||
}
|
||||
|
||||
export const getToken = (path, params) => new Promise((resolve, reject) => {
|
||||
if (window.xm_token.isGetingToken) return wait(1000).then(() => getToken(path, params).then(data => resolve(data)))
|
||||
if (window.xm_token.token) return resolve({ token: createToken(window.xm_token.token, path, params), cookie: window.xm_token.cookie })
|
||||
window.xm_token.isGetingToken = true
|
||||
httpGet('https://www.xiami.com/', (err, resp) => {
|
||||
window.xm_token.isGetingToken = false
|
||||
if (err) return reject(err)
|
||||
if (resp.statusCode != 200) return reject(new Error('获取失败'))
|
||||
|
||||
handleSaveToken(matchToken(resp.headers))
|
||||
|
||||
resolve({ token: createToken(window.xm_token.token, path, params), cookie: window.xm_token.cookie })
|
||||
})
|
||||
})
|
||||
|
||||
const baseUrl = 'https://www.xiami.com'
|
||||
export const xmRequest = (path, params = '') => {
|
||||
let query = params
|
||||
if (params != '') {
|
||||
params = JSON.stringify(params)
|
||||
query = '&_q=' + encodeURIComponent(params)
|
||||
}
|
||||
let requestObj = {
|
||||
isInited: false,
|
||||
isCancelled: false,
|
||||
cancelHttp() {
|
||||
if (!this.isInited) this.isCancelled = true
|
||||
this.requestObj.cancelHttp()
|
||||
},
|
||||
}
|
||||
|
||||
requestObj.promise = getToken(path, params).then(data => {
|
||||
// console.log(data)
|
||||
if (requestObj.isCancelled) return Promise.reject('取消请求')
|
||||
let url = path
|
||||
if (!/^http/.test(path)) url = baseUrl + path
|
||||
let s = `_s=${data.token}${query}`
|
||||
url += (url.includes('?') ? '&' : '?') + s
|
||||
requestObj.requestObj = httpFetch(url, {
|
||||
headers: {
|
||||
Referer: 'https://www.xiami.com/',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
|
||||
cookie: data.cookie,
|
||||
},
|
||||
})
|
||||
return requestObj.requestObj.promise.then(resp => {
|
||||
// console.log(resp.body)
|
||||
if (resp.statusCode != 200) {
|
||||
// console.log(resp.headers)
|
||||
window.xm_token.token = null
|
||||
return Promise.reject(new Error('获取失败'))
|
||||
}
|
||||
if (resp.body.code !== 'SUCCESS' && resp.body.rgv587_flag == 'sm') {
|
||||
window.globalObj.xm.isShowVerify = true
|
||||
return wait(300).then(() => {
|
||||
return rendererInvoke('xm_verify_open', 'https:' + resp.body.url).then(x5sec => {
|
||||
handleSaveToken({ cookies: { x5sec } })
|
||||
// console.log(x5sec)
|
||||
window.globalObj.xm.isShowVerify = false
|
||||
return Promise.reject(new Error('获取失败'))
|
||||
})
|
||||
})
|
||||
}
|
||||
if (resp.headers['set-cookie']) handleSaveToken(matchToken(resp.headers))
|
||||
|
||||
return Promise.resolve(resp)
|
||||
})
|
||||
})
|
||||
return requestObj
|
||||
}
|
||||
|
||||
export const closeVerifyModal = async() => {
|
||||
if (!window.globalObj.xm.isShowVerify) return
|
||||
await rendererInvoke('xm_verify_close')
|
||||
window.globalObj.xm.isShowVerify = false
|
||||
}
|
|
@ -129,6 +129,8 @@ export default {
|
|||
case 'tx':
|
||||
case 'wy':
|
||||
type = '128k'
|
||||
case 'xm':
|
||||
if (type == 'flac') type = 'wav'
|
||||
}
|
||||
this.createDownloadMultiple({ list: [...this.selectdData], type })
|
||||
this.isShowDownloadMultiple = false
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
material-checkbox(:id="index.toString()" v-model="selectdData" :value="item")
|
||||
td.break(style="width: 25%;")
|
||||
span.select {{item.name}}
|
||||
span.badge.badge-theme-success(:class="$style.labelQuality" v-if="item._types.ape || item._types.flac") {{$t('material.song_list.lossless')}}
|
||||
span.badge.badge-theme-success(:class="$style.labelQuality" v-if="item._types.ape || item._types.flac || item._types.wav") {{$t('material.song_list.lossless')}}
|
||||
span.badge.badge-theme-info(:class="$style.labelQuality" v-else-if="item._types['320k']") {{$t('material.song_list.high_quality')}}
|
||||
span(:class="$style.labelSource" v-if="searchSourceId == 'all'") {{item.source}}
|
||||
td.break(style="width: 20%;")
|
||||
|
|
|
@ -100,6 +100,7 @@ export default {
|
|||
case 'tx':
|
||||
case 'mg':
|
||||
case 'kg':
|
||||
case 'xm':
|
||||
list.push({
|
||||
name: this.$t('view.song_list.open_list', { name: this.sourceInfo.sources.find(s => s.id == this.source).name }),
|
||||
id: 'importSongList',
|
||||
|
@ -254,6 +255,8 @@ export default {
|
|||
case 'tx':
|
||||
case 'wy':
|
||||
type = '128k'
|
||||
case 'xm':
|
||||
if (type == 'flac') type = 'wav'
|
||||
}
|
||||
this.createDownloadMultiple({ list: this.filterList(this.selectdData), type })
|
||||
this.resetSelect()
|
||||
|
|
Loading…
Reference in New Issue