hnarayanan/shpotify

Artist Not Found

MatthewWolff opened this issue ยท 42 comments

First noticed issue when a command that previously worked stopped working.
"spotify play artist moderat" now returns "no results when searching for moderat"
Issue persists for all searches. "spotify play artist drake" also returns that no results were found.

Searching artists for: drake
No results when searching for drake

This is a serious (and new) bug. They've probably changed their search API.

I will investigate.

It's probably because the curl call needs an access token from now on (correct me if I'm wrong)
I've added my access token as followed:
Change line 131:
curl -s -G $SPOTIFY_SEARCH_API --data-urlencode "q=$Q" -d "type=$type&limit=1&offset=0" -H "Accept: application/json" -H "Authorization: Bearer <yourAccessToken>" \
Obviously you need to change the <yourAccessToken> with your own access token.
You can get your access token from this example by clicking on 'Request accesstoken' on the following page: https://developer.spotify.com/web-api/console/get-search-item/

So a feature on this would be a command which saves your access token to a local file.
The command to save your access token would need to be something like spotify authorize

๐Ÿ˜ž Yes, this looks like the way it must go.

I'll be having a look at, I'm a total bash noob so don't expect to much here ๐Ÿ˜…
In the meantime you could add a piece of documentation in the readme.md on how request and add your access token manually?

I fixed my vimify (full spotify interface in the VIM editor) by having the user generate a token, then sending that in as a parameter on the vim ENV.
You could make a look-alike of that and on command 'spotify auth' open a browser sending the user to the spotify auth page.
(https://github.com/HendrikPetertje/vimify/blob/master/plugin/vimify.vim#L114-L118)

Would you mind if I open a pull request later today with an auth interface that does the following:

  • User writes spotify auth
  • Shell session opens browser on spotify auth page
  • Shell session asks user to paste token
  • Token is saved in ~/.shpotify as export SHPOTIFY_TOKEN=""
  • File is sourced on new shell if present
  • Request is done to search with new token.
  • A please auth message is provided if $SHPOTIFY_TOKEN is nul

Ow this is fun, When creating an auth token, it actually expires somewhere between 30 minutes and an hour.
Seems spotify is trying to put an end to (headless) automated scripts then :(

๐Ÿ˜ž๐Ÿ˜ž

Couldn't you store a refresh token instead so you can obtain a new auth token?

Perhaps. It's just this cognitive load and now it feels, as @HendrikPetertje says, that we're fighting against the tide.

I've created a php script which is hosted on a personal server, It exports the accesstoken in json. The only thing I can't seem to figure out is how to read out the accesstoken code in bash. I've already written a part where I store the json locally.

"authorize" )
cecho "Opening Authorization.";
ACCESS_URL="http://shpotify.preflight.space/access.php"
CALL=""
CALL=$(
curl -s -G $ACCESS_URL -H "Accept: application/json"
)
echo $CALL > auth.json
break ;;

Thank you for helping research this. I am going to make some time to experiment with some of this and will report back here too.

Thanks!

g-bon commented

Technically is not a big challenge, I've obtained a key and implemented a correct authentication (that can be refreshed automatically so it doesn't expire) in 10 minutes, and I think that apart from a possible rate limit on the requests, you don't violate the terms of services.

In fact you are piloting spotify itself and not building a standalone application. So your app is considered a non-streaming sda (spotify developer application) which saves you a lot of troubles.

Worst case scenario if you receive any complaint, or the rate limit becomes a problem, every user needs to get a key (just once for good) which is 2 clicks away.

Awesome. Could you submit a PR?

g-bon commented

My implementation is in python so I'm afraid I don't have a PR ready, but I'm sure someone confident with bash can pull this off quickly.

The steps involved are described here
https://developer.spotify.com/web-api/authorization-guide/#client_credentials_flow

Curl post request to the /token resource
Parse the json response to get the returned token
Any following request should contain the token

You can then ask for a refresh_token or for a new token when the current expires (1h at the moment)

