Exemplo n.º 1
0
def import_playlist(user_id, playlist_id, force=False):
    """Imports a single playlist from spotify, optionally regardless if it has been changed or not."""
    if playlist_id is None and user_id is None:
        click.echo("Please specify either a user-id, a playlist-id, or both.")
        return -1

    start = time.time()

    # if no user specified, find one that follows this playlist
    if user_id is None:
        user_id = Playlist.get_followers(playlist_id)[0]

    user = User.load(user_id)
    t, al, ar = Playlist.import_user_playlist(user, playlist_id, force)
    mysql.connection.commit()
    elapsed = time.time() - start
    click.echo(
        '--------------------------------------------------------------------------------'
    )
    click.echo('done. Elapsed time: %s' % elapsed)
    click.echo()
    click.echo('New Tracks:     %s' % t)
    click.echo('New Albums:     %s' % al)
    click.echo('New Artists:    %s' % ar)
    click.echo(
        '--------------------------------------------------------------------------------'
    )
Exemplo n.º 2
0
def authorized():
    if 'error' in request.args:
        error = request.args.get('error')
        app.logger.error('Error response from authorize: %s', error)
        return render_template('error.html', error=error)

    auth_code = request.args.get('code')
    state = unquote(request.args.get('state'))
    app.logger.debug('authorized state: %s', state)

    # TODO: verify state matches

    authorize_callback_url = request.url_root + 'authorized'
    status, token = get_auth_token(auth_code, authorize_callback_url)
    if status != 200:
        app.logger.error('Failed to get auth_token. Status=%s, response = %s' %
                         (status, token))
        return render_template('error.html', error=token)

    # TODO: if user is already in our database, look for changes
    status, spotify_user = get_user(token['access_token'])
    if status != 200:
        app.logger.error('Failed to get user. Status=%s, response = %s' %
                         (status, spotify_user))
        return render_template('error.html', error=spotify_user)

    user = User.load(spotify_user['id'])
    if not user:
        app.logger.info('Creating new user record for user id %s' %
                        spotify_user['id'])
        user = User.from_json(spotify_user, token)
        user.status = 'New'
    else:
        user.access_token = token['access_token']
        user.token_expiration = datetime.utcnow() + timedelta(
            seconds=token['expires_in'])
        user.refresh_token = token['refresh_token']

    user.save()
    mysql.connection.commit()

    user_url = '/user/%s/playlists' % user.id
    session['user_id'] = user.id
    session.modified = True
    app.logger.info('redirecting to %s with session set to user_id %s' %
                    (user_url, session['user_id']))
    return redirect(user_url)
Exemplo n.º 3
0
def full_refresh(user_id):
    if 'user_id' not in session: abort(401)
    if session['user_id'] != user_id: abort(403)
    user = User.load(user_id)
    refresh_result = Playlist.import_user_playlists(user)
    mysql.connection.commit()
    playlists = PlaylistSummaryView.for_user(user)
    return jsonify([p.__dict__ for p in playlists])
Exemplo n.º 4
0
def refresh(user_id):
    # Adding this light-weight "refresh" so I can test without waiting 10 minutes to reload my playlists
    if 'user_id' not in session: abort(401)
    if session['user_id'] != user_id: abort(403)
    user = User.load(user_id)
    mysql.connection.commit()
    playlists = PlaylistSummaryView.for_user(user)
    return jsonify([p.__dict__ for p in playlists])
Exemplo n.º 5
0
def refresh_all_tracks(user_id):
    user = User.load(user_id)
    cursor = mysql.connection.cursor()
    cursor.execute('select id from Track')
    spotify_tracks = spotify.get_tracks(user, [row[0] for row in cursor])
    for track in [Track.from_json(js) for js in spotify_tracks]:
        track.save()

    mysql.connection.commit()
Exemplo n.º 6
0
def user_save(user_id):
    if 'user_id' not in session: abort(401)
    if session['user_id'] != user_id: abort(403)
    user = User.load(user_id)
    user.name = request.json['displayName']
    user.save()
    mysql.connection.commit()
    return jsonify(
        dict(id=user.id, email=user.email, name=user.name, joined=user.joined))
Exemplo n.º 7
0
def admin_import_user(user_id):
    if 'user_id' not in session: abort(403)
    user = User.load(session['user_id'])
    if not user.is_admin: abort(403)

    url = 'https://clef2.scm.azurewebsites.net/api/triggeredwebjobs/import-user-playlists/run?arguments=%s' % user_id
    target_user = User.load(user_id)
    target_user.status = 'Importing'
    target_user.save()

    app.logger.info('staring import for user_id %s' % user_id)
    resp = requests.post(url, auth=webjobs_auth())
    if resp.status_code != 202: abort(resp.status_code)
    location = resp.headers['Location']
    url = urlparse(location)
    job_id = url.path.split('/')[-1]
    app.logger.info('import for user_id %s -> job_id %s' % (user_id, job_id))
    return jsonify(dict(status='started', jobId=job_id)), resp.status_code
