homelab-brain/homelab-ai-bot/savetv_auto_download.py
2026-04-11 14:45:18 +02:00

119 lines
2.8 KiB
Python
Executable file

#!/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()