Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API Changes #123

Open
kingosticks opened this issue Apr 6, 2021 · 70 comments
Open

API Changes #123

kingosticks opened this issue Apr 6, 2021 · 70 comments

Comments

@kingosticks
Copy link
Member

kingosticks commented Apr 6, 2021

Soundcloud devs seem to be alive! They've made / are making some API changes which look like they will impact us. The API docs have moved here. The old endpoints still seem to work as of now. They also seem to be doing something to pagination and it sounds like the default response format is going to change.

@djmattyg007
Copy link

How does this affect the PRs that @Laurentww has submitted recently?

@kingosticks
Copy link
Member Author

I've only looked at the rate limit one. Only the image one seems to hit the official API and that's restricted to the tracks endpoint which I don't think changed. Looks like it's mostly the /me/foo endpoints.

@Laurentww
Copy link
Contributor

Adding images (#121) still uses the official API, as the standard app client id doesn't return rate errors here. Though, #121 could be improved as well by first attempting with the publicly obtained client id and reversing to the standard app client id on failure.

As far as I can see, no pagination calls are made and the current API call uris are up to date.

@kingosticks
Copy link
Member Author

More api changes coming https://developers.soundcloud.com/blog/security-updates-api

@dreamlayers
Copy link
Contributor

It seems the security related changes prevent mopidy-soundcloud from working now, as explained in https://stackoverflow.com/questions/68459401/soundcloud-api-authentication-always-throws-401-unauthorized

@bretonium
Copy link

looks like it. I am constantly getting mopidy[7898]: ERROR [SoundCloudBackend-6] mopidy_soundcloud.soundcloud Invalid "auth_token" used for SoundCloud authentication!

@bretonium
Copy link

According to soundcloud/api#151, this will not be fixed. Soundcloud api can now be used only together with a service that will issue a token. The tokens also need to be refreshed, since they are now time-limited.

Can mopidy provide an API endpoint that the clients could use to fetch the tokens? Is there anything similar in mopidy already?

@kingosticks
Copy link
Member Author

Yes, Mopidy-Spotify works this way (utilising https://github.com/adamcik/oauthclientbridge hosted at auth.mopidy.com). We should be able to re-use that here also. Although I am not sure who controls Mopidy's soundcloud app and if they would need to update anything in the account settings, maybe it is @adamcik ?

Although they (Soundcloud) maybe need to sort out their CORS issues also (from soundcloud/api#151).

@adamcik
Copy link
Member

adamcik commented Oct 19, 2021

I don't think I have access to the oauth things for this account. However, I did play with using the bridge for SoundCloud and it worked at the time.

So if we can recover the old account or get new credentials we should be good to go.

Perhaps check with @tkem if he has access?

But, ideally we should have this attached to a non-personal account like we've done for Spotify if at all possible.

@tkem
Copy link
Member

tkem commented Oct 19, 2021

@adamcik Well, sorry, no access.

@bretonium
Copy link

The current client_id was added in 2013 by @dz0ny

@kingosticks
Copy link
Member Author

As far as I know there's still no way to get new soundcloud credentials (facepalm) but if the authorization flow worked previously as is, maybe we don't need to hunt down the owner (although it'd be nice to sort that too).

@adamcik
Copy link
Member

adamcik commented Oct 20, 2021

That was with the old flow that got / is getting removed, so won't work :( Checked https://soundcloud.com/you/apps and I don't have anything setup myself.

@kingosticks
Copy link
Member Author

@dz0ny has access and can provide he secret (is that all we need @adamcik) but everything else is locked out and can't be changed. This includes the callback URL but hopefully that isn't a show-stopper for us.

@adamcik
Copy link
Member

adamcik commented Oct 31, 2021

That should be workable with the id + secret

@adamcik
Copy link
Member

adamcik commented Nov 9, 2021

Thanks @kingosticks for getting the secret to me, I tried running this in my local test instance of the oauth bridge and I need to do one minor code change and it should all just work.

Only ugly bit we'll have to do is to update https://mopidy.com/soundcloud_callback with some JS and a fallback link that sends people to https://auth.mopidy.com/soundcloud/callback with the same parameters and then we are back in business.

So what we need to progress is:

  • List of the scopes we should ask for
  • Setting up the oauthclientbridge properly
  • Update of soundcloud_callback to redirect if the "right" oauth param is there so we can handle old and new cases
  • Update of the plugin to start using the new flow with refresh tokens
  • Update of the extension page on mopidy.com to fetch the new token types

What did I miss?

@adamcik
Copy link
Member

adamcik commented Nov 9, 2021

And by should just work I mean that I did manage to get a working token in my locally modified test setup.

@chris-aeviator
Copy link

is there a way where users can setup their own bridge in order to get soundcloud running again?

@adamcik
Copy link
Member

adamcik commented Nov 22, 2021

Sorry for the delay, I haven't had much chance to work on my part of this.

@chris-aeviator no not really, my code is on github, but you need credentials from soundcloud that they've stopped handing out years ago :(

@chris-aeviator
Copy link

Ok - thanks for clarification - I can see that I can't register a new API account...bummer that soundcloud forces us to use their crappy player

@adamcik
Copy link
Member

adamcik commented Nov 26, 2021

https://auth.mopidy.com/soundcloud is now up and running - since we can't change the redirect it sends us to https://mopidy.com/soundcloud_callback/?code=REDACTED&state=REDACTED and not https://auth.mopidy.com/soundcloud/callback as it's supposed to. I.e. next step is to add JS to /soundcloud_callback to detect that we are in the wrong place and send people to the right domain so the rest of the flow can complete.

With the bridge up and running none of the remaining work should be blocked on me, other than the one minor code change to the bridge that I only have in my dev setup. If we need to specify a default scope just let me know, and I'll update the config. But at least other contributors can pickup the other items I mentioned further up.

@adamcik
Copy link
Member

adamcik commented Nov 26, 2021

The old case sends you to https://mopidy.com/soundcloud_callback/?code=REDACTED&state=REDACTED#access_token=REDACTED&scope=non-expiring and fails with eg https://mopidy.com/soundcloud_callback/?error_code=access_denied&error_description=user%20cancelled%20request&state=REDACTED

So for successful requests we can check if the hash is set and decide if we should redirect or not, but for errors I think our only option is to encode something in our state parameter :/

@adamcik
Copy link
Member

adamcik commented Nov 26, 2021

Testing with changing the button href in https://mopidy.com/ext/soundcloud/ to point at the bridge and going through ends up failing with INVALID_STATE: Authentication page sent wrong state to pop-up. since we get the state that the bridge and soundcloud share, not the mopidy website and the bridge.

So perhaps we can just blindly assume that we should redirect this case to the bridge, and worst case it also fails the state check and no harm done, and in most cases we end up with a page that can handle the old and new cases.

@nimbling
Copy link

nimbling commented Dec 30, 2021

EDIT: NO IT DID NOT MY BAD, SORRY :(

Hopefully this helps:
I had the mopidy_soundcloud.soundcloud Invalid "auth_token" used for SoundCloud authentication! line in my Mopidy log, but that disappeared after I authorized myself at https://developers.soundcloud.com/docs/api/explorer/open-api

@simaovienna
Copy link

As soundcloud "...will no longer be processing API application requests at this time...":

https://soundcloud.com/you/apps/new

is there any chance/workaround to get the integration to work? @nimbling how did you authorize?

thanks

@nimbling
Copy link

nimbling commented Jan 5, 2022

I didn't, please see my correction. I did just log in using that link here: https://developers.soundcloud.com/docs/api/explorer/open-api - but it did not help as much as I thought it did.

@kingosticks kingosticks pinned this issue Mar 22, 2022
tbouska added a commit to buvis/container-images that referenced this issue Mar 29, 2022
@Goosegit11
Copy link

Goosegit11 commented Aug 9, 2022

Hello all, sorry if I ask stupid questions, I am new to GNU/Linux and I want to listen to soundcloud with mopidy.

so, which token should I put into "auth_token"?
1-1111111-111111111, which is on readme.md of this repo, or 1-11111-11111111111-abcdvteewq323176dfd which is on the mopidy-soundcloud auth page

and did I understand correctly that this is the right way to install mopidy-soundcloud now: sudo python3 -m pip install "git+https://github.com/mopidy/mopidy-soundcloud@master"

offtopic question: how do I turn off mopidy.service and use mopidy as user? do I just systemctl disable mopidy or what?

@dominikdeka
Copy link

In order to obtain authenticate key go to https://mopidy.com/ext/soundcloud/ and utilize Authenticate mopidy with SoundCloud button.

and did I understand correctly that this is the right way to install mopidy-soundcloud now: sudo python3 -m pip install "git+https://github.com/mopidy/mopidy-soundcloud@master"

Yeap, it worked for me two days ago. (I am afraid new realese still not yet ready. :( )

offtopic question: how do I turn off mopidy.service and use mopidy as user? do I just systemctl disable mopidy or what?

Yes, but as a root sudo systemctl disable mopidy. Also make sure you stop the service, before launching mopidy as user: sudo systemctl stop mopidy

markferry added a commit to markferry/multizone-audio that referenced this issue Oct 3, 2022
markferry added a commit to markferry/multizone-audio that referenced this issue Oct 12, 2022
markferry added a commit to markferry/multizone-audio that referenced this issue Oct 13, 2022
@Goosegit11
Copy link

Goosegit11 commented Jan 30, 2023

Jesus Christ, seems like I got it working now 💀

For those who haven't figured that shit out yet:

don't use mopidy-soundcloud from AUR,
don't use just sudo pip install mopidy-soundcloud, it's not working.

Use this:

sudo python3 -m pip install "git+https://github.com/mopidy/mopidy-soundcloud@master"

thank you @dominikdeka @kingosticks and all contributors of mopidy-soundcloud

@kingosticks
Copy link
Member Author

So... I never made that release?! Yikes. Sorry

@dreamlayers
Copy link
Contributor

dreamlayers commented Jan 31, 2023

There is no need to run pip as root via sudo. The installation only needs to be accessible to the user running mopidy. I used sudo -u mopidy bash to become the mopidy user and then installed without sudo, with the install ending up under ~mopidy/.local/lib/.

@kingosticks
Copy link
Member Author

I don't know what to do about this extension going forward. I can do this long overdue release tonight (I hope) but it's still fundamentally crippled by their incredibly stupid rate limiting. They (Soundcloud) keep banging on about how they are working away on the API but they re-iterated just last week they've no plans to open it up again. I don't get the point.

@herrernst
Copy link

A new release would be nice, thanks in advance.

@kingosticks
Copy link
Member Author

https://github.com/mopidy/mopidy-soundcloud/releases/tag/v3.0.2

@herrernst
Copy link

Thank you very much! Do you know if it will appear automatically in the apt repos at apt.mopidy.com? Here I see only 3.0.1: https://apt.mopidy.com/pool/

@kingosticks
Copy link
Member Author

kingosticks commented Feb 18, 2023 via email

@dominikdeka
Copy link

Thank you @kingosticks for preparing this release!

@blacklight
Copy link

Is anything broken again with this integration?

It worked for a few days but it's failing again now, no matter the track I'm trying to play.

I have tried both the latest pip version and the git version just in case. I can log in to SC with my token, browse my music collections and all, but whenever I try to play a track I get this:

DEBUG    2023-03-24 10:26:26,524 [798355:SoundCloudBackend-10 (_actor_loop)] mopidy_soundcloud.soundcloud
  Requested https://api.soundcloud.com/tracks/256913562
DEBUG    2023-03-24 10:26:26,787 [798355:SoundCloudBackend-10 (_actor_loop)] mopidy.backend
  Backend translated URI from soundcloud:song/We Have Lost The Way (Instrumental).256913562 to None
WARNING  2023-03-24 10:26:26,787 [798355:Core-12 (_actor_loop)] mopidy.core.tracklist
  Track is not playable: soundcloud:song/We Have Lost The Way (Instrumental).256913562

That Backend translated URI from soundcloud:song/... to None part is very suspicious. It seems like something goes very wrong when mapping the SC item to a mopidy item.

Before I start diving into this can of worms, has anybody been experiencing the same issue?

@kingosticks
Copy link
Member Author

Working for me. Where is the output from https://github.com/mopidy/mopidy-soundcloud/blob/master/mopidy_soundcloud/soundcloud.py#L245 in your debug log?

@blacklight
Copy link

@kingosticks it is there, I just omitted it in the previous message. A full log trace for a request to play a SoundCloud track looks like this:

DEBUG    2023-03-24 14:02:59,265 [890454:MpdSession-21 (_actor_loop)] mopidy_mpd.session
  Request from [::ffff:127.0.0.1]:45772: playid "37"
DEBUG    2023-03-24 14:02:59,268 [890454:Audio-2 (_actor_loop)] mopidy.audio.gst
  Changing state to GST_STATE_READY: result=GST_STATE_CHANGE_SUCCESS
DEBUG    2023-03-24 14:02:59,268 [890454:SoundCloudBackend-9 (_actor_loop)] mopidy_soundcloud.soundcloud
  Parsing track soundcloud:song/We Have Lost The Way (Instrumental).256913562
DEBUG    2023-03-24 14:02:59,268 [890454:MainThread] mopidy.audio.gst
  Got STATE_CHANGED bus message: old=GST_STATE_NULL new=GST_STATE_READY pending=GST_STATE_VOID_PENDING
DEBUG    2023-03-24 14:02:59,268 [890454:SoundCloudBackend-9 (_actor_loop)] mopidy_soundcloud.soundcloud
  Getting info for track with ID 256913562
DEBUG    2023-03-24 14:02:59,437 [890454:SoundCloudBackend-9 (_actor_loop)] urllib3.connectionpool
  https://api.soundcloud.com:443 "GET /tracks/256913562 HTTP/1.1" 200 889
DEBUG    2023-03-24 14:02:59,437 [890454:SoundCloudBackend-9 (_actor_loop)] mopidy_soundcloud.soundcloud
  Requested https://api.soundcloud.com/tracks/256913562
DEBUG    2023-03-24 14:02:59,438 [890454:SoundCloudBackend-9 (_actor_loop)] urllib3.connectionpool
  Starting new HTTPS connection (1): soundcloud.com:443
DEBUG    2023-03-24 14:02:59,655 [890454:SoundCloudBackend-9 (_actor_loop)] urllib3.connectionpool
  https://soundcloud.com:443 "GET / HTTP/1.1" 200 None
DEBUG    2023-03-24 14:02:59,664 [890454:SoundCloudBackend-9 (_actor_loop)] urllib3.connectionpool
  Starting new HTTPS connection (1): a-v2.sndcdn.com:443
DEBUG    2023-03-24 14:03:00,143 [890454:SoundCloudBackend-9 (_actor_loop)] urllib3.connectionpool
  https://a-v2.sndcdn.com:443 "GET /assets/53-aed4402d.js HTTP/1.1" 200 None
DEBUG    2023-03-24 14:03:00,164 [890454:SoundCloudBackend-9 (_actor_loop)] urllib3.connectionpool
  https://a-v2.sndcdn.com:443 "GET /assets/51-f3c4bf71.js HTTP/1.1" 200 None
DEBUG    2023-03-24 14:03:00,166 [890454:SoundCloudBackend-9 (_actor_loop)] urllib3.connectionpool
  Starting new HTTPS connection (1): cdn.cookielaw.org:443
DEBUG    2023-03-24 14:03:00,167 [890454:SoundCloudBackend-9 (_actor_loop)] mopidy.backend
  Backend translated URI from soundcloud:song/We Have Lost The Way (Instrumental).256913562 to None
WARNING  2023-03-24 14:03:00,168 [890454:Core-12 (_actor_loop)] mopidy.core.tracklist
  Track is not playable: soundcloud:song/We Have Lost The Way (Instrumental).256913562

This line is quite interesting:

DEBUG    2023-03-24 14:03:00,166 [890454:SoundCloudBackend-9 (_actor_loop)] urllib3.connectionpool
  Starting new HTTPS connection (1): cdn.cookielaw.org:443

This is received just before the track fails to play. Is there maybe some weird redirect to cookielaw.org that prevents all the data from being retrieved?

@kingosticks
Copy link
Member Author

kingosticks commented Mar 24, 2023

I think that's a normal (or at least functioning) part of the public stream client code. I get:

Mar 24 13:05:57 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] mopidy_soundcloud.soundcloud Parsing track soundcloud:song/Disappear.284103524
Mar 24 13:05:57 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] mopidy_soundcloud.soundcloud Getting info for track with ID 284103524
Mar 24 13:05:57 raspberrypi mopidy[30917]: DEBUG    [MainThread] mopidy.audio.gst Got STATE_CHANGED bus message: old=GST_STATE_NULL new=GST_STATE_READY pending=GST_STATE_VOID_PENDING
Mar 24 13:05:58 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://api.soundcloud.com:443 "GET /tracks/284103524 HTTP/1.1" 200 1039
Mar 24 13:05:58 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] mopidy_soundcloud.soundcloud Requested https://api.soundcloud.com/tracks/284103524
Mar 24 13:05:58 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool Starting new HTTPS connection (1): soundcloud.com:443
Mar 24 13:05:58 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://soundcloud.com:443 "GET / HTTP/1.1" 200 None
Mar 24 13:05:59 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool Starting new HTTPS connection (1): a-v2.sndcdn.com:443
Mar 24 13:05:59 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://a-v2.sndcdn.com:443 "GET /assets/53-aed4402d.js HTTP/1.1" 200 None
Mar 24 13:05:59 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://a-v2.sndcdn.com:443 "GET /assets/51-f3c4bf71.js HTTP/1.1" 200 None
Mar 24 13:05:59 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool Starting new HTTPS connection (1): cdn.cookielaw.org:443
Mar 24 13:05:59 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://cdn.cookielaw.org:443 "GET /consent/7e62c772-c97a-4d95-8d0a-f99bbeadcf61/otSDKStub.js HTTP/1.1" 200 7684
Mar 24 13:05:59 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://a-v2.sndcdn.com:443 "GET /assets/16-c0f3e8c3.js HTTP/1.1" 200 None
Mar 24 13:05:59 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://a-v2.sndcdn.com:443 "GET /assets/52-dacb4af2.js HTTP/1.1" 200 None
Mar 24 13:05:59 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://a-v2.sndcdn.com:443 "GET /assets/1-ac706f12.js HTTP/1.1" 200 None
Mar 24 13:06:00 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://a-v2.sndcdn.com:443 "GET /assets/3-0b89809f.js HTTP/1.1" 200 None
Mar 24 13:06:00 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] mopidy_soundcloud.soundcloud Updated SoundCloud public client id to: RMDIzNoU4QIzQsT3xq9J5TdxFFQlJvLY
Mar 24 13:06:00 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://soundcloud.com:443 "GET /young-legionnaire/disappear-1 HTTP/1.1" 200 None
Mar 24 13:06:00 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool Starting new HTTPS connection (1): api-v2.soundcloud.com:443
Mar 24 13:06:00 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://api-v2.soundcloud.com:443 "GET /media/soundcloud:tracks:284103524/6e05c0df-dac1-47c5-900c-37e8a738480b/stream/progressive?client_id=RMDIzNoU4QIzQsT3xq9J5TdxFFQlJvLY HTTP/1.1" 403 28
Mar 24 13:06:00 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://soundcloud.com:443 "GET / HTTP/1.1" 200 None
Mar 24 13:06:01 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://a-v2.sndcdn.com:443 "GET /assets/53-aed4402d.js HTTP/1.1" 200 None
Mar 24 13:06:01 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://a-v2.sndcdn.com:443 "GET /assets/51-f3c4bf71.js HTTP/1.1" 200 None
Mar 24 13:06:01 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://cdn.cookielaw.org:443 "GET /consent/7e62c772-c97a-4d95-8d0a-f99bbeadcf61/otSDKStub.js HTTP/1.1" 200 7684
Mar 24 13:06:01 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://a-v2.sndcdn.com:443 "GET /assets/16-c0f3e8c3.js HTTP/1.1" 200 None
Mar 24 13:06:01 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://a-v2.sndcdn.com:443 "GET /assets/52-dacb4af2.js HTTP/1.1" 200 None
Mar 24 13:06:01 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://a-v2.sndcdn.com:443 "GET /assets/1-ac706f12.js HTTP/1.1" 200 None
Mar 24 13:06:01 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://a-v2.sndcdn.com:443 "GET /assets/3-0b89809f.js HTTP/1.1" 200 None
Mar 24 13:06:01 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] mopidy_soundcloud.soundcloud Updated SoundCloud public client id to: RMDIzNoU4QIzQsT3xq9J5TdxFFQlJvLY
Mar 24 13:06:02 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] urllib3.connectionpool https://api-v2.soundcloud.com:443 "GET /media/soundcloud:tracks:284103524/6e05c0df-dac1-47c5-900c-37e8a738480b/stream/progressive?client_id=RMDIzNoU4QIzQsT3xq9J5TdxFFQlJvLY HTTP/1.1" 200 547
Mar 24 13:06:02 raspberrypi mopidy[30917]: DEBUG    [SoundCloudBackend-4] mopidy.backend Backend translated URI from soundcloud:song/Disappear.284103524 to https://cf-media.sndcdn.com/FdsWYJXWHnVP.128.mp3?Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiKjovL2NmLW1lZGlhLnNuZGNkbi5jb20vRmRzV1lKWFdIblZQLjEyOC5tcDMqIiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNjc5NjYzNDg1fX19XX0_&Signature=VysjZz98E8-7--aJYOj2zUC5kCi544NKKCJB~ToapCj3WOBvLgefWS1037g4yx55XL~NycT4cuRhOAeDxHK9Mge6-3pdZws-aUHne2esNA4f~C2H5LFwcG75rn9JXdKrZ1yLri77jLaK~MT3nua7RVBrpRFCNGdWRK-npe84qVUBxAUqxsDyEIutx9-PH~MufHWu0LWRYP8HmlNS5efyYaFCwSqeMHxpJHTyYqSzteKaAe3CFEVEPGbP6WiMBeJljlwtv1-yOo2ds4SeVR~oLGZD33tjckEE3zOJoF8q0IfW1HhEtHr8lsIXJ8QlnunMVGXiWCJZD6Sycabo-~59wQ__&Key-Pair-Id=APKAI6TU7MMXM5DG6EPQ

