MusicUtils / db.py
sathvik77's picture
fix(db): handle None from supabase-py maybe_single().execute()
ce489e3
Raw
History Blame Contribute Delete
2.16 kB
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