This commit is contained in:
猫头猫
2024-10-03 22:31:57 +08:00
parent a89553f90f
commit 3779c06d8b
20 changed files with 2558 additions and 2412 deletions

View File

@@ -1 +1 @@
{"desc":"此链接为 MusicFree 插件,插件开发及使用方式参考 https://musicfree.upup.fun","plugins":[{"name":"bilibili","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/bilibili/index.js","version":"0.1.15"},{"name":"Audiomack","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/audiomack/index.js","version":"0.0.2"},{"name":"歌词千寻","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/geciqianxun/index.js","version":"0.0.0"},{"name":"歌词网","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/geciwang/index.js","version":"0.0.0"},{"name":"快手","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/kuaishou/index.js","version":"0.0.1"},{"name":"Navidrome","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/navidrome/index.js","version":"0.0.0"},{"name":"猫耳FM","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/maoerfm/index.js","version":"0.1.4"},{"name":"suno","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/suno/index.js","version":"0.0.0"},{"name":"udio","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/udio/index.js","version":"0.0.0"},{"name":"音悦台","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/yinyuetai/index.js","version":"0.0.1"},{"name":"WebDAV","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/webdav/index.js","version":"0.0.2"},{"name":"Youtube","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/youtube/index.js","version":"0.0.1"}]}
{"desc":"此链接为 MusicFree 插件,插件开发及使用方式参考 https://musicfree.upup.fun","plugins":[{"name":"Audiomack","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/audiomack/index.js","version":"0.0.2"},{"name":"歌词千寻","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/geciqianxun/index.js","version":"0.0.0"},{"name":"bilibili","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/bilibili/index.js","version":"0.2.0"},{"name":"歌词网","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/geciwang/index.js","version":"0.0.0"},{"name":"suno","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/suno/index.js","version":"0.0.0"},{"name":"猫耳FM","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/maoerfm/index.js","version":"0.1.4"},{"name":"快手","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/kuaishou/index.js","version":"0.0.1"},{"name":"udio","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/udio/index.js","version":"0.0.0"},{"name":"Navidrome","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/navidrome/index.js","version":"0.0.0"},{"name":"WebDAV","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/webdav/index.js","version":"0.0.2"},{"name":"Youtube","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/youtube/index.js","version":"0.0.1"},{"name":"音悦台","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/yinyuetai/index.js","version":"0.0.1"}]}

View File