But I agree it looks fishy. https://cdn.cookielaw.org:443 "GET /consent/7e62c772-c97a-4d95-8d0a-f99bbeadcf61/otSDKStub.js sounds interesting. The error reporting for this should be better, that is for sure.

@blacklight
Copy link

blacklight commented Mar 24, 2023

Hmm I think I know why.

Your log traces look the same as mine for the first part, but I don't get beyond the GET to cdn.cookielaw.org part.

And that's most likely because I use PiHole on my network, which redirects all the requests to that domain to localhost (I just don't like being harassed by cookie banners).

So it seems like the original request to SoundCloud at some point triggers a request to cookielaw.org, which fails, and therefore the whole parsing logic fails.

First of all, it'd be interesting to know why a backend request gets a redirect to cookielaw.org - as my voice assistant would say, "I can't show you a banner, I don't have a screen!".

Secondly, maybe it's worth skipping those connections on the extension's side as well, if at some point we get that redirect?

A workaround for now can be to whitelist cdn.cookielaw.org on my DNS and block it on the frontend side via NoScript instead, but it's probably worth skipping that logic entirely on the backend (or at least not make the upstream request fail if that particular request fails), since it's not functional to the purpose of the operation.

EDIT

I've done a quick test by whitelisting the domain on my DNS and things are working now - so that was indeed the issue.

