source/animelib/animelib.js

306 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

async function searchResults(keyword) {
const results = [];
try {
const response = await fetchv2("https://api.cdnlibs.org/api/anime?fields[]=rate_avg&fields[]=rate&fields[]=releaseDate&q=" + keyword);
const json = await response.json();
if (json && Array.isArray(json.data)) {
for (const item of json.data) {
const image = item.cover?.default || item.cover?.thumbnail || "";
results.push({
title: item.eng_name || item.name || "Unknown",
image: "https://passthrough-worker.simplepostrequest.workers.dev/?simple=" + image + "&referer=https://animelib.org/",
href: item.slug_url || item.slug || item.id
});
}
}
return JSON.stringify(results);
} catch (err) {
return JSON.stringify([{
title: "Error",
image: "Error",
href: "Error"
}]);
}
}
async function extractDetails(slug) {
try {
const response = await fetchv2(
"https://api.cdnlibs.org/api/anime/" + slug +
"?fields[]=background&fields[]=eng_name&fields[]=otherNames&fields[]=summary&fields[]=releaseDate&fields[]=type_id&fields[]=caution&fields[]=views&fields[]=close_view&fields[]=rate_avg&fields[]=rate&fields[]=genres&fields[]=tags&fields[]=teams&fields[]=user&fields[]=franchise&fields[]=authors&fields[]=publisher&fields[]=userRating&fields[]=moderated&fields[]=metadata&fields[]=metadata.count&fields[]=metadata.close_comments&fields[]=anime_status_id&fields[]=time&fields[]=episodes&fields[]=episodes_count&fields[]=episodesSchedule&fields[]=shiki_rate"
);
const json = await response.json();
const data = json.data || {};
const aliases = Array.isArray(data.otherNames) ? data.otherNames.join(", ") : "";
return JSON.stringify([{
description: data.summary || "No summary available",
airdate: data.releaseDate || "Unknown",
aliases: aliases
}]);
} catch (err) {
return JSON.stringify([{
description: "Error",
airdate: "Error",
aliases: ""
}]);
}
}
async function extractEpisodes(slug) {
const results = [];
try {
const response = await fetchv2("https://api.cdnlibs.org/api/episodes?anime_id=" + slug);
const json = await response.json();
if (json && Array.isArray(json.data)) {
for (const episode of json.data) {
results.push({
href: episode.id ? String(episode.id) : "",
number: parseFloat(episode.number) || 0
});
}
}
return JSON.stringify(results);
} catch (err) {
return JSON.stringify([{
href: "Error",
number: "Error"
}]);
}
}
async function extractStreamUrl(ID) {
try {
const response = await fetchv2("https://api.cdnlibs.org/api/episodes/" + ID);
const json = await response.json();
const data = json.data || {};
const players = data.players || [];
// const parserPromises = players
// .filter(player => player.src && player.team && player.team.name)
// .map(async (player) => {
// try {
// const kodikUrl = "https:" + player.src;
// const qualitiesJson = await kodikParser(kodikUrl);
// const qualities = JSON.parse(qualitiesJson);
// let highestQuality = null;
// let highestQualityNum = 0;
// for (const quality in qualities) {
// if (qualities[quality].src) {
// const qualityNum = parseInt(quality.replace('p', '')) || 0;
// if (qualityNum > highestQualityNum) {
// highestQualityNum = qualityNum;
// highestQuality = qualities[quality].src;
// }
// }
// }
// if (highestQuality) {
// if (highestQuality.startsWith('//')) {
// highestQuality = 'https:' + highestQuality;
// }
// return {
// title: player.team.name,
// streamUrl: highestQuality,
// headers: {
// "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
// "Referer": "https://kodik.info/"
// }
// };
// }
// return null;
// } catch (err) {
// return null;
// }
// });
players.sort((a, b) => {
const order = { Animelib: 0, Kodik: 1 };
return (order[a.player] ?? 99) - (order[b.player] ?? 99);
});
const parserPromises = players
.filter(player => player.team && player.team.name)
.map(async (player) => {
try {
let streamUrl = null;
let highestQualityNum = 0;
if (player.player === "Animelib" && player.video && player.video.quality) {
const qualities = player.video.quality;
console.log(qualities);
for (const qualityItem of qualities) {
if (qualityItem.href && qualityItem.quality > highestQualityNum) {
highestQualityNum = qualityItem.quality;
streamUrl = qualityItem.href;
console.log("Found Animelib quality: " + qualityItem.quality + " URL: " + streamUrl);
}
}
// Animelib URLs are relative, prepend base URL
if (streamUrl && !streamUrl.startsWith('http')) {
// https://video1.cdnlibs.org/.аs/
// https://video2.anilib.me/.аs/
// https://video3.anilib.me/.аs/
streamUrl = 'https://video1.cdnlibs.org/.%D0%B0s/' + streamUrl;
}
} else if (player.player === "Kodik" && player.src) {
const kodikUrl = "https:" + player.src;
const qualitiesJson = await kodikParser(kodikUrl);
const qualities = JSON.parse(qualitiesJson);
for (const quality in qualities) {
if (qualities[quality].src) {
const qualityNum = parseInt(quality.replace('p', '')) || 0;
if (qualityNum > highestQualityNum) {
highestQualityNum = qualityNum;
streamUrl = qualities[quality].src;
}
}
}
if (streamUrl && streamUrl.startsWith('//')) {
streamUrl = 'https:' + streamUrl;
}
}
if (streamUrl) {
return {
title: player.team.name + (highestQualityNum ? ` (${highestQualityNum}p)` : '') + (player.player === "Animelib" ? " (Animelib)" : " (Kodik)"),
streamUrl,
headers: {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"Referer": player.player === "Kodik" ? "https://kodik.info/" : "https://v3.animelib.org/"
}
};
}
return null;
} catch (err) {
return null;
}
});
const results = await Promise.all(parserPromises);
const streams = results.filter(stream => stream !== null);
return JSON.stringify({
streams: streams,
subtitle: "https://none.com"
});
} catch (err) {
return JSON.stringify({
streams: [],
subtitle: "https://none.com"
});
}
}
async function kodikParser(url) {
try {
const headers = {
"Referer": "https://v3.animelib.org/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
};
const response = await fetchv2(url, headers);
const htmlText = await response.text();
const urlParamsMatch = htmlText.match(/var\s+urlParams\s*=\s*'([^']+)'/);
const videoInfoTypeMatch = htmlText.match(/videoInfo\.type\s*=\s*'([^']+)'/);
const videoInfoHashMatch = htmlText.match(/videoInfo\.hash\s*=\s*'([^']+)'/);
const videoInfoIdMatch = htmlText.match(/videoInfo\.id\s*=\s*'([^']+)'/);
const urlParams = urlParamsMatch ? JSON.parse(urlParamsMatch[1]) : {};
const videoInfo_type = videoInfoTypeMatch ? videoInfoTypeMatch[1] : '';
const videoInfo_hash = videoInfoHashMatch ? videoInfoHashMatch[1] : '';
const videoInfo_id = videoInfoIdMatch ? videoInfoIdMatch[1] : '';
const finalData =
`d=${urlParams.d}` +
`&d_sign=${urlParams.d_sign}` +
`&pd=${urlParams.pd}` +
`&pd_sign=${urlParams.pd_sign}` +
`&ref=${urlParams.ref}` +
`&ref_sign=${urlParams.ref_sign}` +
`&bad_user=false&cdn_is_working=false` +
`&type=${videoInfo_type}&hash=${videoInfo_hash}&id=${videoInfo_id}&info=%7B%7D`;
const headers2 = {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Referer": "https://kodik.info",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
"X-Requested-With": "XMLHttpRequest"
};
const apiResponse = await fetchv2("https://kodik.info/ftor", headers2, "POST", finalData);
const apiJson = await apiResponse.json();
const qualities = {};
if (apiJson?.links) {
for (const quality in apiJson.links) {
const qualityData = apiJson.links[quality];
if (qualityData && qualityData[0] && qualityData[0].src) {
const encodedSrc = qualityData[0].src;
const decodedUrl = decode(encodedSrc);
qualities[quality] = {
src: decodedUrl,
type: qualityData[0].type || 'application/x-mpegURL'
};
}
}
}
return JSON.stringify(qualities, null, 2);
} catch (error) {
console.log(error);
return JSON.stringify({ error: "error.org" });
}
}
function decode(input) {
const _0x1a = ["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "=", String.fromCharCode, ">="];
(function() {})();
const _map = _0x1a[0];
let _o = '',
_b = 0,
_c = 0;
const _r = [];
for (let _i = 0; _i < input.length; _i++) {
const _ch = input[_i];
if (/[a-zA-Z]/.test(_ch)) {
const _cc = _ch.charCodeAt(0);
const _max = _ch <= 'Z' ? 90 : 122;
let _sh = _cc + 18;
_r.push(String.fromCharCode(_sh <= _max ? _sh : _sh - 26));
} else _r.push(_ch);
}
const _rot = _r.join('');
for (let _j = 0; _j < _rot.length; _j++) {
const _ch = _rot[_j];
if (_ch === _0x1a[1]) break;
const _v = _map.indexOf(_ch);
if (_v === -1) continue;
_b = (_b << 6) | _v;
_c += 6;
if (_c >= 8) {
_c -= 8;
_o += _0x1a[2]((_b >> _c) & 0xFF);
}
}
return _o;
}