]*>([\s\S]*?)<\/div>/;
const dubRegex = /
]*>([\s\S]*?)<\/div>/;
const subMatch = subRegex.exec(serverHtmlSource);
const softsubMatch = softsubRegex.exec(serverHtmlSource);
const dubMatch = dubRegex.exec(serverHtmlSource);
const subContent = subMatch ? subMatch[1].trim() : "";
const softsubContent = softsubMatch ? softsubMatch[1].trim() : "";
const dubContent = dubMatch ? dubMatch[1].trim() : "";
const extractServerId = (content) => {
if (!content) return null;
const preferred = /]*data-lid="([^"]+)"[^>]*>\s*Server\s*1\s*<\/span>/i.exec(content);
if (preferred?.[1]) return preferred[1];
return /]*data-lid="([^"]+)"/i.exec(content)?.[1] || null;
};
const serverIdDub = extractServerId(dubContent);
const serverIdSoftsub = extractServerId(softsubContent);
const serverIdSub = extractServerId(subContent);
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}`
}));
const streamResponses = await Promise.all(
streamUrls.map(async ({ type, url }) => {
try {
const res = await fetchv2(url);
const json = await res.json();
return { type, result: json.result };
} catch {
return { type, result: null };
}
})
);
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 => ({ name: item.type, url: json.result?.url || null }))
.catch(() => ({ 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;
const decryptedDub = urlMap.Dub;
const decryptedRaw = urlMap.Softsub;
async function getStream(url) {
try {
const response = await fetchv2(url.replace("/e/", "/media/"), headers);
const responseJson = await response.json();
const result = responseJson?.result;
const finalResponse = await fetchv2(
"https://enc-dec.app/api/dec-mega",
{ "Content-Type": "application/json" },
"POST",
JSON.stringify({ text: result, agent: headers["User-Agent"] })
);
const finalJson = await finalResponse.json();
return finalJson?.result?.sources?.[0]?.file || null;
} catch {
return null;
}
}
const [subStream, dubStream, rawStream] = await Promise.all([
decryptedSub ? getStream(decryptedSub) : Promise.resolve(null),
decryptedDub ? getStream(decryptedDub) : Promise.resolve(null),
decryptedRaw ? getStream(decryptedRaw) : Promise.resolve(null)
]);
console.log("[extractStreamUrl] Sub:", subStream, "Dub:", dubStream, "Softsub:", rawStream);
const streams = [];
if (subStream) streams.push({ title: "Hardsub English", streamUrl: subStream });
if (dubStream) streams.push({ title: "Dubbed English", streamUrl: dubStream });
if (rawStream) streams.push({ title: "Original audio", streamUrl: rawStream });
return JSON.stringify({ streams, subtitles: "" });
} catch (error) {
console.error("Animekai fetch error:" + error);
return "https://error.org";
}
}
function cleanHtmlSymbols(string) {
if (!string) {
return "";
}
return string
.replace(/’/g, "'")
.replace(/–/g, "-")
.replace(/[0-9]+;/g, "")
.replace(/\r?\n|\r/g, " ")
.replace(/\s+/g, " ")
.trim();
}
function cleanJsonHtml(jsonHtml) {
if (!jsonHtml) {
return "";
}
return jsonHtml
.replace(/\\"/g, "\"")
.replace(/\\'/g, "'")
.replace(/\\\\/g, "\\")
.replace(/\\n/g, "\n")
.replace(/\\t/g, "\t")
.replace(/\\r/g, "\r");
}
function decodeHtmlEntities(text) {
if (!text) {
return "";
}
return text
.replace(/'/g, "'")
.replace(/"/g, "\"")
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/ /g, " ");
}