mirror of
https://git.luna-app.eu/50n50/sources
synced 2025-12-21 21:26:19 +01:00
Upload
This commit is contained in:
commit
09c423e95a
276 changed files with 54396 additions and 0 deletions
307
animekai/dub/animekai.js
Normal file
307
animekai/dub/animekai.js
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
async function searchResults(query) {
|
||||
const encodeQuery = keyword => encodeURIComponent(keyword);
|
||||
const searchBaseUrl = "https://animekai.to/browser?keyword=";
|
||||
const baseUrl = "https://animekai.to";
|
||||
|
||||
const posterHrefRegex = /href="[^"]*" class="poster"/g;
|
||||
const titleRegex = /class="title"[^>]*title="[^"]*"/g;
|
||||
const imageRegex = /data-src="[^"]*"/g;
|
||||
const extractHrefRegex = /href="([^"]*)"/;
|
||||
const extractImageRegex = /data-src="([^"]*)"/;
|
||||
const extractTitleRegex = /title="([^"]*)"/;
|
||||
|
||||
try {
|
||||
const encodedQuery = encodeQuery(query);
|
||||
const searchUrl = searchBaseUrl + encodedQuery;
|
||||
const response = await fetchv2(searchUrl);
|
||||
const htmlText = await response.text();
|
||||
|
||||
const results = [];
|
||||
const posterMatches = htmlText.match(posterHrefRegex) || [];
|
||||
const titleMatches = htmlText.match(titleRegex) || [];
|
||||
const imageMatches = htmlText.match(imageRegex) || [];
|
||||
|
||||
const minLength = Math.min(posterMatches.length, titleMatches.length, imageMatches.length);
|
||||
|
||||
for (let index = 0; index < minLength; index++) {
|
||||
const hrefMatch = posterMatches[index].match(extractHrefRegex);
|
||||
const fullHref = hrefMatch ?
|
||||
(hrefMatch[1].startsWith("http") ? hrefMatch[1] : baseUrl + hrefMatch[1]) :
|
||||
null;
|
||||
|
||||
const imageMatch = imageMatches[index].match(extractImageRegex);
|
||||
const imageSrc = imageMatch ? imageMatch[1] : null;
|
||||
|
||||
const titleMatch = titleMatches[index].match(extractTitleRegex);
|
||||
const cleanTitle = titleMatch ?
|
||||
decodeHtmlEntities(titleMatch[1]) :
|
||||
null;
|
||||
|
||||
if (fullHref && imageSrc && cleanTitle) {
|
||||
results.push({
|
||||
href: fullHref,
|
||||
image: imageSrc,
|
||||
title: cleanTitle
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return JSON.stringify(results);
|
||||
} catch (error) {
|
||||
return JSON.stringify([{
|
||||
href: "",
|
||||
image: "",
|
||||
title: "Search failed: " + error.message
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
async function extractDetails(url) {
|
||||
try {
|
||||
const response = await fetchv2(url);
|
||||
const htmlText = await response.text();
|
||||
console.log(htmlText);
|
||||
|
||||
const descriptionMatch = (/<div class="desc text-expand">([\s\S]*?)<\/div>/.exec(htmlText) || [])[1];
|
||||
const aliasesMatch = (/<small class="al-title text-expand">([\s\S]*?)<\/small>/.exec(htmlText) || [])[1];
|
||||
|
||||
return JSON.stringify([{
|
||||
description: descriptionMatch ? cleanHtmlSymbols(descriptionMatch) : "Not available",
|
||||
aliases: aliasesMatch ? cleanHtmlSymbols(aliasesMatch) : "Not available",
|
||||
airdate: "If stream doesn't load try later or disable VPN/DNS"
|
||||
}]);
|
||||
} catch (error) {
|
||||
console.error("Error fetching details:" + error);
|
||||
return [{
|
||||
description: "Error loading description",
|
||||
aliases: "Aliases: Unknown",
|
||||
airdate: "Aired: Unknown"
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
async function extractEpisodes(animeUrl) {
|
||||
try {
|
||||
const response = await fetchv2(animeUrl);
|
||||
const htmlText = await response.text();
|
||||
|
||||
const animeIdMatch = (htmlText.match(/<div class="rate-box"[^>]*data-id="([^"]+)"/) || [])[1];
|
||||
if (!animeIdMatch) {
|
||||
return [{
|
||||
error: "AniID not found"
|
||||
}];
|
||||
}
|
||||
|
||||
const tokenResponse = await fetchv2(`https://ilovekai.simplepostrequest.workers.dev/?ilovefeet=${encodeURIComponent(animeIdMatch)}`);
|
||||
const token = await tokenResponse.text();
|
||||
|
||||
const episodeListUrl = `https://animekai.to/ajax/episodes/list?ani_id=${animeIdMatch}&_=${token}`;
|
||||
|
||||
const episodeListResponse = await fetchv2(episodeListUrl);
|
||||
const episodeListData = await episodeListResponse.json();
|
||||
const cleanedHtml = cleanJsonHtml(episodeListData.result);
|
||||
|
||||
const episodeRegex = /<a[^>]+num="([^"]+)"[^>]+token="([^"]+)"[^>]*>/g;
|
||||
const episodeMatches = [...cleanedHtml.matchAll(episodeRegex)];
|
||||
|
||||
const episodeData = episodeMatches.map(([_, episodeNum, episodeToken]) => ({
|
||||
name: `Episode ${episodeNum}`,
|
||||
data: episodeToken
|
||||
}));
|
||||
|
||||
const batchResponse = await fetchv2(
|
||||
"https://ilovekai.simplepostrequest.workers.dev/?ilovefeet",
|
||||
{},
|
||||
"POST",
|
||||
JSON.stringify(episodeData)
|
||||
);
|
||||
|
||||
const batchResults = await batchResponse.json();
|
||||
|
||||
const episodes = batchResults.map((result, index) => ({
|
||||
number: parseInt(episodeMatches[index][1], 10),
|
||||
href: `https://animekai.to/ajax/links/list?token=${episodeMatches[index][2]}&_=${result.data}`
|
||||
}));
|
||||
|
||||
return JSON.stringify(episodes);
|
||||
} catch (err) {
|
||||
console.error("Error fetching episodes:" + err);
|
||||
return [{
|
||||
number: 1,
|
||||
href: "Error fetching episodes"
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
async function extractStreamUrl(url) {
|
||||
try {
|
||||
const fetchUrl = `${url}`;
|
||||
const response = await fetchv2(fetchUrl);
|
||||
const text = await response.text();
|
||||
const cleanedHtml = cleanJsonHtml(text);
|
||||
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 subMatch = subRegex.exec(cleanedHtml);
|
||||
const softsubMatch = softsubRegex.exec(cleanedHtml);
|
||||
const dubMatch = dubRegex.exec(cleanedHtml);
|
||||
const subContent = subMatch ? subMatch[1].trim() : "";
|
||||
const softsubContent = softsubMatch ? softsubMatch[1].trim() : "";
|
||||
const dubContent = dubMatch ? dubMatch[1].trim() : "";
|
||||
const serverSpanRegex = /<span class="server"[^>]*data-lid="([^"]+)"[^>]*>Server 1<\/span>/;
|
||||
const serverIdDub = serverSpanRegex.exec(dubContent)?.[1];
|
||||
const serverIdSoftsub = serverSpanRegex.exec(softsubContent)?.[1];
|
||||
const serverIdSub = serverSpanRegex.exec(subContent)?.[1];
|
||||
|
||||
const tokenRequestData = [
|
||||
{ name: "Dub", data: serverIdDub },
|
||||
{ name: "Softsub", data: serverIdSoftsub },
|
||||
{ name: "Sub", data: serverIdSub }
|
||||
].filter(item => item.data);
|
||||
|
||||
const tokenBatchResponse = await fetchv2(
|
||||
"https://ilovekai.simplepostrequest.workers.dev/?ilovefeet",
|
||||
{},
|
||||
"POST",
|
||||
JSON.stringify(tokenRequestData)
|
||||
);
|
||||
const tokenResults = await tokenBatchResponse.json();
|
||||
|
||||
const streamUrls = tokenResults.map(result => {
|
||||
const serverIdMap = {
|
||||
"Dub": serverIdDub,
|
||||
"Softsub": serverIdSoftsub,
|
||||
"Sub": serverIdSub
|
||||
};
|
||||
return {
|
||||
type: result.name,
|
||||
url: `https://animekai.to/ajax/links/view?id=${serverIdMap[result.name]}&_=${result.data}`
|
||||
};
|
||||
});
|
||||
|
||||
const processStreams = async (streamUrls) => {
|
||||
const streamResponses = await Promise.all(
|
||||
streamUrls.map(async ({ type, url }) => {
|
||||
try {
|
||||
const res = await fetchv2(url);
|
||||
const json = await res.json();
|
||||
return {
|
||||
type: type,
|
||||
result: json.result
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(`Error fetching ${type} stream:`, error);
|
||||
return {
|
||||
type: type,
|
||||
result: null
|
||||
};
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const decryptRequestData = streamResponses
|
||||
.filter(item => item.result)
|
||||
.map(item => ({
|
||||
name: item.type,
|
||||
data: item.result
|
||||
}));
|
||||
|
||||
if (decryptRequestData.length === 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const decryptBatchResponse = await fetchv2(
|
||||
"https://ilovekai.simplepostrequest.workers.dev/?ilovearmpits",
|
||||
{},
|
||||
"POST",
|
||||
JSON.stringify(decryptRequestData)
|
||||
);
|
||||
const decryptResults = await decryptBatchResponse.json();
|
||||
|
||||
const finalResults = {};
|
||||
decryptResults.forEach(result => {
|
||||
try {
|
||||
const parsed = JSON.parse(result.data);
|
||||
finalResults[result.name] = parsed.url;
|
||||
console.log(`decrypted${result.name} URL:` + parsed.url);
|
||||
} catch (error) {
|
||||
console.log(`Error parsing ${result.name} result:`, error);
|
||||
finalResults[result.name] = null;
|
||||
}
|
||||
});
|
||||
|
||||
return finalResults;
|
||||
};
|
||||
|
||||
const decryptedUrls = await processStreams(streamUrls);
|
||||
const decryptedDub = decryptedUrls.Dub || decryptedUrls.Sub || decryptedUrls.Softsub;
|
||||
|
||||
console.log(decryptedDub);
|
||||
const headers = {
|
||||
"Referer": "https://animekai.to/",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"
|
||||
};
|
||||
|
||||
if (decryptedDub) {
|
||||
const response = await fetchv2(decryptedDub.replace("/e/", "/media/"), headers);
|
||||
const responseJson = await response.json();
|
||||
|
||||
const result = responseJson?.result;
|
||||
|
||||
const postData = {
|
||||
"text": result,
|
||||
"Useragent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"
|
||||
}
|
||||
|
||||
const finalResponse = await fetchv2("https://ilovekai.simplepostrequest.workers.dev/ilovebush", {}, "POST", JSON.stringify(postData));
|
||||
const finalJson = await finalResponse.json();
|
||||
const m3u8Link = finalJson?.result?.sources?.[0]?.file;
|
||||
|
||||
return m3u8Link;
|
||||
}
|
||||
|
||||
return "error";
|
||||
} catch (error) {
|
||||
console.log("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, " ");
|
||||
}
|
||||
20
animekai/dub/animekai.json
Normal file
20
animekai/dub/animekai.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"sourceName": "AnimeKai (Dub)",
|
||||
"iconUrl": "https://apktodo.io/uploads/2025/5/animekai-icon.jpg",
|
||||
"author": {
|
||||
"name": "50/50",
|
||||
"icon": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3122kQwublLkZ6rf1fEpUP79BxZOFmH9BSA&s"
|
||||
},
|
||||
"version": "1.0.3",
|
||||
"language": "English",
|
||||
"streamType": "HLS",
|
||||
"quality": "1080p",
|
||||
"baseUrl": "https://animekai.to/",
|
||||
"searchBaseUrl": "https://animekai.to/",
|
||||
"scriptUrl": "https://gitlab.com/50n50/sources/-/raw/main/animekai/dub/animekai.js",
|
||||
"type": "anime",
|
||||
"asyncJS": true,
|
||||
"softsub": false,
|
||||
"downloadSupport": true,
|
||||
"note": "Make sure you're on the latest version of Sora."
|
||||
}
|
||||
307
animekai/hardsub/animekai.js
Normal file
307
animekai/hardsub/animekai.js
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
async function searchResults(query) {
|
||||
const encodeQuery = keyword => encodeURIComponent(keyword);
|
||||
const searchBaseUrl = "https://animekai.to/browser?keyword=";
|
||||
const baseUrl = "https://animekai.to";
|
||||
|
||||
const posterHrefRegex = /href="[^"]*" class="poster"/g;
|
||||
const titleRegex = /class="title"[^>]*title="[^"]*"/g;
|
||||
const imageRegex = /data-src="[^"]*"/g;
|
||||
const extractHrefRegex = /href="([^"]*)"/;
|
||||
const extractImageRegex = /data-src="([^"]*)"/;
|
||||
const extractTitleRegex = /title="([^"]*)"/;
|
||||
|
||||
try {
|
||||
const encodedQuery = encodeQuery(query);
|
||||
const searchUrl = searchBaseUrl + encodedQuery;
|
||||
const response = await fetchv2(searchUrl);
|
||||
const htmlText = await response.text();
|
||||
|
||||
const results = [];
|
||||
const posterMatches = htmlText.match(posterHrefRegex) || [];
|
||||
const titleMatches = htmlText.match(titleRegex) || [];
|
||||
const imageMatches = htmlText.match(imageRegex) || [];
|
||||
|
||||
const minLength = Math.min(posterMatches.length, titleMatches.length, imageMatches.length);
|
||||
|
||||
for (let index = 0; index < minLength; index++) {
|
||||
const hrefMatch = posterMatches[index].match(extractHrefRegex);
|
||||
const fullHref = hrefMatch ?
|
||||
(hrefMatch[1].startsWith("http") ? hrefMatch[1] : baseUrl + hrefMatch[1]) :
|
||||
null;
|
||||
|
||||
const imageMatch = imageMatches[index].match(extractImageRegex);
|
||||
const imageSrc = imageMatch ? imageMatch[1] : null;
|
||||
|
||||
const titleMatch = titleMatches[index].match(extractTitleRegex);
|
||||
const cleanTitle = titleMatch ?
|
||||
decodeHtmlEntities(titleMatch[1]) :
|
||||
null;
|
||||
|
||||
if (fullHref && imageSrc && cleanTitle) {
|
||||
results.push({
|
||||
href: fullHref,
|
||||
image: imageSrc,
|
||||
title: cleanTitle
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return JSON.stringify(results);
|
||||
} catch (error) {
|
||||
return JSON.stringify([{
|
||||
href: "",
|
||||
image: "",
|
||||
title: "Search failed: " + error.message
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
async function extractDetails(url) {
|
||||
try {
|
||||
const response = await fetchv2(url);
|
||||
const htmlText = await response.text();
|
||||
console.log(htmlText);
|
||||
|
||||
const descriptionMatch = (/<div class="desc text-expand">([\s\S]*?)<\/div>/.exec(htmlText) || [])[1];
|
||||
const aliasesMatch = (/<small class="al-title text-expand">([\s\S]*?)<\/small>/.exec(htmlText) || [])[1];
|
||||
|
||||
return JSON.stringify([{
|
||||
description: descriptionMatch ? cleanHtmlSymbols(descriptionMatch) : "Not available",
|
||||
aliases: aliasesMatch ? cleanHtmlSymbols(aliasesMatch) : "Not available",
|
||||
airdate: "If stream doesn't load try later or disable VPN/DNS"
|
||||
}]);
|
||||
} catch (error) {
|
||||
console.error("Error fetching details:" + error);
|
||||
return [{
|
||||
description: "Error loading description",
|
||||
aliases: "Aliases: Unknown",
|
||||
airdate: "Aired: Unknown"
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
async function extractEpisodes(animeUrl) {
|
||||
try {
|
||||
const response = await fetchv2(animeUrl);
|
||||
const htmlText = await response.text();
|
||||
|
||||
const animeIdMatch = (htmlText.match(/<div class="rate-box"[^>]*data-id="([^"]+)"/) || [])[1];
|
||||
if (!animeIdMatch) {
|
||||
return [{
|
||||
error: "AniID not found"
|
||||
}];
|
||||
}
|
||||
|
||||
const tokenResponse = await fetchv2(`https://ilovekai.simplepostrequest.workers.dev/?ilovefeet=${encodeURIComponent(animeIdMatch)}`);
|
||||
const token = await tokenResponse.text();
|
||||
|
||||
const episodeListUrl = `https://animekai.to/ajax/episodes/list?ani_id=${animeIdMatch}&_=${token}`;
|
||||
|
||||
const episodeListResponse = await fetchv2(episodeListUrl);
|
||||
const episodeListData = await episodeListResponse.json();
|
||||
const cleanedHtml = cleanJsonHtml(episodeListData.result);
|
||||
|
||||
const episodeRegex = /<a[^>]+num="([^"]+)"[^>]+token="([^"]+)"[^>]*>/g;
|
||||
const episodeMatches = [...cleanedHtml.matchAll(episodeRegex)];
|
||||
|
||||
const episodeData = episodeMatches.map(([_, episodeNum, episodeToken]) => ({
|
||||
name: `Episode ${episodeNum}`,
|
||||
data: episodeToken
|
||||
}));
|
||||
|
||||
const batchResponse = await fetchv2(
|
||||
"https://ilovekai.simplepostrequest.workers.dev/?ilovefeet",
|
||||
{},
|
||||
"POST",
|
||||
JSON.stringify(episodeData)
|
||||
);
|
||||
|
||||
const batchResults = await batchResponse.json();
|
||||
|
||||
const episodes = batchResults.map((result, index) => ({
|
||||
number: parseInt(episodeMatches[index][1], 10),
|
||||
href: `https://animekai.to/ajax/links/list?token=${episodeMatches[index][2]}&_=${result.data}`
|
||||
}));
|
||||
|
||||
return JSON.stringify(episodes);
|
||||
} catch (err) {
|
||||
console.error("Error fetching episodes:" + err);
|
||||
return [{
|
||||
number: 1,
|
||||
href: "Error fetching episodes"
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
async function extractStreamUrl(url) {
|
||||
try {
|
||||
const fetchUrl = `${url}`;
|
||||
const response = await fetchv2(fetchUrl);
|
||||
const text = await response.text();
|
||||
const cleanedHtml = cleanJsonHtml(text);
|
||||
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 subMatch = subRegex.exec(cleanedHtml);
|
||||
const softsubMatch = softsubRegex.exec(cleanedHtml);
|
||||
const dubMatch = dubRegex.exec(cleanedHtml);
|
||||
const subContent = subMatch ? subMatch[1].trim() : "";
|
||||
const softsubContent = softsubMatch ? softsubMatch[1].trim() : "";
|
||||
const dubContent = dubMatch ? dubMatch[1].trim() : "";
|
||||
const serverSpanRegex = /<span class="server"[^>]*data-lid="([^"]+)"[^>]*>Server 1<\/span>/;
|
||||
const serverIdDub = serverSpanRegex.exec(dubContent)?.[1];
|
||||
const serverIdSoftsub = serverSpanRegex.exec(softsubContent)?.[1];
|
||||
const serverIdSub = serverSpanRegex.exec(subContent)?.[1];
|
||||
|
||||
const tokenRequestData = [
|
||||
{ name: "Dub", data: serverIdDub },
|
||||
{ name: "Softsub", data: serverIdSoftsub },
|
||||
{ name: "Sub", data: serverIdSub }
|
||||
].filter(item => item.data);
|
||||
|
||||
const tokenBatchResponse = await fetchv2(
|
||||
"https://ilovekai.simplepostrequest.workers.dev/?ilovefeet",
|
||||
{},
|
||||
"POST",
|
||||
JSON.stringify(tokenRequestData)
|
||||
);
|
||||
const tokenResults = await tokenBatchResponse.json();
|
||||
|
||||
const streamUrls = tokenResults.map(result => {
|
||||
const serverIdMap = {
|
||||
"Dub": serverIdDub,
|
||||
"Softsub": serverIdSoftsub,
|
||||
"Sub": serverIdSub
|
||||
};
|
||||
return {
|
||||
type: result.name,
|
||||
url: `https://animekai.to/ajax/links/view?id=${serverIdMap[result.name]}&_=${result.data}`
|
||||
};
|
||||
});
|
||||
|
||||
const processStreams = async (streamUrls) => {
|
||||
const streamResponses = await Promise.all(
|
||||
streamUrls.map(async ({ type, url }) => {
|
||||
try {
|
||||
const res = await fetchv2(url);
|
||||
const json = await res.json();
|
||||
return {
|
||||
type: type,
|
||||
result: json.result
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(`Error fetching ${type} stream:`, error);
|
||||
return {
|
||||
type: type,
|
||||
result: null
|
||||
};
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const decryptRequestData = streamResponses
|
||||
.filter(item => item.result)
|
||||
.map(item => ({
|
||||
name: item.type,
|
||||
data: item.result
|
||||
}));
|
||||
|
||||
if (decryptRequestData.length === 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const decryptBatchResponse = await fetchv2(
|
||||
"https://ilovekai.simplepostrequest.workers.dev/?ilovearmpits",
|
||||
{},
|
||||
"POST",
|
||||
JSON.stringify(decryptRequestData)
|
||||
);
|
||||
const decryptResults = await decryptBatchResponse.json();
|
||||
|
||||
const finalResults = {};
|
||||
decryptResults.forEach(result => {
|
||||
try {
|
||||
const parsed = JSON.parse(result.data);
|
||||
finalResults[result.name] = parsed.url;
|
||||
console.log(`decrypted${result.name} URL:` + parsed.url);
|
||||
} catch (error) {
|
||||
console.log(`Error parsing ${result.name} result:`, error);
|
||||
finalResults[result.name] = null;
|
||||
}
|
||||
});
|
||||
|
||||
return finalResults;
|
||||
};
|
||||
|
||||
const decryptedUrls = await processStreams(streamUrls);
|
||||
const decryptedSub = decryptedUrls.Sub || decryptedUrls.Softsub || decryptedUrls.Dub;
|
||||
|
||||
console.log(decryptedSub);
|
||||
const headers = {
|
||||
"Referer": "https://animekai.to/",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"
|
||||
};
|
||||
|
||||
if (decryptedSub) {
|
||||
const response = await fetchv2(decryptedSub.replace("/e/", "/media/"), headers);
|
||||
const responseJson = await response.json();
|
||||
|
||||
const result = responseJson?.result;
|
||||
|
||||
const postData = {
|
||||
"text": result,
|
||||
"Useragent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"
|
||||
}
|
||||
|
||||
const finalResponse = await fetchv2("https://ilovekai.simplepostrequest.workers.dev/ilovebush", {}, "POST", JSON.stringify(postData));
|
||||
const finalJson = await finalResponse.json();
|
||||
const m3u8Link = finalJson?.result?.sources?.[0]?.file;
|
||||
|
||||
return m3u8Link;
|
||||
}
|
||||
|
||||
return "error";
|
||||
} catch (error) {
|
||||
console.log("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, " ");
|
||||
}
|
||||
20
animekai/hardsub/animekai.json
Normal file
20
animekai/hardsub/animekai.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"sourceName": "AnimeKai (Hardsub)",
|
||||
"iconUrl": "https://apktodo.io/uploads/2025/5/animekai-icon.jpg",
|
||||
"author": {
|
||||
"name": "50/50",
|
||||
"icon": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3122kQwublLkZ6rf1fEpUP79BxZOFmH9BSA&s"
|
||||
},
|
||||
"version": "1.0.2",
|
||||
"language": "English",
|
||||
"streamType": "HLS",
|
||||
"quality": "1080p",
|
||||
"baseUrl": "https://animekai.to/",
|
||||
"searchBaseUrl": "https://animekai.to/",
|
||||
"scriptUrl": "https://gitlab.com/50n50/sources/-/raw/main/animekai/hardsub/animekai.js",
|
||||
"type": "anime",
|
||||
"asyncJS": true,
|
||||
"softsub": false,
|
||||
"downloadSupport": true,
|
||||
"note": "Make sure you're on the latest version of Sora."
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue