Source code for minim.api.deezer._api.search

from __future__ import annotations
from typing import TYPE_CHECKING

from ..._shared import TTLCache
from ._shared import DeezerResourceAPI

if TYPE_CHECKING:
    from typing import Any


[docs] class SearchAPI(DeezerResourceAPI): """ Search API endpoints for the Deezer API. .. important:: This class is managed by :class:`~minim.api.deezer.DeezerAPIClient` and should not be instantiated directly. """ _SORT_FIELDS = { "RANKING", "TRACK", "ARTIST", "ALBUM", "RATING", "DURATION", } __slot__ = () def _search_resource( self, resource_type: str | None, query: str | None, /, *, strict: bool | None = None, limit: int | None = None, offset: int | None = None, sort_by: str | None = None, descending: bool = False, ) -> dict[str, Any]: """ Search for albums, artists, playlists, podcasts, radios, tracks, and/or users on Deezer. Parameters ---------- resource_type : str or None; positional-only Resource type. **Valid values**: :code:`"albums"`, :code:`"artists"`, :code:`"playlists"`, :code:`"podcasts"`, :code:`"rasios"`, :code:`"tracks"`, :code:`"users"`. query : str; positional-only; optional Search query. strict : bool; keyword-only; optional Whether to use strict matching instead of fuzzy search. **API default**: :code:`False`. limit : int; keyword-only; optional Maximum number of items to return. **Minimum value**: :code:`1`. 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`. sort_by : str; keyword-only; optional Field to sort the search results by. **Valid values**: :code:`"RANKING"`, :code:`"TRACK"`, :code:`"ARTIST"`, :code:`"ALBUM"`, :code:`"RATING"`, :code:`"DURATION"`. descending : bool; keyword-only; default: :code:`False` Whether to sort in descending order. Only applicable when `sort_by` is not :code:`"RANKING"`. Returns ------- results : dict[str, Any] Page of Deezer metadata for the matching catalog items. """ endpoint = "search" if resource_type is not None: endpoint += f"/{resource_type}" if query is not None: params = {"q": self._prepare_string("query", query)} elif resource_type == "history": params = {} else: raise ValueError("`query` cannot be blank.") if strict is not None: self._validate_type("strict", strict, bool) if strict: params["strict"] = "on" if limit is not None: self._validate_number("limit", limit, int, 1) params["limit"] = limit if offset is not None: self._validate_number("offset", offset, int, 0) params["index"] = offset if sort_by is not None: sort_by = sort_by.strip().upper() if sort_by == "RANKING": params["order"] = sort_by else: if sort_by not in self._SORT_FIELDS: raise ValueError( f"Invalid sort field {sort_by!r}. Valid " f"values: {self._join_values(self._SORT_FIELDS)}." ) self._validate_type("descending", descending, bool) params["order"] = ( f"{sort_by}_{'DESC' if descending else 'ASC'}" ) return self._client._request("GET", endpoint, params=params).json()
[docs] @TTLCache.cached_method(ttl="search") def search_albums( self, query: str, /, *, strict: bool | None = None, limit: int | None = None, offset: int | None = None, sort_by: str | None = None, descending: bool = False, ) -> dict[str, Any]: """ `Search > Album <https://developers.deezer.com/api/search /album>`_: Search for albums in the Deezer catalog. Parameters ---------- query : str; positional-only Search query. .. tip:: Use the Advanced Search feature to narrow down results by specific fields. Provide key–value pairs separated by a colon (:code:`:`), and wrap strings in quotes: * :code:`artist` - Artist name, e.g., :code:`artist:"aloe blacc"`. * :code:`album` - Album name, e.g., :code:`album:"good things"`. * :code:`track` - Track name, e.g., :code:`track:"i need a dollar"`. * :code:`label` - Label name, e.g., :code:`label:"because music"`. * :code:`dur_min` / :code:`dur_max` - Track duration in seconds, e.g., :code:`dur_min:300 dur_max:500`. * :code:`bpm_min` / :code:`bpm_max` - Track tempo (BPM), e.g., :code:`bpm_min:120 bpm_max:200`. **Example**: :code:`artist:"aloe blacc" track:"i need a dollar" bpm_min:120 dur_min:300`. strict : bool; keyword-only; optional Whether to use strict matching instead of fuzzy search. **API default**: :code:`False`. limit : int; keyword-only; optional Maximum number of albums to return. **Minimum value**: :code:`1`. offset : int; keyword-only; optional Index of the first album to return. Use with `limit` to get the next batch of albums. **Minimum value**: :code:`0`. **API default**: :code:`0`. sort_by : str; keyword-only; optional Field to sort the returned albums by. **Valid values**: :code:`"RANKING"`, :code:`"TRACK"`, :code:`"ARTIST"`, :code:`"ALBUM"`, :code:`"RATING"`, :code:`"DURATION"`. descending : bool; keyword-only; default: :code:`False` Whether to sort in descending order. Only applicable when `sort_by` is not :code:`"RANKING"`. Returns ------- albums : dict[str, Any] Page of Deezer metadata for the matching albums. .. admonition:: Sample response :class: response dropdown .. code-block:: { "data": [ { "artist": { "id": <int>, "link": <str>, "name": <str>, "picture": <str>, "picture_big": <str>, "picture_medium": <str>, "picture_small": <str>, "picture_xl": <str>, "tracklist": <str>, "type": "artist" }, "cover": <str>, "cover_big": <str>, "cover_medium": <str>, "cover_small": <str>, "cover_xl": <str>, "explicit_lyrics": <bool>, "genre_id": <int>, "id": <int>, "link": <str>, "md5_image": <str>, "nb_tracks": <int>, "record_type": <str>, "title": <str>, "tracklist": <str>, "type": "album" } ], "next": <str>, "prev": <str>, "total": <int> } """ return self._search_resource( "album", query, strict=strict, limit=limit, offset=offset, sort_by=sort_by, descending=descending, )
[docs] @TTLCache.cached_method(ttl="search") def search_artists( self, query: str, /, *, strict: bool | None = None, limit: int | None = None, offset: int | None = None, sort_by: str | None = None, descending: bool = False, ) -> dict[str, Any]: """ `Search > Artist <https://developers.deezer.com/api/search /artist>`_: Search for artists in the Deezer catalog. Parameters ---------- query : str; positional-only Search query. .. tip:: Use the Advanced Search feature to narrow down results by specific fields. Provide key–value pairs separated by a colon (:code:`:`), and wrap strings in quotes: * :code:`artist` - Artist name, e.g., :code:`artist:"aloe blacc"`. * :code:`album` - Album name, e.g., :code:`album:"good things"`. * :code:`track` - Track name, e.g., :code:`track:"i need a dollar"`. * :code:`label` - Label name, e.g., :code:`label:"because music"`. * :code:`dur_min` / :code:`dur_max` - Track duration in seconds, e.g., :code:`dur_min:300 dur_max:500`. * :code:`bpm_min` / :code:`bpm_max` - Track tempo (BPM), e.g., :code:`bpm_min:120 bpm_max:200`. **Example**: :code:`artist:"aloe blacc" track:"i need a dollar" bpm_min:120 dur_min:300`. strict : bool; keyword-only; optional Whether to use strict matching instead of fuzzy search. **API default**: :code:`False`. limit : int; keyword-only; optional Maximum number of artists to return. **Minimum value**: :code:`1`. offset : int; keyword-only; optional Index of the first artist to return. Use with `limit` to get the next batch of artists. **Minimum value**: :code:`0`. **API default**: :code:`0`. sort_by : str; keyword-only; optional Field to sort the returned artists by. **Valid values**: :code:`"RANKING"`, :code:`"TRACK"`, :code:`"ARTIST"`, :code:`"ALBUM"`, :code:`"RATING"`, :code:`"DURATION"`. descending : bool; keyword-only; default: :code:`False` Whether to sort in descending order. Only applicable when `sort_by` is not :code:`"RANKING"`. Returns ------- artists : dict[str, Any] Page of Deezer metadata for the matching artists. .. admonition:: Sample response :class: response dropdown .. code-block:: { "data": [ { "id": <int>, "link": <str>, "name": <str>, "nb_album": <int>, "nb_fan": <int>, "picture": <str>, "picture_big": <str>, "picture_medium": <str>, "picture_small": <str>, "picture_xl": <str>, "radio": <bool>, "tracklist": <str>, "type": "artist" } ], "next": <str>, "prev": <str>, "total": <int> } """ return self._search_resource( "artist", query, strict=strict, limit=limit, offset=offset, sort_by=sort_by, descending=descending, )
[docs] @TTLCache.cached_method(ttl="search") def search_playlists( self, query: str, /, *, strict: bool | None = None, limit: int | None = None, offset: int | None = None, sort_by: str | None = None, descending: bool = False, ) -> dict[str, Any]: """ `Search > Playlist <https://developers.deezer.com/api/search /playlist>`_: Search for playlists in the Deezer catalog. Parameters ---------- query : str; positional-only Search query. strict : bool; keyword-only; optional Whether to use strict matching instead of fuzzy search. **API default**: :code:`False`. limit : int; keyword-only; optional Maximum number of playlists to return. **Minimum value**: :code:`1`. offset : int; keyword-only; optional Index of the first playlist to return. Use with `limit` to get the next batch of playlists. **Minimum value**: :code:`0`. **API default**: :code:`0`. sort_by : str; keyword-only; optional Field to sort the returned playlists by. **Valid values**: :code:`"RANKING"`, :code:`"TRACK"`, :code:`"ARTIST"`, :code:`"ALBUM"`, :code:`"RATING"`, :code:`"DURATION"`. descending : bool; keyword-only; default: :code:`False` Whether to sort in descending order. Only applicable when `sort_by` is not :code:`"RANKING"`. Returns ------- playlists : dict[str, Any] Page of Deezer metadata for the matching playlists. .. admonition:: Sample response :class: response dropdown .. code-block:: { "data": [ { "add_date": <str>, "checksum": <str>, "creation_date": <str>, "id": <int>, "link": <str>, "md5_image": <str>, "mod_date": <str>, "nb_tracks": <int>, "picture": <str>, "picture_big": <str>, "picture_medium": <str>, "picture_small": <str>, "picture_type": <str>, "picture_xl": <str>, "public": <bool>, "title": <str>, "tracklist": <str>, "type": <str>, "user": { "id": <int>, "name": <str>, "tracklist": <str>, "type": "user" } } ], "next": <str>, "prev": <str>, "total": <int> } """ return self._search_resource( "playlist", query, strict=strict, limit=limit, offset=offset, sort_by=sort_by, descending=descending, )
[docs] @TTLCache.cached_method(ttl="search") def search_podcasts( self, query: str, /, *, strict: bool | None = None, limit: int | None = None, offset: int | None = None, sort_by: str | None = None, descending: bool = False, ) -> dict[str, Any]: """ `Search > Podcast <https://developers.deezer.com/api/search /podcast>`_: Search for podcasts in the Deezer catalog. Parameters ---------- query : str; positional-only Search query. strict : bool; keyword-only; optional Whether to use strict matching instead of fuzzy search. **API default**: :code:`False`. limit : int; keyword-only; optional Maximum number of podcasts to return. **Minimum value**: :code:`1`. offset : int; keyword-only; optional Index of the first podcast to return. Use with `limit` to get the next batch of podcasts. **Minimum value**: :code:`0`. **API default**: :code:`0`. sort_by : str; keyword-only; optional Field to sort the returned podcasts by. **Valid values**: :code:`"RANKING"`, :code:`"TRACK"`, :code:`"ARTIST"`, :code:`"ALBUM"`, :code:`"RATING"`, :code:`"DURATION"`. descending : bool; keyword-only; default: :code:`False` Whether to sort in descending order. Only applicable when `sort_by` is not :code:`"RANKING"`. Returns ------- podcasts : dict[str, Any] Page of Deezer metadata for the matching podcasts. .. admonition:: Sample response :class: response dropdown .. code-block:: { "data": [ { "available": <bool>, "description": <str>, "fans": <int>, "id": <int>, "link": <str>, "picture": <str>, "picture_big": <str>, "picture_medium": <str>, "picture_small": <str>, "picture_xl": <str>, "share": <str>, "title": <str>, "type": "podcast" } ], "next": <str>, "prev": <str>, "total": <int> } """ return self._search_resource( "podcast", query, strict=strict, limit=limit, offset=offset, sort_by=sort_by, descending=descending, )
[docs] @TTLCache.cached_method(ttl="search") def search_radios( self, query: str, /, *, strict: bool | None = None, limit: int | None = None, offset: int | None = None, sort_by: str | None = None, descending: bool = False, ) -> dict[str, Any]: """ `Search > Radio <https://developers.deezer.com/api/search /radio>`_: Search for radios in the Deezer catalog. Parameters ---------- query : str; positional-only Search query. strict : bool; keyword-only; optional Whether to use strict matching instead of fuzzy search. **API default**: :code:`False`. limit : int; keyword-only; optional Maximum number of radios to return. **Minimum value**: :code:`1`. offset : int; keyword-only; optional Index of the first radio to return. Use with `limit` to get the next batch of radios. **Minimum value**: :code:`0`. **API default**: :code:`0`. sort_by : str; keyword-only; optional Field to sort the returned radios by. **Valid values**: :code:`"RANKING"`, :code:`"TRACK"`, :code:`"ARTIST"`, :code:`"ALBUM"`, :code:`"RATING"`, :code:`"DURATION"`. descending : bool; keyword-only; default: :code:`False` Whether to sort in descending order. Only applicable when `sort_by` is not :code:`"RANKING"`. Returns ------- radios : dict[str, Any] Page of Deezer metadata for the matching radios. .. admonition:: Sample response :class: response dropdown .. code-block:: { "data": [ { "id": <int>, "md5_image": <str>, "picture": <str>, "picture_big": <str>, "picture_medium": <str>, "picture_small": <str>, "picture_xl": <str>, "title": <str>, "tracklist": <str>, "type": "radio" } ], "next": <str>, "prev": <str>, "total": <int> } """ return self._search_resource( "radio", query, strict=strict, limit=limit, offset=offset, sort_by=sort_by, descending=descending, )
[docs] @TTLCache.cached_method(ttl="search") def search_tracks( self, query: str, /, *, strict: bool | None = None, limit: int | None = None, offset: int | None = None, sort_by: str | None = None, descending: bool = False, ) -> dict[str, Any]: """ `Search > Track <https://developers.deezer.com/api/search /track>`_: Search for tracks in the Deezer catalog. Parameters ---------- query : str; positional-only Search query. .. tip:: Use the Advanced Search feature to narrow down results by specific fields. Provide key–value pairs separated by a colon (:code:`:`), and wrap strings in quotes: * :code:`artist` - Artist name, e.g., :code:`artist:"aloe blacc"`. * :code:`album` - Album name, e.g., :code:`album:"good things"`. * :code:`track` - Track name, e.g., :code:`track:"i need a dollar"`. * :code:`label` - Label name, e.g., :code:`label:"because music"`. * :code:`dur_min` / :code:`dur_max` - Track duration in seconds, e.g., :code:`dur_min:300 dur_max:500`. * :code:`bpm_min` / :code:`bpm_max` - Track tempo (BPM), e.g., :code:`bpm_min:120 bpm_max:200`. **Example**: :code:`artist:"aloe blacc" track:"i need a dollar" bpm_min:120 dur_min:300`. strict : bool; keyword-only; optional Whether to use strict matching instead of fuzzy search. **API default**: :code:`False`. limit : int; keyword-only; optional Maximum number of tracks to return. **Minimum value**: :code:`1`. **API default**: :code:`25`. offset : int; keyword-only; optional Index of the first track to return. Use with `limit` to get the next batch of tracks. **Minimum value**: :code:`0`. **API default**: :code:`0`. sort_by : str; keyword-only; optional Field to sort the returned tracks by. **Valid values**: :code:`"RANKING"`, :code:`"TRACK"`, :code:`"ARTIST"`, :code:`"ALBUM"`, :code:`"RATING"`, :code:`"DURATION"`. descending : bool; keyword-only; default: :code:`False` Whether to sort in descending order. Only applicable when `sort_by` is not :code:`"RANKING"`. Returns ------- tracks : dict[str, Any] Page of Deezer metadata for the matching tracks. .. admonition:: Sample response :class: response dropdown .. code-block:: { "data": [ { "album": { "cover": <str>, "cover_big": <str>, "cover_medium": <str>, "cover_small": <str>, "cover_xl": <str>, "id": <int>, "md5_image": <str>, "title": <str>, "tracklist": <str>, "type": "album" }, "artist": { "id": <int>, "link": <str>, "name": <str>, "picture": <str>, "picture_big": <str>, "picture_medium": <str>, "picture_small": <str>, "picture_xl": <str>, "tracklist": <str>, "type": "artist" }, "duration": <int>, "explicit_content_cover": <int>, "explicit_content_lyrics": <int>, "explicit_lyrics": <bool>, "id": <int>, "link": <str>, "md5_image": <str>, "preview": <str>, "rank": <int>, "readable": <bool>, "title": <str>, "title_short": <str>, "title_version": <str>, "type": "track" } ], "next": <str>, "prev": <str>, "total": <int> } """ return self._search_resource( "track", query, strict=strict, limit=limit, offset=offset, sort_by=sort_by, descending=descending, )
[docs] @TTLCache.cached_method(ttl="search") def search_users( self, query: str, /, *, strict: bool | None = None, limit: int | None = None, offset: int | None = None, sort_by: str | None = None, descending: bool = False, ) -> dict[str, Any]: """ `Search > User <https://developers.deezer.com/api/search /user>`_: Search for users on Deezer. Parameters ---------- query : str; positional-only Search query. strict : bool; keyword-only; optional Whether to use strict matching instead of fuzzy search. **API default**: :code:`False`. limit : int; keyword-only; optional Maximum number of users to return. **Minimum value**: :code:`1`. **API default**: :code:`25`. offset : int; keyword-only; optional Index of the first user to return. Use with `limit` to get the next batch of users. **Minimum value**: :code:`0`. **API default**: :code:`0`. sort_by : str; keyword-only; optional Field to sort the returned users by. **Valid values**: :code:`"RANKING"`, :code:`"TRACK"`, :code:`"ARTIST"`, :code:`"ALBUM"`, :code:`"RATING"`, :code:`"DURATION"`. descending : bool; keyword-only; default: :code:`False` Whether to sort in descending order. Only applicable when `sort_by` is not :code:`"RANKING"`. Returns ------- users : dict[str, Any] Page of Deezer metadata for the matching users. .. admonition:: Sample response :class: response dropdown .. code-block:: { "data": [ { "id": <int>, "name": <str>, "picture": <str>, "picture_big": <str>, "picture_medium": <str>, "picture_small": <str>, "picture_xl": <str>, "tracklist": <str>, "type": "user" } ], "next": <str>, "prev": <str>, "total": <int> } """ return self._search_resource( "user", query, strict=strict, limit=limit, offset=offset, sort_by=sort_by, descending=descending, )
[docs] @TTLCache.cached_method(ttl="user") def get_my_search_history( self, query: str | None = None, /, *, strict: bool | None = None, limit: int | None = None, offset: int | None = None, sort_by: str | None = None, descending: bool = False, ) -> dict[str, Any]: """ `Search > History <https://developers.deezer.com/api/search /history>`_: Get the current user's search history on Deezer. .. admonition:: User authentication :class: entitlement .. tab-set:: .. tab-item:: Required User authentication Access the :code:`GET /search/history` endpoint. Parameters ---------- query : str; positional-only; optional Search query. strict : bool; keyword-only; optional Whether to use strict matching instead of fuzzy search. **API default**: :code:`False`. limit : int; keyword-only; optional Maximum number of searches to return. **Minimum value**: :code:`1`. offset : int; keyword-only; optional Index of the first search to return. Use with `limit` to get the next batch of searches. **Minimum value**: :code:`0`. **API default**: :code:`0`. sort_by : str; keyword-only; optional Field to sort the returned searches by. **Valid values**: :code:`"RANKING"`, :code:`"TRACK"`, :code:`"ARTIST"`, :code:`"ALBUM"`, :code:`"RATING"`, :code:`"DURATION"`. descending : bool; keyword-only; default: :code:`False` Whether to sort in descending order. Only applicable when `sort_by` is not :code:`"RANKING"`. Returns ------- searches : dict[str, Any] Page of Deezer metadata for the current user's search history. .. admonition:: Sample response :class: response dropdown .. code-block:: { "count": <int>, "data": [], "next": <str>, "prev": <str>, "total": <int> } """ self._client._require_authentication("search.get_my_search_history") return self._search_resource( "history", query, strict=strict, limit=limit, offset=offset, sort_by=sort_by, descending=descending, )