async function searchResults(keyword) { const results = []; try { const response = await fetchv2("https://www.animebum.net/search?s=" + encodeURIComponent(keyword)); const html = await response.text(); const regex = /
]*>]*><\/a>[\s\S]*?

([^<]+)<\/h2>/g; let match; while ((match = regex.exec(html)) !== null) { results.push({ title: match[3].trim(), image: match[2].trim(), href: match[1].trim() }); } return JSON.stringify(results); } catch (err) { return JSON.stringify([{ title: "Error", image: "Error", href: "Error" }]); } } async function extractDetails(url) { try { const response = await fetchv2(url); const html = await response.text(); const regex = /
\s*

([\s\S]*?)<\/p>/i; const match = regex.exec(html); let description = match ? match[1].trim() : "N/A"; description = description.replace(/<[^>]+>/g, ""); description = description.replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, '"') .replace(/'/g, "'") .replace(/á/g, "á") .replace(/é/g, "é") .replace(/í/g, "í") .replace(/ó/g, "ó") .replace(/ú/g, "ú") .replace(/ñ/g, "ñ") .replace(/ü/g, "ü") .replace(/“/g, "“") .replace(/”/g, "”") .replace(/‘/g, "‘") .replace(/’/g, "’") .replace(/¡/g, "¡") .replace(/¿/g, "¿"); return JSON.stringify([{ description: description, aliases: "N/A", airdate: "N/A" }]); } catch (err) { return JSON.stringify([{ description: "Error", aliases: "Error", airdate: "Error" }]); } } async function extractEpisodes(url) { const results = []; try { const response = await fetchv2(url); const html = await response.text(); const containerMatch = html.match( /

([\s\S]*?)<\/div>/ ); if (!containerMatch) { return JSON.stringify([{ href: "Not found", number: "N/A" }]); } const containerHtml = containerMatch[1]; const regex = /]+href="([^"]+)"[^>]*>[\s\S]*?Episodio\s+(\d+)\s*<\/a>/gi; let match; while ((match = regex.exec(containerHtml)) !== null) { results.push({ href: match[1].trim(), number: parseInt(match[2], 10) }); } return JSON.stringify(results); } catch (err) { return JSON.stringify([{ href: "Error", number: "Error" }]); } } async function extractStreamUrl(url) { try { const response = await fetchv2(url); const html = await response.text(); // Try Filemoon first const filemoonRegex = /(https:\/\/filemoon\.(?:to|sx)\/e\/[A-Za-z0-9]+\/[^\s"']+)/; const filemoonMatch = filemoonRegex.exec(html); if (filemoonMatch) { const filemoon = filemoonMatch[1]; console.log("Filemoon URL found: " + filemoon); const headers = { "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", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Referer": "https://animebum.net/", }; const filemoonResponse = await fetchv2(filemoon, headers); const filemoonHtml = await filemoonResponse.text(); try { const streamUrl = await filemoonExtractor(filemoonHtml, "https://animebum.net/"); if (streamUrl) return streamUrl; } catch (err) { console.log("Filemoon extraction error:" + err); } } const optionRegex = /
    ([\s\S]*?)<\/ul>/i; const optionMatch = optionRegex.exec(html); if (!optionMatch) return null; const optionsHtml = optionMatch[1]; const faireMatch = /]*data-id="(\d+)"[^>]*>\s*]*title="Faire"/i.exec(optionsHtml); if (!faireMatch) return null; const faireId = parseInt(faireMatch[1], 10); const videoRegex = new RegExp(`video\\[${faireId}\\]\\s*=\\s*'([^']+)'`); const videoMatch = videoRegex.exec(html); if (!videoMatch) return null; const iframeHtml = videoMatch[1]; const srcMatch = /src=["']([^"']+)["']/.exec(iframeHtml); const streamUrl = srcMatch ? srcMatch[1] : null; const responeSome = await fetchv2(streamUrl); const htmlSome = await responeSome.text(); const shareIdMatch = htmlSome.match(/var\s+shareId\s*=\s*"([^"]+)"/); if (!shareIdMatch) return null; const shareId = shareIdMatch[1]; const someUrl = `https://www.amazon.com/drive/v1/shares/${shareId}?resourceVersion=V2&ContentType=JSON&asset=ALL`; const shareJsonResp = await fetchv2(someUrl); const shareJson = await shareJsonResp.json(); console.log(JSON.stringify(shareJson)); const nodeId = shareJson.nodeInfo?.id; if (!nodeId) return null; const childrenUrl = `https://www.amazon.com/drive/v1/nodes/${nodeId}/children?resourceVersion=V2&ContentType=JSON&limit=200&sort=%5B%22kind+DESC%22%2C+%22modifiedDate+DESC%22%5D&asset=ALL&tempLink=true&shareId=${shareId}`; const childrenResp = await fetchv2(childrenUrl); const childrenData = await childrenResp.json(); console.log(JSON.stringify(childrenData)); const file = childrenData.data.find(item => item.kind === "FILE"); if (!file) return null; return file.tempLink; } catch (err) { console.log("Fetch error:" + err); return "https://error.org/"; } } /* SCHEME START */ /* {REQUIRED PLUGINS: unbaser} */ /** * @name filemoonExtractor * @author Cufiy - Inspired by Churly */ async function filemoonExtractor(html, url = null) { // check if contains iframe, if does, extract the src and get the url const regex = /]+src="([^"]+)"[^>]*><\/iframe>/; const match = html.match(regex); if (match) { console.log("Iframe URL: " + match[1]); const iframeUrl = match[1]; const iframeResponse = await soraFetch(iframeUrl, { headers: { "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", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Referer": url, } }); console.log("Iframe Response: " + iframeResponse.status); html = await iframeResponse.text(); } // console.log("HTML: " + html); // get /]*>([\s\S]*?)<\/script>/gi const scriptRegex = /]*>([\s\S]*?)<\/script>/gi; const scripts = []; let scriptMatch; while ((scriptMatch = scriptRegex.exec(html)) !== null) { scripts.push(scriptMatch[1]); } // get the script with eval and m3u8 const evalRegex = /eval\((.*?)\)/; const m3u8Regex = /m3u8/; // console.log("Scripts: " + scripts); const evalScript = scripts.find(script => evalRegex.test(script) && m3u8Regex.test(script)); if (!evalScript) { console.log("No eval script found"); return null; } const unpackedScript = unpack(evalScript); // get the m3u8 url const m3u8Regex2 = /https?:\/\/[^\s]+master\.m3u8[^\s]*?(\?[^"]*)?/; const m3u8Match = unpackedScript.match(m3u8Regex2); if (m3u8Match) { return m3u8Match[0]; } else { console.log("No M3U8 URL found"); return null; } } /* REMOVE_START */ class Unbaser { constructor(base) { this.ALPHABET = { 62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 95: "' !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'", }; this.dictionary = {}; this.base = base; if (36 < base && base < 62) { this.ALPHABET[base] = this.ALPHABET[base] || this.ALPHABET[62].substr(0, base); } if (2 <= base && base <= 36) { this.unbase = (value) => parseInt(value, base); } else { try { [...this.ALPHABET[base]].forEach((cipher, index) => { this.dictionary[cipher] = index; }); } catch (er) { throw Error("Unsupported base encoding."); } this.unbase = this._dictunbaser; } } _dictunbaser(value) { let ret = 0; [...value].reverse().forEach((cipher, index) => { ret = ret + ((Math.pow(this.base, index)) * this.dictionary[cipher]); }); return ret; } } function unpack(source) { let { payload, symtab, radix, count } = _filterargs(source); if (count != symtab.length) { throw Error("Malformed p.a.c.k.e.r. symtab."); } let unbase; try { unbase = new Unbaser(radix); } catch (e) { throw Error("Unknown p.a.c.k.e.r. encoding."); } function lookup(match) { const word = match; let word2; if (radix == 1) { word2 = symtab[parseInt(word)]; } else { word2 = symtab[unbase.unbase(word)]; } return word2 || word; } source = payload.replace(/\b\w+\b/g, lookup); return _replacestrings(source); function _filterargs(source) { const juicers = [ /}\('(.*)', *(\d+|\[\]), *(\d+), *'(.*)'\.split\('\|'\), *(\d+), *(.*)\)\)/, /}\('(.*)', *(\d+|\[\]), *(\d+), *'(.*)'\.split\('\|'\)/, ]; for (const juicer of juicers) { const args = juicer.exec(source); if (args) { let a = args; if (a[2] == "[]") { } try { return { payload: a[1], symtab: a[4].split("|"), radix: parseInt(a[2]), count: parseInt(a[3]), }; } catch (ValueError) { throw Error("Corrupted p.a.c.k.e.r. data."); } } } throw Error("Could not make sense of p.a.c.k.e.r data (unexpected code structure)"); } function _replacestrings(source) { return source; } } /** * Uses Sora's fetchv2 on ipad, fallbacks to regular fetch on Windows * @author ShadeOfChaos * * @param {string} url The URL to make the request to. * @param {object} [options] The options to use for the request. * @param {object} [options.headers] The headers to send with the request. * @param {string} [options.method='GET'] The method to use for the request. * @param {string} [options.body=null] The body of the request. * * @returns {Promise} The response from the server, or null if the * request failed. */ async function soraFetch(url, options = { headers: {}, method: 'GET', body: null }) { try { return await fetchv2(url, options.headers ?? {}, options.method ?? 'GET', options.body ?? null); } catch(e) { try { return await fetch(url, options); } catch(error) { return null; } } } /* REMOVE_END */ /* SCHEME END */