From 7f4a1f265a4e0947c2771977908e2145663cfc1c Mon Sep 17 00:00:00 2001 From: Type-Delta <121682210+Type-Delta@users.noreply.github.com> Date: Sun, 28 Dec 2025 19:20:46 +0700 Subject: [PATCH] fix: animepahe unable to stream/download --- viu_media/core/downloader/yt_dlp.py | 3 +++ .../provider/anime/animepahe/constants.py | 21 ++++++++++++++++++- .../libs/provider/anime/animepahe/mappers.py | 3 ++- .../libs/provider/anime/animepahe/provider.py | 12 ++++++++++- 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/viu_media/core/downloader/yt_dlp.py b/viu_media/core/downloader/yt_dlp.py index 1bc55cc..8d95ff0 100644 --- a/viu_media/core/downloader/yt_dlp.py +++ b/viu_media/core/downloader/yt_dlp.py @@ -30,6 +30,9 @@ class YtDLPDownloader(BaseDownloader): sub_paths = [] merged_path = None + logger.debug(f"Starting download for URL: {params.url}") + logger.debug(f"Using Headers: {params.headers}") + if TORRENT_REGEX.match(params.url): from .torrents import download_torrent_with_webtorrent_cli diff --git a/viu_media/libs/provider/anime/animepahe/constants.py b/viu_media/libs/provider/anime/animepahe/constants.py index c2b77e4..1973bb1 100644 --- a/viu_media/libs/provider/anime/animepahe/constants.py +++ b/viu_media/libs/provider/anime/animepahe/constants.py @@ -3,6 +3,8 @@ import re ANIMEPAHE = "animepahe.si" ANIMEPAHE_BASE = f"https://{ANIMEPAHE}" ANIMEPAHE_ENDPOINT = f"{ANIMEPAHE_BASE}/api" +CDN_PROVIDER = "kwik.cx" +CDN_PROVIDER_BASE = f"https://{CDN_PROVIDER}" SERVERS_AVAILABLE = ["kwik"] REQUEST_HEADERS = { @@ -25,7 +27,7 @@ SERVER_HEADERS = { "Accept-Encoding": "Utf-8", "DNT": "1", "Connection": "keep-alive", - "Referer": "https://animepahe.si/", + "Referer": ANIMEPAHE_BASE + '/', "Upgrade-Insecure-Requests": "1", "Sec-Fetch-Dest": "iframe", "Sec-Fetch-Mode": "navigate", @@ -33,5 +35,22 @@ SERVER_HEADERS = { "Priority": "u=4", "TE": "trailers", } + +STREAM_HEADERS = { + # "Host": "vault-16.owocdn.top", # This will have to be the actual host of the stream (behind Kwik) + "Accept": "*/*", + "Accept-Language": "en-US,en;q=0.5", + "Accept-Encoding": "gzip, deflate, br, zstd", + "Origin": CDN_PROVIDER_BASE, + "Sec-GPC": "1", + "Connection": "keep-alive", + "Referer": CDN_PROVIDER_BASE + '/', + "Sec-Fetch-Dest": "empty", + "Sec-Fetch-Mode": "cors", + "Sec-Fetch-Site": "cross-site", + "TE": "trailers", +} + + JUICY_STREAM_REGEX = re.compile(r"source='(.*)';") KWIK_RE = re.compile(r"Player\|(.+?)'") diff --git a/viu_media/libs/provider/anime/animepahe/mappers.py b/viu_media/libs/provider/anime/animepahe/mappers.py index fd1c9ae..ef59922 100644 --- a/viu_media/libs/provider/anime/animepahe/mappers.py +++ b/viu_media/libs/provider/anime/animepahe/mappers.py @@ -88,6 +88,7 @@ def map_to_server( episode: AnimeEpisodeInfo, translation_type: str, stream_links: list[tuple[str, str]], + headers: dict[str, str], ) -> Server: links = [ EpisodeStream( @@ -97,4 +98,4 @@ def map_to_server( ) for link in stream_links ] - return Server(name="kwik", links=links, episode_title=episode.title) + return Server(name="kwik", links=links, episode_title=episode.title, headers=headers) diff --git a/viu_media/libs/provider/anime/animepahe/provider.py b/viu_media/libs/provider/anime/animepahe/provider.py index 9adaf99..1e42d0a 100644 --- a/viu_media/libs/provider/anime/animepahe/provider.py +++ b/viu_media/libs/provider/anime/animepahe/provider.py @@ -1,6 +1,7 @@ import logging from functools import lru_cache from typing import Iterator, Optional +from urllib.parse import urlparse from ..base import BaseAnimeProvider from ..params import AnimeParams, EpisodeStreamsParams, SearchParams @@ -9,9 +10,11 @@ from ..utils.debug import debug_provider from .constants import ( ANIMEPAHE_BASE, ANIMEPAHE_ENDPOINT, + CDN_PROVIDER, JUICY_STREAM_REGEX, REQUEST_HEADERS, SERVER_HEADERS, + STREAM_HEADERS, ) from .extractor import process_animepahe_embed_page from .mappers import map_to_anime_result, map_to_search_results, map_to_server @@ -132,6 +135,7 @@ class AnimePahe(BaseAnimeProvider): quality = None translation_type = None stream_links = [] + stream_host = None # TODO: better document the scraping process for res_dict in res_dicts: @@ -170,13 +174,19 @@ class AnimePahe(BaseAnimeProvider): continue logger.debug(f"Found juicy stream: {juicy_stream.group(1)}") juicy_stream = juicy_stream.group(1) + stream_host = urlparse(juicy_stream).hostname quality = res_dict["resolution"] logger.debug(f"Found quality: {quality}") translation_type = data_audio stream_links.append((quality, juicy_stream)) if translation_type and stream_links: - yield map_to_server(episode, translation_type, stream_links) + headers = { + "User-Agent": self.client.headers["User-Agent"], + "Host": stream_host or CDN_PROVIDER, + **STREAM_HEADERS + } + yield map_to_server(episode, translation_type, stream_links, headers=headers) @lru_cache() def _get_episode_info(