"""8kporner.com — JWPlayer sources → direct mp4 na OK.ru CDN. Dodany 2026-07-27. **Pułapka, o którą łatwo się rozbić:** JSON-LD `contentUrl` na tej stronie to ZAWSZE 144p (256x144, sprawdzone). Prawdziwe jakości siedzą wyłącznie w tablicy `sources` JWPlayera. Skopiowanie wzorca z `hqfap.py` (który czyta `contentUrl`) wysłałoby każdemu userowi 144p. Fetch idzie przez `?link1=watch&id=`, bo kanoniczna forma `/watch/_.html` jest CF-blokowana (403, również przez proxy). CDN to `vd*.okcdn.ru` / `ok6-*.vkuser.net` — ta sama rodzina co 4k69/hqfap: `srcIp` jest w URL-u, ale NIE jest egzekwowane, więc token działa cross-IP (mobile_direct). **Limit przepustowości:** OK.ru dławi pojedyncze połączenie do ~2,1 Mbps. 1080p potrzebuje 3,8 Mbps, 2K 6,2, a 4K 13,8 — czyli nie dociągną się w czasie rzeczywistym i dałyby „loading forever" (ten sam objaw co przy 4K na fullmovies). Dlatego oddajemy maksymalnie 720p (1,5 Mbps), zgodnie z decyzją podjętą już dla 4k69. """ from __future__ import annotations import logging import re from app.extractors._fetch import fetch_tube_html from app.extractors._models import StreamSource log = logging.getLogger(__name__) _BASE = "https://8kporner.com" _SCENE_ID_RE = re.compile(r"_(\d+)\.html") # Pary z JWPlayer setupu: "file":"","label":"720p" _SOURCE_RE = re.compile( r'"file"\s*:\s*"(https?://[^"]+)"\s*,\s*"label"\s*:\s*"([^"]+)"', re.IGNORECASE ) # Powyżej 720p CDN nie nadąża (patrz docstring). _MAX_HEIGHT = 720 def _height(label: str) -> int: lab = (label or "").strip().lower() if lab.startswith("4k"): return 2160 if lab.startswith("2k"): return 1440 m = re.match(r"(\d{3,4})", lab) return int(m.group(1)) if m else 0 def extract(page_url: str, *, timeout: float = 60.0) -> list[StreamSource] | None: # Kanoniczny URL → forma omijająca CF. m = _SCENE_ID_RE.search(page_url) fetch_url = f"{_BASE}/?link1=watch&id={m.group(1)}" if m else page_url html_text = fetch_tube_html(fetch_url, timeout=timeout) seen: set[str] = set() out: list[StreamSource] = [] for sm in _SOURCE_RE.finditer(html_text): url = sm.group(1).replace("&", "&") label = sm.group(2).strip() h = _height(label) if url in seen or h == 0 or h > _MAX_HEIGHT: continue seen.add(url) out.append( StreamSource( link=url, type="mp4", quality=label, referer=_BASE + "/", # srcIp nieegzekwowane (jak 4k69) → telefon gra direct z CDN. raw={"mobile_direct_ok": True}, ) ) if not out: log.info("8kporner: brak sources <=720p na %s", page_url) return None out.sort(key=lambda s: _height(s.quality or ""), reverse=True) return out