修复网易云128k直接试听
							parent
							
								
									a104ce688e
								
							
						
					
					
						commit
						9dc9d3b1b7
					
				| 
						 | 
				
			
			@ -2,3 +2,4 @@
 | 
			
		|||
 | 
			
		||||
- 修复QQ源歌单无法翻页Bug
 | 
			
		||||
- 修复默认列表没有创建时无法显示收藏列表的Bug
 | 
			
		||||
- 修复网易云128k直接试听
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ material-modal(:show="show" :bg-close="bgClose" @close="handleClose")
 | 
			
		|||
      | {{ info.name }}
 | 
			
		||||
      br
 | 
			
		||||
      | {{ 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>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -52,7 +52,6 @@ export default {
 | 
			
		|||
    checkSource(type) {
 | 
			
		||||
      switch (this.musicInfo.source) {
 | 
			
		||||
        case 'wy':
 | 
			
		||||
          return false
 | 
			
		||||
        case 'tx':
 | 
			
		||||
          return type == '128k'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,9 +29,9 @@ div(:class="$style.songList")
 | 
			
		|||
              td(style="width: 20%; padding-left: 0; padding-right: 0;")
 | 
			
		||||
                material-list-buttons(:index="index" :search-btn="true"
 | 
			
		||||
                  :remove-btn="false" @btn-click="handleListBtnClick"
 | 
			
		||||
                  :listAdd-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
 | 
			
		||||
                  :play-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
 | 
			
		||||
                  :download-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')")
 | 
			
		||||
                  :listAdd-btn="item.source == 'kw' || (!isAPITemp)"
 | 
			
		||||
                  :play-btn="item.source == 'kw' || (!isAPITemp)"
 | 
			
		||||
                  :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-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)') +
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +140,7 @@ export default {
 | 
			
		|||
        this.clickIndex = index
 | 
			
		||||
        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.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
 | 
			
		||||
  },
 | 
			
		||||
  getPic(songInfo) {
 | 
			
		||||
    const requestObj = httpFetch(`http://ts.tempmusic.tk/pic/wy/${songInfo.songmid}`, {
 | 
			
		||||
/*   getPic(songInfo) {
 | 
			
		||||
    const requestObj = httpFetch(`http://localhost:3100/pic/wy/${songInfo.songmid}`, {
 | 
			
		||||
      method: 'get',
 | 
			
		||||
      timeout,
 | 
			
		||||
      headers,
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ const api_test = {
 | 
			
		|||
    return requestObj
 | 
			
		||||
  },
 | 
			
		||||
  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',
 | 
			
		||||
      timeout,
 | 
			
		||||
      headers,
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ const api_test = {
 | 
			
		|||
      return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))
 | 
			
		||||
    })
 | 
			
		||||
    return requestObj
 | 
			
		||||
  },
 | 
			
		||||
  }, */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default api_test
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
import leaderboard from './leaderboard'
 | 
			
		||||
import api_source from '../api-source'
 | 
			
		||||
import getLyric from './lyric'
 | 
			
		||||
import getMusicInfo from './musicInfo'
 | 
			
		||||
 | 
			
		||||
const wy = {
 | 
			
		||||
  leaderboard,
 | 
			
		||||
| 
						 | 
				
			
			@ -7,10 +9,10 @@ const wy = {
 | 
			
		|||
    return api_source('wy').getMusicUrl(songInfo, type)
 | 
			
		||||
  },
 | 
			
		||||
  getLyric(songInfo) {
 | 
			
		||||
    return api_source('wy').getLyric(songInfo)
 | 
			
		||||
    return getLyric(songInfo.songmid)
 | 
			
		||||
  },
 | 
			
		||||
  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) {
 | 
			
		||||
      switch (this.source) {
 | 
			
		||||
        // case 'kg':
 | 
			
		||||
        case 'tx':
 | 
			
		||||
        case 'wy':
 | 
			
		||||
          type = '128k'
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@
 | 
			
		|||
        table
 | 
			
		||||
          tbody
 | 
			
		||||
            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)
 | 
			
		||||
                  material-checkbox(:id="index.toString()" v-model="selectdData" :value="item")
 | 
			
		||||
              td.break(style="width: 25%;")
 | 
			
		||||
| 
						 | 
				
			
			@ -218,7 +218,7 @@ export default {
 | 
			
		|||
      this.clickIndex = -1
 | 
			
		||||
    },
 | 
			
		||||
    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 })
 | 
			
		||||
    },
 | 
			
		||||
    handleRemove(index) {
 | 
			
		||||
| 
						 | 
				
			
			@ -228,7 +228,7 @@ export default {
 | 
			
		|||
      switch (info.action) {
 | 
			
		||||
        case 'download': {
 | 
			
		||||
          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.$nextTick(() => {
 | 
			
		||||
            this.isShowDownload = true
 | 
			
		||||
| 
						 | 
				
			
			@ -261,7 +261,7 @@ export default {
 | 
			
		|||
      this.selectdData = []
 | 
			
		||||
    },
 | 
			
		||||
    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.resetSelect()
 | 
			
		||||
      this.isShowDownloadMultiple = false
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,8 +30,8 @@
 | 
			
		|||
              td.break(style="width: 25%;") {{item.albumName}}
 | 
			
		||||
              td(style="width: 15%; padding-left: 0; padding-right: 0;")
 | 
			
		||||
                material-list-buttons(:index="index" :remove-btn="false" :class="$style.listBtn"
 | 
			
		||||
                  :play-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
 | 
			
		||||
                  :download-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
 | 
			
		||||
                  :play-btn="item.source == 'kw' || !isAPITemp"
 | 
			
		||||
                  :download-btn="item.source == 'kw' || !isAPITemp"
 | 
			
		||||
                  @btn-click="handleListBtnClick")
 | 
			
		||||
              td(style="width: 10%;") {{item.interval || '--/--'}}
 | 
			
		||||
        div(:class="$style.pagination")
 | 
			
		||||
| 
						 | 
				
			
			@ -189,7 +189,7 @@ export default {
 | 
			
		|||
        targetSong = this.selectdData[0]
 | 
			
		||||
        this.listAddMultiple({ id: 'default', list: this.filterList(this.selectdData) })
 | 
			
		||||
      } 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]
 | 
			
		||||
        this.listAdd({ id: 'default', musicInfo: targetSong })
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -238,7 +238,7 @@ export default {
 | 
			
		|||
      }
 | 
			
		||||
    },
 | 
			
		||||
    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) {
 | 
			
		||||
      if (isSelect) this.resetSelect()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -200,6 +200,7 @@ export default {
 | 
			
		|||
    handleAddDownloadMultiple(type) {
 | 
			
		||||
      switch (this.source) {
 | 
			
		||||
        // case 'kg':
 | 
			
		||||
        case 'tx':
 | 
			
		||||
        case 'wy':
 | 
			
		||||
          type = '128k'
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue