Skip to content

Spotify API related operations

Spotipy client endpoints.

add_to_queue(track)

Add a track to the user's queue.

Parameters:

Name Type Description Default
track TrackData

Track to add

required
Source code in chopin/client/endpoints.py
def add_to_queue(track: TrackData) -> None:
    """Add a track to the user's queue.

    Args:
        track: Track to add
    """
    _client.add_to_queue(track.uri)

add_tracks_to_playlist(playlist_id, track_ids)

Add tracks to a user playlist.

Parameters:

Name Type Description Default
playlist_id str

URI of the target playlist

required
track_ids list[str]

IDs for the tracks.

required
Source code in chopin/client/endpoints.py
def add_tracks_to_playlist(playlist_id: str, track_ids: list[str]) -> None:
    """Add tracks to a user playlist.

    Args:
        playlist_id: URI of the target playlist
        track_ids: IDs for the tracks.
    """
    paginated_tracks = [track_ids[i : i + 99] for i in range(0, len(track_ids), 99)]
    for page_tracks in paginated_tracks:
        _client.playlist_add_items(playlist_id, page_tracks)

create_user_playlist(user_id, name, description='Playlist created with Chopin')

Create a playlist in the user library.

Parameters:

Name Type Description Default
user_id str

ID of the user for which to add a playlist

required
name str

Name for the playlist

required
description str

Optional description for the playlist

'Playlist created with Chopin'

Returns:

Type Description
PlaylistData

Created playlist data.

Source code in chopin/client/endpoints.py
def create_user_playlist(user_id: str, name: str, description: str = "Playlist created with Chopin") -> PlaylistData:
    """Create a playlist in the user library.

    Args:
        user_id: ID of the user for which to add a playlist
        name: Name for the playlist
        description: Optional description for the playlist

    Returns:
        Created playlist data.
    """
    playlist = _client.user_playlist_create(user=user_id, name=name, description=description)
    return PlaylistData(name=playlist["name"], uri=playlist["uri"], id=playlist["id"])

get_album_tracks(album_id)

Get album tracks for the given album.

Parameters:

Name Type Description Default
album_id str

The id of the album.

required

Returns:

Type Description
list[TrackData]

A list of tracks from said album.

Source code in chopin/client/endpoints.py
def get_album_tracks(album_id: str) -> list[TrackData]:
    """Get album tracks for the given album.

    Args:
        album_id: The id of the album.

    Returns:
        A list of tracks from said album.
    """
    response = _client.album_tracks(album_id=album_id)["items"]
    return [TrackData(**track) for track in response]

get_artist_top_tracks(artist, max_tracks=20)

Get an artist top tracks.

Parameters:

Name Type Description Default
artist ArtistData

current artist.

required
max_tracks int

maximum number of tracks to find.

20

Returns:

Type Description
list[TrackData]

A list of track data.

Source code in chopin/client/endpoints.py
def get_artist_top_tracks(artist: ArtistData, max_tracks: int = 20) -> list[TrackData]:
    """Get an artist top tracks.

    Args:
        artist: current artist.
        max_tracks: maximum number of tracks to find.

    Returns:
        A list of track data.
    """
    response = _client.artist_top_tracks(artist_id=artist.id)
    tracks = response["tracks"]
    return [TrackData(**track) for track in random.sample(tracks, min(len(tracks), max_tracks))]

get_current_user() cached

Retrieve the current user.

Returns:

Type Description
UserData

User data.

Source code in chopin/client/endpoints.py
@lru_cache
def get_current_user() -> UserData:
    """Retrieve the current user.

    Returns:
        User data.
    """
    user = _client.current_user()
    return UserData(name=user["display_name"], id=user["id"], uri=user["uri"])

get_currently_playing()

Get the track being played.

Returns:

Type Description
TrackData | None

The track data of the track; or nothing if the user doesn't have an active listening session.

Source code in chopin/client/endpoints.py
def get_currently_playing() -> TrackData | None:
    """Get the track being played.

    Returns:
        The track data of the track; or nothing if the user doesn't have an active listening session.
    """
    response = _client.current_playback()
    if not response or response["currently_playing_type"] != "track":
        return None
    return TrackData.model_validate(response["item"])

get_likes()

Get user liked tracks.

Returns:

Type Description
list[TrackData]

The liked tracks.

