Files
arte-dl/main.py
T
dev 124afb6d20
Docker / docker (push) Has been cancelled
feat: nommage UNFR -ReMoRa automatique après téléchargement
Format : Title.Event.Year.FRENCH.Resolution.WEBRip.x264|HEVC.AAC-ReMoRa.mp4

- build_release_name() : slugify avec strip accents, apostrophe→point,
  déduplique l'année si présente dans le titre ET passée séparément,
  détecte la résolution et le codec depuis les infos yt-dlp
- enqueue() : reçoit subtitle + year depuis l'API
- _run() : renomme le fichier après download, met à jour le filename en DB
- DownloadRequest : subtitle + year ajoutés
- app.js : extrait l'année du subtitle via regex avant d'envoyer la requête

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 13:48:56 +02:00

84 lines
2.3 KiB
Python

import asyncio
import json
import logging
from fastapi import BackgroundTasks, FastAPI, HTTPException, Request
from fastapi.responses import HTMLResponse, StreamingResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel
from arte_api import fetch_concerts, invalidate_cache, CATEGORIES
from downloader import DownloadManager
logging.basicConfig(level=logging.INFO)
app = FastAPI(title="Arte-dl")
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")
dm = DownloadManager()
# ------------------------------------------------------------------ pages
@app.get("/", response_class=HTMLResponse)
async def index(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
# ------------------------------------------------------------------ API: concerts
@app.get("/api/categories")
async def api_categories():
return CATEGORIES
@app.get("/api/concerts")
async def api_concerts(page: int = 1, search: str = "", page_size: int = 24, category: str = ""):
return await fetch_concerts(page=page, search=search, page_size=page_size, category=category)
@app.post("/api/refresh")
async def api_refresh():
count = await invalidate_cache()
return {"count": count}
# ------------------------------------------------------------------ API: downloads
class DownloadRequest(BaseModel):
url: str
title: str
subtitle: str = ""
year: int | None = None
@app.post("/api/download")
async def api_download(req: DownloadRequest, bg: BackgroundTasks):
if not req.url:
raise HTTPException(status_code=400, detail="url required")
dl_id = dm.enqueue(req.url, req.title, req.subtitle, req.year, bg)
return {"id": dl_id}
@app.get("/api/downloads")
async def api_downloads():
return dm.history()
@app.get("/api/progress/{dl_id}")
async def api_progress(dl_id: str):
async def stream():
while True:
s = dm.status(dl_id)
yield f"data: {json.dumps(s)}\n\n"
if s.get("state") in ("done", "error", "unknown"):
break
await asyncio.sleep(0.8)
return StreamingResponse(stream(), media_type="text/event-stream")