Source code for nyora.services.sources

"""Source catalog operations."""

from __future__ import annotations

import builtins
from typing import TYPE_CHECKING, Any, cast

from nyora.models import Source, SourceFilter

if TYPE_CHECKING:
    from nyora.client import Nyora


[docs] class SourcesService: """Browse, manage, and inspect the helper's content sources. Attached to a client as ``client.sources``. """ def __init__(self, client: Nyora) -> None: """Bind the service to a helper client. Args: client: The owning :class:`nyora.client.Nyora` instance. """ self._client = client
[docs] def list(self) -> builtins.list[Source]: """List the installed sources. Returns: The installed :class:`~nyora.models.Source` records. """ data = cast(dict[str, Any], self._client.get("/sources")) return [Source.from_json(item) for item in data.get("sources", data.get("entries", []))]
[docs] def catalog(self) -> builtins.list[Source]: """List every source available in the catalog (installed or not). Returns: All catalog :class:`~nyora.models.Source` records. """ data = cast(dict[str, Any], self._client.get("/sources/catalog")) return [Source.from_json(item) for item in data.get("entries", [])]
[docs] def refresh(self) -> builtins.list[Source]: """Refresh the source catalog from the remote feed. Returns: The refreshed list of :class:`~nyora.models.Source` records. """ data = cast(dict[str, Any], self._client.post("/sources/refresh")) return [Source.from_json(item) for item in data.get("sources", data.get("entries", []))]
[docs] def install(self, source_id: str) -> Source | dict[str, Any]: """Install a source by id. Args: source_id: Identifier of the source to install. Returns: The installed :class:`~nyora.models.Source`, or the raw response dict when no ``source`` field is present. """ data = cast(dict[str, Any], self._client.post("/sources/install", params={"id": source_id})) if "source" in data: return Source.from_json(data["source"]) return data
[docs] def uninstall(self, source_id: str) -> dict[str, Any]: """Uninstall a source by id. Args: source_id: Identifier of the source to uninstall. Returns: The raw helper response. """ return cast( dict[str, Any], self._client.delete("/sources/uninstall", params={"id": source_id}), )
[docs] def pin(self, source_id: str) -> dict[str, Any]: """Toggle the pinned state of a source. Args: source_id: Identifier of the source to pin/unpin. Returns: The raw helper response. """ return cast(dict[str, Any], self._client.post("/sources/pin", params={"id": source_id}))
[docs] def filters(self, source_id: str) -> builtins.list[SourceFilter]: """List the search filters a source advertises. Args: source_id: Identifier of the source to query. Returns: The source's :class:`~nyora.models.SourceFilter` definitions. """ data = cast(dict[str, Any], self._client.get("/sources/filters", params={"id": source_id})) entries = data.get("filters", data.get("entries", [])) return [SourceFilter.from_json(item) for item in entries]
[docs] def find(self, query: str) -> Source: """Find an installed source by a case-insensitive id or name substring. Args: query: Substring matched against each source's id and name. Returns: The first matching :class:`~nyora.models.Source`. Raises: LookupError: If no installed source matches ``query``. """ needle = query.casefold() for source in self.list(): if needle in source.id.casefold() or needle in source.name.casefold(): return source raise LookupError(f"No installed source matched {query!r}")