feat: téléchargement dans sous-dossiers par catégorie
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+6
-5
@@ -107,7 +107,7 @@ class DownloadManager:
|
|||||||
# ------------------------------------------------------------------ public
|
# ------------------------------------------------------------------ public
|
||||||
|
|
||||||
def enqueue(self, url: str, title: str, subtitle: str, year: int | None,
|
def enqueue(self, url: str, title: str, subtitle: str, year: int | None,
|
||||||
bg: BackgroundTasks) -> str:
|
category: str, bg: BackgroundTasks) -> str:
|
||||||
dl_id = str(uuid.uuid4())
|
dl_id = str(uuid.uuid4())
|
||||||
now = datetime.now().isoformat()
|
now = datetime.now().isoformat()
|
||||||
with _db() as conn:
|
with _db() as conn:
|
||||||
@@ -117,7 +117,7 @@ class DownloadManager:
|
|||||||
)
|
)
|
||||||
with self._lock:
|
with self._lock:
|
||||||
self._active[dl_id] = {"state": "queued", "progress": 0, "title": title}
|
self._active[dl_id] = {"state": "queued", "progress": 0, "title": title}
|
||||||
bg.add_task(self._run, dl_id, url, title, subtitle, year)
|
bg.add_task(self._run, dl_id, url, title, subtitle, year, category)
|
||||||
return dl_id
|
return dl_id
|
||||||
|
|
||||||
def status(self, dl_id: str) -> dict:
|
def status(self, dl_id: str) -> dict:
|
||||||
@@ -144,8 +144,9 @@ class DownloadManager:
|
|||||||
with self._lock:
|
with self._lock:
|
||||||
self._active.setdefault(dl_id, {}).update(kw)
|
self._active.setdefault(dl_id, {}).update(kw)
|
||||||
|
|
||||||
def _run(self, dl_id: str, url: str, title: str, subtitle: str, year: int | None):
|
def _run(self, dl_id: str, url: str, title: str, subtitle: str, year: int | None, category: str = ""):
|
||||||
Path(OUTPUT_DIR).mkdir(parents=True, exist_ok=True)
|
out_dir = f"{OUTPUT_DIR}/{category}" if category else OUTPUT_DIR
|
||||||
|
Path(out_dir).mkdir(parents=True, exist_ok=True)
|
||||||
self._set(dl_id, state="downloading")
|
self._set(dl_id, state="downloading")
|
||||||
with _db() as conn:
|
with _db() as conn:
|
||||||
conn.execute("UPDATE downloads SET state='downloading' WHERE id=?", (dl_id,))
|
conn.execute("UPDATE downloads SET state='downloading' WHERE id=?", (dl_id,))
|
||||||
@@ -172,7 +173,7 @@ class DownloadManager:
|
|||||||
self._set(dl_id, state="processing", progress=100)
|
self._set(dl_id, state="processing", progress=100)
|
||||||
|
|
||||||
ydl_opts = {
|
ydl_opts = {
|
||||||
"outtmpl": f"{OUTPUT_DIR}/%(title)s.%(ext)s",
|
"outtmpl": f"{out_dir}/%(title)s.%(ext)s",
|
||||||
"format": "bestvideo[vcodec^=avc1]+bestaudio/bestvideo+bestaudio/best",
|
"format": "bestvideo[vcodec^=avc1]+bestaudio/bestvideo+bestaudio/best",
|
||||||
"merge_output_format": "mp4",
|
"merge_output_format": "mp4",
|
||||||
"progress_hooks": [hook],
|
"progress_hooks": [hook],
|
||||||
|
|||||||
@@ -55,13 +55,14 @@ class DownloadRequest(BaseModel):
|
|||||||
title: str
|
title: str
|
||||||
subtitle: str = ""
|
subtitle: str = ""
|
||||||
year: int | None = None
|
year: int | None = None
|
||||||
|
category: str = ""
|
||||||
|
|
||||||
|
|
||||||
@app.post("/api/download")
|
@app.post("/api/download")
|
||||||
async def api_download(req: DownloadRequest, bg: BackgroundTasks):
|
async def api_download(req: DownloadRequest, bg: BackgroundTasks):
|
||||||
if not req.url:
|
if not req.url:
|
||||||
raise HTTPException(status_code=400, detail="url required")
|
raise HTTPException(status_code=400, detail="url required")
|
||||||
dl_id = dm.enqueue(req.url, req.title, req.subtitle, req.year, bg)
|
dl_id = dm.enqueue(req.url, req.title, req.subtitle, req.year, req.category, bg)
|
||||||
return {"id": dl_id}
|
return {"id": dl_id}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -110,9 +110,10 @@ function renderConcerts(data) {
|
|||||||
const dl = state.downloadedUrls.has(c.url) ? `<span class="card-downloaded">✓ Téléchargé</span>` : '';
|
const dl = state.downloadedUrls.has(c.url) ? `<span class="card-downloaded">✓ Téléchargé</span>` : '';
|
||||||
const date = fmtDate(c.upload_date);
|
const date = fmtDate(c.upload_date);
|
||||||
const sub = c.subtitle ? `<div class="card-subtitle">${c.subtitle}</div>` : '';
|
const sub = c.subtitle ? `<div class="card-subtitle">${c.subtitle}</div>` : '';
|
||||||
|
const downloadedClass = state.downloadedUrls.has(c.url) ? 'downloaded' : '';
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="card" data-id="${c.id}" tabindex="0" role="button" aria-label="${c.title}">
|
<div class="card ${downloadedClass}" data-id="${c.id}" tabindex="0" role="button" aria-label="${c.title}">
|
||||||
<div class="card-thumb-wrap">
|
<div class="card-thumb-wrap">
|
||||||
${thumb}${dur}${dl}
|
${thumb}${dur}${dl}
|
||||||
</div>
|
</div>
|
||||||
@@ -270,7 +271,7 @@ $('btn-download').addEventListener('click', async () => {
|
|||||||
const res = await fetch('/api/download', {
|
const res = await fetch('/api/download', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ url: c.url, title: c.title, subtitle: c.subtitle || '', year }),
|
body: JSON.stringify({ url: c.url, title: c.title, subtitle: c.subtitle || '', year, category: state.category }),
|
||||||
});
|
});
|
||||||
const { id } = await res.json();
|
const { id } = await res.json();
|
||||||
trackDownload(id, c.title, c.url);
|
trackDownload(id, c.title, c.url);
|
||||||
|
|||||||
Reference in New Issue
Block a user