From 1d004c56186fab45dd408a75a198d986a51bf717 Mon Sep 17 00:00:00 2001 From: aka paul <50n50@noreply.localhost> Date: Sat, 1 Nov 2025 13:50:08 +0000 Subject: [PATCH] Add animelib/animelib.js --- animelib/animelib.js | 231 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 animelib/animelib.js diff --git a/animelib/animelib.js b/animelib/animelib.js new file mode 100644 index 0000000..56a2a32 --- /dev/null +++ b/animelib/animelib.js @@ -0,0 +1,231 @@ +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) { + 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; + } + }); + + 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; +}