@kingosticks
Copy link
Member Author

kingosticks commented Mar 24, 2023

I was just going to ask if you have an ad blocker!

The "public stream client" code scrapes Soundcloud's regular web page using Beautiful Soup, that'll be following all the script links and so requesting this one too. I don't know how Beautiful Soup Requests would know to ignore this particular script as a potential fix. And anything it did to pretend it wasn't a "real" browser would defeat the point of this.

But what I don't understand yet is, why doesn't it fall back to the (long-suffering rate limited) API method in this case?

EDIT: Requests grabs the data, BS just parses it.

@blacklight
Copy link

blacklight commented Mar 24, 2023

why doesn't it fall back to the (long-suffering rate limited) API method in this case?

That's a good question - I guess the fallback logic isn't really working as expected in this case.

So from what I understand BS parses the web page, it extracts all the <script> tags on that page and it recursively follows them, and then Requests does the job of fetching them.

If that's the case, would it maybe make sense to check if cdn.cookielaw.org has a <script> tag and just filter it out from the scraping logic?

Alternatively, if we get onto that domain through a redirect, maybe calling requests.get with allow_redirects=False can work?

@kingosticks
Copy link
Member Author

Maybe, but only until they change cdn.cookielaw.org to cdn1.cookielaw.org. And what if there was some external JS that was required (maybe updating the page contents to provide the data we are trying to extract)? I'm not saying these are not good ideas, I am just pointing out it's all a bit brittle.

