Skip to content

Commit

Permalink
Add FlaskSessionCacheHandler
Browse files Browse the repository at this point in the history
Updated examples/app.py
Updated CHANGELOG.md and appropriate docs.
  • Loading branch information
bim9262 committed Jun 23, 2022
1 parent 7337bf9 commit 750defb
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Added `market` parameter to `album` and `albums` to address ([#753](https://github.com/plamere/spotipy/issues/753)
* Added 'show_featured_artists.py' to 'examples'.
* Expanded contribution and license sections of the documentation.
* Added `FlaskSessionCacheHandler`, a cache handler that stores the token info in a flask session.

### Fixed

Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Expand Up @@ -235,6 +235,7 @@ The following handlers are available and defined in the URL above.
- ``CacheFileHandler``
- ``MemoryCacheHandler``
- ``DjangoSessionCacheHandler``
- ``FlaskSessionCacheHandler``
- ``RedisCacheHandler``

Feel free to contribute new cache handlers to the repo.
Expand Down
38 changes: 12 additions & 26 deletions examples/app.py
Expand Up @@ -27,65 +27,51 @@
from flask import Flask, session, request, redirect
from flask_session import Session
import spotipy
import uuid

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(64)
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_FILE_DIR'] = './.flask_session/'
Session(app)

caches_folder = './.spotify_caches/'
if not os.path.exists(caches_folder):
os.makedirs(caches_folder)

def session_cache_path():
return caches_folder + session.get('uuid')

@app.route('/')
def index():
if not session.get('uuid'):
# Step 1. Visitor is unknown, give random ID
session['uuid'] = str(uuid.uuid4())

cache_handler = spotipy.cache_handler.CacheFileHandler(cache_path=session_cache_path())
cache_handler = spotipy.cache_handler.FlaskSessionCacheHandler(session)
auth_manager = spotipy.oauth2.SpotifyOAuth(scope='user-read-currently-playing playlist-modify-private',
cache_handler=cache_handler,
show_dialog=True)
cache_handler=cache_handler,
show_dialog=True)

if request.args.get("code"):
# Step 3. Being redirected from Spotify auth page
# Step 2. Being redirected from Spotify auth page
auth_manager.get_access_token(request.args.get("code"))
return redirect('/')

if not auth_manager.validate_token(cache_handler.get_cached_token()):
# Step 2. Display sign in link when no token
# Step 1. Display sign in link when no token
auth_url = auth_manager.get_authorize_url()
return f'<h2><a href="{auth_url}">Sign in</a></h2>'

# Step 4. Signed in, display data
# Step 3. Signed in, display data
spotify = spotipy.Spotify(auth_manager=auth_manager)
return f'<h2>Hi {spotify.me()["display_name"]}, ' \
f'<small><a href="/sign_out">[sign out]<a/></small></h2>' \
f'<a href="/playlists">my playlists</a> | ' \
f'<a href="/currently_playing">currently playing</a> | ' \
f'<a href="/current_user">me</a>' \
f'<a href="/current_user">me</a>' \



@app.route('/sign_out')
def sign_out():
try:
# Remove the CACHE file (.cache-test) so that a new user can authorize.
os.remove(session_cache_path())
session.clear()
except OSError as e:
print ("Error: %s - %s." % (e.filename, e.strerror))
session.pop("token_info", None)
return redirect('/')


@app.route('/playlists')
def playlists():
cache_handler = spotipy.cache_handler.CacheFileHandler(cache_path=session_cache_path())
cache_handler = spotipy.cache_handler.FlaskSessionCacheHandler(session)
auth_manager = spotipy.oauth2.SpotifyOAuth(cache_handler=cache_handler)
if not auth_manager.validate_token(cache_handler.get_cached_token()):
return redirect('/')
Expand All @@ -96,7 +82,7 @@ def playlists():

@app.route('/currently_playing')
def currently_playing():
cache_handler = spotipy.cache_handler.CacheFileHandler(cache_path=session_cache_path())
cache_handler = spotipy.cache_handler.FlaskSessionCacheHandler(session)
auth_manager = spotipy.oauth2.SpotifyOAuth(cache_handler=cache_handler)
if not auth_manager.validate_token(cache_handler.get_cached_token()):
return redirect('/')
Expand All @@ -109,7 +95,7 @@ def currently_playing():

@app.route('/current_user')
def current_user():
cache_handler = spotipy.cache_handler.CacheFileHandler(cache_path=session_cache_path())
cache_handler = spotipy.cache_handler.FlaskSessionCacheHandler(session)
auth_manager = spotipy.oauth2.SpotifyOAuth(cache_handler=cache_handler)
if not auth_manager.validate_token(cache_handler.get_cached_token()):
return redirect('/')
Expand Down
26 changes: 26 additions & 0 deletions spotipy/cache_handler.py
Expand Up @@ -2,6 +2,7 @@
'CacheHandler',
'CacheFileHandler',
'DjangoSessionCacheHandler',
'FlaskSessionCacheHandler',
'MemoryCacheHandler',
'RedisCacheHandler']

Expand Down Expand Up @@ -147,6 +148,31 @@ def save_token_to_cache(self, token_info):
logger.warning("Error saving token to cache: " + str(e))


class FlaskSessionCacheHandler(CacheHandler):
"""
A cache handler that stores the token info in the session framework
provided by flask.
"""

def __init__(self, session):
self.session = session

def get_cached_token(self):
token_info = None
try:
token_info = self.session["token_info"]
except KeyError:
logger.debug("Token not found in the session")

return token_info

def save_token_to_cache(self, token_info):
try:
self.session["token_info"] = token_info
except Exception as e:
logger.warning("Error saving token to cache: " + str(e))


class RedisCacheHandler(CacheHandler):
"""
A cache handler that stores the token info in the Redis.
Expand Down

0 comments on commit 750defb

Please sign in to comment.