@@ -1,476 +1,476 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const cheerio_1 = require("cheerio");
const CryptoJS = require("crypto-js");
const dayjs = require("dayjs");
const pageSize = 20;
const headers = {
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
};
function nonce(e = 10) {
let n = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", r = "";
for (let i = 0; i < e; i++)
r += n.charAt(Math.floor(Math.random() * n.length));
return r;
}
function getNormalizedParams(parameters) {
const sortedKeys = [];
const normalizedParameters = [];
for (let e in parameters) {
sortedKeys.push(_encode(e));
}
sortedKeys.sort();
for (let idx = 0; idx < sortedKeys.length; idx++) {
const e = sortedKeys[idx];
var n, r, i = _decode(e), a = parameters[i];
for (a.sort(), n = 0; n < a.length; n++)
(r = _encode(a[n])), normalizedParameters.push(e + "=" + r);
}
return normalizedParameters.join("&");
}
function _encode(e) {
return e
? encodeURIComponent(e)
.replace(/[!'()]/g, escape)
.replace(/\*/g, "%2A")
: "";
}
function _decode(e) {
return e ? decodeURIComponent(e) : "";
}
function u(e) {
(this._parameters = {}), this._loadParameters(e || {});
}
u.prototype = {
_loadParameters: function (e) {
e instanceof Array
? this._loadParametersFromArray(e)
: "object" == typeof e && this._loadParametersFromObject(e);
},
_loadParametersFromArray: function (e) {
var n;
for (n = 0; n < e.length; n++)
this._loadParametersFromObject(e[n]);
},
_loadParametersFromObject: function (e) {
var n;
for (n in e)
if (e.hasOwnProperty(n)) {
var r = this._getStringFromParameter(e[n]);
this._loadParameterValue(n, r);
}
},
_loadParameterValue: function (e, n) {
var r;
if (n instanceof Array) {
for (r = 0; r < n.length; r++) {
var i = this._getStringFromParameter(n[r]);
this._addParameter(e, i);
}
0 == n.length && this._addParameter(e, "");
}
else
this._addParameter(e, n);
},
_getStringFromParameter: function (e) {
var n = e || "";
try {
("number" == typeof e || "boolean" == typeof e) && (n = e.toString());
}
catch (e) { }
return n;
},
_addParameter: function (e, n) {
this._parameters[e] || (this._parameters[e] = []),
this._parameters[e].push(n);
},
get: function () {
return this._parameters;
},
};
function getSignature(method, urlPath, params, secret = "f3ac5b086f3eab260520d8e3049561e6") {
urlPath = urlPath.split("?")[0];
urlPath = urlPath.startsWith("http")
? urlPath
: "https://api.audiomack.com/v1" + urlPath;
const r = new u(params).get();
const httpMethod = method.toUpperCase();
const normdParams = getNormalizedParams(r);
const l = _encode(httpMethod) + "&" + _encode(urlPath) + "&" + _encode(normdParams);
const hash = CryptoJS.HmacSHA1(l, secret + "&").toString(CryptoJS.enc.Base64);
return hash;
}
function formatMusicItem(raw) {
return {
id: raw.id,
artwork: raw.image || raw.image_base,
duration: +raw.duration,
title: raw.title,
artist: raw.artist,
album: raw.album,
url_slug: raw.url_slug,
};
}
function formatAlbumItem(raw) {
var _a, _b;
return {
artist: raw.artist,
artwork: raw.image || raw.image_base,
id: raw.id,
date: dayjs.unix(+raw.released).format("YYYY-MM-DD"),
title: raw.title,
_musicList: (_b = (_a = raw === null || raw === void 0 ? void 0 : raw.tracks) === null || _a === void 0 ? void 0 : _a.map) === null || _b === void 0 ? void 0 : _b.call(_a, (it) => ({
id: it.song_id || it.id,
artwork: raw.image || raw.image_base,
duration: +it.duration,
title: it.title,
artist: it.artist,
album: raw.title,
})),
};
}
function formatMusicSheetItem(raw) {
var _a, _b, _c, _d, _e, _f;
return {
worksNum: raw.track_count,
id: raw.id,
title: raw.title,
artist: (_a = raw.artist) === null || _a === void 0 ? void 0 : _a.name,
artwork: raw.image || raw.image_base,
artistItem: {
id: (_b = raw.artist) === null || _b === void 0 ? void 0 : _b.id,
avatar: ((_c = raw.artist) === null || _c === void 0 ? void 0 : _c.image) || ((_d = raw.artist) === null || _d === void 0 ? void 0 : _d.image_base),
name: (_e = raw.artist) === null || _e === void 0 ? void 0 : _e.name,
url_slug: (_f = raw.artist) === null || _f === void 0 ? void 0 : _f.url_slug,
},
createAt: dayjs.unix(+raw.created).format("YYYY-MM-DD"),
url_slug: raw.url_slug,
};
}
async function searchBase(query, page, show) {
const params = {
limit: pageSize,
oauth_consumer_key: "audiomack-js",
oauth_nonce: nonce(32),
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: Math.round(Date.now() / 1e3),
oauth_version: "1.0",
page: page,
q: query,
show: show,
sort: "popular",
};
const oauth_signature = getSignature("GET", "/search", params);
const results = (await axios_1.default.get("https://api.audiomack.com/v1/search", {
headers,
params: Object.assign(Object.assign({}, params), { oauth_signature }),
})).data.results;
return results;
}
async function searchMusic(query, page) {
const results = await searchBase(query, page, "songs");
return {
isEnd: results.length < pageSize,
data: results.map(formatMusicItem),
};
}
async function searchAlbum(query, page) {
const results = await searchBase(query, page, "albums");
return {
isEnd: results.length < pageSize,
data: results.map(formatAlbumItem),
};
}
async function searchMusicSheet(query, page) {
const results = await searchBase(query, page, "playlists");
return {
isEnd: results.length < pageSize,
data: results.map(formatMusicSheetItem),
};
}
async function searchArtist(query, page) {
const results = await searchBase(query, page, "artists");
return {
isEnd: results.length < pageSize,
data: results.map((raw) => ({
name: raw.name,
id: raw.id,
avatar: raw.image || raw.image_base,
url_slug: raw.url_slug,
})),
};
}
let dataUrlBase;
async function getDataUrlBase() {
if (dataUrlBase) {
return dataUrlBase;
}
const rawHtml = (await axios_1.default.get("https://audiomack.com/")).data;
const $ = (0, cheerio_1.load)(rawHtml);
const script = $("script#__NEXT_DATA__").text();
const jsonObj = JSON.parse(script);
if (jsonObj.buildId) {
dataUrlBase = `https://audiomack.com/_next/data/${jsonObj.buildId}`;
}
return dataUrlBase;
}
async function getArtistWorks(artistItem, page, type) {
if (type === "music") {
const params = {
artist_id: artistItem.id,
limit: pageSize,
oauth_consumer_key: "audiomack-js",
oauth_nonce: nonce(32),
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: Math.round(Date.now() / 1e3),
oauth_version: "1.0",
page: page,
sort: "rank",
type: "songs",
};
const oauth_signature = getSignature("GET", "/search_artist_content", params);
const results = (await axios_1.default.get("https://api.audiomack.com/v1/search_artist_content", {
headers,
params: Object.assign(Object.assign({}, params), { oauth_signature }),
})).data.results;
return {
isEnd: results.length < pageSize,
data: results.map(formatMusicItem),
};
}
else if (type === "album") {
const params = {
artist_id: artistItem.id,
limit: pageSize,
oauth_consumer_key: "audiomack-js",
oauth_nonce: nonce(32),
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: Math.round(Date.now() / 1e3),
oauth_version: "1.0",
page: page,
sort: "rank",
type: "albums",
};
const oauth_signature = getSignature("GET", "/search_artist_content", params);
const results = (await axios_1.default.get("https://api.audiomack.com/v1/search_artist_content", {
headers,
params: Object.assign(Object.assign({}, params), { oauth_signature }),
})).data.results;
return {
isEnd: results.length < pageSize,
data: results.map(formatAlbumItem),
};
}
}
async function getMusicSheetInfo(sheet, page) {
const _dataUrlBase = await getDataUrlBase();
const res = (await axios_1.default.get(`${_dataUrlBase}/${sheet.artistItem.url_slug}/playlist/${sheet.url_slug}.json`, {
params: {
page_slug: sheet.artistItem.url_slug,
playlist_slug: sheet.url_slug,
},
headers: Object.assign({}, headers),
})).data;
const musicPage = res.pageProps.initialState.musicPage;
const targetKey = Object.keys(musicPage).find((it) => it.startsWith("musicMusicPage"));
const tracks = musicPage[targetKey].results.tracks;
return {
isEnd: true,
musicList: tracks.map(formatMusicItem),
};
}
async function getMediaSource(musicItem, quality) {
if (quality !== "standard") {
return;
}
const params = {
environment: "desktop-web",
hq: true,
oauth_consumer_key: "audiomack-js",
oauth_nonce: nonce(32),
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: Math.round(Date.now() / 1e3),
oauth_version: "1.0",
section: "/search",
};
const oauth_signature = getSignature("GET", `/music/play/${musicItem.id}`, params);
const res = (await axios_1.default.get(`https://api.audiomack.com/v1/music/play/${musicItem.id}`, {
headers: Object.assign(Object.assign({}, headers), { origin: "https://audiomack.com" }),
params: Object.assign(Object.assign({}, params), { oauth_signature }),
})).data;
return {
url: res.signedUrl,
};
}
async function getAlbumInfo(albumItem) {
return {
musicList: albumItem._musicList.map((it) => (Object.assign({}, it))),
};
}
async function getRecommendSheetTags() {
const rawHtml = (await axios_1.default.get("https://audiomack.com/playlists")).data;
const $ = (0, cheerio_1.load)(rawHtml);
const script = $("script#__NEXT_DATA__").text();
const jsonObj = JSON.parse(script);
return {
data: [
{
data: jsonObj.props.pageProps.categories,
},
],
};
}
async function getRecommendSheetsByTag(tag, page) {
if (!tag.id) {
tag = { id: "34", title: "What's New", url_slug: "whats-new" };
}
const params = {
featured: "yes",
limit: pageSize,
oauth_consumer_key: "audiomack-js",
oauth_nonce: nonce(32),
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: Math.round(Date.now() / 1e3),
oauth_version: "1.0",
page: page,
slug: tag.url_slug,
};
const oauth_signature = getSignature("GET", "/playlist/categories", params);
const results = (await axios_1.default.get("https://api.audiomack.com/v1/playlist/categories", {
headers,
params: Object.assign(Object.assign({}, params), { oauth_signature }),
})).data.results.playlists;
return {
isEnd: results.length < pageSize,
data: results.map(formatMusicSheetItem),
};
}
async function getTopLists() {
const genres = [
{
title: "All Genres",
url_slug: null,
},
{
title: "Afrosounds",
url_slug: "afrobeats",
},
{
title: "Hip-Hop/Rap",
url_slug: "rap",
},
{
title: "Latin",
url_slug: "latin",
},
{
title: "Caribbean",
url_slug: "caribbean",
},
{
title: "Pop",
url_slug: "pop",
},
{
title: "R&B",
url_slug: "rb",
},
{
title: "Gospel",
url_slug: "gospel",
},
{
title: "Electronic",
url_slug: "electronic",
},
{
title: "Rock",
url_slug: "rock",
},
{
title: "Punjabi",
url_slug: "punjabi",
},
{
title: "Country",
url_slug: "country",
},
{
title: "Instrumental",
url_slug: "instrumental",
},
{
title: "Podcast",
url_slug: "podcast",
},
];
return [
{
title: "Trending Songs",
data: genres.map((it) => {
var _a;
return (Object.assign(Object.assign({}, it), { type: "trending", id: (_a = it.url_slug) !== null && _a !== void 0 ? _a : it.title }));
}),
},
{
title: "Recently Added Music",
data: genres.map((it) => {
var _a;
return (Object.assign(Object.assign({}, it), { type: "recent", id: (_a = it.url_slug) !== null && _a !== void 0 ? _a : it.title }));
}),
},
];
}
async function getTopListDetail(topListItem, page = 1) {
const type = topListItem.type;
const partialUrl = `/music/${topListItem.url_slug ? `${topListItem.url_slug}/` : ""}${type}/page/${page}`;
const url = `https://api.audiomack.com/v1${partialUrl}`;
const params = {
oauth_consumer_key: "audiomack-js",
oauth_nonce: nonce(32),
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: Math.round(Date.now() / 1e3),
oauth_version: "1.0",
type: "song",
};
const oauth_signature = getSignature("GET", partialUrl, params);
const results = (await axios_1.default.get(url, {
headers,
params: Object.assign(Object.assign({}, params), { oauth_signature }),
})).data.results;
return {
musicList: results.map(formatMusicItem),
};
}
module.exports = {
platform: "Audiomack",
version: "0.0.2",
author: '猫头猫',
primaryKey: ["id", "url_slug"],
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/audiomack/index.js",
cacheControl: "no-cache",
supportedSearchType: ['music', 'album', 'sheet', 'artist'],
async search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
else if (type === "album") {
return await searchAlbum(query, page);
}
else if (type === "sheet") {
return await searchMusicSheet(query, page);
}
else if (type === "artist") {
return await searchArtist(query, page);
}
},
getMediaSource,
getAlbumInfo,
getMusicSheetInfo,
getArtistWorks,
getRecommendSheetTags,
getRecommendSheetsByTag,
getTopLists,
getTopListDetail,
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const cheerio_1 = require("cheerio");
const CryptoJS = require("crypto-js");
const dayjs = require("dayjs");
const pageSize = 20;
const headers = {
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
};
function nonce(e = 10) {
let n = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", r = "";
for (let i = 0; i < e; i++)
r += n.charAt(Math.floor(Math.random() * n.length));
return r;
}
function getNormalizedParams(parameters) {
const sortedKeys = [];
const normalizedParameters = [];
for (let e in parameters) {
sortedKeys.push(_encode(e));
}
sortedKeys.sort();
for (let idx = 0; idx < sortedKeys.length; idx++) {
const e = sortedKeys[idx];
var n, r, i = _decode(e), a = parameters[i];
for (a.sort(), n = 0; n < a.length; n++)
(r = _encode(a[n])), normalizedParameters.push(e + "=" + r);
}
return normalizedParameters.join("&");
}
function _encode(e) {
return e
? encodeURIComponent(e)
.replace(/[!'()]/g, escape)
.replace(/\*/g, "%2A")
: "";
}
function _decode(e) {
return e ? decodeURIComponent(e) : "";
}
function u(e) {
(this._parameters = {}), this._loadParameters(e || {});
}
u.prototype = {
_loadParameters: function (e) {
e instanceof Array
? this._loadParametersFromArray(e)
: "object" == typeof e && this._loadParametersFromObject(e);
},
_loadParametersFromArray: function (e) {
var n;
for (n = 0; n < e.length; n++)
this._loadParametersFromObject(e[n]);
},
_loadParametersFromObject: function (e) {
var n;
for (n in e)
if (e.hasOwnProperty(n)) {
var r = this._getStringFromParameter(e[n]);
this._loadParameterValue(n, r);
}
},
_loadParameterValue: function (e, n) {
var r;
if (n instanceof Array) {
for (r = 0; r < n.length; r++) {
var i = this._getStringFromParameter(n[r]);
this._addParameter(e, i);
}
0 == n.length && this._addParameter(e, "");
}
else
this._addParameter(e, n);
},
_getStringFromParameter: function (e) {
var n = e || "";
try {
("number" == typeof e || "boolean" == typeof e) && (n = e.toString());
}
catch (e) { }
return n;
},
_addParameter: function (e, n) {
this._parameters[e] || (this._parameters[e] = []),
this._parameters[e].push(n);
},
get: function () {
return this._parameters;
},
};
function getSignature(method, urlPath, params, secret = "f3ac5b086f3eab260520d8e3049561e6") {
urlPath = urlPath.split("?")[0];
urlPath = urlPath.startsWith("http")
? urlPath
: "https://api.audiomack.com/v1" + urlPath;
const r = new u(params).get();
const httpMethod = method.toUpperCase();
const normdParams = getNormalizedParams(r);
const l = _encode(httpMethod) + "&" + _encode(urlPath) + "&" + _encode(normdParams);
const hash = CryptoJS.HmacSHA1(l, secret + "&").toString(CryptoJS.enc.Base64);
return hash;
}
function formatMusicItem(raw) {
return {
id: raw.id,
artwork: raw.image || raw.image_base,
duration: +raw.duration,
title: raw.title,
artist: raw.artist,
album: raw.album,
url_slug: raw.url_slug,
};
}
function formatAlbumItem(raw) {
var _a, _b;
return {
artist: raw.artist,
artwork: raw.image || raw.image_base,
id: raw.id,
date: dayjs.unix(+raw.released).format("YYYY-MM-DD"),
title: raw.title,
_musicList: (_b = (_a = raw === null || raw === void 0 ? void 0 : raw.tracks) === null || _a === void 0 ? void 0 : _a.map) === null || _b === void 0 ? void 0 : _b.call(_a, (it) => ({
id: it.song_id || it.id,
artwork: raw.image || raw.image_base,
duration: +it.duration,
title: it.title,
artist: it.artist,
album: raw.title,
})),
};
}
function formatMusicSheetItem(raw) {
var _a, _b, _c, _d, _e, _f;
return {
worksNum: raw.track_count,
id: raw.id,
title: raw.title,
artist: (_a = raw.artist) === null || _a === void 0 ? void 0 : _a.name,
artwork: raw.image || raw.image_base,
artistItem: {
id: (_b = raw.artist) === null || _b === void 0 ? void 0 : _b.id,
avatar: ((_c = raw.artist) === null || _c === void 0 ? void 0 : _c.image) || ((_d = raw.artist) === null || _d === void 0 ? void 0 : _d.image_base),
name: (_e = raw.artist) === null || _e === void 0 ? void 0 : _e.name,
url_slug: (_f = raw.artist) === null || _f === void 0 ? void 0 : _f.url_slug,
},
createAt: dayjs.unix(+raw.created).format("YYYY-MM-DD"),
url_slug: raw.url_slug,
};
}
async function searchBase(query, page, show) {
const params = {
limit: pageSize,
oauth_consumer_key: "audiomack-js",
oauth_nonce: nonce(32),
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: Math.round(Date.now() / 1e3),
oauth_version: "1.0",
page: page,
q: query,
show: show,
sort: "popular",
};
const oauth_signature = getSignature("GET", "/search", params);
const results = (await axios_1.default.get("https://api.audiomack.com/v1/search", {
headers,
params: Object.assign(Object.assign({}, params), { oauth_signature }),
})).data.results;
return results;
}
async function searchMusic(query, page) {
const results = await searchBase(query, page, "songs");
return {
isEnd: results.length < pageSize,
data: results.map(formatMusicItem),
};
}
async function searchAlbum(query, page) {
const results = await searchBase(query, page, "albums");
return {
isEnd: results.length < pageSize,
data: results.map(formatAlbumItem),
};
}
async function searchMusicSheet(query, page) {
const results = await searchBase(query, page, "playlists");
return {
isEnd: results.length < pageSize,
data: results.map(formatMusicSheetItem),
};
}
async function searchArtist(query, page) {
const results = await searchBase(query, page, "artists");
return {
isEnd: results.length < pageSize,
data: results.map((raw) => ({
name: raw.name,
id: raw.id,
avatar: raw.image || raw.image_base,
url_slug: raw.url_slug,
})),
};
}
let dataUrlBase;
async function getDataUrlBase() {
if (dataUrlBase) {
return dataUrlBase;
}
const rawHtml = (await axios_1.default.get("https://audiomack.com/")).data;
const $ = (0, cheerio_1.load)(rawHtml);
const script = $("script#__NEXT_DATA__").text();
const jsonObj = JSON.parse(script);
if (jsonObj.buildId) {
dataUrlBase = `https://audiomack.com/_next/data/${jsonObj.buildId}`;
}
return dataUrlBase;
}
async function getArtistWorks(artistItem, page, type) {
if (type === "music") {
const params = {
artist_id: artistItem.id,
limit: pageSize,
oauth_consumer_key: "audiomack-js",
oauth_nonce: nonce(32),
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: Math.round(Date.now() / 1e3),
oauth_version: "1.0",
page: page,
sort: "rank",
type: "songs",
};
const oauth_signature = getSignature("GET", "/search_artist_content", params);
const results = (await axios_1.default.get("https://api.audiomack.com/v1/search_artist_content", {
headers,
params: Object.assign(Object.assign({}, params), { oauth_signature }),
})).data.results;
return {
isEnd: results.length < pageSize,
data: results.map(formatMusicItem),
};
}
else if (type === "album") {
const params = {
artist_id: artistItem.id,
limit: pageSize,
oauth_consumer_key: "audiomack-js",
oauth_nonce: nonce(32),
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: Math.round(Date.now() / 1e3),
oauth_version: "1.0",
page: page,
sort: "rank",
type: "albums",
};
const oauth_signature = getSignature("GET", "/search_artist_content", params);
const results = (await axios_1.default.get("https://api.audiomack.com/v1/search_artist_content", {
headers,
params: Object.assign(Object.assign({}, params), { oauth_signature }),
})).data.results;
return {
isEnd: results.length < pageSize,
data: results.map(formatAlbumItem),
};
}
}
async function getMusicSheetInfo(sheet, page) {
const _dataUrlBase = await getDataUrlBase();
const res = (await axios_1.default.get(`${_dataUrlBase}/${sheet.artistItem.url_slug}/playlist/${sheet.url_slug}.json`, {
params: {
page_slug: sheet.artistItem.url_slug,
playlist_slug: sheet.url_slug,
},
headers: Object.assign({}, headers),
})).data;
const musicPage = res.pageProps.initialState.musicPage;
const targetKey = Object.keys(musicPage).find((it) => it.startsWith("musicMusicPage"));
const tracks = musicPage[targetKey].results.tracks;
return {
isEnd: true,
musicList: tracks.map(formatMusicItem),
};
}
async function getMediaSource(musicItem, quality) {
if (quality !== "standard") {
return;
}
const params = {
environment: "desktop-web",
hq: true,
oauth_consumer_key: "audiomack-js",
oauth_nonce: nonce(32),
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: Math.round(Date.now() / 1e3),
oauth_version: "1.0",
section: "/search",
};
const oauth_signature = getSignature("GET", `/music/play/${musicItem.id}`, params);
const res = (await axios_1.default.get(`https://api.audiomack.com/v1/music/play/${musicItem.id}`, {
headers: Object.assign(Object.assign({}, headers), { origin: "https://audiomack.com" }),
params: Object.assign(Object.assign({}, params), { oauth_signature }),
})).data;
return {
url: res.signedUrl,
};
}
async function getAlbumInfo(albumItem) {
return {
musicList: albumItem._musicList.map((it) => (Object.assign({}, it))),
};
}
async function getRecommendSheetTags() {
const rawHtml = (await axios_1.default.get("https://audiomack.com/playlists")).data;
const $ = (0, cheerio_1.load)(rawHtml);
const script = $("script#__NEXT_DATA__").text();
const jsonObj = JSON.parse(script);
return {
data: [
{
data: jsonObj.props.pageProps.categories,
},
],
};
}
async function getRecommendSheetsByTag(tag, page) {
if (!tag.id) {
tag = { id: "34", title: "What's New", url_slug: "whats-new" };
}
const params = {
featured: "yes",
limit: pageSize,
oauth_consumer_key: "audiomack-js",
oauth_nonce: nonce(32),
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: Math.round(Date.now() / 1e3),
oauth_version: "1.0",
page: page,
slug: tag.url_slug,
};
const oauth_signature = getSignature("GET", "/playlist/categories", params);
const results = (await axios_1.default.get("https://api.audiomack.com/v1/playlist/categories", {
headers,
params: Object.assign(Object.assign({}, params), { oauth_signature }),
})).data.results.playlists;
return {
isEnd: results.length < pageSize,
data: results.map(formatMusicSheetItem),
};
}
async function getTopLists() {
const genres = [
{
title: "All Genres",
url_slug: null,
},
{
title: "Afrosounds",
url_slug: "afrobeats",
},
{
title: "Hip-Hop/Rap",
url_slug: "rap",
},
{
title: "Latin",
url_slug: "latin",
},
{
title: "Caribbean",
url_slug: "caribbean",
},
{
title: "Pop",
url_slug: "pop",
},
{
title: "R&B",
url_slug: "rb",
},
{
title: "Gospel",
url_slug: "gospel",
},
{
title: "Electronic",
url_slug: "electronic",
},
{
title: "Rock",
url_slug: "rock",
},
{
title: "Punjabi",
url_slug: "punjabi",
},
{
title: "Country",
url_slug: "country",
},
{
title: "Instrumental",
url_slug: "instrumental",
},
{
title: "Podcast",
url_slug: "podcast",
},
];
return [
{
title: "Trending Songs",
data: genres.map((it) => {
var _a;
return (Object.assign(Object.assign({}, it), { type: "trending", id: (_a = it.url_slug) !== null && _a !== void 0 ? _a : it.title }));
}),
},
{
title: "Recently Added Music",
data: genres.map((it) => {
var _a;
return (Object.assign(Object.assign({}, it), { type: "recent", id: (_a = it.url_slug) !== null && _a !== void 0 ? _a : it.title }));
}),
},
];
}
async function getTopListDetail(topListItem, page = 1) {
const type = topListItem.type;
const partialUrl = `/music/${topListItem.url_slug ? `${topListItem.url_slug}/` : ""}${type}/page/${page}`;
const url = `https://api.audiomack.com/v1${partialUrl}`;
const params = {
oauth_consumer_key: "audiomack-js",
oauth_nonce: nonce(32),
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: Math.round(Date.now() / 1e3),
oauth_version: "1.0",
type: "song",
};
const oauth_signature = getSignature("GET", partialUrl, params);
const results = (await axios_1.default.get(url, {
headers,
params: Object.assign(Object.assign({}, params), { oauth_signature }),
})).data.results;
return {
musicList: results.map(formatMusicItem),
};
}
module.exports = {
platform: "Audiomack",
version: "0.0.2",
author: '猫头猫',
primaryKey: ["id", "url_slug"],
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/audiomack/index.js",
cacheControl: "no-cache",
supportedSearchType: ['music', 'album', 'sheet', 'artist'],
async search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
else if (type === "album") {
return await searchAlbum(query, page);
}
else if (type === "sheet") {
return await searchMusicSheet(query, page);
}
else if (type === "artist") {
return await searchArtist(query, page);
}
},
getMediaSource,
getAlbumInfo,
getMusicSheetInfo,
getArtistWorks,
getRecommendSheetTags,
getRecommendSheetsByTag,
getTopLists,
getTopListDetail,
};

1000
dist/bilibili/index.js vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,49 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const cheerio_1 = require("cheerio");
async function search(query, page, type) {
if (type !== 'lyric') {
return;
}
const result = (await axios_1.default.get('https://so.lrcgc.com/', {
params: {
q: query,
}
})).data;
const $ = (0, cheerio_1.load)(result);
const results = $('.resultWrap').children();
const data = [];
if (results.first().prop('tagName') === 'DL') {
const title = results.first().find('dt > a');
const desc = results.first().find('dd > small');
const descText = desc.text().replace(/[\s|\n]/g, '').split(/[歌手:|专辑:]/).filter(it => it.trim() !== '');
data.push({
title: title.text(),
id: title.attr('href'),
artist: descText === null || descText === void 0 ? void 0 : descText[0],
album: descText === null || descText === void 0 ? void 0 : descText[1]
});
}
return {
isEnd: true,
data
};
}
async function getLyric(musicItem) {
const res = (await axios_1.default.get(musicItem.id)).data;
const $ = (0, cheerio_1.load)(res);
const rawLrc = $('p#J_lyric').text().replace(/\n/g, '');
return {
rawLrc: rawLrc,
};
}
module.exports = {
platform: "歌词千寻",
version: "0.0.0",
srcUrl: 'https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/geciqianxun/index.js',
cacheControl: "no-store",
supportedSearchType: ['lyric'],
search,
getLyric
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const cheerio_1 = require("cheerio");
async function search(query, page, type) {
if (type !== 'lyric') {
return;
}
const result = (await axios_1.default.get('https://so.lrcgc.com/', {
params: {
q: query,
}
})).data;
const $ = (0, cheerio_1.load)(result);
const results = $('.resultWrap').children();
const data = [];
if (results.first().prop('tagName') === 'DL') {
const title = results.first().find('dt > a');
const desc = results.first().find('dd > small');
const descText = desc.text().replace(/[\s|\n]/g, '').split(/[歌手:|专辑:]/).filter(it => it.trim() !== '');
data.push({
title: title.text(),
id: title.attr('href'),
artist: descText === null || descText === void 0 ? void 0 : descText[0],
album: descText === null || descText === void 0 ? void 0 : descText[1]
});
}
return {
isEnd: true,
data
};
}
async function getLyric(musicItem) {
const res = (await axios_1.default.get(musicItem.id)).data;
const $ = (0, cheerio_1.load)(res);
const rawLrc = $('p#J_lyric').text().replace(/\n/g, '');
return {
rawLrc: rawLrc,
};
}
module.exports = {
platform: "歌词千寻",
version: "0.0.0",
srcUrl: 'https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/geciqianxun/index.js',
cacheControl: "no-store",
supportedSearchType: ['lyric'],
search,
getLyric
};

104
dist/geciwang/index.js vendored
View File

@@ -1,52 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const cheerio_1 = require("cheerio");
async function search(query, page, type) {
if (type !== 'lyric') {
return;
}
const result = (await axios_1.default.get('https://zh.followlyrics.com/search', {
params: {
name: query,
type: 'song'
}
})).data;
const $ = (0, cheerio_1.load)(result);
const results = $('.table.table-striped > tbody');
const items = results.children('tr');
const data = items.map((index, el) => {
const tds = $(el).children();
const title = $(tds.get(0)).text().trim();
const artist = $(tds.get(1)).text().trim();
const album = $(tds.get(2)).text().trim();
const id = $(tds.get(3)).children('a').attr('href');
return {
title,
artist,
album,
id
};
}).toArray();
return {
isEnd: true,
data
};
}
async function getLyric(musicItem) {
const res = (await axios_1.default.get(musicItem.id)).data;
const $ = (0, cheerio_1.load)(res);
const rawLrc = $('div#lyrics').text().replace(/\n/g, '');
return {
rawLrc: rawLrc,
};
}
module.exports = {
platform: "歌词网",
version: "0.0.0",
srcUrl: 'https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/geciwang/index.js',
cacheControl: "no-store",
supportedSearchType: ['lyric'],
search,
getLyric
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const cheerio_1 = require("cheerio");
async function search(query, page, type) {
if (type !== 'lyric') {
return;
}
const result = (await axios_1.default.get('https://zh.followlyrics.com/search', {
params: {
name: query,
type: 'song'
}
})).data;
const $ = (0, cheerio_1.load)(result);
const results = $('.table.table-striped > tbody');
const items = results.children('tr');
const data = items.map((index, el) => {
const tds = $(el).children();
const title = $(tds.get(0)).text().trim();
const artist = $(tds.get(1)).text().trim();
const album = $(tds.get(2)).text().trim();
const id = $(tds.get(3)).children('a').attr('href');
return {
title,
artist,
album,
id
};
}).toArray();
return {
isEnd: true,
data
};
}
async function getLyric(musicItem) {
const res = (await axios_1.default.get(musicItem.id)).data;
const $ = (0, cheerio_1.load)(res);
const rawLrc = $('div#lyrics').text().replace(/\n/g, '');
return {
rawLrc: rawLrc,
};
}
module.exports = {
platform: "歌词网",
version: "0.0.0",
srcUrl: 'https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/geciwang/index.js',
cacheControl: "no-store",
supportedSearchType: ['lyric'],
search,
getLyric
};

324
dist/kuaishou/index.js vendored
View File

@@ -1,162 +1,162 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const pageSize = 20;
function formatMusicItem(it) {
return {
id: it.photo.id,
title: it.photo.caption,
artist: it.author.name,
artwork: it.photo.coverUrl || it.photo.photoUrl,
manifest: it.photo.manifest
};
}
async function searchMusic(query, page) {
var _a, _b;
const body = {
query: `fragment photoContent on PhotoEntity {
__typename
id
duration
caption
originCaption
likeCount
viewCount
commentCount
realLikeCount
coverUrl
photoUrl
photoH265Url
manifest
manifestH265
videoResource
coverUrls {
url
__typename
}
timestamp
expTag
animatedCoverUrl
distance
videoRatio
liked
stereoType
profileUserTopPhoto
musicBlocked
}
fragment recoPhotoFragment on recoPhotoEntity {
__typename
id
duration
caption
originCaption
likeCount
viewCount
commentCount
realLikeCount
coverUrl
photoUrl
photoH265Url
manifest
manifestH265
videoResource
coverUrls {
url
__typename
}
timestamp
expTag
animatedCoverUrl
distance
videoRatio
liked
stereoType
profileUserTopPhoto
musicBlocked
}
fragment feedContent on Feed {
type
author {
id
name
headerUrl
following
headerUrls {
url
__typename
}
__typename
}
photo {
...photoContent
...recoPhotoFragment
__typename
}
canAddComment
llsid
status
currentPcursor
tags {
type
name
__typename
}
__typename
}
query visionSearchPhoto($keyword: String, $pcursor: String, $searchSessionId: String, $page: String, $webPageArea: String) {
visionSearchPhoto(keyword: $keyword, pcursor: $pcursor, searchSessionId: $searchSessionId, page: $page, webPageArea: $webPageArea) {
result
llsid
webPageArea
feeds {
...feedContent
__typename
}
searchSessionId
pcursor
aladdinBanner {
imgUrl
link
__typename
}
__typename
}
}`,
variables: {
keyword: query,
page: "search",
pcursor: `${page - 1}`,
},
};
const result = (await axios_1.default.post("https://www.kuaishou.com/graphql", body)).data.data.visionSearchPhoto;
return {
isEnd: !(result === null || result === void 0 ? void 0 : result.pcursor) || (result === null || result === void 0 ? void 0 : result.pcursor) === 'no_more',
data: (_b = (_a = result === null || result === void 0 ? void 0 : result.feeds) === null || _a === void 0 ? void 0 : _a.map) === null || _b === void 0 ? void 0 : _b.call(_a, formatMusicItem)
};
}
module.exports = {
platform: "快手",
version: "0.0.1",
author: '猫头猫',
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/kuaishou/index.js",
cacheControl: "no-cache",
supportedSearchType: ["music"],
async search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
},
async getMediaSource(musicItem, quality) {
if (!musicItem.manifest) {
return;
}
const adaptationSet = musicItem.manifest.adaptationSet;
const representation = adaptationSet[0].representation;
return {
url: representation[0].url
};
},
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const pageSize = 20;
function formatMusicItem(it) {
return {
id: it.photo.id,
title: it.photo.caption,
artist: it.author.name,
artwork: it.photo.coverUrl || it.photo.photoUrl,
manifest: it.photo.manifest
};
}
async function searchMusic(query, page) {
var _a, _b;
const body = {
query: `fragment photoContent on PhotoEntity {
__typename
id
duration
caption
originCaption
likeCount
viewCount
commentCount
realLikeCount
coverUrl
photoUrl
photoH265Url
manifest
manifestH265
videoResource
coverUrls {
url
__typename
}
timestamp
expTag
animatedCoverUrl
distance
videoRatio
liked
stereoType
profileUserTopPhoto
musicBlocked
}
fragment recoPhotoFragment on recoPhotoEntity {
__typename
id
duration
caption
originCaption
likeCount
viewCount
commentCount
realLikeCount
coverUrl
photoUrl
photoH265Url
manifest
manifestH265
videoResource
coverUrls {
url
__typename
}
timestamp
expTag
animatedCoverUrl
distance
videoRatio
liked
stereoType
profileUserTopPhoto
musicBlocked
}
fragment feedContent on Feed {
type
author {
id
name
headerUrl
following
headerUrls {
url
__typename
}
__typename
}
photo {
...photoContent
...recoPhotoFragment
__typename
}
canAddComment
llsid
status
currentPcursor
tags {
type
name
__typename
}
__typename
}
query visionSearchPhoto($keyword: String, $pcursor: String, $searchSessionId: String, $page: String, $webPageArea: String) {
visionSearchPhoto(keyword: $keyword, pcursor: $pcursor, searchSessionId: $searchSessionId, page: $page, webPageArea: $webPageArea) {
result
llsid
webPageArea
feeds {
...feedContent
__typename
}
searchSessionId
pcursor
aladdinBanner {
imgUrl
link
__typename
}
__typename
}
}`,
variables: {
keyword: query,
page: "search",
pcursor: `${page - 1}`,
},
};
const result = (await axios_1.default.post("https://www.kuaishou.com/graphql", body)).data.data.visionSearchPhoto;
return {
isEnd: !(result === null || result === void 0 ? void 0 : result.pcursor) || (result === null || result === void 0 ? void 0 : result.pcursor) === 'no_more',
data: (_b = (_a = result === null || result === void 0 ? void 0 : result.feeds) === null || _a === void 0 ? void 0 : _a.map) === null || _b === void 0 ? void 0 : _b.call(_a, formatMusicItem)
};
}
module.exports = {
platform: "快手",
version: "0.0.1",
author: '猫头猫',
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/kuaishou/index.js",
cacheControl: "no-cache",
supportedSearchType: ["music"],
async search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
},
async getMediaSource(musicItem, quality) {
if (!musicItem.manifest) {
return;
}
const adaptationSet = musicItem.manifest.adaptationSet;
const representation = adaptationSet[0].representation;
return {
url: representation[0].url
};
},
};

398
dist/maoerfm/index.js vendored
View File

@@ -1,199 +1,199 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const pageSize = 30;
function validMusicFilter(_) {
return `${_.pay_type}` === "0";
}
function formatMusicItem(_) {
var _a;
return {
id: _.id,
artwork: _.front_cover,
title: _.soundstr,
artist: _.username,
user_id: _.user_id,
duration: +((_a = _.duration) !== null && _a !== void 0 ? _a : 0),
};
}
function formatAlbumItem(_) {
return {
id: _.id,
artist: _.author,
title: _.name,
artwork: _.cover,
description: _.abstract,
};
}
const searchHeaders = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
accept: "application/json",
"accept-encoding": "gzip, deflate, br",
referer: "https://www.missevan.com/sound/search",
};
async function searchMusic(query, page) {
const res = (await axios_1.default.get("https://www.missevan.com/sound/getsearch", {
params: {
s: query,
p: page,
type: 3,
page_size: pageSize,
},
headers: searchHeaders,
})).data.info;
return {
isEnd: res.pagination.p >= res.pagination.maxpage,
data: res.Datas.filter(validMusicFilter).map(formatMusicItem),
};
}
async function searchAlbum(query, page) {
const res = (await axios_1.default.get("https://www.missevan.com/dramaapi/search", {
headers: searchHeaders,
params: {
s: query,
page,
},
})).data.info;
return {
isEnd: res.pagination.p >= res.pagination.maxpage,
data: res.Datas.filter(validMusicFilter).map(formatAlbumItem),
};
}
async function getAlbumInfo(albumItem) {
const res = (await axios_1.default.get("https://www.missevan.com/dramaapi/getdrama", {
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
accept: "application/json",
"accept-encoding": "gzip, deflate, br",
referer: `https://www.missevan.com/mdrama/${albumItem.id}`,
},
params: {
drama_id: albumItem.id,
},
})).data;
return {
musicList: res.info.episodes.episode
.filter(validMusicFilter)
.map(_ => {
const r = formatMusicItem(_);
r.artwork = albumItem.artwork;
return r;
}),
};
}
async function getMediaSource(musicItem, quality) {
if (quality === "high" || quality === "super") {
return;
}
const res = (await axios_1.default.get("https://www.missevan.com/sound/getsound", {
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
accept: "application/json",
"accept-encoding": "gzip, deflate, br",
referer: `https://www.missevan.com/sound/player?id=${musicItem.id}`,
},
params: {
soundid: musicItem.id,
},
})).data.info;
if (quality === "low") {
return {
url: res.sound.soundurl_128,
};
}
else {
return {
url: res.sound.soundurl,
};
}
}
async function getRecommendSheetTags() {
const res = (await axios_1.default.get(`https://www.missevan.com/malbum/recommand`, {
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
accept: "application/json",
"accept-encoding": "gzip, deflate, br",
referer: `https://www.missevan.com`,
}
})).data.info;
const data = Object.entries(res !== null && res !== void 0 ? res : {}).map(group => ({
title: group[0],
data: group[1].map(_ => ({
id: _[0],
title: _[1]
}))
}));
return {
data,
};
}
async function getRecommendSheetsByTag(tag, page) {
const res = (await axios_1.default.get(`https://www.missevan.com/explore/tagalbum`, {
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
accept: "application/json",
"accept-encoding": "gzip, deflate, br",
referer: `https://m.missevan.com`,
},
params: {
order: 0,
tid: (tag === null || tag === void 0 ? void 0 : tag.id) || 0,
p: page
}
})).data;
return {
isEnd: res.page >= res.maxpage,
data: res.albums.map(sheet => ({
id: sheet.id,
title: sheet.title,
artwork: sheet.front_cover,
artist: sheet.username,
createUserId: sheet.user_id
}))
};
}
async function getMusicSheetInfo(sheet, page) {
const res = (await axios_1.default.get(`https://www.missevan.com/sound/soundalllist`, {
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
accept: "application/json",
"accept-encoding": "gzip, deflate, br",
referer: `https://m.missevan.com`,
},
params: {
albumid: sheet.id
}
})).data.info;
return {
isEnd: true,
musicList: res.sounds.filter(validMusicFilter).map(item => ({
id: item.id,
title: item.soundstr,
artwork: item.front_cover,
url: item.soundurl,
artist: item.username,
}))
};
}
module.exports = {
platform: "猫耳FM",
author: '猫头猫',
version: "0.1.4",
appVersion: ">0.1.0-alpha.0",
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/maoerfm/index.js",
cacheControl: "no-cache",
supportedSearchType: ["music", "album",],
async search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
if (type === "album") {
return await searchAlbum(query, page);
}
},
getMediaSource,
getAlbumInfo,
getRecommendSheetTags,
getRecommendSheetsByTag,
getMusicSheetInfo
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const pageSize = 30;
function validMusicFilter(_) {
return `${_.pay_type}` === "0";
}
function formatMusicItem(_) {
var _a;
return {
id: _.id,
artwork: _.front_cover,
title: _.soundstr,
artist: _.username,
user_id: _.user_id,
duration: +((_a = _.duration) !== null && _a !== void 0 ? _a : 0),
};
}
function formatAlbumItem(_) {
return {
id: _.id,
artist: _.author,
title: _.name,
artwork: _.cover,
description: _.abstract,
};
}
const searchHeaders = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
accept: "application/json",
"accept-encoding": "gzip, deflate, br",
referer: "https://www.missevan.com/sound/search",
};
async function searchMusic(query, page) {
const res = (await axios_1.default.get("https://www.missevan.com/sound/getsearch", {
params: {
s: query,
p: page,
type: 3,
page_size: pageSize,
},
headers: searchHeaders,
})).data.info;
return {
isEnd: res.pagination.p >= res.pagination.maxpage,
data: res.Datas.filter(validMusicFilter).map(formatMusicItem),
};
}
async function searchAlbum(query, page) {
const res = (await axios_1.default.get("https://www.missevan.com/dramaapi/search", {
headers: searchHeaders,
params: {
s: query,
page,
},
})).data.info;
return {
isEnd: res.pagination.p >= res.pagination.maxpage,
data: res.Datas.filter(validMusicFilter).map(formatAlbumItem),
};
}
async function getAlbumInfo(albumItem) {
const res = (await axios_1.default.get("https://www.missevan.com/dramaapi/getdrama", {
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
accept: "application/json",
"accept-encoding": "gzip, deflate, br",
referer: `https://www.missevan.com/mdrama/${albumItem.id}`,
},
params: {
drama_id: albumItem.id,
},
})).data;
return {
musicList: res.info.episodes.episode
.filter(validMusicFilter)
.map(_ => {
const r = formatMusicItem(_);
r.artwork = albumItem.artwork;
return r;
}),
};
}
async function getMediaSource(musicItem, quality) {
if (quality === "high" || quality === "super") {
return;
}
const res = (await axios_1.default.get("https://www.missevan.com/sound/getsound", {
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
accept: "application/json",
"accept-encoding": "gzip, deflate, br",
referer: `https://www.missevan.com/sound/player?id=${musicItem.id}`,
},
params: {
soundid: musicItem.id,
},
})).data.info;
if (quality === "low") {
return {
url: res.sound.soundurl_128,
};
}
else {
return {
url: res.sound.soundurl,
};
}
}
async function getRecommendSheetTags() {
const res = (await axios_1.default.get(`https://www.missevan.com/malbum/recommand`, {
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
accept: "application/json",
"accept-encoding": "gzip, deflate, br",
referer: `https://www.missevan.com`,
}
})).data.info;
const data = Object.entries(res !== null && res !== void 0 ? res : {}).map(group => ({
title: group[0],
data: group[1].map(_ => ({
id: _[0],
title: _[1]
}))
}));
return {
data,
};
}
async function getRecommendSheetsByTag(tag, page) {
const res = (await axios_1.default.get(`https://www.missevan.com/explore/tagalbum`, {
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
accept: "application/json",
"accept-encoding": "gzip, deflate, br",
referer: `https://m.missevan.com`,
},
params: {
order: 0,
tid: (tag === null || tag === void 0 ? void 0 : tag.id) || 0,
p: page
}
})).data;
return {
isEnd: res.page >= res.maxpage,
data: res.albums.map(sheet => ({
id: sheet.id,
title: sheet.title,
artwork: sheet.front_cover,
artist: sheet.username,
createUserId: sheet.user_id
}))
};
}
async function getMusicSheetInfo(sheet, page) {
const res = (await axios_1.default.get(`https://www.missevan.com/sound/soundalllist`, {
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
accept: "application/json",
"accept-encoding": "gzip, deflate, br",
referer: `https://m.missevan.com`,
},
params: {
albumid: sheet.id
}
})).data.info;
return {
isEnd: true,
musicList: res.sounds.filter(validMusicFilter).map(item => ({
id: item.id,
title: item.soundstr,
artwork: item.front_cover,
url: item.soundurl,
artist: item.username,
}))
};
}
module.exports = {
platform: "猫耳FM",
author: '猫头猫',
version: "0.1.4",
appVersion: ">0.1.0-alpha.0",
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/maoerfm/index.js",
cacheControl: "no-cache",
supportedSearchType: ["music", "album",],
async search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
if (type === "album") {
return await searchAlbum(query, page);
}
},
getMediaSource,
getAlbumInfo,
getRecommendSheetTags,
getRecommendSheetsByTag,
getMusicSheetInfo
};