Source code in chopin/client/endpoints.py
def get_likes() -> list[TrackData]:
    """Get user liked tracks.

    Returns:
        The liked tracks.
    """
    offset = 0
    tracks = []
    while True:
        response = _client.current_user_saved_tracks(limit=20, offset=offset)
        tracks.extend(response.get("items"))
        offset += 20
        if not response.get("next"):
            break
    return [TrackData(**track["track"]) for track in tracks]

get_named_playlist(name)

Find a user playlist based on its name.

Parameters:

Name Type Description Default
name str

A string identifying the playlist name

required

Returns:

Type Description
PlaylistData

The playlist data

Raises:

Type Description
ValueError

the playlist name was not found.

Source code in chopin/client/endpoints.py
def get_named_playlist(name: str) -> PlaylistData:
    """Find a user playlist based on its name.

    Args:
        name: A string identifying the playlist name

    Returns:
        The playlist data

    Raises:
        ValueError: the playlist `name` was not found.
    """
    playlists = get_user_playlists()
    names = [simplify_string(p.name) for p in playlists]
    try:
        index_ = names.index(simplify_string(name))
    except ValueError as exc:
        raise ValueError(f"Couldn't find playlist {name} in user playlists") from exc
    return playlists[index_]

get_playlist_tracks(playlist_id, release_date_range=None)

Get tracks of a given playlist.

Parameters:

Name Type Description Default
playlist_id str

The uri of the playlist.

required
release_date_range tuple[date, date] | None

A date range; tracks to retrieve must have been released in this range.

None

Returns:

Type Description
list[TrackData]

A list of track uuids.

Source code in chopin/client/endpoints.py
def get_playlist_tracks(
    playlist_id: str, release_date_range: tuple[datetime.date, datetime.date] | None = None
) -> list[TrackData]:
    """Get tracks of a given playlist.

    Args:
        playlist_id: The uri of the playlist.
        release_date_range: A date range; tracks to retrieve must have been released in this range.


    Returns:
        A list of track uuids.
    """
    offset: int = 0
    tracks: list[TrackData] = []
    response: dict[str, Any] = {"response": []}

    while response:
        response = _client.playlist_items(
            playlist_id,
            offset=offset,
            fields=constants.TRACK_FIELDS,
            additional_types=["track"],
        )
        offset += len(response["items"])

        response_tracks = _validate_tracks(response["items"])
        if release_date_range:
            response_tracks = [
                track
                for track in response_tracks
                if release_date_range[0].date() <= track.album.release_date <= release_date_range[1].date()
            ]
        tracks.extend(response_tracks)

        if len(response["items"]) == 0:
            break
    return tracks

get_queue()

Get the current user's listening queue.

Returns:

Type Description
list[TrackData]

The list of track data in the user's queue.

Raises:

Type Description
ValueError

if the user doesn't have an active (ie: doesn't have a track playing)

Note

API Call has to be custom made, waiting for its implementation in Spotipy.

Source code in chopin/client/endpoints.py
def get_queue() -> list[TrackData]:
    """Get the current user's listening queue.

    Returns:
        The list of track data in the user's queue.

    Raises:
        ValueError: if the user doesn't have an active (ie: doesn't have a track playing)

    Note:
        API Call has to be custom made, waiting for its implementation in Spotipy.
    """
    current_playback = _client.current_playback()
    if not current_playback or not current_playback.get("is_playing"):
        raise ValueError(
            "Spotify should be active on a device and the playback should be on for the get_queue endpoint to work."
        )

    response = _client.queue()
    return [TrackData(**track) for track in response.get("queue")]

get_top_artists(time_range, limit)

Get top artists for the current user.

Parameters:

Name Type Description Default
time_range Literal['short_term', 'medium_term', 'long_term']

The time scope of top artists

required
limit int

A maximum number of artists to fetch

required

Returns:

Type Description
list[ArtistData]

The user top artists for the given scope.

Source code in chopin/client/endpoints.py
def get_top_artists(time_range: Literal["short_term", "medium_term", "long_term"], limit: int) -> list[ArtistData]:
    """Get top artists for the current user.

    Args:
        time_range: The time scope of top artists
        limit: A maximum number of artists to fetch

    Returns:
        The user top artists for the given scope.
    """
    response = _client.current_user_top_artists(limit=limit, time_range=time_range)["items"]
    return [ArtistData(**artist) for artist in response]

