async function searchResults(keyword) { const results = []; const url = "https://www.doramasyt.com/buscar?q=" + encodeURIComponent(keyword); try { const response = await fetchv2(url); const html = await response.text(); console.log(html); const regex = /
  • \s*
    \s*]*data-src="([^"]+)"[^>]*>[\s\S]*?]*>(.*?)<\/h3>[\s\S]*?<\/a>\s*<\/article>\s*<\/li>/g; let match; while ((match = regex.exec(html)) !== null) { results.push({ title: cleanTitle(match[3].trim().replace(/<[^>]*>/g, '')), image: match[2].trim(), href: match[1].trim() }); } return JSON.stringify(results); } catch (err) { return JSON.stringify([{ title: "Error", image: "Error", href: "Error" }]); } } function cleanTitle(title) { return title .replace(/’/g, "'") .replace(/–/g, "-") .replace(/&#[0-9]+;/g, ""); } async function extractDetails(url) { try { const response = await fetchv2(url); const html = await response.text(); const descMatch = html.match(/]*>([^<]+)<\/h1>/); const aliasMatch = html.match(/([^<]+)<\/span>/); const description = descMatch ? descMatch[1].trim() : "N/A"; const aliases = aliasMatch ? aliasMatch[1].trim() : "N/A"; return JSON.stringify([{ description: cleanTitle(description), aliases: cleanTitle(aliases), airdate: "N/A" }]); } catch (err) { return JSON.stringify([{ description: "Error", aliases: "Error", airdate: "Error" }]); } } async function extractEpisodes(url) { const results = []; try { const response = await networkFetch(url, { timeoutSeconds: 2, returnHTML: true }); const html = await response.html; const regex = /]*data-episode="(\d+)"/g; let match; while ((match = regex.exec(html)) !== 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 responseOne = await fetchv2(url); const htmlOne = await responseOne.text(); const matchOne = htmlOne.match(/]*data-player="([^"]+)"[^>]*>filemoon<\/button>/i); const filemoonData = matchOne ? matchOne[1] : null; const response = await fetchv2("https://www.doramasyt.com/reproductor?video=" + encodeURIComponent(filemoonData)); const html = await response.text(); const matchIframe = html.match(/]*src="([^"]*filemoon\.sx\/e\/[^"]+)"/i); const filemoonUrl = matchIframe ? matchIframe[1] : null; console.log(filemoonUrl); const responseTwo = await fetchv2(filemoonUrl); const htmlTwo = await responseTwo.text(); let streamUrl = null; try { streamUrl = await filemoonExtractor(htmlTwo, filemoonUrl); } catch (error) { console.log("filemoon HD extraction error:" + error); } console.log("filemoon Stream URL: " + streamUrl); if (streamUrl && streamUrl !== false && streamUrl !== null) { return streamUrl; } console.log("No stream URL found"); return null; } catch (error) { console.log("Fetch error:", error); return null; } } /* 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 */