Exemplo n.º 8
0
def admin_playlists():
    if 'user_id' not in session: abort(403)
    user = User.load(session['user_id'])
    if not user.is_admin: abort(403)

    offset = request.args.get('offset')
    limit = request.args.get('limit')
    return jsonpickle.encode(AdminPlaylistSummaryView(offset, limit),
                             unpicklable=False)
Exemplo n.º 9
0
def get_spotify_playlist(user_id, playlist_id, owner_id, fields):
    """Get a Spotify playlist by id."""
    user = User.load(user_id)
    playlist = spotify.get_playlist(user,
                                    playlist_id,
                                    owner=owner_id,
                                    fields=fields)
    mysql.connection.commit()  # in case the user's token was refreshed
    click.echo('Result:')
    click.echo(json.dumps(playlist, indent=2, sort_keys=True))
Exemplo n.º 10
0
def admin_import_job_results(job_id):
    if 'user_id' not in session: abort(403)
    user = User.load(session['user_id'])
    if not user.is_admin: abort(403)

    url = 'https://clef2.scm.azurewebsites.net/vfs/data/jobs/triggered/import-user-playlists/%s/output_log.txt' % job_id
    resp = requests.get(url, auth=webjobs_auth())
    return resp.content, resp.status_code, {
        'Content-Type': 'text/plain; charset=utf-8'
    }
Exemplo n.º 11
0
def get_spotify_tracks(user_id, track_ids):
    """Get spotify tracks by id."""
    user = User.load(user_id)
    count = 0
    for track in spotify.get_tracks(user, track_ids):
        click.echo(json.dumps(track, indent=2, sort_keys=True))
        click.echo()
        count += 1

    mysql.connection.commit()  # in case the user's token was refreshed
    click.echo('done. Total %s tracks' % count)
Exemplo n.º 12
0
def get_spotify_user_playlists(user_id):
    """Get all Spotify playlists for a user."""
    user = User.load(user_id)
    count = 0
    for playlist in spotify.get_user_playlists(user):
        click.echo(json.dumps(playlist, indent=2, sort_keys=True))
        click.echo(',')
        count += 1

    mysql.connection.commit()  # in case user token changed
    click.echo('done. Total %s playlists' % count)
Exemplo n.º 13
0
def get_spotify_artists(user_id, artist_ids):
    """Get Spotify artists by id."""
    user = User.load(user_id)
    count = 0
    for artist in spotify.get_artists(user, artist_ids):
        click.echo(json.dumps(artist, indent=2, sort_keys=True))
        click.echo()
        count += 1

    mysql.connection.commit()  # in case the user's token was refreshed
    click.echo('done. Total %s artists' % count)
Exemplo n.º 14
0
def update_stale_playlists(limit):
    start = time.time()
    cur = mysql.connection.cursor()

    # For each stale or new playlist, get it's id and one user id we can use to retrieve it
    cur.execute(
        """
select   p.id, min(pf.user_id)
from     Playlist p
         inner join PlaylistFollow pf on p.id = pf.playlist_id
where    p.status in ('New', 'Stale')
group by p.id
limit    %s;
    """, (limit, ))

    updated = set()
    users = dict()
    artist_cache, track_cache, album_cache = dict(), dict(), dict()
    new_tracks = 0
    new_albums = 0
    new_artists = 0
    for pid, uid in cur:
        if uid not in users: users[uid] = User.load(uid)
        nt, nal, nar = Playlist.import_user_playlist(users[uid],
                                                     pid,
                                                     force_reimport=True,
                                                     album_cache=album_cache,
                                                     track_cache=track_cache,
                                                     artist_cache=artist_cache)
        mysql.connection.commit()
        updated.add(pid)
        new_tracks = new_tracks + nt
        new_albums = new_albums + nal
        new_artists = new_artists + nar

    elapsed = time.time() - start
    click.echo(
        '--------------------------------------------------------------------------------'
    )
    click.echo('done. Elapsed time: %s' % elapsed)
    click.echo()
    click.echo('%s' % updated)
    click.echo()
    click.echo('Playlists Updated:     %s' % len(updated))
    click.echo('New Tracks Added:      %s' % new_tracks)
    click.echo('New Albums Added:      %s' % new_albums)
    click.echo('New Artists Added:     %s' % new_artists)
    click.echo('Total Tracks Loaded:   %s' % len(track_cache))
    click.echo('Total Albums Loaded:   %s' % len(album_cache))
    click.echo('Total Artists Loaded:  %s' % len(artist_cache))
    click.echo(
        '--------------------------------------------------------------------------------'
    )
Exemplo n.º 15
0
def user_playlist_recommend(user_id, playlist_id):
    if 'user_id' not in session: abort(401)
    if session['user_id'] != user_id: abort(403)
    user = User.load(session['user_id'])
    PlaylistDetailsView.get(user_id, playlist_id)

    # first cut, just pick a random song from the playlist and see where it takes us
    user_average_vector = user.average_attributes()
    tracks = Track.for_playlist_id(playlist_id)
    track = random.choice(tracks)
    recs = clef.clustering.recommend(user, track.id, user_average_vector)
    return jsonpickle.encode(recs, unpicklable=False)
Exemplo n.º 16
0
def get_spotify_audio_features(user_id, track_ids):
    """Get Spotify's audio features for a track.
    See: https://beta.developer.spotify.com/documentation/web-api/reference/tracks/get-audio-features/"""
    user = User.load(user_id)
    count = 0
    for features in spotify.get_audio_features(user, track_ids):
        click.echo(json.dumps(features, indent=2, sort_keys=True))
        click.echo()
        count += 1

    mysql.connection.commit()  # in case the user's token was refreshed
    click.echo('done. Total %s tracks' % count)
Exemplo n.º 17
0
def refresh_all_albums(user_id, album_ids=None, limit=1000):
    user = User.load(user_id)
    if album_ids is None:
        cursor = mysql.connection.cursor()
        cursor.execute('select id from Album limit %s' % limit)
        album_ids = [row[0] for row in cursor]

    spotify_albums = spotify.get_albums(user, album_ids)
    for album in [Album.import_json(js) for js in spotify_albums]:
        album.save()
        click.echo('Updated album %s (%s)' % (album.id, album.name))

    mysql.connection.commit()
Exemplo n.º 18
0
def admin_import_job(user_id, job_id):
    if 'user_id' not in session: abort(403)
    user = User.load(session['user_id'])
    if not user.is_admin: abort(403)

    url = 'https://clef2.scm.azurewebsites.net/api/triggeredwebjobs/import-user-playlists/history/%s' % job_id
    resp = requests.get(url, auth=webjobs_auth())
    if resp.status_code != 200: abort(resp.status_code)
    job_info = jsonpickle.decode(resp.content)
    app.logger.debug('job %s, status %s, duration: %s' %
                     (id, job_info['status'], job_info['duration']))
    if job_info['status'] == 'Success':
        user = UserListEntry.get(user_id)
        job_info['userInfo'] = jsonpickle.encode(user, unpicklable=True)
    return jsonify(job_info)
Exemplo n.º 19
0
def import_playlist_images(user_id):
    """Imports images for all of a user's playlists. This is to mitigate an issue with the normal import process."""
    user = User.load(user_id)
    image_count = 0
    playlist_count = 0
    for playlist in Playlist.for_user(user):
        playlist_count += 1
        spotify_playlist = spotify.get_playlist(user,
                                                playlist.id,
                                                playlist.owner,
                                                fields='id,images')
        for image in spotify_playlist['images']:
            playlist.add_image(image['width'], image['height'], image['url'])
            image_count += 1

    mysql.connection.commit()
    click.echo('done. %s playlists, %s images.' %
               (playlist_count, image_count))
Exemplo n.º 20
0
def get_spotify_playlist_tracks(user_id, playlist_id):
    """Get tracks in a Spotify playlist."""
    user = User.load(user_id)
    playlist = Playlist.load(playlist_id)
    if playlist is None:
        status, result = get_playlist(user, pl_id)
        if status != 200:
            click.echo('failed to fetch playlist: %s, %s', (status, result))

        playlist = Playlist.from_json(result)

    count = 0
    for track in spotify.get_playlist_tracks(user, playlist):
        click.echo(json.dumps(track, indent=2, sort_keys=True))
        count += 1

    mysql.connection.commit()  # in case user token changed
    click.echo('done. Total %s tracks' % count)
Exemplo n.º 21
0
def refresh_artists(user_id, artist_ids=[], limit=1000):
    user = User.load(user_id)
    if len(artist_ids) < 1:
        cursor = mysql.connection.cursor()
        cursor.execute('''
                          select distinct a.id
                          from   Artist a
                          left outer join ArtistGenre ag on a.id = ag.artist_id
                          where  isnull(ag.genre)
                          limit %s''' % limit)
        artist_ids = [row[0] for row in cursor]

    for artist in [
            Artist.import_json(sa)
            for sa in spotify.get_artists(user, artist_ids)
    ]:
        artist.save()
        click.echo('Updated artist %s (%s)' % (artist.id, artist.name))

    mysql.connection.commit()
Exemplo n.º 22
0
def user(id):
    app.logger.debug('/user/%s' % id)
    if 'user_id' in session:
        user_id = session['user_id']
        app.logger.debug('Session user: %s' % user_id)
        app.logger.info('Loading user %s' % id)
        user = User.load(session['user_id'])
        if user:
            if id != user.id: abort(403)
            app.logger.info('User %s is logged in.' % user.id)
            playlists = PlaylistSummaryView.for_user(user)
            return render_template('playlists.html',
                                   user=user,
                                   playlists=playlists)

        app.logger.warn('User %s not found in database.' % user_id)
    else:
        dump_session('No user_id in current session')

    return login()
Exemplo n.º 23
0
def get_spotify_audio_analysis(user_id, track_id):
    """Get Spotify's audio analysis for a track. See: https://beta.developer.spotify.com/documentation/web-api/reference/tracks/get-audio-analysis/"""
    user = User.load(user_id)
    count = 0
    analysis = spotify.get_audio_analysis(user, track_id)
    click.echo('{')

    click.echo('"bars": [')
    for bar in analysis['bars']:
        click.echo('\t%s' % json.dumps(bar))
    click.echo('],')

    click.echo('"beats": [')
    for beat in analysis['beats']:
        click.echo('\t%s' % json.dumps(beat))
    click.echo('],')

    click.echo('"sections": [')
    for section in analysis['sections']:
        click.echo('\t%s' % json.dumps(section))
    click.echo('],')

    click.echo('"segments": [')
    for segment in analysis['segments']:
        click.echo('\t%s' % json.dumps(segment))
    click.echo('],')

    click.echo('"tatums": [')
    for tatum in analysis['tatums']:
        click.echo('\t%s' % json.dumps(tatum))
    click.echo('],')

    click.echo('"track": %s,' %
               json.dumps(analysis['track'], indent=2, sort_keys=True))
    click.echo()
    click.echo('"meta": %s,' %
               json.dumps(analysis['meta'], indent=2, sort_keys=True))

    click.echo('}')

    mysql.connection.commit()  # in case the user's token was refreshed
Exemplo n.º 24
0
def refresh_track_audio_features(user_id, track_ids, limit):
    user = User.load(user_id)
    if len(track_ids) < 1:
        cursor = mysql.connection.cursor()
        cursor.execute(
            'select id from Track where danceability is null limit %s',
            (limit, ))
        track_ids = [row[0] for row in cursor]

    features = spotify.get_audio_features(user, track_ids)
    by_track_id = {f['id']: f for f in features if f != None}
    if len(by_track_id) < 1:
        click.echo('No features available for these tracks.')
        return

    tracks = Track.load_many(by_track_id.keys()).values()
    for track in tracks:
        track.update_features(by_track_id[track.id])
        track.save()

    mysql.connection.commit()
Exemplo n.º 25
0
def get_user_playlists(user_id):
    """Fetches all user playlists for a user from the clef database."""
    u = User.load(user_id)
    show_collection(Playlist.for_user(u))
Exemplo n.º 26
0
def get_user_playlists_summary(user_id):
    """Fetches a user's playlist summary view (what's shown on the user page)."""
    u = User.load(user_id)
    show_collection(PlaylistSummaryView.for_user(u))
Exemplo n.º 27
0
def admin():
    if 'user_id' not in session: abort(403)
    user = User.load(session['user_id'])
    if not user.is_admin: abort(403)
    user_list = UserList()
    return render_template('admin.html', user=user, user_list=user_list)
Exemplo n.º 28
0
def remove_playlist(user_id, playlist_id):
    """Deletes playlists."""
    user = User.load(user_id)
    Playlist.remove_playlists(user, playlist_id)
    mysql.connection.commit()
Exemplo n.º 29
0
def artists(user_id):
    if 'user_id' not in session: abort(401)
    if session['user_id'] != user_id: abort(403)
    user = User.load(user_id)
    artists = list(UserArtistOverview.for_user(user))
    return render_template('artists.html', user=user, artists=artists)
Exemplo n.º 30
0
def recommend(user_id, seed_tracks):
    user = User.load(user_id)
    user_average_vector = user.average_attributes()
    recs = clustering.recommend(user, seed_tracks, user_average_vector)
    click.echo(recs)