get_top_tracks(time_range, limit)

Get top tracks for the current user.

Parameters:

Name Type Description Default
time_range Literal['short_term', 'medium_term', 'long_term']

The scope of the 'top' tracks.

required
limit int

A maximum number of tracks to fetch

required

!!! note Time range is as follow: - short_term: last month - medium_term: last 6 months - long_term: all time

Note

There is a Spotify limit for a user's top tracks. If limit is above, it will be reduced to the accepted number.

Returns:

Type Description
list[TrackData]

The user top tracks for the given time scope.

Source code in chopin/client/endpoints.py
def get_top_tracks(time_range: Literal["short_term", "medium_term", "long_term"], limit: int) -> list[TrackData]:
    """Get top tracks for the current user.

    Args:
        time_range: The scope of the 'top' tracks.
        limit: A maximum number of tracks to fetch

     !!! note
        Time range is as follow:
        - short_term: last month
        - medium_term: last 6 months
        - long_term: all time

    !!! note
        There is a Spotify limit for a user's top tracks.
        If `limit` is above, it will be reduced to the accepted number.

    Returns:
        The user top tracks for the given time scope.
    """
    if limit > constants.SPOTIFY_API_HISTORY_LIMIT:
        logger.warning(
            f"Asked for {limit} tracks for {time_range} best songs, "
            f"but Spotify API limits to {constants.SPOTIFY_API_HISTORY_LIMIT}"
        )
        limit = constants.SPOTIFY_API_HISTORY_LIMIT
    response = _client.current_user_top_tracks(limit=limit, time_range=time_range)["items"]
    return [TrackData(**track) for track in response]

get_user_playlists() cached

Retrieve the playlists of the current user.

Returns:

Type Description
list[PlaylistData]

A list of playlist data.

Source code in chopin/client/endpoints.py
@lru_cache
def get_user_playlists() -> list[PlaylistData]:
    """Retrieve the playlists of the current user.

    Returns:
        A list of playlist data.
    """
    playlists = _client.current_user_playlists().get("items", [])
    return [PlaylistData(name=simplify_string(p["name"]), uri=p["uri"], id=p["id"]) for p in playlists]

like_tracks(track_uris)

Add tracks to the user' library.

Parameters:

Name Type Description Default
track_uris list[str]

Tracks to save.

required
Source code in chopin/client/endpoints.py
def like_tracks(track_uris: list[str]) -> None:
    """Add tracks to the user' library.

    Args:
        track_uris: Tracks to save.
    """
    _client.current_user_saved_tracks_add(track_uris)

replace_tracks_in_playlist(playlist_id, track_ids)

Replace tracks in a given playlist.

Parameters:

Name Type Description Default
playlist_id str

URI of the target playlist. All of its tracks will be removed!

required
track_ids list[str]

New tracks to add in the playlist.

required
Source code in chopin/client/endpoints.py
def replace_tracks_in_playlist(playlist_id: str, track_ids: list[str]) -> None:
    """Replace tracks in a given playlist.

    Args:
        playlist_id: URI of the target playlist. All of its tracks will be removed!
        track_ids: New tracks to add in the playlist.
    """
    tracks_to_remove = get_playlist_tracks(playlist_id)
    tracks_to_remove_ids = [track.id for track in tracks_to_remove]
    paginated_tracks = [tracks_to_remove_ids[i : i + 99] for i in range(0, len(tracks_to_remove_ids), 99)]
    for page_tracks in paginated_tracks:
        _client.playlist_remove_all_occurrences_of_items(playlist_id, page_tracks)
    add_tracks_to_playlist(playlist_id, track_ids)

search_artist(artist_name)

Search an artist.

Parameters:

Name Type Description Default
artist_name str

Name of the artist

required

Returns:

Type Description
ArtistData | None

Artist data, if found.

Source code in chopin/client/endpoints.py
def search_artist(artist_name: str) -> ArtistData | None:
    """Search an artist.

    Args:
        artist_name: Name of the artist

    Returns:
        Artist data, if found.
    """
    response = _client.search(q=artist_name, limit=10, type="artist", market="fr")["artists"]
    items = response.get("items")
    matched_artists = [artist for artist in items if match_strings([artist["name"], artist_name])]
    if matched_artists:
        return ArtistData(**matched_artists[0])