123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691 |
- import axios from "axios";
- import CryptoJs = require("crypto-js");
- import qs = require("qs");
- import bigInt = require("big-integer");
- import dayjs = require("dayjs");
- import cheerio = require("cheerio");
- /** 内部的函数 */
- function a() {
- 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 b(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 c(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 = b(text, "0CoJUm6Qyw8W8jud");
- const rand = a();
- const params = b(first, rand);
- const encSecKey = c(rand);
- return {
- params,
- encSecKey,
- };
- }
- function formatMusicItem(_) {
- const album = _.al || _.album;
- return {
- id: _.id,
- artwork: album?.picUrl,
- title: _.name,
- artist: (_.ar || _.artists)[0].name,
- album: album?.name,
- url: `https://music.163.com/song/media/outer/url?id=${_.id}.mp3`,
- qualities: {
- low: {
- size: (_.l || {})?.size,
- },
- standard: {
- size: (_.m || {})?.size,
- },
- high: {
- size: (_.h || {})?.size,
- },
- super: {
- size: (_.sq || {})?.size,
- },
- },
- copyrightId: _?.copyrightId
- };
- }
- function formatAlbumItem(_) {
- return {
- id: _.id,
- artist: _.artist.name,
- title: _.name,
- artwork: _.picUrl,
- description: "",
- date: dayjs.unix(_.publishTime / 1000).format("YYYY-MM-DD"),
- };
- }
- function musicCanPlayFilter(_) {
- return (_.fee === 0 || _.fee === 8) && (!_.privilege || _.privilege?.st >= 0);
- }
- 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 axios({
- 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
- .filter(musicCanPlayFilter)
- .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((_) => ({
- title: _.name,
- id: _.id,
- coverImg: _.coverImgUrl,
- artist: _.creator?.nickname,
- playCount: _.playCount,
- worksNum: _.trackCount,
- }));
- return {
- isEnd: res.result.playlistCount <= page * pageSize,
- data: playlists,
- };
- }
- async function searchLyric(query, page) {
- const res = await searchBase(query, page, 1006);
- const lyrics =
- res.result.songs?.map((it) => ({
- title: it.name,
- artist: it.ar?.map((_) => _.name).join(", "),
- id: it.id,
- artwork: it.al?.picUrl,
- album: it.al?.name,
- rawLrcTxt: it.lyrics?.join("\n"),
- })) ?? [];
- 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 axios({
- method: "post",
- url: `https://music.163.com/weapi/v1/artist/${artistItem.id}?csrf_token=`,
- headers,
- data: paeData,
- })
- ).data;
- return {
- isEnd: true,
- data: res.hotSongs.filter(musicCanPlayFilter).map(formatMusicItem),
- };
- } else if (type === "album") {
- const res = (
- await axios({
- 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 {
- ...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 axios({
- method: "post",
- url: `https://interface.music.163.com/weapi/song/lyric?csrf_token=`,
- headers,
- data: paeData,
- })
- ).data;
- return {
- rawLrc: result.lrc.lyric,
- };
- }
- 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 axios({
- 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 || [])
- .filter(musicCanPlayFilter)
- .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 data = {
- csrf_token: "",
- ids: `[${trackIds.join(",")}]`,
- level: "standard",
- encodeType: "flac",
- };
- const pae = getParamsAndEnc(JSON.stringify(data));
- const urlencoded = qs.stringify(pae);
- const res = (
- await axios({
- method: "post",
- url: `https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token=`,
- headers,
- data: urlencoded,
- })
- ).data;
- const validTrackIds = res.data.filter((_) => _.url).map((_) => _.id);
- const songDetails = (
- await axios.get(
- `https://music.163.com/api/song/detail/?id=${
- validTrackIds[0]
- }&ids=[${validTrackIds.join(",")}]`,
- { headers }
- )
- ).data;
- const validMusicItems = songDetails.songs
- .filter((_) => _.fee === 0 || _.fee === 8)
- .map(formatMusicItem);
- return validMusicItems;
- } catch (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.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.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: Record<string, any> = {};
- 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");
- 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: Record<IMusic.IQualityKey, string> = {
- low: "",
- standard: "standard",
- high: "exhigh",
- super: "lossless",
- };
- /** 获取音乐源 */
- async function getMediaSource(
- musicItem: IMusic.IMusicItem,
- quality: IMusic.IQualityKey
- ) {
- if (quality !== "standard") {
- return;
- }
- return {
- url: `https://music.163.com/song/media/outer/url?id=${musicItem.id}.mp3`,
- };
- }
- 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",
- };
- /** 推荐歌单tag */
- async function getRecommendSheetTags() {
- const data = {
- csrf_token: "",
- };
- const pae = getParamsAndEnc(JSON.stringify(data));
- const paeData = qs.stringify(pae);
- const res = (
- await axios({
- 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: number) {
- const pageSize = 20;
- const data = {
- cat: tag.id || "全部",
- order: "hot", // hot,new
- limit: pageSize,
- offset: (page - 1) * pageSize,
- total: true,
- csrf_token: "",
- };
- const pae = getParamsAndEnc(JSON.stringify(data));
- const paeData = qs.stringify(pae);
- const res = (
- await axios({
- 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: IMusicSheet.IMusicSheetItem, 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.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 {
- isEnd: trackIds.length <= page * pageSize,
- musicList: res,
- ...extra,
- };
- }
- module.exports = {
- platform: "网易云",
- version: "0.2.1",
- appVersion: ">0.1.0-alpha.0",
- srcUrl:
- "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/netease/index.js",
- cacheControl: "no-store",
- hints: {
- importMusicSheet: [
- "网易云移动端:APP点击分享,然后复制链接",
- "网易云H5/PC端:复制URL,或者直接输入歌单ID即可",
- "默认歌单无法导入,先新建一个空白歌单复制过去再导入新歌单即可",
- "导入过程中会过滤掉所有VIP/试听/收费音乐,导入时间和歌单大小有关,请耐心等待",
- ],
- },
- 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,
- getAlbumInfo,
- getLyric,
- getArtistWorks,
- importMusicSheet,
- getTopLists,
- getTopListDetail,
- getRecommendSheetTags,
- getMusicSheetInfo,
- getRecommendSheetsByTag,
- };
- // async function getValidMusicItemsBak(trackIds: Array<number|string>) {
- // let idsData = {
- // c:
- // '[' +
- // trackIds
- // .slice(0, 5)
- // .map((item) => '{"id":' + item + '}')
- // .join(',') +
- // ']',
- // }
- // const pae = getParamsAndEnc(JSON.stringify(idsData));
- // const paeData = qs.stringify(pae);
- // const res = (
- // await axios({
- // method: "post",
- // url: "https://music.163.com/weapi/v3/song/detail",
- // headers,
- // data: paeData,
- // })
- // ).data;
- // return res.songs.filter(musicCanPlayFilter)
- // }
- // g();
|