consumet.custom
Version:
Nodejs library that provides high-level APIs for obtaining information on various entertainment media such as books, movies, comic books, anime, manga, and so on.
154 lines • 6.49 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_1 = __importDefault(require("crypto"));
const models_1 = require("../models");
const megacloud = {
script: 'https://megacloud.tv/js/player/a/prod/e1-player.min.js?v=',
sources: 'https://megacloud.tv/embed-2/ajax/e-1/getSources?id=',
};
class MegaCloud extends models_1.VideoExtractor {
constructor() {
super(...arguments);
this.serverName = 'MegaCloud';
this.sources = [];
}
async extract(videoUrl) {
var _a, _b, _c;
try {
const result = {
sources: [],
subtitles: [],
};
const videoId = (_c = (_b = (_a = videoUrl === null || videoUrl === void 0 ? void 0 : videoUrl.href) === null || _a === void 0 ? void 0 : _a.split('/')) === null || _b === void 0 ? void 0 : _b.pop()) === null || _c === void 0 ? void 0 : _c.split('?')[0];
const { data: srcsData } = await this.client.get(megacloud.sources.concat(videoId || ''), {
headers: {
Accept: '*/*',
'X-Requested-With': 'XMLHttpRequest',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
Referer: videoUrl.href,
},
});
if (!srcsData) {
throw new Error('Url may have an invalid video id');
}
const encryptedString = srcsData.sources;
if (!srcsData.encrypted && Array.isArray(encryptedString)) {
result.intro = srcsData.intro;
result.outro = srcsData.outro;
result.subtitles = srcsData.tracks.map((s) => ({
url: s.file,
lang: s.label ? s.label : 'Thumbnails',
}));
result.sources = encryptedString.map(s => ({
url: s.file,
type: s.type,
isM3U8: s.file.includes('.m3u8'),
}));
return result;
}
const { data } = await this.client.get(megacloud.script.concat(Date.now().toString()));
const text = data;
if (!text)
throw new Error("Couldn't fetch script to decrypt resource");
const vars = this.extractVariables(text);
const { secret, encryptedSource } = this.getSecret(encryptedString, vars);
const decrypted = this.decrypt(encryptedSource, secret);
try {
const sources = JSON.parse(decrypted);
result.intro = srcsData.intro;
result.outro = srcsData.outro;
result.subtitles = srcsData.tracks.map((s) => ({
url: s.file,
lang: s.label ? s.label : 'Thumbnails',
}));
result.sources = sources.map((s) => ({
url: s.file,
type: s.type,
isM3U8: s.file.includes('.m3u8'),
}));
return result;
}
catch (error) {
throw new Error('Failed to decrypt resource');
}
}
catch (err) {
throw err;
}
}
extractVariables(text) {
// copied from github issue #30 'https://github.com/ghoshRitesh12/aniwatch-api/issues/30'
const regex = /case\s*0x[0-9a-f]+:(?![^;]*=partKey)\s*\w+\s*=\s*(\w+)\s*,\s*\w+\s*=\s*(\w+);/g;
const matches = text.matchAll(regex);
const vars = Array.from(matches, match => {
const matchKey1 = this.matchingKey(match[1], text);
const matchKey2 = this.matchingKey(match[2], text);
try {
return [parseInt(matchKey1, 16), parseInt(matchKey2, 16)];
}
catch (e) {
return [];
}
}).filter(pair => pair.length > 0);
return vars;
}
getSecret(encryptedString, values) {
let secret = '', encryptedSource = '', encryptedSourceArray = encryptedString.split(''), currentIndex = 0;
for (const index of values) {
const start = index[0] + currentIndex;
const end = start + index[1];
for (let i = start; i < end; i++) {
secret += encryptedString[i];
encryptedSourceArray[i] = '';
}
currentIndex += index[1];
}
encryptedSource = encryptedSourceArray.join('');
return { secret, encryptedSource };
}
decrypt(encrypted, keyOrSecret, maybe_iv) {
let key;
let iv;
let contents;
if (maybe_iv) {
key = keyOrSecret;
iv = maybe_iv;
contents = encrypted;
}
else {
// copied from 'https://github.com/brix/crypto-js/issues/468'
const cypher = Buffer.from(encrypted, 'base64');
const salt = cypher.subarray(8, 16);
const password = Buffer.concat([Buffer.from(keyOrSecret, 'binary'), salt]);
const md5Hashes = [];
let digest = password;
for (let i = 0; i < 3; i++) {
md5Hashes[i] = crypto_1.default.createHash('md5').update(digest).digest();
digest = Buffer.concat([md5Hashes[i], password]);
}
key = Buffer.concat([md5Hashes[0], md5Hashes[1]]);
iv = md5Hashes[2];
contents = cypher.subarray(16);
}
const decipher = crypto_1.default.createDecipheriv('aes-256-cbc', key, iv);
const decrypted = decipher.update(contents, typeof contents === 'string' ? 'base64' : undefined, 'utf8') +
decipher.final();
return decrypted;
}
// function copied from github issue #30 'https://github.com/ghoshRitesh12/aniwatch-api/issues/30'
matchingKey(value, script) {
const regex = new RegExp(`,${value}=((?:0x)?([0-9a-fA-F]+))`);
const match = script.match(regex);
if (match) {
return match[1].replace(/^0x/, '');
}
else {
throw new Error('Failed to match the key');
}
}
}
exports.default = MegaCloud;
//# sourceMappingURL=megacloud.js.map