diff --git a/app/extractors/tubes/yespornvip.py b/app/extractors/tubes/yespornvip.py index 0eda42f..41e5938 100644 --- a/app/extractors/tubes/yespornvip.py +++ b/app/extractors/tubes/yespornvip.py @@ -1,22 +1,23 @@ """yesporn.vip — KVS engine direct stream extractor. -User bug-report 2026-05-27: "Yespornvip dalej nie działa". Origin `tube:yespornvip` -istniał w playback_sources ale brak wpisu w `_REGISTRY` → `try_extract()` zwracał -None → mobile player no-source. +User bug-report 2026-05-27 (#1, scene 0d8ec317): "Yespornvip dalej nie działa". +Origin `tube:yespornvip` istniał w playback_sources ale brak wpisu w `_REGISTRY` +→ `try_extract()` zwracał None → mobile player no-source. Detail page sceny linkuje do `/embed/` w iframe. Embed page renderuje KVS player z `flashvars`: - - `video_url: 'function/0/https://yesporn.vip/get_file/////.mp4/?embed=true'` - - `event_reporting2: 'https://yesporn.vip/get_file/.../.mp4/'` (analytics ping - URL, ale jest valid get_file) - - `video_url_text: '480p'` — quality label dla video_url + - `video_url: 'function/0/https://yesporn.vip/get_file/7//.../.mp4/?embed=true'` + — **NIE używać.** Server `/get_file/7/` wymaga PHPSESSID + cookies z embed + page (testowane 2026-05-29: 404 nawet z fresh tokenem, mobile-side cookies + nie matchują VPS-side session). KVS kt_player.js loaduje to wewnątrz + embed page gdzie cookies są dostępne. + - `event_reporting2: 'https://yesporn.vip/get_file/1//.../.mp4/'` + — server `/get_file/1/` jest standalone, time-bound signed URL, **200 OK** + direct fetch z headerami (UA + Referer). Bierzemy to. + - `video_url_text: '480p'` — quality label. -`function/0/` to KVS player JS dekoder prefix — dla type 0 to passthrough, -URL po prefixie jest bezpośrednio użyteczny. - -Single-quality (480p) z embed bo wyższe (`video_alt_url`) to redirect URLs -(`video_alt_url_redirect: '1'`), nie direct streamy. CDN time-bound signed, -mobile gra direct. +Single quality (480p) z embed. CDN time-bound signed, mobile gra direct z phone +IP (zero VPS bandwidth). """ from __future__ import annotations @@ -30,9 +31,10 @@ log = logging.getLogger(__name__) _BASE = "https://yesporn.vip" -# `video_url: 'function/0/https://.../get_file/...mp4/?embed=true'` lub bez prefixu -_VIDEO_URL_RE = re.compile( - r"video_url\s*:\s*'(?:function/0/)?(https?://[^']+/get_file/[^']+\.mp4/?[^']*)'", +# `event_reporting2: 'https://.../get_file/1/.../.mp4/'` — analytics ping URL +# który (per testom 2026-05-29) jest sessionless i 200 OK direct. +_EVENT_REPORTING2_RE = re.compile( + r"event_reporting2\s*:\s*'(https?://[^']+/get_file/[^']+\.mp4/?[^']*)'", re.IGNORECASE, ) _QUALITY_RE = re.compile(r"video_url_text\s*:\s*'([^']*)'", re.IGNORECASE) @@ -52,15 +54,12 @@ def extract(page_url: str, *, timeout: float = 60.0) -> list[StreamSource] | Non html = fetch_tube_html(embed_url, timeout=timeout) - m = _VIDEO_URL_RE.search(html) + m = _EVENT_REPORTING2_RE.search(html) if not m: - log.info("yespornvip: no video_url in flashvars on %s", embed_url) + log.info("yespornvip: no event_reporting2 in flashvars on %s", embed_url) return None url = m.group(1) - # `?embed=true` parametr — get_file z embed=true może zwracać HTML wrapper - # zamiast 302 do CDN. Zostawiamy bo player tak go używa, ale jeśli 302 nie - # wskoczy poprawnie to fallback usunie param. quality = None q_match = _QUALITY_RE.search(html) if q_match: