def update_singles_playlists(**kwargs): # Don't want artist.singles_df to instantiate # a new spotify (sp) object for every artist df = dataframe() sp = utilities.get_user_sp() sdfs = [] artist_names = [] time_window = kwargs.get('time_window', 100) cutoff = datetime.today() - timedelta(days=time_window) n_artists = kwargs.get('n_artists', len(df.track_artist_id.unique())) artist_ids = list(df.track_artist_id.unique()[600:n_artists]) for i, artist_id in enumerate(artist_ids): sdf = artist.singles_df(artist_id=artist_id, sp=sp) print(f'artist {i+1} of {len(artist_ids)}') cutoff_date = '-'.join( [str(integer).zfill(2) for integer in cutoff.isocalendar()]) if sdf.empty == True: print(f'No singles from {artist_name} since {cutoff_date}') else: artist_name = sdf.artist_name.iloc[0] # Drop singles from before the cut off date, which # defaults to current day - offset bool_inds = [] for rd in sdf.release_date: try: bool_ind = datetime.fromisoformat(rd) >= cutoff except: bool_ind = False bool_inds.append(bool_ind) sdf = sdf.loc[bool_inds, :] sdfs.append(sdf) artist_names.append(artist_name) for single_album_id in sdf.album_id.values: try: album = sp.album(single_album_id) tracks = sp.album_tracks(single_album_id)['items'] except: # Might need to refresh an expired token sp = utilities.get_user_sp() album = sp.album(single_album_id) tracks = sp.album_tracks(single_album_id)['items'] rd = album['release_date'] for track in tracks: add_single_to_playlist(track, release_date=rd, suffix='auto')
def add_track_to_playlist(track, playlist_name, **kwargs): """ Look up the playlist id corresponding to playlist_name in the dataframe returned by DataBase().df and add track to that playlist. This function won't add track to playlist if track is already on that playlist. """ assert type(track) == dict, "track must be a dictionary" db = DataBase().df sp = kwargs.get('sp', utilities.get_user_sp()) # If the sp object was passed as a kwarg, we need to make # sure it isn't expired try: sp.user(constants.user_vars['username']) except: sp = utilities.get_user_sp() user = constants.user_vars['username'] # Need to update so that if playlist_name not in db.name.values, # create a new playlist with that track using playlist.new_playlist() # which will add the new playlist's information to playlist.database(). assert playlist_name in db.name.values, "playlist name not recorded in playlist.DataBase().df" # Check if the track is already on the playlist. If so, don't add it # and let the user know playlist_id = db.set_index('name').loc[playlist_name, 'id'] # Get the playlist spotify object so we can check whether the # track is already in the playlist pl = sp.user_playlist(user=user, playlist_id=playlist_id) track_items = pl['tracks']['items'] # This will only get the 100 earliest added tracks, so duplicates # could still be added. Trying to figure out a loop to reliably # make extension playlists everytime the orginial playlist gets # to 100 tracks existing_ids = [track_item['track']['id'] for track_item in track_items] if track['id'] in existing_ids: print(f"{track['name']} already in {playlist_name}") return else: track_ids = [track['id']] sp.user_playlist_add_tracks(user, playlist_id, tracks=track_ids, position=None) print( f"Added {track['name']} by {track['artists'][0]['name']} to {playlist_name}" )
def new_playlist(**kwargs): """ Create an empty playlist and add it to playlist.DataBase().df using playlist.DataBase().update_database(). If playlist_name is already in the database, warn the user, return None and don't make a new playlist. """ username = kwargs.get('username', constants.user_vars['username']) now = datetime.now() name = kwargs.get('name', f'Playlist {now.year}{now.month}{now.day}') public = kwargs.get('public', False) sp = utilities.get_user_sp() db = DataBase().df # The playlist will have been create at the top # of playlist organization, so update_datebase() # will find it and add it to the database if name in db.name.values: print(f'Playlist already exists with name: {name}') return None else: # user_playlist_create() returns the playlist dict # object new_pl = sp.user_playlist_create(username, name, public) DataBase().update_database() return new_pl
def make_playlists_df(): sp = utilities.get_user_sp() username = constants.user_vars['username'] playlists = get_playlists_from_db() playlist_dfs = [] keys = ['name', 'uri', 'id'] for i, playlist_dict in enumerate(playlists): print(f"Making playlist DataFrame {i+1} of {len(playlists)}", end='\r') columns_dict = {} for key in keys: columns_dict[key] = playlist_dict[key] if key == 'id': tracks_df = make_playlist_tracks_df( playlist_id=playlist_dict[key], sp=sp) # need to add functinality to get song release date and my add date # to make_playlist_tracks_df() for col in tracks_df.columns: columns_dict[f'track_{col}'] = tracks_df.loc[:, col] if tracks_df.empty == False: playlist_df = pd.DataFrame(columns_dict, index=range(0, len(tracks_df))) playlist_dfs.append(playlist_df) else: # No tracks found for this playlist pass playlists_df = pd.concat(playlist_dfs, ignore_index=True) playlists_df.to_json(constants.user_vars['playlist_df_path']) return playlists_df
def recently_played(**kwargs): """ Return the list of track_dicts for the 50 (limited by spotify) tracks for the user. Adds 'played_at' item to track_dict as a datetime object in central timezone """ sp = kwargs.get('sp', utilities.get_user_sp()) recently_played = sp.current_user_recently_played(limit=50)['items'] track_dicts = [] for item in recently_played: played_at = item['played_at'] played_at_dt = parse(played_at) played_at_central_dt = played_at_dt - timedelta(hours=5) # Get rid of timezone awareness because it # simplifies things downstream played_at_central_dt = played_at_central_dt.replace(tzinfo=None) track = item['track'] track['played_at'] = played_at_central_dt track_dicts.append(track) return track_dicts
def n_tracks(playlist_id, **kwargs): sp = kwargs.get('sp', utilities.get_user_sp()) user = constants.user_vars['username'] pl = sp.user_playlist(user=user, playlist_id=playlist_id) track_items = pl['tracks']['items'] existing_ids = [track_item['track']['id'] for track_item in track_items] n = len(existing_ids) return n
def get_playlists_from_db(): """ Return a list of playlist objects returned by sp.playlist(<playlist_id>) for each playlist_id in playlist.playlist.DataBase().df """ sp = utilities.get_user_sp() db = DataBase().df playlist_ids = db.id playlists = [sp.playlist(plid) for plid in playlist_ids] print(f"Found {len(playlists)} playlists") return playlists
def get_playlist(playlist_id='7Gr9kNeQNwapj3KYaAIhCu', **kwargs): """ Return playlist (a dictionary). playlist_id can be looked up by name in in the DataFrame returned by playlist.playlist.DataBase().df This function does instantiate a user spotipy object (utilities.get_user_sp()) """ sp = kwargs.get('sp', utilities.get_user_sp()) try: playlist = sp.playlist(playlist_id, fields="tracks,next") except Exception as e: playlist = None print( f"Couldn't find playlist with id: {playlist_id}\nSpotipy error:\n{e}" ) print(f'You can look up playlist ids in playlist.DataBase().df') return playlist
def make_database_df(self): sp = utilities.get_user_sp() username = constants.user_vars['username'] playlists = sp.user_playlists(username, limit=50) playlist_dfs = [] keys = ['name', 'uri', 'id'] for i, playlist_dict in enumerate(playlists['items']): columns_dict = {} for key in keys: columns_dict[key] = playlist_dict[key] playlist_df = pd.DataFrame(columns_dict, index=[i]) playlist_dfs.append(playlist_df) playlists_df = pd.concat(playlist_dfs) return playlists_df
def make_playlist_tracks_df(playlist_id='7Gr9kNeQNwapj3KYaAIhCu', allkeys=False, **kwargs): # need to add functinality to get song release date and my add date # to make_playlist_tracks_df() keys = kwargs.get( 'fields', ['name', 'uri', 'id', 'artist_name', 'artist_id', 'release_date']) tracks_list = get_playlist_tracks(playlist_id) columns_dict = {} track_dfs = [] for i, track_dict in enumerate(tracks_list): # Add some custom extracted fields. Sometimes track_dict['artist_name'] = track.artist_names(track_dict)[0] track_dict['artist_id'] = track.artist_ids(track_dict)[0] track_dict['release_date'] = track.release_date(track_dict) if allkeys: for key in track_dict.keys(): columns_dict[key] = track_dict[key] try: track_df = pd.DataFrame(columns_dict, index=[i]) track_dfs.append(track_df) except: pass else: # Only get keys from shorter list above for key in keys: columns_dict[key] = track_dict[key] track_df = pd.DataFrame(columns_dict, index=[i]) track_dfs.append(track_df) if len(track_dfs) > 0: tracks_df = pd.concat(track_dfs) else: sp = utilities.get_user_sp() current_pl = sp.playlist(playlist_id=playlist_id) name = current_pl['name'] print(f'No tracks on playlist: {name}\nid:{playlist_id}') tracks_df = None return tracks_df