Last active
February 18, 2018 19:47
-
-
Save cbilson/fb81ba6834ba084a803f5f817b22d5c6 to your computer and use it in GitHub Desktop.
get a user's spotify playlists
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>Clef</title> | |
</head> | |
<body id="home"> | |
<h1>Logged in as {{user.display_name}}</h1> | |
<h3>Playlists</h3> | |
<ul> | |
{% for item in user.playlists %} | |
<li>{{ item }}</li> | |
{% endfor %} | |
</ul> | |
<footer> | |
Also online: {{other_users}} | |
</footer> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import base64, json, logging, os, requests, sys, threading, webbrowser | |
from urllib.parse import urlencode, unquote | |
from flask import Flask, render_template, request, session, redirect | |
from datetime import datetime | |
from logging import StreamHandler | |
from logging.handlers import RotatingFileHandler | |
app = Flask(__name__) | |
app.logger.setLevel(logging.DEBUG) | |
app.config.update( | |
SESSION_COOKIE_NAME = 'clef_1_session') | |
if (os.getenv('DEBUG')): | |
stdoutLogger = StreamHandler(sys.stdout) | |
stdoutLogger.setLevel(logging.DEBUG) | |
app.logger.addHandler(stdoutLogger) | |
app.config.update( | |
DEBUG = True, | |
# just for running locally | |
SECRET_KEY='P/5K82pTf0Gmx/DGvS/5s6S+XCy7133NUSm5kOAxKCH1xoK9oI/sDrmUJy1wsFfZcvVlu6QtEGuxyvlMP98YcQ==') | |
else: | |
fileHandler = RotatingFileHandler('app.log', maxBytes=10*1024*1024, backupCount=100) | |
fileHandler.setLevel(logging.DEBUG) | |
app.logger.addHandler(fileHandler) | |
app.config.update( | |
SECRET_KEY = os.getenv('SECRET_KEY'), | |
SESSION_COOKIE_SECURE = True) | |
if not app.config['SECRET_KEY']: | |
raise Exception('Please specify a SECRET_KEY or DEBUG environment variable.') | |
CLIENT_ID = os.getenv("SPOTIFY_CLIENT_ID") | |
if not CLIENT_ID: | |
raise Exception('SPOTIFY_CLIENT_ID environment variable not set.') | |
CLIENT_SECRET = os.getenv("SPOTIFY_CLIENT_SECRET") | |
if not CLIENT_SECRET: | |
raise Exception('SPOTIFY_CLIENT_SECRET environment variable not set.') | |
ENCODED_AUTHENTICATION = base64.b64encode(bytes(CLIENT_ID + ':' + CLIENT_SECRET, 'utf-8')).decode('ascii') | |
scope = "playlist-read-private user-library-read user-read-email user-read-playback-state user-modify-playback-state user-read-currently-playing user-read-recently-played" | |
class User: | |
def __init__(self, token_json, me_json, playlists_json): | |
self.access_token = token_json['access_token'] | |
self.scope = token_json['scope'] | |
self.expires_in = token_json['expires_in'] | |
self.refresh_token = token_json['refresh_token'] | |
self.id = me_json['id'] | |
self.display_name = me_json['display_name'] | |
self.email = me_json['email'] | |
self.playlists = [item['name'] for item in playlists_json['items']] | |
# this would be in our database eventually | |
users = {} | |
pending_authentications = {} | |
@app.route('/') | |
def index(): | |
if 'user_id' in session and session['user_id'] in users: | |
app.logger.debug('All users: %s' % ', '.join(users.keys())) | |
user = users[session['user_id']] | |
other_users = ', '.join([u for u in list(users.keys()) if u != user.id][:10]) | |
return render_template('logged-in.html', user=user, other_users=other_users) | |
session.clear() | |
state = base64.b64encode(os.urandom(64)).decode('ascii') | |
app.logger.info('Redirecting to authorize, state = %s', state) | |
pending_authentications[state] = datetime.utcnow() | |
params = urlencode({'client_id': CLIENT_ID, | |
'response_type': 'code', | |
'redirect_uri': request.url_root + 'authorized', | |
'state': state, | |
'scope': scope}) | |
authorize_url = 'https://accounts.spotify.com/authorize/?' + params | |
return redirect(authorize_url) | |
@app.route('/authorized') | |
def authorized(): | |
if 'error' in request.args: | |
error = request.args.get('error') | |
app.logger.error('Error response from authorize: %s', error) | |
return render_template('auth-error.html', error=error) | |
auth_code = request.args.get('code') | |
state = unquote(request.args.get('state')) | |
app.logger.info('authorized state: %s', state) | |
if state not in pending_authentications: | |
app.logger.error("state doesn't match: state: %s" % state) | |
app.logger.error("pending_authentications: %s" % ', '.join(pending_authentications.keys())) | |
return render_template('auth-error.html', error="Hmm...this doesn't look like an authorization requested by Clef.") | |
pending_authentications.pop(state) | |
headers = {'Authorization': 'Basic ' + ENCODED_AUTHENTICATION} | |
data = {'grant_type': 'authorization_code', | |
'code': auth_code, | |
'redirect_uri': request.url_root + 'authorized'} | |
app.logger.info('Requesting token.') | |
resp = requests.post('https://accounts.spotify.com/api/token', headers=headers, data=data) | |
token_json = resp.json() | |
if resp.status_code != 200: | |
app.logger.error('Failed to get token: ' + str(token_json)) | |
error = 'Failed to get token.' | |
if 'error_description' in token_json: error = token_json['error_description'] | |
return render_template('auth-error.html', error=error) | |
headers['Authorization'] = 'Bearer ' + token_json['access_token'] | |
app.logger.info('Requesting user information') | |
resp = requests.get('https://api.spotify.com/v1/me', headers=headers) | |
if resp.status_code != 200: | |
app.logger.error('me resp code not OK, Response: ' + (resp)) | |
return render_template('auth-error.html', error="Failed to get your profile.") | |
# TODO: This would be stored in a database | |
user_json = resp.json() | |
app.logger.debug('User info: %s', json.dumps(user_json)) | |
app.logger.info('Requesting user playlists') | |
resp = requests.get('https://api.spotify.com/v1/me/playlists', headers=headers) | |
playlists_json = resp.json() | |
app.logger.debug('User playlists: %s', json.dumps(playlists_json)) | |
user = User(token_json, user_json, playlists_json) | |
users[user.id] = user | |
session['user_id'] = user.id | |
return redirect('/') | |
if __name__ == '__main__': | |
#threading.Timer(1.25, lambda: webbrowser.open('http://localhost:5000/')).start() | |
app.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment