77 lines
2.5 KiB
Python
77 lines
2.5 KiB
Python
"""tilderadio: the tildeverse's community station.
|
|
|
|
One stream, one catalogue entry, a live DJ when a show is on and the shared
|
|
library rotation the rest of the time. Everything tilderadio-specific — the
|
|
``/api/now/`` schema, the ``now_playing`` + ``history[]`` pairing, the AzuraCast
|
|
mount list and the bundled fallback — lives in this package; the app only sees
|
|
:class:`TilderadioProvider`.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import httpx
|
|
|
|
from ... import config
|
|
from ...models import Broadcast, Song, Station
|
|
from ..base import RadioProvider
|
|
from . import api, fallback
|
|
from . import hero as hero_art
|
|
|
|
__all__ = ["TilderadioProvider"]
|
|
|
|
|
|
class TilderadioProvider(RadioProvider):
|
|
id = "tilderadio"
|
|
name = "tilderadio"
|
|
homepage = "tilderadio.org"
|
|
brand = "TILDE RADIO"
|
|
tagline = "community radio · tildeverse"
|
|
station_source = "tilderadio.org/api/now/"
|
|
history_source = "now_playing + history[]"
|
|
|
|
# The station's own radio icon, converted to half blocks by
|
|
# ``tools/ansi_art.py``; the caption is the tildeverse's motto.
|
|
hero = hero_art.HERO
|
|
hero_lines = (
|
|
"TILDERADIO",
|
|
"STREAMED BY / FOR USERS OF THE",
|
|
"TILDEVERSE",
|
|
)
|
|
# One stream, so the left pane is a schedule instead of a station list.
|
|
has_schedule = True
|
|
# A shared library rotation is not a Bandcamp catalogue; skip the lookups.
|
|
bandcamp = False
|
|
|
|
@property
|
|
def user_agent(self) -> str:
|
|
# A small volunteer station; introduce ourselves and say where we are.
|
|
return f"{config.USER_AGENT}; +https://tilderadio.org"
|
|
|
|
async def fetch_stations(self, client: httpx.AsyncClient) -> list[Station]:
|
|
return [await api.fetch_station(client)]
|
|
|
|
def load_cached_stations(self) -> list[Station]:
|
|
return api.load_cached_station()
|
|
|
|
def fallback_stations(self) -> list[Station]:
|
|
return fallback.fallback_stations()
|
|
|
|
async def fetch_history(
|
|
self, client: httpx.AsyncClient, station_id: str
|
|
) -> list[Song]:
|
|
return await api.fetch_songs(client, station_id)
|
|
|
|
def load_cached_history(self, station_id: str) -> list[Song]:
|
|
return api.load_cached_songs(station_id)
|
|
|
|
async def fetch_schedule(
|
|
self, client: httpx.AsyncClient
|
|
) -> list[Broadcast]:
|
|
return await api.fetch_schedule(client)
|
|
|
|
def load_cached_schedule(self) -> list[Broadcast]:
|
|
return api.load_cached_schedule()
|
|
|
|
def fallback_urls(self, station: Station) -> list[str]:
|
|
return fallback.known_stream_urls()
|