"""Radio Browser: a directory of the community's stations rather than a station. The most-clicked working relays are loaded a page at a time, and the rest of the 60,000-station directory is searched on the server as you type. There is no now-playing API, so this catalogue offers breadth, not history: pick a station and the stream speaks for itself. """ from __future__ import annotations import httpx from ... import config from ...models import Song, Station from ..base import RadioProvider, StationPage from . import api, fallback from . import hero as hero_art __all__ = ["RadioBrowserProvider"] class RadioBrowserProvider(RadioProvider): id = "radiobrowser" name = "Radio Browser" homepage = "radio-browser.info" brand = "RADIO BROWSER" tagline = "community directory · live search" station_source = "radio-browser.info (paged + search)" history_source = "" hero = hero_art.HERO hero_lines = ("RADIO BROWSER", "COMMUNITY DIRECTORY", "KEYLESS · OPEN DATA") # A directory has no show schedule and no Bandcamp worth scraping. bandcamp = False # The full directory is much larger than the list fetched at startup; the # app asks the API when the filter changes. server_search = True # The directory is loaded a page at a time, in click-count order. paginated = True preserve_order = True @property def user_agent(self) -> str: return f"{config.USER_AGENT}; +https://www.radio-browser.info" async def fetch_stations(self, client: httpx.AsyncClient) -> list[Station]: return await api.fetch_stations(client) async def fetch_station_page( self, client: httpx.AsyncClient, offset: int = 0 ) -> StationPage: return await api.fetch_station_page(client, offset) async def fetch_stations_by_ids( self, client: httpx.AsyncClient, station_ids: list[str] ) -> list[Station]: return await api.fetch_stations_by_ids(client, station_ids) async def search_stations( self, client: httpx.AsyncClient, query: str ) -> list[Station]: return await api.search_stations(client, query) def load_cached_stations(self) -> list[Station]: return api.load_cached_stations() def fallback_stations(self) -> list[Station]: return fallback.fallback_stations() async def fetch_history( self, client: httpx.AsyncClient, station_id: str ) -> list[Song]: # Radio Browser publishes no now-playing data at all. return [] def load_cached_history(self, station_id: str) -> list[Song]: return [] def fallback_urls(self, station: Station) -> list[str]: return [entry["url"] for entry in station.sorted_playlists()]