Source code for minim.api.spotify._web_api.player

from __future__ import annotations
from datetime import datetime
from typing import TYPE_CHECKING

from ..._shared import TTLCache
from ._shared import SpotifyResourceAPI

if TYPE_CHECKING:
    from typing import Any

    from ...._types import Collection


[docs] class PlayerAPI(SpotifyResourceAPI): """ Player API endpoints for the Spotify Web API. .. important:: This class is managed by :class:`~minim.api.spotify.SpotifyWebAPIClient` and should not be instantiated directly. """ _CONTEXT_TYPES = {"album", "artist", "playlist"} _REPEAT_MODES = {"track", "context", "off"} __slots__ = () def _control_playback( self, subresource: str, /, *, device_id: str | None = None, params: dict[str, Any] | None = None, payload: dict[str, Any] | None = None, ) -> None: """ Control playback. Parameters ---------- subresource : str; positional-only Subresource of the endpoint to call. device_id : str; keyword-only; optional Playback device ID. If not specified, the currently active device is the target. 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. payload : dict[str, Any]; keyword-only; optional JSON payload to include in the request. """ if params is None: params = {} if device_id is not None: self._validate_spotify_id(device_id) params["device_id"] = device_id self._client._request( "PUT", f"me/player/{subresource}", params=params, json=payload )
[docs] def get_playback_state( self, *, supported_item_types: str | Collection[str] | None = None, country_code: str | None = None, ) -> dict[str, Any]: """ `Player > Get Playback State <https://developer.spotify.com /documentation/web-api/reference /get-information-about-the-users-current-playback>`_: Get the current playback state. .. admonition:: Authorization scope and third-party application mode :class: entitlement .. tab-set:: .. tab-item:: Required :code:`user-read-playback-state` scope Read your currently playing content and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation/web-api /reference /get-information-about-the-users-current-playback>`__ .. tab-item:: Optional Extended quota mode before November 27, 2024 Access 30-second preview URLs. `Learn more. <https://developer.spotify.com/blog /2024-11-27-changes-to-the-web-api>`__ Parameters ---------- supported_item_types : str or Collection[str]; keyword-only; \ optional Item types supported by the client. .. note:: This parameter was introduced to allow existing clients to maintain their current behavior and may be deprecated in the future. **Valid values**: :code:`"track"`, :code:`"episode"`. **API default**: :code:`"track"`. **Examples**: :code:`"track"`, :code:`"track,episode"`, :code:`["track", "episode"]`. country_code : str; keyword-only; optional ISO 3166-1 alpha-2 country code. If provided, only content available in that market is returned. When a user access token accompanies the request, the country associated with the user account takes priority over this parameter. .. note:: If neither a country code is provided nor a country can be determined from the user account, the content is considered unavailable for the client. **Example**: :code:`"ES"`. Returns ------- state : dict[str, Any] Playback state and Spotify metadata for the currently playing item. .. admonition:: Sample response :class: response dropdown .. code-block:: { "actions": { "interrupting_playback": <bool>, "pausing": <bool>, "resuming": <bool>, "seeking": <bool>, "skipping_next": <bool>, "skipping_prev": <bool>, "toggling_repeat_context": <bool>, "toggling_repeat_track": <bool>, "toggling_shuffle": <bool>, "transferring_playback": <bool> }, "context": { "external_urls": { "spotify": <str> }, "href": <str>, "type": <str>, "uri": <str> }, "currently_playing_type": <str>, "device": { "id": <str>, "is_active": <bool>, "is_private_session": <bool>, "is_restricted": <bool>, "name": <str>, "supports_volume": <bool>, "type": <str>, "volume_percent": <int> }, "is_playing": <bool>, "item": { "album": { "album_type": <str>, "artists": [ { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "name": <str>, "type": "artist", "uri": <str> } ], "available_markets": <list[str]>, "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "images": [ { "height": <int>, "url": <str>, "width": <int> } ], "name": <str>, "release_date": <str>, "release_date_precision": <str>, "restrictions": { "reason": <str> }, "total_tracks": <int>, "type": "album", "uri": <str> }, "artists": [ { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "name": <str>, "type": "artist", "uri": <str> } ], "available_markets": <list[str]>, "disc_number": <int>, "duration_ms": <int>, "explicit": <bool>, "external_ids": { "ean": <str>, "isrc": <str>, "upc": <str> }, "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "is_local": <bool>, "is_playable": <bool>, "linked_from": { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "type": "track", "uri": <str> }, "name": <str>, "popularity": <int>, "preview_url": <str>, "restrictions": { "reason": <str> }, "track_number": <int>, "type": "track", "uri": <str> }, "progress_ms": <int>, "repeat_state": <str>, "shuffle_state": <bool>, "timestamp": <int> } """ self._client._require_scopes( "player.get_playback_state", "user-read-playback-state" ) params = {} if country_code is not None: self._client.markets._validate_market(country_code) params["market"] = country_code if supported_item_types is not None: params["additional_types"] = self._prepare_types( supported_item_types, allowed_types=self._AUDIO_TYPES, type_prefix="audio", ) return self._client._request("GET", "me/player", params=params).json()
[docs] def transfer_playback( self, device_id: str, /, *, play: bool | None = None ) -> None: """ `Player > Transfer Playback <https://developer.spotify.com /documentation/web-api/reference/transfer-a-users-playback>`_: Transfer playback to a new device. .. admonition:: Authorization scope and subscription :class: entitlement .. tab-set:: .. tab-item:: Required Spotify Premium subscription Access the :code:`PUT /me/player` endpoint. `Learn more. <https://www.spotify.com/us/premium>`__ :code:`user-modify-playback-state` scope Control playback on your Spotify clients and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation/web-api /reference/transfer-a-users-playback>`__ .. caution:: The order of execution is not guaranteed when this endpoint is used with other Player API endpoints in the Spotify Web API. Parameters ---------- device_id : str; positional-only ID of the target playback device. **Example**: :code:`"0d1841b0976bae2a3a310dd74c0f3df354899bc8"`. play : bool; keyword-only; optional Whether to start playback on the new device. If :code:`True`, playback begins immediately. If :code:`False`, the current playback state is preserved. """ self._client._require_spotify_premium("player.transfer_playback") self._client._require_scopes( "player.transfer_playback", "user-modify-playback-state" ) self._validate_spotify_id(device_id) payload = {"device_id": device_id} if play is not None: self._validate_type("play", play, bool) payload["play"] = play self._client._request("PUT", "me/player", json=payload)
[docs] @TTLCache.cached_method(ttl="playback") def get_devices( self, ) -> dict[str, list[dict[str, bool | int | str]]]: """ `Player > Get Available Devices <https://developer.spotify.com /documentation/web-api/reference /get-a-users-available-devices>`_: Get available Spotify Connect devices. .. admonition:: Authorization scope :class: entitlement .. tab-set:: .. tab-item:: Required :code:`user-read-playback-state` scope Read your currently playing content and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation/web-api /reference /get-information-about-the-users-current-playback>`__ Returns ------- devices : dict[str, list[dict[str, bool | int | str]]] Metadata of the available Spotify Connect devices. .. admonition:: Sample response :class: response dropdown .. code-block:: { "devices": [ { "id": <str>, "is_active": <bool>, "is_private_session": <bool>, "is_restricted": <bool>, "name": <str>, "type": <str>, "supports_volume": <bool>, "volume_percent": <int> } ] } """ self._client._require_scopes( "player.get_devices", "user-read-playback-state" ) return self._client._request("GET", "me/player/devices").json()
[docs] def get_currently_playing( self, *, supported_item_types: str | Collection[str] | None = None, country_code: str | None = None, ) -> dict[str, Any]: """ `Player > Get Currently Playing Track <https://developer.spotify.com/documentation/web-api/reference /get-the-users-currently-playing-track>`_: Get playback state and Spotify catalog information for the currently playing item. .. admonition:: Authorization scope and third-party application mode :class: entitlement .. tab-set:: .. tab-item:: Required :code:`user-read-currently-playing` scope Read your currently playing content. `Learn more. <https://developer.spotify.com/documentation/web-api /reference/get-the-users-currently-playing-track>`__ .. tab-item:: Optional Extended quota mode before November 27, 2024 Access 30-second preview URLs. `Learn more. <https://developer.spotify.com/blog /2024-11-27-changes-to-the-web-api>`__ Parameters ---------- supported_item_types : str or Collection[str]; keyword-only; optional Item types supported by the client. .. note:: This parameter was introduced to allow existing clients to maintain their current behavior and may be deprecated in the future. **Valid values**: :code:`"track"`, :code:`"episode"`. **API default**: :code:`"track"`. **Examples**: :code:`"track"`, :code:`"track,episode"`, :code:`["track", "episode"]`. country_code : str; keyword-only; optional ISO 3166-1 alpha-2 country code. If provided, only content available in that market is returned. When a user access token accompanies the request, the country associated with the user account takes priority over this parameter. .. note:: If neither a country code is provided nor a country can be determined from the user account, the content is considered unavailable for the client. **Example**: :code:`"ES"`. Returns ------- item : dict[str, Any] Playback state and Spotify metadata for the currently playing item. .. admonition:: Sample response :class: response dropdown .. code-block:: { "actions": { "interrupting_playback": <bool>, "pausing": <bool>, "resuming": <bool>, "seeking": <bool>, "skipping_next": <bool>, "skipping_prev": <bool>, "toggling_repeat_context": <bool>, "toggling_repeat_track": <bool>, "toggling_shuffle": <bool>, "transferring_playback": <bool> }, "context": { "external_urls": { "spotify": <str> }, "href": <str>, "type": <str>, "uri": <str> }, "currently_playing_type": <str>, "device": { "id": <str>, "is_active": <bool>, "is_private_session": <bool>, "is_restricted": <bool>, "name": <str>, "supports_volume": <bool>, "type": <str>, "volume_percent": <int> }, "is_playing": <bool>, "item": { "album": { "album_type": <str>, "artists": [ { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "name": <str>, "type": "artist", "uri": <str> } ], "available_markets": <list[str]>, "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "images": [ { "height": <int>, "url": <str>, "width": <int> } ], "name": <str>, "release_date": <str>, "release_date_precision": <str>, "restrictions": { "reason": <str> }, "total_tracks": <int>, "type": "album", "uri": <str> }, "artists": [ { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "name": <str>, "type": "artist", "uri": <str> } ], "available_markets": <list[str]>, "disc_number": <int>, "duration_ms": <int>, "explicit": <bool>, "external_ids": { "ean": <str>, "isrc": <str>, "upc": <str> }, "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "is_local": <bool>, "is_playable": <bool>, "linked_from": { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "type": "track", "uri": <str> }, "name": <str>, "popularity": <int>, "preview_url": <str>, "restrictions": { "reason": <str> }, "track_number": <int>, "type": "track", "uri": <str> }, "progress_ms": <int>, "repeat_state": <str>, "shuffle_state": <bool>, "timestamp": <int> } """ self._client._require_scopes( "player.get_currently_playing", "user-read-currently-playing" ) params = {} if country_code is not None: self._client.markets._validate_market(country_code) params["market"] = country_code if supported_item_types is not None: params["additional_types"] = self._prepare_types( supported_item_types, allowed_types=self._AUDIO_TYPES, type_prefix="audio", ) return self._client._request( "GET", "me/player/currently-playing", params=params ).json()
[docs] def start_playback( self, uris: str | Collection[str], /, *, device_id: str | None = None, offset: int | str | None = None, position_ms: int | None = None, ) -> None: """ `Player > Start/Resume Playback <https://developer.spotify.com /documentation/web-api/reference/start-a-users-playback>`_: Start or resume playback. .. admonition:: Authorization scope and subscription :class: entitlement .. tab-set:: .. tab-item:: Required Spotify Premium subscription Access the :code:`PUT /me/player/play` endpoint. `Learn more. <https://www.spotify.com/us/premium>`__ :code:`user-modify-playback-state` scope Control playback on your Spotify clients and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation/web-api /reference/transfer-a-users-playback>`__ Parameters ---------- uris : str or Collection[str]; positional-only Spotify URIs to play. For context playback, provide an album, artist, or playlist URI. For item playback, provide one or more track URIs. **Examples**: * :code:`"spotify:album:1Je1IMUlBXcx1Fz0WE7oPT"` * :code:`"spotify:track:4iV5W9uYEdYUVa79Axb7Rh"` * :code:`"spotify:track:4iV5W9uYEdYUVa79Axb7Rh,spotify:track:1301WleyT98MSxVHPZCA6M"` * :code:`["spotify:track:4iV5W9uYEdYUVa79Axb7Rh", "spotify:track:1301WleyT98MSxVHPZCA6M"]` device_id : str; keyword-only; optional ID of the target playback device. If not specified, the currently active device is the target. **Example**: :code:`"0d1841b0976bae2a3a310dd74c0f3df354899bc8"`. offset : int or str; keyword-only; optional Zero-based index or Spotify URI of the item within the context specified by `uris` at which playback should start. Only applicable when `uris` contains a context (album, artist, or playlist). **Examples**: * :code:`5` – Sixth item in the context. * :code:`spotify:track:1301WleyT98MSxVHPZCA6M` – Specific item in the context. position_ms : int; keyword-only; optional Playback start position within the first track, in milliseconds. If the specified position exceeds the length of the track, playback will start at the next track. **Minimum value**: :code:`0`. **Example**: :code:`25_000`. """ self._client._require_spotify_premium("player.start_playback") self._client._require_scopes( "player.start_playback", "user-modify-playback-state" ) payload = {} multiple = True if isinstance(uris, str): uris = uris.strip().split(",") if len(uris) == 1: uri = uris[0] try: self._validate_spotify_uri(uri, resource_types={"track"}) payload["context_uri"] = uri multiple = False except ValueError: payload["uris"] = self._prepare_spotify_uris( uri, limit=1, resource_types=self._CONTEXT_TYPES ) else: payload["uris"] = self._prepare_spotify_uris( uris, limit=100, resource_types=self._CONTEXT_TYPES ) if multiple and offset is not None: if isinstance(offset, int): self._validate_number("offset", offset, int, 0) payload["offset"] = {"position": offset} elif isinstance(offset, str): self._validate_spotify_uri(offset, resource_types={"track"}) payload["offset"] = {"uri": offset} else: raise ValueError( "`offset` must be either a zero-based index " "(int) or a Spotify track URI (str)." ) if position_ms is not None: self._validate_number("position_ms", position_ms, int, 0) payload["position_ms"] = position_ms self._control_playback("play", device_id=device_id, payload=payload)
[docs] def pause_playback(self, *, device_id: str | None = None) -> None: """ `Player > Pause Playback <https://developer.spotify.com /documentation/web-api/reference/pause-a-users-playback>`_: Pause playback. .. admonition:: Authorization scope and subscription :class: entitlement .. tab-set:: .. tab-item:: Required Spotify Premium subscription Access the :code:`PUT /me/player/pause` endpoint. `Learn more. <https://www.spotify.com/us/premium>`__ :code:`user-modify-playback-state` scope Control playback on your Spotify clients and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation/web-api /reference/transfer-a-users-playback>`__ .. caution:: The order of execution is not guaranteed when this endpoint is used with other Player API endpoints in the Spotify Web API. Parameters ---------- device_id : str; keyword-only; optional ID of the target playback device. If not specified, the currently active device is the target. **Example**: :code:`"0d1841b0976bae2a3a310dd74c0f3df354899bc8"`. """ self._client._require_spotify_premium("player.pause_playback") self._client._require_scopes( "player.pause_playback", "user-modify-playback-state" ) self._control_playback("pause", device_id=device_id)
[docs] def skip_to_next(self, *, device_id: str | None = None) -> None: """ `Player > Skip To Next <https://developer.spotify.com /documentation/web-api/reference /skip-users-playback-to-next-track>`_: Skip to the next item in the queue. .. admonition:: Authorization scope and subscription :class: entitlement .. tab-set:: .. tab-item:: Required Spotify Premium subscription Access the :code:`PUT /me/player/next` endpoint. `Learn more. <https://www.spotify.com/us/premium>`__ :code:`user-modify-playback-state` scope Control playback on your Spotify clients and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation/web-api /reference/transfer-a-users-playback>`__ .. caution:: The order of execution is not guaranteed when this endpoint is used with other Player API endpoints in the Spotify Web API. Parameters ---------- device_id : str; keyword-only; optional ID of the target playback device. If not specified, the currently active device is the target. **Example**: :code:`"0d1841b0976bae2a3a310dd74c0f3df354899bc8"`. """ self._client._require_spotify_premium("player.skip_to_next") self._client._require_scopes( "player.skip_to_next", "user-modify-playback-state" ) self._control_playback("next", device_id=device_id)
[docs] def skip_to_previous(self, *, device_id: str | None = None) -> None: """ `Player > Skip To Previous <https://developer.spotify.com /documentation/web-api/reference /skip-users-playback-to-previous-track>`_: Skip to the previous item in the queue. .. admonition:: Authorization scope and subscription :class: entitlement .. tab-set:: .. tab-item:: Required Spotify Premium subscription Access the :code:`PUT /me/player/previous` endpoint. `Learn more. <https://www.spotify.com/us/premium>`__ :code:`user-modify-playback-state` scope Control playback on your Spotify clients and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation/web-api /reference/transfer-a-users-playback>`__ .. caution:: The order of execution is not guaranteed when this endpoint is used with other Player API endpoints in the Spotify Web API. Parameters ---------- device_id : str; keyword-only; optional ID of the target playback device. If not specified, the currently active device is the target. **Example**: :code:`"0d1841b0976bae2a3a310dd74c0f3df354899bc8"`. """ self._client._require_spotify_premium("player.skip_to_previous") self._client._require_scopes( "player.skip_to_previous", "user-modify-playback-state" ) self._control_playback("previous", device_id=device_id)
[docs] def seek_to_position( self, position_ms: int, /, *, device_id: str | None = None ) -> None: """ `Player > Seek To Position <https://developer.spotify.com /documentation/web-api/reference /seek-to-position-in-currently-playing-track>`_: Seek to a specific position in the currently playing item. .. admonition:: Authorization scope and subscription :class: entitlement .. tab-set:: .. tab-item:: Required Spotify Premium subscription Access the :code:`PUT /me/player/seek` endpoint. `Learn more. <https://www.spotify.com/us/premium>`__ :code:`user-modify-playback-state` scope Control playback on your Spotify clients and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation/web-api /reference/transfer-a-users-playback>`__ .. caution:: The order of execution is not guaranteed when this endpoint is used with other Player API endpoints in the Spotify Web API. Parameters ---------- position_ms : int; positional-only Playback position to seek to, in milliseconds. If the specified position exceeds the length of the track, the next track will start playing. **Minimum value**: :code:`0`. **Example**: :code:`25_000`. device_id : str; keyword-only; optional ID of the target playback device. If not specified, the currently active device is the target. **Example**: :code:`"0d1841b0976bae2a3a310dd74c0f3df354899bc8"`. """ self._client._require_spotify_premium("player.seek_to_position") self._client._require_scopes( "player.seek_to_position", "user-modify-playback-state" ) self._validate_number("position_ms", position_ms, int, 0) self._control_playback( "seek", device_id=device_id, params={"position_ms": position_ms} )
[docs] def set_repeat( self, repeat_mode: str, /, *, device_id: str | None = None ) -> None: """ `Player > Set Repeat Mode <https://developer.spotify.com /documentation/web-api/reference /set-repeat-mode-on-users-playback>`_: Set playback repeat mode. .. admonition:: Authorization scope and subscription :class: entitlement .. tab-set:: .. tab-item:: Required Spotify Premium subscription Access the :code:`PUT /me/player/repeat` endpoint. `Learn more. <https://www.spotify.com/us/premium>`__ :code:`user-modify-playback-state` scope Control playback on your Spotify clients and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation/web-api /reference/transfer-a-users-playback>`__ .. caution:: The order of execution is not guaranteed when this endpoint is used with other Player API endpoints in the Spotify Web API. Parameters ---------- repeat_mode : str; positional-only Playback repeat mode. **Valid values**: * :code:`"track"` – Repeat the current track. * :code:`"context"` – Repeat tracks in the current context (album, artist, or playlist). * :code:`"off"` – Turn repeat off. device_id : str; keyword-only; optional ID of the target playback device. If not specified, the currently active device is the target. **Example**: :code:`"0d1841b0976bae2a3a310dd74c0f3df354899bc8"`. """ self._client._require_spotify_premium("player.set_repeat") self._client._require_scopes( "player.set_repeat", "user-modify-playback-state" ) if repeat_mode not in self._REPEAT_MODES: raise ValueError( f"Invalid repeat mode {repeat_mode!r}. Valid " f"values: {self._join_values(self._REPEAT_MODES)}." ) self._control_playback( "repeat", device_id=device_id, params={"state": repeat_mode} )
[docs] def set_volume( self, volume_percent: int, /, *, device_id: str | None = None ) -> None: """ `Player > Set Playback Volume <https://developer.spotify.com /documentation/web-api/reference /set-volume-for-users-playback>`_: Set playback volume. .. admonition:: Authorization scope and subscription :class: entitlement .. tab-set:: .. tab-item:: Required Spotify Premium subscription Access the :code:`PUT /me/player/volume` endpoint. `Learn more. <https://www.spotify.com/us/premium>`__ :code:`user-modify-playback-state` scope Control playback on your Spotify clients and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation/web-api /reference/transfer-a-users-playback>`__ .. caution:: The order of execution is not guaranteed when this endpoint is used with other Player API endpoints in the Spotify Web API. Parameters ---------- volume_percent : int; positional-only Playback volume as a percentage. **Valid range**: :code:`0` to :code:`100`. device_id : str; keyword-only; optional ID of the target playback device. If not specified, the currently active device is the target. **Example**: :code:`"0d1841b0976bae2a3a310dd74c0f3df354899bc8"`. """ self._client._require_spotify_premium("player.set_volume") self._client._require_scopes( "player.set_volume", "user-modify-playback-state" ) self._validate_number("volume_percent", volume_percent, int, 0, 100) self._control_playback( "volume", device_id=device_id, params={"volume_percent": volume_percent}, )
[docs] def set_shuffle( self, shuffle: bool, /, *, device_id: str | None = None ) -> None: """ `Player > Toggle Playback Shuffle <https://developer.spotify.com /documentation/web-api/reference /toggle-shuffle-for-users-playback>`_: Set playback shuffle state. .. admonition:: Authorization scope and subscription :class: entitlement .. tab-set:: .. tab-item:: Required Spotify Premium subscription Access the :code:`PUT /me/player/shuffle` endpoint. `Learn more. <https://www.spotify.com/us/premium>`__ :code:`user-modify-playback-state` scope Control playback on your Spotify clients and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation/web-api /reference/transfer-a-users-playback>`__ .. caution:: The order of execution is not guaranteed when this endpoint is used with other Player API endpoints in the Spotify Web API. Parameters ---------- shuffle : bool; positional-only Whether to shuffle playback. device_id : str; keyword-only; optional ID of the target playback device. If not specified, the currently active device is the target. **Example**: :code:`"0d1841b0976bae2a3a310dd74c0f3df354899bc8"`. """ self._client._require_spotify_premium("player.set_shuffle") self._client._require_scopes( "player.set_shuffle", "user-modify-playback-state" ) self._validate_type("shuffle", shuffle, bool) self._control_playback( "shuffle", device_id=device_id, params={"state": shuffle} )
[docs] @TTLCache.cached_method(ttl="playback") def get_recently_played( self, *, played_after: int | None = None, played_before: int | None = None, limit: int | None = None, ) -> dict[str, Any]: """ `Player > Get Recently Played Tracks <https://developer.spotify.com/documentation/web-api/reference /get-recently-played>`_: Get Spotify catalog information for items recently played by the current user. .. admonition:: Authorization scope and third-party application mode :class: entitlement .. tab-set:: .. tab-item:: Required :code:`user-read-recently-played` scope Access your recently played items. `Learn more. <https://developer.spotify.com/documentation/web-api /concepts/scopes#user-read-recently-played>`__ .. tab-item:: Optional Extended quota mode before November 27, 2024 Access 30-second preview URLs. `Learn more. <https://developer.spotify.com/blog /2024-11-27-changes-to-the-web-api>`__ .. important:: Exactly one of `played_after` or `played_before` must be provided. Parameters ---------- played_after : int or datetime.datetime; keyword-only; optional Only return items played after this Unix timestamp, in milliseconds. **Minimum value**: :code:`0`. played_before : int or datetime.datetime; keyword-only; optional Only return items played before this Unix timestamp, in milliseconds. **Minimum value**: :code:`0`. limit : int; keyword-only; optional Maximum number of items to return. **Valid range**: :code:`1` to :code:`50`. **API default**: :code:`20`. Returns ------- items : dict[str, Any] Page of Spotify metadata for the recently played items. .. admonition:: Sample response :class: response dropdown .. code-block:: { "cursors": { "after": <str>, "before": <str> }, "href": <str>, "items": [ { "context": { "external_urls": { "spotify": <str> }, "href": <str>, "type": <str>, "uri": <str> }, "played_at": <str>, "track": { "album": { "album_type": <str>, "artists": [ { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "name": <str>, "type": "artist", "uri": <str> } ], "available_markets": <list[str]>, "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "images": [ { "height": <int>, "url": <str>, "width": <int> } ], "name": <str>, "release_date": <str>, "release_date_precision": <str>, "restrictions": { "reason": <str> }, "total_tracks": <int>, "type": "album", "uri": <str> }, "artists": [ { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "name": <str>, "type": "artist", "uri": <str> } ], "available_markets": <list[str]>, "disc_number": <int>, "duration_ms": <int>, "explicit": <bool>, "external_ids": { "ean": <str>, "isrc": <str>, "upc": <str> }, "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "is_local": <bool>, "is_playable": <bool>, "linked_from": { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "type": "track", "uri": <str> }, "name": <str>, "popularity": <int>, "preview_url": <str>, "restrictions": { "reason": <str> }, "track_number": <int>, "type": "track", "uri": <str> } } ], "limit": <int>, "next": <str>, "total": <int> } """ self._client._require_scopes( "player.get_recently_played", "user-read-recently-played" ) params = {} if played_after is not None: if played_before is not None: raise ValueError( "Exactly one of `played_after` or `played_before` must be provided." ) if isinstance(played_after, datetime): params["after"] = int(1_000 * played_after.timestamp()) else: self._validate_number("played_after", played_after, int, 0) params["after"] = played_after elif played_before is not None: if isinstance(played_before, datetime): params["before"] = int(1_000 * played_before.timestamp()) else: self._validate_number("played_before", played_before, int, 0) params["before"] = played_before if limit is not None: self._validate_number("limit", limit, int, 1, 50) params["limit"] = limit return self._client._request( "GET", "me/player/recently-played", params=params ).json()
[docs] def get_queue(self) -> dict[str, Any]: """ `Player > Get the User's Queue <https://developer.spotify.com /documentation/web-api/reference/get-queue>`_: Get Spotify catalog information for the currently playing and queued items. .. admonition:: Authorization scope and third-party application mode :class: entitlement .. tab-set:: .. tab-item:: Required :code:`user-read-currently-playing` scope Read your currently playing content. `Learn more. <https://developer.spotify.com/documentation /web-api/reference /get-the-users-currently-playing-track>`__ :code:`user-read-playback-state` scope Read your currently playing content and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation /web-api/reference /get-information-about-the-users-current-playback>`__ .. tab-item:: Optional Extended quota mode before November 27, 2024 Access 30-second preview URLs. `Learn more. <https://developer.spotify.com/blog /2024-11-27-changes-to-the-web-api>`__ Returns ------- queue : dict[str, Any] Spotify metadata for the currently playing and queued items. .. admonition:: Sample response :class: response dropdown .. code-block:: { "currently_playing": { "album": { "album_type": <str>, "artists": [ { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "name": <str>, "type": "artist", "uri": <str> } ], "available_markets": <list[str]>, "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "images": [ { "height": <int>, "url": <str>, "width": <int> } ], "name": <str>, "release_date": <str>, "release_date_precision": <str>, "restrictions": { "reason": <str> }, "total_tracks": <int>, "type": "album", "uri": <str> }, "artists": [ { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "name": <str>, "type": "artist", "uri": <str> } ], "available_markets": <list[str]>, "disc_number": <int>, "duration_ms": <int>, "explicit": <bool>, "external_ids": { "ean": <str>, "isrc": <str>, "upc": <str> }, "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "is_local": <bool>, "is_playable": <bool>, "linked_from": { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "type": "track", "uri": <str> }, "name": <str>, "popularity": <int>, "preview_url": <str>, "restrictions": { "reason": <str> }, "track_number": <int>, "type": "track", "uri": <str> }, "queue": [ { "album": { "album_type": <str>, "artists": [ { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "name": <str>, "type": "artist", "uri": <str> } ], "available_markets": <list[str]>, "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "images": [ { "height": <int>, "url": <str>, "width": <int> } ], "name": <str>, "release_date": <str>, "release_date_precision": <str>, "restrictions": { "reason": <str> }, "total_tracks": <int>, "type": "album", "uri": <str> }, "artists": [ { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "name": <str>, "type": "artist", "uri": <str> } ], "available_markets": <list[str]>, "disc_number": <int>, "duration_ms": <int>, "explicit": <bool>, "external_ids": { "ean": <str>, "isrc": <str>, "upc": <str> }, "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "is_local": <bool>, "is_playable": <bool>, "linked_from": { "external_urls": { "spotify": <str> }, "href": <str>, "id": <str>, "type": "track", "uri": <str> }, "name": <str>, "popularity": <int>, "preview_url": <str>, "restrictions": { "reason": <str> }, "track_number": <int>, "type": "track", "uri": <str> } ] } """ self._client._require_scopes( "player.get_queue", {"user-read-currently-playing", "user-read-playback-state"}, ) return self._client._request("GET", "me/player/queue").json()
[docs] def add_to_queue( self, uri: str, /, *, device_id: str | None = None ) -> None: """ `Player > Add Item to Playback Queue <https://developer.spotify.com/documentation/web-api/reference /add-to-queue>`_: Add items to the playback queue. .. admonition:: Authorization scope and subscription :class: entitlement .. tab-set:: .. tab-item:: Required Spotify Premium subscription Access the :code:`PUT /me/player/queue` endpoint. `Learn more. <https://www.spotify.com/us/premium>`__ :code:`user-modify-playback-state` scope Control playback on your Spotify clients and Spotify Connect devices. `Learn more. <https://developer.spotify.com/documentation/web-api /reference/transfer-a-users-playback>`__ Parameters ---------- uri : str; positional-only Spotify URI of the track or episode to add to the queue. **Example**: :code:`spotify:track:4iV5W9uYEdYUVa79Axb7Rh`. device_id : str; keyword-only; optional ID of the target playback device. If not specified, the currently active device is the target. **Example**: :code:`"0d1841b0976bae2a3a310dd74c0f3df354899bc8"`. """ self._client._require_scopes( "player.add_to_queue", "user-modify-playback-state" ) self._client._require_spotify_premium("player.add_to_queue") self._validate_spotify_uri(uri, resource_types=self._AUDIO_TYPES) params = {"uri": uri} if device_id is not None: self._validate_spotify_id(device_id) params["device_id"] = device_id self._client._request("POST", "me/player/queue", params=params)