"""Przywraca ostatnie zrodla scen zabite przytrzymaniem w apce, jesli strona zyje (2026-10-15). Do 15.10 przytrzymanie "mark as broken" zabijalo zrodlo bez sprawdzenia. W 30 dni 490 scen zostalo przez to bez zadnego zrodla i zniknelo z list (porndoe: 403 z sieci uzytkownika, galaxyporn, perverzija, javflix...). Od 15.10 serwer sprawdza ostatnie zrodlo przed oznaczeniem; ten skrypt cofa wczesniejsze przypadki, ale tylko z POZYTYWNYM dowodem: - ekstraktor zwraca zrodla (strona i film istnieja), - dla serwisow grajacych tylko w WebView (ekstraktor nic nie pobiera): strona odpowiada 200. python scripts/revive_user_marked_last_sources.py # podglad python scripts/revive_user_marked_last_sources.py --apply [--days 30] """ from __future__ import annotations import argparse import logging from collections import Counter import sqlalchemy as sa from app.db import session_scope from app.extractors import is_vps_blocked_fallback, try_extract from app.extractors._fetch import browser_get log = logging.getLogger(__name__) def _alive(origin: str, page_url: str) -> bool: if not origin.startswith(("tube:", "pornapp:")): return False sitetag = origin.split(":", 1)[1] if is_vps_blocked_fallback(sitetag): try: return browser_get(page_url, timeout=20.0).status_code < 400 except Exception: return False try: return bool(try_extract(sitetag, page_url)) except Exception: return False def run(apply: bool, days: int) -> dict: with session_scope() as s: rows = s.execute( sa.text( """ SELECT p.id, p.origin, p.page_url FROM playback_sources p WHERE p.dead_reason LIKE 'user-marked dead%' AND p.dead_at > now() - make_interval(days => :d) AND NOT EXISTS ( SELECT 1 FROM playback_sources o WHERE o.scene_id = p.scene_id AND o.dead_at IS NULL ) """ ), {"d": days}, ).all() revive: list = [] by_origin: Counter = Counter() for pb_id, origin, url in rows: if _alive(origin, url): revive.append(pb_id) by_origin[origin] += 1 print({"candidates": len(rows), "alive": len(revive)}, by_origin.most_common(8)) if apply and revive: with session_scope() as s: s.execute( sa.text("UPDATE playback_sources SET dead_at = NULL, dead_reason = NULL WHERE id = ANY(:ids)"), {"ids": revive}, ) s.commit() print("revived", len(revive)) return {"candidates": len(rows), "revived": len(revive) if apply else 0} def main() -> int: logging.basicConfig(level=logging.WARNING) p = argparse.ArgumentParser() p.add_argument("--apply", action="store_true") p.add_argument("--days", type=int, default=30) args = p.parse_args() run(args.apply, args.days) return 0 if __name__ == "__main__": raise SystemExit(main())