Collections¶
The Spotify service implements the standard collection interfaces that are common across all services.
Library Collection¶
The SpotifyLibraryCollection represents the full spotify catalog from the perspective of an authenticated user.
from plistsync.services.spotify import SpotifyLibraryCollection
library = SpotifyLibraryCollection()
Track Lookup¶
The Spotify library collection supports lookup by global IDs, specifically by spotify_id and isrc. This allows for efficient retrieval of tracks using these identifiers.
# By spotify id
if track1 := library.find_by_global_ids({"spotify_id": "6fzwardfFs6sVfNA5R1ypt"}):
print(track1)
# By isrc
if track2 := library.find_by_global_ids({"isrc": "GBBZH9601601"}):
print(track2)
assert track1 == track2
Track[Origin Unknown > Valley of the Shadows, hash: -406311439666707691]
Track[Origin Unknown > Valley of the Shadows, hash: -406311439666707691]
If you need/want to lookup many tracks at once, consider using SpotifyLibraryCollection.find_many_by_global_ids for better performance.
Playlist Collection¶
The SpotifyPlaylistCollection represents a playlist of an authenticated user.
Retrieving playlists¶
You can retrieve all playlists of a user using the library’s SpotifyLibraryCollection.playlists property.
playlists = library.playlists
for playlist in playlists:
print(f"Playlist: {playlist.name} ({len(playlist)} tracks)")
Playlist: plistsync (3 tracks)
If you just want a specific playlist, you can use the library’s SpotifyLibraryCollection.get_playlist method to retrieve a playlist.
# By name
pl = library.get_playlist(
name="plistsync"
# id = "6tPAXg3zqkOgUPZPyD5Pph"
# uri = "spotify:playlist:6tPAXg3zqkOgUPZPyD5Pph"
# url = "https://open.spotify.com/playlist/6tPAXg3zqkOgUPZPyD5Pph"
)
if pl is not None:
print(f"Found playlist: {pl.name} ({len(pl.tracks)} tracks)")
else:
print("Playlist not found.")
Found playlist: plistsync (3 tracks)
Note
This method supports lookup by various identifiers, including name=, id=, url=, or uri=.
Lookup by name will return None if no matching playlist is found, while lookups by other identifiers will raise a ValueError if the playlist cannot be resolved.
Creating playlists¶
Use {py.class}SpotifyPlaylistCollection <plistsync.services.spotify.SpotifyPlaylistCollection> to model a playlist locally, then (optionally) create/associate it on Spotify.
from plistsync.services.spotify import SpotifyPlaylistCollection
pl = SpotifyPlaylistCollection(
library,
name="My New Playlist",
description="Created via plistsync",
)
assert pl.remote_associated == False
To remotly create the same playlist use the SpotifyPlaylistCollection.remote_create method.
pl.remote_create()
assert pl.remote_associated == True
Updating a playlist¶
For updating a playlist, you should use the playlist’s SpotifyPlaylistCollection.edit context manager. This ensures that all changes are properly saved back to Spotify when you exit the context. This also minifies changes and therefore reduces API calls.
# Updating a playlist description/name
with pl.remote_edit():
pl.description = "Updated Description"
pl.description
'Updated Description'
You can add tracks to a playlist using the same context manager, again this will add the tracks when you exit the context.
from plistsync.services.spotify import SpotifyPlaylistTrack
new_track_1 = library.find_by_global_ids({"isrc": "GBBZH9601601"})
new_track_2 = library.find_by_global_ids({"isrc": "GBXJH1000082"})
assert new_track_1 is not None
assert new_track_2 is not None
with pl.remote_edit():
# TODO: We should reevaluate the type hierarchy here.
# for now, we have to manually cast SpotifyTrack to SpotifyPlaylistTrack.
# this will become more convenient, eventually.
pl.tracks.append(SpotifyPlaylistTrack(new_track_1))
pl.tracks.append(SpotifyPlaylistTrack(new_track_2))
pl.tracks
[Track[Origin Unknown > Valley of the Shadows, hash: -406311439666707691],
Track[Break > If I Could, hash: 1472772941810935056]]
To reorder tracks in a playlist, you can change the order of the SpotifyPlaylistCollection.tracks list within the context manager.
with pl.remote_edit():
pl.tracks.insert(0, pl.tracks.pop())
Delete a playlist¶
You can also delete the playlist again.
pl.remote_delete()
Even tho the playlist is deleted from your users library it still does exist on spotify. This is a design choice with spotify itself as it is impossible to truly delete a playlist. See here for more information.
We opted to have the playlist still registered as remote_associated in this case.
assert pl.remote_associated
You can also still get the playlist via its id but lookup by name does not work anymore.
assert pl.id
assert library.get_playlist(id=pl.id)
assert not library.get_playlist(name=pl.name)