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

  1. If you don’t already have one, create a Spotify for Developers account.

  2. 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.

  3. 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

  1. 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)
    
  2. 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")
    
  3. 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)
    
  4. Run the program:

    import asyncio
    
    asyncio.run(load_objects(api))
    asyncio.run(update_playlist("<YOUR PLAYLIST'S NAME>", api))  # case sensitive