Skip to content

Commit

Permalink
Avoid rate limit by reducing requests to track stream endpoint.
Browse files Browse the repository at this point in the history
Combine the request for finding if stream is playable with the
request for the actual stream URI. This should help with mopidy#99.
  • Loading branch information
kingosticks committed Mar 23, 2018
1 parent 7f5ed75 commit 64eee31
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 9 deletions.
18 changes: 11 additions & 7 deletions mopidy_soundcloud/soundcloud.py
Expand Up @@ -30,6 +30,10 @@ def readable_url(uri):
''.join(c for c in safe_uri if c in valid_chars)).strip()


def streamble_url(url, client_id):
return '%s?client_id=%s' % (url, client_id)


class cache(object):
# TODO: merge this to util library

Expand Down Expand Up @@ -244,12 +248,12 @@ def parse_track(self, data, remote_url=False):
track_kwargs[b'date'] = data['date']

if remote_url:
if not self.can_be_streamed(data['stream_url']):
track_kwargs[b'uri'] = self.get_streamble_url(data['stream_url'])
if track_kwargs[b'uri'] is None:
logger.info(
"'%s' can't be streamed from SoundCloud" % data.get(
'title'))
return None
track_kwargs[b'uri'] = self.get_streamble_url(data['stream_url'])
else:
track_kwargs[b'uri'] = 'soundcloud:song/%s.%s' % (
readable_url(data.get('title')), data.get('id')
Expand All @@ -276,12 +280,12 @@ def parse_track(self, data, remote_url=False):
return track

@cache()
def can_be_streamed(self, url):
req = self.http_client.head(self.get_streamble_url(url))
return req.status_code == 302

def get_streamble_url(self, url):
return '%s?client_id=%s' % (url, self.CLIENT_ID)
req = self.http_client.head(streamble_url(url, self.CLIENT_ID))
if req.status_code == 302:
return req.headers.get('Location', None)
elif req.status_code == 429:
logger.info('SoundCloud daily rate limit exceeded')

def resolve_tracks(self, track_ids):
"""Resolve tracks concurrently emulating browser
Expand Down
12 changes: 10 additions & 2 deletions tests/test_api.py
Expand Up @@ -108,6 +108,14 @@ def test_resolves_stream_track(self):
self.assertIsInstance(track, Track)
self.assertEquals(
track.uri,
'https://api.soundcloud.com/tracks/'
'13158665/stream?client_id=93e33e327fd8a9b77becd179652272e2'
'https://cf-media.sndcdn.com/fxguEjG4ax6B.128.mp3?Policy=eyJTdGF0ZW'
'1lbnQiOlt7IlJlc291cmNlIjoiKjovL2NmLW1lZGlhLnNuZGNkbi5jb20vZnhndUVq'
'RzRheDZCLjEyOC5tcDMiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUz'
'pFcG9jaFRpbWUiOjE0Nzc2MDA1NTd9fX1dfQ__&Signature=u9bxAkZOtTTF1VqTm'
'LGmw3ENrqbiSTFK-sMvZL-ZsQK85DOepHh5MfPA4MNooszUy~PZqiVyBn4YnElhWyb'
'~4B7kS6y0VZ6t-qF78CfTMOimemafpqfWJ8nYXczhM9pUpAwiS--lkNjGks4Qxi-FZ'
'JDBPG99gAIU0eVW78CADcpuOKLugGpzHl6gRPN2Z4zZ9dVujZ5MlG2OWnPuNiBcE~w'
'UFwcOxt9N6ePTff-wMFQR2PGpEK6wc6bWuB4WFNBkE0bmEke4cOQjWHa5FwYEidZN5'
'rvv5lVT1r07zzifnADEipwMaZ2-QYdqzOYaM4jymFDhl7DklaU24PY5C5mH0A__&Ke'
'y-Pair-Id=APKAJAGZ7VMH2PFPW6UQ'
)

0 comments on commit 64eee31

Please sign in to comment.