feat(perverzija): natywny HLS zamiast WebView z reklamami
Some checks failed
Backend tests / test (push) Has been cancelled
Some checks failed
Backend tests / test (push) Has been cancelled
Bug-reports 40ec88cc / 92e9133e ('zacina sie na pierwszych sekundach i robi loop').
Trace CDP wykazal: iframe pervl4.xtremestream.xyz/player/index.php?data=<md5> ma w
HTML WYLACZNIE preroll/midroll (opencdn.b-cdn.net) - to one lecialy w petli. Wideo
player dociaga dopiero w runtime:
GET /player/xs1.php?data=<md5>&q=<480|720> -> GOTOWY manifest HLS (#EXTM3U, VOD,
segmenty ~4,17s z PELNYMI URL-ami do pervl4.xspcdn{01..10}.sa.com/cdn/down/...).
Segmenty maja rozszerzenie .html (kamuflaz), ale to zwykly HLS - nic nie trzeba
deszyfrowac ani skladac.
Nowy extractor zwraca oba warianty jako type='m3u8' z referer=index.php?data=<md5>
(taki Referer wysyla przegladarka; bez niego ryzyko 403). Zweryfikowane na prodzie:
2 zrodla, oba HTTP 200 i #EXTM3U (44245 / 41142 B).
Uwaga: sciezka manifestu nie konczy sie na .m3u8, wiec musi isc przez /proxy/hls
passthrough (casus pornhat) - segmenty i tak leca direct z CDN.
This commit is contained in:
parent
c1ba536607
commit
580e4db535
2 changed files with 78 additions and 1 deletions
|
|
@ -34,6 +34,7 @@ from app.extractors.tubes import (
|
|||
galaxyporn,
|
||||
hdporngg,
|
||||
hqfap,
|
||||
perverzija,
|
||||
hqporner,
|
||||
fullporner,
|
||||
kporner8,
|
||||
|
|
@ -188,7 +189,11 @@ _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.
|
||||
"perverzijacom": _embed_iframe.extract,
|
||||
# perverzija — natywny HLS (2026-07-28). Player xtremestream ma w HTML tylko
|
||||
# preroll/midroll (grały w pętli, bug 40ec88cc/92e9133e), a wideo dociąga runtime:
|
||||
# xs1.php?data=<md5>&q=<480|720> zwraca GOTOWY manifest HLS z pełnymi URL-ami
|
||||
# segmentów. Zamiast WebView oddajemy m3u8 wprost.
|
||||
"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
|
||||
|
|
|
|||
72
app/extractors/tubes/perverzija.py
Normal file
72
app/extractors/tubes/perverzija.py
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
"""perverzija.com (tube.perverzija.com) — natywny HLS zamiast WebView.
|
||||
|
||||
Ustalone trace'em CDP (2026-07-28, bug-reports 40ec88cc / 92e9133e "zacina się na
|
||||
pierwszych sekundach i robi loop"):
|
||||
|
||||
Strona osadza iframe `pervl4.xtremestream.xyz/player/index.php?data=<md5>`. Samo źródło
|
||||
tego iframe'a NIE zawiera streamu (jest tam wyłącznie preroll/midroll z opencdn.b-cdn.net
|
||||
— to one leciały w pętli). Player dociąga wideo dopiero w runtime:
|
||||
|
||||
GET /player/xs1.php?data=<md5>&q=<480|720> → GOTOWY manifest HLS (#EXTM3U, VOD,
|
||||
segmenty po ~4,17 s z PEŁNYMI URL-ami do pervl4.xspcdn{01..10}.sa.com/cdn/down/...)
|
||||
|
||||
Segmenty mają rozszerzenie `.html` (kamuflaż), ale to zwykły HLS — nic nie trzeba
|
||||
deszyfrować ani składać. Wystarczy oddać URL `xs1.php` jako `type='m3u8'`.
|
||||
|
||||
WAŻNE (mobile): ścieżka manifestu NIE kończy się na `.m3u8`, a expo-video bez contentType
|
||||
potraktowałby ją jako progressive i padł — dokładnie casus pornhat. Dlatego manifest musi
|
||||
iść przez `/proxy/hls` (passthrough); segmenty i tak lecą direct z CDN, więc przez VPS
|
||||
przechodzi ~41 KB, nie wideo.
|
||||
|
||||
`referer` celowo wskazuje na `index.php?data=<md5>` — taki Referer wysyła przeglądarka
|
||||
przy wywołaniu xs1.php i bez niego jest ryzyko 403.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
from app.extractors._models import StreamSource
|
||||
from app.extractors import browser_get
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# iframe playera: https://pervl4.xtremestream.xyz/player/index.php?data=<32 hex>
|
||||
_PLAYER_IFRAME_RE = re.compile(
|
||||
r"https?://(?P<host>[a-z0-9\-]+\.xtremestream\.[a-z]+)/player/index\.php\?data=(?P<id>[0-9a-f]{16,64})",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
# Player wystawia te dwie jakości (trace: xs1.php?...&q=480 i &q=720). Kolejność =
|
||||
# preferencja (najlepsza pierwsza), tak jak w pozostałych ekstraktorach.
|
||||
_QUALITIES = ("720", "480")
|
||||
|
||||
|
||||
def extract(page_url: str, *, timeout: float = 60.0) -> list[StreamSource] | None:
|
||||
try:
|
||||
res = browser_get(page_url, timeout=timeout)
|
||||
html = res.text if hasattr(res, "text") else str(res)
|
||||
except Exception as e:
|
||||
log.info("perverzija page fetch failed %s: %s", page_url, e)
|
||||
return None
|
||||
|
||||
m = _PLAYER_IFRAME_RE.search(html)
|
||||
if not m:
|
||||
log.info("perverzija: brak iframe xtremestream na %s", page_url)
|
||||
return None
|
||||
|
||||
host, vid = m.group("host"), m.group("id")
|
||||
player_url = f"https://{host}/player/index.php?data={vid}"
|
||||
|
||||
out: list[StreamSource] = []
|
||||
for q in _QUALITIES:
|
||||
out.append(
|
||||
StreamSource(
|
||||
link=f"https://{host}/player/xs1.php?data={vid}&q={q}",
|
||||
quality=f"{q}p",
|
||||
type="m3u8",
|
||||
referer=player_url,
|
||||
raw={"extractor": "perverzija", "player": player_url, "q": q},
|
||||
)
|
||||
)
|
||||
return out or None
|
||||
Loading…
Add table
Reference in a new issue