ytmusic_api_unofficial
Version:
A simple API to get music from YouTube Music
149 lines • 5.93 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSignatureTimestamp = getSignatureTimestamp;
exports.getDecodeScript = getDecodeScript;
exports.getUrlDecode = getUrlDecode;
exports.decode = decode;
const error_1 = require("./error");
let decodeFile = '';
function getSignatureTimestamp() {
return new Promise((resolve) => {
fetchScript("SignatureTimestamp").then((res) => {
resolve(eval(res));
});
});
}
function getDecodeScript(force = false) {
return new Promise((resolve) => {
fetchScript(['ExtractDecipher', 'NTransform'], force).then((res) => {
resolve(res);
});
});
}
function getUrlDecode(url, retry = false) {
return new Promise((resolve, reject) => {
getDecodeScript(retry).then((_a) => __awaiter(this, [_a], void 0, function* ([decipherScript, nTransformScript]) {
checkUrlIsMusic((yield decode(url, decipherScript, nTransformScript)).url).then(resolve).catch((e) => {
if (!retry)
return resolve(getUrlDecode(url, true));
reject(e);
});
}));
});
}
function checkUrlIsMusic(url) {
return new Promise((resolve, reject) => {
fetch(url).then((res) => __awaiter(this, void 0, void 0, function* () {
if ((res.headers.get('content-type') || '').match(/audio|video/gm))
return resolve(url);
else {
if (res.status === 403)
return reject((0, error_1.error)(2005, {
url,
error: 'The download link returned is not valid, please retry or report the error'
}));
resolve(checkUrlIsMusic(yield res.text()));
}
})).catch((e) => {
reject((0, error_1.error)(2005, { url, error: e.message }));
});
});
}
function fetchScript(nameFunc = "ExtractDecipher", force = false) {
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
let file = null;
if (process.env.buildDevDecoderFile) {
process.emitWarning('You are using a development build, the decoder will be use as local. If you want to use the internet decoder, please use a production build.');
file = process.env.buildDevDecoderFile.toString();
}
if (!force && decodeFile !== '')
file = decodeFile;
if (!file) {
yield fetch('https://raw.githubusercontent.com/Alexis06030631/yt_music_api/docs/decoder.js').then(res => {
return res.text();
}).then(res => {
file = res;
decodeFile = res;
});
}
if (!file)
return reject((0, error_1.error)(5000, { code: 1005, message: 'The decoder file is not available' }));
let scriptsS = null;
if (typeof nameFunc === 'string') {
scriptsS = file.match(new RegExp(`//${nameFunc}\n((?:.|\n)*?)(?:\n\n|$)`))[1];
}
if (Array.isArray(nameFunc)) {
scriptsS = nameFunc.map((name) => {
return file.match(new RegExp(`//${name}\n((?:.|\n)*?)(?:\n\n|$)`))[1];
});
}
return resolve(scriptsS);
}));
}
function runScript(script, ...args) {
try {
args.forEach((arg) => {
script = script.replace(new RegExp(`${arg.name}`, 'g'), `"${arg.value.replace('"', '\\"')}"`);
});
return eval(script);
}
catch (e) {
return args[0].value;
}
}
function exportArgsUrl(url) {
const return_object = {};
const args = url.match(/(.*?)=(.*?)(?:&|$)/g);
if (args) {
args.forEach((arg) => {
const [name, value] = arg.split('=');
return_object[name] = value.replace(/&$/, '');
});
}
return return_object;
}
function decode(format, decipherScript, nTransformScript) {
try {
if (!decipherScript)
return;
const decipher = (url) => {
const args = exportArgsUrl(url);
if (!args.s)
return args.url;
const components = new URL(decodeURIComponent(args.url));
components.searchParams.set(args.sp || "sig", runScript(decipherScript, {
name: 'sig',
value: decodeURIComponent(args.s)
}));
return components.toString();
};
const nTransform = (url) => {
const components = new URL(decodeURIComponent(url));
const n = components.searchParams.get("n");
if (!n || !nTransformScript)
return url;
components.searchParams.set("n", runScript(nTransformScript, { name: 'ncode', value: n }));
return components.toString();
};
const cipher = !format.url;
const url = format.url || format.signatureCipher || format.cipher;
format.url = nTransform(cipher ? decipher(url) : url);
delete format.signatureCipher;
delete format.cipher;
return format;
}
catch (e) {
console.error(e);
return format;
}
}
//# sourceMappingURL=decode.js.map