feat(stage): show Bandcamp link in ON AIR

This commit is contained in:
beefcarver committed 2026-10-30 15:12:37 +00:00
1 parent 8e1c0a64eb
commit 66729c7542
4 files changed
+81 -3

No files matched your search

+46 -1
View File
@@ -17,7 +17,7 @@ from textual.css.query import NoMatches
from textual.theme import Theme
from textual.widgets import Input
from . import api, artwork, config
from . import api, artwork, bandcamp, config
from .api import Station
from .fallback import fallback_channels
from .mpris import MprisService
@@ -133,6 +133,7 @@ class SomaFMApp(App[None]):
self.artwork_url = ""
self.artwork_bytes: bytes | None = None
self._art_track_key = ""
self._bandcamp_key = ""
self._http: httpx.AsyncClient | None = None
self._closed = False
self._tick_timer = None
@@ -415,8 +416,51 @@ class SomaFMApp(App[None]):
)
self.mpris.set_status(self._mpris_status())
self.mpris.set_volume(self.volume / 100.0)
self._update_bandcamp()
self._update_artwork()
def _update_bandcamp(self) -> None:
"""Find a Bandcamp track link once per now-playing track."""
station = self.current
if station is None or self.offline or self._http is None:
return
song = station.now_playing
if song is None or not (song.artist.strip() or song.title.strip()):
return
track_key = f"{station.id}|{song.key()}"
if track_key == self._bandcamp_key:
return
self._bandcamp_key = track_key
self._fetch_bandcamp(
station.id, song.key(), song.artist, song.album, song.title
)
@work(exclusive=True, group="bandcamp", exit_on_error=False)
async def _fetch_bandcamp(
self,
station_id: str,
song_key: str,
artist: str,
album: str,
title: str,
) -> None:
if self._http is None or self.offline:
return
url = await bandcamp.find_track(self._http, artist, album, title)
if not url:
return
station = next((s for s in self.stations if s.id == station_id), None)
if station is None or self.current is None or self.current.id != station_id:
return
song = station.now_playing
if song is None or song.key() != song_key:
return
song.bandcamp_url = url
with contextlib.suppress(NoMatches):
self.query_one(StagePanel).refresh_stage()
def _refresh_art(self) -> None:
with contextlib.suppress(NoMatches):
self.query_one(StagePanel).refresh_art()
@@ -758,6 +802,7 @@ class SomaFMApp(App[None]):
def action_refresh(self) -> None:
self._last_history_fetch = 0.0
self._bandcamp_key = ""
self._set_notice("refreshing…", 2)
if self.offline:
self._set_notice("offline mode — nothing to refresh", 3)