1
votes

I'm trying to allow users to login with Spotify (using the Spotipy library) to provide authentication for creating a playlist on their account and populating the playlist. After the user has logged in, I will display the playlist they have just created in the redirect template via an embedded Spotify player (using the playlist ID of the newly created playlist).

I have a form input box in my HTML template which takes input from the user (their Spotify username). I also have a list of Spotify URIs for tracks ready to populate the playlist with.

I followed Spotipy's documentation regarding obtaining a token for users for authentication as follows (I have removed my client-id & secret).. I'm not sure why it isn't working:

import os
import spotipy
import spotipy.util as util
from json.decoder import JSONDecodeError
from datetime import date

@login_required
def save_playlist(request, data='Default_Data'):

    username = data.split('/')[0] #spotify username
    track_ids = data.split('/')[1:11] #list of spotify IDs for playlist tracks
    client_id =  '****'
    client_secret = '****'
    scope = 'playlist-modify-public, playlist-modify-private'
    redirect_uri = 'http://127.0.0.1:8000/save_playlist/'

    #check if username is already in cache, if not, create cache 
    try:
        token = util.prompt_for_user_token(username, 
            scope=scope,client_id=client_id, 
            client_secret=client_secret,redirect_uri=redirect_uri)
    except (AttributeError, JSONDecodeError):
        os.remove(f".cache-{username}")
        token = util.prompt_for_user_token(username, 
            scope=scope,client_id=client_id, 
            client_secret=client_secret,redirect_uri=redirect_uri)


    sp=spotipy.Spotify(auth=token)
    today = date.today()
    date_string = (str(today.day) + ' - ' + str(today.month) + ' - ' + str(today.year))

    #playlist title
    playlist_name = f"GENIE - " + username + ' | ' + date_string
    #create a new public playlist to be populated
    sp.user_playlist_create(username, name=playlist_name, public=True)
    #id of playlist we just created
    playlist_id = sp.current_user_playlists(limit=1)['items'][0]['id']
    #add playlist tracks to this playlist
    sp.user_playlist_add_tracks(username,playlist_id,tracks=track_ids)

    return render(request, 'blog/save_playlist.html', {'playlist_id':playlist_id})

When a user enters their username and logins to Spotify, multiple windows keep popping up rather than just one (see terminal below). I believe the issue is somewhere in obtaining the token.

terminal output when attempting to login

I have set the redirect URI in the Spotify developer console to be the same as above ('http://127.0.0.1:8000/save_playlist/').

Thanks in advance!

2

2 Answers

0
votes

util.prompt_for_user_token should not be used in a web app that would allow any user to sign in, since we don't know the user's ID/name in advance. It's just a helper to get started quickly locally.

Instead you should use spotipy.oauth2.SpotifyOAuth directly, by specifying a unique cache path for your user. In the case of a web app it would be a session ID.

Here is a complete example made for Flask which you can adapt to your needs https://github.com/plamere/spotipy/blob/master/examples/app.py

-1
votes

Instead of using Spotipy, a quick solution is to go to https://pypi.org/project/spotify-token/ ,it is a Python script that can generate a Spotify token if a Spotify username and password is provided.

With that said, just keep in mind that not everyone will provide their username and password willingly. Cheers!