diff --git a/app/extractors/tubes/galaxyporn.py b/app/extractors/tubes/galaxyporn.py index 00a3e16..a471efc 100644 --- a/app/extractors/tubes/galaxyporn.py +++ b/app/extractors/tubes/galaxyporn.py @@ -27,6 +27,28 @@ _IFRAME_RE = re.compile(r']+src="([^"]+)"', re.IGNORECASE) #: Hostery, ktorych NIE resolwujemy serwerowo, tylko oddajemy telefonowi do WebView. _NEEDS_WEBVIEW_RE = re.compile(r"vikingfile\.", re.IGNORECASE) +#: Link do pliku na vikingfile, gdziekolwiek w HTML (iframe ALBO zwykly ). +_VIKINGFILE_RE = re.compile(r"https?://vikingfile\.com/f/[A-Za-z0-9]+", re.IGNORECASE) + + +def _vikingfile_source(html_text: str, page_url: str) -> list[StreamSource] | None: + """Link do vikingfile z DOWOLNEGO miejsca strony, nie tylko z iframe'a. + + Na starszych stronach vikingfile siedzi w zwyklym ``, a iframe wskazuje + stary, martwy player. Dlatego szukamy po calym HTML, nie po samym iframie. + """ + mv = _VIKINGFILE_RE.search(html_text) + if not mv: + return None + return [ + StreamSource( + link=mv.group(0), + quality="hoster", + type="hoster", + referer=page_url, + raw={"extractor": "galaxyporn", "hoster": "vikingfile"}, + ) + ] def extract(page_url: str, *, timeout: float = 60.0) -> list[StreamSource] | None: @@ -34,7 +56,7 @@ def extract(page_url: str, *, timeout: float = 60.0) -> list[StreamSource] | Non m = _IFRAME_RE.search(html_text) if not m: log.info("galaxyporn: no iframe on %s", page_url) - return None + return _vikingfile_source(html_text, page_url) iframe_src = m.group(1).strip() if iframe_src.startswith("//"): iframe_src = "https:" + iframe_src @@ -62,12 +84,26 @@ def extract(page_url: str, *, timeout: float = 60.0) -> list[StreamSource] | Non ) ] - sources = seekplayer_engine.extract(iframe_src, timeout=timeout) + try: + sources = seekplayer_engine.extract(iframe_src, timeout=timeout) + except Exception as e: + # Martwy player potrafi RZUCIC (HosterDead przy 404 z /api/v1/video), a nie tylko + # oddac pustke. Bez tego wyjatek wychodzil na zewnatrz i ratunek z vikingfile + # nigdy sie nie wykonywal. + log.info("galaxyporn: seekplayer rzucil dla %s (%s), probuje vikingfile", iframe_src, e) + return _vikingfile_source(html_text, page_url) if not sources: - # Nie oddajemy iframe'a jako type='hoster', seekplayer to SPA, w WebView - # user zobaczy pusty player. Lepiej None (źródło jako nierozwiązane). - log.info("galaxyporn: seekplayer resolve failed for %s", iframe_src) - return None + # Iframe bywa ZWIETRZALY. Serwis przeniosl pliki na vikingfile, ale w starszych + # wpisach zostawil stary iframe (news.upns.pro, sport.seekplays.com, + # galaxy.4meplayer.pro), ktory dzis wypisuje "Video is not ready yet", a jego API + # oddaje payload BEZ jakiegokolwiek adresu wideo (75% probki 16 scen). Wygladalo to + # na skasowany katalog, ale na TYCH SAMYCH stronach jest link do vikingfile, a pliki + # tam zyja: sprawdzone trzy, 890 MB / 742 MB / 2,5 GB, nazwy zgodne ze scenami. + # Dlatego zamiast poddawac sie, siegamy po vikingfile. Kolejnosc jest celowa: + # seekplayer PIERWSZY, bo resolwuje sie po naszej stronie i gra bez CAPTCHA, + # a vikingfile to ratunek, ktory kosztuje usera przejscie Turnstile w WebView. + log.info("galaxyporn: seekplayer padl dla %s, probuje vikingfile", iframe_src) + return _vikingfile_source(html_text, page_url) # Referer MUSI być hostem PLAYERA (np. https://galaxy.4meplayer.pro/), NIE # galaxyporn.net, zweryfikowane: ten sam manifest z Refererem galaxyporn = 403,