Load a Spotify library and objects
- In this example, you will:
Authorise access to the Spotify Web API
Load your Spotify library
Load some other Spotify objects
Add some tracks to a playlist
Set up logging
Set up logging to ensure you can see all info reported by the later operations.
Libraries log info about loaded objects to the custom STAT
level.
import logging
import sys
from musify.logger import STAT
logging.basicConfig(format="%(message)s", level=STAT, stream=sys.stdout)
Set up the Spotify API
If you don’t already have one, create a Spotify for Developers account.
If you don’t already have one, create an app. Select “Web API” when asked which APIs you are planning on using. To use this program, you will only need to take note of the client ID and client secret.
Create a
SpotifyAPI
object and authorise the program access to Spotify data as follows:Note
The scopes listed in this example will allow access to read your library data and write to your playlists. See Spotify Web API documentation for more information about scopes
from musify.libraries.remote.spotify.api import SpotifyAPI api = SpotifyAPI( client_id="<YOUR CLIENT ID>", client_secret="<YOUR CLIENT SECRET>", scope=[ "user-library-read", "user-follow-read", "playlist-read-collaborative", "playlist-read-private", "playlist-modify-public", "playlist-modify-private" ], # providing a `token_file_path` will save the generated token to your system # for quicker authorisations in future token_file_path="<PATH TO JSON TOKEN>" )
Load your library
Define helper functions for loading your library data:
from musify.libraries.remote.spotify.library import SpotifyLibrary async def load_library(library: SpotifyLibrary) -> None: """Load the objects for a given ``library``. Does not enrich the loaded data.""" # authorise the program to access your Spotify data in your web browser async with library: # if you have a very large library, this will take some time... await library.load() async def load_library_by_parts(library: SpotifyLibrary) -> None: """Load the objects for a given ``library`` by each of its distinct parts. Does not enrich the loaded data.""" # authorise the program to access your Spotify data in your web browser async with library: # load distinct sections of your library await library.load_playlists() await library.load_tracks() await library.load_saved_albums() await library.load_saved_artists() async def enrich_library(library: SpotifyLibrary) -> None: """Enrich the loaded objects in the given ``library``""" # authorise the program to access your Spotify data in your web browser async with library: # enrich the loaded objects; see each function's docstring for more info on arguments # each of these will take some time depending on the size of your library await library.enrich_tracks(features=True, analysis=False, albums=False, artists=False) await library.enrich_saved_albums() await library.enrich_saved_artists(tracks=True, types=("album", "single")) def log_library(library: SpotifyLibrary) -> None: """Log stats about the loaded ``library``""" library.log_playlists() library.log_tracks() library.log_albums() library.log_artists() # pretty print an overview of your library print(library)
Define helper functions for loading some Spotify objects using any of the supported identifiers:
from musify.libraries.remote.spotify.object import SpotifyTrack, SpotifyAlbum, SpotifyPlaylist, SpotifyArtist async def load_playlist(api: SpotifyAPI) -> SpotifyPlaylist: """Loads a playlist from the given ``api`` object""" # authorise the program to access your Spotify data in your web browser async with api as a: playlist = await SpotifyPlaylist.load("spotify:playlist:37i9dQZF1E4zg1xOOORiP1", api=a, extend_tracks=True) return playlist async def load_tracks(api: SpotifyAPI) -> list[SpotifyTrack]: """Loads some tracks from the given ``api`` object""" tracks = [] # authorise the program to access your Spotify data in your web browser async with api as a: # load by ID tracks.append(await SpotifyTrack.load("6fWoFduMpBem73DMLCOh1Z", api=a)) # load by URI tracks.append(await SpotifyTrack.load("spotify:track:4npv0xZO9fVLBmDS2XP9Bw", api=a)) # load by open/external style URL tracks.append(await SpotifyTrack.load("https://open.spotify.com/track/1TjVbzJUAuOvas1bL00TiH", api=a)) # load by API style URI tracks.append(await SpotifyTrack.load("https://api.spotify.com/v1/tracks/6pmSweeisgfxxsiLINILdJ", api=api)) return tracks async def load_album(api: SpotifyAPI) -> SpotifyAlbum: """Loads an album from the given ``api`` object""" # authorise the program to access your Spotify data in your web browser async with api as a: album = await SpotifyAlbum.load( "https://open.spotify.com/album/0rAWaAAMfzHzCbYESj4mfx", api=a, extend_tracks=True ) return album async def load_artist(api: SpotifyAPI) -> SpotifyArtist: """Loads an artist from the given ``api`` object""" # authorise the program to access your Spotify data in your web browser async with api as a: artist = await SpotifyArtist.load("1odSzdzUpm3ZEEb74GdyiS", api=a, extend_tracks=True) return artist async def load_objects(api: SpotifyAPI) -> None: """Loads multiple types of objects from the given ``api`` object and prints them""" playlist = await load_playlist(api) tracks = await load_tracks(api) album = await load_album(api) artist = await load_artist(api) # pretty print information about the loaded objects print(playlist, *tracks, album, artist, sep="\n")
Define helper function for adding some tracks to a playlist in your library, synchronising with Spotify, and logging the results:
async def update_playlist(name: str, library: SpotifyLibrary) -> None: """Update a playlist with the given ``name`` in the given ``library``""" tracks = await load_tracks(library.api) album = await load_album(library.api) await load_library(library) my_playlist = library.playlists[name] # add a track to the playlist my_playlist.append(tracks[0]) # add an album to the playlist using either of the following my_playlist.extend(album) my_playlist += album # sync the object with Spotify and log the results async with library: result = await my_playlist.sync(dry_run=False) library.log_sync(result)
Run the program:
import asyncio asyncio.run(load_objects(api)) asyncio.run(update_playlist("<YOUR PLAYLIST'S NAME>", api)) # case sensitive