View File

@@ -1,137 +1,137 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const CryptoJs = require("crypto-js");
const pageSize = 25;
async function httpGet(urlPath, params) {
var _a;
const userVariables = (_a = env === null || env === void 0 ? void 0 : env.getUserVariables()) !== null && _a !== void 0 ? _a : {};
let { url, username, password } = userVariables;
console.log(userVariables);
if (!(url && username && password)) {
return null;
}
if (!url.startsWith("http://") && !url.startsWith("https://")) {
url = `http://${url}`;
}
const salt = Math.random().toString(16).slice(2);
const preParams = {
u: username,
s: salt,
t: CryptoJs.MD5(`${password}${salt}`).toString(CryptoJs.enc.Hex),
c: "MusicFree",
v: "1.14.1",
f: "json",
};
return (await axios_1.default.get(`${url}/rest/${urlPath}`, {
params: Object.assign(Object.assign({}, preParams), params),
})).data;
}
function formatMusicItem(it) {
return Object.assign(Object.assign({}, it), { artwork: it.coverArt });
}
function formatAlbumItem(it) {
return Object.assign(Object.assign({}, it), { artwork: it.coverArt });
}
function formatArtistItem(it) {
return Object.assign(Object.assign({}, it), { avatar: it.artistImageUrl });
}
async function searchMusic(query, page) {
const data = await httpGet('search2', {
query,
songCount: pageSize,
songOffset: (page - 1) * pageSize
});
const songs = data['subsonic-response'].searchResult2.song;
return {
isEnd: songs.length < pageSize,
data: songs.map(formatMusicItem)
};
}
async function searchAlbum(query, page) {
const data = await httpGet('search2', {
query,
albumCount: pageSize,
albumOffset: (page - 1) * pageSize
});
const songs = data['subsonic-response'].searchResult2.album;
return {
isEnd: songs.length < pageSize,
data: songs.map(formatAlbumItem)
};
}
async function searchArtist(query, page) {
const data = await httpGet('search2', {
query,
songCount: pageSize,
songOffset: (page - 1) * pageSize
});
const songs = data['subsonic-response'].searchResult2.song;
return {
isEnd: songs.length < pageSize,
data: songs.map(formatMusicItem)
};
}
async function getAlbumInfo(albumItem) {
const data = await httpGet('getAlbum', {
id: albumItem.id
});
return {
isEnd: true,
data: data['subsonic-response'].album.song.map(formatMusicItem)
};
}
module.exports = {
platform: "Navidrome",
version: "0.0.0",
author: '猫头猫',
appVersion: ">0.1.0-alpha.0",
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/navidrome/index.js",
cacheControl: "no-cache",
userVariables: [
{
key: "url",
name: "服务器地址",
},
{
key: "username",
name: "用户名",
},
{
key: "password",
name: "密码",
},
],
supportedSearchType: ["music", "album"],
async search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
if (type === "album") {
return await searchAlbum(query, page);
}
},
async getMediaSource(musicItem) {
var _a;
const userVariables = (_a = env === null || env === void 0 ? void 0 : env.getUserVariables()) !== null && _a !== void 0 ? _a : {};
let { url, username, password } = userVariables;
if (!(url && username && password)) {
return null;
}
if (!url.startsWith("http://") && !url.startsWith("https://")) {
url = `http://${url}`;
}
const salt = Math.random().toString(16).slice(2);
const urlObj = new URL(`${url}/rest/stream`);
urlObj.searchParams.append('u', username);
urlObj.searchParams.append('s', salt);
urlObj.searchParams.append('t', CryptoJs.MD5(`${password}${salt}`).toString(CryptoJs.enc.Hex));
urlObj.searchParams.append('c', 'MusicFree');
urlObj.searchParams.append('v', '1.14.1');
urlObj.searchParams.append('f', 'json');
urlObj.searchParams.append('id', musicItem.id);
return {
url: urlObj.toString()
};
}
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const CryptoJs = require("crypto-js");
const pageSize = 25;
async function httpGet(urlPath, params) {
var _a;
const userVariables = (_a = env === null || env === void 0 ? void 0 : env.getUserVariables()) !== null && _a !== void 0 ? _a : {};
let { url, username, password } = userVariables;
console.log(userVariables);
if (!(url && username && password)) {
return null;
}
if (!url.startsWith("http://") && !url.startsWith("https://")) {
url = `http://${url}`;
}
const salt = Math.random().toString(16).slice(2);
const preParams = {
u: username,
s: salt,
t: CryptoJs.MD5(`${password}${salt}`).toString(CryptoJs.enc.Hex),
c: "MusicFree",
v: "1.14.1",
f: "json",
};
return (await axios_1.default.get(`${url}/rest/${urlPath}`, {
params: Object.assign(Object.assign({}, preParams), params),
})).data;
}
function formatMusicItem(it) {
return Object.assign(Object.assign({}, it), { artwork: it.coverArt });
}
function formatAlbumItem(it) {
return Object.assign(Object.assign({}, it), { artwork: it.coverArt });
}
function formatArtistItem(it) {
return Object.assign(Object.assign({}, it), { avatar: it.artistImageUrl });
}
async function searchMusic(query, page) {
const data = await httpGet('search2', {
query,
songCount: pageSize,
songOffset: (page - 1) * pageSize
});
const songs = data['subsonic-response'].searchResult2.song;
return {
isEnd: songs.length < pageSize,
data: songs.map(formatMusicItem)
};
}
async function searchAlbum(query, page) {
const data = await httpGet('search2', {
query,
albumCount: pageSize,
albumOffset: (page - 1) * pageSize
});
const songs = data['subsonic-response'].searchResult2.album;
return {
isEnd: songs.length < pageSize,
data: songs.map(formatAlbumItem)
};
}
async function searchArtist(query, page) {
const data = await httpGet('search2', {
query,
songCount: pageSize,
songOffset: (page - 1) * pageSize
});
const songs = data['subsonic-response'].searchResult2.song;
return {
isEnd: songs.length < pageSize,
data: songs.map(formatMusicItem)
};
}
async function getAlbumInfo(albumItem) {
const data = await httpGet('getAlbum', {
id: albumItem.id
});
return {
isEnd: true,
data: data['subsonic-response'].album.song.map(formatMusicItem)
};
}
module.exports = {
platform: "Navidrome",
version: "0.0.0",
author: '猫头猫',
appVersion: ">0.1.0-alpha.0",
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/navidrome/index.js",
cacheControl: "no-cache",
userVariables: [
{
key: "url",
name: "服务器地址",
},
{
key: "username",
name: "用户名",
},
{
key: "password",
name: "密码",
},
],
supportedSearchType: ["music", "album"],
async search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
if (type === "album") {
return await searchAlbum(query, page);
}
},
async getMediaSource(musicItem) {
var _a;
const userVariables = (_a = env === null || env === void 0 ? void 0 : env.getUserVariables()) !== null && _a !== void 0 ? _a : {};
let { url, username, password } = userVariables;
if (!(url && username && password)) {
return null;
}
if (!url.startsWith("http://") && !url.startsWith("https://")) {
url = `http://${url}`;
}
const salt = Math.random().toString(16).slice(2);
const urlObj = new URL(`${url}/rest/stream`);
urlObj.searchParams.append('u', username);
urlObj.searchParams.append('s', salt);
urlObj.searchParams.append('t', CryptoJs.MD5(`${password}${salt}`).toString(CryptoJs.enc.Hex));
urlObj.searchParams.append('c', 'MusicFree');
urlObj.searchParams.append('v', '1.14.1');
urlObj.searchParams.append('f', 'json');
urlObj.searchParams.append('id', musicItem.id);
return {
url: urlObj.toString()
};
}
};

