Skip to content

Instantly share code, notes, and snippets.

@RitamDey
Last active August 17, 2023 04:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RitamDey/33d4b62238d2ab47945442f311a33ef4 to your computer and use it in GitHub Desktop.
Save RitamDey/33d4b62238d2ab47945442f311a33ef4 to your computer and use it in GitHub Desktop.
Automation script to sort liked tracks into years and create playlists based upon when they were added to liked playlist
import spotipy
from spotipy.oauth2 import SpotifyOAuth
from datetime import datetime, timezone
import logging
from logging.handlers import TimedRotatingFileHandler
from collections import defaultdict
def save_playlist_and_last_seen_data(spotify):
pass
def collect_and_sort_tracks(spotify):
songs_year_mapping = defaultdict(list) # Using defaultdict so as to not handle if a year key is absent
user_playlists = spotify.current_user_saved_tracks(limit=50, market="IN")
while user_playlists is not None and user_playlists["total"] > 0:
for track in user_playlists["items"]:
name = track["track"]["name"]
added_at = datetime.fromisoformat(track["added_at"])
year = str(added_at.year) # int is not hashable, thus convert to string
songs_year_mapping[year].append(track["track"]["uri"]) # Only the Spotify URI is needed for adding tracks to playlists
logging.info(f"Sorted {name} in {track.added_year()}")
# Get the next set of saved tracks from the liked playlist
user_playlists = spotify.next(user_playlists)
return songs_year_mapping
def search_playlists(spotify, years):
pass
def create_playlists(spotify, years):
# TODO: Handle if a playlist with the same exists. Spotify doesn't allow fetching playlist by name
# Get the current user's ID
user = spotify.me()
user_id = user["id"]
# Template to be used for playlist names and descriptions
name_template = "{} Discoveries"
description_temple = "Songs that I liked in {}"
logging.info(f"Creating playlits for user ID {user_id}.")
created_playlist_data = {}
for year in years:
playlist = name_template.format(year)
description = description_temple.format(year)
created_playlist = spotify.user_playlist_create(
user = user_id,
name = playlist,
description = description,
public = False
)
spotify_id = created_playlist["id"]
created_playlist_data[year] = spotify_id
logging.info(f"Created playlist {playlist} (Spotify ID {spotify_id})")
return created_playlist_data
def add_tracks_to_playlist(spotify, playlist_data, tracks_data, years):
# Spotify currently allows a max of 100 items to be added at one
track_chunk_size = 100
for year in years:
# Get the created playlist ID
playlist_id = playlist_data[year]
logging.info(f"Adding tracks for {year} playlist")
# Get all saved tracks from that year and have a count of the number of tracks added
tracks = tracks_data[year]
tracks_count = len(tracks)
# Chunk up the tracks into lists of 100 track chunks, this is done to reduce API calls to Spotify
# ref: https://www.programiz.com/python-programming/examples/list-chunks
tracks_chunked = [ tracks[i:i + track_chunk_size ] for i in range(0, tracks_count, track_chunk_size) ]
# Add each chunks to current pplaylist
for chunk in tracks_chunked:
spotify.playlist_add_items(playlist_id, chunk)
logging.info(f"Added {chunk} tracks to playlist {playlist_id}")
if __name__ == "__main__":
# Setup logging for the entire script
# log = TimedRotatingFileHandler(filename="execution.log", when="D", backupCount=10)
# log.setLevel(logging.INFO)
# log.setFormatter(logging.Formatter(
# fmt="%(asctime)s - %(filename)s - %(levelname)s: %(message)s",
# datefmt="%d/%m/%Y %I:%M:%S %p"
# ))
# logging.getLogger().addHandler(log)
logging.basicConfig(
format="%(asctime)s - %(filename)s - %(levelname)s: %(message)s",
datefmt="%d/%m/%Y %I:%M:%S %p",
level=logging.INFO
)
scope = "playlist-modify-private,user-library-modify,user-library-read,user-read-private,user-read-email"
auth = SpotifyOAuth(scope=scope)
spotify = spotipy.Spotify(auth_manager=auth)
logging.info("Authentication successful with Spotify APIs")
tokens = auth.get_cached_token()
if tokens:
auth.refresh_access_token(tokens['refresh_token'])
logging.info("Authentication successful with Spotify APIs")
sorted_tracks = collect_and_sort_tracks(spotify)
years = sorted_tracks.keys()
playlists = create_playlists(spotify, years)
add_tracks_to_playlist(spotify, playlists, sorted_tracks, years)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment