Jikan/MAL-Quelle + Job-Titel + Abbrechen-Knopf + Dark-Hover + Ordner-Verwaltung
Ampel / ampel (push) Failing after 38s
Ampel / ampel (push) Failing after 38s
Commander-Befunde (Screenshots 23.07. abends):
- Jikan (MyAnimeList, kostenlos OHNE Key) als Anime-Quelle vor OMDb —
waehlt per Titel-Aehnlichkeit (SequenceMatcher, Schwelle 0.55) statt
blind Treffer 1; damit trifft "Evangelion 2.22" den exakten Film
- Job-Titel: POST /jobs uebernimmt den erkannten Disc-Titel aus dem
DISC_CACHE — Schluss mit "Unbekannt" in der Queue
- Kooperativer Job-Abbruch: POST /jobs/{id}/cancel setzt canceling,
der Worker prueft das Flag bei jedem Fortschritts-Update und killt
den Encoder-Prozess sauber (RipAbbruch); UI-Knopf "Abbrechen" fuer
laufende, Status-Badge "Wird abgebrochen"
- Dark-Mode: Job-Zeilen-Hover war hart hell (hover:bg-slate-50)
- Speicherziele: lokaler Ordner-Browser mit "Ordner anlegen"
(GET /browse + POST /browse/mkdir, nur unter /app/media)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+35
-15
@@ -20,6 +20,11 @@ import tempfile
|
||||
RIP_OUTPUT_DIR = os.getenv("RIP_OUTPUT_DIR", "/app/media")
|
||||
|
||||
|
||||
class RipAbbruch(Exception):
|
||||
"""Kooperativer Abbruch: vom Fortschritts-Callback geworfen, wenn der
|
||||
Nutzer den Job abgebrochen hat (Status 'canceling' in der DB)."""
|
||||
|
||||
|
||||
def check_makemkv_installed() -> bool:
|
||||
"""Prüft, ob makemkvcon installiert ist."""
|
||||
return shutil.which("makemkvcon") is not None
|
||||
@@ -124,10 +129,15 @@ def run_handbrake(input_path: str, output_path: str, preset: str = DEFAULT_HB_PR
|
||||
bufsize=1
|
||||
)
|
||||
|
||||
for line in process.stdout:
|
||||
progress = get_progress_from_line(line)
|
||||
if progress > 0 and progress_cb:
|
||||
progress_cb(progress)
|
||||
try:
|
||||
for line in process.stdout:
|
||||
progress = get_progress_from_line(line)
|
||||
if progress > 0 and progress_cb:
|
||||
progress_cb(progress)
|
||||
except RipAbbruch:
|
||||
process.kill()
|
||||
process.wait()
|
||||
return {"status": "cancelled", "error": "Abgebrochen durch Nutzer"}
|
||||
|
||||
process.wait()
|
||||
|
||||
@@ -185,15 +195,20 @@ def run_makemkv(device_path: str, output_dir: str, progress_cb=None) -> dict:
|
||||
)
|
||||
|
||||
letzte_meldung = ""
|
||||
for line in process.stdout:
|
||||
progress = get_progress_from_prgv(line)
|
||||
if progress >= 0 and progress_cb:
|
||||
progress_cb(progress)
|
||||
elif line.startswith("MSG:"):
|
||||
# MSG:code,flags,count,"message",... — Klartext ist Feld 4
|
||||
teile = line.split(",", 4)
|
||||
if len(teile) >= 4:
|
||||
letzte_meldung = teile[3].strip('"')
|
||||
try:
|
||||
for line in process.stdout:
|
||||
progress = get_progress_from_prgv(line)
|
||||
if progress >= 0 and progress_cb:
|
||||
progress_cb(progress)
|
||||
elif line.startswith("MSG:"):
|
||||
# MSG:code,flags,count,"message",... — Klartext ist Feld 4
|
||||
teile = line.split(",", 4)
|
||||
if len(teile) >= 4:
|
||||
letzte_meldung = teile[3].strip('"')
|
||||
except RipAbbruch:
|
||||
process.kill()
|
||||
process.wait()
|
||||
return {"status": "cancelled", "error": "Abgebrochen durch Nutzer"}
|
||||
|
||||
process.wait()
|
||||
|
||||
@@ -267,8 +282,13 @@ def rip_cd(device_path: str, disc_id: str, progress_cb=None, output_dir: str = N
|
||||
bufsize=1
|
||||
)
|
||||
|
||||
for line in process.stdout:
|
||||
melde(50, line.strip()[:200])
|
||||
try:
|
||||
for line in process.stdout:
|
||||
melde(50, line.strip()[:200])
|
||||
except RipAbbruch:
|
||||
process.kill()
|
||||
process.wait()
|
||||
return {"status": "cancelled", "error": "Abgebrochen durch Nutzer"}
|
||||
|
||||
process.wait()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user