188
dist/suno/index.js vendored
View File

@@ -1,94 +1,94 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
host: "studio-api.suno.ai"
};
async function getTopLists() {
return [
{
title: "趋势榜",
data: [
{
id: "1190bf92-10dc-4ce5-968a-7a377f37f984",
title: "趋势榜 - 最近一天",
},
{
id: "08a079b2-a63b-4f9c-9f29-de3c1864ddef",
title: "趋势榜 - 最近一周",
},
{
id: "845539aa-2a39-4cf5-b4ae-16d3fe159a77",
title: "趋势榜 - 最近一月",
},
{
id: "6943c7ee-cbc5-4f72-bc4e-f3371a8be9d5",
title: "趋势榜 - 全部时间",
},
],
},
{
title: "最新榜",
data: [
{
id: "cc14084a-2622-4c4b-8258-1f6b4b4f54b3",
title: "最新榜",
},
],
},
{
title: "其他类别",
data: [
{
id: "1ac7823f-8faf-474f-b14c-e4f7c7bb373f",
title: "动物开会",
},
{
id: '6713d315-3541-460d-8788-162cce241336',
title: 'Lo-Fi'
}
],
},
];
}
async function getTopListDetail(topListItem) {
const result = (await axios_1.default.get(`https://studio-api.suno.ai/api/playlist/${topListItem.id}/?page=0`, {
headers
})).data;
return {
isEnd: true,
musicList: result.playlist_clips.map(it => {
var _a, _b;
const clip = it.clip;
return {
id: clip.id,
url: clip.audio_url,
artwork: clip.image_large_url || clip.image_url,
duration: (_a = clip.metadata) === null || _a === void 0 ? void 0 : _a.duration,
title: clip.title,
artist: clip.display_name,
userId: clip.user_id,
rawLrc: (_b = clip.metadata) === null || _b === void 0 ? void 0 : _b.prompt
};
})
};
}
async function getLyric(musicItem) {
return {
rawLrc: musicItem.rawLrc
};
}
module.exports = {
platform: "suno",
version: "0.0.0",
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/suno/index.js",
cacheControl: "no-cache",
getTopLists,
getTopListDetail,
getLyric
};
getTopListDetail({
id: "1ac7823f-8faf-474f-b14c-e4f7c7bb373f",
title: "最新榜",
}).then(e => console.log(e.musicList[0]));
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
host: "studio-api.suno.ai"
};
async function getTopLists() {
return [
{
title: "趋势榜",
data: [
{
id: "1190bf92-10dc-4ce5-968a-7a377f37f984",
title: "趋势榜 - 最近一天",
},
{
id: "08a079b2-a63b-4f9c-9f29-de3c1864ddef",
title: "趋势榜 - 最近一周",
},
{
id: "845539aa-2a39-4cf5-b4ae-16d3fe159a77",
title: "趋势榜 - 最近一月",
},
{
id: "6943c7ee-cbc5-4f72-bc4e-f3371a8be9d5",
title: "趋势榜 - 全部时间",
},
],
},
{
title: "最新榜",
data: [
{
id: "cc14084a-2622-4c4b-8258-1f6b4b4f54b3",
title: "最新榜",
},
],
},
{
title: "其他类别",
data: [
{
id: "1ac7823f-8faf-474f-b14c-e4f7c7bb373f",
title: "动物开会",
},
{
id: '6713d315-3541-460d-8788-162cce241336',
title: 'Lo-Fi'
}
],
},
];
}
async function getTopListDetail(topListItem) {
const result = (await axios_1.default.get(`https://studio-api.suno.ai/api/playlist/${topListItem.id}/?page=0`, {
headers
})).data;
return {
isEnd: true,
musicList: result.playlist_clips.map(it => {
var _a, _b;
const clip = it.clip;
return {
id: clip.id,
url: clip.audio_url,
artwork: clip.image_large_url || clip.image_url,
duration: (_a = clip.metadata) === null || _a === void 0 ? void 0 : _a.duration,
title: clip.title,
artist: clip.display_name,
userId: clip.user_id,
rawLrc: (_b = clip.metadata) === null || _b === void 0 ? void 0 : _b.prompt
};
})
};
}
async function getLyric(musicItem) {
return {
rawLrc: musicItem.rawLrc
};
}
module.exports = {
platform: "suno",
version: "0.0.0",
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/suno/index.js",
cacheControl: "no-cache",
getTopLists,
getTopListDetail,
getLyric
};
getTopListDetail({
id: "1ac7823f-8faf-474f-b14c-e4f7c7bb373f",
title: "最新榜",
}).then(e => console.log(e.musicList[0]));

