예제 #1
0
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')
예제 #2
0
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}"
        )
예제 #3
0
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
예제 #4
0
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
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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
예제 #8
0
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
예제 #9
0
    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
예제 #10
0
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