async function searchResults(keyword) {
    const urls = [
        `https://verseriesonline.net/buscar?q=${encodeURIComponent(keyword)}`,
        `https://verseriesonline.net/buscar?q=${encodeURIComponent(keyword)}&page=2`,
        `https://verseriesonline.net/buscar?q=${encodeURIComponent(keyword)}&page=3`,
        `https://verseriesonline.net/buscar?q=${encodeURIComponent(keyword)}&page=4`
    ];
    const regex = /<article class="serie-card gridder-list">.*?<a[^>]+href="([^"]+)"[^>]*>.*?<img[^>]+data-src="([^"]+)"[^>]*>.*?<a class="serie-card__title"[^>]*>([^<]+)<\/a>/gs;
    try {
        const fetchPromises = urls.map(url => fetchv2(url).then(r => r.text()));
        const htmls = await Promise.all(fetchPromises);
        const results = [];
        for (const html of htmls) {
            let match;
            while ((match = regex.exec(html)) !== null) {
                results.push({
                    href: match[1].trim(),
                    image: "https://verseriesonline.net" + match[2].trim(),
                    title: match[3].trim()
                });
            }
            regex.lastIndex = 0;
        }
        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 = /<div class="full_content-desc">[\s\S]*?<p>(.*?)<\/p>/s;
        const match = regex.exec(html);
        const description = match ? match[1].trim() : "N/A";

        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 episodeRegex = /<a class="episode-card line-item" href="([^"]+)"[^>]*>[\s\S]*?T\s*<span>(\d+)<\/span>\s*E\s*<span>(\d+)<\/span>/g;
        let match;
        
        while ((match = episodeRegex.exec(html)) !== null) {
            results.push({
                season: parseInt(match[2], 10),
                href: match[1].trim(),
                number: parseInt(match[3], 10)
            });
        }

        results.sort((a, b) => {
            if (a.season !== b.season) {
                return a.season - b.season;
            }
            return a.number - b.number;
        });

        return JSON.stringify(results);
    } catch (err) {
        return JSON.stringify([{
            href: "Error",
            number: "Error",
            season: "Error"
        }]);
    }
}


async function extractStreamUrl(url) {
    try {
        const response = await fetchv2(url);
        const html = await response.text();

        let hash = null;
        const blockRegex = /<a[^>]*class="play-option"[^>]*data-hash="([^"]+)"[^>]*>[\s\S]*?streamwish\.to[\s\S]*?<\/a>/g;
        let blockMatch;
        while ((blockMatch = blockRegex.exec(html)) !== null) {
            const hashMatch = blockMatch[0].match(/data-hash="([^"]+)"/);
            if (hashMatch) {
                hash = hashMatch[1].trim();
                break;
            }
        }

        const tokenRegex = /_token:\s*"([^"]+)"/;
        const tokenMatch = html.match(tokenRegex);
        const token = tokenMatch ? tokenMatch[1].trim() : null;

        console.log("Hash:"+ hash);
        console.log("Token:"+ token);

        const embedResponse = await fetchv2("https://www.verseriesonline.net/hashembedlink", { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}, "POST", `hash=${encodeURIComponent(hash)}&_token=${encodeURIComponent(token)}`);
        const embedJson = await embedResponse.json();
        console.log("Embed JSON:"+ JSON.stringify(embedJson));
        const embedUrl = embedJson.link;

        const someHtml = await fetchv2(embedUrl);
        const someText = await someHtml.text();

        const finalUrl = await streamwishExtractor(someText, embedUrl);
        const streamObj = {
            streams: [
                {
                    title: "Server 1",
                    streamUrl: finalUrl,
                    headers: {
                        referer: ""
                    }
                }
            ],
            subtitle: "https://none.com"
        };
        return JSON.stringify(streamObj);
    } catch (err) {
        return  "https://error.org/";
    }
}

/* SCHEME START */

/**
 * @name streamwishExtractor
 * @author Ibro
 */

async function streamwishExtractor(data, url = null) {
    const obfuscatedScript = data.match(/<script[^>]*>\s*(eval\(function\(p,a,c,k,e,d.*?\)[\s\S]*?)<\/script>/);

    const unpackedScript = unpack(obfuscatedScript[1]);

    const m3u8Match = unpackedScript.match(/file:"(https?:\/\/.*?\.m3u8.*?)"/);

    const m3u8Url = m3u8Match[1];
    console.log(m3u8Url);
    return m3u8Url;
}

////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////       Helper Functions       ////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////

/*
Credit to GitHub user @mnsrulz for Unpacker Node library

Credits to @jcpiccodev for writing the full deobfuscator <3
*/

/* 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 detect(source) {
    return source.replace(" ", "").startsWith("eval(function(p,a,c,k,e,");
}

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;
    }
}
/* REMOVE_END */

/* SCHEME END */