update
Fetch and Save Remote Content / fetch (push) Successful in 39s
Sync Versions to index.json / sync-versions (push) Failing after 54s

This commit is contained in:
aka paul
2026-05-27 20:30:23 +02:00
parent caffaabc88
commit 597f279e49
113 changed files with 1207 additions and 980 deletions
+126 -63
View File
@@ -124,79 +124,142 @@ async function extractStreamUrl(url) {
const responseText = await ddosInterceptor.fetchWithBypass(url);
const dataText = await responseText.text();
const buttonMatches = dataText.match(/<button[^>]*data-src="([^"]*)"[^>]*>/g);
if (!buttonMatches) {
const buttonRegex = /<button[^>]*data-src="([^"]+)"[^>]*data-fansub="([^"]+)"[^>]*data-resolution="([^"]+)"[^>]*data-audio="([^"]+)"[^>]*>/g;
const buttons = [];
let match;
while ((match = buttonRegex.exec(dataText)) !== null) {
buttons.push({
src: match[1],
fansub: match[2],
resolution: match[3],
audio: match[4]
});
}
if (buttons.length === 0) {
const buttonMatches = dataText.match(/<button[^>]*data-src="([^"]*)"[^>]*>/g);
if (!buttonMatches) {
return JSON.stringify({ streams: [], subtitle: "" });
}
return JSON.stringify({ streams: [], subtitle: "" });
}
const streamPromises = buttonMatches.map(async (buttonHtml) => {
const srcMatch = buttonHtml.match(/data-src="([^"]*)"/);
const resMatch = buttonHtml.match(/data-resolution="([^"]*)"/);
const audioMatch = buttonHtml.match(/data-audio="([^"]*)"/);
const fansubMatch = buttonHtml.match(/data-fansub="([^"]*)"/);
if (!srcMatch || !srcMatch[1].includes('kwik.cx')) return null;
const kwikUrl = srcMatch[1];
const resolution = resMatch ? resMatch[1] : "Unknown";
const audio = audioMatch ? audioMatch[1] : "jpn";
const fansub = fansubMatch ? fansubMatch[1] : "Unknown";
try {
const html = await fetchv2(kwikUrl).then(r => r.text());
const scriptMatch = html.match(/<script>(.*?)<\/script>/s);
if (scriptMatch) {
const scriptContent = scriptMatch[1];
let unpacked = null;
if (scriptContent.includes('));eval(')) {
const parts = scriptContent.split('));eval(');
if (parts.length === 2) {
const layer2Packed = parts[1].substring(0, parts[1].length - 1);
unpacked = unpack(layer2Packed);
}
} else {
unpacked = unpack(scriptContent);
}
if (unpacked) {
const urlMatch = unpacked.match(/const source=\\?['"]([^'"]+)['"]/) ||
unpacked.match(/https:\/\/[^\s'";]+\.m3u8/);
if (urlMatch) {
let hlsUrl = (urlMatch[1] || urlMatch[0]).replace(/\\+$/, '');
const audioType = audio === "eng" ? "Dub" : "Hardsub";
const title = `${resolution}p • ${audioType}`;
hlsUrl = hlsUrl
.replace("/stream/", "/hls/")
.replace("uwu.m3u8", "owo.m3u8");
return {
title: title,
streamUrl: hlsUrl,
headers: {
"Referer": "https://kwik.cx/",
"Origin": "https://kwik.cx"
}
};
const deepUnpack = (source) => {
let decoded = source;
let safety = 0;
while (/eval\(function\(p,a,c,k,e,d\)/.test(decoded) && safety < 5) {
try {
decoded = unpack(decoded);
safety++;
} catch (e) {
console.warn("[Animepahe] Unpack error at depth " + safety + ": " + e.message);
break;
}
}
return decoded;
};
const streamPromises = buttons.map(async (btn) => {
const kwikUrl = btn.src;
const audioType = btn.audio === "jpn" ? "Hardsub" : "Dub";
const title = btn.resolution + "p • " + audioType;
try {
const headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
"Referer": "https://animepahe.pw/",
"Origin": "https://kwik.cx",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
};
const resp = await fetchv2(kwikUrl, headers);
const html = await resp.text();
const evalRegex = /eval\(function\(p,a,c,k,e,d\)\{[^}]*\}\('[^']*',\d+,\d+,'[^']*'\.split\('\|'\)[^)]*\)/g;
const evalBlocks = [...html.matchAll(evalRegex)].map(m => m[0]);
if (evalBlocks.length === 0) {
const scriptMatch = html.match(/<script>(.*?)<\/script>/s);
if (scriptMatch) {
const scriptContent = scriptMatch[1];
let unpacked = null;
if (scriptContent.includes('));eval(')) {
const parts = scriptContent.split('));eval(');
if (parts.length === 2) {
const layer2Packed = parts[1].substring(0, parts[1].length - 1);
try { unpacked = unpack(layer2Packed); } catch(e) {}
}
} else {
try { unpacked = unpack(scriptContent); } catch(e) {}
}
if (unpacked) {
const urlMatch = unpacked.match(/const source=\\?['"]([^'"]+)['"]/) ||
unpacked.match(/https:\/\/[^\s'";]+\.m3u8/);
if (urlMatch) {
let hlsUrl = (urlMatch[1] || urlMatch[0]).replace(/\\+$/, '');
hlsUrl = hlsUrl.replace("/stream/", "/hls/").replace("uwu.m3u8", "owo.m3u8");
return {
title: title,
streamUrl: hlsUrl,
headers: { "Referer": "https://kwik.cx/", "Origin": "https://kwik.cx" }
};
}
}
}
return null;
}
let hlsUrl = null;
for (const block of evalBlocks) {
try {
const unpacked = deepUnpack(block);
console.log("[Animepahe] Unpacked snippet: " + unpacked.substring(0, 150));
const sourceMatch = unpacked.match(/(?:source\s*=\s*['"]([^'"]+\.m3u8)['"])/i);
if (sourceMatch) {
hlsUrl = sourceMatch[1];
break;
}
const directMatch = unpacked.match(/https?:\/\/[^\s'"<>]+\.m3u8[^\s'"<>]*/i);
if (directMatch) {
hlsUrl = directMatch[0];
break;
}
} catch (e) {
}
}
if (!hlsUrl) {
return null;
}
hlsUrl = hlsUrl.replace(/\\+$/, '');
hlsUrl = hlsUrl.replace("/stream/", "/hls/").replace("uwu.m3u8", "owo.m3u8");
return {
title: title,
streamUrl: hlsUrl,
headers: { "Referer": "https://kwik.cx/", "Origin": "https://kwik.cx" }
};
} catch (e) {
// Continue to next
return null;
}
return null;
});
const streamResults = await Promise.all(streamPromises);
const streams = streamResults.filter(s => s !== null);
return JSON.stringify({
streams: streams,
subtitle: ""
const results = await Promise.allSettled(streamPromises);
const streams = results
.filter(r => r.status === "fulfilled" && r.value)
.map(r => r.value);
streams.sort((a, b) => {
const aIsSub = a.title.includes("Hardsub") ? 0 : 1;
const bIsSub = b.title.includes("Hardsub") ? 0 : 1;
if (aIsSub !== bIsSub) return aIsSub - bIsSub;
const aRes = parseInt(a.title.match(/(\d+)p/)?.[1] || 0);
const bRes = parseInt(b.title.match(/(\d+)p/)?.[1] || 0);
return bRes - aRes;
});
const finalResult = JSON.stringify({ streams: streams, subtitle: "" });
return finalResult;
} catch (err) {
return JSON.stringify({ streams: [], subtitle: "" });
}