I think the first thing would be to make the fallback more reliable. In your case, I assume it gets an empty 200 response for that page and then should just carry on as usual. I don't have time to look into this but I will review and merge a fix.

@blacklight
Copy link

In your case, I assume it gets an empty 200 response for that page and then should just carry on as usual.

It's more like a 404 in my case - because the domain redirects to localhost and I have a web server running on it. Otherwise, it would just be a timed out request. Maybe it's worth checking if any of the nested requests fail, and if those are associated to static files (like images and .js) perhaps the logic should just move on?

@kingosticks
Copy link
Member Author

kingosticks commented Mar 24, 2023

Ahh ok so it's trying to update the public client_id that's needed when making requests to https://api-v2.soundcloud.com/foo for foo streams it just scraped from the public page (i.e,. not from API calls).

In my case it finds the client_id in <script crossorigin src="[https://a-v2.sndcdn.com/assets/3-0b89809f.js](view-source:https://a-v2.sndcdn.com/assets/3-0b89809f.js)"></script>. In your case the blocked request must be causing an exception which is silently caught by

try:
return self.parse_track(self._get(f"tracks/{track_id}"), streamable)
except Exception:
return None
.

except Exception: is never a good idea. Especially for exceptions that have bubbled up from the deep! Maybe we should use https://pypi.org/project/flake8-blind-except/

