feat(ui): SoC Refactoring & Config Validation
- Theme Context ausgelagert (ThemeContext.tsx + useDarkMode.ts) - Config Validation mit TMDB-API-Key Pflicht (config_validation.py) - Cache Key Centralization (cache/keys.py) - CD-Ripping mit abcde implementiert (Worker) - Docker Compose mit Healthchecks & LOG_LEVEL - ROADMAP.md & SAVEPOINT.md aktualisiert
This commit is contained in:
@@ -103,6 +103,16 @@ def detect_disc_type(device_path: str) -> str:
|
||||
return "unknown"
|
||||
|
||||
|
||||
def check_abcde_installed() -> bool:
|
||||
"""Prüft, ob abcde installiert ist."""
|
||||
return shutil.which("abcde") is not None
|
||||
|
||||
|
||||
def check_cdparanoia_installed() -> bool:
|
||||
"""Prüft, ob cdparanoia installiert ist."""
|
||||
return shutil.which("cdparanoia") is not None
|
||||
|
||||
|
||||
@celery_app.task(bind=True, name="worker.ripping.rip_dvd")
|
||||
def rip_dvd(self, device_path: str, disc_id: str) -> dict:
|
||||
"""Rippt eine DVD mit HandBrake."""
|
||||
@@ -133,3 +143,83 @@ def rip_bluray(self, device_path: str, disc_id: str) -> dict:
|
||||
output_path = f"{output_dir}/bluray_{disc_id}.mkv"
|
||||
|
||||
return run_handbrake(device_path, output_path)
|
||||
|
||||
|
||||
@celery_app.task(bind=True, name="worker.ripping.rip_cd")
|
||||
def rip_cd(self, device_path: str, disc_id: str) -> dict:
|
||||
"""Rippt eine CD mit abcde."""
|
||||
if not check_abcde_installed():
|
||||
return {
|
||||
"status": "error",
|
||||
"error": "abcde ist nicht installiert. Installiere abcde und cdparanoia für CD-Ripping."
|
||||
}
|
||||
|
||||
if not check_cdparanoia_installed():
|
||||
return {
|
||||
"status": "error",
|
||||
"error": "cdparanoia ist nicht installiert. Installiere abcde und cdparanoia für CD-Ripping."
|
||||
}
|
||||
|
||||
output_dir = f"/output/cd/{disc_id}"
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
try:
|
||||
cmd = [
|
||||
"abcde",
|
||||
"-d", device_path,
|
||||
"-o", "flac",
|
||||
"-b",
|
||||
"-t", "1",
|
||||
"-a", "default",
|
||||
"-x",
|
||||
"-o", output_dir
|
||||
]
|
||||
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
text=True,
|
||||
bufsize=1
|
||||
)
|
||||
|
||||
for line in process.stdout:
|
||||
self.send_task(
|
||||
"worker.ripping.update_progress",
|
||||
kwargs={
|
||||
"progress": 50,
|
||||
"status": "ripping",
|
||||
"message": f"Rippe CD: {line.strip()}"
|
||||
}
|
||||
)
|
||||
|
||||
process.wait()
|
||||
|
||||
if process.returncode == 0:
|
||||
# MusikBrainz Lookup (via abcde's post-read)
|
||||
self.send_task(
|
||||
"worker.ripping.update_progress",
|
||||
kwargs={
|
||||
"progress": 90,
|
||||
"status": "ripping",
|
||||
"message": "MusikBrainz Lookup läuft..."
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
"status": "success",
|
||||
"output_dir": output_dir,
|
||||
"return_code": process.returncode
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"status": "error",
|
||||
"error": f"abcde failed with code {process.returncode}",
|
||||
"return_code": process.returncode
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return {
|
||||
"status": "error",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
from celery_app import celery_app
|
||||
from ripping import rip_dvd, rip_bluray, detect_disc_type
|
||||
from ripping import rip_dvd, rip_bluray, rip_cd, detect_disc_type
|
||||
|
||||
|
||||
@celery_app.task(bind=True, name="worker.tasks.rip_disc")
|
||||
@@ -12,11 +12,7 @@ def rip_disc(self, device_path: str, disc_id: str = None):
|
||||
disc_id = device_path.replace("/", "_")
|
||||
|
||||
if disc_type == "cd":
|
||||
return {
|
||||
"status": "not_implemented",
|
||||
"message": "CD-Ripping mit abcde noch nicht implementiert",
|
||||
"disc_type": disc_type
|
||||
}
|
||||
return rip_cd(device_path, disc_id)
|
||||
elif disc_type == "dvd":
|
||||
return rip_dvd(device_path, disc_id)
|
||||
elif disc_type == "bluray":
|
||||
|
||||
Reference in New Issue
Block a user