🔴 Dringend
0
laufen bald ab
🎬 Kino-Highlights
0
📺 Deutsche TV-Filme
0
"""Save.TV Web-UI — Film-Archiv durchsuchen und downloaden. Läuft auf Port 8765 in CT 116. Erreichbar via Tailscale: http://100.123.47.7:8765 """ import os import re as _re import subprocess import sys import json import threading import urllib.request from datetime import datetime from pathlib import Path sys.path.insert(0, os.path.dirname(__file__)) sys.path.insert(0, '/opt') from flask import Flask, jsonify, render_template_string, request from tools import savetv app = Flask(__name__) DOWNLOAD_LOG = Path("/mnt/savetv/.download_log.json") def _load_download_log(): if DOWNLOAD_LOG.exists(): try: return json.loads(DOWNLOAD_LOG.read_text()) except Exception: pass return {} def _save_download_log(log): try: DOWNLOAD_LOG.write_text(json.dumps(log, ensure_ascii=False, indent=2)) except Exception: pass DOWNLOAD_PROGRESS = Path("/mnt/savetv/.download_progress.json") DOWNLOAD_DIR = Path("/mnt/savetv") _PROGRESS_LOCK = threading.Lock() def _load_progress_raw(): """Liest Progress-Datei ohne Lock (nur innerhalb von _PROGRESS_LOCK aufrufen).""" if DOWNLOAD_PROGRESS.exists(): try: return json.loads(DOWNLOAD_PROGRESS.read_text()) except Exception: pass return {} def _save_progress_raw(prog): """Schreibt Progress-Datei ohne Lock (nur innerhalb von _PROGRESS_LOCK aufrufen).""" DOWNLOAD_PROGRESS.write_text(json.dumps(prog, ensure_ascii=False, indent=2)) def _load_progress(): with _PROGRESS_LOCK: return _load_progress_raw() def _save_progress(prog): with _PROGRESS_LOCK: try: _save_progress_raw(prog) except Exception: pass def _head_content_length(url): try: req = urllib.request.Request(url, method='HEAD') with urllib.request.urlopen(req, timeout=10) as resp: return int(resp.headers.get('Content-Length', 0)) except Exception: return 0 HTML = r"""