修复网易云128k直接试听
parent
a104ce688e
commit
9dc9d3b1b7
|
@ -2,3 +2,4 @@
|
||||||
|
|
||||||
- 修复QQ源歌单无法翻页Bug
|
- 修复QQ源歌单无法翻页Bug
|
||||||
- 修复默认列表没有创建时无法显示收藏列表的Bug
|
- 修复默认列表没有创建时无法显示收藏列表的Bug
|
||||||
|
- 修复网易云128k直接试听
|
||||||
|
|
|
@ -5,7 +5,7 @@ material-modal(:show="show" :bg-close="bgClose" @close="handleClose")
|
||||||
| {{ info.name }}
|
| {{ info.name }}
|
||||||
br
|
br
|
||||||
| {{ info.singer }}
|
| {{ info.singer }}
|
||||||
material-btn(:class="$style.btn" :title="!checkSource(type.type) && '目前腾讯音源仅支持下载128k音质'" :disabled="!checkSource(type.type)" :key="type.type" @click="handleClick(type.type)" v-for="type in info.types") {{getTypeName(type.type)}} {{ type.type.toUpperCase() }}{{ type.size && ` - ${type.size.toUpperCase()}` }}
|
material-btn(:class="$style.btn" :title="!checkSource(type.type) && '腾讯、网易音源仅支持下载128k音质'" :disabled="!checkSource(type.type)" :key="type.type" @click="handleClick(type.type)" v-for="type in info.types") {{getTypeName(type.type)}} {{ type.type.toUpperCase() }}{{ type.size && ` - ${type.size.toUpperCase()}` }}
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -52,7 +52,6 @@ export default {
|
||||||
checkSource(type) {
|
checkSource(type) {
|
||||||
switch (this.musicInfo.source) {
|
switch (this.musicInfo.source) {
|
||||||
case 'wy':
|
case 'wy':
|
||||||
return false
|
|
||||||
case 'tx':
|
case 'tx':
|
||||||
return type == '128k'
|
return type == '128k'
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,9 @@ div(:class="$style.songList")
|
||||||
td(style="width: 20%; padding-left: 0; padding-right: 0;")
|
td(style="width: 20%; padding-left: 0; padding-right: 0;")
|
||||||
material-list-buttons(:index="index" :search-btn="true"
|
material-list-buttons(:index="index" :search-btn="true"
|
||||||
:remove-btn="false" @btn-click="handleListBtnClick"
|
:remove-btn="false" @btn-click="handleListBtnClick"
|
||||||
:listAdd-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
|
:listAdd-btn="item.source == 'kw' || (!isAPITemp)"
|
||||||
:play-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
|
:play-btn="item.source == 'kw' || (!isAPITemp)"
|
||||||
:download-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')")
|
:download-btn="item.source == 'kw' || (!isAPITemp)")
|
||||||
//- button.btn-info(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k'] || item._types.flac" @click.stop='openDownloadModal(index)') 下载
|
//- button.btn-info(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k'] || item._types.flac" @click.stop='openDownloadModal(index)') 下载
|
||||||
//- button.btn-secondary(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k']" @click.stop='testPlay(index)') 试听
|
//- button.btn-secondary(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k']" @click.stop='testPlay(index)') 试听
|
||||||
//- button.btn-success(type='button' v-if="(item._types['128k'] || item._types['192k'] || item._types['320k']) && userInfo" @click.stop='showListModal(index)') +
|
//- button.btn-success(type='button' v-if="(item._types['128k'] || item._types['192k'] || item._types['320k']) && userInfo" @click.stop='showListModal(index)') +
|
||||||
|
@ -140,7 +140,7 @@ export default {
|
||||||
this.clickIndex = index
|
this.clickIndex = index
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.emitEvent((this.source == 'kw' || (!this.isAPITemp && this.list[index].source != 'wy')) ? 'testPlay' : 'search', index)
|
this.emitEvent((this.source == 'kw' || !this.isAPITemp) ? 'testPlay' : 'search', index)
|
||||||
this.clickTime = 0
|
this.clickTime = 0
|
||||||
this.clickIndex = -1
|
this.clickIndex = -1
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
import { httpFatch } from '../../request'
|
|
||||||
import { requestMsg } from '../../message'
|
|
||||||
import { headers, timeout } from '../options'
|
|
||||||
|
|
||||||
const api_messoer = {
|
|
||||||
getMusicUrl(songInfo, type) {
|
|
||||||
const requestObj = httpFatch(`https://v1.itooi.cn/netease/url?id=${songInfo.songmid}&quality=${type.replace(/k$/, '')}&isRedirect=0`, {
|
|
||||||
method: 'get',
|
|
||||||
timeout,
|
|
||||||
headers,
|
|
||||||
})
|
|
||||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
|
||||||
return body.code === 200 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))
|
|
||||||
})
|
|
||||||
return requestObj
|
|
||||||
},
|
|
||||||
getPic(songInfo) {
|
|
||||||
const requestObj = httpFatch(`https://v1.itooi.cn/netease/pic?id=${songInfo.songmid}&isRedirect=0`, {
|
|
||||||
method: 'get',
|
|
||||||
timeout,
|
|
||||||
headers,
|
|
||||||
})
|
|
||||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
|
||||||
return body.code === 200 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))
|
|
||||||
})
|
|
||||||
return requestObj
|
|
||||||
},
|
|
||||||
getLyric(songInfo) {
|
|
||||||
const requestObj = httpFatch(`https://v1.itooi.cn/netease/lrc?id=${songInfo.songmid}&isRedirect=0`, {
|
|
||||||
method: 'get',
|
|
||||||
timeout,
|
|
||||||
headers,
|
|
||||||
})
|
|
||||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
|
||||||
return body ? Promise.resolve(body) : Promise.reject(new Error(requestMsg.fail))
|
|
||||||
})
|
|
||||||
return requestObj
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default api_messoer
|
|
|
@ -15,8 +15,8 @@ const api_test = {
|
||||||
})
|
})
|
||||||
return requestObj
|
return requestObj
|
||||||
},
|
},
|
||||||
getPic(songInfo) {
|
/* getPic(songInfo) {
|
||||||
const requestObj = httpFetch(`http://ts.tempmusic.tk/pic/wy/${songInfo.songmid}`, {
|
const requestObj = httpFetch(`http://localhost:3100/pic/wy/${songInfo.songmid}`, {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
timeout,
|
timeout,
|
||||||
headers,
|
headers,
|
||||||
|
@ -28,7 +28,7 @@ const api_test = {
|
||||||
return requestObj
|
return requestObj
|
||||||
},
|
},
|
||||||
getLyric(songInfo) {
|
getLyric(songInfo) {
|
||||||
const requestObj = httpFetch(`http://ts.tempmusic.tk/lrc/wy/${songInfo.songmid}`, {
|
const requestObj = httpFetch(`http://localhost:3100/lrc/wy/${songInfo.songmid}`, {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
timeout,
|
timeout,
|
||||||
headers,
|
headers,
|
||||||
|
@ -38,7 +38,7 @@ const api_test = {
|
||||||
return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))
|
return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))
|
||||||
})
|
})
|
||||||
return requestObj
|
return requestObj
|
||||||
},
|
}, */
|
||||||
}
|
}
|
||||||
|
|
||||||
export default api_test
|
export default api_test
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import leaderboard from './leaderboard'
|
import leaderboard from './leaderboard'
|
||||||
import api_source from '../api-source'
|
import api_source from '../api-source'
|
||||||
|
import getLyric from './lyric'
|
||||||
|
import getMusicInfo from './musicInfo'
|
||||||
|
|
||||||
const wy = {
|
const wy = {
|
||||||
leaderboard,
|
leaderboard,
|
||||||
|
@ -7,10 +9,10 @@ const wy = {
|
||||||
return api_source('wy').getMusicUrl(songInfo, type)
|
return api_source('wy').getMusicUrl(songInfo, type)
|
||||||
},
|
},
|
||||||
getLyric(songInfo) {
|
getLyric(songInfo) {
|
||||||
return api_source('wy').getLyric(songInfo)
|
return getLyric(songInfo.songmid)
|
||||||
},
|
},
|
||||||
getPic(songInfo) {
|
getPic(songInfo) {
|
||||||
return api_source('wy').getPic(songInfo)
|
return getMusicInfo(songInfo.songmid).then(info => info.al.picUrl)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { httpFetch } from '../../request'
|
||||||
|
import { linuxapi } from './utils/crypto'
|
||||||
|
|
||||||
|
export default songmid => {
|
||||||
|
const requestObj = httpFetch('https://music.163.com/api/linux/forward', {
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36',
|
||||||
|
Referer: 'https://music.163.com/song?id=' + songmid,
|
||||||
|
origin: 'https://music.163.com',
|
||||||
|
},
|
||||||
|
form: linuxapi({
|
||||||
|
method: 'POST',
|
||||||
|
url: 'https://music.163.com/api/song/lyric?lv=-1&kv=-1&tv=-1',
|
||||||
|
params: {
|
||||||
|
id: songmid,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||||
|
// console.log(body)
|
||||||
|
if (body.code !== 200) return Promise.reject('获取歌词失败')
|
||||||
|
return body.lrc.lyric
|
||||||
|
})
|
||||||
|
return requestObj
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/song_detail.js
|
||||||
|
import { httpFetch } from '../../request'
|
||||||
|
import { weapi } from './utils/crypto'
|
||||||
|
|
||||||
|
export default songmid => {
|
||||||
|
const requestObj = httpFetch('https://music.163.com/weapi/v3/song/detail', {
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36',
|
||||||
|
Referer: 'https://music.163.com/song?id=' + songmid,
|
||||||
|
origin: 'https://music.163.com',
|
||||||
|
},
|
||||||
|
form: weapi({
|
||||||
|
c: `[{"id":${songmid}}]`,
|
||||||
|
ids: '[songmid]',
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||||
|
// console.log(body)
|
||||||
|
if (body.code !== 200 || !body.songs.length) return Promise.reject('获取歌曲信息失败')
|
||||||
|
return body.songs[0]
|
||||||
|
})
|
||||||
|
return requestObj
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/util/crypto.js
|
||||||
|
|
||||||
|
import { createCipheriv, publicEncrypt, constants, randomBytes } from 'crypto'
|
||||||
|
const iv = Buffer.from('0102030405060708')
|
||||||
|
const presetKey = Buffer.from('0CoJUm6Qyw8W8jud')
|
||||||
|
const linuxapiKey = Buffer.from('rFgB&h#%2?^eDg:Q')
|
||||||
|
const base62 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
||||||
|
const publicKey = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgtQn2JZ34ZC28NWYpAUd98iZ37BUrX/aKzmFbt7clFSs6sXqHauqKWqdtLkF2KexO40H1YTX8z2lSgBBOAxLsvaklV8k4cBFK9snQXE9/DDaFt6Rr7iVZMldczhC0JNgTz+SHXT6CBHuX3e9SdB1Ua44oncaTWz7OBGLbCiK45wIDAQAB\n-----END PUBLIC KEY-----'
|
||||||
|
|
||||||
|
const aesEncrypt = (buffer, mode, key, iv) => {
|
||||||
|
const cipher = createCipheriv('aes-128-' + mode, key, iv)
|
||||||
|
return Buffer.concat([cipher.update(buffer), cipher.final()])
|
||||||
|
}
|
||||||
|
|
||||||
|
const rsaEncrypt = (buffer, key) => {
|
||||||
|
buffer = Buffer.concat([Buffer.alloc(128 - buffer.length), buffer])
|
||||||
|
return publicEncrypt({ key: key, padding: constants.RSA_NO_PADDING }, buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const weapi = object => {
|
||||||
|
const text = JSON.stringify(object)
|
||||||
|
const secretKey = randomBytes(16).map(n => (base62.charAt(n % 62).charCodeAt()))
|
||||||
|
return {
|
||||||
|
params: aesEncrypt(Buffer.from(aesEncrypt(Buffer.from(text), 'cbc', presetKey, iv).toString('base64')), 'cbc', secretKey, iv).toString('base64'),
|
||||||
|
encSecKey: rsaEncrypt(secretKey.reverse(), publicKey).toString('hex'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const linuxapi = object => {
|
||||||
|
const text = JSON.stringify(object)
|
||||||
|
return {
|
||||||
|
eparams: aesEncrypt(Buffer.from(text), 'ecb', linuxapiKey, '').toString('hex').toUpperCase(),
|
||||||
|
}
|
||||||
|
}
|
|
@ -126,6 +126,7 @@ export default {
|
||||||
handleAddDownloadMultiple(type) {
|
handleAddDownloadMultiple(type) {
|
||||||
switch (this.source) {
|
switch (this.source) {
|
||||||
// case 'kg':
|
// case 'kg':
|
||||||
|
case 'tx':
|
||||||
case 'wy':
|
case 'wy':
|
||||||
type = '128k'
|
type = '128k'
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
table
|
table
|
||||||
tbody
|
tbody
|
||||||
tr(v-for='(item, index) in list' :key='item.songmid'
|
tr(v-for='(item, index) in list' :key='item.songmid'
|
||||||
@click="handleDoubleClick(index)" :class="[isPlayList && playIndex === index ? $style.active : '', (isAPITemp && item.source != 'kw') || item.source == 'wy' ? $style.disabled : '']")
|
@click="handleDoubleClick(index)" :class="[isPlayList && playIndex === index ? $style.active : '', (isAPITemp && item.source != 'kw') ? $style.disabled : '']")
|
||||||
td.nobreak.center(style="width: 37px;" @click.stop)
|
td.nobreak.center(style="width: 37px;" @click.stop)
|
||||||
material-checkbox(:id="index.toString()" v-model="selectdData" :value="item")
|
material-checkbox(:id="index.toString()" v-model="selectdData" :value="item")
|
||||||
td.break(style="width: 25%;")
|
td.break(style="width: 25%;")
|
||||||
|
@ -218,7 +218,7 @@ export default {
|
||||||
this.clickIndex = -1
|
this.clickIndex = -1
|
||||||
},
|
},
|
||||||
testPlay(index) {
|
testPlay(index) {
|
||||||
if ((this.isAPITemp && this.list[index].source != 'kw') || this.list[index].source == 'wy') return
|
if (this.isAPITemp && this.list[index].source != 'kw') return
|
||||||
this.setPlayList({ list: this.list, listId: this.listId, index })
|
this.setPlayList({ list: this.list, listId: this.listId, index })
|
||||||
},
|
},
|
||||||
handleRemove(index) {
|
handleRemove(index) {
|
||||||
|
@ -228,7 +228,7 @@ export default {
|
||||||
switch (info.action) {
|
switch (info.action) {
|
||||||
case 'download': {
|
case 'download': {
|
||||||
const minfo = this.list[info.index]
|
const minfo = this.list[info.index]
|
||||||
if ((this.isAPITemp && minfo.source != 'kw') || minfo.source == 'wy') return
|
if (this.isAPITemp && minfo.source != 'kw') return
|
||||||
this.musicInfo = minfo
|
this.musicInfo = minfo
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.isShowDownload = true
|
this.isShowDownload = true
|
||||||
|
@ -261,7 +261,7 @@ export default {
|
||||||
this.selectdData = []
|
this.selectdData = []
|
||||||
},
|
},
|
||||||
handleAddDownloadMultiple(type) {
|
handleAddDownloadMultiple(type) {
|
||||||
const list = this.setting.apiSource == 'temp' ? this.selectdData.filter(s => s.source == 'kw') : this.selectdData.filter(s => s.source != 'wy')
|
const list = this.setting.apiSource == 'temp' ? this.selectdData.filter(s => s.source == 'kw') : [...this.selectdData]
|
||||||
this.createDownloadMultiple({ list, type })
|
this.createDownloadMultiple({ list, type })
|
||||||
this.resetSelect()
|
this.resetSelect()
|
||||||
this.isShowDownloadMultiple = false
|
this.isShowDownloadMultiple = false
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
td.break(style="width: 25%;") {{item.albumName}}
|
td.break(style="width: 25%;") {{item.albumName}}
|
||||||
td(style="width: 15%; padding-left: 0; padding-right: 0;")
|
td(style="width: 15%; padding-left: 0; padding-right: 0;")
|
||||||
material-list-buttons(:index="index" :remove-btn="false" :class="$style.listBtn"
|
material-list-buttons(:index="index" :remove-btn="false" :class="$style.listBtn"
|
||||||
:play-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
|
:play-btn="item.source == 'kw' || !isAPITemp"
|
||||||
:download-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
|
:download-btn="item.source == 'kw' || !isAPITemp"
|
||||||
@btn-click="handleListBtnClick")
|
@btn-click="handleListBtnClick")
|
||||||
td(style="width: 10%;") {{item.interval || '--/--'}}
|
td(style="width: 10%;") {{item.interval || '--/--'}}
|
||||||
div(:class="$style.pagination")
|
div(:class="$style.pagination")
|
||||||
|
@ -189,7 +189,7 @@ export default {
|
||||||
targetSong = this.selectdData[0]
|
targetSong = this.selectdData[0]
|
||||||
this.listAddMultiple({ id: 'default', list: this.filterList(this.selectdData) })
|
this.listAddMultiple({ id: 'default', list: this.filterList(this.selectdData) })
|
||||||
} else {
|
} else {
|
||||||
if ((this.isAPITemp && this.listInfo.list[index].source != 'kw') || this.listInfo.list[index].source == 'wy') return
|
if (this.isAPITemp && this.listInfo.list[index].source != 'kw') return
|
||||||
targetSong = this.listInfo.list[index]
|
targetSong = this.listInfo.list[index]
|
||||||
this.listAdd({ id: 'default', musicInfo: targetSong })
|
this.listAdd({ id: 'default', musicInfo: targetSong })
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
filterList(list) {
|
filterList(list) {
|
||||||
return this.setting.apiSource == 'temp' ? list.filter(s => s.source == 'kw') : list.filter(s => s.source != 'wy')
|
return this.setting.apiSource == 'temp' ? list.filter(s => s.source == 'kw') : [...list]
|
||||||
},
|
},
|
||||||
handleListAddModalClose(isSelect) {
|
handleListAddModalClose(isSelect) {
|
||||||
if (isSelect) this.resetSelect()
|
if (isSelect) this.resetSelect()
|
||||||
|
|
|
@ -200,6 +200,7 @@ export default {
|
||||||
handleAddDownloadMultiple(type) {
|
handleAddDownloadMultiple(type) {
|
||||||
switch (this.source) {
|
switch (this.source) {
|
||||||
// case 'kg':
|
// case 'kg':
|
||||||
|
case 'tx':
|
||||||
case 'wy':
|
case 'wy':
|
||||||
type = '128k'
|
type = '128k'
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue