diff --git a/app/extractors/__init__.py b/app/extractors/__init__.py index f3e2d0a..87a205c 100644 --- a/app/extractors/__init__.py +++ b/app/extractors/__init__.py @@ -219,13 +219,14 @@ _REGISTRY: dict[str, Callable[[str], list[StreamSource] | None]] = { # 0dayxx + pornditt + pornhat, USUNIĘTE CAŁKOWICIE 2026-06-22 (user request): orphan # factories (0-0.2% canonical match), zastępujemy lepszymi źródłami. Dane skasowane. # CF-protected tube, curl_cffi w fetch_tube_html bypassa JA3, embed-iframe pattern. - # perverzija: BYŁ natywny HLS przez xtremestream/xs1.php (2026-07-28), ale strona - # przeszła na mixdrop (2026-08-18: 520 błędów "Input does not start with #EXTM3U", - # zero sukcesów, bo xs1.php oddaje już HTML zamiast manifestu). Teraz embed-iframe - # wyłuskuje mixdrop i oddaje type='hoster' → telefon resolwuje w WebView (mixdrop - # gejtuje reCAPTCHA v3 na IP datacenter, przechodzi dopiero z residential). Natywny - # ekstraktor `perverzija.py` zostaje w drzewie, gdyby xtremestream wrócił. - "perverzijacom": _embed_iframe.extract, + # perverzija: natywny HLS przez xtremestream/xs1.php. Uwaga na regresję z 2026-08-18: + # przestawiliśmy to wtedy na embed-iframe/mixdrop na podstawie JEDNEJ strony, która + # akurat miała mixdrop. Sprawdzenie 8 losowych stron (2026-08-20) daje 8/8 działających + # manifestów xs1.php, na SZEŚCIU różnych subdomenach (perv, j2, moviekh, pervl1, + # pervl3, pervm1) — host rotuje, regex w `perverzija.py` to obejmuje. Warunkiem 200 jest + # Referer równy URL-owi playera; zły Referer daje 403 z HTML-em i to on wyglądał jak + # "Input does not start with #EXTM3U". Zanim to znowu przełączysz: sprawdź PRÓBKĘ stron. + "perverzijacom": perverzija.extract, # Special: WebView-only (Yii2 session-bound player). "paradisehillcc": paradisehill.extract, # PornDoe, dołączony 2026-05-21 (theporndude audit). Stream URL nie inline w diff --git a/app/extractors/tubes/perverzija.py b/app/extractors/tubes/perverzija.py index a8d400c..cc8fbdb 100644 --- a/app/extractors/tubes/perverzija.py +++ b/app/extractors/tubes/perverzija.py @@ -52,8 +52,18 @@ def extract(page_url: str, *, timeout: float = 60.0) -> list[StreamSource] | Non m = _PLAYER_IFRAME_RE.search(html) if not m: - log.info("perverzija: brak iframe xtremestream na %s", page_url) - return None + # ~10% katalogu siedzi na innym playerze niż xtremestream (próbka 30 stron + # 2026-08-20: 27 xtremestream, 1 mixdrop, 1 playhydrax, 1 nie do pobrania). + # Oddajemy je generycznemu embed-iframe: wychodzi type='hoster', czyli telefon + # resolwuje je po swojej stronie, zamiast żeby scena wyglądała na martwą. + log.info("perverzija: brak xtremestream na %s, probuje embed-iframe", page_url) + from app.extractors.tubes import _embed_iframe + + try: + return _embed_iframe.extract(page_url, timeout=timeout) + except Exception as e: + log.info("perverzija: embed-iframe fallback tez padl %s: %s", page_url, e) + return None host, vid = m.group("host"), m.group("id") player_url = f"https://{host}/player/index.php?data={vid}" @@ -66,7 +76,17 @@ def extract(page_url: str, *, timeout: float = 60.0) -> list[StreamSource] | Non quality=f"{q}p", type="m3u8", referer=player_url, - raw={"extractor": "perverzija", "player": player_url, "q": q}, + raw={ + "extractor": "perverzija", + "player": player_url, + "q": q, + # Segmenty NIE są IP-bound i nie potrzebują Referera: segment pobrany + # z domowego łącza po manifeście wziętym na VPS oddał 200 i 76 kB + # zaczynające się od 0x47 (sync MPEG-TS), test 2026-08-20. Dzięki temu + # przez VPS idzie sam manifest (~16 kB) przez /proxy/hls, a segmenty + # telefon ciągnie prosto z xspcdn. Bez tej flagi całe wideo szło proxy. + "mobile_direct_ok": True, + }, ) ) return out or None