feat(radiobrowser): add search, paging and favourite lookup
This commit is contained in:
1 parent
f96923b5b7
commit
638cc9eddb
8 files changed
+1018
-45
No files matched your search
@@ -18,6 +18,7 @@ import asyncio
|
||||
import re
|
||||
import time
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
from urllib.parse import quote
|
||||
|
||||
@@ -29,6 +30,7 @@ from ..models import Broadcast, Song, Station
|
||||
__all__ = [
|
||||
"PLAYLIST_TTL",
|
||||
"RadioProvider",
|
||||
"StationPage",
|
||||
"fetch_json",
|
||||
"is_direct_stream",
|
||||
"is_playlist",
|
||||
@@ -62,6 +64,15 @@ def reset_playlist_cache() -> None:
|
||||
_PLAYLIST_CACHE = None
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class StationPage:
|
||||
"""One page of a large catalogue, in the catalogue's own order."""
|
||||
|
||||
stations: list[Station]
|
||||
#: Offset to request next, or ``None`` when the catalogue is exhausted.
|
||||
next_offset: int | None = None
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# the interface
|
||||
# --------------------------------------------------------------------------- #
|
||||
@@ -114,6 +125,20 @@ class RadioProvider(ABC):
|
||||
#: stations that would rather not be scraped).
|
||||
bandcamp: bool = True
|
||||
|
||||
#: The catalogue can search its whole directory on the server. When true,
|
||||
#: the app calls :meth:`search_stations` as the filter changes instead of
|
||||
#: only filtering the (possibly small) list from :meth:`fetch_stations`.
|
||||
server_search: bool = False
|
||||
|
||||
#: The catalogue is larger than one page. When true, the app fetches the
|
||||
#: first page with :meth:`fetch_station_page` and asks for the next one as
|
||||
#: the station list nears its end.
|
||||
paginated: bool = False
|
||||
|
||||
#: Keep the catalogue's own ordering (popularity, schedule, ...) instead of
|
||||
#: sorting the station list alphabetically.
|
||||
preserve_order: bool = False
|
||||
|
||||
# -- catalogue ------------------------------------------------------- #
|
||||
|
||||
@abstractmethod
|
||||
@@ -128,6 +153,37 @@ class RadioProvider(ABC):
|
||||
def fallback_stations(self) -> list[Station]:
|
||||
"""A bundled list, so a fresh offline start still works."""
|
||||
|
||||
async def search_stations(
|
||||
self, client: httpx.AsyncClient, query: str
|
||||
) -> list[Station]:
|
||||
"""Search the catalogue for *query*.
|
||||
|
||||
Only called when :attr:`server_search` is true. Providers that search
|
||||
locally leave this alone; the app filters the loaded list itself.
|
||||
"""
|
||||
return []
|
||||
|
||||
async def fetch_station_page(
|
||||
self, client: httpx.AsyncClient, offset: int = 0
|
||||
) -> StationPage:
|
||||
"""One page of a paginated catalogue.
|
||||
|
||||
Only called when :attr:`paginated` is true. ``offset`` is the value
|
||||
from the previous page's :attr:`StationPage.next_offset`.
|
||||
"""
|
||||
return StationPage(stations=[], next_offset=None)
|
||||
|
||||
async def fetch_stations_by_ids(
|
||||
self, client: httpx.AsyncClient, station_ids: list[str]
|
||||
) -> list[Station]:
|
||||
"""Fetch specific stations by id.
|
||||
|
||||
Used for favourites that are not on the first page of a paginated
|
||||
catalogue. Providers that return their whole catalogue at once can
|
||||
leave this alone.
|
||||
"""
|
||||
return []
|
||||
|
||||
# -- metadata -------------------------------------------------------- #
|
||||
|
||||
@abstractmethod
|
||||
|
||||
Reference in new issue
Block a user