"""Mixdrop embed hoster — P.A.C.K.E.R. eval → MDCore.wurl direct mp4. Pattern (verified 2026-05-15 via curl_cffi impersonate=chrome120): 1. Fetch `https://mixdrop.my/e/` → 200 z 95KB body, redirect 301 do `https://m1xdrop.bz/e/` (current TLD). 2. Body zawiera P.A.C.K.E.R. obfuscated JS block: `eval(function(p,a,c,k,e,d){...}('...packed...',N,N,'...|...'.split('|'),0,{}))` 3. yt-dlp's `decode_packed_codes()` rozkrywa do ~390 chars JavaScript: `MDCore.wurl="//a-delivery22.mxcontent.net/v2/.mp4?s=&e=&_t="` 4. URL na `mxcontent.net` zwraca **direct mp4** (Content-Type: video/mp4, Content-Length: ~485MB) — działa z Hetzner VPS IP, brak token IP-bind. `s` to signed token (HMAC?), `e` to expiry timestamp (unix sec), `_t` to issued timestamp. Token jest valid ~24h od `_t`. Refetching embed page po expiry zwraca nowy URL. Active mango movies: 203 playbacks origin='mangoporn:mixdrop' w DB. """ from __future__ import annotations import logging import re from app.extractors._fetch import browser_get from app.extractors._models import StreamSource log = logging.getLogger(__name__) _PACKER_RE = re.compile( r"eval\(function\(p,a,c,k,e,d\)\{.+?\}\(.+?\)\)", re.DOTALL, ) _MP4_URL_RE = re.compile(r'MDCore\.wurl\s*=\s*"([^"]+\.mp4[^"]*)"') def extract(page_url: str, *, timeout: float = 30.0) -> list[StreamSource] | None: res = browser_get(page_url, timeout=timeout) if res.status_code != 200 or not res.text: log.info("mixdrop: fetch fail status=%s url=%s", res.status_code, page_url) return None m = _PACKER_RE.search(res.text) if not m: log.info("mixdrop: no P.A.C.K.E.R. block in %s (page changed?)", page_url) return None try: from yt_dlp.utils import decode_packed_codes decoded = decode_packed_codes(m.group(0)) except Exception as e: log.warning("mixdrop: decode_packed_codes failed: %s", e) return None url_match = _MP4_URL_RE.search(decoded) if not url_match: log.info("mixdrop: no MDCore.wurl in decoded payload (len=%d)", len(decoded)) return None raw_url = url_match.group(1) # URL z mixdrop często jest protocol-relative (`//a-delivery22...`). if raw_url.startswith("//"): raw_url = "https:" + raw_url return [ StreamSource( link=raw_url, quality=None, # mixdrop nie listuje quality variants w MDCore type="mp4", referer="https://mixdrop.my/", # mxcontent CDN wymaga **same-session cookies** z embed page + # Chrome JA3. Backend `extract` zamyka sesję po fetch → mobile # próbuje mp4 bez cookies → 403. Proxy MUSI re-fetchować embed # w fresh curl_cffi session, extract nowy mp4 URL, stream. # `refetch_url` w raw → token field `rf` → proxy refresh logic. raw={ "proxy_impersonate": True, "refetch_url": page_url, # embed page do re-extract "refetch_hoster": "mixdrop", }, ) ]