diff --git a/frontend/app/routes.py b/frontend/app/routes.py index f0f6a18..3699c96 100644 --- a/frontend/app/routes.py +++ b/frontend/app/routes.py @@ -1,8 +1,10 @@ from __future__ import annotations +import json import re import shutil import subprocess +import tempfile import threading import uuid from pathlib import Path @@ -40,6 +42,7 @@ YOUTUBE_POSTPROCESS_HINTS = ( "destination", ) INVALID_FILENAME_CHARS_PATTERN = re.compile(r"[<>:\"/\\|?*\x00-\x1f]") +YOUTUBE_JOBS_DIR = Path(tempfile.gettempdir()) / "pysonnerie-youtube-jobs" _YOUTUBE_JOBS_LOCK = threading.Lock() _YOUTUBE_JOBS: dict[str, dict[str, object]] = {} @@ -186,21 +189,40 @@ def _extract_progress_percent(line: str) -> float | None: def _set_youtube_job_state(job_id: str, **updates: object) -> None: + YOUTUBE_JOBS_DIR.mkdir(parents=True, exist_ok=True) + job_path = YOUTUBE_JOBS_DIR / f"{job_id}.json" + with _YOUTUBE_JOBS_LOCK: current = _YOUTUBE_JOBS.get(job_id) + if current is None and job_path.exists(): + try: + current = json.loads(job_path.read_text(encoding="utf-8")) + except Exception: + current = None if current is None: - return + current = {} current.update(updates) + _YOUTUBE_JOBS[job_id] = current + + tmp_path = job_path.with_suffix(".json.tmp") + tmp_path.write_text(json.dumps(current, ensure_ascii=False), encoding="utf-8") + tmp_path.replace(job_path) def _create_youtube_job() -> str: job_id = uuid.uuid4().hex + YOUTUBE_JOBS_DIR.mkdir(parents=True, exist_ok=True) + payload = { + "status": "running", + "percent": 0.0, + "message": "Préparation du téléchargement...", + } with _YOUTUBE_JOBS_LOCK: - _YOUTUBE_JOBS[job_id] = { - "status": "running", - "percent": 0.0, - "message": "Préparation du téléchargement...", - } + _YOUTUBE_JOBS[job_id] = payload + job_path = YOUTUBE_JOBS_DIR / f"{job_id}.json" + tmp_path = job_path.with_suffix(".json.tmp") + tmp_path.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8") + tmp_path.replace(job_path) return job_id @@ -721,6 +743,13 @@ def youtube_download_status(job_id: str) -> Response: with _YOUTUBE_JOBS_LOCK: job = _YOUTUBE_JOBS.get(job_id) + if job is None: + job_path = YOUTUBE_JOBS_DIR / f"{job_id}.json" + if job_path.exists(): + try: + job = json.loads(job_path.read_text(encoding="utf-8")) + except Exception: + job = None if job is None: return jsonify({"ok": False, "error": "Téléchargement introuvable."}), 404 payload = {