初始提交
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import { DownloaderHelper } from 'node-downloader-helper'
|
||||
// import { pauseResumeTimer } from './util'
|
||||
import { sizeFormate } from '../index'
|
||||
import { debugDownload } from '../env'
|
||||
|
||||
// these are the default options
|
||||
// const options = {
|
||||
// method: 'GET', // Request Method Verb
|
||||
// // Custom HTTP Header ex: Authorization, User-Agent
|
||||
// headers: {},
|
||||
// fileName: '', // Custom filename when saved
|
||||
// override: false, // if true it will override the file, otherwise will append '(number)' to the end of file
|
||||
// forceResume: false, // If the server does not return the "accept-ranges" header, can be force if it does support it
|
||||
// // httpRequestOptions: {}, // Override the http request options
|
||||
// // httpsRequestOptions: {}, // Override the https request options, ex: to add SSL Certs
|
||||
// }
|
||||
|
||||
export default ({
|
||||
url,
|
||||
path,
|
||||
fileName,
|
||||
method = 'get',
|
||||
headers,
|
||||
override,
|
||||
forceResume,
|
||||
// resumeTime = 5000,
|
||||
onEnd = () => {},
|
||||
onError = () => {},
|
||||
onStateChanged = () => {},
|
||||
onDownload = () => {},
|
||||
onPause = () => {},
|
||||
onResume = () => {},
|
||||
onProgress = () => {},
|
||||
resumeInfo,
|
||||
} = {}) => {
|
||||
const dl = new DownloaderHelper(url, path, {
|
||||
fileName,
|
||||
method,
|
||||
headers,
|
||||
override,
|
||||
forceResume,
|
||||
})
|
||||
|
||||
dl.on('end', () => {
|
||||
onEnd()
|
||||
debugDownload && console.log('Download Completed')
|
||||
}).on('error', err => {
|
||||
onError(err)
|
||||
dl.resume()
|
||||
console.log('Download failed, Attempting Retry')
|
||||
debugDownload && console.error('Something happend', err)
|
||||
}).on('stateChanged', state => {
|
||||
onStateChanged(state)
|
||||
debugDownload && console.log('State: ', state)
|
||||
}).on('download', () => {
|
||||
onDownload()
|
||||
// pauseResumeTimer(dl, resumeTime)
|
||||
}).on('progress', stats => {
|
||||
const progress = stats.progress.toFixed(2)
|
||||
const speed = sizeFormate(stats.speed)
|
||||
onProgress({
|
||||
progress,
|
||||
speed,
|
||||
downloaded: stats.downloaded,
|
||||
total: stats.total,
|
||||
})
|
||||
if (debugDownload) {
|
||||
const downloaded = sizeFormate(stats.downloaded)
|
||||
const total = sizeFormate(stats.total)
|
||||
console.log(`${speed}/s - ${progress}% [${downloaded}/${total}]`)
|
||||
}
|
||||
}).on('pause', () => {
|
||||
onPause()
|
||||
debugDownload && console.log('paused')
|
||||
}).on('resume', () => {
|
||||
onResume()
|
||||
debugDownload && console.log('resume')
|
||||
})
|
||||
|
||||
debugDownload && console.log('Downloading: ', url)
|
||||
|
||||
if (resumeInfo) {
|
||||
dl.__total = resumeInfo.totalFileSize // <--- Workaround
|
||||
// dl.__filePath = resumeInfo.filePath // <--- Workaround
|
||||
dl.__isResumable = true // <--- Workaround
|
||||
dl.resume()
|
||||
} else {
|
||||
dl.start()
|
||||
}
|
||||
|
||||
return dl
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { DH_STATES } from 'node-downloader-helper'
|
||||
|
||||
|
||||
export const pauseResumeTimer = (_dl, wait) => {
|
||||
setTimeout(() => {
|
||||
if (_dl.state === DH_STATES.FINISHED || _dl.state === DH_STATES.FAILED) {
|
||||
return
|
||||
}
|
||||
|
||||
_dl
|
||||
.pause()
|
||||
.then(() => console.log(`Paused for ${wait / 1000} seconds`))
|
||||
.then(() =>
|
||||
setTimeout(() => {
|
||||
if (!_dl.isResumable()) {
|
||||
console.warn(
|
||||
"This URL doesn't support resume, it will start from the beginning"
|
||||
)
|
||||
}
|
||||
return _dl.resume()
|
||||
}, wait)
|
||||
)
|
||||
}, wait)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
const isDev = process.env.NODE_ENV === 'development'
|
||||
|
||||
export const debug = isDev && true
|
||||
export const debugRequest = isDev && false
|
||||
export const debugDownload = isDev && false
|
||||
@@ -0,0 +1,196 @@
|
||||
import fs from 'fs'
|
||||
import { shell, remote } from 'electron'
|
||||
import path from 'path'
|
||||
import os from 'os'
|
||||
|
||||
/**
|
||||
* 获取两个数之间的随机整数,大于等于min,小于max
|
||||
* @param {*} min
|
||||
* @param {*} max
|
||||
*/
|
||||
export const getRandom = (min, max) => Math.floor(Math.random() * (max - min)) + min
|
||||
|
||||
|
||||
export const sizeFormate = size => {
|
||||
// https://gist.github.com/thomseddon/3511330
|
||||
if (!size) return '0 b'
|
||||
let units = ['b', 'kB', 'MB', 'GB', 'TB']
|
||||
let number = Math.floor(Math.log(size) / Math.log(1024))
|
||||
return `${(size / Math.pow(1024, Math.floor(number))).toFixed(2)} ${units[number]}`
|
||||
}
|
||||
|
||||
export const formatPlayTime = time => {
|
||||
let m = parseInt(time / 60)
|
||||
let s = parseInt(time % 60)
|
||||
return m === 0 && s === 0 ? '--/--' : (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s)
|
||||
}
|
||||
|
||||
export const formatPlayTime2 = time => {
|
||||
let m = parseInt(time / 60)
|
||||
let s = parseInt(time % 60)
|
||||
return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s)
|
||||
}
|
||||
|
||||
export const b64DecodeUnicode = str => {
|
||||
// Going backwards: from bytestream, to percent-encoding, to original string.
|
||||
return decodeURIComponent(window.atob(str).split('').map(function(c) {
|
||||
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
|
||||
}).join(''))
|
||||
}
|
||||
|
||||
export const decodeName = str => str.replace(/'/g, '\'')
|
||||
|
||||
export const scrollTo = (element, to, duration = 300, fn = function() {}) => {
|
||||
const start = element.scrollTop || element.scrollY
|
||||
const change = to - start
|
||||
const increment = 10
|
||||
if (!change) {
|
||||
fn()
|
||||
return
|
||||
}
|
||||
let currentTime = 0; let val
|
||||
const easeInOutQuad = (t, b, c, d) => {
|
||||
t /= d / 2
|
||||
if (t < 1) return (c / 2) * t * t + b
|
||||
t--
|
||||
return (-c / 2) * (t * (t - 2) - 1) + b
|
||||
}
|
||||
const animateScroll = () => {
|
||||
currentTime += increment
|
||||
val = parseInt(easeInOutQuad(currentTime, start, change, duration))
|
||||
if (element.scrollTo) {
|
||||
element.scrollTo(0, val)
|
||||
} else {
|
||||
element.scrollTop = val
|
||||
}
|
||||
if (currentTime < duration) {
|
||||
setTimeout(animateScroll, increment)
|
||||
} else {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
animateScroll()
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查路径是否存在
|
||||
* @param {*} path
|
||||
*/
|
||||
export const checkPath = path => fs.existsSync(path)
|
||||
|
||||
|
||||
/**
|
||||
* 在资源管理器中打开目录
|
||||
* @param {*} 选项
|
||||
*/
|
||||
export const openSelectDir = options => remote.dialog.showOpenDialog(remote.getCurrentWindow(), options)
|
||||
|
||||
/**
|
||||
* 在资源管理器中打开目录
|
||||
* @param {*} 选项
|
||||
*/
|
||||
export const openSaveDir = options => remote.dialog.showSaveDialog(remote.getCurrentWindow(), options)
|
||||
|
||||
/**
|
||||
* 在资源管理器中打开目录
|
||||
* @param {*} dir
|
||||
*/
|
||||
export const openDirInExplorer = dir => {
|
||||
shell.showItemInFolder(dir)
|
||||
}
|
||||
|
||||
export const checkVersion = (currentVer, targetVer) => {
|
||||
// console.log(currentVer)
|
||||
// console.log(targetVer)
|
||||
currentVer = currentVer.split('.')
|
||||
targetVer = targetVer.split('.')
|
||||
let maxLen = Math.max(currentVer.length, targetVer.length)
|
||||
if (currentVer.length < maxLen) {
|
||||
for (let index = 0, len = maxLen - currentVer.length; index < len; index++) {
|
||||
currentVer.push(0)
|
||||
}
|
||||
}
|
||||
if (targetVer.length < maxLen) {
|
||||
for (let index = 0, len = maxLen - targetVer.length; index < len; index++) {
|
||||
targetVer.push(0)
|
||||
}
|
||||
}
|
||||
for (let index = 0; index < currentVer.length; index++) {
|
||||
if (parseInt(currentVer[index]) < parseInt(targetVer[index])) return true
|
||||
if (parseInt(currentVer[index]) > parseInt(targetVer[index])) return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export const isObject = item => item && typeof item === 'object' && !Array.isArray(item)
|
||||
|
||||
/**
|
||||
* 对象深度合并
|
||||
* 注意:循环引用的对象会出现死循环
|
||||
* @param {} target 要合并源对象
|
||||
* @param {} source 要合并目标对象
|
||||
*/
|
||||
export const objectDeepMerge = (target, source) => {
|
||||
let base = {}
|
||||
Object.keys(source).forEach(item => {
|
||||
if (Array.isArray(source[item])) {
|
||||
let arr = Array.isArray(target[item]) ? target[item] : []
|
||||
target[item] = arr.concat(source[item])
|
||||
return
|
||||
} else if (isObject(source[item])) {
|
||||
if (!isObject(target[item])) target[item] = {}
|
||||
objectDeepMerge(target[item], source[item])
|
||||
return
|
||||
}
|
||||
base[item] = source[item]
|
||||
})
|
||||
Object.assign(target, base)
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否父子元素
|
||||
* @param {*} parent
|
||||
* @param {*} children
|
||||
*/
|
||||
export const isChildren = (parent, children) => {
|
||||
return children.parentNode ? children.parentNode === parent ? true : isChildren(parent, children.parentNode) : false
|
||||
}
|
||||
|
||||
export const updateSetting = setting => {
|
||||
const defaultVersion = '1.0.1'
|
||||
const defaultSetting = {
|
||||
version: defaultVersion,
|
||||
player: {
|
||||
togglePlayMethod: 'listLoop',
|
||||
highQuality: false,
|
||||
},
|
||||
list: {
|
||||
isShowAlbumName: true,
|
||||
},
|
||||
download: {
|
||||
savePath: path.join(os.homedir(), 'Desktop'),
|
||||
fileName: '歌名 - 歌手',
|
||||
},
|
||||
leaderboard: {
|
||||
source: 'kw',
|
||||
tabId: 'kwbiaosb',
|
||||
},
|
||||
themeId: 0,
|
||||
sourceId: 'kw',
|
||||
randomAnimate: true,
|
||||
}
|
||||
const overwriteSetting = {
|
||||
version: defaultVersion,
|
||||
sourceId: 'kw',
|
||||
}
|
||||
|
||||
|
||||
if (!setting) {
|
||||
setting = defaultSetting
|
||||
} else if (checkVersion(setting.version, defaultSetting.version)) {
|
||||
objectDeepMerge(defaultSetting, setting)
|
||||
objectDeepMerge(defaultSetting, overwriteSetting)
|
||||
setting = defaultSetting
|
||||
}
|
||||
return setting
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import kw from './kw'
|
||||
import kg from './kg'
|
||||
import tx from './tx'
|
||||
import wy from './wy'
|
||||
export default {
|
||||
sources: [
|
||||
{
|
||||
name: '酷我音乐',
|
||||
id: 'kw',
|
||||
},
|
||||
{
|
||||
name: '酷狗音乐',
|
||||
id: 'kg',
|
||||
},
|
||||
{
|
||||
name: 'QQ音乐',
|
||||
id: 'tx',
|
||||
},
|
||||
{
|
||||
name: '网易音乐',
|
||||
id: 'wy',
|
||||
},
|
||||
],
|
||||
kw,
|
||||
kg,
|
||||
tx,
|
||||
wy,
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import leaderboard from './leaderboard'
|
||||
|
||||
const kg = {
|
||||
leaderboard,
|
||||
}
|
||||
|
||||
export default kg
|
||||
@@ -0,0 +1,125 @@
|
||||
import { httpGet, cancelHttp } from '../../request'
|
||||
import { formatPlayTime } from '../../index'
|
||||
|
||||
export default {
|
||||
list: [
|
||||
{
|
||||
id: 'kgtop500',
|
||||
name: '酷狗TOP500',
|
||||
bangid: '8888',
|
||||
},
|
||||
{
|
||||
id: 'kgwlhgb',
|
||||
name: '网络红歌榜',
|
||||
bangid: '23784',
|
||||
},
|
||||
{
|
||||
id: 'kgbsb',
|
||||
name: '飙升榜',
|
||||
bangid: '6666',
|
||||
},
|
||||
{
|
||||
id: 'kgfxb',
|
||||
name: '分享榜',
|
||||
bangid: '21101',
|
||||
},
|
||||
{
|
||||
id: 'kgcyyb',
|
||||
name: '纯音乐榜',
|
||||
bangid: '33164',
|
||||
},
|
||||
{
|
||||
id: 'kggfjqb',
|
||||
name: '古风金曲榜',
|
||||
bangid: '33161',
|
||||
},
|
||||
{
|
||||
id: 'kgyyjqb',
|
||||
name: '粤语金曲榜',
|
||||
bangid: '33165',
|
||||
},
|
||||
{
|
||||
id: 'kgomjqb',
|
||||
name: '欧美金曲榜',
|
||||
bangid: '33166',
|
||||
},
|
||||
// {
|
||||
// id: 'kgdyrgb',
|
||||
// name: '电音热歌榜',
|
||||
// bangid: '33160',
|
||||
// },
|
||||
// {
|
||||
// id: 'kgjdrgb',
|
||||
// name: 'DJ热歌榜',
|
||||
// bangid: '24971',
|
||||
// },
|
||||
// {
|
||||
// id: 'kghyxgb',
|
||||
// name: '华语新歌榜',
|
||||
// bangid: '31308',
|
||||
// },
|
||||
],
|
||||
getUrl(p, id) {
|
||||
return `http://www2.kugou.kugou.com/yueku/v9/rank/home/${p}-${id}.html`
|
||||
},
|
||||
regExps: {
|
||||
total: /total: '(\d+)',/,
|
||||
page: /page: '(\d+)',/,
|
||||
limit: /pagesize: '(\d+)',/,
|
||||
listData: /global\.features = (\[.+\]);/,
|
||||
},
|
||||
_cancelIndex: null,
|
||||
_cancelPromiseCancelFn: null,
|
||||
getData(url) {
|
||||
if (this._cancelIndex != null) {
|
||||
cancelHttp(this._cancelIndex)
|
||||
this._cancelPromiseCancelFn(new Error('取消http请求'))
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._cancelPromiseCancelFn = reject
|
||||
this._cancelIndex = httpGet(url, (err, resp, body) => {
|
||||
this._cancelIndex = null
|
||||
this._cancelPromiseCancelFn = null
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
}
|
||||
resolve(body)
|
||||
})
|
||||
})
|
||||
},
|
||||
filterData(rawList) {
|
||||
return rawList.map(item => ({
|
||||
singer: item.singername,
|
||||
name: item.songname,
|
||||
albumName: item.album_name,
|
||||
albumId: item.album_id,
|
||||
songmid: item.audio_id,
|
||||
source: 'kg',
|
||||
interval: formatPlayTime(item.duration / 1000),
|
||||
img: null,
|
||||
lrc: null,
|
||||
typeUrl: {},
|
||||
}))
|
||||
},
|
||||
getList(id, page) {
|
||||
let type = this.list.find(s => s.id === id)
|
||||
if (!type) return Promise.reject()
|
||||
return this.getData(this.getUrl(page, type.bangid)).then(html => {
|
||||
let total = html.match(this.regExps.total)
|
||||
if (total) total = parseInt(RegExp.$1)
|
||||
page = html.match(this.regExps.page)
|
||||
if (page) page = parseInt(RegExp.$1)
|
||||
let limit = html.match(this.regExps.limit)
|
||||
if (limit) limit = parseInt(RegExp.$1)
|
||||
let listData = html.match(this.regExps.listData)
|
||||
if (listData) listData = this.filterData(JSON.parse(RegExp.$1))
|
||||
return {
|
||||
total,
|
||||
list: listData,
|
||||
limit,
|
||||
page,
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
import { httpGet, cancelHttp } from '../../request'
|
||||
import tempSearch from './tempSearch'
|
||||
import musicSearch from './musicSearch'
|
||||
import { formatSinger } from './util'
|
||||
import leaderboard from './leaderboard'
|
||||
import lyric from './lyric'
|
||||
|
||||
const kw = {
|
||||
_musicInfoIndex: null,
|
||||
_musicInfoPromiseCancelFn: null,
|
||||
_musicPicIndex: null,
|
||||
_musicPicPromiseCancelFn: null,
|
||||
// context: null,
|
||||
|
||||
|
||||
// init(context) {
|
||||
// if (this.isInited) return
|
||||
// this.isInited = true
|
||||
// this.context = context
|
||||
|
||||
// // this.musicSearch.search('我又想你了').then(res => {
|
||||
// // console.log(res)
|
||||
// // })
|
||||
|
||||
// // this.getMusicUrl('62355680', '320k').then(url => {
|
||||
// // console.log(url)
|
||||
// // })
|
||||
// },
|
||||
|
||||
tempSearch,
|
||||
musicSearch,
|
||||
leaderboard,
|
||||
getLyric(songInfo) {
|
||||
// let singer = songInfo.singer.indexOf('、') > -1 ? songInfo.singer.split('、')[0] : songInfo.singer
|
||||
return lyric.getLyric(songInfo.songmid)
|
||||
},
|
||||
handleMusicInfo(songInfo) {
|
||||
return this.getMusicInfo(songInfo).then(info => {
|
||||
// console.log(JSON.stringify(info))
|
||||
songInfo.name = info.name
|
||||
songInfo.singer = formatSinger(info.artist)
|
||||
songInfo.img = info.pic
|
||||
songInfo.albumName = info.album
|
||||
return songInfo
|
||||
// return Object.assign({}, songInfo, {
|
||||
// name: info.name,
|
||||
// singer: formatSinger(info.artist),
|
||||
// img: info.pic,
|
||||
// albumName: info.album,
|
||||
// })
|
||||
})
|
||||
},
|
||||
|
||||
getMusicUrl(songInfo, type) {
|
||||
return new Promise((resolve, reject) => {
|
||||
httpGet(`https://v1.itooi.cn/kuwo/url?id=${songInfo.songmid}&quality=${type.replace(/k$/, '')}&isRedirect=0`, (err, resp, body) => {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
return this.getMusicUrl(songInfo, type)
|
||||
}
|
||||
body.code === 200 ? resolve({ type, url: body.data }) : reject(new Error(body.msg))
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
getMusicInfo(songInfo) {
|
||||
if (this._musicInfoIndex != null) {
|
||||
cancelHttp(this._musicInfoIndex)
|
||||
this._musicInfoPromiseCancelFn(new Error('取消http请求'))
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._musicInfoPromiseCancelFn = reject
|
||||
this._musicInfoIndex = httpGet(`http://www.kuwo.cn/api/www/music/musicInfo?mid=${songInfo.songmid}`, (err, resp, body) => {
|
||||
this._musicInfoIndex = null
|
||||
this._musicInfoPromiseCancelFn = null
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
}
|
||||
body.code === 200 ? resolve(body.data) : reject(new Error(body.msg))
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
getMusicUrls(musicInfo, cb) {
|
||||
let tasks = []
|
||||
let songId = musicInfo.songmid
|
||||
musicInfo.types.forEach(type => {
|
||||
tasks.push(kw.getMusicUrl(songId, type.type))
|
||||
})
|
||||
Promise.all(tasks).then(urlInfo => {
|
||||
let typeUrl = {}
|
||||
urlInfo.forEach(info => {
|
||||
typeUrl[info.type] = info.url
|
||||
})
|
||||
cb(typeUrl)
|
||||
})
|
||||
},
|
||||
|
||||
getPic(songInfo) {
|
||||
if (this._musicPicIndex != null) {
|
||||
cancelHttp(this._musicPicIndex)
|
||||
this._musicPicPromiseCancelFn(new Error('取消http请求'))
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._musicPicPromiseCancelFn = reject
|
||||
this._musicPicIndex = httpGet(`https://v1.itooi.cn/kuwo/pic?id=${songInfo.songmid}&isRedirect=0`, (err, resp, body) => {
|
||||
this._musicPicIndex = null
|
||||
this._musicPicPromiseCancelFn = null
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
}
|
||||
console.log(body)
|
||||
body.code === 200 ? resolve(body.data) : reject(new Error(body.msg))
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
export default kw
|
||||
@@ -0,0 +1,190 @@
|
||||
import { httpGet, cancelHttp } from '../../request'
|
||||
import { formatPlayTime } from '../../index'
|
||||
|
||||
export default {
|
||||
list: [
|
||||
{
|
||||
id: 'kwbiaosb',
|
||||
name: '飙升榜',
|
||||
bangid: 93,
|
||||
},
|
||||
{
|
||||
id: 'kwregb',
|
||||
name: '热歌榜',
|
||||
bangid: 16,
|
||||
},
|
||||
{
|
||||
id: 'kwhuiyb',
|
||||
name: '会员榜',
|
||||
bangid: 145,
|
||||
},
|
||||
{
|
||||
id: 'kwdouyb',
|
||||
name: '抖音榜',
|
||||
bangid: 158,
|
||||
},
|
||||
{
|
||||
id: 'kwqsb',
|
||||
name: '趋势榜',
|
||||
bangid: 187,
|
||||
},
|
||||
{
|
||||
id: 'kwhuaijb',
|
||||
name: '怀旧榜',
|
||||
bangid: 26,
|
||||
},
|
||||
{
|
||||
id: 'kwhuayb',
|
||||
name: '华语榜',
|
||||
bangid: 104,
|
||||
},
|
||||
{
|
||||
id: 'kwyueyb',
|
||||
name: '粤语榜',
|
||||
bangid: 182,
|
||||
},
|
||||
{
|
||||
id: 'kwoumb',
|
||||
name: '欧美榜',
|
||||
bangid: 22,
|
||||
},
|
||||
{
|
||||
id: 'kwhanyb',
|
||||
name: '韩语榜',
|
||||
bangid: 184,
|
||||
},
|
||||
{
|
||||
id: 'kwriyb',
|
||||
name: '日语榜',
|
||||
bangid: 183,
|
||||
},
|
||||
],
|
||||
getUrl: (p, l, id) => `http://kbangserver.kuwo.cn/ksong.s?from=pc&fmt=json&pn=${p - 1}&rn=${l}&type=bang&data=content&id=${id}&show_copyright_off=0&pcmp4=1&isbang=1`,
|
||||
getUrl2: (p, l, id) => `http://www.kuwo.cn/api/www/bang/bang/musicList?bangId=${id}&pn=${p}&rn=${l}`,
|
||||
regExps: {
|
||||
|
||||
},
|
||||
limit: 30,
|
||||
_cancelIndex: null,
|
||||
_cancelPromiseCancelFn: null,
|
||||
_cancelIndex2: null,
|
||||
_cancelPromiseCancelFn2: null,
|
||||
getData(url) {
|
||||
if (this._cancelIndex != null) {
|
||||
cancelHttp(this._cancelIndex)
|
||||
this._cancelPromiseCancelFn(new Error('取消http请求'))
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._cancelPromiseCancelFn = reject
|
||||
this._cancelIndex = httpGet(url, (err, resp, body) => {
|
||||
this._cancelIndex = null
|
||||
this._cancelPromiseCancelFn = null
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
}
|
||||
resolve(body)
|
||||
})
|
||||
})
|
||||
},
|
||||
getData2(url) {
|
||||
if (this._cancelIndex2 != null) {
|
||||
cancelHttp(this._cancelIndex2)
|
||||
this._cancelPromiseCancelFn2(new Error('取消http请求'))
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._cancelPromiseCancelFn2 = reject
|
||||
this._cancelIndex2 = httpGet(url, (err, resp, body) => {
|
||||
this._cancelIndex2 = null
|
||||
this._cancelPromiseCancelFn2 = null
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
}
|
||||
resolve(body)
|
||||
})
|
||||
})
|
||||
},
|
||||
filterData(rawList, rawList2) {
|
||||
return rawList.map((item, inedx) => {
|
||||
let formats = item.formats.split('|')
|
||||
let types = []
|
||||
let _types = {}
|
||||
if (formats.indexOf('MP3128')) {
|
||||
types.push({ type: '128k', size: null })
|
||||
_types['128k'] = {
|
||||
size: null,
|
||||
}
|
||||
}
|
||||
if (formats.indexOf('MP3192')) {
|
||||
types.push({ type: '192k', size: null })
|
||||
_types['192k'] = {
|
||||
size: null,
|
||||
}
|
||||
}
|
||||
if (formats.indexOf('MP3H')) {
|
||||
types.push({ type: '320k', size: null })
|
||||
_types['320k'] = {
|
||||
size: null,
|
||||
}
|
||||
}
|
||||
if (formats.indexOf('AL')) {
|
||||
types.push({ type: 'ape', size: null })
|
||||
_types['ape'] = {
|
||||
size: null,
|
||||
}
|
||||
}
|
||||
if (formats.indexOf('ALFLAC')) {
|
||||
types.push({ type: 'flac', size: null })
|
||||
_types['flac'] = {
|
||||
size: null,
|
||||
}
|
||||
}
|
||||
types.reverse()
|
||||
return {
|
||||
singer: item.artist,
|
||||
name: item.name,
|
||||
albumName: item.album,
|
||||
albumId: item.albumid,
|
||||
songmid: item.id,
|
||||
source: 'kw',
|
||||
interval: formatPlayTime(rawList2[inedx].duration),
|
||||
img: item.pic,
|
||||
lrc: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
}
|
||||
})
|
||||
},
|
||||
loadData(p1, p2, page, bangid) {
|
||||
return Promise.all([p1, p2]).then(([data1, data2]) => {
|
||||
// console.log(data1, data2)
|
||||
if (!data1.musiclist.length) {
|
||||
return this.loadData(this.getData(this.getUrl(page, this.limit, bangid)),
|
||||
data2.data.musicList.length
|
||||
? Promise.resolve(data2)
|
||||
: this.getData2(this.getUrl2(page, this.limit, bangid)), page, bangid)
|
||||
}
|
||||
if (!data2.data.musicList.length) {
|
||||
return this.loadData(Promise.resolve(data1), this.getData2(this.getUrl2(page, this.limit, bangid)), page, bangid)
|
||||
}
|
||||
return Promise.resolve([data1, data2])
|
||||
})
|
||||
},
|
||||
getList(id, page) {
|
||||
let type = this.list.find(s => s.id === id)
|
||||
if (!type) return Promise.reject()
|
||||
return this.loadData(this.getData(this.getUrl(page, this.limit, type.bangid)), this.getData2(this.getUrl2(page, this.limit, type.bangid)), page, type.bangid).then(([data1, data2]) => {
|
||||
// console.log(data1.musiclist, data2.data)
|
||||
let total = parseInt(data1.num)
|
||||
let list = this.filterData(data1.musiclist, data2.data.musicList)
|
||||
return {
|
||||
total,
|
||||
list,
|
||||
limit: this.limit,
|
||||
page,
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { httpGet, cancelHttp } from '../../request'
|
||||
|
||||
export default {
|
||||
_musicLrcIndex: null,
|
||||
_musicLrcPromiseCancelFn: null,
|
||||
formatTime(time) {
|
||||
let m = parseInt(time / 60)
|
||||
let s = (time % 60).toFixed(2)
|
||||
return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s)
|
||||
},
|
||||
getLyric(songId) {
|
||||
if (this._musicLrcIndex != null) {
|
||||
cancelHttp(this._musicLrcIndex)
|
||||
this._musicLrcPromiseCancelFn(new Error('取消http请求'))
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._musicLrcPromiseCancelFn = reject
|
||||
this._musicLrcIndex = httpGet(`https://v1.itooi.cn/kuwo/lrc?id=${songId}`, (err, resp, body) => {
|
||||
this._musicLrcIndex = null
|
||||
this._musicLrcPromiseCancelFn = null
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
}
|
||||
// console.log(body.data)
|
||||
// console.log(this.transformLrc(body.data))
|
||||
resolve(body)
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
// import '../../polyfill/array.find'
|
||||
// import jshtmlencode from 'js-htmlencode'
|
||||
import { httpGet, cancelHttp } from '../../request'
|
||||
import { formatPlayTime, decodeName } from '../../index'
|
||||
// import { debug } from '../../utils/env'
|
||||
import { formatSinger } from './util'
|
||||
|
||||
export default {
|
||||
regExps: {
|
||||
mInfo: /bitrate:(\d+),format:(\w+),size:([\w.]+)/,
|
||||
},
|
||||
_musicSearchIndex: null,
|
||||
_musicSearchPromiseCancelFn: null,
|
||||
limit: 30,
|
||||
total: 0,
|
||||
page: 0,
|
||||
allPage: 1,
|
||||
// cancelFn: null,
|
||||
musicSearch(str, page) {
|
||||
if (this._musicSearchIndex != null) {
|
||||
cancelHttp(this._musicSearchIndex)
|
||||
this._musicSearchPromiseCancelFn(new Error('取消http请求'))
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._musicSearchPromiseCancelFn = reject
|
||||
this._musicSearchIndex = httpGet(`http://search.kuwo.cn/r.s?client=kt&all=${encodeURIComponent(str)}&pn=${page - 1}&rn=${this.limit}&uid=794762570&ver=kwplayer_ar_9.2.2.1&vipver=1&show_copyright_off=1&newver=1&ft=music&cluster=0&strategy=2012&encoding=utf8&rformat=json&vermerge=1&mobi=1&issubtitle=1`, (err, resp, body) => {
|
||||
this._musicSearchIndex = null
|
||||
this._musicSearchPromiseCancelFn = null
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
}
|
||||
resolve(body)
|
||||
})
|
||||
})
|
||||
},
|
||||
// getImg(songId) {
|
||||
// return httpGet(`http://player.kuwo.cn/webmusic/sj/dtflagdate?flag=6&rid=MUSIC_${songId}`)
|
||||
// },
|
||||
// getLrc(songId) {
|
||||
// return httpGet(`http://mobile.kuwo.cn/mpage/html5/songinfoandlrc?mid=${songId}&flag=0`)
|
||||
// },
|
||||
handleResult(rawData) {
|
||||
const result = []
|
||||
for (let i = 0; i < rawData.length; i++) {
|
||||
const info = rawData[i]
|
||||
let songId = info.MUSICRID.replace('MUSIC_', '')
|
||||
// const format = (info.FORMATS || info.formats).split('|')
|
||||
|
||||
if (!info.MINFO) {
|
||||
console.log('mInfo is undefined')
|
||||
return null
|
||||
}
|
||||
|
||||
const types = []
|
||||
const _types = {}
|
||||
|
||||
let infoArr = info.MINFO.split(';')
|
||||
infoArr.forEach(info => {
|
||||
info = info.match(this.regExps.mInfo)
|
||||
if (info) {
|
||||
switch (info[2]) {
|
||||
case 'flac':
|
||||
types.push({ type: 'flac', size: info[3] })
|
||||
_types.flac = {
|
||||
size: info[3].toLocaleUpperCase(),
|
||||
}
|
||||
break
|
||||
case 'ape':
|
||||
types.push({ type: 'ape', size: info[3] })
|
||||
_types.ape = {
|
||||
size: info[3].toLocaleUpperCase(),
|
||||
}
|
||||
break
|
||||
case 'mp3':
|
||||
switch (info[1]) {
|
||||
case '320':
|
||||
types.push({ type: '320k', size: info[3] })
|
||||
_types['320k'] = {
|
||||
size: info[3].toLocaleUpperCase(),
|
||||
}
|
||||
break
|
||||
case '192':
|
||||
types.push({ type: '192k', size: info[3] })
|
||||
_types['192k'] = {
|
||||
size: info[3].toLocaleUpperCase(),
|
||||
}
|
||||
break
|
||||
case '128':
|
||||
types.push({ type: '128k', size: info[3] })
|
||||
_types['128k'] = {
|
||||
size: info[3].toLocaleUpperCase(),
|
||||
}
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
types.reverse()
|
||||
|
||||
let interval = parseInt(info.DURATION)
|
||||
|
||||
result.push({
|
||||
name: decodeName(info.SONGNAME),
|
||||
singer: formatSinger(decodeName(info.ARTIST)),
|
||||
source: 'kw',
|
||||
// img = (info.album.name === '' || info.album.name === '空')
|
||||
// ? `http://player.kuwo.cn/webmusic/sj/dtflagdate?flag=6&rid=MUSIC_160911.jpg`
|
||||
// : `https://y.gtimg.cn/music/photo_new/T002R500x500M000${info.album.mid}.jpg`
|
||||
songmid: songId,
|
||||
albumId: decodeName(info.ALBUMID || ''),
|
||||
interval: Number.isNaN(interval) ? 0 : formatPlayTime(interval),
|
||||
albumName: info.ALBUM ? decodeName(info.ALBUM) : '',
|
||||
lyric: null,
|
||||
img: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
})
|
||||
}
|
||||
return result
|
||||
},
|
||||
search(str, page = 1, { limit }) {
|
||||
if (limit != null) this.limit = limit
|
||||
// http://newlyric.kuwo.cn/newlyric.lrc?62355680
|
||||
return this.musicSearch(str, page).then(result => {
|
||||
if (!result || (result.TOTAL !== '0' && result.SHOW === '0')) return this.search(str, page, { limit })
|
||||
let list = this.handleResult(result.abslist)
|
||||
|
||||
if (list == null) return this.search(str, page, { limit })
|
||||
|
||||
this.total = parseInt(result.TOTAL)
|
||||
this.page = page
|
||||
this.allPage = Math.ceil(this.total / this.limit)
|
||||
|
||||
return Promise.resolve({
|
||||
list,
|
||||
allPage: this.allPage,
|
||||
total: this.total,
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { httpGet, cancelHttp } from '../../request'
|
||||
import { decodeName } from '../../index'
|
||||
|
||||
export default {
|
||||
regExps: {
|
||||
relWord: /RELWORD=(.+)/,
|
||||
},
|
||||
_musicTempSearchIndex: null,
|
||||
_musicTempSearchPromiseCancelFn: null,
|
||||
tempSearch(str) {
|
||||
if (this._musicTempSearchIndex != null) {
|
||||
cancelHttp(this._musicTempSearchIndex)
|
||||
this._musicTempSearchPromiseCancelFn(new Error('取消http请求'))
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._musicTempSearchPromiseCancelFn = reject
|
||||
this._musicTempSearchIndex = httpGet(`http://www.kuwo.cn/api/www/search/searchKey?key=${encodeURIComponent(str)}`, (err, resp, body) => {
|
||||
this._musicTempSearchIndex = null
|
||||
this._musicTempSearchPromiseCancelFn = null
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
}
|
||||
resolve(body)
|
||||
})
|
||||
})
|
||||
},
|
||||
handleResult(rawData) {
|
||||
return rawData.map(info => {
|
||||
let matchResult = info.match(this.regExps.relWord)
|
||||
return matchResult ? decodeName(matchResult[1]) : ''
|
||||
})
|
||||
},
|
||||
cancelTempSearch() {
|
||||
if (this._musicTempSearchIndex != null) {
|
||||
cancelHttp(this._musicTempSearchIndex)
|
||||
this._musicTempSearchPromiseCancelFn(new Error('取消http请求'))
|
||||
}
|
||||
},
|
||||
search(str) {
|
||||
return this.tempSearch(str).then(result => this.handleResult(result.data))
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
export const formatSinger = rawData => rawData.replace(/&/g, '、')
|
||||
@@ -0,0 +1,7 @@
|
||||
import leaderboard from './leaderboard'
|
||||
|
||||
const tx = {
|
||||
leaderboard,
|
||||
}
|
||||
|
||||
export default tx
|
||||
@@ -0,0 +1,203 @@
|
||||
import { httpGet, cancelHttp } from '../../request'
|
||||
import { formatPlayTime, sizeFormate } from '../../index'
|
||||
|
||||
export default {
|
||||
limit: 300,
|
||||
list: [
|
||||
{
|
||||
id: 'txlxzsb',
|
||||
name: '流行榜',
|
||||
bangid: 4,
|
||||
},
|
||||
{
|
||||
id: 'txrgb',
|
||||
name: '热歌榜',
|
||||
bangid: 26,
|
||||
},
|
||||
{
|
||||
id: 'txwlhgb',
|
||||
name: '网络榜',
|
||||
bangid: 28,
|
||||
},
|
||||
{
|
||||
id: 'txdyb',
|
||||
name: '抖音榜',
|
||||
bangid: 60,
|
||||
},
|
||||
{
|
||||
id: 'txndb',
|
||||
name: '内地榜',
|
||||
bangid: 5,
|
||||
},
|
||||
{
|
||||
id: 'txxgb',
|
||||
name: '香港榜',
|
||||
bangid: 59,
|
||||
},
|
||||
{
|
||||
id: 'txtwb',
|
||||
name: '台湾榜',
|
||||
bangid: 61,
|
||||
},
|
||||
{
|
||||
id: 'txoumb',
|
||||
name: '欧美榜',
|
||||
bangid: 3,
|
||||
},
|
||||
{
|
||||
id: 'txhgb',
|
||||
name: '韩国榜',
|
||||
bangid: 16,
|
||||
},
|
||||
{
|
||||
id: 'txrbb',
|
||||
name: '日本榜',
|
||||
bangid: 17,
|
||||
},
|
||||
// {
|
||||
// id: 'txtybb',
|
||||
// name: 'YouTube榜',
|
||||
// bangid: 128,
|
||||
// },
|
||||
],
|
||||
getUrl(id, period, limit) {
|
||||
return `https://u.y.qq.com/cgi-bin/musicu.fcg?format=json&inCharset=utf8&outCharset=utf-8&platform=yqq.json&needNewCode=0&data=${encodeURIComponent(JSON.stringify({
|
||||
comm: {
|
||||
cv: 1602,
|
||||
ct: 20,
|
||||
},
|
||||
toplist: {
|
||||
module: 'musicToplist.ToplistInfoServer',
|
||||
method: 'GetDetail',
|
||||
param: {
|
||||
topid: id,
|
||||
num: limit,
|
||||
period,
|
||||
},
|
||||
},
|
||||
}))}`
|
||||
},
|
||||
regExps: {
|
||||
periodList: /<i class="play_cover__btn c_tx_link js_icon_play" data-listkey=".+?" data-listname=".+?" data-tid=".+?" data-date=".+?" .+?<\/i>/g,
|
||||
period: /data-listname="(.+?)" data-tid=".*?\/(.+?)" data-date="(.+?)" .+?<\/i>/,
|
||||
},
|
||||
periods: {},
|
||||
periodUrl: 'https://c.y.qq.com/node/pc/wk_v15/top.html',
|
||||
_cancelIndex: null,
|
||||
_cancelPromiseCancelFn: null,
|
||||
getData(url) {
|
||||
if (this._cancelIndex != null) {
|
||||
cancelHttp(this._cancelIndex)
|
||||
this._cancelPromiseCancelFn(new Error('取消http请求'))
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._cancelPromiseCancelFn = reject
|
||||
this._cancelIndex = httpGet(url, (err, resp, body) => {
|
||||
this._cancelIndex = null
|
||||
this._cancelPromiseCancelFn = null
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
}
|
||||
resolve(body)
|
||||
})
|
||||
})
|
||||
},
|
||||
getSinger(singers) {
|
||||
let arr = []
|
||||
singers.forEach(singer => {
|
||||
arr.push(singer.name)
|
||||
})
|
||||
return arr.join('、')
|
||||
},
|
||||
filterData(rawList) {
|
||||
// console.log(rawList)
|
||||
return rawList.map(item => {
|
||||
let types = []
|
||||
let _types = {}
|
||||
if (item.file.size_128mp3 !== 0) {
|
||||
let size = sizeFormate(item.file.size_128mp3)
|
||||
types.push({ type: '128k', size })
|
||||
_types['128k'] = {
|
||||
size,
|
||||
}
|
||||
}
|
||||
if (item.file.size_320mp3 !== 0) {
|
||||
let size = sizeFormate(item.file.size_320mp3)
|
||||
types.push({ type: '320k', size })
|
||||
_types['320k'] = {
|
||||
size,
|
||||
}
|
||||
}
|
||||
if (item.file.size_ape !== 0) {
|
||||
let size = sizeFormate(item.file.size_ape)
|
||||
types.push({ type: 'ape', size })
|
||||
_types.ape = {
|
||||
size,
|
||||
}
|
||||
}
|
||||
if (item.file.size_flac !== 0) {
|
||||
let size = sizeFormate(item.file.size_flac)
|
||||
types.push({ type: 'flac', size })
|
||||
_types.flac = {
|
||||
size,
|
||||
}
|
||||
}
|
||||
types.reverse()
|
||||
return {
|
||||
singer: this.getSinger(item.singer),
|
||||
name: item.title,
|
||||
albumName: item.album.title,
|
||||
albumId: item.album.mid,
|
||||
source: 'tx',
|
||||
interval: formatPlayTime(item.interval),
|
||||
songId: item.id,
|
||||
albumMid: item.album.mid,
|
||||
strMediaMid: item.file.media_mid,
|
||||
songmid: item.mid,
|
||||
img: (item.album.name === '' || item.album.name === '空')
|
||||
? `https://y.gtimg.cn/music/photo_new/T001R500x500M000${item.singer[0].mid}.jpg`
|
||||
: `https://y.gtimg.cn/music/photo_new/T002R500x500M000${item.album.mid}.jpg`,
|
||||
lrc: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
}
|
||||
})
|
||||
},
|
||||
getPeriods(bangid) {
|
||||
return this.getData(this.periodUrl).then(html => {
|
||||
let result = html.match(this.regExps.periodList)
|
||||
if (!result) return Promise.reject()
|
||||
result.forEach(item => {
|
||||
let result = item.match(this.regExps.period)
|
||||
if (!result) return
|
||||
this.periods[result[2]] = {
|
||||
name: result[1],
|
||||
bangid: result[2],
|
||||
period: result[3],
|
||||
}
|
||||
})
|
||||
const info = this.periods[bangid]
|
||||
return info && info.period
|
||||
})
|
||||
},
|
||||
getList(id, page) {
|
||||
let type = this.list.find(s => s.id === id)
|
||||
if (!type) return Promise.reject()
|
||||
let info = this.periods[type.bangid]
|
||||
let p = info ? Promise.resolve(info.period) : this.getPeriods(type.bangid)
|
||||
return p.then(period => {
|
||||
return this.getData(this.getUrl(type.bangid, period, this.limit)).then(data => {
|
||||
// console.log(data)
|
||||
if (data.code !== 0) return Promise.reject()
|
||||
return {
|
||||
total: data.toplist.data.songInfoList.length,
|
||||
list: this.filterData(data.toplist.data.songInfoList),
|
||||
limit: this.limit,
|
||||
page: 1,
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import leaderboard from './leaderboard'
|
||||
|
||||
const wy = {
|
||||
leaderboard,
|
||||
}
|
||||
|
||||
export default wy
|
||||
@@ -0,0 +1,123 @@
|
||||
import { httpGet, cancelHttp } from '../../request'
|
||||
import { formatPlayTime } from '../../index'
|
||||
|
||||
export default {
|
||||
limit: 300,
|
||||
list: [
|
||||
{
|
||||
id: 'wybsb',
|
||||
name: '飙升榜',
|
||||
bangid: '19723756',
|
||||
},
|
||||
{
|
||||
id: 'wyrgb',
|
||||
name: '热歌榜',
|
||||
bangid: '3778678',
|
||||
},
|
||||
{
|
||||
id: 'wyxgb',
|
||||
name: '新歌榜',
|
||||
bangid: '3779629',
|
||||
},
|
||||
{
|
||||
id: 'wyycb',
|
||||
name: '原创榜',
|
||||
bangid: '2884035',
|
||||
},
|
||||
{
|
||||
id: 'wygdb',
|
||||
name: '古典榜',
|
||||
bangid: '71384707',
|
||||
},
|
||||
{
|
||||
id: 'wydouyb',
|
||||
name: '抖音榜',
|
||||
bangid: '2250011882',
|
||||
},
|
||||
{
|
||||
id: 'wyhyb',
|
||||
name: '韩语榜',
|
||||
bangid: '745956260',
|
||||
},
|
||||
{
|
||||
id: 'wydianyb',
|
||||
name: '电音榜',
|
||||
bangid: '1978921795',
|
||||
},
|
||||
{
|
||||
id: 'wydjb',
|
||||
name: '电竞榜',
|
||||
bangid: '2006508653',
|
||||
},
|
||||
{
|
||||
id: 'wyktvbb',
|
||||
name: 'KTV唛榜',
|
||||
bangid: '21845217',
|
||||
},
|
||||
],
|
||||
getUrl(id) {
|
||||
return `https://music.163.com/discover/toplist?id=${id}`
|
||||
},
|
||||
regExps: {
|
||||
list: /<textarea id="song-list-pre-data" style="display:none;">(.+?)<\/textarea>/,
|
||||
},
|
||||
_cancelIndex: null,
|
||||
_cancelPromiseCancelFn: null,
|
||||
getData(url) {
|
||||
if (this._cancelIndex != null) {
|
||||
cancelHttp(this._cancelIndex)
|
||||
this._cancelPromiseCancelFn(new Error('取消http请求'))
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._cancelPromiseCancelFn = reject
|
||||
this._cancelIndex = httpGet(url, (err, resp, body) => {
|
||||
this._cancelIndex = null
|
||||
this._cancelPromiseCancelFn = null
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
}
|
||||
resolve(body)
|
||||
})
|
||||
})
|
||||
},
|
||||
getSinger(singers) {
|
||||
let arr = []
|
||||
singers.forEach(singer => {
|
||||
arr.push(singer.name)
|
||||
})
|
||||
return arr.join('、')
|
||||
},
|
||||
filterData(rawList) {
|
||||
// console.log(rawList)
|
||||
return rawList.map(item => {
|
||||
return {
|
||||
singer: this.getSinger(item.artists),
|
||||
name: item.name,
|
||||
albumName: item.album.name,
|
||||
albumId: item.album.id,
|
||||
source: 'wy',
|
||||
interval: formatPlayTime(item.duration / 1000),
|
||||
songmid: item.id,
|
||||
img: item.album.picUrl,
|
||||
lrc: null,
|
||||
typeUrl: {},
|
||||
}
|
||||
})
|
||||
},
|
||||
getList(id, page) {
|
||||
let type = this.list.find(s => s.id === id)
|
||||
if (!type) return Promise.reject()
|
||||
return this.getData(this.getUrl(type.bangid)).then(html => {
|
||||
let result = html.match(this.regExps.list)
|
||||
if (!result) return Promise.reject()
|
||||
const list = this.filterData(JSON.parse(RegExp.$1))
|
||||
return {
|
||||
total: list.length,
|
||||
list,
|
||||
limit: this.limit,
|
||||
page,
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
import request from 'request'
|
||||
// import progress from 'request-progress'
|
||||
import { debugRequest } from './env'
|
||||
// import fs from 'fs'
|
||||
|
||||
const tasks = []
|
||||
|
||||
const fatchData = (url, method, options, callback) => {
|
||||
let index = pushTask(tasks, request(url, {
|
||||
method,
|
||||
headers: options.headers,
|
||||
Origin: options.origin,
|
||||
data: options.data,
|
||||
json: options.format === undefined || options.format === 'json',
|
||||
}, (err, resp, body) => {
|
||||
tasks[index] = null
|
||||
if (err) return callback(err, null)
|
||||
callback(null, resp, body)
|
||||
}))
|
||||
return index
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消请求
|
||||
* @param {*} index
|
||||
*/
|
||||
export const cancelHttp = index => {
|
||||
if (index == null) return
|
||||
console.log('cancel: ', index)
|
||||
let r = tasks[index]
|
||||
if (r == null) return
|
||||
r.abort()
|
||||
tasks[index] = null
|
||||
}
|
||||
|
||||
|
||||
const pushTask = (tasks, newTask) => {
|
||||
for (const [index, task] of tasks.entries()) {
|
||||
if (task == null) {
|
||||
tasks[index] = newTask
|
||||
return index
|
||||
}
|
||||
}
|
||||
tasks.push(newTask)
|
||||
return tasks.length - 1
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* http 请求
|
||||
* @param {*} url 地址
|
||||
* @param {*} options 选项
|
||||
* @param {*} cb 回调
|
||||
* @return {Number} index 用于取消请求
|
||||
*/
|
||||
export const http = (url, options, cb) => {
|
||||
if (typeof options === 'function') {
|
||||
cb = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
// 默认选项
|
||||
if (options.method == null) options.method = 'get'
|
||||
|
||||
debugRequest && console.log(`\n---send request------${url}------------`)
|
||||
return fatchData(url, options.method, options, (err, resp, body) => {
|
||||
// options.isShowProgress && window.api.hideProgress()
|
||||
debugRequest && console.log(`\n---response------${url}------------`)
|
||||
debugRequest && console.log(JSON.stringify(body))
|
||||
if (err) {
|
||||
debugRequest && console.log(JSON.stringify(err))
|
||||
}
|
||||
cb(err, resp, body)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* http get 请求
|
||||
* @param {*} url 地址
|
||||
* @param {*} options 选项
|
||||
* @param {*} callback 回调
|
||||
* @return {Number} index 用于取消请求
|
||||
*/
|
||||
export const httpGet = (url, options, callback) => {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
// options.isShowProgress && window.api.showProgress({
|
||||
// title: options.progressMsg || '请求中',
|
||||
// modal: true,
|
||||
// })
|
||||
|
||||
debugRequest && console.log(`\n---send request-------${url}------------`)
|
||||
return fatchData(url, 'get', options, function(err, resp, body) {
|
||||
// options.isShowProgress && window.api.hideProgress()
|
||||
debugRequest && console.log(`\n---response------${url}------------`)
|
||||
debugRequest && console.log(JSON.stringify(body))
|
||||
if (err) {
|
||||
debugRequest && console.log(JSON.stringify(err))
|
||||
}
|
||||
callback(err, resp, body)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* http post 请求
|
||||
* @param {*} url 请求地址
|
||||
* @param {*} data 提交的数据
|
||||
* @param {*} options 选项
|
||||
* @param {*} callback 回调
|
||||
* @return {Number} index 用于取消请求
|
||||
*/
|
||||
export const httpPost = (url, data, options, callback) => {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
// options.isShowProgress && window.api.showProgress({
|
||||
// title: options.progressMsg || '请求中',
|
||||
// modal: true,
|
||||
// })
|
||||
options.data = data
|
||||
|
||||
debugRequest && console.log(`\n---send request-------${url}------------`)
|
||||
return fatchData(url, 'post', options, function(err, resp, body) {
|
||||
// options.isShowProgress && window.api.hideProgress()
|
||||
debugRequest && console.log(`\n---response------${url}------------`)
|
||||
debugRequest && console.log(JSON.stringify(body))
|
||||
if (err) {
|
||||
debugRequest && console.log(JSON.stringify(err))
|
||||
}
|
||||
callback(err, resp, body)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* http jsonp 请求
|
||||
* @param {*} url 请求地址
|
||||
* @param {*} options 选项
|
||||
* options.jsonpCallback 回调
|
||||
* @param {*} callback 回调
|
||||
* @return {Number} index 用于取消请求
|
||||
*/
|
||||
export const http_jsonp = (url, options, callback) => {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
let jsonpCallback = 'jsonpCallback'
|
||||
if (url.indexOf('?') < 0) url += '?'
|
||||
url += `&${options.jsonpCallback}=${jsonpCallback}`
|
||||
|
||||
options.format = 'script'
|
||||
|
||||
// options.isShowProgress && window.api.showProgress({
|
||||
// title: options.progressMsg || '请求中',
|
||||
// modal: true,
|
||||
// })
|
||||
|
||||
debugRequest && console.log(`\n---send request-------${url}------------`)
|
||||
return fatchData(url, 'get', options, function(err, resp, body) {
|
||||
// options.isShowProgress && window.api.hideProgress()
|
||||
debugRequest && console.log(`\n---response------${url}------------`)
|
||||
debugRequest && console.log(JSON.stringify(body))
|
||||
if (err) {
|
||||
debugRequest && console.log(JSON.stringify(err))
|
||||
} else {
|
||||
body = JSON.parse(body.replace(new RegExp(`^${jsonpCallback}\\(({.*})\\)$`), '$1'))
|
||||
}
|
||||
|
||||
callback(err, resp, body)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user