316
dist/udio/index.js vendored
View File

@@ -1,158 +1,158 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
};
function formatMusicItem(it) {
return {
id: it.id,
artist: it.artist,
title: it.title,
createdAt: it.created_at,
artwork: it.image_path,
url: it.song_path,
duration: it.duration,
mv: it.video_path,
rawLrc: it.lyrics,
};
}
async function searchMusic(query, page) {
const pageSize = 30;
const data = `{"searchQuery":{"sort":"plays","searchTerm":"${query}"},"pageParam":${page - 1},"pageSize":${pageSize},"trendingId":"93de406e-bdc1-40a6-befd-90637a362158"}`;
const config = {
method: "post",
url: "https://www.udio.com/api/songs/search",
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.0.0",
host: "www.udio.com",
},
data: data,
};
const result = (await (0, axios_1.default)(config)).data.data;
return {
isEnd: result.length < pageSize,
data: result.map(formatMusicItem),
};
}
async function search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
}
async function getMediaSource(musicItem, quality) {
if (quality !== "standard") {
return;
}
return musicItem.url;
}
async function getTopLists() {
return [
{
title: "趋势榜",
data: [
{
id: "today",
maxAgeInHours: 24,
type: "search",
title: "趋势榜 - 最近一天",
},
{
id: "1week",
maxAgeInHours: 168,
type: "search",
title: "趋势榜 - 最近一周",
},
{
id: "1month",
maxAgeInHours: 720,
type: "search",
title: "趋势榜 - 最近一月",
},
{
id: "alltime",
type: "search",
title: "趋势榜 - 全部时间",
},
],
},
{
title: "流派榜单",
data: [
{
id: "89f0089f-1bfe-4713-8070-5830a6161afb",
type: "playlist",
title: "爵士",
},
{
id: "935deb12-dc32-4005-a1fe-3c00c284ca52",
type: "playlist",
title: "乡村",
},
{
id: "6028ad08-68cb-406d-aa35-a4917b6467d6",
type: "playlist",
title: "流行",
},
{
id: "d033aa6e-655e-45d0-8138-dc9a0dc6b3a6",
type: "playlist",
title: "摇滚",
},
],
},
];
}
async function getTopListDetail(topListItem) {
if (topListItem.type === "playlist") {
const res = (await axios_1.default.get(`https://www.udio.com/api/playlists?id=${topListItem.id}`, {
headers,
})).data;
const songList = res.playlists[0].song_list.join(",");
const songs = (await axios_1.default.get(`https://www.udio.com/api/songs?songIds=${songList}`, {
headers,
})).data.songs;
return {
isEnd: true,
musicList: songs.map(formatMusicItem),
};
}
else if (topListItem.type === "search") {
const pageSize = 30;
const data = `{"searchQuery":{"sort":"plays","searchTerm":""${topListItem.maxAgeInHours
? `,"maxAgeInHours": ${topListItem.maxAgeInHours}`
: ""}},"pageParam":0,"pageSize":${pageSize}}`;
const config = {
method: "post",
url: "https://www.udio.com/api/songs/search",
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.0.0",
host: "www.udio.com",
},
data: data,
};
const songs = (await (0, axios_1.default)(config)).data.data;
return {
isEnd: true,
musicList: songs.map(formatMusicItem),
};
}
}
async function getLyric(musicItem) {
return {
rawLrc: musicItem.rawLrc
};
}
module.exports = {
platform: "udio",
author: "猫头猫",
version: "0.0.0",
supportedSearchType: ["music"],
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/udio/index.js",
cacheControl: "no-cache",
search,
getMediaSource,
getTopListDetail,
getTopLists,
getLyric
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61",
};
function formatMusicItem(it) {
return {
id: it.id,
artist: it.artist,
title: it.title,
createdAt: it.created_at,
artwork: it.image_path,
url: it.song_path,
duration: it.duration,
mv: it.video_path,
rawLrc: it.lyrics,
};
}
async function searchMusic(query, page) {
const pageSize = 30;
const data = `{"searchQuery":{"sort":"plays","searchTerm":"${query}"},"pageParam":${page - 1},"pageSize":${pageSize},"trendingId":"93de406e-bdc1-40a6-befd-90637a362158"}`;
const config = {
method: "post",
url: "https://www.udio.com/api/songs/search",
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.0.0",
host: "www.udio.com",
},
data: data,
};
const result = (await (0, axios_1.default)(config)).data.data;
return {
isEnd: result.length < pageSize,
data: result.map(formatMusicItem),
};
}
async function search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
}
async function getMediaSource(musicItem, quality) {
if (quality !== "standard") {
return;
}
return musicItem.url;
}
async function getTopLists() {
return [
{
title: "趋势榜",
data: [
{
id: "today",
maxAgeInHours: 24,
type: "search",
title: "趋势榜 - 最近一天",
},
{
id: "1week",
maxAgeInHours: 168,
type: "search",
title: "趋势榜 - 最近一周",
},
{
id: "1month",
maxAgeInHours: 720,
type: "search",
title: "趋势榜 - 最近一月",
},
{
id: "alltime",
type: "search",
title: "趋势榜 - 全部时间",
},
],
},
{
title: "流派榜单",
data: [
{
id: "89f0089f-1bfe-4713-8070-5830a6161afb",
type: "playlist",
title: "爵士",
},
{
id: "935deb12-dc32-4005-a1fe-3c00c284ca52",
type: "playlist",
title: "乡村",
},
{
id: "6028ad08-68cb-406d-aa35-a4917b6467d6",
type: "playlist",
title: "流行",
},
{
id: "d033aa6e-655e-45d0-8138-dc9a0dc6b3a6",
type: "playlist",
title: "摇滚",
},
],
},
];
}
async function getTopListDetail(topListItem) {
if (topListItem.type === "playlist") {
const res = (await axios_1.default.get(`https://www.udio.com/api/playlists?id=${topListItem.id}`, {
headers,
})).data;
const songList = res.playlists[0].song_list.join(",");
const songs = (await axios_1.default.get(`https://www.udio.com/api/songs?songIds=${songList}`, {
headers,
})).data.songs;
return {
isEnd: true,
musicList: songs.map(formatMusicItem),
};
}
else if (topListItem.type === "search") {
const pageSize = 30;
const data = `{"searchQuery":{"sort":"plays","searchTerm":""${topListItem.maxAgeInHours
? `,"maxAgeInHours": ${topListItem.maxAgeInHours}`
: ""}},"pageParam":0,"pageSize":${pageSize}}`;
const config = {
method: "post",
url: "https://www.udio.com/api/songs/search",
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.0.0",
host: "www.udio.com",
},
data: data,
};
const songs = (await (0, axios_1.default)(config)).data.data;
return {
isEnd: true,
musicList: songs.map(formatMusicItem),
};
}
}
async function getLyric(musicItem) {
return {
rawLrc: musicItem.rawLrc
};
}
module.exports = {
platform: "udio",
author: "猫头猫",
version: "0.0.0",
supportedSearchType: ["music"],
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/udio/index.js",
cacheControl: "no-cache",
search,
getMediaSource,
getTopListDetail,
getTopLists,
getLyric
};