@kingosticks
Copy link
Member Author

So, We should
a) catch the exceptions properly and generally handle errors better in this code
b) possibly ignore cdn.cookielaw.org? It might stop being useful but I can't imagine it'll ever break anything,

@blacklight
Copy link

I completely agree on (at the very least) log the exception instead of silently swallowing it - that would have definitely saved me some debugging time.

It sounds to me like some of the JS is actually required, so my initial idea of just skipping <script> URLs may not work.

Skipping cdn.cookielaw.org sounds like a sensible option, but I agree with you that it may also be a brittle one - all it takes is a domain name to change to throw a wrench in the logic.

If the extension only needs to scrape the page's static JS because it needs a particular one (the sndcdn.com link that contains the client_id) then maybe it can also make sense to just look for a <script> tag that matches the criteria, instead of downloading all of them?

@kingosticks
Copy link
Member Author

We could only download scripts from sndcdn.com (there are a bunch), but again, that domain could change and then it would be broken. Unfortunately, other than this cookie one, the scripts mostly look the same and if we decide on some arbitrary criteria that works today it could easily be wrong tomorrow. I think as long as we handle (and log) errored requests we'll be in much better shape. I'll hack a fix in and make an issue to fix it properly. Anyone else that hits this is very welcome to take it on.

wallon-ines pushed a commit to wallon-ines/mopidy-soundcloud that referenced this issue May 6, 2023
@Goosegit11
Copy link

