Create a playlist of your followed artists’ latest music

In this example, you will:
  • Load information about your followed artists

  • Load the tracks released by these artists between two dates

  • Create a playlist containing these tracks

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)

Create the playlist

  1. Create a RemoteAPI object:

    Note

    This step uses the SpotifyLibrary, but any supported music streaming service can be used in generally the same way. Just modify the imports and classes as required.

    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>"
    )
    
  2. If you haven’t already, you will need to load and enrich data about your followed artists. You may use this helper function to help do so:

    from musify.libraries.remote.core.library import RemoteLibrary
    
    
    async def load_artists(library: RemoteLibrary) -> None:
        """Loads the artists followed by a given user in their given ``library`` and enriches them."""
        async with library:
            await library.load_saved_artists()
            await library.enrich_saved_artists(types=("album", "single"))
    
  3. Define helper function for filtering albums:

    from datetime import date
    
    from musify.libraries.remote.core.object import RemoteAlbum
    
    
    def match_date(alb: RemoteAlbum, start: date, end: date) -> bool:
        """Match ``start`` and ``end`` dates to the release date of the given ``alb``"""
        if alb.date:
            return start <= alb.date <= end
        if alb.month:
            return start.year <= alb.year <= end.year and start.month <= alb.month <= end.month
        if alb.year:
            return start.year <= alb.year <= end.year
        return False
    
  4. Define helper function for filtering the albums and loading the tracks for only these albums:

    from musify.libraries.remote.core.types import RemoteObjectType
    from musify.libraries.remote.core.object import RemoteAlbum
    
    
    async def get_albums(library: RemoteLibrary, start: date, end: date) -> list[RemoteAlbum]:
        """
        Get the albums that match the ``start`` and ``end`` date range from a given ``library``
        and get the tracks on those albums if needed.
        """
        albums = [album for artist in library.artists for album in artist.albums if match_date(album, start, end)]
        albums_need_extend = [album for album in albums if len(album.tracks) < album.track_total]
    
        if not albums_need_extend:
            return albums
    
        kind = RemoteObjectType.ALBUM
        key = api.collection_item_map[kind]
    
        async with library:
            await library.logger.get_asynchronous_iterator(
                (api.extend_items(album.response, kind=kind, key=key) for album in albums),
                desc="Getting album tracks",
                unit="albums"
            )
    
        for album in albums:
            album.refresh(skip_checks=False)
    
        return albums
    
  5. Define driver function for creating the playlist:

    from musify.libraries.remote.spotify.object import SpotifyPlaylist
    
    
    async def create_new_music_playlist(name: str, library: RemoteLibrary, start: date, end: date) -> None:
        """
        Create a playlist with the given ``name`` in the given ``library`` featuring
        new music by followed artists released between ``start`` date and ``end`` date.
        """
        await load_artists(library)
        albums = await get_albums(library, start, end)
    
        # log stats about the loaded artists
        library.log_artists()
    
        async with library:
            playlist = await SpotifyPlaylist.create(api=api, name=name)
    
            tracks = [track for album in sorted(albums, key=lambda x: x.date, reverse=True) for track in album]
            playlist.extend(tracks, allow_duplicates=False)
    
            # sync the object with Spotify and log the results
            results = await playlist.sync(kind="refresh", reload=False, dry_run=False)
            library.log_sync({name: results})
    
  1. Define the required parameters and run the operation:

    import asyncio
    from datetime import datetime, timedelta
    
    from musify.libraries.remote.spotify.library import SpotifyLibrary
    
    playlist_name = "New Music Playlist"
    library = SpotifyLibrary(api=api)
    end = datetime.now().date()
    start = end - timedelta(weeks=4)
    
    asyncio.run(create_new_music_playlist(playlist_name, library, start, end))