#!/usr/bin/python3 from dataclasses import dataclass, field from typing import Optional, Dict, Any, List from .track import Track from .album import Album from .artist import Artist from .playlist import Playlist from .types import _int @dataclass class SearchTracksPage: limit: int = 0 offset: int = 0 total: int = 0 items: List[Track] = field(default_factory=list) @staticmethod def from_dict(obj: Any) -> "SearchTracksPage": if not isinstance(obj, dict): return SearchTracksPage() items: List[Track] = [] for it in obj.get("items", []) or []: if isinstance(it, dict): items.append(Track.from_dict(it)) return SearchTracksPage( limit=_int(obj.get("limit")) or 0, offset=_int(obj.get("offset")) or 0, total=_int(obj.get("total")) or len(items), items=items, ) def to_dict(self) -> Dict[str, Any]: return { "limit": self.limit, "offset": self.offset, "total": self.total, "items": [it.to_dict() for it in (self.items or [])] } @dataclass class SearchAlbumsPage: limit: int = 0 offset: int = 0 total: int = 0 items: List[Album] = field(default_factory=list) @staticmethod def from_dict(obj: Any) -> "SearchAlbumsPage": if not isinstance(obj, dict): return SearchAlbumsPage() items: List[Album] = [] for it in obj.get("items", []) or []: if isinstance(it, dict): items.append(Album.from_dict(it)) return SearchAlbumsPage( limit=_int(obj.get("limit")) or 0, offset=_int(obj.get("offset")) or 0, total=_int(obj.get("total")) or len(items), items=items, ) def to_dict(self) -> Dict[str, Any]: return { "limit": self.limit, "offset": self.offset, "total": self.total, "items": [it.to_dict() for it in (self.items or [])] } @dataclass class SearchArtistsPage: limit: int = 0 offset: int = 0 total: int = 0 items: List[Artist] = field(default_factory=list) @staticmethod def from_dict(obj: Any) -> "SearchArtistsPage": if not isinstance(obj, dict): return SearchArtistsPage() items: List[Artist] = [] for it in obj.get("items", []) or []: if isinstance(it, dict): items.append(Artist.from_dict(it)) return SearchArtistsPage( limit=_int(obj.get("limit")) or 0, offset=_int(obj.get("offset")) or 0, total=_int(obj.get("total")) or len(items), items=items, ) def to_dict(self) -> Dict[str, Any]: return { "limit": self.limit, "offset": self.offset, "total": self.total, "items": [it.to_dict() for it in (self.items or [])] } @dataclass class SearchPlaylistsPage: limit: int = 0 offset: int = 0 total: int = 0 items: List[Playlist] = field(default_factory=list) @staticmethod def from_dict(obj: Any) -> "SearchPlaylistsPage": if not isinstance(obj, dict): return SearchPlaylistsPage() items: List[Playlist] = [] for it in obj.get("items", []) or []: if isinstance(it, dict): items.append(Playlist.from_dict(it)) return SearchPlaylistsPage( limit=_int(obj.get("limit")) or 0, offset=_int(obj.get("offset")) or 0, total=_int(obj.get("total")) or len(items), items=items, ) def to_dict(self) -> Dict[str, Any]: return { "limit": self.limit, "offset": self.offset, "total": self.total, "items": [it.to_dict() for it in (self.items or [])] } @dataclass class SearchResult: query: Optional[str] = None tracks: Optional[SearchTracksPage] = None albums: Optional[SearchAlbumsPage] = None artists: Optional[SearchArtistsPage] = None playlists: Optional[SearchPlaylistsPage] = None # raw passthrough for unsupported sections (e.g., shows, episodes) other: Dict[str, Any] = field(default_factory=dict) @staticmethod def from_dict(obj: Any) -> "SearchResult": if not isinstance(obj, dict): return SearchResult() tracks = SearchTracksPage.from_dict(obj.get("tracks", {})) if isinstance(obj.get("tracks"), dict) else None albums = SearchAlbumsPage.from_dict(obj.get("albums", {})) if isinstance(obj.get("albums"), dict) else None artists = SearchArtistsPage.from_dict(obj.get("artists", {})) if isinstance(obj.get("artists"), dict) else None playlists = SearchPlaylistsPage.from_dict(obj.get("playlists", {})) if isinstance(obj.get("playlists"), dict) else None known = {k for k in ("query", "tracks", "albums", "artists", "playlists")} other = {k: v for k, v in obj.items() if k not in known} return SearchResult( query=obj.get("query"), tracks=tracks, albums=albums, artists=artists, playlists=playlists, other=other, ) def to_dict(self) -> Dict[str, Any]: out: Dict[str, Any] = {} if self.query is not None: out["query"] = self.query if self.tracks is not None: out["tracks"] = self.tracks.to_dict() if self.albums is not None: out["albums"] = self.albums.to_dict() if self.artists is not None: out["artists"] = self.artists.to_dict() if self.playlists is not None: out["playlists"] = self.playlists.to_dict() out.update(self.other or {}) return out