Caveat: not sure how many people use shpotify but if the number is too large, a single client_key might exceed the requests limit. In that case it would be nice to indicate to a user how to get his own key (I imagine shpotify users are power users anyway).

@HendrikPetertje Maybe it's something you could also be interested in for vimify. Same Caveat applies.

Thank you very much for sharing so much detail. I or someone else will attempt to improve shpotify in this manner.

Hey everyone, I've been quietly using shpotify up until this bug came along (major bummer because shpotify is awesome!) and just noticed this official issue. Anyway I didn't realize shpotify was just a single bash script (love it!), so I thought I'd give it a go and ended up with a pretty simple fix.

I threw this together really quickly so it's probably way off your bash style, but I basically just get a new oauth token every search request (in searchAndPlay) via curl then use it in the call to the search endpoint. I think this is probably the simplest way to do it, but there are probably more performant things that could be added in. This runs fast enough on my computer and only adds a couple lines of code, but yeah I'd be 100% open to other approaches.

It does lead to the problem of imbedding client id/secrets in open source code -- but it would be possible to push those into a user config file, like ~/.shpotify.cfg for example, if anyone has problems with exposing those values (or if the rate limit stuff becomes a problem). I also use jq but could re-write that step in grep if you don't want more dependencies.

@hnarayanan I'd be happy to open a PR from my branch if that's cool with you?https://github.com/fonsecapeter/shpotify/tree/bug/76-oauth-for-search

@fonsecapeter: Why, please do!

@fonsecapeter: I was so excited to get to this, I didn't read your full notes :) I have pointed out both the jq dependency and the embedded API token as part of a code review of your PR.

Haha no worries! I'll reply in the PR

g-bon commented

That's good! Finally a kind heart fixed this.
The brew formula should b updated as well when this is integrated. https://github.com/Homebrew/homebrew-core/blob/master/Formula/shpotify.rb

Any update on this issue? I've pulled down the latest brew formula 1.2.0, and I'm still seeing this issue. Is the brew formula still waiting to be updated?

Not yet, I am yet to merge the pull request that fixes this.

Whoever likes updating brew formulas, please do your thing. ๐Ÿ™

@fonsecapeter: I'd forgotten about the expiration thing that @g-bon pointed out. Need to figure out how to work in that behaviour too.

I have the brew package installed and ~/.shpotify.cfg set up as specified in the Readme, but there seems to be no results for any search. Is there a timeline for this fix?
No background in Ruby/Homebrew or I would have fixed this myself (Up for it, if someone can guide me on where to start).

It's not super cool to show up to an open source project and ask about a timeline for anything.

Anyway, there is a problem where the auth credentials expire in some time, which causes subsequent searches to fail. There is an idea provided by @g-bon above if someone wants to attempt a fix.

g-bon commented

Hi @hnarayanan and @nevinvalsaraj let's try to figure out what's happening.

What I see:

  • Just updated from homebrew and everything is working fine for me. Search included. @nevinvalsaraj could you provide a bit more details? What command are you launching exactly, what error message do you see?

  • From the new code pulled in, I see that the authentication phase is repeated from scratch for every search operation. This means a new token is generated every time. It might not be the fastest and and most efficient way to do it but it's simple in code and should solve the token expiration problem completely, because the token is never stored or reused.

So either I'm not reading the code correctly or @nevinvalsaraj has a different problem we can investigate.

If this is the case I suggest to open a separate bug. Feel free to mention me, so I receive a notification and can have a look.

For me, it works for about 1 hour at which point searches stop working.

[~] spotify play kanye amazing
Searching tracks for: kanye amazing
No results when searching for kanye amazing

Reproducing what the code attempts to do in the command line seems to suggest what is going on.

[~] source ~/.shpotify.cfg                                                                                    22:56:22 
[~] SPOTIFY_CREDENTIALS=$(printf "${CLIENT_ID}:${CLIENT_SECRET}" | base64 | tr -d "\n");                      22:57:15 
[~] SPOTIFY_TOKEN_RESPONSE_DATA=$( \                                                                          22:57:17 
                        curl "${SPOTIFY_TOKEN_URI}" \
                            --silent \
                            -X "POST" \
                            -H "Authorization: Basic ${SHPOTIFY_CREDENTIALS}" \
                            -d "grant_type=client_credentials" \
                    )
