Zgloszenie 3b03a744 ("Pornbusy pisze ze temporary problem with the host"). Wbrew
mojej pierwszej diagnozie to NIE byla awaria rodziny seekplayera: pornbusy w ogole
juz jej nie uzywa. Probka 10 najswiezszych scen (2026-08-21): morencius.com 4,
cdn.loadvid.com 4, playmate.to 1, upload18 1.
Morencius to zwykly JWPlayer z P.A.C.K.E.R.-em i HLS-em, bez Turnstile, wiec radzi
sobie z nim nasz generyczny rozpakowywacz BEZ zadnych zmian (oddaje gotowy
master.m3u8). Zamiast wiec zwracac None dla kazdego nieznanego hostera, najpierw
podajemy embed generycznemu: najgorszy przypadek to None, czyli stan sprzed zmiany.
Bylo 0/5, jest 3/5. Zostaja playmate.to (rozpakowywacz go nie zna) oraz upload18,
ktory pomijamy swiadomie, bo ma token zwiazany z IP.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
98 lines
3.9 KiB
Python
98 lines
3.9 KiB
Python
"""pornbusy.com, dispatch po hosterze z `itemprop="embedURL"`.
|
|
|
|
Katalog jest rozproszony po hosterach (próbka 120 scen): ~41% loadvid,
|
|
~20% rodzina seekplayer (av.ezplayer.me / av.seeks.cloud / 4k.upn.one /
|
|
4k.player4me.vip, objęte poszerzonym `_HOST_RE` silnika), ~8% zpi.cx,
|
|
~12% upload18 (token z wbitym `i=<ip>/24` = IP-bound), reszta ogon.
|
|
|
|
Obsługujemy trzy pierwsze (~69% katalogu):
|
|
- loadvid → manifest przez POST, marker `manifest_producer` (patrz hosters/loadvid.py)
|
|
- seekplayer → istniejący silnik (ten sam AES key/IV)
|
|
- zpi.cx → `embedURL` JEST plikiem wideo (mimo `.webm` w nazwie to mp4);
|
|
zweryfikowane: Range 206 `video/mp4`, bez Referera, bez tokena
|
|
|
|
upload18 i ogon zwracamy jako None, resolve na VPS wymusiłby proxowanie CAŁEGO
|
|
wideo (token IP-bound), co łamie zasadę no-video-proxy.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import re
|
|
from urllib.parse import urlparse
|
|
|
|
from app.extractors._fetch import fetch_tube_html
|
|
from app.extractors._models import StreamSource
|
|
from app.extractors.hoster import extract_stream_from_hoster
|
|
from app.extractors.hosters import loadvid, seekplayer_engine
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
_BASE = "https://pornbusy.com"
|
|
_EMBED_RE = re.compile(r'itemprop="embedURL"\s+content="([^"]+)"', re.IGNORECASE)
|
|
_IFRAME_RE = re.compile(r'<iframe[^>]+src="([^"]+)"', re.IGNORECASE)
|
|
_ZPI_HOST_RE = re.compile(r"^(?:[a-z0-9]+\.)?zpi\.cx$", re.IGNORECASE)
|
|
|
|
|
|
def extract(page_url: str, *, timeout: float = 60.0) -> list[StreamSource] | None:
|
|
html_text = fetch_tube_html(page_url, timeout=timeout)
|
|
m = _EMBED_RE.search(html_text) or _IFRAME_RE.search(html_text)
|
|
if not m:
|
|
log.info("pornbusy: no embedURL/iframe on %s", page_url)
|
|
return None
|
|
embed = m.group(1).strip()
|
|
if embed.startswith("//"):
|
|
embed = "https:" + embed
|
|
|
|
if loadvid.matches(embed):
|
|
return loadvid.extract(embed, timeout=timeout)
|
|
|
|
if seekplayer_engine.matches(embed):
|
|
sources = seekplayer_engine.extract(embed, timeout=timeout)
|
|
if not sources:
|
|
return None
|
|
player_origin = f"https://{urlparse(embed).hostname}/"
|
|
out: list[StreamSource] = []
|
|
for s in sources:
|
|
raw = dict(s.raw or {})
|
|
raw["proxy_no_verify"] = True
|
|
out.append(
|
|
StreamSource(
|
|
link=s.link,
|
|
type=s.type or "m3u8",
|
|
quality=s.quality,
|
|
# Referer = origin PLAYERA, nie strony (jak przy galaxyporn:
|
|
# z Refererem strony CDN zwraca 403).
|
|
referer=s.referer or player_origin,
|
|
raw=raw,
|
|
)
|
|
)
|
|
return out
|
|
|
|
host = (urlparse(embed).hostname or "").lower()
|
|
if _ZPI_HOST_RE.match(host):
|
|
# embedURL to bezpośrednio plik (rozszerzenie `.webm` myli, to mp4).
|
|
return [
|
|
StreamSource(
|
|
link=embed,
|
|
type="mp4",
|
|
raw={"mobile_direct_ok": True},
|
|
)
|
|
]
|
|
|
|
# Serwis dosypuje nowych hosterow: probka 10 najswiezszych scen (2026-08-21) dala
|
|
# morencius.com 4, cdn.loadvid.com 4, playmate.to 1, upload18 1. Morencius to zwykly
|
|
# JWPlayer z P.A.C.K.E.R.-em i HLS-em, bez Turnstile, wiec radzi sobie z nim nasz
|
|
# generyczny rozpakowywacz bez zadnych zmian (sprawdzone: oddaje gotowy master.m3u8).
|
|
# Probujemy go dla KAZDEGO nieznanego hostera zamiast od razu poddawac: gorszy
|
|
# przypadek to None, czyli dokladnie to, co bylo wczesniej.
|
|
try:
|
|
link = extract_stream_from_hoster(embed, referer=page_url)
|
|
except Exception as e:
|
|
log.info("pornbusy: generyczny hoster padl dla %s: %s", host, e)
|
|
link = None
|
|
if link:
|
|
log.info("pornbusy: %s rozwiazany generycznym hosterem", host)
|
|
return [StreamSource(link=link, type="m3u8" if ".m3u8" in link else "mp4")]
|
|
|
|
log.info("pornbusy: unsupported hoster %s (%s)", host, page_url)
|
|
return None
|