Spaces:
Running
Running
| from datetime import datetime, timezone | |
| from typing import Any | |
| from slugify import slugify as _slugify | |
| from supabase import Client | |
| def slugify(title: str, artist: str, max_len: int = 80) -> str: | |
| raw = _slugify(f"{title} {artist}") | |
| return raw[:max_len].rstrip("-") | |
| _TERMINAL = {"ready", "failed_fetch", "failed_separation", "failed_other"} | |
| class SongRepo: | |
| def __init__(self, client: Client): | |
| self._c = client | |
| # songs --------------------------------------------------------------- | |
| def get_song(self, youtube_id: str) -> dict | None: | |
| res = ( | |
| self._c.table("songs").select("*") | |
| .eq("youtube_id", youtube_id).maybe_single().execute() | |
| ) | |
| return res.data if res else None | |
| def get_song_by_slug(self, slug: str) -> dict | None: | |
| res = ( | |
| self._c.table("songs").select("*") | |
| .eq("slug", slug).eq("status", "ready").maybe_single().execute() | |
| ) | |
| return res.data if res else None | |
| def upsert_song(self, row: dict[str, Any]) -> None: | |
| self._c.table("songs").upsert(row, on_conflict="youtube_id").execute() | |
| def increment_play_count(self, youtube_id: str) -> None: | |
| # Best-effort, ignore the row if missing. | |
| self._c.rpc("increment_play_count", {"yt_id": youtube_id}).execute() | |
| # jobs ---------------------------------------------------------------- | |
| def create_job(self, youtube_id: str) -> str: | |
| res = self._c.table("jobs").insert( | |
| {"youtube_id": youtube_id, "status": "queued"} | |
| ).execute() | |
| return res.data[0]["id"] | |
| def update_job(self, job_id: str, *, status: str, error: str | None = None) -> None: | |
| patch: dict[str, Any] = {"status": status, "error": error} | |
| if status in _TERMINAL: | |
| patch["finished_at"] = datetime.now(timezone.utc).isoformat() | |
| self._c.table("jobs").update(patch).eq("id", job_id).execute() | |
| def get_job(self, job_id: str) -> dict | None: | |
| res = ( | |
| self._c.table("jobs").select("*") | |
| .eq("id", job_id).maybe_single().execute() | |
| ) | |
| return res.data if res else None | |