music/wy.js
2024-11-16 07:21:48 -06:00

556 lines
19 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const CryptoJs = require("crypto-js");
const qs = require("qs");
const bigInt = require("big-integer");
const dayjs = require("dayjs");
const cheerio = require("cheerio");
function create_key() {
var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
for (d = 0; 16 > d; d += 1)
(e = Math.random() * b.length), (e = Math.floor(e)), (c += b.charAt(e));
return c;
}
function AES(a, b) {
var c = CryptoJs.enc.Utf8.parse(b), d = CryptoJs.enc.Utf8.parse("0102030405060708"), e = CryptoJs.enc.Utf8.parse(a), f = CryptoJs.AES.encrypt(e, c, {
iv: d,
mode: CryptoJs.mode.CBC,
});
return f.toString();
}
function Rsa(text) {
text = text.split("").reverse().join("");
const d = "010001";
const e = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7";
const hexText = text
.split("")
.map((_) => _.charCodeAt(0).toString(16))
.join("");
const res = bigInt(hexText, 16)
.modPow(bigInt(d, 16), bigInt(e, 16))
.toString(16);
return Array(256 - res.length)
.fill("0")
.join("")
.concat(res);
}
function getParamsAndEnc(text) {
const first = AES(text, "0CoJUm6Qyw8W8jud");
const rand = create_key();
const params = AES(first, rand);
const encSecKey = Rsa(rand);
return {
params,
encSecKey,
};
}
function formatMusicItem(_) {
var _a, _b, _c, _d;
const album = _.al || _.album;
return {
id: _.id,
artwork: album === null || album === void 0 ? void 0 : album.picUrl,
title: _.name,
artist: (_.ar || _.artists)[0].name,
album: album === null || album === void 0 ? void 0 : album.name,
url: `https://share.duanx.cn/url/wy/${_.id}/128k`,
qualities: {
low: {
size: (_a = (_.l || {})) === null || _a === void 0 ? void 0 : _a.size,
},
standard: {
size: (_b = (_.m || {})) === null || _b === void 0 ? void 0 : _b.size,
},
high: {
size: (_c = (_.h || {})) === null || _c === void 0 ? void 0 : _c.size,
},
super: {
size: (_d = (_.sq || {})) === null || _d === void 0 ? void 0 : _d.size,
},
},
copyrightId: _ === null || _ === void 0 ? void 0 : _.copyrightId
};
}
function formatAlbumItem(_) {
return {
id: _.id,
artist: _.artist.name,
title: _.name,
artwork: _.picUrl,
description: "",
date: dayjs.unix(_.publishTime / 1000).format("YYYY-MM-DD"),
};
}
const pageSize = 30;
async function searchBase(query, page, type) {
const data = {
s: query,
limit: pageSize,
type: type,
offset: (page - 1) * pageSize,
csrf_token: "",
};
const pae = getParamsAndEnc(JSON.stringify(data));
const paeData = qs.stringify(pae);
const headers = {
authority: "music.163.com",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
"content-type": "application/x-www-form-urlencoded",
accept: "*/*",
origin: "https://music.163.com",
"sec-fetch-site": "same-origin",
"sec-fetch-mode": "cors",
"sec-fetch-dest": "empty",
referer: "https://music.163.com/search/",
"accept-language": "zh-CN,zh;q=0.9",
};
const res = (await (0, axios_1.default)({
method: "post",
url: "https://music.163.com/weapi/search/get",
headers,
data: paeData,
})).data;
return res;
}
async function searchMusic(query, page) {
const res = await searchBase(query, page, 1);
const songs = res.result.songs
.map(formatMusicItem);
return {
isEnd: res.result.songCount <= page * pageSize,
data: songs,
};
}
async function searchAlbum(query, page) {
const res = await searchBase(query, page, 10);
const albums = res.result.albums.map(formatAlbumItem);
return {
isEnd: res.result.albumCount <= page * pageSize,
data: albums,
};
}
async function searchArtist(query, page) {
const res = await searchBase(query, page, 100);
const artists = res.result.artists.map((_) => ({
name: _.name,
id: _.id,
avatar: _.img1v1Url,
worksNum: _.albumSize,
}));
return {
isEnd: res.result.artistCount <= page * pageSize,
data: artists,
};
}
async function searchMusicSheet(query, page) {
const res = await searchBase(query, page, 1000);
const playlists = res.result.playlists.map((_) => {
var _a;
return ({
title: _.name,
id: _.id,
coverImg: _.coverImgUrl,
artist: (_a = _.creator) === null || _a === void 0 ? void 0 : _a.nickname,
playCount: _.playCount,
worksNum: _.trackCount,
});
});
return {
isEnd: res.result.playlistCount <= page * pageSize,
data: playlists,
};
}
async function searchLyric(query, page) {
var _a, _b;
const res = await searchBase(query, page, 1006);
const lyrics = (_b = (_a = res.result.songs) === null || _a === void 0 ? void 0 : _a.map((it) => {
var _a, _b, _c, _d;
return ({
title: it.name,
artist: (_a = it.ar) === null || _a === void 0 ? void 0 : _a.map((_) => _.name).join(", "),
id: it.id,
artwork: (_b = it.al) === null || _b === void 0 ? void 0 : _b.picUrl,
album: (_c = it.al) === null || _c === void 0 ? void 0 : _c.name,
rawLrcTxt: (_d = it.lyrics) === null || _d === void 0 ? void 0 : _d.join("\n"),
});
})) !== null && _b !== void 0 ? _b : [];
return {
isEnd: res.result.songCount <= page * pageSize,
data: lyrics,
};
}
async function getArtistWorks(artistItem, page, type) {
const data = {
csrf_token: "",
};
const pae = getParamsAndEnc(JSON.stringify(data));
const paeData = qs.stringify(pae);
const headers = {
authority: "music.163.com",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
"content-type": "application/x-www-form-urlencoded",
accept: "*/*",
origin: "https://music.163.com",
"sec-fetch-site": "same-origin",
"sec-fetch-mode": "cors",
"sec-fetch-dest": "empty",
referer: "https://music.163.com/search/",
"accept-language": "zh-CN,zh;q=0.9",
};
if (type === "music") {
const res = (await (0, axios_1.default)({
method: "post",
url: `https://music.163.com/weapi/v1/artist/${artistItem.id}?csrf_token=`,
headers,
data: paeData,
})).data;
return {
isEnd: true,
data: res.hotSongs.map(formatMusicItem),
};
}
else if (type === "album") {
const res = (await (0, axios_1.default)({
method: "post",
url: `https://music.163.com/weapi/artist/albums/${artistItem.id}?csrf_token=`,
headers,
data: paeData,
})).data;
return {
isEnd: true,
data: res.hotAlbums.map(formatAlbumItem),
};
}
}
async function getTopListDetail(topListItem) {
const musicList = await getSheetMusicById(topListItem.id);
return Object.assign(Object.assign({}, topListItem), { musicList });
}
async function getLyric(musicItem) {
const headers = {
Referer: "https://y.music.163.com/",
Origin: "https://y.music.163.com/",
authority: "music.163.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded",
};
const data = { id: musicItem.id, lv: -1, tv: -1, csrf_token: "" };
const pae = getParamsAndEnc(JSON.stringify(data));
const paeData = qs.stringify(pae);
const result = (await (0, axios_1.default)({
method: "post",
url: `https://interface.music.163.com/weapi/song/lyric?csrf_token=`,
headers,
data: paeData,
})).data;
return {
rawLrc: result.lrc.lyric,
};
}
async function getMusicInfo(musicItem) {
const headers = {
Referer: "https://y.music.163.com/",
Origin: "https://y.music.163.com/",
authority: "music.163.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded",
};
const data = { id: musicItem.id, ids: `[${musicItem.id}]` };
const result = (await axios_1.get('http://music.163.com/api/song/detail',
{
headers,
params: data
})).data;
return {
artwork: result.songs[0].album.picUrl,
};
}
async function getAlbumInfo(albumItem) {
const headers = {
Referer: "https://y.music.163.com/",
Origin: "https://y.music.163.com/",
authority: "music.163.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded",
};
const data = {
resourceType: 3,
resourceId: albumItem.id,
limit: 15,
csrf_token: "",
};
const pae = getParamsAndEnc(JSON.stringify(data));
const paeData = qs.stringify(pae);
const res = (await (0, axios_1.default)({
method: "post",
url: `https://interface.music.163.com/weapi/v1/album/${albumItem.id}?csrf_token=`,
headers,
data: paeData,
})).data;
return {
albumItem: { description: res.album.description },
musicList: (res.songs || [])
.map(formatMusicItem),
};
}
async function getValidMusicItems(trackIds) {
const headers = {
Referer: "https://y.music.163.com/",
Origin: "https://y.music.163.com/",
authority: "music.163.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded",
};
try {
// 获取歌曲详情数据
const res = (await axios_1.default.get(`https://music.163.com/api/song/detail/?ids=[${trackIds.join(",")}]`, { headers })).data;
// 直接格式化歌曲项,不检查 URL
const validMusicItems = res.songs.map(formatMusicItem);
return validMusicItems;
}
catch (e) {
console.error(e);
return [];
}
}
async function getSheetMusicById(id) {
const headers = {
Referer: "https://y.music.163.com/",
Origin: "https://y.music.163.com/",
authority: "music.163.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
};
const sheetDetail = (await axios_1.default.get(`https://music.163.com/api/v3/playlist/detail?id=${id}&n=5000`, {
headers,
})).data;
const trackIds = sheetDetail.playlist.trackIds.map((_) => _.id);
let result = [];
let idx = 0;
while (idx * 200 < trackIds.length) {
const res = await getValidMusicItems(trackIds.slice(idx * 200, (idx + 1) * 200));
result = result.concat(res);
++idx;
}
return result;
}
async function importMusicSheet(urlLike) {
const matchResult = urlLike.match(/(?:https:\/\/y\.music\.163.com\/m\/playlist\?id=([0-9]+))|(?:https?:\/\/music\.163\.com\/playlist\/([0-9]+)\/.*)|(?:https?:\/\/music.163.com(?:\/#)?\/playlist\?id=(\d+))|(?:^\s*(\d+)\s*$)/);
const id = matchResult[1] || matchResult[2] || matchResult[3] || matchResult[4];
return getSheetMusicById(id);
}
async function getTopLists() {
const res = await axios_1.default.get("https://music.163.com/discover/toplist", {
headers: {
referer: "https://music.163.com/",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54",
},
});
const $ = cheerio.load(res.data);
const children = $(".n-minelst").children();
const groups = [];
let currentGroup = {};
for (let c of children) {
if (c.tagName == "h2") {
if (currentGroup.title) {
groups.push(currentGroup);
}
currentGroup = {};
currentGroup.title = $(c).text();
currentGroup.data = [];
}
else if (c.tagName === "ul") {
let sections = $(c).children();
currentGroup.data = sections
.map((index, element) => {
const ele = $(element);
const id = ele.attr("data-res-id");
const coverImg = ele.find("img").attr("src").replace(/(\.jpg\?).*/, ".jpg?param=800y800");
const title = ele.find("p.name").text();
const description = ele.find("p.s-fc4").text();
return {
id,
coverImg,
title,
description,
};
})
.toArray();
}
}
if (currentGroup.title) {
groups.push(currentGroup);
}
return groups;
}
const qualityLevels = {
low: "128k",
standard: "320k",
high: "320k",
super: "320k",
};
async function getMediaSource(musicItem, quality) {
const res = (
await axios_1.default.get(`https://lxmusicapi.onrender.com/url/wy/${musicItem.id}/${qualityLevels[quality]}`, {
headers: {
"X-Request-Key": "share-v2"
},
})
).data;
return {
url: res.url,
};
}
const headers = {
authority: "music.163.com",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
"content-type": "application/x-www-form-urlencoded",
accept: "*/*",
origin: "https://music.163.com",
"sec-fetch-site": "same-origin",
"sec-fetch-mode": "cors",
"sec-fetch-dest": "empty",
referer: "https://music.163.com/",
"accept-language": "zh-CN,zh;q=0.9",
};
async function getRecommendSheetTags() {
const data = {
csrf_token: "",
};
const pae = getParamsAndEnc(JSON.stringify(data));
const paeData = qs.stringify(pae);
const res = (await (0, axios_1.default)({
method: "post",
url: "https://music.163.com/weapi/playlist/catalogue",
headers,
data: paeData,
})).data;
const cats = res.categories;
const map = {};
const catData = Object.entries(cats).map((_) => {
const tagData = {
title: _[1],
data: [],
};
map[_[0]] = tagData;
return tagData;
});
const pinned = [];
res.sub.forEach((tag) => {
const _tag = {
id: tag.name,
title: tag.name,
};
if (tag.hot) {
pinned.push(_tag);
}
map[tag.category].data.push(_tag);
});
return {
pinned,
data: catData,
};
}
async function getRecommendSheetsByTag(tag, page) {
const pageSize = 20;
const data = {
cat: tag.id || "全部",
order: "hot",
limit: pageSize,
offset: (page - 1) * pageSize,
total: true,
csrf_token: "",
};
const pae = getParamsAndEnc(JSON.stringify(data));
const paeData = qs.stringify(pae);
const res = (await (0, axios_1.default)({
method: "post",
url: "https://music.163.com/weapi/playlist/list",
headers,
data: paeData,
})).data;
const playLists = res.playlists.map((_) => ({
id: _.id,
artist: _.creator.nickname,
title: _.name,
artwork: _.coverImgUrl,
playCount: _.playCount,
createUserId: _.userId,
createTime: _.createTime,
description: _.description,
}));
return {
isEnd: !(res.more === true),
data: playLists,
};
}
async function getMusicSheetInfo(sheet, page) {
let trackIds = sheet._trackIds;
if (!trackIds) {
const id = sheet.id;
const headers = {
Referer: "https://y.music.163.com/",
Origin: "https://y.music.163.com/",
authority: "music.163.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
};
const sheetDetail = (await axios_1.default.get(`https://music.163.com/api/v3/playlist/detail?id=${id}&n=5000`, {
headers,
})).data;
trackIds = sheetDetail.playlist.trackIds.map((_) => _.id);
}
const pageSize = 40;
const currentPageIds = trackIds.slice((page - 1) * pageSize, page * pageSize);
const res = await getValidMusicItems(currentPageIds);
let extra = {};
if (page <= 1) {
extra = {
_trackIds: trackIds,
};
}
return Object.assign({ isEnd: trackIds.length <= page * pageSize, musicList: res }, extra);
}
module.exports = {
platform: "网易云音乐",
author: 'Huibq',
version: "0.3.0",
appVersion: ">0.1.0-alpha.0",
srcUrl: "https://raw.niuma666bet.buzz/Huibq/keep-alive/master/Music_Free/xiaoyun.js",
cacheControl: "no-store",
hints: {
importMusicSheet: [
"网易云APP点击分享然后复制链接",
"默认歌单无法导入,先新建一个空白歌单复制过去再导入新歌单即可"
],
},
supportedSearchType: ["music", "album", "sheet", "artist", "lyric"],
async search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
if (type === "album") {
return await searchAlbum(query, page);
}
if (type === "artist") {
return await searchArtist(query, page);
}
if (type === "sheet") {
return await searchMusicSheet(query, page);
}
if (type === "lyric") {
return await searchLyric(query, page);
}
},
getMediaSource,
getMusicInfo,
getAlbumInfo,
getLyric,
getArtistWorks,
importMusicSheet,
getTopLists,
getTopListDetail,
getRecommendSheetTags,
getMusicSheetInfo,
getRecommendSheetsByTag,
};