#!/usr/bin/env python3 """SaveTV Auto-Download — Lädt fertige Aufnahmen automatisch herunter. Cronjob: */30 * * * * (alle 30 Minuten) Prüft das Save.TV-Archiv auf fertige Aufnahmen die noch nicht auf Hetzner liegen und startet den Download im Hintergrund. """ import json import logging import os import re import sys import time from pathlib import Path sys.path.insert(0, os.path.dirname(__file__)) sys.path.insert(0, "/opt") from tools import savetv, savetv_country_filter log = logging.getLogger("savetv_auto_download") logging.basicConfig( level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", datefmt="%H:%M:%S", ) DOWNLOAD_DIR = Path("/mnt/savetv") DOWNLOAD_LOG = DOWNLOAD_DIR / ".download_log.json" MAX_PARALLEL = 3 MIN_SCORE = 80 def _load_download_log(): if DOWNLOAD_LOG.exists(): try: return json.loads(DOWNLOAD_LOG.read_text()) except Exception: pass return {} def _save_download_log(dl_log): try: DOWNLOAD_LOG.write_text(json.dumps(dl_log, ensure_ascii=False, indent=2)) except Exception: pass def _normalize(s): return re.sub(r"\s+", " ", re.sub(r"[^\w\s]", " ", s)).strip().lower() def _already_stored(title): norm = _normalize(title) for fp in DOWNLOAD_DIR.iterdir(): if fp.suffix == ".mp4" and fp.stat().st_size > 1_000_000: raw = fp.stem.rsplit(" (", 1)[0] if _normalize(raw) == norm: return True return False def run(): log.info("Starte Auto-Download Check...") entries = savetv._get_full_archive() if not entries: log.info("Kein Archiv-Zugriff oder leeres Archiv") return dl_log = _load_download_log() filminfo_cache = savetv_country_filter.load_filminfo_cache() started = 0 for e in entries: tc = e.get("STRTELECASTENTRY", {}) tid = str(int(float(tc.get("ITELECASTID", 0)))) title = tc.get("STITLE", "") if not title or not tid or tid == "0": continue if tc.get("SFOLGE", ""): continue if savetv._is_excluded(title): continue if savetv_country_filter.should_exclude_production_country(title, filminfo_cache): continue if tid in dl_log: continue if _already_stored(title): dl_log[tid] = "done" continue if started >= MAX_PARALLEL: break log.info(f"Starte Download: {title} (TID {tid})") filename, err = savetv._download_film(int(float(tid)), title) if err: log.warning(f"Download-Fehler {title}: {err}") continue dl_log[tid] = "done" started += 1 time.sleep(2) _save_download_log(dl_log) log.info(f"Fertig: {started} neue Downloads gestartet") if __name__ == "__main__": run()