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
+100
View File
@@ -6,6 +6,7 @@ import importlib.util
import io
import json
import os
import subprocess
import sys
import tempfile
import threading
@@ -4904,6 +4905,105 @@ https://shard-102.snapcdn.top/anime/show/episode/seg-f1-00083.css
self.assertEqual([source["server"] for source in sources], ["HD-1", "HD-2"])
def test_concise_error_keeps_first_provider_error_line(self):
error = RuntimeError("Error: Request failed with status code 403\n at async main")
self.assertEqual(provider_downloader.concise_error(error), "Error: Request failed with status code 403")
def test_anikoto_episode_language_probe_ignores_empty_dub_group(self):
script = r"""
global.axios = {
get: async (url) => {
if (url.includes("/ajax/episode/list/123")) {
return {
data: {
result: '<div class="filter type"><button data-value="dub">Dub</button></div><a data-id="ep4" data-ids="servers4" data-num="4" title="Episode 4"></a>'
}
};
}
if (url.includes("/ajax/server/list?servers=servers4")) {
return {
data: {
result: '<div class="servers"><div class="type" data-type="sub"><ul><li data-id="s1" data-link-id="l1">HD-1</li></ul></div><div class="type" data-type="dub"><ul></ul></div></div>'
}
};
}
throw new Error(`unexpected url ${url}`);
}
};
const provider = require("./providers/extensions/Anime/anikoto.js");
provider.fetchEpisode("123").then((data) => {
console.log(JSON.stringify(data.episodes[0].langs));
}).catch((err) => {
console.error(err && err.stack ? err.stack : err);
process.exit(1);
});
"""
proc = subprocess.run(
["node", "-e", script],
cwd=ROOT,
text=True,
capture_output=True,
check=False,
)
self.assertEqual(proc.returncode, 0, proc.stderr)
self.assertEqual(json.loads(proc.stdout), ["sub"])
def test_anikoto_process_server_decodes_encrypted_megaplay_sources(self):
script = r"""
const encryptedPayload = "wdeBruh3qqn_i5wUNnyaPQQl1wp7r0SrL6KQPNFd24_nH3bjQ-zZlyDs9ryZRqOqluMFxGXpzqi4xA9i5N3T4SDfaQAFzkb6BCj2QorrmxfAd1_nBhcma5SSJZ9rSUWBrBzsNlbhi3a9aCjlekwZGRoHmqEcH3gn2pl0RNQ2JsM";
global.setDynamicReferer = () => {};
global.setFallbackReferer = () => {};
global.axios = {
get: async (url) => {
if (url.includes("/ajax/server?get=dub-link")) {
return { data: { result: { url: "https://megaplay.buzz/stream/s-2/664726/dub" } } };
}
if (url.includes("/stream/s-2/664726/dub")) {
return {
data: `
<div id="megaplay-player" data-id="179510"></div>
<script>
const settings = {
type: 'dub',
cidu : '6aa1ade0620e3',
};
</script>
`
};
}
if (url.includes("/stream/getSources?id=179510&type=dub&cidu=6aa1ade0620e3")) {
return { data: { enc: encryptedPayload, tracks: [{ file: "https://cdn.example/sub.vtt", label: "English" }] } };
}
throw new Error(`unexpected url ${url}`);
}
};
const provider = require("./providers/extensions/Anime/anikoto.js");
provider.processServer({ name: "HD-2", type: "dub", linkId: "dub-link" }).then((source) => {
console.log(JSON.stringify(source));
}).catch((err) => {
console.error(err && err.stack ? err.stack : err);
process.exit(1);
});
"""
proc = subprocess.run(
["node", "-e", script],
cwd=ROOT,
text=True,
capture_output=True,
check=False,
)
self.assertEqual(proc.returncode, 0, proc.stderr)
source = json.loads(proc.stdout)
self.assertEqual(
source["url"],
"https://cdn.imgnex.top/anime/a7e93c78e547abf7dce1e0f3f0b77977/0eb80d76b8867b42b6e6e62ebe515704/master.m3u8",
)
self.assertEqual(source["type"], "dub")
self.assertEqual(source["subtitles"][0]["url"], "https://cdn.example/sub.vtt")
def test_provider_downloader_tries_next_same_provider_source_after_failure(self):
calls = []