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

from __future__ import annotations
from typing import TYPE_CHECKING

from ..._shared import TTLCache, _copy_docstring
from ._shared import MusixmatchResourceAPI
from .charts import ChartsAPI
from .matcher import MatcherAPI

if TYPE_CHECKING:
    from datetime import datetime
    from typing import Any


[docs] class TracksAPI(MusixmatchResourceAPI): """ Tracks API endpoints for the Musixmatch Lyrics API. .. important:: This class is managed by :class:`~minim.api.musixmatch.MusixmatchLyricsAPIClient` and should not be instantiated directly. """ _SUBTITLE_FORMATS = {"lrc", "dfxp", "mxm"} __slots__ = () def _get_track_resource( self, endpoint: str, /, *, track_id: int | str | None = None, common_track_id: int | str | None = None, isrc: str | None = None, params: dict[str, Any] | None = None, ) -> dict[str, Any]: """ Get Musixmatch catalog information for a track resource. Parameters ---------- endpoint : str; positional-only API endpoint for the track resource. track_id : int or str; keyword-only; optional Musixmatch ID of the track. common_track_id : int or str; keyword-only; optional Musixmatch common ID of the track. isrc : int or str; keyword-only; optional ISRC of the track. 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 resource. """ _params = {} if track_id is not None: self._validate_numeric("track_id", track_id, int) _params["track_id"] = track_id if common_track_id is not None: self._validate_numeric("common_track_id", common_track_id, int) _params["commontrack_id"] = common_track_id if isrc is not None: _params["track_isrc"] = self._prepare_isrc(isrc) if not _params: raise ValueError( "At least one of `track_id'`, `common_track_id`, or `isrc` " "must be provided." ) return self._client._request( "GET", endpoint, params=(params or {}) | _params ).json()
[docs] @TTLCache.cached_method(ttl="popularity") def get_track( self, *, track_id: int | str | None = None, common_track_id: int | str | None = None, isrc: str | None = None, ) -> dict[str, Any]: """ `Track > track.get <https://docs.musixmatch.com/lyrics-api /track/track-get>`_: Get Musixmatch catalog information for a track. .. 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>`__ .. important:: At least one of :code:`track_id`, :code:`common_track_id`, or :code:`isrc` must be specified. Parameters ---------- track_id : int or str; keyword-only; optional Musixmatch ID of the track. **Examples**: :code:`84584600`, :code:`"359206419"`. common_track_id : int or str; keyword-only; optional Musixmatch common ID of the track. **Examples**: :code:`5920049`, :code:`"40728258"`. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. Returns ------- track : dict[str, Any] Musixmatch metadata for the track. .. admonition:: Sample response :class: response dropdown .. code-block:: { "message": { "body": { "track": { "album_coverart_100x100": <str>, "album_coverart_350x350": <str>, "album_coverart_500x500": <str>, "album_coverart_800x800": <str>, "album_id": <int>, "album_name": <str>, "album_vanity_id": <str>, "artist_id": <int>, "artist_mbid": <str>, "artist_name": <str>, "commontrack_7digital_ids": <list[int]>, "commontrack_id": <int>, "commontrack_isrcs": <list[list[str]]>, "commontrack_itunes_ids": <list[int]>, "commontrack_spotify_ids": <list[str]>, "commontrack_vanity_id": <str>, "explicit": <int>, "first_release_date": <str>, "has_lyrics": <int>, "has_lyrics_crowd": <int>, "has_richsync": <int>, "has_subtitles": <int>, "has_track_structure": <int>, "instrumental": <int>, "lyrics_id": <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>, "secondary_genres": { "music_genre_list": [] }, "subtitle_id": <int>, "track_edit_url": <str>, "track_id": <int>, "track_isrc": <str>, "track_length": <int>, "track_mbid": <str>, "track_name": <str>, "track_name_translation_list": [], "track_rating": <int>, "track_share_url": <str>, "track_soundcloud_id": <int>, "track_spotify_id": <str>, "track_xboxmusic_id": <str>, "updated_time": <str> } }, "header": { "execute_time": <float>, "status_code": <int> } } } """ return self._get_track_resource( "track.get", track_id=track_id, common_track_id=common_track_id, isrc=isrc, )
[docs] @TTLCache.cached_method(ttl="static") def get_track_lyrics( self, *, track_id: int | str | None = None, common_track_id: int | str | None = None, isrc: str | None = None, ) -> dict[str, Any]: """ `Track > track.lyrics.get <https://docs.musixmatch.com /lyrics-api/track/track-lyrics-get>`_: Get Musixmatch catalog information for lyrics for a track. .. 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>`__ .. important:: At least one of :code:`track_id`, :code:`common_track_id`, or :code:`isrc` must be specified. Parameters ---------- track_id : int or str; keyword-only; optional Musixmatch ID of the track. **Examples**: :code:`84584600`, :code:`"359206419"`. common_track_id : int or str; keyword-only; optional Musixmatch common ID of the track. **Examples**: :code:`5920049`, :code:`"40728258"`. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. Returns ------- lyrics : dict[str, Any] Musixmatch metadata for the track's lyrics. .. admonition:: Sample response :class: response dropdown .. code-block:: { "message": { "body": { "lyrics": { "action_requested": <str>, "backlink_url": <str>, "can_edit": <int>, "check_validation_overridable": <int>, "explicit": <int>, "html_tracking_url": <str>, "instrumental": <int>, "locked": <int>, "lyrics_body": <str>, "lyrics_copyright": <str>, "lyrics_id": <int>, "lyrics_language": <str>, "lyrics_language_description": <str>, "pixel_tracking_url": <str>, "published_status": <int>, "publisher_list": [], "restricted": <int>, "script_tracking_url": <str>, "updated_time": <str>, "verified": <int>, "writer_list": [] } }, "header": { "execute_time": <float>, "status_code": <int> } } } """ return self._get_track_resource( "track.lyrics.get", track_id=track_id, common_track_id=common_track_id, isrc=isrc, )
[docs] @TTLCache.cached_method(ttl="static") def get_track_lyrics_moods( self, *, track_id: int | str | None = None, common_track_id: int | str | None = None, isrc: str | None = None, ) -> dict[str, Any]: """ `Track > track.lyrics.mood.get <https://docs.musixmatch.com /lyrics-api/track/track-lyrics-mood-get>`_: Get the five most prevalent moods associated with a track's lyrics. .. admonition:: Subscription :class: entitlement .. tab-set:: .. tab-item:: Required Musixmatch Enterprise plan Access extended music metadata, advanced search, translations, song structure, and lyric analysis. `Learn more. <https://about.musixmatch.com /api-pricing>`__ .. important:: At least one of :code:`track_id`, :code:`common_track_id`, or :code:`isrc` must be specified. Parameters ---------- track_id : int or str; keyword-only; optional Musixmatch ID of the track. **Examples**: :code:`84584600`, :code:`"359206419"`. common_track_id : int or str; keyword-only; optional Musixmatch common ID of the track. **Examples**: :code:`5920049`, :code:`"40728258"`. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. Returns ------- moods : dict[str, Any] Moods associated with the track's lyrics. .. admonition:: Sample response :class: response dropdown .. code-block:: { "message": { "body": { "mood_list": [ { "label": <str>, "value": <float> } ] }, "header": { "execute_time": <float>, "status_code": <int> } } } """ self._client._require_api_key("tracks.get_track_lyrics_moods") return self._get_track_resource( "track.lyrics.mood.get", track_id=track_id, common_track_id=common_track_id, isrc=isrc, )
[docs] @TTLCache.cached_method(ttl="static") def get_track_subtitles( self, *, track_id: int | str | None = None, common_track_id: int | str | None = None, isrc: str | None = None, format: str | None = None, duration: int | str | None = None, max_duration_deviation: int | str | None = None, ) -> dict[str, Any]: """ `Track > track.subtitle.get <https://docs.musixmatch.com /lyrics-api/track/track-subtitle-get>`_: Get Musixmatch catalog information for subtitles for a track. .. admonition:: Subscription :class: entitlement .. tab-set:: .. tab-item:: Required Musixmatch Scale plan Access time-synced lyrics. `Learn more. <https://about.musixmatch.com/api-pricing>`__ .. important:: At least one of :code:`track_id`, :code:`common_track_id`, or :code:`isrc` must be specified. Parameters ---------- track_id : int or str; keyword-only; optional Musixmatch ID of the track. **Examples**: :code:`84584600`, :code:`"359206419"`. common_track_id : int or str; keyword-only; optional Musixmatch common ID of the track. **Examples**: :code:`5920049`, :code:`"40728258"`. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. format : str; keyword-only; optional Subtitle format. **Valid values**: :code:`"lrc"`, :code:`"dfxp"`, :code:`"mxm"`. **API default**: :code:`"lrc"`. 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 track's subtitles. .. admonition:: Sample response :class: response dropdown .. code-block:: { "message": { "body": { "subtitle": { "lyrics_copyright": <str>, "pixel_tracking_url": <str>, "script_tracking_url": <str>, "subtitle_body": <str>, "subtitle_id": <int>, "subtitle_language": <str>, "subtitle_language_description": <str>, "subtitle_length": <int>, "updated_time": <str> } }, "header": { "execute_time": <float>, "instrumental": <int>, "status_code": <int>, } } } """ self._client._require_api_key("tracks.get_track_subtitles") params = {} if format is not None: format = self._prepare_string("format", format).lower() if format not in self._SUBTITLE_FORMATS: raise ValueError( f"Invalid subtitle format {format!r}. Valid " f"values: {self._join_values(self._SUBTITLE_FORMATS)}." ) params["subtitle_format"] = format 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._get_track_resource( "track.subtitles.get", track_id=track_id, common_track_id=common_track_id, isrc=isrc, params=params, )
[docs] @TTLCache.cached_method(ttl="static") def get_track_word_synced_lyrics( self, *, track_id: int | str | None = None, common_track_id: int | str | None = None, isrc: str | None = None, duration: int | None = None, max_duration_deviation: int | None = None, ) -> dict[str, Any]: """ `Track > track.richsync.get <https://docs.musixmatch.com /lyrics-api/track/track-richsync-get>`_: Get Musixmatch catalog information for Rich Sync (word-synchronized) lyrics for a track. .. admonition:: Subscription :class: entitlement .. tab-set:: .. tab-item:: Required Musixmatch Enterprise plan Access extended music metadata, advanced search, translations, song structure, and lyric analysis. `Learn more. <https://about.musixmatch.com /api-pricing>`__ .. important:: At least one of :code:`track_id`, :code:`common_track_id`, or :code:`isrc` must be specified. Parameters ---------- track_id : int or str; keyword-only; optional Musixmatch ID of the track. **Examples**: :code:`84584600`, :code:`"359206419"`. common_track_id : int or str; keyword-only; optional Musixmatch common ID of the track. **Examples**: :code:`5920049`, :code:`"40728258"`. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. duration : int or str; keyword-only; optional Target Rich Sync lyrics 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 ------- lyrics : dict[str, Any] Musixmatch metadata for the track's Rich Sync lyrics. .. admonition:: Sample response :class: response dropdown .. code-block:: { "message": { "body": { "richsync": { "html_tracking_url": <str>, "lyrics_copyright": <str>, "pixel_tracking_url": <str>, "publisher_list": [], "restricted": <int>, "richssync_language": <str>, "richsync_avg_count": <int>, "richsync_body": <str>, "richsync_id": <int>, "richsync_language_description": <str>, "richsync_length": <int>, "script_tracking_url": <str>, "updated_time": <str>, "writer_list": [] } }, "header": { "available": <int>, "execute_time": <float>, "status_code": <int> } } } """ self._client._require_api_key("tracks.get_track_rich_sync_lyrics") params = {} if duration is not None: self._validate_numeric("duration", duration, int, 0) params["f_richsync_length"] = duration if max_duration_deviation is not None: self._validate_numeric( "max_duration_deviation", max_duration_deviation, int, 0 ) params["f_richsync_length_max_deviation"] = max_duration_deviation return self._get_track_resource( "track.richsync.get", track_id=track_id, common_track_id=common_track_id, isrc=isrc, params=params, )
[docs] @TTLCache.cached_method(ttl="static") def get_track_lyrics_snippet( self, *, track_id: int | str | None = None, common_track_id: int | str | None = None, isrc: str | None = None, ) -> dict[str, Any]: """ `Track > track.snippet.get <https://docs.musixmatch.com /lyrics-api/track/track-snippet-get>`_: Get Musixmatch catalog information for a snippet of a track's 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>`__ .. important:: At least one of :code:`track_id`, :code:`common_track_id`, or :code:`isrc` must be specified. Parameters ---------- track_id : int or str; keyword-only; optional Musixmatch ID of the track. **Examples**: :code:`84584600`, :code:`"359206419"`. common_track_id : int or str; keyword-only; optional Musixmatch common ID of the track. **Examples**: :code:`5920049`, :code:`"40728258"`. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. Returns ------- snippet : dict[str, Any] Musixmatch metadata for the snippet of the track's lyrics. .. admonition:: Sample response :class: response dropdown .. code-block:: { "message": { "body": { "snippet": { "html_tracking_url": <str>, "instrumental": <int>, "pixel_tracking_url": <str>, "region_restriction": { "allowed": <list[str]>, "blocked": [] }, "restricted": <int>, "script_tracking_url": <str>, "snippet_body": <str>, "snippet_id": <int>, "snippet_language": <str>, "updated_time": <str> } }, "header": { "execute_time": <float>, "status_code": <int> } } } """ return self._get_track_resource( "track.snippet.get", track_id=track_id, common_track_id=common_track_id, isrc=isrc, )
[docs] @TTLCache.cached_method(ttl="static") def get_track_lyrics_translation( self, language: str, *, track_id: int | str | None = None, common_track_id: int | str | None = None, isrc: str | None = None, min_translation_ratio: float | str | None = None, ) -> dict[str, Any]: """ `Track > track.lyrics.translation.get <https://docs.musixmatch.com/lyrics-api/track /track-lyrics-translation-get>`_: Get Musixmatch catalog information for a translation of a track's lyrics. .. admonition:: Subscription :class: entitlement .. tab-set:: .. tab-item:: Required Musixmatch Enterprise plan Access extended music metadata, advanced search, translations, song structure, and lyric analysis. `Learn more. <https://about.musixmatch.com /api-pricing>`__ .. important:: At least one of :code:`track_id`, :code:`common_track_id`, or :code:`isrc` must be specified. Parameters ---------- language : str ISO 639-1 language code for the desired translation language. **Example**: :code:`"it"`. track_id : int or str; keyword-only; optional Musixmatch ID of the track. **Examples**: :code:`84584600`, :code:`"359206419"`. common_track_id : int or str; keyword-only; optional Musixmatch common ID of the track. **Examples**: :code:`5920049`, :code:`"40728258"`. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. min_translation_ratio : float; keyword-only; optional Minimum translation completion ratio. **Valid range**: :code:`0.0` to :code:`1.0`. Returns ------- translation : dict[str, Any] Musixmatch metadata for the translation of the 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>, "lyrics_translated": { "html_tracking_url": <str>, "lyrics_body": <str>, "pixel_tracking_url": <str>, "restricted": <int>, "script_tracking_url": <str>, "selected_language": <str> }, "pixel_tracking_url": <str>, "region_restriction": { "allowed": <list[str]>, "blocked": [] }, "script_tracking_url": <str>, "updated_time": <str> } }, "header": { "execute_time": <float>, "status_code": <int> } } } """ self._client._require_api_key("tracks.get_track_lyrics_translation") params = {} if language is not None: self._validate_language_code(language) params["selected_language"] = language if min_translation_ratio is not None: self._validate_numeric( "min_translation_ratio", min_translation_ratio, float, 0.0, 1.0 ) params["min_completed"] = min_translation_ratio return self._get_track_resource( "track.lyrics.translation.get", track_id=track_id, common_track_id=common_track_id, isrc=isrc, params=params, )
[docs] @TTLCache.cached_method(ttl="static") def get_track_subtitles_translation( self, language: str, *, track_id: int | str | None = None, common_track_id: int | str | None = None, isrc: str | None = None, min_translation_ratio: float | None = None, duration: int | None = None, max_duration_deviation: int | None = None, ) -> dict[str, Any]: """ `Track > track.subtitle.translation.get <https://docs.musixmatch.com/lyrics-api/track /track-subtitle-translation-get>`_: Get Musixmatch catalog information for a translation of a track's subtitles. .. admonition:: Subscription :class: entitlement .. tab-set:: .. tab-item:: Required Musixmatch Enterprise plan Access extended music metadata, advanced search, translations, song structure, and lyric analysis. `Learn more. <https://about.musixmatch.com /api-pricing>`__ .. important:: At least one of :code:`track_id`, :code:`common_track_id`, or :code:`isrc` must be specified. Parameters ---------- language : str ISO 639-1 language code for the desired translation language. **Example**: :code:`"it"`. track_id : int or str; keyword-only; optional Musixmatch ID of the track. **Examples**: :code:`84584600`, :code:`"359206419"`. common_track_id : int or str; keyword-only; optional Musixmatch common ID of the track. **Examples**: :code:`5920049`, :code:`"40728258"`. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. min_translation_ratio : float; keyword-only; optional Minimum translation completion ratio. **Valid range**: :code:`0.0` to :code:`1.0`. 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 ------- translation : dict[str, Any] Musixmatch metadata for the translation of the track's subtitles. .. admonition:: Sample response :class: response dropdown .. code-block:: { "message": { "body": { "subtitle": { "lyrics_copyright": <str>, "pixel_tracking_url": <str>, "region_restriction": { "allowed": <list[str]>, "blocked": [] }, "script_tracking_url": <str>, "subtitle_body": <str>, "subtitle_id": <int>, "subtitle_language": <str>, "subtitle_language_description": <str>, "subtitle_length": <int>, "subtitle_translated": { "html_tracking_url": <str>, "pixel_tracking_url": <str>, "restricted": <int>, "script_tracking_url": <str>, "selected_language": <str>, "subtitle_body": <str>, }, "updated_time": <str> } }, "header": { "execute_time": <float>, "instrumental": <int>, "status_code": <int> } } } """ self._client._require_api_key("tracks.get_track_subtitles_translation") params = {} if language is not None: self._validate_language_code(language) params["selected_language"] = language if min_translation_ratio is not None: self._validate_numeric( "min_translation_ratio", min_translation_ratio, float, 0.0, 1.0 ) params["min_completed"] = min_translation_ratio 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._get_track_resource( "track.lyrics.translation.get", track_id=track_id, common_track_id=common_track_id, isrc=isrc, params=params, )
[docs] @TTLCache.cached_method(ttl="search") def search_tracks( self, query: str | None = None, *, artist_query: str | None = None, lyrics_query: str | None = None, track_query: str | None = None, track_artist_query: str | None = None, writer_query: str | None = None, artist_id: int | str | None = None, genre_id: int | str | None = None, language: str | None = None, has_lyrics: bool | None = None, released_after: str | datetime | None = None, released_before: str | datetime | None = None, artist_popularity_sort_order: str | None = None, track_popularity_sort_order: str | None = None, page: int | None = None, limit: int | None = None, ) -> dict[str, Any]: """ `Track > track.search <https://docs.musixmatch.com/lyrics-api /track/track-search>`_: Search for tracks in the Musixmatch catalog. .. 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 ---------- query : str; optional Search query matching any word in the artist name, track name, or lyrics. artist_query : str; keyword-only; optional Search query matching any word in the artist name. lyrics_query : str; keyword-only; optional Search query matching any word in the track's lyrics. track_query : str; keyword-only; optional Search query matching any word in the track name. track_artist_query : str; keyword-only; optional Search query matching any word in the track artist name. writer_query : str; keyword-only; optional Search query matching any word in the track writer name. artist_id : int or str; keyword-only; optional Musixmatch ID of the artist to filter results by. **Examples**: :code:`259675`, :code:`"24403590"`. genre_id : int or str; keyword-only; optional Musixmatch genre ID to filter results by. language : str; keyword-only; optional ISO 639-1 language code to filter results by lyrics availability. **Example**: :code:`"it"`. has_lyrics : bool; keyword-only; optional Whether to only include tracks that have lyrics. **API default**: :code:`False`. released_after : str or datetime.datetime; keyword-only; \ optional Only return tracks released after this date, in :code:`YYYYMMDD` format. released_before : str or datetime.datetime; keyword-only; \ optional Only return tracks released before this date, in :code:`YYYYMMDD` format. artist_popularity_sort_order : str; keyword-only; optional Sort order for artist popularity. **Valid values**: :code:`"asc"`, :code:`"desc"`. track_popularity_sort_order : str; keyword-only; optional Sort order for track popularity. **Valid values**: :code:`"asc"`, :code:`"desc"`. limit : int; keyword-only; optional Maximum number of tracks to return. **Valid range**: :code:`1` to :code:`100`. **API default**: :code:`10`. page : int; keyword-only; optional Page number. Use with `limit` to get the next page of tracks. **Minimum value**: :code:`1`. **API default**: :code:`1`. Returns ------- tracks : dict[str, Any] Page of Musixmatch metadata for the matching tracks. .. admonition:: Sample response :class: response dropdown .. code-block:: { "message": { "body": { "track_list": [ { "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": { "available": <int>, "execute_time": <float>, "status_code": <int> } } } """ params = {} if query is not None: params["q"] = self._prepare_string("query", query) if artist_query is not None: params["q_artist"] = self._prepare_string( "artist_query", artist_query ) if lyrics_query is not None: params["q_lyrics"] = self._prepare_string( "lyrics_query", lyrics_query ) if track_query is not None: params["q_track"] = self._prepare_string( "track_query", track_query ) if track_artist_query is not None: params["q_track_artist"] = self._prepare_string( "track_artist_query", track_artist_query ) if writer_query is not None: params["q_writer"] = self._prepare_string( "writer_query", writer_query ) if artist_id is not None: self._validate_numeric("artist_id", artist_id, int) params["f_artist_id"] = artist_id if genre_id is not None: self._validate_numeric("genre_id", genre_id, int) params["f_music_genre_id"] = genre_id if language is not None: self._validate_language_code(language) params["f_lyrics_language"] = language if has_lyrics is not None: self._validate_type("has_lyrics", has_lyrics, bool) params["f_has_lyrics"] = int(has_lyrics) if released_after is not None: params["f_first_release_date_min"] = self._prepare_datetime( released_after, "%Y%m%d" ) if released_before is not None: params["f_first_release_date_max"] = self._prepare_datetime( released_before, "%Y%m%d" ) if artist_popularity_sort_order is not None: self._validate_sort_order( artist_popularity_sort_order, sort_by="artist popularity" ) params["s_artist_rating"] = artist_popularity_sort_order if track_popularity_sort_order is not None: self._validate_sort_order( track_popularity_sort_order, sort_by="track popularity" ) params["s_track_rating"] = track_popularity_sort_order if limit is not None: self._validate_number("limit", limit, int, 1, 100) params["page_size"] = limit if page is not None: self._validate_number("page", page, int, 1) params["page"] = page return self._client._request( "GET", "track.search", params=params ).json()
[docs] @TTLCache.cached_method(ttl="static") def get_track_lyrics_analysis( self, *, track_id: int | str | None = None, common_track_id: int | str | None = None, isrc: str | None = None, ) -> dict[str, Any]: """ `Enterprise > track.lyricslens.get <https://docs.musixmatch.com /enterprise-integration/api-reference/track-lyricslens-get>`_: Get the Lyric Lens analysis of a track's lyrics. .. admonition:: Subscription :class: entitlement .. tab-set:: .. tab-item:: Required Musixmatch Enterprise plan Access extended music metadata, advanced search, translations, song structure, and lyric analysis. `Learn more. <https://about.musixmatch.com /api-pricing>`__ .. seealso:: `Musixmatch Lyrics API documentation <https://docs.musixmatch.com/enterprise-integration /lyric-lens>`_ – Lyric Lens introduction and metadata overview. Parameters ---------- track_id : int or str; keyword-only; optional Musixmatch ID of the track. **Examples**: :code:`84584600`, :code:`"359206419"`. common_track_id : int or str; keyword-only; optional Musixmatch common ID of the track. **Examples**: :code:`5920049`, :code:`"40728258"`. isrc : str; keyword-only; optional ISRC of the track. **Example**: :code:`"USUM70905526"`. Returns ------- analysis : dict[str, Any] Lyric Lens analysis of the track's lyrics. .. admonition:: Sample response :class: response dropdown .. code-block:: { "message": { "body": { "lens": { "entities": { "entity_list": [ { "categories": <list[str]>, "entity_name": <str>, "matches": [ { "end_char": <int>, "matched_text": <str>, "start_char": <int> } ], "model_metadata": { "description": <str>, "type": <str> }, "occurrencies": <int>, "wikidata": { "description": <str>, "id": <str>, "rank": <int>, "thumbnail": <str>, "types": <list[str]> }, "wikipedia": [ { "language": <str>, "url": <str> } ] } ] }, "language_detection": { "languages": [ { "is_romanized": <bool>, "language_iso_code_1": <str>, "language_iso_code_3": <str>, "language_name": <str>, "percentage": <int> } ] }, "meaning": { "description": <str>, "explanation": <str> }, "moderation": { "categories": [ { "category": <str>, "is_present": <bool>, "score": <float> } ], "description": <str>, "needs_moderation": <bool> }, "moods": { "description": <str>, "main_moods": <list[str]> }, "rating": { "audience":<str>, "description": <str>, "descriptor": <str>, }, "religion": { "description": <str>, "has_references": <bool> }, "themes": { "description": <str>, "main_themes": [ { "quotes": <list[str]>, "theme": <str> } ] } } }, "header": { "execute_time": <float>, "status_code": <int> } } } """ return self._get_track_resource( "track.lyricslens.get", track_id=track_id, common_track_id=common_track_id, isrc=isrc, )
[docs] @_copy_docstring(ChartsAPI.get_top_tracks) def get_top_tracks( self, chart_name: str | None = None, *, country_code: str | None = None, has_lyrics: bool | None = None, limit: int | None = None, page: int | None = None, ) -> dict[str, Any]: return self._client.charts.get_top_tracks( chart_name=chart_name, country_code=country_code, has_lyrics=has_lyrics, limit=limit, page=page, )
[docs] @_copy_docstring(MatcherAPI.match_track_lyrics) def match_track_lyrics( self, *, artist: str | None = None, track: str | None = None, isrc: str | None = None, ) -> dict[str, Any]: return self._client.matcher.match_track_lyrics( artist=artist, track=track, isrc=isrc )
[docs] @_copy_docstring(MatcherAPI.match_track) def match_track( self, *, artist: str | None = None, track: str | None = None, isrc: str | None = None, ) -> dict[str, Any]: return self._client.matcher.match_track( artist=artist, track=track, isrc=isrc )
[docs] @_copy_docstring(MatcherAPI.match_track_subtitles) 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]: return self._client.matcher.match_track_subtitles( artist=artist, track=track, isrc=isrc, duration=duration, max_duration_deviation=max_duration_deviation, )