コード例 #1
0
ファイル: playlist.py プロジェクト: johnpcooper/spotify_jpc
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
ファイル: playlist.py プロジェクト: johnpcooper/spotify_jpc
def add_track_to_playlist(track, playlist_name, **kwargs):
    """
    Look up the playlist id corresponding to playlist_name
    in the dataframe returned by database() 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()
    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()"
    # 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 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
コード例 #4
0
def get_current_track(**kwargs):
    """
    Return the currently playing track (a dictionary)
    """
    sp = get_user_sp()
    track = sp.current_user_playing_track()
    return track['item']
コード例 #5
0
ファイル: playlist.py プロジェクト: johnpcooper/spotify_jpc
def new_playlist(**kwargs):
    """
    Create an empty playlist and add it to playlist.database()
    using playlist.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()
    # 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 False
    else:
        # user_playlist_create() returns the playlist dict
        # object
        new_pl = sp.user_playlist_create(username, name, public)
        update_database()
        return True
コード例 #6
0
ファイル: playlist.py プロジェクト: johnpcooper/spotify_jpc
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]

        playlist_df = pd.DataFrame(columns_dict)
        playlist_dfs.append(playlist_df)

    playlists_df = pd.concat(playlist_dfs)
    playlists_df.to_csv(constants.user_vars['playlist_df_path'], index=False)

    return playlists_df
コード例 #7
0
ファイル: playlist.py プロジェクト: johnpcooper/spotify_jpc
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
コード例 #8
0
def add_clipboard_to_queue():
    """
    Search spotify for the string on the clipboard
    and add the first track result to queue
    """
    sp = get_user_sp()
    track = get_clipboard_uri()
    clipboard_uri = get_clipboard_uri()
    sp.add_to_queue(clipboard_uri)
    print(f"Added song with uri '{clipboard_uri}' to queue")
コード例 #9
0
def seek_for(increment_s=30):
    """
    Seek the currently playing track to current track
    progress in ms + 15 seconds (s)
    """
    increment_ms = increment_s * 1000
    sp = get_user_sp()
    current_track = sp.current_playback()
    current_prog_ms = current_track['progress_ms']
    sp.seek_track(current_prog_ms + increment_ms)
コード例 #10
0
def seek_rev(increment_s=15):
    """
    Seek the currently playing track to current track
    progress in ms - 30 seconds (s)
    """
    increment_ms = increment_s * 1000
    sp = get_user_sp()
    current_track = sp.current_playback()
    current_prog_ms = current_track['progress_ms']
    target_ms = current_prog_ms - increment_ms
    sp.seek_track(target_ms)
コード例 #11
0
def pseudoskip(fraction=0.001):
    """
    Navigate to the very last 0.1 % of currently
    playing track. If you do this instead of 
    skipping the track, it makes it into recently
    played.
    """
    sp = get_user_sp()
    current_track = sp.current_playback()
    duration_ms = current_track['item']['duration_ms']
    target_ms = duration_ms - round(duration_ms * fraction)
    sp.seek_track(target_ms)
コード例 #12
0
ファイル: playlist.py プロジェクト: johnpcooper/spotify_jpc
def get_playlists_from_db():
    """
    Return a list of playlist objects returned by sp.playlist(<playlist_id>)
    for each playlist_id in playlist.database()
    """
    sp = utilities.get_user_sp()
    db = database()
    playlist_ids = db.id
    playlists = [sp.playlist(plid) for plid in playlist_ids]
    print(f"Found {len(playlists)} playlists")

    return playlists
コード例 #13
0
def play_clipboard(**kwargs):
    """
    Search spotify for whatever's on the clipboard and
    play the first resulting track
    """
    sp = kwargs.get('sp', get_user_sp())
    track_uri = get_clipboard_uri()

    if track_uri:
        sp.start_playback(uris=[track_uri])
        print(f"Playing track")
    else:
        print("Couldn't find a track with this clipboard query")
コード例 #14
0
ファイル: playlist.py プロジェクト: johnpcooper/spotify_jpc
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.database()

    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()')

    return playlist
コード例 #15
0
ファイル: playlist.py プロジェクト: johnpcooper/spotify_jpc
def make_playlists_db():

    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
コード例 #16
0
ファイル: artist.py プロジェクト: johnpcooper/spotify_jpc
def singles_df(**kwargs):
    """
    Return a dataframe with a row for each of the last 20 (limited
    by spotify api) singles released by the artist_name or artist_id
    passed to singles_df. 

    This function uses artits.drop_clean_and_dup_tracks() to remove
    duplicated and clean versions of singles albums

    Should be tested by passing kwarg artist_name = nonsense ('asdlfkj'), 
    artist with no singles ("Infinity Crush") which will return either an 
    empty dataframe or None. Then artist name that's not in playlist.dataframe(),
    and finally real artist who is in the archive ("TOPS").

    Right now all of these situations are handled in artist.all_artists_singles_df()
    which compiles all singles albums from all artists found in playlist.dataframe()
    """

    # Get objects from spotify_jpc
    pldf = playlist.dataframe()
    pldb = playlist.database()
    sp = kwargs.get('sp', utilities.get_user_sp())
    # Parse keyword args
    artist_name = kwargs.get('artist_name', None)
    artist_id = kwargs.get('artist_id', None)

    if artist_name != None:

        if artist_name not in pldf.track_artist_name.values:
            print(
                "Must pass an artist name that exists in playlist.dataframe().track_artist_name"
            )
            return None
        else:
            pass

        artist_slice = pldf.set_index('track_artist_name',
                                      drop=False).loc[artist_name, :]
        try:
            # Works if there are multiple appearances of this artist
            # across user playlists
            artist_id = artist_slice.track_artist_id.unique()[0]
        except:
            # Works if there's only one appearance of this artst
            # across user playlists
            artist_id = artist_slice.track_artist_id
    else:
        artist_id = kwargs.get('artist_id', pldf.track_artist_id[0])
        artist_slice = pldf.set_index('track_artist_id',
                                      drop=False).loc[artist_id, :]
        artist_name = artist_slice.track_artist_name[0]
    try:
        albums = sp.artist_albums(artist_id, album_type='single')['items']
    except:
        print(f"No singles found for artist {artist_name}")
        return None
    # We need to scan each album for the explicit version
    # Since album objects are not tagged with the 'explicit'
    # key, we have to look through each track in each album
    # to find whether the album was explicit
    df = pd.DataFrame()
    for i, album in enumerate(albums):
        album_title = album['name']
        album_id = album['id']
        album_uri = album['uri']
        albums_tracks = sp.album_tracks(album_id, limit=50)['items']
        explicit_tracks = False
        release_date = album['release_date']
        for track in albums_tracks:
            if track['explicit'] == True:
                explicit_tracks = True

        df.loc[i, 'artist_name'] = artist_name
        df.loc[i, 'artist_id'] = artist_id
        df.loc[i, 'album_title'] = album_title
        df.loc[i, 'album_id'] = album_id
        df.loc[i, 'explicit_tracks'] = explicit_tracks
        df.loc[i, 'release_date'] = release_date
        df.loc[i, 'album_uri'] = album_uri

    print(f'Compiled singles DataFrame for {artist_name}')
    singles_df = drop_clean_and_dup_tracks(df)

    return singles_df