diff --git a/main.py b/main.py index c6de434..e8f1106 100644 --- a/main.py +++ b/main.py @@ -1069,6 +1069,20 @@ async def admin_yt_add(request: Request, url: str = Form(""), playlist: str = Fo return RedirectResponse("/admin/yt?saved=Lagt i kø — hentningen er i gang", status_code=303) +@app.post("/admin/yt/slet") +async def admin_yt_delete(request: Request): + require_admin(request) + f = await request.form() + res = yt.delete_video(f.get("path") or "") + if not res["ok"]: + return RedirectResponse(f"/admin/yt?saved={urllib.parse.quote(res['error'])}", status_code=303) + cache.clear("yt:") + await yt.refresh_library() + return RedirectResponse( + "/admin/yt?saved=" + urllib.parse.quote(f"Slettet: {res['title']} ({yt._human(res['size'])})"), + status_code=303) + + @app.post("/admin/yt/settings") async def admin_yt_settings(request: Request): require_admin(request) diff --git a/templates/admin_yt.html b/templates/admin_yt.html index 0dfdf7d..6fb6f09 100644 --- a/templates/admin_yt.html +++ b/templates/admin_yt.html @@ -126,7 +126,7 @@

Hentede videoer

{% if not ours %}

Ingen endnu — indsæt en URL ovenfor.

{% else %} - + {% for v in ours %} @@ -142,6 +142,13 @@ {% elif v.delete_after %}om {{ ((v.delete_after - now) / 86400) | round(0, 'ceil') | int }} dage {% else %}—{% endif %} + {% endfor %} diff --git a/ytdl.py b/ytdl.py index 9311978..717d0d4 100644 --- a/ytdl.py +++ b/ytdl.py @@ -488,6 +488,44 @@ async def enforce_cycles() -> dict: return res +def delete_video(path: str) -> dict: + """Slet én video manuelt (knappen på /admin/yt), med samme sikkerhedsnet som + oprydningen: KUN filer portalen selv har hentet, og sidecars med. + + Video-id'et bliver stående i abonnementets `seen`, så en overvåget kanal ikke + henter den igen. Er det jobbets sidste fil, markeres jobbet som slettet. + """ + real = os.path.realpath(path or "") + if real not in owned_paths(): + return {"ok": False, "error": "Den video har portalen ikke selv hentet, så den røres ikke"} + st = get_state() + try: + size = file_size(real) + for side in _sidecars(real): + os.remove(side) + if os.path.exists(real): + os.remove(real) + except OSError as e: + return {"ok": False, "error": f"Kunne ikke slette: {e}"} + st["leaving"].pop(real, None) + titel = os.path.basename(real) + for j in st["jobs"].values(): + paths = [p for p in (j.get("paths") or ([j["path"]] if j.get("path") else [])) if p] + if real not in {os.path.realpath(p) for p in paths}: + continue + titel = j.get("title") or titel + rest = [p for p in paths if os.path.realpath(p) != real] + if j.get("paths") is not None: + j["paths"] = rest + if j.get("videos"): + j["videos"] = [v for v in j["videos"] if os.path.realpath(v.get("path") or "") != real] + if not rest: + j["status"] = "deleted" + _log(st, f"Slettet manuelt: {titel} ({_human(size)})") + save_state(st) + return {"ok": True, "title": titel, "size": size} + + # ---------------- Emby ---------------- async def _emby(client, path, **params): params["api_key"] = config.EMBY_API_KEY
TitelStørrelseStatusSlettes
TitelStørrelseStatusSlettes
+
+ + +
+