Fix Anikoto encrypted source resolution

This commit is contained in:
Dymas
2026-09-10 09:08:28 +02:00
parent 079488fa5a
commit 6e68f762b7
6 changed files with 158 additions and 9 deletions
+43 -5
View File
@@ -22,9 +22,36 @@
* service of the target website.
*/
const crypto = require("crypto");
const cheerio = require("cheerio");
const baseUrl = "https://anikototv.to";
const megaPlayEncKey = "i?LMTAx0Q6,:}50U";
const megaPlayEncIv = "W0;27ToaUpl_P%'c";
function decodeMegaPlayEnc(value) {
if (!value || typeof value !== "string") return null;
try {
const key = Buffer.alloc(32);
Buffer.from(megaPlayEncKey).copy(key);
const input = Buffer.from(
value.replace(/-/g, "+").replace(/_/g, "/"),
"base64",
);
const decipher = crypto.createDecipheriv(
"aes-256-cbc",
key,
Buffer.from(megaPlayEncIv),
);
const decoded = Buffer.concat([
decipher.update(input),
decipher.final(),
]).toString("utf8");
return JSON.parse(decoded);
} catch (e) {
return null;
}
}
function parsePagination($, defaultPage) {
let totalPages = 1;
@@ -229,11 +256,17 @@ async function fetchServerTypes(dataIds) {
});
const $ = cheerio.load(serverRes.data?.result || "");
const types = new Set();
const serverLinkSelector =
"[data-link-id], li[data-id], a[data-id], button[data-id], .server-item[data-id], .item[data-id]";
$(".servers .type[data-type], [data-type]").each((i, el) => {
const type = String($(el).attr("data-type") || "")
.trim()
.toLowerCase();
if (type) types.add(type);
const hasOwnServerLink =
Boolean($(el).attr("data-link-id")) ||
($(el).is("li,a,button,.server-item,.item") && Boolean($(el).attr("data-id")));
const hasNestedServerLink = $(el).find(serverLinkSelector).length > 0;
if (type && (hasOwnServerLink || hasNestedServerLink)) types.add(type);
});
return types;
} catch (e) {
@@ -406,8 +439,13 @@ async function processServer(server) {
},
);
if (sourcesRes.data && sourcesRes.data.sources) {
const rawSrc = sourcesRes.data.sources;
const decodedSourcesData =
sourcesRes.data?.sources || sourcesRes.data?.file
? sourcesRes.data
: decodeMegaPlayEnc(sourcesRes.data?.enc);
if (decodedSourcesData && (decodedSourcesData.sources || decodedSourcesData.file)) {
const rawSrc = decodedSourcesData.sources || decodedSourcesData.file;
const m3u8Url =
typeof rawSrc === "string"
? rawSrc
@@ -425,7 +463,7 @@ async function processServer(server) {
global.setFallbackReferer(playerReferer);
} catch (e) {}
const subtitles = (sourcesRes.data.tracks || [])
const subtitles = (sourcesRes.data.tracks || decodedSourcesData.tracks || [])
.filter(
(t) => t.file && (!t.kind || t.kind.toLowerCase() !== "thumbnails"),
)
@@ -584,7 +622,7 @@ async function fetchEpisodeSources(episodeIdStr, category = null) {
module.exports = {
name: "anikoto",
version: "5.0.3",
version: "5.0.4",
SearchAnime,
AnimeInfo,
fetchEpisodeSources,