This commit is contained in:
aka paul
2026-05-10 12:58:17 +02:00
parent 7cced4311b
commit 92fa874883
9 changed files with 407 additions and 391 deletions
+104 -115
View File
@@ -121,131 +121,120 @@ async function extractStreamUrl(url) {
try {
const tokenMatch = url.match(/token=([^&]+)/);
if (tokenMatch && tokenMatch[1]) {
const rawToken = tokenMatch[1];
const encryptResponse = await fetchv2(`https://enc-dec.app/api/enc-kai?text=${encodeURIComponent(rawToken)}`);
const encryptData = await encryptResponse.json();
const encryptedToken = encryptData.result;
url = url.replace('&_=ENCRYPT_ME', `&_=${encryptedToken}`);
}
const response = await fetchv2("https://deno-proxies-sznvnpnxwhbv.deno.dev/?url=" + encodeURIComponent(url));
const text = await response.text();
if (!tokenMatch?.[1]) throw new Error("No token found in URL");
const rawToken = tokenMatch[1];
let ajaxResultHtml = "";
try {
const parsedAjax = JSON.parse(text);
ajaxResultHtml = parsedAjax?.result || "";
} catch {}
const encTokenRes = await fetchv2(`https://enc-dec.app/api/enc-kai?text=${encodeURIComponent(rawToken)}`);
const encTokenData = await encTokenRes.json();
const encryptedToken = encTokenData.result;
const cleanedHtml = cleanJsonHtml(text);
const cleanedAjaxResultHtml = cleanJsonHtml(ajaxResultHtml);
const serverHtmlSource = cleanedAjaxResultHtml || cleanedHtml;
const actualUrl = url.replace('&_=ENCRYPT_ME', `&_=${encryptedToken}`);
const subRegex = /<div class="server-items lang-group" data-id="sub"[^>]*>([\s\S]*?)<\/div>/;
const softsubRegex = /<div class="server-items lang-group" data-id="softsub"[^>]*>([\s\S]*?)<\/div>/;
const dubRegex = /<div class="server-items lang-group" data-id="dub"[^>]*>([\s\S]*?)<\/div>/;
const subContent = subRegex.exec(serverHtmlSource)?.[1]?.trim() || "";
const softsubContent = softsubRegex.exec(serverHtmlSource)?.[1]?.trim() || "";
const dubContent = dubRegex.exec(serverHtmlSource)?.[1]?.trim() || "";
const response = await fetchv2(actualUrl);
const text = await response.text();
const extractServerId = (content) => {
if (!content) return null;
const preferred = /<span class="server"[^>]*data-lid="([^"]+)"[^>]*>\s*Server\s*1\s*<\/span>/i.exec(content);
if (preferred?.[1]) return preferred[1];
return /<span class="server"[^>]*data-lid="([^"]+)"/i.exec(content)?.[1] || null;
};
let ajaxResultHtml = "";
try {
const parsedAjax = JSON.parse(text);
ajaxResultHtml = parsedAjax?.result || "";
} catch {}
const serverIdDub = extractServerId(dubContent);
const serverIdSoftsub = extractServerId(softsubContent);
const serverIdSub = extractServerId(subContent);
const cleanedHtml = cleanJsonHtml(text);
const cleanedAjaxResultHtml = cleanJsonHtml(ajaxResultHtml);
const serverHtmlSource = cleanedAjaxResultHtml || cleanedHtml;
const tokenRequestData = [
{ name: "Dub", data: serverIdDub },
{ name: "Softsub", data: serverIdSoftsub },
{ name: "Sub", data: serverIdSub }
].filter(item => item.data);
const tokenPromises = tokenRequestData.map(item =>
fetchv2(`https://enc-dec.app/api/enc-kai?text=${encodeURIComponent(item.data)}`)
.then(res => res.json())
.then(json => ({ name: item.name, data: json.result }))
.catch(err => ({ name: item.name, error: err.toString() }))
);
const tokenResults = await Promise.all(tokenPromises);
const serverIdMap = {
"Dub": serverIdDub,
"Softsub": serverIdSoftsub,
"Sub": serverIdSub
};
const streamUrls = tokenResults.map(result => ({
type: result.name,
url: `https://anikai.to/ajax/links/view?id=${serverIdMap[result.name]}&_=${result.data}`
}));
// Step 1: fetch links/view via proxy
const streamResponses = await Promise.all(
streamUrls.map(async ({ type, url }) => {
try {
const res = await fetchv2("https://deno-proxies-sznvnpnxwhbv.deno.dev/?url=" + encodeURIComponent(url));
const json = await res.json();
return { type, result: json.result };
} catch (error) {
console.log(`Error fetching ${type} stream:`, error);
return { type, result: null };
}
})
);
// Step 2: decrypt with browser UA — no encodeURIComponent
const decryptPromises = streamResponses
.filter(item => item.result)
.map(item =>
fetchv2(`https://enc-dec.app/api/dec-kai?text=${item.result}`, headers)
.then(res => res.json())
.then(json => {
console.log(`decrypted ${item.type} URL:`, json.result?.url);
return { name: item.type, url: json.result?.url || null };
})
.catch(err => ({ name: item.type, url: null }))
);
const decryptResults = await Promise.all(decryptPromises);
const urlMap = Object.fromEntries(decryptResults.map(i => [i.name, i.url]));
const decryptedSub = urlMap.Sub || urlMap.Dub || urlMap.Softsub;
console.log("Using URL:", decryptedSub);
if (decryptedSub) {
const mediaResponse = await fetchv2(decryptedSub.replace("/e/", "/media/"), headers);
const responseJson = await mediaResponse.json();
const result = responseJson?.result;
const postData = {
"text": result,
"agent": headers["User-Agent"]
const extractServerIds = (type) => {
const regex = new RegExp(`<div class="server-items lang-group" data-id="${type}"[^>]*>([\\s\\S]*?)<\\/div>`);
const content = regex.exec(serverHtmlSource)?.[1] ?? "";
const spanRegex = /<span class="server"[^>]*data-lid="([^"]+)"[^>]*>/g;
const ids = [];
let match;
while ((match = spanRegex.exec(content)) !== null) ids.push(match[1]);
return ids.length > 1 ? ids[1] : ids[0] ?? null;
};
const finalResponse = await fetchv2(
"https://enc-dec.app/api/dec-mega",
{ "Content-Type": "application/json" },
"POST",
JSON.stringify(postData)
);
const finalJson = await finalResponse.json();
console.log("dec-mega result:", finalJson);
const m3u8Link = finalJson?.result?.sources?.[0]?.file;
const types = ["sub"];
return m3u8Link;
const servers = types
.map(type => ({ type, lid: extractServerIds(type) }))
.filter(s => s.lid);
const streams = [];
const subtitles = [];
await Promise.all(servers.map(async ({ type, lid }) => {
try {
const decLidRes = await fetchv2(`https://enc-dec.app/api/enc-kai?text=${encodeURIComponent(lid)}`);
const decLidData = await decLidRes.json();
const decodedLid = decLidData.result;
const viewUrl = `https://anikai.to/ajax/links/view?id=${lid}&_=${decodedLid}`;
const viewRes = await fetchv2(viewUrl);
const viewJson = await viewRes.json();
const encodedResult = viewJson.result;
const decRes = await fetchv2(
"https://enc-dec.app/api/dec-kai",
{ "Content-Type": "application/json" },
"POST",
JSON.stringify({ text: encodedResult })
);
const decJson = await decRes.json();
let iframeUrl = decJson.result?.url ?? null;
if (!iframeUrl) return;
if (iframeUrl.includes("anikai.to/iframe")) {
const iframePageRes = await fetchv2(iframeUrl, headers);
const iframePageText = await iframePageRes.text();
const iframeSrcMatch = iframePageText.match(/<iframe[^>]+src="([^"]+)"/i);
if (iframeSrcMatch && iframeSrcMatch[1]) {
iframeUrl = iframeSrcMatch[1];
}
}
const mediaUrl = iframeUrl.replace("/e/", "/media/").replace("/e2/", "/media/");
const mediaRes = await fetchv2(mediaUrl, headers);
const mediaJson = await mediaRes.json();
const encodedM3u8 = mediaJson?.result;
if (!encodedM3u8) return;
const finalRes = await fetchv2(
"https://enc-dec.app/api/dec-mega",
{ "Content-Type": "application/json" },
"POST",
JSON.stringify({ text: encodedM3u8, agent: headers["User-Agent"] })
);
const finalJson = await finalRes.json();
const sources = finalJson?.result?.sources ?? [];
const tracks = finalJson?.result?.tracks ?? [];
const file = sources[0]?.file ?? null;
if (file) {
const titleMap = { sub: "Hardsub English" };
streams.push({ title: titleMap[type] || type, streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + file });
}
for (const track of tracks) {
if (track.file && track.label) {
subtitles.push({ url: track.file, language: track.label });
}
}
} catch (e) {
console.log(`[extractStreamUrl] error for ${type}:`, e.toString());
}
}));
return streams.length > 0 ? streams[0].streamUrl : "error";
} catch (error) {
console.error("Animekai fetch error:" + error);
return "https://error.org";
}
return "error";
} catch (error) {
console.log("Fetch error:" + error);
return "https://error.org";
}
}
function cleanHtmlSymbols(string) {
+1 -1
View File
@@ -5,7 +5,7 @@
"name": "50/50",
"icon": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3122kQwublLkZ6rf1fEpUP79BxZOFmH9BSA&s"
},
"version": "1.1.3",
"version": "1.1.4",
"language": "English",
"streamType": "HLS",
"quality": "1080p",