"""Uzupelnia obsade, studio i tagi filmow z serwisow dooplay po zmianie motywu (2026-10). Mangoporn, streamporn.li i pandamovies przeszly na motyw "vid": obsada tylko w JSON-LD, studio i rok w chipach bez rel="tag". Parser tego nie czytal, wiec filmy dodane od ok. 5.10 przyszly bez obsady i czesto bez studia (cichy fail parsera, ingest konczyl sie "errors: 0"). Skrypt pobiera ich strony na nowo i puszcza przez resolve_movie, ktory przy znanym refie tylko uzupelnia puste pola i dopina obsade/tagi. Strony przez proxy, bo mangoporn z VPS bywa niedostepny (timeout, blad TLS). python3 /srv/scripts/backfill_dooplay_metadata.py # dry-run: tylko liczy python3 /srv/scripts/backfill_dooplay_metadata.py --apply [--since 2026-10-01] """ from __future__ import annotations import argparse import functools import logging import app.connectors.dooplay as dp from app.config import get_settings dp.browser_get = functools.partial(dp.browser_get, proxy=get_settings().brightdata_proxy_url) from sqlalchemy import text # noqa: E402 from app.db import session_scope # noqa: E402 from app.normalize.movies import normalize_movie # noqa: E402 from app.resolve.movie_resolver import resolve_movie # noqa: E402 _CONNECTORS = { "mangoporn": dp.MangopornConnector, "streampornvip": dp.StreampornVipConnector, "pandamovies": dp.PandamoviesConnector, } _REFS_SQL = """ SELECT r.movie_id, r.external_id, r.url, so.id AS source_id, so.name FROM movie_external_refs r JOIN sources so ON so.id = r.source_id JOIN movies m ON m.id = r.movie_id WHERE so.name = ANY(:names) AND m.created_at >= :since AND r.url IS NOT NULL AND (m.studio_id IS NULL OR NOT EXISTS (SELECT 1 FROM movie_performers p WHERE p.movie_id = m.id)) ORDER BY m.created_at DESC """ def main() -> None: ap = argparse.ArgumentParser() ap.add_argument("--apply", action="store_true") ap.add_argument("--since", default="2026-10-01") args = ap.parse_args() logging.basicConfig(level=logging.WARNING) with session_scope() as s: refs = s.execute(text(_REFS_SQL), {"names": list(_CONNECTORS), "since": args.since}).all() print(f"refow do uzupelnienia: {len(refs)}", flush=True) if not args.apply: return conns = {name: cls() for name, cls in _CONNECTORS.items()} done = failed = with_cast = 0 for n, ref in enumerate(refs, 1): try: raw = conns[ref.name]._fetch_detail(ref.url) except Exception as e: # noqa: BLE001 failed += 1 print(f" blad {ref.name} {ref.url}: {str(e)[:100]}", flush=True) continue if raw is None: failed += 1 continue norm = normalize_movie(raw) if norm.external_id != ref.external_id: failed += 1 print(f" inny id {ref.external_id} -> {norm.external_id}, pomijam", flush=True) continue with session_scope() as s: resolve_movie(s, norm=norm, source_id=ref.source_id) done += 1 with_cast += bool(raw.performers) if n % 25 == 0: print(f"... {n}/{len(refs)}, uzupelnione {done}, z obsada {with_cast}, bledy {failed}", flush=True) print(f"uzupelnione: {done}, z obsada: {with_cast}, bledy: {failed}", flush=True) if __name__ == "__main__": main()