|
|
|
|
|
|
|
class kuwo { |
|
|
|
static html_decode(str) { |
|
let text = str; |
|
const entities = [ |
|
['amp', '&'], |
|
['apos', "'"], |
|
['#x27', "'"], |
|
['#x2F', '/'], |
|
['#39', "'"], |
|
['#47', '/'], |
|
['lt', '<'], |
|
['gt', '>'], |
|
['nbsp', ' '], |
|
['quot', '"'], |
|
]; |
|
|
|
for (let i = 0, max = entities.length; i < max; i += 1) { |
|
text = text.replace( |
|
new RegExp(`&${entities[i][0]};`, 'g'), |
|
entities[i][1] |
|
); |
|
} |
|
|
|
return text; |
|
} |
|
|
|
|
|
static fix_json(data) { |
|
return data.replace(/(')/g, '"'); |
|
} |
|
|
|
static num2str(num) { |
|
|
|
return parseInt(num / 10, 10).toString() + (num % 10).toString(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static kw_convert_song2(item) { |
|
return { |
|
id: `kwtrack_${item.rid}`, |
|
title: this.html_decode(item.name), |
|
artist: this.html_decode(item.artist), |
|
artist_id: `kwartist_${item.artistid}`, |
|
album: this.html_decode(item.album), |
|
album_id: `kwalbum_${item.albumid}`, |
|
source: 'kuwo', |
|
source_url: `https://www.kuwo.cn/play_detail/${item.rid}`, |
|
img_url: item.pic, |
|
|
|
lyric_url: item.rid, |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static kw_get_token(callback, isRetry) { |
|
let isRetryValue = true; |
|
if (isRetry === undefined) { |
|
isRetryValue = false; |
|
} else { |
|
isRetryValue = isRetry; |
|
} |
|
const domain = 'https://www.kuwo.cn'; |
|
const name = 'kw_token'; |
|
|
|
cookieGet( |
|
{ |
|
url: domain, |
|
name, |
|
}, |
|
(cookie) => { |
|
if (cookie == null) { |
|
if (isRetryValue) { |
|
return callback(''); |
|
} |
|
return axios.get('https://www.kuwo.cn/').then(() => { |
|
this.kw_get_token(callback, true); |
|
}); |
|
} |
|
return callback(cookie.value); |
|
} |
|
); |
|
} |
|
|
|
static kw_cookie_get(url, callback) { |
|
this.kw_get_token((token) => { |
|
axios |
|
.get(url, { |
|
headers: { |
|
csrf: token, |
|
}, |
|
}) |
|
.then((response) => { |
|
if (response.data.success === false) { |
|
|
|
this.kw_get_token((token2) => { |
|
axios |
|
.get(url, { |
|
headers: { |
|
csrf: token2, |
|
}, |
|
}) |
|
.then((res) => { |
|
callback(res); |
|
}); |
|
}); |
|
} else { |
|
callback(response); |
|
} |
|
}) |
|
.catch(() => { |
|
callback(); |
|
}); |
|
}); |
|
} |
|
|
|
static kw_render_tracks(url, page, callback) { |
|
const list_id = getParameterByName('list_id', url).split('_').pop(); |
|
const playlist_type = getParameterByName('list_id', url).split('_')[0]; |
|
let tracks_url = ''; |
|
switch (playlist_type) { |
|
case 'kwplaylist': |
|
|
|
tracks_url = `https://www.kuwo.cn/api/www/playlist/playListInfo?pid=${list_id}&pn=${page}&rn=100&httpsStatus=1`; |
|
break; |
|
case 'kwalbum': |
|
|
|
tracks_url = `https://www.kuwo.cn/api/www/album/albumInfo?albumId=${list_id}&pn=${page}&rn=100&httpsStatus=1`; |
|
break; |
|
default: |
|
break; |
|
} |
|
|
|
this.kw_cookie_get(tracks_url, (response) => { |
|
const tracks = response.data.data.musicList.map((item) => |
|
this.kw_convert_song2(item) |
|
); |
|
return callback(null, tracks); |
|
}); |
|
} |
|
|
|
static search(url) { |
|
|
|
const keyword = getParameterByName('keywords', url); |
|
const curpage = getParameterByName('curpage', url); |
|
const searchType = getParameterByName('type', url); |
|
let api = ''; |
|
switch (searchType) { |
|
case '0': |
|
api = 'searchMusicBykeyWord'; |
|
break; |
|
case '1': |
|
api = 'searchPlayListBykeyWord'; |
|
break; |
|
default: |
|
break; |
|
} |
|
const target_url = `https://www.kuwo.cn/api/www/search/${api}?key=${keyword}&pn=${curpage}&rn=20`; |
|
return { |
|
success: (fn) => { |
|
this.kw_cookie_get(target_url, (response) => { |
|
let result = []; |
|
let total = 0; |
|
if (response === undefined) { |
|
return fn({ |
|
result, |
|
total, |
|
type: searchType, |
|
}); |
|
} |
|
if (searchType === '0' && response.data.data !== undefined) { |
|
result = response.data.data.list.map((item) => |
|
this.kw_convert_song2(item) |
|
); |
|
total = response.data.data.total; |
|
} else if (searchType === '1' && response.data.data !== undefined) { |
|
result = response.data.data.list.map((item) => ({ |
|
id: `kwplaylist_${item.id}`, |
|
title: this.html_decode(item.name), |
|
source: 'kuwo', |
|
source_url: `https://www.kuwo.cn/playlist_detail/${item.id}`, |
|
img_url: item.img, |
|
url: `kwplaylist_${item.id}`, |
|
author: this.html_decode(item.uname), |
|
count: item.total, |
|
})); |
|
total = response.data.data.total; |
|
} |
|
return fn({ |
|
result, |
|
total, |
|
type: searchType, |
|
}); |
|
}); |
|
}, |
|
}; |
|
} |
|
|
|
|
|
static bootstrap_track(track, success, failure) { |
|
const sound = {}; |
|
const song_id = track.id.slice('kwtrack_'.length); |
|
const target_url = |
|
'https://antiserver.kuwo.cn/anti.s?' + |
|
`type=convert_url&format=mp3&response=url&rid=${song_id}`; |
|
|
|
|
|
|
|
|
|
axios.get(target_url).then((response) => { |
|
const { data } = response; |
|
if (data.length > 0) { |
|
sound.url = data; |
|
sound.platform = 'kuwo'; |
|
|
|
success(sound); |
|
} else { |
|
failure(sound); |
|
} |
|
}); |
|
} |
|
|
|
static kw_get_lrc(arr) { |
|
const lyric = arr.reduce((str, item) => { |
|
const t = parseFloat(item.time); |
|
const m = parseInt(t / 60, 10); |
|
const s = parseInt(t - m * 60, 10); |
|
const ms = parseInt((t - m * 60 - s) * 100, 10); |
|
return `${str}[${this.num2str(m)}:${this.num2str( |
|
parseInt(s, 10) |
|
)}.${this.num2str(ms)}]${item.lineLyric}\n`; |
|
}, ''); |
|
return lyric; |
|
} |
|
|
|
static kw_generate_translation(lrclist) { |
|
if (lrclist) { |
|
lrclist.filter((e) => e && e.lineLyric !== '//'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return { |
|
lrc: kuwo.kw_get_lrc(lrclist), |
|
tlrc: kuwo.kw_get_lrc([]), |
|
}; |
|
} |
|
return { |
|
lrc: '', |
|
tlrc: '', |
|
}; |
|
} |
|
|
|
static lyric(url) { |
|
|
|
const track_id = getParameterByName('lyric_url', url); |
|
const target_url = `https://m.kuwo.cn/newh5/singles/songinfoandlrc?musicId=${track_id}`; |
|
|
|
return { |
|
success: (fn) => { |
|
axios.get(target_url).then((response) => { |
|
let { data } = response; |
|
data = |
|
data.status === 200 |
|
? this.kw_generate_translation(data.data.lrclist) |
|
: {}; |
|
return fn({ |
|
lyric: data.lrc || '', |
|
tlyric: data.tlrc || '', |
|
}); |
|
}); |
|
}, |
|
}; |
|
} |
|
|
|
static kw_artist(url) { |
|
|
|
const artist_id = getParameterByName('list_id', url).split('_').pop(); |
|
return { |
|
success: (fn) => { |
|
let target_url = `https://www.kuwo.cn/api/www/artist/artist?artistid=${artist_id}`; |
|
this.kw_cookie_get(target_url, (response) => { |
|
const { data } = response.data; |
|
|
|
const info = { |
|
cover_img_url: data.pic300, |
|
title: this.html_decode(data.name), |
|
id: `kwartist_${data.id}`, |
|
source_url: `https://www.kuwo.cn/singer_detail/${data.id}`, |
|
}; |
|
|
|
|
|
target_url = `https://www.kuwo.cn/api/www/artist/artistMusic?artistid=${artist_id}&pn=1&rn=50`; |
|
this.kw_cookie_get(target_url, (res) => { |
|
const tracks = res.data.data.list.map((item) => |
|
this.kw_convert_song2(item) |
|
); |
|
return fn({ |
|
tracks, |
|
info, |
|
}); |
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}); |
|
}, |
|
}; |
|
} |
|
|
|
static kw_album(url) { |
|
|
|
const album_id = getParameterByName('list_id', url).split('_').pop(); |
|
return { |
|
success: (fn) => { |
|
const target_url = |
|
'https://search.kuwo.cn/r.s?pn=0&rn=0&stype=albuminfo' + |
|
`&albumid=${album_id}&alflac=1&pcmp4=1&encoding=utf8` + |
|
'&vipver=MUSIC_8.7.7.0_W4'; |
|
axios.get(target_url).then((response) => { |
|
let { data } = response; |
|
data = JSON.parse(this.fix_json(data)); |
|
|
|
const info = { |
|
cover_img_url: data.hts_img.replace('/120/', '/400/'), |
|
title: this.html_decode(data.name), |
|
id: `kwalbum_${data.albumid}`, |
|
source_url: `https://www.kuwo.cn/album_detail/${data.albumid}`, |
|
}; |
|
|
|
const total = data.songnum; |
|
const page = Math.ceil(total / 100); |
|
const page_array = Array.from({ length: page }, (v, k) => k + 1); |
|
async.concat( |
|
page_array, |
|
(item, callback) => this.kw_render_tracks(url, item, callback), |
|
(err, tracks) => { |
|
fn({ |
|
tracks, |
|
info, |
|
}); |
|
} |
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}); |
|
}, |
|
}; |
|
} |
|
|
|
static show_playlist(url) { |
|
const offset = Number(getParameterByName('offset', url)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const target_url = `https://www.kuwo.cn/api/pc/classify/playlist/getRcmPlayList?pn=${ |
|
offset / 25 + 1 |
|
}&rn=25&order=hot&httpsStatus=1`; |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
success: (fn) => { |
|
axios.get(target_url).then((response) => { |
|
const { data } = response.data; |
|
if (!data) { |
|
return fn([]); |
|
} |
|
const result = data.data.map((item) => ({ |
|
cover_img_url: item.img, |
|
title: item.name, |
|
id: `kwplaylist_${item.id}`, |
|
source_url: `https://www.kuwo.cn/playlist_detail/${item.id}`, |
|
})); |
|
return fn({ |
|
result, |
|
}); |
|
}); |
|
}, |
|
}; |
|
} |
|
|
|
static kw_get_playlist(url) { |
|
|
|
const list_id = getParameterByName('list_id', url).split('_').pop(); |
|
const target_url = |
|
'https://nplserver.kuwo.cn/pl.svc?' + |
|
'op=getlistinfo&pn=0&rn=0&encode=utf-8&keyset=pl2012&pcmp4=1' + |
|
`&pid=${list_id}&vipver=MUSIC_9.0.2.0_W1&newver=1`; |
|
|
|
return { |
|
success: (fn) => { |
|
axios.get(target_url).then((response) => { |
|
const { data } = response; |
|
|
|
const info = { |
|
cover_img_url: data.pic.replace('_150.jpg', '_400.jpg'), |
|
title: data.title, |
|
id: `kwplaylist_${data.id}`, |
|
source_url: `https://www.kuwo.cn/playlist_detail/${data.id}`, |
|
}; |
|
const { total } = data; |
|
const page = Math.ceil(total / 100); |
|
const page_array = Array.from({ length: page }, (v, k) => k + 1); |
|
async.concat( |
|
page_array, |
|
(item, callback) => this.kw_render_tracks(url, item, callback), |
|
(err, tracks) => { |
|
fn({ |
|
tracks, |
|
info, |
|
}); |
|
} |
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}); |
|
}, |
|
}; |
|
} |
|
|
|
static parse_url(myurl) { |
|
let result; |
|
let id; |
|
let url = myurl; |
|
url = url.replace(/kuwo.cn\/(h5app|newh5(?:app){0,1})\//, 'kuwo.cn/'); |
|
url = url.replace(/kuwo.cn\/(album\/|\?albumid=)/, 'kuwo.cn/album_detail/'); |
|
url = url.replace(/kuwo.cn\/(artist|singers)\//, 'kuwo.cn/singer_detail/'); |
|
url = url.replace(/kuwo.cn\/playlist\//, 'kuwo.cn/playlist_detail/'); |
|
if (url.search('kuwo.cn/playlist_detail') !== -1) { |
|
const match = /kuwo.cn\/playlist_detail\/([0-9]+)/.exec(url); |
|
id = match ? match[1] : getParameterByName('pid', url); |
|
result = { |
|
type: 'playlist', |
|
id: `kwplaylist_${id}`, |
|
}; |
|
} else if (url.search('kuwo.cn/singer_detail') !== -1) { |
|
const match = /kuwo.cn\/singer_detail\/([0-9]+)/.exec(url); |
|
id = match ? match[1] : getParameterByName('id', url); |
|
result = { |
|
type: 'playlist', |
|
id: `kwartist_${id}`, |
|
}; |
|
} else if (url.search('kuwo.cn/album_detail') !== -1) { |
|
const match = /kuwo.cn\/album_detail\/([0-9]+)/.exec(url); |
|
if (match) { |
|
|
|
id = match[1]; |
|
result = { |
|
type: 'playlist', |
|
id: `kwalbum_${id}`, |
|
}; |
|
} |
|
} |
|
return { |
|
success: (fn) => { |
|
fn(result); |
|
}, |
|
}; |
|
} |
|
|
|
static get_playlist(url) { |
|
const list_id = getParameterByName('list_id', url).split('_')[0]; |
|
switch (list_id) { |
|
case 'kwplaylist': |
|
return this.kw_get_playlist(url); |
|
case 'kwalbum': |
|
return this.kw_album(url); |
|
case 'kwartist': |
|
return this.kw_artist(url); |
|
default: |
|
return null; |
|
} |
|
} |
|
|
|
static get_playlist_filters() { |
|
return { |
|
success: (fn) => fn({ recommend: [], all: [] }), |
|
}; |
|
} |
|
|
|
static get_user() { |
|
return { |
|
success: (fn) => { |
|
fn({ status: 'fail', data: {} }); |
|
}, |
|
}; |
|
} |
|
|
|
static get_login_url() { |
|
return `https://www.kuwo.com`; |
|
} |
|
|
|
static logout() {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|