CatPtain's picture
Upload 83 files
765bc42 verified
/* eslint-disable no-undef */
/* eslint-disable no-unused-vars */
/* global async getParameterByName isElectron */
class kuwo {
// Convert html code
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;
}
// Fix single quote in json
static fix_json(data) {
return data.replace(/(')/g, '"');
}
static num2str(num) {
// const t = parseInt(num, 10);
return parseInt(num / 10, 10).toString() + (num % 10).toString();
}
/*
static kw_convert_song(item) {
const song_id = item.MUSICRID.split('_').pop();
const track = {
id: `kwtrack_${song_id}`,
title: html_decode(item.SONGNAME),
artist: html_decode(item.ARTIST),
artist_id: `kwartist_${item.ARTISTID}`,
album: html_decode(item.ALBUM),
album_id: `kwalbum_${item.ALBUMID}`,
source: 'kuwo',
source_url: `https://www.kuwo.cn/play_detail/${song_id}`,
img_url: '',
// url: `kwtrack_${song_id}`,
lyric_url: song_id,
};
return track;
}
*/
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,
// url: `kwtrack_${musicrid}`,
lyric_url: item.rid,
};
}
/*
function async_process_list(data_list, handler, handler_extra_param_list, callback) {
const fnDict = {};
data_list.forEach((item, index) => {
fnDict[index] = (cb) => handler(index, item, handler_extra_param_list, cb);
});
async.parallel(fnDict, (err, results) => {
callback(null, data_list.map((item, index) => results[index]));
});
}
function kw_add_song_pic_in_track(track, params, callback) {
// Add song picture image
const target_url = 'https://artistpicserver.kuwo.cn/pic.web?'
+ `type=rid_pic&pictype=url&size=240&rid=${track.lyric_url}`;
axios.get(target_url)
.then((response) => {
const { data } = response;
track.img_url = data; // eslint-disable-line no-param-reassign
callback(null, track);
});
}
function kw_render_search_result_item(index, item, params, callback) {
const track = kw_convert_song(item);
kw_add_song_pic_in_track(track, params, callback);
}
function kw_render_artist_result_item(index, item, params, callback) {
const track = {
id: `kwtrack_${item.musicrid}`,
title: html_decode(item.name),
artist: item.artist,
artist_id: `kwartist_${item.artistid}`,
album: html_decode(item.album),
album_id: `kwalbum_${item.albumid}`,
source: 'kuwo',
source_url: `https://www.kuwo.cn/play_detail/${item.musicrid}`,
img_url: '',
//url: `kwtrack_${item.musicrid}`,
lyric_url: item.musicrid,
};
kw_add_song_pic_in_track(track, params, callback);
}
function kw_render_album_result_item(index, item, params, callback) {
const info = params[0];
const track = {
id: `kwtrack_${item.id}`,
title: html_decode(item.name),
artist: item.artist,
artist_id: `kwartist_${item.artistid}`,
album: info.title,
album_id: `kwalbum_${info.id}`,
source: 'kuwo',
source_url: `https://www.kuwo.cn/play_detail/${item.id}`,
img_url: '',
//url: `kwtrack_${item.id}`,
lyric_url: item.id,
};
kw_add_song_pic_in_track(track, params, callback);
}
function kw_render_playlist_result_item(index, item, params, callback) {
const track = {
id: `kwtrack_${item.id}`,
title: html_decode(item.name),
artist: item.artist,
artist_id: `kwartist_${item.artistid}`,
album: html_decode(item.album),
album_id: `kwalbum_${item.albumid}`,
source: 'kuwo',
source_url: `https://www.kuwo.cn/play_detail/${item.id}`,
img_url: '',
//url: `kwtrack_${item.id}`,
lyric_url: item.id,
};
kw_add_song_pic_in_track(track, params, callback);
}
*/
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) {
// token expire, refetch token and start get url
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://m.kuwo.cn/newh5app/api/mobile/v1/music/playlist/${list_id}?pn=${page}&rn=1000`
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://m.kuwo.cn/newh5app/api/mobile/v1/music/album/${list_id}?rn=1000`
tracks_url = `https://www.kuwo.cn/api/www/album/albumInfo?albumId=${list_id}&pn=${page}&rn=100&httpsStatus=1`;
break;
default:
break;
}
// axios.get(tracks_url).then((response) => {
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) {
// eslint-disable-line no-unused-vars
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,
});
});
},
};
}
// eslint-disable-next-line no-unused-vars
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}`;
/* const target_url = 'https://www.kuwo.cn/url?'
+ `format=mp3&rid=${song_id}&response=url&type=convert_url3&br=128kmp3&from=web`;
https://m.kuwo.cn/newh5app/api/mobile/v1/music/src/${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 !== '//');
// 暂时原歌词和翻译都在原歌词显示
// 酷我的歌词格式中没区分,查看了几个歌词文件发现,翻译歌词也存在和原来歌词的时间轴不一致的情况
// 如果按照时间区分可能造成错行问题。
// 将歌词和翻译分成两个数组,并将对应歌词和翻译的时间调整为相等,数组最后一个数据无法做判断,故传给翻译数组做后续处理
// const lrc_arr = [];
// const tlrc_arr = [];
// let lrc_arr = lrclist.filter(
// (item, index, self) => {
// if (index < self.length - 1) {
// if (Number(item.time) === 0) {
// return item;
// }
// return item.time !== self[index + 1].time;
// }
// return null;
// },
// );
// let tlrc_arr = lrclist.filter(
// (item, index, self) => {
// if (index < self.length - 1 && Number(item.time) !== 0
// && item.time === self[index + 1].time) {
// return item.time === self[index - 1].time;
// }
// return (index === self.length - 1 ? item : null);
// },
// );
// // tlrc_arr如只有一个即为没有翻译歌词
// if (tlrc_arr.length === 1) {
// lrc_arr = [...lrc_arr, ...tlrc_arr];
// tlrc_arr = [];
// } else {
// tlrc_arr[tlrc_arr.length - 1].time = lrc_arr[lrc_arr.length - 1].time;
// }
return {
lrc: kuwo.kw_get_lrc(lrclist),
tlrc: kuwo.kw_get_lrc([]),
};
}
return {
lrc: '',
tlrc: '',
};
}
static lyric(url) {
// eslint-disable-line no-unused-vars
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) {
// eslint-disable-line no-unused-vars
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;
// data = JSON.parse(fix_json(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}`,
};
// Get songs
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,
});
});
/*
target_url = 'https://search.kuwo.cn/r.s?stype=artist2music'
+ '&sortby=0&alflac=1&pcmp4=1&encoding=utf8'
+ `&artistid=${artist_id}&pn=0&rn=100`;
axios.get(target_url).then((response) => {
let { data } = response; // TODO: Check JSON Schema is correct
data = JSON.parse(fix_json(data));
async_process_list(data.musiclist, kw_render_artist_result_item, [],
(err, tracks) => fn({
tracks,
info,
}));
*/
});
},
};
}
static kw_album(url) {
// eslint-disable-line no-unused-vars
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}`,
};
// Get songs
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,
});
}
);
/*
async_process_list(data.musiclist, kw_render_album_result_item, [info],
(err, tracks) => fn({
tracks,
info,
}));
*/
});
},
};
}
static show_playlist(url) {
const offset = Number(getParameterByName('offset', url));
/* const id_available = {
1265: '经典',
577: '纯音乐',
621: '网络',
155: '怀旧',
1879: '网红',
220: '佛乐',
180: '影视',
578: '器乐',
1877: '游戏',
181: '二次元',
882: 'KTV',
216: '喊麦',
1366: '3D',
146: '伤感',
62: '放松',
58: '励志',
143: '开心',
137: '甜蜜',
139: '兴奋',
67: '安静',
66: '治愈',
147: '寂寞',
160: '四年',
366: '运动',
354: '睡前',
378: '跳舞',
1876: '学习',
353: '清晨',
359: '夜店',
382: '校园',
544: '亲热',
363: '咖啡店',
375: '旅行',
371: '散步',
386: '工作',
336: '婚礼',
637: '70后',
638: '80后',
639: '90后',
640: '00后',
268: '10后',
393: '流行',
391: '电子',
389: '摇滚',
1921: '民歌',
392: '民谣',
399: '乡村',
35: '欧洲',
37: '华语',
}; */
// const target_url = 'https://www.kuwo.cn/www/categoryNew/getPlayListInfoUnderCategory?'
// + `type=taglist&digest=10000&id=${37}&start=${offset}&count=50`;
const target_url = `https://www.kuwo.cn/api/pc/classify/playlist/getRcmPlayList?pn=${
offset / 25 + 1
}&rn=25&order=hot&httpsStatus=1`;
/*
精选歌单:roder=最热:hot, 最新:new
tag歌单地址 https://www.kuwo.cn/api/pc/classify/playlist/getTagPlayList?pn=${offset / 25 + 1}&rn=25&id=37&httpsStatus=1
id =华语:37,
*/
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) {
// eslint-disable-line no-unused-vars
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`;
// https://www.kuwo.cn/api/www/playlist/playListInfo?pid=3134372426&pn=1&rn=30
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,
});
}
);
/*
async_process_list(data.musiclist, kw_render_playlist_result_item, [],
(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) {
// eslint-disable-next-line prefer-destructuring
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() {}
// return {
// show_playlist: kw_show_playlist,
// get_playlist_filters,
// get_playlist,
// parse_url: kw_parse_url,
// bootstrap_track: kw_bootstrap_track,
// search: kw_search,
// lyric: kw_lyric,
// get_user: kw_get_user,
// get_login_url: kw_get_login_url,
// logout: kw_logout,
// };
}