240
dist/webdav/index.js vendored
View File

@@ -1,120 +1,120 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const webdav_1 = require("webdav");
let cachedData = {};
function getClient() {
var _a, _b, _c;
const { url, username, password, searchPath } = (_b = (_a = env === null || env === void 0 ? void 0 : env.getUserVariables) === null || _a === void 0 ? void 0 : _a.call(env)) !== null && _b !== void 0 ? _b : {};
if (!(url && username && password)) {
return null;
}
if (!(cachedData.url === url &&
cachedData.username === username &&
cachedData.password === password &&
cachedData.searchPath === searchPath)) {
cachedData.url = url;
cachedData.username = username;
cachedData.password = password;
cachedData.searchPath = searchPath;
cachedData.searchPathList = (_c = searchPath === null || searchPath === void 0 ? void 0 : searchPath.split) === null || _c === void 0 ? void 0 : _c.call(searchPath, ",");
cachedData.cacheFileList = null;
}
return (0, webdav_1.createClient)(url, {
authType: webdav_1.AuthType.Password,
username,
password,
});
}
async function searchMusic(query) {
var _a, _b;
const client = getClient();
if (!cachedData.cacheFileList) {
const searchPathList = ((_a = cachedData.searchPathList) === null || _a === void 0 ? void 0 : _a.length)
? cachedData.searchPathList
: ["/"];
let result = [];
for (let search of searchPathList) {
try {
const fileItems = (await client.getDirectoryContents(search)).filter((it) => it.type === "file" && it.mime.startsWith("audio"));
result = [...result, ...fileItems];
}
catch (_c) { }
}
cachedData.cacheFileList = result;
}
return {
isEnd: true,
data: ((_b = cachedData.cacheFileList) !== null && _b !== void 0 ? _b : [])
.filter((it) => it.basename.includes(query))
.map((it) => ({
title: it.basename,
id: it.filename,
artist: "未知作者",
album: "未知专辑",
})),
};
}
async function getTopLists() {
getClient();
const data = {
title: "全部歌曲",
data: (cachedData.searchPathList || []).map((it) => ({
title: it,
id: it,
})),
};
return [data];
}
async function getTopListDetail(topListItem) {
const client = getClient();
const fileItems = (await client.getDirectoryContents(topListItem.id)).filter((it) => it.type === "file" && it.mime.startsWith("audio"));
return {
musicList: fileItems.map((it) => ({
title: it.basename,
id: it.filename,
artist: "未知作者",
album: "未知专辑",
})),
};
}
module.exports = {
platform: "WebDAV",
author: "猫头猫",
description: "使用此插件前先配置用户变量",
userVariables: [
{
key: "url",
name: "WebDAV地址",
},
{
key: "username",
name: "用户名",
},
{
key: "password",
name: "密码",
type: "password",
},
{
key: "searchPath",
name: "存放歌曲的路径",
},
],
version: "0.0.2",
supportedSearchType: ["music"],
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/webdav/index.js",
cacheControl: "no-cache",
search(query, page, type) {
if (type === "music") {
return searchMusic(query);
}
},
getTopLists,
getTopListDetail,
getMediaSource(musicItem) {
const client = getClient();
return {
url: client.getFileDownloadLink(musicItem.id),
};
},
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const webdav_1 = require("webdav");
let cachedData = {};
function getClient() {
var _a, _b, _c;
const { url, username, password, searchPath } = (_b = (_a = env === null || env === void 0 ? void 0 : env.getUserVariables) === null || _a === void 0 ? void 0 : _a.call(env)) !== null && _b !== void 0 ? _b : {};
if (!(url && username && password)) {
return null;
}
if (!(cachedData.url === url &&
cachedData.username === username &&
cachedData.password === password &&
cachedData.searchPath === searchPath)) {
cachedData.url = url;
cachedData.username = username;
cachedData.password = password;
cachedData.searchPath = searchPath;
cachedData.searchPathList = (_c = searchPath === null || searchPath === void 0 ? void 0 : searchPath.split) === null || _c === void 0 ? void 0 : _c.call(searchPath, ",");
cachedData.cacheFileList = null;
}
return (0, webdav_1.createClient)(url, {
authType: webdav_1.AuthType.Password,
username,
password,
});
}
async function searchMusic(query) {
var _a, _b;
const client = getClient();
if (!cachedData.cacheFileList) {
const searchPathList = ((_a = cachedData.searchPathList) === null || _a === void 0 ? void 0 : _a.length)
? cachedData.searchPathList
: ["/"];
let result = [];
for (let search of searchPathList) {
try {
const fileItems = (await client.getDirectoryContents(search)).filter((it) => it.type === "file" && it.mime.startsWith("audio"));
result = [...result, ...fileItems];
}
catch (_c) { }
}
cachedData.cacheFileList = result;
}
return {
isEnd: true,
data: ((_b = cachedData.cacheFileList) !== null && _b !== void 0 ? _b : [])
.filter((it) => it.basename.includes(query))
.map((it) => ({
title: it.basename,
id: it.filename,
artist: "未知作者",
album: "未知专辑",
})),
};
}
async function getTopLists() {
getClient();
const data = {
title: "全部歌曲",
data: (cachedData.searchPathList || []).map((it) => ({
title: it,
id: it,
})),
};
return [data];
}
async function getTopListDetail(topListItem) {
const client = getClient();
const fileItems = (await client.getDirectoryContents(topListItem.id)).filter((it) => it.type === "file" && it.mime.startsWith("audio"));
return {
musicList: fileItems.map((it) => ({
title: it.basename,
id: it.filename,
artist: "未知作者",
album: "未知专辑",
})),
};
}
module.exports = {
platform: "WebDAV",
author: "猫头猫",
description: "使用此插件前先配置用户变量",
userVariables: [
{
key: "url",
name: "WebDAV地址",
},
{
key: "username",
name: "用户名",
},
{
key: "password",
name: "密码",
type: "password",
},
{
key: "searchPath",
name: "存放歌曲的路径",
},
],
version: "0.0.2",
supportedSearchType: ["music"],
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/webdav/index.js",
cacheControl: "no-cache",
search(query, page, type) {
if (type === "music") {
return searchMusic(query);
}
},
getTopLists,
getTopListDetail,
getMediaSource(musicItem) {
const client = getClient();
return {
url: client.getFileDownloadLink(musicItem.id),
};
},
};

View File

@@ -1,96 +1,96 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const pageNum = 20;
function formatMusicItem(item) {
var _a, _b, _c, _d;
return {
id: item.id,
title: item.title,
artist: (item === null || item === void 0 ? void 0 : item.allArtistNames) ||
((_b = (_a = item.artists) === null || _a === void 0 ? void 0 : _a.map) === null || _b === void 0 ? void 0 : _b.call(_a, (s) => s.name).join(", ")) ||
((_c = item.user) === null || _c === void 0 ? void 0 : _c.niceName),
artwork: item === null || item === void 0 ? void 0 : item.headImg,
urls: (_d = item === null || item === void 0 ? void 0 : item.fullClip) === null || _d === void 0 ? void 0 : _d.urls,
};
}
function formatArtistItem(item) {
return {
id: item.id,
name: item.name,
avatar: item.headImg,
};
}
let lastQuery;
let lastMusicId;
async function searchMusic(query, page) {
if (query !== lastQuery || page === 1) {
lastMusicId = 0;
}
lastQuery = query;
let data = JSON.stringify({
searchType: "MV",
key: query,
sinceId: lastMusicId,
size: pageNum,
requestTagRows: [
{
key: "sortType",
chosenTags: ["HOTTEST"],
},
{
key: "source",
chosenTags: ["-1"],
},
{
key: "duration",
chosenTags: ["-1"],
},
],
});
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://search-api.yinyuetai.com/search/get_search_result.json",
headers: {
referrer: "https://www.yinyuetai.com/",
accept: "application/json",
"content-type": "application/json",
wua: "YYT/1.0.0 (WEB;web;11;zh-CN;kADiV2jNJFy2ryvuyB5Ne)",
},
data: data,
};
const response = (await axios_1.default.request(config)).data.data;
lastMusicId = response[response.length - 1].id;
return {
isEnd: pageNum > response.length,
data: response.map(formatMusicItem),
};
}
async function search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
}
async function getMediaSource(musicItem, quality) {
let url;
if (quality === "standard") {
url = musicItem.urls.find((it) => it.streamType === 5).url;
}
else if (quality === "high") {
url = musicItem.urls.find((it) => it.streamType === 1).url;
}
return {
url,
};
}
module.exports = {
platform: "音悦台",
author: '猫头猫',
version: "0.0.1",
supportedSearchType: ["music"],
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/yinyuetai/index.js",
cacheControl: "no-cache",
search,
getMediaSource,
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const pageNum = 20;
function formatMusicItem(item) {
var _a, _b, _c, _d;
return {
id: item.id,
title: item.title,
artist: (item === null || item === void 0 ? void 0 : item.allArtistNames) ||
((_b = (_a = item.artists) === null || _a === void 0 ? void 0 : _a.map) === null || _b === void 0 ? void 0 : _b.call(_a, (s) => s.name).join(", ")) ||
((_c = item.user) === null || _c === void 0 ? void 0 : _c.niceName),
artwork: item === null || item === void 0 ? void 0 : item.headImg,
urls: (_d = item === null || item === void 0 ? void 0 : item.fullClip) === null || _d === void 0 ? void 0 : _d.urls,
};
}
function formatArtistItem(item) {
return {
id: item.id,
name: item.name,
avatar: item.headImg,
};
}
let lastQuery;
let lastMusicId;
async function searchMusic(query, page) {
if (query !== lastQuery || page === 1) {
lastMusicId = 0;
}
lastQuery = query;
let data = JSON.stringify({
searchType: "MV",
key: query,
sinceId: lastMusicId,
size: pageNum,
requestTagRows: [
{
key: "sortType",
chosenTags: ["HOTTEST"],
},
{
key: "source",
chosenTags: ["-1"],
},
{
key: "duration",
chosenTags: ["-1"],
},
],
});
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://search-api.yinyuetai.com/search/get_search_result.json",
headers: {
referrer: "https://www.yinyuetai.com/",
accept: "application/json",
"content-type": "application/json",
wua: "YYT/1.0.0 (WEB;web;11;zh-CN;kADiV2jNJFy2ryvuyB5Ne)",
},
data: data,
};
const response = (await axios_1.default.request(config)).data.data;
lastMusicId = response[response.length - 1].id;
return {
isEnd: pageNum > response.length,
data: response.map(formatMusicItem),
};
}
async function search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
}
async function getMediaSource(musicItem, quality) {
let url;
if (quality === "standard") {
url = musicItem.urls.find((it) => it.streamType === 5).url;
}
else if (quality === "high") {
url = musicItem.urls.find((it) => it.streamType === 1).url;
}
return {
url,
};
}
module.exports = {
platform: "音悦台",
author: '猫头猫',
version: "0.0.1",
supportedSearchType: ["music"],
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/yinyuetai/index.js",
cacheControl: "no-cache",
search,
getMediaSource,
};

