feat(backend): Media-Server-Aufbereitung, echte Webhooks, SMB-Klartext, UHD-Arbeitsverzeichnis, MakeMKV-Key via UI
- jobs.meta (Migration in beiden db.py): Disc-Metadaten wandern in den Job —
Quelle fuer Job-Detail-Popup (GET /jobs/{id}/detail), Ordner-Benennung, NFO.
- medien.py (Worker, mit Tests): Zielordner 'Titel (Jahr)' statt Job-UUID;
movie.nfo/tvshow.nfo (Kodi-Schema, kodi.wiki/view/NFO_files) + poster.jpg
fuer jellyfin/emby/kodi; plex nur Benennung; Kollision -> Job-ID-Suffix.
- notify.py (identisch in API+Worker, mit Tests): Webhook bei Job-Ende —
Discord ({content}, discord.com/developers), Slack ({text},
api.slack.com/messaging/webhooks), ntfy (Rohtext + ?title=, docs.ntfy.sh),
generisches JSON. Vorher war das Setting ein Placebo: nichts sendete je.
POST /notifications/test beweist die Anbindung sofort.
- mounts.py: NT_STATUS-Fehler -> handelbarer Klartext (ACCESS_DENIED ohne
Credentials = Gast-Abfrage verweigert), Timeout-Meldung, mount-Hinweis
bei error(13). Mit Tests.
- tasks.py: Platz-Check per Disc-Groesse (ioctl BLKGETSIZE64) VOR dem Rip;
Arbeitsverzeichnis workDir (unter /app/media, z.B. NAS) statt fix
/app/temp/raw — 4K-UHD-Rohdaten (bis 100 GB) sprengen sonst die VM-Platte;
MakeMKV-Key aus UI-Settings (~/.MakeMKV/settings.conf, Format wie
entrypoint.sh) gilt ab dem naechsten Rip ohne Rebuild.
- caps.py: Werkzeug-Versionen (MakeMKV aus ENV MAKEMKV_VERSION im Image,
makemkvcon hat keinen --version-Schalter lt. usage.txt; HandBrakeCLI
--version lt. handbrake.fr/docs) + Key-Quelle; workers.info-Spalte.
- /browse liefert jetzt auch DATEIEN (Name + Groesse) — der 'leere'
bluray-Ordner war voll, der Browser zeigte nur Unterordner.
- GET /system/info: Versionen, Plattenplatz, Key-/Webhook-Status.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+15
-1
@@ -43,6 +43,7 @@ jobs = Table(
|
||||
Column("output_path", Text),
|
||||
Column("target_dir", String(255)),
|
||||
Column("error", Text),
|
||||
Column("meta", Text), # Disc-Metadaten (JSON: Jahr/Poster/Plot) für Detail-Popup + NFO
|
||||
Column("created_at", DateTime(timezone=True)),
|
||||
Column("finished_at", DateTime(timezone=True)),
|
||||
)
|
||||
@@ -69,6 +70,7 @@ workers = Table(
|
||||
metadata,
|
||||
Column("name", String(128), primary_key=True),
|
||||
Column("encoders", Text),
|
||||
Column("info", Text), # Werkzeug-Versionen (JSON: makemkv/handbrake/key-Quelle)
|
||||
Column("last_seen", DateTime(timezone=True)),
|
||||
)
|
||||
|
||||
@@ -96,6 +98,10 @@ def list_workers() -> list:
|
||||
eintrag["encoders"] = json.loads(eintrag.get("encoders") or "[]")
|
||||
except ValueError:
|
||||
eintrag["encoders"] = []
|
||||
try:
|
||||
eintrag["info"] = json.loads(eintrag.get("info") or "{}")
|
||||
except ValueError:
|
||||
eintrag["info"] = {}
|
||||
if eintrag.get("last_seen"):
|
||||
eintrag["last_seen"] = eintrag["last_seen"].isoformat()
|
||||
ergebnis.append(eintrag)
|
||||
@@ -134,10 +140,17 @@ def init_db() -> None:
|
||||
conn.exec_driver_sql(
|
||||
"ALTER TABLE jobs ADD COLUMN IF NOT EXISTS target_dir VARCHAR(255)"
|
||||
)
|
||||
conn.exec_driver_sql(
|
||||
"ALTER TABLE jobs ADD COLUMN IF NOT EXISTS meta TEXT"
|
||||
)
|
||||
conn.exec_driver_sql(
|
||||
"ALTER TABLE workers ADD COLUMN IF NOT EXISTS info TEXT"
|
||||
)
|
||||
|
||||
|
||||
def insert_job(
|
||||
job_id: str, device: str, disc_type: str = None, title: str = None, target_dir: str = None
|
||||
job_id: str, device: str, disc_type: str = None, title: str = None,
|
||||
target_dir: str = None, meta: str = None,
|
||||
) -> None:
|
||||
with engine.begin() as conn:
|
||||
conn.execute(
|
||||
@@ -147,6 +160,7 @@ def insert_job(
|
||||
disc_type=disc_type,
|
||||
title=title,
|
||||
target_dir=target_dir,
|
||||
meta=meta,
|
||||
status="pending",
|
||||
progress=0,
|
||||
created_at=utcnow(),
|
||||
|
||||
Reference in New Issue
Block a user