Source code for minim.api.qobuz._private_api.favorites

from __future__ import annotations
from typing import TYPE_CHECKING

from ..._shared import TTLCache
from ._shared import PrivateQobuzResourceAPI

if TYPE_CHECKING:
    from typing import Any

    from ...._types import Collection


[docs] class PrivateFavoritesAPI(PrivateQobuzResourceAPI): """ Favorites API endpoints for the private Qobuz API. .. important:: This class is managed by :class:`~minim.api.qobuz.PrivateQobuzAPIClient` and should not be instantiated directly. """ _FAVORITE_TYPES = { "albums", "artists", "articles", "awards", "labels", "tracks", } __slots__ = ()
[docs] def save_items( self, *, album_ids: str | Collection[str] | None = None, artist_ids: int | str | Collection[int | str] | None = None, track_ids: int | str | Collection[int | str] | None = None, ) -> dict[str, str]: """ Favorite one or more albums, artists, and/or tracks. .. admonition:: User authentication :class: entitlement .. tab-set:: .. tab-item:: Required User authentication Access and manage your library. .. important:: At least one of :code:`album_ids`, :code:`artist_ids`, or :code:`track_ids` must be specified. Parameters ---------- album_ids : str or Collection[str]; keyword-only; optional Qobuz IDs of the albums. **Examples**: :code:`"0075679933652"`, :code:`"0075679933652,aaxy9wirwgn2a"`. artist_ids : int, str, or Collection[int | str]; keyword-only; \ optional Qobuz IDs of the artists. **Examples**: :code:`865362`, :code:`"21473137"`, :code:`"865362,21473137"`, :code:`[865362, "21473137"]`. track_ids : int, str, or Collection[int | str]; keyword-only; \ optional Qobuz IDs of the tracks. **Examples**: :code:`23929516`, :code:`"344521217"`, :code:`"23929516,344521217"`, :code:`[23929516, "344521217"]`. Returns ------- status : dict[str, str] Whether the items were favorited successfully. **Sample response**: :code:`{"status": "success"}`. """ self._client._require_authentication("favorites.save_items") payload = {} if album_ids is not None: payload["album_ids"] = self._prepare_album_ids(album_ids) if artist_ids is not None: payload["artist_ids"] = self._prepare_qobuz_ids( artist_ids, data_type=str ) if track_ids is not None: payload["track_ids"] = self._prepare_qobuz_ids( track_ids, data_type=str ) if not payload: raise RuntimeError( "At least one of `album_ids`, `artist_ids`, or " "`track_ids` must be specified." ) return self._client._request( "POST", "favorite/create", data=payload ).json()
[docs] def remove_saved_items( self, *, album_ids: str | Collection[str] | None = None, artist_ids: int | str | Collection[int | str] | None = None, track_ids: int | str | Collection[int | str] | None = None, ) -> dict[str, str]: """ Unfavorite one or more albums, artists, and/or tracks. .. admonition:: User authentication :class: entitlement .. tab-set:: .. tab-item:: Required User authentication Access and manage your library. .. important:: At least one of :code:`album_ids`, :code:`artist_ids`, or :code:`track_ids` must be specified. Parameters ---------- album_ids : str or Collection[str]; keyword-only; optional Qobuz IDs of the albums. **Examples**: :code:`"0075679933652"`, :code:`"0075679933652,aaxy9wirwgn2a"`. artist_ids : int, str, or Collection[int | str]; keyword-only; \ optional Qobuz IDs of the artists. **Examples**: :code:`865362`, :code:`"21473137"`, :code:`"865362,21473137"`, :code:`[865362, "21473137"]`. track_ids : int, str, or Collection[int | str]; keyword-only; \ optional Qobuz IDs of the tracks. **Examples**: :code:`23929516`, :code:`"344521217"`, :code:`"23929516,344521217"`, :code:`[23929516, "344521217"]`. Returns ------- status : dict[str, str] Whether the items were unfavorited successfully. **Sample response**: :code:`{"status": "success"}`. """ self._client._require_authentication("favorites.remove_saved_items") payload = {} if album_ids is not None: payload["album_ids"] = self._prepare_album_ids(album_ids) if artist_ids is not None: payload["artist_ids"] = self._prepare_qobuz_ids( artist_ids, data_type=str ) if track_ids is not None: payload["track_ids"] = self._prepare_qobuz_ids( track_ids, data_type=str ) if not payload: raise RuntimeError( "At least one of `album_ids`, `artist_ids`, or " "`track_ids` must be specified." ) return self._client._request( "POST", "favorite/delete", data=payload ).json()
[docs] @TTLCache.cached_method(ttl="user") def get_my_saved_items( self, item_type: str | None = None, /, *, limit: int | None = None, offset: int | None = None, ) -> dict[str, Any]: """ Get Qobuz catalog information for the current user's favorites. .. admonition:: User authentication :class: entitlement .. tab-set:: .. tab-item:: Required User authentication Access and manage your library. Parameters ---------- item_type : str; positional-only; optional Type of item to return. If not specified, favorites of all types are returned. **Valid values**: :code:`"albums"`, :code:`"articles"`, :code:`"artists"`, :code:`"awards"`, :code:`"labels"`, :code:`"tracks"`. limit : int; keyword-only; optional Maximum number of items to return. **Valid range**: :code:`1` to :code:`500`. **API default**: :code:`50`. offset : int; keyword-only; optional Index of the first item to return. Use with `limit` to get the next batch of items. **Minimum value**: :code:`0`. **API default**: :code:`0`. Returns ------- items : dict[str, Any] Page of Qobuz metadata for the current user's favorites. .. admonition:: Sample response :class: response dropdown .. code-block:: { "albums": { "items": [ { "articles": [], "artist": { "albums_count": <int>, "id": <int>, "image": None, "name": <str>, "picture": None, "slug": <str>, }, "artists": [ { "id": <int>, "name": <str>, "roles": <list[str]> } ], "displayable": <bool>, "downloadable": <bool>, "duration": <int>, "favorited_at": <int>, "genre": { "color": <str>, "id": <int>, "name": <str>, "path": <list[int]>, "slug": <str> }, "hires": <bool>, "hires_streamable": <bool>, "id": <str>, "image": { "back": None, "large": <str>, "small": <str>, "thumbnail": <str>, }, "label": { "albums_count": <int>, "id": <int>, "name": <str>, "slug": <str>, "supplier_id": <int> }, "maximum_bit_depth": <int>, "maximum_channel_count": <int>, "maximum_sampling_rate": <float>, "media_count": <int>, "parental_warning": <bool>, "popularity": <int>, "previewable": <bool>, "purchasable": <bool>, "purchasable_at": <int>, "qobuz_id": <int>, "release_date_download": <str>, "release_date_original": <str>, "release_date_stream": <str>, "released_at": <int>, "sampleable": <bool>, "slug": <str>, "streamable": <bool>, "streamable_at": <int>, "title": <str>, "tracks_count": <int>, "upc": <str>, "url": <str>, "version": <str> } ], "limit": <int>, "offset": <int>, "total": <int> }, "artists": { "items": [ { "albums_count": <int>, "favorited_at": <int>, "id": <int>, "image": { "extralarge": <str>, "large": <str>, "medium": <str>, "mega": <str>, "small": <str>, }, "name": <str>, "slug": <str> } ], "limit": <int>, "offset": <int>, "total": <int> }, "tracks": { "items": [ { "album": { "artist": { "albums_count": <int>, "id": <int>, "image": None, "name": <str>, "picture": None, "slug": <str> }, "displayable": <bool>, "downloadable": <bool>, "duration": <int>, "genre": { "id": <int>, "name": <str>, "path": <list[int]>, "slug": <str> }, "hires": <bool>, "hires_streamable": <bool>, "id": <str>, "image": { "large": <str>, "small": <str>, "thumbnail": <str> }, "label": { "albums_count": <int>, "id": <int>, "name": <str>, "slug": <str>, "supplier_id": <int> }, "maximum_bit_depth": <int>, "maximum_channel_count": <int>, "maximum_sampling_rate": <float>, "media_count": <int>, "parental_warning": <bool>, "previewable": <bool>, "purchasable": <bool>, "purchasable_at": null, "qobuz_id": <int>, "release_date_download": <str>, "release_date_original": <str>, "release_date_purchase": <str>, "release_date_stream": <str>, "released_at": <int>, "sampleable": <bool>, "streamable": <bool>, "streamable_at": <int>, "title": <str>, "tracks_count": <int>, "upc": <str>, "version": None }, "audio_info": { "replaygain_track_gain": <float>, "replaygain_track_peak": <float>, }, "composer": { "id": <int>, "name": <str> }, "copyright": <str>, "displayable": <bool>, "downloadable": <bool>, "duration": <int>, "favorited_at": <int>, "hires": <bool>, "hires_streamable": <bool>, "id": <int>, "isrc": <str>, "maximum_bit_depth": <int>, "maximum_channel_count": <int>, "maximum_sampling_rate": <float>, "media_number": <int>, "parental_warning": <bool>, "performer": { "id": <int>, "name": <str> }, "performers": <str>, "previewable": <bool>, "purchasable": <bool>, "purchasable_at": <int>, "release_date_download": <str>, "release_date_original": <str>, "release_date_purchase": <str>, "release_date_stream": <str>, "sampleable": <bool>, "streamable": <bool>, "streamable_at": <int>, "title": <str>, "track_number": <int>, "version": <str>, "work": None } ], "limit": <int>, "offset": <int>, "total": <int> }, "user": { "id": <int>, "login": <str> } } """ self._client._require_authentication("favorites.get_my_saved_items") params = {} if item_type is not None: item_type = self._prepare_string("item_type", item_type).lower() if item_type not in self._FAVORITE_TYPES: raise ValueError( f"Invalid item type {item_type!r}. Valid values: " f"{self._join_values(self._FAVORITE_TYPES)}." ) return self._get_paginated_resources( "favorite/getUserFavorites", limit=limit, offset=offset, params=params, )
[docs] @TTLCache.cached_method(ttl="user") def get_my_saved_item_ids(self) -> dict[str, Any]: """ Get Qobuz IDs of the current user's favorites. .. admonition:: User authentication :class: entitlement .. tab-set:: .. tab-item:: Required User authentication Access and manage your library. Returns ------- saved_ids : dict[str, Any] Qobuz IDs of the current user's favorites. .. admonition:: Sample response :class: response dropdown .. code-block:: { "albums": <list[str]>, "articles": [], "artists": <list[int]>, "awards": [], "labels": [], "tracks": <list[int]>, } """ self._client._require_authentication("favorites.get_my_saved_item_ids") return self._client._request( "GET", "favorite/getUserFavoriteIds" ).json()
[docs] @TTLCache.cached_method(ttl="user") def is_item_saved( self, item_type: str, item_id: int | str, / ) -> dict[str, bool]: """ Check whether the current user has an item favorited. .. admonition:: User authentication :class: entitlement .. tab-set:: .. tab-item:: Required User authentication Access and manage your library. Parameters ---------- item_type : str; positional-only Type of item. **Valid values**: :code:`"album"`, :code:`"artist"`, :code:`"article"`, :code:`"award"`, :code:`"label"`, :code:`"track"`. item_id : int or str; positional-only Qobuz ID of the item. Returns ------- saved : dict[str, bool] Whether the current user has the item favorited. **Sample response**: :code:`{"status": <bool>}`. """ self._client._require_authentication("favorites.is_item_saved") item_type = self._prepare_string("item_type", item_type).lower() if f"{item_type}s" not in self._FAVORITE_TYPES: raise ValueError( f"Invalid item type {item_type!r}. Valid values: " f"{self._join_values(ft[:-1] for ft in self._FAVORITE_TYPES)}." ) if item_type == "album": self._validate_album_id(item_id) else: self._validate_qobuz_ids(item_id, recursive=False) return self._client._request( "GET", "favorite/status", params={"type": item_type, "item_id": item_id}, ).json()
[docs] def toggle_item_saved( self, item_type: str, item_id: int | str, / ) -> dict[str, bool]: """ Toggle the favorite status of an item. .. admonition:: User authentication :class: entitlement .. tab-set:: .. tab-item:: Required User authentication Access and manage your library. Parameters ---------- item_type : str; positional-only Type of item. **Valid values**: :code:`"album"`, :code:`"artist"`, :code:`"article"`, :code:`"award"`, :code:`"label"`, :code:`"track"`. item_id : int or str; positional-only Qobuz ID of the item. Returns ------- saved : dict[str, bool] Whether the item is now favorited. **Sample response**: :code:`{"status": <bool>}`. """ self._client._require_authentication("favorites.toggle_item_saved") item_type = self._prepare_string("item_type", item_type).lower() if f"{item_type}s" not in self._FAVORITE_TYPES: raise ValueError( f"Invalid item type {item_type!r}. Valid values: " f"{self._join_values(ft[:-1] for ft in self._FAVORITE_TYPES)}." ) if item_type == "album": self._validate_album_id(item_id) else: self._validate_qobuz_ids(item_id, recursive=False) return self._client._request( "POST", "favorite/toggle", params={"type": item_type, "item_id": item_id}, ).json()