bridge: 4 metodi Api per feature Beatport (fetch + download riusa start_tracks_download)

This commit is contained in:
luciano committed 2026-07-14 16:30:49 +02:00
1 parent 1c52d52986
commit be4f7e1024
1 file changed
+91
+91
View File
@@ -8,9 +8,12 @@ import re
import threading import threading
import time import time
import webbrowser import webbrowser
from dataclasses import asdict
from pathlib import Path
from typing import Any, Optional from typing import Any, Optional
from core.config import load_config, save_config, VERSION, LICENSE_API_URL from core.config import load_config, save_config, VERSION, LICENSE_API_URL
from core import beatport
from core import license as license_mod from core import license as license_mod
from core.downloader import ( from core.downloader import (
download_playlist, download_playlist,
@@ -903,3 +906,91 @@ class Api:
}) })
self._emit("video:done", {"ok": True}) self._emit("video:done", {"ok": True})
# ================================================================
# Beatport charts
# ================================================================
def beatport_genres(self) -> list:
"""Lista dei generi disponibili per il dropdown UI."""
return beatport.list_genres()
def beatport_fetch_chart(self, slug: str, force_refresh: bool = False) -> dict:
"""Fetches la Top 100 per il genere. Salva anche l'ultimo genere in config.
Ritorna {ok: True, tracks: [...]} oppure {ok: False, error, message}."""
# Memoria: ricorda l'ultimo genere usato
try:
cfg = load_config()
cfg["beatport_last_genre"] = slug
save_config(cfg)
except Exception:
pass
try:
tracks = beatport.fetch_top100(slug, force_refresh=force_refresh)
except ValueError as e:
return {"ok": False, "error": "invalid_genre", "message": str(e)}
except beatport.BeatportUnreachableError as e:
return {"ok": False, "error": "unreachable", "message": str(e)}
except beatport.BeatportParseError as e:
return {"ok": False, "error": "parse", "message": str(e)}
return {"ok": True, "tracks": [asdict(t) for t in tracks]}
def beatport_check_existing(self, tracks: list, genre_name: str) -> list:
"""Per ogni track ritorna True se il file esiste gia' in output_dir/Beatport/<genre_name>/.
Match euristico: nel filename (senza extension) devono comparire sia il titolo
che il primo artista (case-insensitive)."""
cfg = load_config()
out_root = (cfg.get("output_dir") or "").strip()
if not out_root:
return [False] * len(tracks)
safe_name = genre_name.replace("/", "_").replace("\\", "_").strip()
out_dir = Path(out_root) / "Beatport" / safe_name
if not out_dir.exists():
return [False] * len(tracks)
existing_stems = [p.stem.lower() for p in out_dir.glob("*.mp3")]
result = []
for t in tracks:
title = (t.get("title") or "").lower().strip()
artists = (t.get("artists") or "")
first_artist = artists.split(",")[0].split("&")[0].strip().lower()
if not title or not first_artist:
result.append(False)
continue
found = any(
(title in stem and first_artist in stem)
for stem in existing_stems
)
result.append(found)
return result
def beatport_download_selected(self, tracks: list, genre_name: str) -> dict:
"""Converte i BeatportTrack in tracklist compatibile con start_tracks_download
e lancia il download riusando l'infrastruttura esistente (license gate,
skip file gia' scaricati, log su canale 'download', ecc.)."""
cfg = load_config()
out_root = (cfg.get("output_dir") or "").strip()
if not out_root:
return {"ok": False, "error": "Cartella output non impostata"}
safe_genre = genre_name.replace("/", "_").replace("\\", "_").strip()
subfolder = f"Beatport/{safe_genre}" if safe_genre else "Beatport"
converted = []
for t in tracks:
title = (t.get("title") or "").strip()
artists = (t.get("artists") or "").strip()
if not title:
continue
converted.append({"name": title, "artist": artists})
if not converted:
return {"ok": False, "error": "Nessun brano valido"}
return self.start_tracks_download({
"tracks": converted,
"output_dir": out_root,
"subfolder": subfolder,
})