392
dist/youtube/index.js vendored
View File

@@ -1,196 +1,196 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
function formatMusicItem(item) {
var _a, _b, _c, _d, _e, _f, _g;
return {
id: item.videoId,
title: (_b = (_a = item.title.runs) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.text,
artist: (_d = (_c = item.ownerText.runs) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.text,
artwork: (_g = (_f = (_e = item === null || item === void 0 ? void 0 : item.thumbnail) === null || _e === void 0 ? void 0 : _e.thumbnails) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.url,
};
}
let lastQuery;
let musicContinToken;
async function searchMusic(query, page) {
if (query !== lastQuery || page === 1) {
musicContinToken = undefined;
}
lastQuery = query;
let data = JSON.stringify({
context: {
client: {
hl: "zh-CN",
gl: "US",
deviceMake: "",
deviceModel: "",
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0,gzip(gfe)",
clientName: "WEB",
clientVersion: "2.20231121.08.00",
osName: "Windows",
osVersion: "10.0",
platform: "DESKTOP",
userInterfaceTheme: "USER_INTERFACE_THEME_LIGHT",
browserName: "Edge Chromium",
browserVersion: "119.0.0.0",
acceptHeader: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
screenWidthPoints: 1358,
screenHeightPoints: 1012,
screenPixelDensity: 1,
screenDensityFloat: 1.2395833730697632,
utcOffsetMinutes: 480,
memoryTotalKbytes: "8000000",
mainAppWebInfo: {
pwaInstallabilityStatus: "PWA_INSTALLABILITY_STATUS_UNKNOWN",
webDisplayMode: "WEB_DISPLAY_MODE_BROWSER",
isWebNativeShareAvailable: true,
},
timeZone: "Asia/Shanghai",
},
user: {
lockedSafetyMode: false,
},
request: {
useSsl: true,
internalExperimentFlags: [],
},
},
query: musicContinToken ? undefined : query,
continuation: musicContinToken || undefined,
});
var config = {
method: "post",
url: "https://www.youtube.com/youtubei/v1/search?prettyPrint=false",
headers: {
"Content-Type": "text/plain",
},
data: data,
};
const response = (await (0, axios_1.default)(config)).data;
const contents = response.contents.twoColumnSearchResultsRenderer.primaryContents
.sectionListRenderer.contents;
const isEndItem = contents.find((it) => {
var _a, _b, _c;
return ((_c = (_b = (_a = it.continuationItemRenderer) === null || _a === void 0 ? void 0 : _a.continuationEndpoint) === null || _b === void 0 ? void 0 : _b.continuationCommand) === null || _c === void 0 ? void 0 : _c.request) === "CONTINUATION_REQUEST_TYPE_SEARCH";
});
if (isEndItem) {
musicContinToken =
isEndItem.continuationItemRenderer.continuationEndpoint
.continuationCommand.token;
}
const musicData = contents.find((it) => it.itemSectionRenderer)
.itemSectionRenderer.contents;
let resultMusicData = [];
for (let i = 0; i < musicData.length; ++i) {
if (musicData[i].videoRenderer) {
resultMusicData.push(formatMusicItem(musicData[i].videoRenderer));
}
}
return {
isEnd: !isEndItem,
data: resultMusicData,
};
}
async function search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
}
let cacheMediaSource = {
id: null,
urls: {},
};
function getQuality(label) {
if (label === "small") {
return "standard";
}
else if (label === "tiny") {
return "low";
}
else if (label === "medium") {
return "high";
}
else if (label === "large") {
return "super";
}
else {
return "standard";
}
}
async function getMediaSource(musicItem, quality) {
var _a, _b;
if (musicItem.id === cacheMediaSource.id) {
return {
url: cacheMediaSource.urls[quality],
};
}
cacheMediaSource = {
id: null,
urls: {},
};
const data = {
context: {
client: {
screenWidthPoints: 689,
screenHeightPoints: 963,
screenPixelDensity: 1,
utcOffsetMinutes: 120,
hl: "en",
gl: "GB",
remoteHost: "1.1.1.1",
deviceMake: "",
deviceModel: "",
userAgent: "com.google.android.apps.youtube.music/6.14.50 (Linux; U; Android 13; GB) gzip",
clientName: "ANDROID_MUSIC",
clientVersion: "6.14.50",
osName: "Android",
osVersion: "13",
originalUrl: "https://www.youtube.com/tv?is_account_switch=1&hrld=1&fltor=1",
theme: "CLASSIC",
platform: "MOBILE",
clientFormFactor: "UNKNOWN_FORM_FACTOR",
webpSupport: false,
timeZone: "Europe/Amsterdam",
acceptHeader: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
},
user: { enableSafetyMode: false },
request: {
internalExperimentFlags: [],
consistencyTokenJars: [],
},
},
contentCheckOk: true,
racyCheckOk: true,
video_id: musicItem.id,
};
var config = {
method: "post",
url: "https://www.youtube.com/youtubei/v1/player?prettyPrint=false",
headers: {
"Content-Type": "application/json",
},
data: JSON.stringify(data),
};
const result = (await (0, axios_1.default)(config)).data;
const formats = (_a = result.streamingData.formats) !== null && _a !== void 0 ? _a : [];
const adaptiveFormats = (_b = result.streamingData.adaptiveFormats) !== null && _b !== void 0 ? _b : [];
[...formats, ...adaptiveFormats].forEach((it) => {
const q = getQuality(it.quality);
if (q && it.url && !cacheMediaSource.urls[q]) {
cacheMediaSource.urls[q] = it.url;
}
});
return {
url: cacheMediaSource.urls[quality],
};
}
module.exports = {
platform: "Youtube",
author: '猫头猫',
version: "0.0.1",
supportedSearchType: ["music"],
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/youtube/index.js",
cacheControl: "no-cache",
search,
getMediaSource,
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
function formatMusicItem(item) {
var _a, _b, _c, _d, _e, _f, _g;
return {
id: item.videoId,
title: (_b = (_a = item.title.runs) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.text,
artist: (_d = (_c = item.ownerText.runs) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.text,
artwork: (_g = (_f = (_e = item === null || item === void 0 ? void 0 : item.thumbnail) === null || _e === void 0 ? void 0 : _e.thumbnails) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.url,
};
}
let lastQuery;
let musicContinToken;
async function searchMusic(query, page) {
if (query !== lastQuery || page === 1) {
musicContinToken = undefined;
}
lastQuery = query;
let data = JSON.stringify({
context: {
client: {
hl: "zh-CN",
gl: "US",
deviceMake: "",
deviceModel: "",
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0,gzip(gfe)",
clientName: "WEB",
clientVersion: "2.20231121.08.00",
osName: "Windows",
osVersion: "10.0",
platform: "DESKTOP",
userInterfaceTheme: "USER_INTERFACE_THEME_LIGHT",
browserName: "Edge Chromium",
browserVersion: "119.0.0.0",
acceptHeader: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
screenWidthPoints: 1358,
screenHeightPoints: 1012,
screenPixelDensity: 1,
screenDensityFloat: 1.2395833730697632,
utcOffsetMinutes: 480,
memoryTotalKbytes: "8000000",
mainAppWebInfo: {
pwaInstallabilityStatus: "PWA_INSTALLABILITY_STATUS_UNKNOWN",
webDisplayMode: "WEB_DISPLAY_MODE_BROWSER",
isWebNativeShareAvailable: true,
},
timeZone: "Asia/Shanghai",
},
user: {
lockedSafetyMode: false,
},
request: {
useSsl: true,
internalExperimentFlags: [],
},
},
query: musicContinToken ? undefined : query,
continuation: musicContinToken || undefined,
});
var config = {
method: "post",
url: "https://www.youtube.com/youtubei/v1/search?prettyPrint=false",
headers: {
"Content-Type": "text/plain",
},
data: data,
};
const response = (await (0, axios_1.default)(config)).data;
const contents = response.contents.twoColumnSearchResultsRenderer.primaryContents
.sectionListRenderer.contents;
const isEndItem = contents.find((it) => {
var _a, _b, _c;
return ((_c = (_b = (_a = it.continuationItemRenderer) === null || _a === void 0 ? void 0 : _a.continuationEndpoint) === null || _b === void 0 ? void 0 : _b.continuationCommand) === null || _c === void 0 ? void 0 : _c.request) === "CONTINUATION_REQUEST_TYPE_SEARCH";
});
if (isEndItem) {
musicContinToken =
isEndItem.continuationItemRenderer.continuationEndpoint
.continuationCommand.token;
}
const musicData = contents.find((it) => it.itemSectionRenderer)
.itemSectionRenderer.contents;
let resultMusicData = [];
for (let i = 0; i < musicData.length; ++i) {
if (musicData[i].videoRenderer) {
resultMusicData.push(formatMusicItem(musicData[i].videoRenderer));
}
}
return {
isEnd: !isEndItem,
data: resultMusicData,
};
}
async function search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
}
let cacheMediaSource = {
id: null,
urls: {},
};
function getQuality(label) {
if (label === "small") {
return "standard";
}
else if (label === "tiny") {
return "low";
}
else if (label === "medium") {
return "high";
}
else if (label === "large") {
return "super";
}
else {
return "standard";
}
}
async function getMediaSource(musicItem, quality) {
var _a, _b;
if (musicItem.id === cacheMediaSource.id) {
return {
url: cacheMediaSource.urls[quality],
};
}
cacheMediaSource = {
id: null,
urls: {},
};
const data = {
context: {
client: {
screenWidthPoints: 689,
screenHeightPoints: 963,
screenPixelDensity: 1,
utcOffsetMinutes: 120,
hl: "en",
gl: "GB",
remoteHost: "1.1.1.1",
deviceMake: "",
deviceModel: "",
userAgent: "com.google.android.apps.youtube.music/6.14.50 (Linux; U; Android 13; GB) gzip",
clientName: "ANDROID_MUSIC",
clientVersion: "6.14.50",
osName: "Android",
osVersion: "13",
originalUrl: "https://www.youtube.com/tv?is_account_switch=1&hrld=1&fltor=1",
theme: "CLASSIC",
platform: "MOBILE",
clientFormFactor: "UNKNOWN_FORM_FACTOR",
webpSupport: false,
timeZone: "Europe/Amsterdam",
acceptHeader: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
},
user: { enableSafetyMode: false },
request: {
internalExperimentFlags: [],
consistencyTokenJars: [],
},
},
contentCheckOk: true,
racyCheckOk: true,
video_id: musicItem.id,
};
var config = {
method: "post",
url: "https://www.youtube.com/youtubei/v1/player?prettyPrint=false",
headers: {
"Content-Type": "application/json",
},
data: JSON.stringify(data),
};
const result = (await (0, axios_1.default)(config)).data;
const formats = (_a = result.streamingData.formats) !== null && _a !== void 0 ? _a : [];
const adaptiveFormats = (_b = result.streamingData.adaptiveFormats) !== null && _b !== void 0 ? _b : [];
[...formats, ...adaptiveFormats].forEach((it) => {
const q = getQuality(it.quality);
if (q && it.url && !cacheMediaSource.urls[q]) {
cacheMediaSource.urls[q] = it.url;
}
});
return {
url: cacheMediaSource.urls[quality],
};
}
module.exports = {
platform: "Youtube",
author: '猫头猫',
version: "0.0.1",
supportedSearchType: ["music"],
srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/youtube/index.js",
cacheControl: "no-cache",
search,
getMediaSource,
};

View File

@@ -1 +1 @@
{"desc":"此链接为 MusicFree 插件,插件开发及使用方式参考 https://musicfree.upup.fun","plugins":[{"name":"bilibili","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/bilibili/index.js","version":"0.1.15"},{"name":"Audiomack","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/audiomack/index.js","version":"0.0.2"},{"name":"歌词千寻","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/geciqianxun/index.js","version":"0.0.0"},{"name":"歌词网","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/geciwang/index.js","version":"0.0.0"},{"name":"快手","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/kuaishou/index.js","version":"0.0.1"},{"name":"Navidrome","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/navidrome/index.js","version":"0.0.0"},{"name":"猫耳FM","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/maoerfm/index.js","version":"0.1.4"},{"name":"suno","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/suno/index.js","version":"0.0.0"},{"name":"udio","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/udio/index.js","version":"0.0.0"},{"name":"音悦台","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/yinyuetai/index.js","version":"0.0.1"},{"name":"WebDAV","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/webdav/index.js","version":"0.0.2"},{"name":"Youtube","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/youtube/index.js","version":"0.0.1"}]}
{"desc":"此链接为 MusicFree 插件,插件开发及使用方式参考 https://musicfree.upup.fun","plugins":[{"name":"Audiomack","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/audiomack/index.js","version":"0.0.2"},{"name":"歌词千寻","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/geciqianxun/index.js","version":"0.0.0"},{"name":"bilibili","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/bilibili/index.js","version":"0.2.0"},{"name":"歌词网","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/geciwang/index.js","version":"0.0.0"},{"name":"suno","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/suno/index.js","version":"0.0.0"},{"name":"猫耳FM","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/maoerfm/index.js","version":"0.1.4"},{"name":"快手","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/kuaishou/index.js","version":"0.0.1"},{"name":"udio","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/udio/index.js","version":"0.0.0"},{"name":"Navidrome","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/navidrome/index.js","version":"0.0.0"},{"name":"WebDAV","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/webdav/index.js","version":"0.0.2"},{"name":"Youtube","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/youtube/index.js","version":"0.0.1"},{"name":"音悦台","url":"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/yinyuetai/index.js","version":"0.0.1"}]}

View File

@@ -521,10 +521,54 @@ async function importMusicSheet(urlLike: string) {
}));
}
function formatComment(item) {
return {
id: item.rpid,
// 用户名
nickName: item.member?.uname,
// 头像
avatar: item.member?.avatar,
// 评论内容
comment: item.content?.message,
// 点赞数
like: item.like,
// 评论时间
createAt: item.ctime * 1000,
// 地址
location: item.reply_control?.location?.startsWith("IP属地") ? item.reply_control.location.slice(5): undefined
}
}
async function getMusicComments(musicItem) {
const res = (await (axios.get("https://api.bilibili.com/x/v2/reply", {
params: {
type: 1,
oid: musicItem.aid,
mode: 3,
plat: 1
}
}))).data;
const data = res.data.replies;
const comments = [];
for (let i = 0; i < data.length; ++i) {
comments[i] = formatComment(data[i]);
if (data[i].replies?.length) {
comments[i].replies = data[i]?.replies.map(formatComment);
}
}
return {
isEnd: true,
data: comments
}
}
module.exports = {
platform: "bilibili",
appVersion: ">=0.0",
version: "0.1.15",
version: "0.2.0",
author: "猫头猫",
cacheControl: "no-cache",
srcUrl:
@@ -579,6 +623,7 @@ module.exports = {
getTopLists,
getTopListDetail,
importMusicSheet,
getMusicComments
};
// searchAlbum('周杰伦', 2)
@@ -595,7 +640,7 @@ module.exports = {
// }
// }
// getMediaSource( {
// getMediaComment( {
// id: 'BV1r7411p7R4',
// aid: 86670567,
// bvid: 'BV1r7411p7R4',
@@ -610,7 +655,7 @@ module.exports = {
// '重新修复伪4K修复仅为提升观感',
// duration: 242,
// date: '2020-02-04'
// }, 'standard').then(console.log)
// }).then(console.log)
// getArtistWorks({
// name: '不想睡觉猫头猫',

View File

@@ -1,169 +1,182 @@
import axios from "axios";
const pageSize = 20;
function formatMusicItem(it){
return {
id: it.photo.id,
title: it.photo.caption,
artist: it.author.name,
artwork: it.photo.coverUrl || it.photo.photoUrl,
manifest: it.photo.manifest
}
}
async function searchMusic(query, page) {
const body = {
query: `fragment photoContent on PhotoEntity {
__typename
id
duration
caption
originCaption
likeCount
viewCount
commentCount
realLikeCount
coverUrl
photoUrl
photoH265Url
manifest
manifestH265
videoResource
coverUrls {
url
__typename
}
timestamp
expTag
animatedCoverUrl
distance
videoRatio
liked
stereoType
profileUserTopPhoto
musicBlocked
}
fragment recoPhotoFragment on recoPhotoEntity {
__typename
id
duration
caption
originCaption
likeCount
viewCount
commentCount
realLikeCount
coverUrl
photoUrl
photoH265Url
manifest
manifestH265
videoResource
coverUrls {
url
__typename
}
timestamp
expTag
animatedCoverUrl
distance
videoRatio
liked
stereoType
profileUserTopPhoto
musicBlocked
}
fragment feedContent on Feed {
type
author {
id
name
headerUrl
following
headerUrls {
url
__typename
}
__typename
}
photo {
...photoContent
...recoPhotoFragment
__typename
}
canAddComment
llsid
status
currentPcursor
tags {
type
name
__typename
}
__typename
}
query visionSearchPhoto($keyword: String, $pcursor: String, $searchSessionId: String, $page: String, $webPageArea: String) {
visionSearchPhoto(keyword: $keyword, pcursor: $pcursor, searchSessionId: $searchSessionId, page: $page, webPageArea: $webPageArea) {
result
llsid
webPageArea
feeds {
...feedContent
__typename
}
searchSessionId
pcursor
aladdinBanner {
imgUrl
link
__typename
}
__typename
}
}`,
variables: {
keyword: query,
page: "search",
pcursor: `${page - 1}`,
},
};
const result = (await axios.post("https://www.kuaishou.com/graphql", body)).data.data.visionSearchPhoto;
return {
isEnd: !result?.pcursor || result?.pcursor === 'no_more',
data: result?.feeds?.map?.(formatMusicItem)
}
}
module.exports = {
platform: "快手",
version: "0.0.1",
author: '猫头猫',
srcUrl:
"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/kuaishou/index.js",
cacheControl: "no-cache",
supportedSearchType: ["music"],
async search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
},
async getMediaSource(musicItem, quality: IMusic.IQualityKey) {
if(!musicItem.manifest) {
return;
}
const adaptationSet = musicItem.manifest.adaptationSet;
const representation = adaptationSet[0].representation;
return {
url: representation[0].url
};
},
};
// searchMusic('夜曲', 1).then(e => console.log(e.data[1].manifest.adaptationSet[0].representation));
import axios from "axios";
const pageSize = 20;
function formatMusicItem(it){
return {
id: it.photo.id,
title: it.photo.caption,
artist: it.author.name,
artwork: it.photo.coverUrl || it.photo.photoUrl,
manifest: it.photo.manifest
}
}
async function searchMusic(query, page) {
const body = {
query: `fragment photoContent on PhotoEntity {
__typename
id
duration
caption
originCaption
likeCount
viewCount
commentCount
realLikeCount
coverUrl
photoUrl
photoH265Url
manifest
manifestH265
videoResource
coverUrls {
url
__typename
}
timestamp
expTag
animatedCoverUrl
distance
videoRatio
liked
stereoType
profileUserTopPhoto
musicBlocked
riskTagContent
riskTagUrl
}
fragment recoPhotoFragment on recoPhotoEntity {
__typename
id
duration
caption
originCaption
likeCount
viewCount
commentCount
realLikeCount
coverUrl
photoUrl
photoH265Url
manifest
manifestH265
videoResource
coverUrls {
url
__typename
}
timestamp
expTag
animatedCoverUrl
distance
videoRatio
liked
stereoType
profileUserTopPhoto
musicBlocked
riskTagContent
riskTagUrl
}
fragment feedContent on Feed {
type
author {
id
name
headerUrl
following
headerUrls {
url
__typename
}
__typename
}
photo {
...photoContent
...recoPhotoFragment
__typename
}
canAddComment
llsid
status
currentPcursor
tags {
type
name
__typename
}
__typename
}
query visionSearchPhoto($keyword: String, $pcursor: String, $searchSessionId: String, $page: String, $webPageArea: String) {
visionSearchPhoto(keyword: $keyword, pcursor: $pcursor, searchSessionId: $searchSessionId, page: $page, webPageArea: $webPageArea) {
result
llsid
webPageArea
feeds {
...feedContent
__typename
}
searchSessionId
pcursor
aladdinBanner {
imgUrl
link
__typename
}
__typename
}
}`,
variables: {
keyword: query,
page: "search",
pcursor: `${page - 1}`,
},
};
const result = (await axios.post("https://www.kuaishou.com/graphql", body, {
headers: {
'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
host: 'www.kuaishou.com',
origin: 'https://www.kuaishou.com',
referer: `https://www.kuaishou.com/search/video?searchKey=${encodeURIComponent((query))}`,
}
})).data.data.visionSearchPhoto;
return {
isEnd: !result?.pcursor || result?.pcursor === 'no_more',
data: result?.feeds?.map?.(formatMusicItem)
}
}
module.exports = {
platform: "快手",
version: "0.0.2",
author: '猫头猫',
srcUrl:
"https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/kuaishou/index.js",
cacheControl: "no-cache",
supportedSearchType: ["music"],
async search(query, page, type) {
if (type === "music") {
return await searchMusic(query, page);
}
},
async getMediaSource(musicItem, quality) {
if(!musicItem.manifest) {
return;
}
const adaptationSet = musicItem.manifest.adaptationSet;
const representation = adaptationSet[0].representation;
return {
url: representation[0].url
};
},
};
// searchMusic('夜曲', 1).then(e => console.log(e.data[1].manifest.adaptationSet[0].representation));

17
test/geciqianxun.ts Normal file
View File

@@ -0,0 +1,17 @@
const plugin = require('../plugins/geciqianxun');
async function run() {
// 测试搜索歌词
const searchResult = await plugin.search('七里香', 1, 'lyric');
console.log(searchResult);
if (searchResult.data.length > 0) {
const musicItem = searchResult.data[0];
const lyricResult = await plugin.getLyric(musicItem);
console.log(lyricResult);
}
}
run();

17
test/geciwang.ts Normal file
View File

@@ -0,0 +1,17 @@
const plugin = require('../plugins/geciwang');
async function run() {
// 测试搜索歌词
const searchResult = await plugin.search('七里香', 1, 'lyric');
console.log(searchResult);
if (searchResult.data.length > 0) {
const musicItem = searchResult.data[0];
const lyricResult = await plugin.getLyric(musicItem);
console.log(lyricResult);
}
}
run();

18
test/kuaishou.ts Normal file
View File

@@ -0,0 +1,18 @@
const plugin = require('../plugins/kuaishou');
async function run() {
// 搜索歌曲
const res = await plugin.search('七里香', 1,'music');
console.log(res);
if (res.data.length > 0) {
const musicItem = res.data[0];
const sourceResult = await plugin.getMediaSource(musicItem, 'standard');
console.log(sourceResult);
}
}
run();

View File

@@ -1,17 +1,17 @@
{
"compilerOptions": {
"noImplicitAny": false,
"noEmitOnError": true,
"removeComments": true,
"allowJs": true,
"sourceMap": false,
"module": "CommonJS",
"target": "ES2017",
"outDir": "dist",
"baseUrl": "./",
},
"include": [
"./types/*",
"./plugins/*/index.ts"
]
}
{
"compilerOptions": {
"noImplicitAny": false,
"noEmitOnError": true,
"removeComments": true,
"allowJs": true,
"sourceMap": false,
"module": "CommonJS",
"target": "ES2017",
"outDir": "dist",
"baseUrl": "./",
},
"include": [
"./types/*",
"./plugins/*/index.ts"
]
}