Skip to content

Instantly share code, notes, and snippets.

@smpanaro
Last active August 8, 2019 04:04
Show Gist options
  • Save smpanaro/a11ee68b7384279ae423e5345be2ed8f to your computer and use it in GitHub Desktop.
Save smpanaro/a11ee68b7384279ae423e5345be2ed8f to your computer and use it in GitHub Desktop.
A script to save/favorite the album for every track that is saved/favorited in Spotify.

Spotify's recent changes caused some albums (those where you saved/favorited songs but not the album) to be removed from your Library's album list.

Those songs are still in your Library's song list however. This script looks at all of your saved songs, finds the corresponding album, and saves it to your Library's album list if it is not already there.

Setup

  • You'll need to create a new client ID on Spotify's developer site, including setting up a redirect URI.
  • Fill in the credentials in populate_env.sh and run source populate_env.sh.
  • Install spotipy. pip install spotipy
  • Update username on line 7 of resave_albums.py to your spotify username.

Run It

Run at your own risk!

python resave_albums.py

#!/usr/bin/env bash
export SPOTIPY_CLIENT_ID='<your client id>'
export SPOTIPY_CLIENT_SECRET='<your client secret>'
export SPOTIPY_REDIRECT_URI='<your redirect URI. something like: http://localhost:8000/callback/>'
#!/usr/bin/env python
import spotipy
from spotipy import util
scope = 'user-library-read user-library-modify'
username = "<your-username-here>"
token = util.prompt_for_user_token(username, scope)
sp = spotipy.Spotify(auth=token)
class SimpleAlbum:
def __init__(self, name, uri, artist):
self.name = name
self.uri = uri
self.artist = artist
def __cmp__(self, other):
return cmp(self.name, other.name)
def __hash__(self):
return hash(self.uri)
def __repr__(self):
return u"<{} -- {} - {}>".format(self.name, self.artist, self.uri).encode('utf-8')
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
def favorite_albums(album_uris):
# Spotify allows at most 50 albums at once, but seems to have trouble with bigger numbers.
for albums_chunk in chunks(album_uris, 5):
print("saving {} albums: {}".format(len(albums_chunk), albums_chunk))
results = sp.current_user_saved_albums_add(albums=albums_chunk)
print("saved albums response: {}\n".format(results))
def get_albums_via_saved_tracks():
albums = set()
offset = 0
while True:
results = sp.current_user_saved_tracks(limit=50, offset=offset)
for item in results['items']:
track = item['track']
album = track['album']
album_uri = album['uri']
album_name = album['name']
artist = album['artists'][0]
artist_name = artist["name"]
albums.add(SimpleAlbum(album_name, album_uri, artist_name))
offset = results['offset'] + results['limit']
if offset >= results['total']:
break
return albums
def get_albums_via_saved_albums():
albums = set()
offset = 0
while True:
results = sp.current_user_saved_albums(limit=50, offset=offset)
for item in results['items']:
album = item['album']
album_uri = album['uri']
album_name = album['name']
artist = album['artists'][0]
artist_name = artist["name"]
albums.add(SimpleAlbum(album_name, album_uri, artist_name))
offset = results['offset'] + results['limit']
if offset >= results['total']:
break
return albums
albums_via_tracks = get_albums_via_saved_tracks()
#for a in sorted(albums_via_tracks):
# print a
already_saved_albums = get_albums_via_saved_albums()
#for a in sorted(already_saved_albums):
# print a
missing_albums = albums_via_tracks - already_saved_albums
#for a in sorted(missing_albums):
# print a
missing_album_uris = map(lambda album: album.uri, missing_albums)
favorite_albums(missing_album_uris)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment