package onlinestream_providers

var AnimepahePayload = "/// <reference path=\"./onlinestream-provider.d.ts\" />\n/// <reference path=\"../goja_bindings/doc.d.ts\" />\n/// <reference path=\"../goja_bindings/crypto.d.ts\" />\n\ntype EpisodeData = {\n    id: number; episode: number; title: string; snapshot: string; filler: number; session: string; created_at?: string\n}\n\ntype AnimeData = {\n    id: number; title: string; type: string; year: number; poster: string; session: string\n}\n\nclass Provider {\n\n    api = \"https://animepahe.ru\"\n    headers = { Referer: \"https://kwik.si\" }\n\n    getSettings(): Settings {\n        return {\n            episodeServers: [\"kwik\"],\n            supportsDub: false,\n        }\n    }\n\n    async search(opts: SearchOptions): Promise<SearchResult[]> {\n        const req = await fetch(`${this.api}/api?m=search&q=${encodeURIComponent(opts.query)}`, {\n            headers: {\n                Cookie: \"__ddg1_=;__ddg2_=;\",\n            },\n        })\n\n        if (!req.ok) {\n            return []\n        }\n        const data = (await req.json()) as { data: AnimeData[] }\n        const results: SearchResult[] = []\n\n        if (!data?.data) {\n            return []\n        }\n\n        data.data.map((item: AnimeData) => {\n            results.push({\n                subOrDub: \"sub\",\n                id: item.session,\n                title: item.title,\n                url: \"\",\n            })\n        })\n\n        return results\n    }\n\n    async findEpisodes(id: string): Promise<EpisodeDetails[]> {\n        let episodes: EpisodeDetails[] = []\n\n        const req =\n            await fetch(\n                `${this.api}${id.includes(\"-\") ? `/anime/${id}` : `/a/${id}`}`,\n                {\n                    headers: {\n                        Cookie: \"__ddg1_=;__ddg2_=;\",\n                    },\n                },\n            )\n\n        const html = await req.text()\n\n\n        function pushData(data: EpisodeData[]) {\n            for (const item of data) {\n                episodes.push({\n                    id: item.session + \"$\" + id,\n                    number: item.episode,\n                    title: item.title && item.title.length > 0 ? item.title : \"Episode \" + item.episode,\n                    url: req.url,\n                })\n            }\n        }\n\n        const $ = LoadDoc(html)\n\n        const tempId = $(\"head > meta[property='og:url']\").attr(\"content\")!.split(\"/\").pop()!\n\n        const { last_page, data } = (await (\n            await fetch(`${this.api}/api?m=release&id=${tempId}&sort=episode_asc&page=1`, {\n                headers: {\n                    Cookie: \"__ddg1_=;__ddg2_=;\",\n                },\n            })\n        ).json()) as {\n            last_page: number;\n            data: EpisodeData[]\n        }\n\n        pushData(data)\n\n        const pageNumbers = Array.from({ length: last_page - 1 }, (_, i) => i + 2)\n\n        const promises = pageNumbers.map((pageNumber) =>\n            fetch(`${this.api}/api?m=release&id=${tempId}&sort=episode_asc&page=${pageNumber}`, {\n                headers: {\n                    Cookie: \"__ddg1_=;__ddg2_=;\",\n                },\n            }).then((res) => res.json()),\n        )\n        const results = (await Promise.all(promises)) as {\n            data: EpisodeData[]\n        }[]\n\n        results.forEach((showData) => {\n            for (const data of showData.data) {\n                if (data) {\n                    pushData([data])\n                }\n            }\n        });\n        (data as any[]).sort((a, b) => a.number - b.number)\n\n        if (episodes.length === 0) {\n            throw new Error(\"No episodes found.\")\n        }\n\n\n        const lowest = episodes[0].number\n        if (lowest > 1) {\n            for (let i = 0; i < episodes.length; i++) {\n                episodes[i].number = episodes[i].number - lowest + 1\n            }\n        }\n        \n        // Remove decimal episode numbers\n       episodes = episodes.filter((episode) => Number.isInteger(episode.number))\n\n        // for (let i = 0; i < episodes.length; i++) {\n        //     // If an episode number is a decimal, round it up to the nearest whole number\n        //     if (Number.isInteger(episodes[i].number)) {\n        //         continue\n        //     }\n        //     const original = episodes[i].number\n        //     episodes[i].number = Math.floor(episodes[i].number)\n        //     episodes[i].title = `Episode ${episodes[i].number} [{${original}}]`\n        // }\n\n        return episodes\n    }\n\n    async findEpisodeServer(episode: EpisodeDetails, _server: string): Promise<EpisodeServer> {\n        const episodeId = episode.id.split(\"$\")[0]\n        const animeId = episode.id.split(\"$\")[1]\n\n        console.log(`${this.api}/play/${animeId}/${episodeId}`)\n\n        const req = await fetch(\n            `${this.api}/play/${animeId}/${episodeId}`,\n            {\n                headers: {\n                    Cookie: \"__ddg1_=;__ddg2_=;\",\n                },\n            },\n        )\n\n        const html = await req.text()\n\n        const regex = /https:\\/\\/kwik\\.si\\/e\\/\\w+/g\n        const matches = html.match(regex)\n\n        if (matches === null) {\n            throw new Error(\"Failed to fetch episode server.\")\n        }\n\n        const $ = LoadDoc(html)\n\n        const result: EpisodeServer = {\n            videoSources: [],\n            headers: this.headers ?? {},\n            server: \"kwik\",\n        }\n\n        $(\"button[data-src]\").each(async (_, el) => {\n            let videoSource: VideoSource = {\n                url: \"\",\n                type: \"m3u8\",\n                quality: \"\",\n                subtitles: [],\n            }\n\n            videoSource.url = el.data(\"src\")!\n            if (!videoSource.url) {\n                return\n            }\n\n            const fansub = el.data(\"fansub\")!\n            const quality = el.data(\"resolution\")!\n\n            videoSource.quality = `${quality}p - ${fansub}`\n\n            if (el.data(\"audio\") === \"eng\") {\n                videoSource.quality += \" (Eng)\"\n            }\n\n            if (videoSource.url === matches[0]) {\n                videoSource.quality += \" (default)\"\n            }\n\n            result.videoSources.push(videoSource)\n        })\n\n        await Promise.all(result.videoSources.map(async (videoSource) => {\n            try {\n                const src_req = await fetch(videoSource.url, {\n                    headers: {\n                        Referer: this.headers.Referer,\n                        \"user-agent\":\n                            \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.56\",\n                    },\n                })\n\n                const src_html = await src_req.text()\n\n                const scripts = src_html.match(/eval\\(f.+?\\}\\)\\)/g)\n                if (!scripts) {\n                    return\n                }\n\n                for (const _script of scripts) {\n                    const scriptMatch = _script.match(/eval(.+)/)\n                    if (!scriptMatch || !scriptMatch[1]) {\n                        continue\n                    }\n\n                    try {\n                        const decoded = eval(scriptMatch[1])\n                        const link = decoded.match(/source='(.+?)'/)\n                        if (!link || !link[1]) {\n                            continue\n                        }\n\n                        videoSource.url = link[1]\n\n                    }\n                    catch (e) {\n                        console.error(\"Failed to extract kwik link\", e)\n                    }\n\n                }\n\n            }\n            catch (e) {\n                console.error(\"Failed to fetch kwik link\", e)\n            }\n        }))\n\n        return result\n    }\n}\n\n"
