fix(proxy): hdporn.gg i fullmovies, swiezy adres zamiast 410 w zapasowym proxy
get_file jest przypiety do IP i sesji ladujacej strone i bywa jednorazowy. Gdy resolver na telefonie zawiodl, proxy dostawalo ten sam zuzyty adres i oddawalo 410/503: 14 urzadzen w tydzien mialo na tych serwisach same porazki (inne serwisy graly im bez problemu). Teraz po 403/404/410 albo trwalym 503 proxy pobiera strone na nowo (try_extract) i bierze adres w tej samej jakosci. Test: adres pobrany z innego IP przez proxy 410 -> z odswiezaniem 206 video/mp4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0f128d2e17
commit
ba53f872d2
4 changed files with 64 additions and 4 deletions
|
|
@ -585,6 +585,40 @@ async def sxyprn_thumb(post_id: str) -> Response:
|
|||
)
|
||||
|
||||
|
||||
#: Po tych statusach proxy pobiera strone tube na nowo (gdy token ma rf + rh "tube:...").
|
||||
#: 503 dopiero po nieudanym ponowieniu: nowy token bywa kierowany na inny wezel CDN.
|
||||
_TUBE_REFRESH_STATUSES = frozenset({403, 404, 410, 503})
|
||||
_QUALITY_IN_URL_RE = re.compile(r"_(\d{3,4})[a-z]?\.mp4", re.IGNORECASE)
|
||||
|
||||
|
||||
async def _fresh_tube_link(sitetag: str, page_url: str, old_target: str) -> str | None:
|
||||
"""Swiezy adres pliku z ekstraktora tube, w tej samej jakosci co `old_target`.
|
||||
|
||||
hdporn.gg / fullmovies.xxx: get_file jest przypiety do IP ladujacego strone i bywa
|
||||
jednorazowy. Telefon, ktoremu nie wyszedl wlasny resolver, dostawal od proxy ten sam
|
||||
zuzyty adres i konczyl na 410/503 (14 urzadzen w tydzien z samymi porazkami, 2026-10-02).
|
||||
"""
|
||||
import anyio
|
||||
|
||||
from app.extractors import try_extract
|
||||
|
||||
try:
|
||||
sources = await anyio.to_thread.run_sync(lambda: try_extract(sitetag, page_url))
|
||||
except Exception as e: # noqa: BLE001 (HosterDead/TubePageError: zostaje stary blad)
|
||||
log.info("proxy: odswiezenie %s nie wyszlo: %s", page_url, e)
|
||||
return None
|
||||
links = [s.link for s in (sources or []) if s.link]
|
||||
if not links:
|
||||
return None
|
||||
want = _QUALITY_IN_URL_RE.search(old_target)
|
||||
if want:
|
||||
for link in links:
|
||||
m = _QUALITY_IN_URL_RE.search(link)
|
||||
if m and m.group(1) == want.group(1):
|
||||
return link
|
||||
return links[0]
|
||||
|
||||
|
||||
async def _refetch_mixdrop_url(session: "AsyncSession", embed_url: str) -> str | None:
|
||||
"""Re-fetch mixdrop embed, decode P.A.C.K.E.R., extract fresh MDCore.wurl.
|
||||
Cookies persist w session, użytkowane potem do mp4 GET (same-session bind).
|
||||
|
|
@ -870,6 +904,23 @@ async def proxy_stream(
|
|||
stream=True,
|
||||
follow_redirects=True,
|
||||
)
|
||||
if (
|
||||
upstream.status_code in _TUBE_REFRESH_STATUSES
|
||||
and refetch_url
|
||||
and (refetch_hoster or "").startswith("tube:")
|
||||
and method.upper() in ("GET", "HEAD")
|
||||
):
|
||||
fresh = await _fresh_tube_link(refetch_hoster[5:], refetch_url, target)
|
||||
if fresh:
|
||||
log.info("proxy: upstream %d, swiezy adres z %s", upstream.status_code, refetch_url[:70])
|
||||
await upstream.aclose()
|
||||
target = fresh
|
||||
cached_target = None # nowy cel: po sukcesie cache dostanie jego koncowy adres
|
||||
upstream = await client.send(
|
||||
client.build_request(method, target, headers=headers),
|
||||
stream=True,
|
||||
follow_redirects=True,
|
||||
)
|
||||
if upstream.status_code >= 400:
|
||||
status = upstream.status_code
|
||||
ups_headers = dict(upstream.headers)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@ _SOURCE_RE = re.compile(
|
|||
_SKIP_QUALITY_RE = re.compile(r"2160|1440|4k", re.IGNORECASE)
|
||||
|
||||
|
||||
def resolve(page_url: str, base_url: str, *, timeout: float = 30.0) -> list[StreamSource] | None:
|
||||
def resolve(
|
||||
page_url: str, base_url: str, *, timeout: float = 30.0, sitetag: str | None = None
|
||||
) -> list[StreamSource] | None:
|
||||
if not _HAS_CURL_CFFI:
|
||||
log.info("source_getfile: curl_cffi unavailable — %s", page_url)
|
||||
return None
|
||||
|
|
@ -59,9 +61,16 @@ def resolve(page_url: str, base_url: str, *, timeout: float = 30.0) -> list[Stre
|
|||
if _SKIP_QUALITY_RE.search(quality):
|
||||
log.info("source_getfile: skip broken-CDN quality %r on %s", quality, page_url)
|
||||
continue
|
||||
raw: dict = {"mobile_direct_ok": True}
|
||||
if sitetag:
|
||||
# get_file jest przypiety do IP tego, kto zaladowal strone, i bywa jednorazowy,
|
||||
# wiec proxy (zapas, gdy resolver na telefonie zawiedzie) po 403/410 pobiera
|
||||
# strone na nowo zamiast oddac blad (stream_proxy._fresh_tube_link, 2026-10-02).
|
||||
raw["refetch_url"] = page_url
|
||||
raw["refetch_hoster"] = f"tube:{sitetag}"
|
||||
out.append(StreamSource(
|
||||
link=url, type="mp4", quality=quality or None,
|
||||
referer=base_url + "/", raw={"mobile_direct_ok": True},
|
||||
referer=base_url + "/", raw=raw,
|
||||
))
|
||||
|
||||
if not out:
|
||||
|
|
|
|||
|
|
@ -16,4 +16,4 @@ _BASE = "https://www.fullmovies.xxx"
|
|||
|
||||
|
||||
def extract(page_url: str, *, timeout: float = 30.0) -> list[StreamSource] | None:
|
||||
return _source_getfile.resolve(page_url, _BASE, timeout=timeout)
|
||||
return _source_getfile.resolve(page_url, _BASE, timeout=timeout, sitetag="fullmoviesxxx")
|
||||
|
|
|
|||
|
|
@ -14,4 +14,4 @@ _BASE = "https://www.hdporn.gg"
|
|||
|
||||
|
||||
def extract(page_url: str, *, timeout: float = 30.0) -> list[StreamSource] | None:
|
||||
return _source_getfile.resolve(page_url, _BASE, timeout=timeout)
|
||||
return _source_getfile.resolve(page_url, _BASE, timeout=timeout, sitetag="hdporngg")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue