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( '--------------------------------------------------------------------------------' )
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)
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])
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])
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()
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))
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
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)
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))
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' }
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)
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)
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)
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( '--------------------------------------------------------------------------------' )
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)
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)
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()
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)
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))
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)
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()
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()
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
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()
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))
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))
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)
def remove_playlist(user_id, playlist_id): """Deletes playlists.""" user = User.load(user_id) Playlist.remove_playlists(user, playlist_id) mysql.connection.commit()
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)
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)