Source code for minim.api.musixmatch._lyrics_api.matcher

from __future__ import annotations
from typing import TYPE_CHECKING
import warnings

from ..._shared import TTLCache
from ._shared import MusixmatchResourceAPI

if TYPE_CHECKING:
    from typing import Any


[docs] class MatcherAPI(MusixmatchResourceAPI): """ Matcher API endpoints for the Musixmatch Lyrics API. .. important:: This class is managed by :class:`~minim.api.musixmatch.MusixmatchLyricsAPIClient` and should not be instantiated directly. """ __slots__ = () def _match_resource( self, endpoint: str, /, *, artist: str | None = None, track: str | None = None, isrc: str | None = None, params: dict[str, Any] | None = None, ) -> dict[str, Any]: """ Match a track by artist and track name or by ISRC, and get Musixmatch catalog information for it or one of its subresources. Parameters ---------- artist : str; keyword-only; optional Artist name to match. track : str; keyword-only; optional Track name to match. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. params : dict[str, Any]; keyword-only; optional Query parameters to include in the request. If not provided, an empty dictionary will be created. .. note:: This `dict` is mutated in-place. Returns ------- resource : dict[str, Any] Musixmatch metadata for the track or one of its subresources. """ if params is None: params = {} if isrc is None: if artist is None or track is None: raise ValueError( "Both artist and track search queries must be provided." ) params["q_artist"] = self._prepare_string("artist", artist) params["q_track"] = self._prepare_string("track", track) else: if artist or track: warnings.warn( "The track ISRC takes precedence over the artist " "and track search queries, so the latter will be " "omitted from the request." ) params["track_isrc"] = self._prepare_isrc(isrc) return self._client._request("GET", endpoint, params=params).json()
[docs] @TTLCache.cached_method(ttl="static") def match_track_lyrics( self, *, artist: str | None = None, track: str | None = None, isrc: str | None = None, ) -> dict[str, Any]: """ `Matcher > matcher.lyrics.get <https://docs.musixmatch.com /lyrics-api/matcher/matcher-lyrics-get>`_: Match a track by artist and track name (fuzzy search) or by ISRC to get Musixmatch catalog information for its lyrics. .. admonition:: Subscription :class: entitlement .. tab-set:: .. tab-item:: Required Musixmatch Basic plan Access music metadata and static lyrics. `Learn more. <https://about.musixmatch.com/api-pricing>`__ Parameters ---------- artist : str; keyword-only; optional Artist name to match. track : str; keyword-only; optional Track name to match. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. Returns ------- lyrics : dict[str, Any] Musixmatch metadata for the matched track's lyrics. .. admonition:: Sample response :class: response dropdown .. code-block:: { "message": { "body": { "lyrics": { "explicit": <int>, "lyrics_body": <str>, "lyrics_copyright": <str>, "lyrics_id": <int>, "lyrics_language": <str>, "pixel_tracking_url": <str>, "region_restriction": { "allowed": <list[str]>, "blocked": <list[str]> }, "script_tracking_url": <str>, "updated_time": <str> } }, "header": { "execute_time": <float>, "status_code": <int> } } } """ return self._match_resource( "matcher.lyrics.get", artist=artist, track=track, isrc=isrc )
[docs] @TTLCache.cached_method(ttl="popularity") def match_track( self, *, artist: str | None = None, track: str | None = None, isrc: str | None = None, ) -> dict[str, Any]: """ `Matcher > matcher.track.get <https://docs.musixmatch.com /lyrics-api/matcher/matcher-track-get>`_: Match a track by artist and track name (fuzzy search) or by ISRC to get Musixmatch catalog information for it. .. admonition:: Subscription :class: entitlement .. tab-set:: .. tab-item:: Required Musixmatch Basic plan Access music metadata and static lyrics. `Learn more. <https://about.musixmatch.com/api-pricing>`__ Parameters ---------- artist : str; keyword-only; optional Artist name to match. track : str; keyword-only; optional Track name to match. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. Returns ------- track : dict[str, Any] Musixmatch metadata for the matched track. .. admonition:: Sample response :class: response dropdown .. code-block:: { "message": { "body": { "track": { "album_id": <int>, "album_name": <str>, "artist_id": <int>, "artist_name": <str>, "commontrack_id": <int>, "commontrack_isrcs": <list[list[str]]>, "explicit": <int>, "has_lyrics": <int>, "has_richsync": <int>, "has_subtitles": <int>, "instrumental": <int>, "num_favourite": <int>, "primary_genres": { "music_genre_list": [ { "music_genre": { "music_genre_id": <int>, "music_genre_name": <str>, "music_genre_name_extended": <str>, "music_genre_parent_id": <int>, "music_genre_vanity": <str> } } ] }, "restricted": <int>, "track_edit_url": <str>, "track_id": <int>, "track_isrc": <str>, "track_length": <int>, "track_lyrics_translation_status": [ { "from": <str>, "perc": <int>, "to": <str> } ], "track_name": <str>, "track_rating": <int>, "track_share_url": <str>, "track_spotify_id": <str>, "updated_time": <str> } }, "header": { "cached": <int>, "confidence": <int>, "execute_time": <float>, "mode": <str>, "status_code": <int> } } } """ return self._match_resource( "matcher.track.get", artist=artist, track=track, isrc=isrc )
[docs] @TTLCache.cached_method(ttl="static") def match_track_subtitles( self, *, artist: str | None = None, track: str | None = None, isrc: str | None = None, duration: int | str | None = None, max_duration_deviation: int | str | None = None, ) -> dict[str, Any]: """ `Matcher > matcher.subtitle.get <https://docs.musixmatch.com /lyrics-api/matcher/matcher-subtitle-get>`_: Match a track by artist and track name (fuzzy search) or by ISRC to get Musixmatch catalog information for its subtitles. .. admonition:: Subscription :class: entitlement .. tab-set:: .. tab-item:: Required Musixmatch Scale plan Access time-synced lyrics. `Learn more. <https://about.musixmatch.com/api-pricing>`__ Parameters ---------- artist : str; keyword-only; optional Artist name to match. track : str; keyword-only; optional Track name to match. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. duration : int or str; keyword-only; optional Target subtitle duration, in seconds. max_duration_deviation : int or str; keyword-only; optional Maximum deviation allowed from the requested duration. Only applicable when `duration` is specified. Returns ------- subtitles : dict[str, Any] Musixmatch metadata for the matched track's subtitles. .. admonition:: Sample response :class: response dropdown .. code-block:: { "message": { "body": { "subtitle": { "html_tracking_url": <str>, "lyrics_copyright": <str>, "pixel_tracking_url": <str>, "published_status": <int>, "publisher_list": [], "restricted": <int>, "script_tracking_url": <str>, "subtitle_avg_count": <int>, "subtitle_body": <str>, "subtitle_id": <int>, "subtitle_language": <str>, "subtitle_language_description": <str>, "subtitle_length": <int>, "updated_time": <str>, "writer_list": [] } }, "header": { "execute_time": <float>, "status_code": <int> } } } """ self._client._require_api_key("matcher.match_track_subtitles") params = {} if duration is not None: self._validate_numeric("duration", duration, int, 0) params["f_subtitle_length"] = duration if max_duration_deviation is not None: self._validate_numeric( "max_duration_deviation", max_duration_deviation, int, 0 ) params["f_subtitle_length_max_deviation"] = ( max_duration_deviation ) return self._match_resource( "matcher.subtitle.get", artist=artist, track=track, isrc=isrc, params=params, )