Goosegit11 commented Dec 9, 2023

Search is working for me, but playing tracks are not... Running these versions (I think they are the latest):

Mopidy                          3.4.1
Mopidy-MPD                      3.3.0
Mopidy-SoundCloud               3.0.2

Log:

INFO     2023-12-09 03:05:00,858 [1342184:MpdSession-14 (_actor_loop)] mopidy_mpd.session
  New MPD connection from [::ffff:127.0.0.1]:46502
ERROR    2023-12-09 03:05:09,424 [1342184:Core-7 (_actor_loop)] mopidy.core.library
  FileBackend backend returned bad data: Expected a SearchResult instance, not []
ERROR    2023-12-09 03:05:09,424 [1342184:Core-7 (_actor_loop)] mopidy.core.library
  StreamBackend backend returned bad data: Expected a SearchResult instance, not []
INFO     2023-12-09 03:05:09,425 [1342184:SoundCloudBackend-6 (_actor_loop)] mopidy_soundcloud.library
  Searching SoundCloud for: серега
WARNING  2023-12-09 03:05:23,179 [1342184:Core-7 (_actor_loop)] mopidy.core.tracklist
  Track is not playable: soundcloud:song/-.1131515467
WARNING  2023-12-09 03:05:30,916 [1342184:Core-7 (_actor_loop)] mopidy.core.tracklist
  Track is not playable: soundcloud:song/-.1131515467
WARNING  2023-12-09 03:05:31,910 [1342184:Core-7 (_actor_loop)] mopidy.core.tracklist
  Track is not playable: soundcloud:song/-.1131515467
WARNING  2023-12-09 03:05:32,382 [1342184:Core-7 (_actor_loop)] mopidy.core.tracklist
  Track is not playable: soundcloud:song/-.1131515467
WARNING  2023-12-09 03:05:32,836 [1342184:Core-7 (_actor_loop)] mopidy.core.tracklist
  Track is not playable: soundcloud:song/-.1131515467
WARNING  2023-12-09 03:05:33,250 [1342184:Core-7 (_actor_loop)] mopidy.core.tracklist
  Track is not playable: soundcloud:song/-.1131515467
WARNING  2023-12-09 03:05:33,656 [1342184:Core-7 (_actor_loop)] mopidy.core.tracklist
  Track is not playable: soundcloud:song/-.1131515467

UPD:
After reading @blacklight post more carefully, it dawned on me - Russia has blocked SoundCloud.
(oddly enough - the search works, so I thought it was some SoundCloud API problems again..)

proxychains mopidy works, although it has some latency issues, but it's tolerable 👍

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests