musikalkemist / spotifyplaylistgenerator

A script to create custom Spotify playlists using the Spotify API, based on seed tracks.
MIT License
70 stars 29 forks source link

Error: #2

Closed AtomicNess123 closed 3 years ago

AtomicNess123 commented 3 years ago

I run python createplaylist.py and I get:

How many tracks would you like to visualise? 10
Traceback (most recent call last):
  File "createplaylist.py", line 40, in <module>
    main()
  File "createplaylist.py", line 12, in main
    last_played_tracks = spotify_client.get_last_played_tracks(num_tracks_to_visualise)
  File "/Users/gahis/spotifyplaylistgenerator/spotifyclient.py", line 30, in get_last_played_tracks
    track in response_json["items"]]
KeyError: 'items'

Thanks for any help provided!

mpierrau commented 3 years ago

Hi!

I encountered this problem too. By printing the response_json variable you may see if you have received an error message from the API request. In my case the error was an "Insufficient client scope" error, which was caused due to me not specifying the correct scopes when getting the OAuth Token from the Spotify dev page. Make sure you tick "user-modify-private", "user-modify-public" and "user-read-recently-played".

AtomicNess123 commented 3 years ago

Thanks so much.

(1) I'm a newbie in API and programming in general. How shall I print the response_json variable? (2) I went to the API dashboard (https://developer.spotify.com/dashboard/applications/MYAPPID) but couldn't find those options to be ticked :(

mpierrau commented 3 years ago

1) When calling the API at response = self._place_post_api_request(url, data) (line 30 in spotifyclient.py according to your error message), you are returned a Response object. This object is then decoded to JSON format (similar to a python dictionary format) in the next line response_json = response.json(). The response content, which is saved in the variable response_json, can be viewed by simply printing the variable name print(response_json). This will give you more information as to what the error message is and will give you a clue to what the problem is.

2) Make sure you have ticked the following boxes (at https://developer.spotify.com/console/get-current-user/) when getting the SPOTIFY_USER_ID:

Screenshot from 2021-07-29 08-35-40

and the following for getting the SPOTIFY_AUTHORIZATION_TOKEN (at https://developer.spotify.com/console/post-playlists/):

Screenshot from 2021-07-29 08-37-59

Also make sure that you have exported the tokens correctly, as detailed by Valerio in the video. :)

AtomicNess123 commented 3 years ago

Thanks! I was getting the message: {'error': {'status': 401, 'message': 'Invalid access token'}} I did the token procedure (THANK YOU!) like this (just to be sure):

(1) I clicked on GET TOKEN (2) I ticked the pertinent options (3) I clicked on REQUEST TOKEN (4) I copy pasted the OAuth Token from the current page showing. (5) I exported those [export SPOTIFY_AUTHORIZATION_TOKEN={token} and export SPOTIFY_USER_ID={token}) in the Terminal (the tokens were a long almost 200 character key, just to confirm

However, I keep getting the same message. {'error': {'status': 401, 'message': 'Invalid access token'}}

mpierrau commented 3 years ago

It sounds like you have followed the instructions. What operating system are you using? If you are on Windows you will have to use "set" instead of "export". Try to print the tokens (print(authorization_token) and print(user_id) in the SpotifyClient __init__ method) to see if they are found by the system.

AtomicNess123 commented 3 years ago

Thanks again!

I am on a MAC, so I used export. I checked on terminal and the tokens were correct. However,

print(spotify_client._authorization_token)
print(spotify_client._user_id)

give me both: None.

So something is wrong with the call to

spotify_client = SpotifyClient(os.getenv("SPOTIFY_AUTHORIZATION_TOKEN"),
                                   os.getenv("SPOTIFY_USER_ID"))
AtomicNess123 commented 3 years ago

Update: in fact, doing os.getenv does nothing. I was all this time trying to run the script in Atom and terminal. Now I restarted the Terminal, and ran python createplaylist.pyand it moved forward for the first time.

When it asked me: What's the playlist name? I entered a name, and the it broke:

File "createplaylist.py", line 47, in <module>
    main()
  File "createplaylist.py", line 38, in main
    playlist = spotify_client.create_playlist(playlist_name)
  File "/Users/gahis/spotifyplaylistgenerator-master/spotifyclient.py", line 66, in create_playlist
    playlist_id = response_json["id"]

So while I still have the problem with os.getenv, I can run the script in Terminal, however getting this last error.

mpierrau commented 3 years ago

Great to hear you are making progress! :)

You can try to print os.environ to see all environment variables that are available, if you want to keep trying to figure that part out.

Since you didn't attach the full error message I'm not sure exactly what is wrong. However, I remember having to change one thing. The url string url = f"https://api.spotify.com/v1/users/{self._user_id}/playlists" uses the _user_id, which is the SPOTIFY_USER_ID provided. However, I found that this should actually be your "real" user ID (the one you log in with to Spotify). You can fetch this ID via response_json['id'].

So in the SpotifyClient __init__ method, change the line self._user_id = user_id to self._user_id = response_json['id']. Although you will have to add this piece of code to after you have defined the response_json variable of course :)

AtomicNess123 commented 3 years ago

Thanks again! Things are going well... I found out that Atom needs to be launched from Terminal so it inherits the env variables. Something learned.

As for the rest, I think I managed to fix the script in the way you explained, but now I am getting:

{'error': {'status': 401, 'message': 'The access token expired'}}

This is a new message that I get now. Are tokens short lived? Does this mean I have to do the whole process of going to the Spotify website (as you indicated above) and produce new tokens? Is there a way to do it remotely?

mpierrau commented 3 years ago

Yes, the token expires after one hour. I have not looked into how to make this process automated, but I think you can read more here.

There is another more developed Python library called Spotipy which has some more functionality and gives a nicer wrapper around the API. I have not used it myself though so I can't tell you more than that :)

AtomicNess123 commented 3 years ago

Besides that, all worked in the end by following your advice. Thank you so much for your kindness and solidarity <3 Indeed, the main issue beside the proper token, the call to

url = f"https://api.spotify.com/v1/users/{self._user_id}/playlists.

self._user is not appropriate as it is a token, not the user login name!

mpierrau commented 3 years ago

Great! Glad to hear it! :) @musikalkemist Perhaps you can change the code so that self._user_id is the user login ID and not the client ID?