[~] echo $SPOTIFY_TOKEN_RESPONSE_DATA                                                                         22:57:21 

//Empty

@hnarayanan Apologies, perhaps I should have been clear. I only meant to ask if someone is working on this, in which case I need not try and dig deeper.

@g-bon It seemed I had not upgraded to version 2.0. Just tried the commands again after upgrading, seems to work just fine. Thanks!

g-bon commented

No worries @nevinvalsaraj, happy it works for you.

@hnarayanan that does not happen to me. Played things for over a day now. Maybe you have some local version in the path and not using the latest one from homebrew?

Hi everyone, sorry for the delay!

As for the expiring tokens, I think @g-bon got it spot on -- I opted for the simple approach of just re-authenticating each request so shouldn't be a thing here. I figure we could always add the storing/authenticating logic later if performance ever becomes a problem.

The only thing I could think of for the issue @hnarayanan found is some kind of throttling -- the spotify API has a notion of rate-limiting that I do not fully understand. It gets enforced if they think someone is trying to DOS them, but I imagine it would take a lot of requests-per-some-amount-of-time to get there. I added a bunch of echo's in my local shpotify to watch the tokens and responses and have been using it since I started working on this, but haven't seen the issue yet (maybe the music I listen to is too chill and I'm not using it hard enough ๐Ÿ˜‚)

Anyway if the rate-limiting is what happened, they should return a 429 status code with a Retry-After header. I think right now any unexpected search response is treated as No results when searching for ... so it'll take some extra echo'ing to figure out what actually happened.

@hnarayanan, when you hit this error, do you happen to know if it started working again right after, or if it went offline for a bit then just sort of started working again later? Also is this happening often for you?

I will confirm, but...

It happens each time I try a new set of keys. It works for about 30 min--1 hour and then it stops. (It doesn't resume working like the next day or whatever.)

I came across shpotify a few weeks ago, prior to this update, and I found this issue when I received no results after initial installation.

I've been following this issue, so when the fix was released over the weekend I jumped on it first thing on Monday morning to install, but I'm having the same results on my end as I did pre-update. No results.

I believe I'm set up correctly, as I've added my keys into the ~/.shpotify.cfg file, per the instructions, but I don't ever get any results โ€“ not for 30 minutes, not after resourcing the config, not after restarting my terminal, not after a full system reboot.

Happy to provide any additional information on this, but I just wanted to call it out in case it's symptomatic of a larger issue at play.

g-bon commented

@hnarayanan Always working fine for me, without being able to replicate it I don't know how to investigate that.

@jillmolloy any progress? did you find .shoptify.cfg created for you and you automatically and you just filled id with your client id and secret?
I know it's stupid but did you triple check the auth values?
What error do you see?

@hnarayanan @jillmolloy I guess it would be nice to add some logging of the response so that life would be much easier when investigating issues.

@g-bon: I had a hunch and tried it. It works in bash but not zsh, my usual shell.

[~] bash                                                                                                      14:41:59 
bash-4.4$ spotify play kanye amazing
Connecting to Spotify's API
Searching tracks for: kanye amazing
play uri: spotify:track:0m3Ze0cy8qBHSsV2exAfCw
Playing (kanye amazing Search) -> Spotify URI: spotify:track:0m3Ze0cy8qBHSsV2exAfCw
bash-4.4$ exit
exit
[~] spotify play kanye amazing                                                                                14:42:21 
Searching tracks for: kanye amazing
No results when searching for kanye amazing

It could have something to do with how the .cfg file is sourced.

@hnarayanan Iโ€™ll get back to you on your other questions when Iโ€™m in front of my computer, but just wanted to let you know you might be on the right track there โ€” I use zsh too. Will try bash.

g-bon commented

awesome that found the probable cause. Shall we continue on a new bug? This is formally close so not visibile automatically to people who might have the same problem

Let me open a new issue.