From dd8d07b2f00164c2056a1c35c4ec6a2cc8766ee1 Mon Sep 17 00:00:00 2001 From: codey Date: Thu, 21 Aug 2025 15:08:13 -0400 Subject: [PATCH] formatting --- endpoints/rip.py | 50 +++++++++++++++++++++++++++-------------- utils/rip_background.py | 46 ++++++++++++++++++++----------------- utils/sr_wrapper.py | 5 +++-- 3 files changed, 62 insertions(+), 39 deletions(-) diff --git a/endpoints/rip.py b/endpoints/rip.py index 0765553..0fb6331 100644 --- a/endpoints/rip.py +++ b/endpoints/rip.py @@ -9,9 +9,12 @@ from rq import Queue, Retry from rq.job import Job from rq.job import JobStatus from rq.registry import ( - StartedJobRegistry, DeferredJobRegistry, - FinishedJobRegistry, FailedJobRegistry, - ScheduledJobRegistry) + StartedJobRegistry, + DeferredJobRegistry, + FinishedJobRegistry, + FailedJobRegistry, + ScheduledJobRegistry, +) from utils.rip_background import bulk_download from lyric_search.sources import private from typing import Literal @@ -87,7 +90,9 @@ class RIP(FastAPI): "started_at": job.started_at, "ended_at": job.ended_at, "progress": progress, - "tracks": f"{tracks_out} / {tracks_in}" if isinstance(tracks_in, int) else tracks_out, + "tracks": f"{tracks_out} / {tracks_in}" + if isinstance(tracks_in, int) + else tracks_out, "target": job.meta.get("target"), "quality": job.meta.get("quality", "Unknown"), } @@ -111,8 +116,11 @@ class RIP(FastAPI): return JSONResponse(content=albums) async def tracks_by_album_id_handler( - self, album_id: int, request: Request, user=Depends(get_current_user), - quality: str = "FLAC" + self, + album_id: int, + request: Request, + user=Depends(get_current_user), + quality: str = "FLAC", ) -> Response: """Get tracks by album id""" tracks = await self.trip_util.get_tracks_by_album_id(album_id, quality) @@ -131,7 +139,11 @@ class RIP(FastAPI): return JSONResponse(content=tracks) async def track_by_id_handler( - self, track_id: int, quality: str, request: Request, user=Depends(get_current_user) + self, + track_id: int, + quality: str, + request: Request, + user=Depends(get_current_user), ) -> Response: """Get track by ID""" track = await self.trip_util.get_stream_url_by_track_id(track_id, quality) @@ -157,19 +169,21 @@ class RIP(FastAPI): target = data.target job = self.task_queue.enqueue( bulk_download, - args=(track_ids, data.quality,), + args=( + track_ids, + data.quality, + ), job_timeout=14400, failure_ttl=86400, result_ttl=-1, retry=Retry(max=1, interval=[30]), meta={ - 'progress': 0, - 'status': 'queued', - 'target': target, - 'tracks_in': len(track_ids), - 'quality': data.quality, - } - + "progress": 0, + "status": "queued", + "target": target, + "tracks_in": len(track_ids), + "quality": data.quality, + }, ) self.redis_conn.lpush("enqueued_job_ids", job.id) return JSONResponse( @@ -181,7 +195,9 @@ class RIP(FastAPI): } ) - async def job_status_handler(self, job_id: str, request: Request, user=Depends(get_current_user)): + async def job_status_handler( + self, job_id: str, request: Request, user=Depends(get_current_user) + ): """Get status and result of a single job""" job = None @@ -209,7 +225,7 @@ class RIP(FastAPI): return JSONResponse({"error": "Job not found"}, status_code=404) return self._format_job(job) - + async def job_list_handler(self, request: Request, user=Depends(get_current_user)): """List all jobs across all registries (queued, started, finished, failed, etc).""" jobs_info = [] diff --git a/utils/rip_background.py b/utils/rip_background.py index 8a0402f..5f8b4a2 100644 --- a/utils/rip_background.py +++ b/utils/rip_background.py @@ -14,7 +14,7 @@ from rq import get_current_job from utils.sr_wrapper import SRUtil # ---------- Config ---------- -ROOT_DIR = Path("/storage/music2") +ROOT_DIR = Path("/storage/music2") MAX_RETRIES = 3 THROTTLE_MIN = 0.3 THROTTLE_MAX = 1.0 @@ -40,9 +40,10 @@ sr = SRUtil() # ---------- Helpers ---------- + def cleanup_empty_dirs(root: Path): """ - Recursively remove any directories under root that contain no files + Recursively remove any directories under root that contain no files (empty or only empty subdirectories). """ for dirpath, dirnames, filenames in os.walk(root, topdown=False): @@ -80,6 +81,7 @@ def ensure_unique_path(p: Path) -> Path: short_id = uuid.uuid4().hex[:8] return parent / f"{stem}_{short_id}{suffix}" + # ---------- Job ---------- def bulk_download(track_list: list, quality: str = "FLAC"): """ @@ -96,7 +98,7 @@ def bulk_download(track_list: list, quality: str = "FLAC"): if job: try: job.meta["track_ids"] = [str(t) for t in (track_list or [])] - job.meta["tracks"] = [] # will hold per-track dicts + job.meta["tracks"] = [] # will hold per-track dicts job.meta["progress"] = 0 job.meta["tarball"] = None job.meta["status"] = "started" @@ -105,9 +107,9 @@ def bulk_download(track_list: list, quality: str = "FLAC"): logging.warning("Failed to init job.meta: %s", e) async def process_tracks(): - per_track_meta = [] # list of per-track dicts (JSON-safe) - all_final_files = [] # list[Path] - all_artists = set() # set[str] + per_track_meta = [] # list of per-track dicts (JSON-safe) + all_final_files = [] # list[Path] + all_artists = set() # set[str] (ROOT_DIR / "completed").mkdir(parents=True, exist_ok=True) @@ -121,10 +123,10 @@ def bulk_download(track_list: list, quality: str = "FLAC"): for i, track_id in enumerate(track_list or []): track_info = { "track_id": str(track_id), - "status": "pending", # pending | success | failed - "file_path": None, # str | None - "error": None, # str | None - "attempts": 0, # int + "status": "pending", # pending | success | failed + "file_path": None, # str | None + "error": None, # str | None + "attempts": 0, # int } attempt = 0 @@ -157,12 +159,12 @@ def bulk_download(track_list: list, quality: str = "FLAC"): # 4) Metadata from SR (prefer API over tags) md = await sr.get_metadata_by_track_id(track_id) or {} artist_raw = md.get("artist") or "Unknown Artist" - album_raw = md.get("album") or "Unknown Album" - title_raw = md.get("song") or f"Track {track_id}" + album_raw = md.get("album") or "Unknown Album" + title_raw = md.get("song") or f"Track {track_id}" artist = sanitize_filename(artist_raw) - album = sanitize_filename(album_raw) - title = sanitize_filename(title_raw) + album = sanitize_filename(album_raw) + title = sanitize_filename(title_raw) all_artists.add(artist) @@ -186,7 +188,9 @@ def bulk_download(track_list: list, quality: str = "FLAC"): break # success; exit retry loop except Exception as e: - logging.error("Track %s attempt %s failed: %s", track_id, attempt, e) + logging.error( + "Track %s attempt %s failed: %s", track_id, attempt, e + ) track_info["error"] = str(e) if attempt >= MAX_RETRIES: track_info["status"] = "failed" @@ -207,7 +211,9 @@ def bulk_download(track_list: list, quality: str = "FLAC"): job.meta["tracks"] = per_track_meta job.save_meta() except Exception as e: - logging.warning("Failed to update job.meta after track %s: %s", track_id, e) + logging.warning( + "Failed to update job.meta after track %s: %s", track_id, e + ) # Throttle between tracks await asyncio.sleep(random.uniform(THROTTLE_MIN, THROTTLE_MAX)) @@ -234,9 +240,9 @@ def bulk_download(track_list: list, quality: str = "FLAC"): artist_counts[artist] = artist_counts.get(artist, 0) + 1 if artist_counts: - top_artist = sorted( - artist_counts.items(), key=lambda kv: (-kv[1], kv[0]) - )[0][0] + top_artist = sorted(artist_counts.items(), key=lambda kv: (-kv[1], kv[0]))[ + 0 + ][0] else: top_artist = "Unknown Artist" @@ -253,7 +259,7 @@ def bulk_download(track_list: list, quality: str = "FLAC"): job.meta["status"] = "compressing" job.save_meta() except Exception: - pass + pass logging.info("Creating tarball: %s", staged_tarball) diff --git a/utils/sr_wrapper.py b/utils/sr_wrapper.py index e1e8e5f..eadb67d 100644 --- a/utils/sr_wrapper.py +++ b/utils/sr_wrapper.py @@ -134,8 +134,9 @@ class SRUtil: logging.debug("Retrieved albums: %s", albums_out) return albums_out - async def get_tracks_by_album_id(self, album_id: int, - quality: str = "FLAC") -> Optional[list | dict]: + async def get_tracks_by_album_id( + self, album_id: int, quality: str = "FLAC" + ) -> Optional[list | dict]: """Get tracks by album ID Args: album_id (int): The ID of the album.