implement rate limiting for spotify - issue #15

Esse commit está contido em:
fossfreedom
2014-07-09 23:22:31 +01:00
commit a09e5414e4
5 arquivos alterados com 40 adições e 58 exclusões
+4 -3
Ver Arquivo
@@ -50,16 +50,17 @@ v1.1
- removed Discogs since they now require oauth2 support
- add Spotify as an coverart provider
- fix bug to carry on search after binning poor MusicBrainz image download
- restructure rate-limits to ensure faster downloads whilst keeping to providers rate-limits
Recommended order for Search Providers
- embedded coverart
- coverart in the track song folder
- local cache search (~/.cache/rhythmbox/covers)
- LastFM (use the LastFM plugin to login)
- MusicBrainz
- Spotify
- Cover Art Archive
- MusicBrainz
- LastFM (use the LastFM plugin to login)
- Spotify
*How to install - Rhythmbox 2.96 to 2.99.1:*
+27 -39
Ver Arquivo
@@ -62,7 +62,24 @@ SPOTIFY_API_URL = "https://api.spotify.com/v1/"
def file_root (f_name):
return os.path.splitext (f_name)[0].lower ()
class BaseSearch(object):
def __init__(self):
self.current_time = time.time()
def rate_limit(self, callback_func, args, per_second_rate):
print ("rate_limit")
diff = time.time() - self.current_time
if diff < (1.0 / per_second_rate):
#Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE,
# int((1.0 / per_second_rate) *100), delay, None)
time.sleep( (1.0 / per_second_rate) - diff)
print ("sleeping")
callback_func( *args )
self.current_time = time.time()
class CoverSearch(object):
def __init__(self, store, key, last_time, searches):
self.store = store
@@ -105,7 +122,7 @@ class CoverSearch(object):
class CoverAlbumSearch:
def __init__ (self):
self.current_time = time.time()
pass
def finished(self, results):
parent = self.file.get_parent()
@@ -162,12 +179,6 @@ class CoverAlbumSearch:
def search (self, key, last_time, store, callback, args):
if time.time() - self.current_time < 1:
#enforce 1 second delay between requests otherwise musicbrainz will reject calls
time.sleep(1)
self.current_time = time.time()
# ignore last_time
print("calling search")
location = key.get_info("location")
@@ -313,9 +324,6 @@ class DiscogsSearch (object):
return False
def search(self, key, last_time, store, callback, args):
#if last_time > (time.time() - REPEAT_SEARCH_PERIOD):
# callback (True)
# return
album = key.get_field("album")
artists = key.get_field_values("artist")
@@ -377,10 +385,10 @@ class CoverartArchiveSearch(object):
loader = rb.Loader()
loader.get_url(url, self.get_release_cb, (key, store, callback, args))
class SpotifySearch (object):
class SpotifySearch (BaseSearch):
def __init__(self):
self.current_time = time.time()
super(SpotifySearch, self).__init__()
def search_url (self, artist, album):
# Remove variants of Disc/CD [1-9] from album title before search
orig_album = album
@@ -410,29 +418,17 @@ class SpotifySearch (object):
encoded = data.decode(encoding)
json_data = json.loads(encoded)
print (json_data['albums'])
print (json_data['albums']['items'])
albums = json_data['albums']['items']
print (albums)
for album in albums:
print (album)
print (album['name'])
print (album_name)
if album['name'] in album_name or \
album_name in album['name']:
print ('matching album names')
print (album['images'])
print (album['images'][0])
url = album['images'][0]['url']
print (url)
self.store.store_uri(self.current_key, RB.ExtDBSourceType.SEARCH, url)
self.callback(False)
print ('exited')
return
print ('getting next search')
self.search_next()
def search_next (self):
@@ -440,30 +436,22 @@ class SpotifySearch (object):
self.callback(True)
print ('no more searches')
return
print ("search_next")
print (self.searches)
(artist, album) = self.searches.pop(0)
self.current_key = RB.ExtDBKey.create_storage("album", album)
key_artist = self.key.get_field("artist")
if key_artist is not None:
if key_artist is None:
self.current_key.add_field("artist", artist)
print("####artist")
print(artist)
else:
self.current_key.add_field("artist", key_artist)
url = self.search_url(artist, album)
l = rb.Loader()
l.get_url(url, self.album_info_cb, album)
self.rate_limit( l.get_url, (url, self.album_info_cb, album), 2 )
def search(self, key, last_time, store, callback, args):
if time.time() - self.current_time < 1:
#enforce 0.5 second delay between requests otherwise spotify will reject calls
time.sleep(0.5)
self.current_time = time.time()
album = key.get_field("album")
artists = key.get_field_values("artist")
self.key = key
+2 -2
Ver Arquivo
@@ -242,11 +242,11 @@ class SearchPreferences(GObject.Object, PeasGtk.Configurable):
self.provider[self.EMBEDDED_SEARCH] = _("Embedded coverart")
self.provider[self.LOCAL_SEARCH] = _("Local folder coverart")
self.provider[self.CACHE_SEARCH] = _("Cached coverart")
self.provider[self.LASTFM_SEARCH] = _("LastFM Internet Provider")
self.provider[self.COVERARTARCHIVE_SEARCH] = _("Coverart Archive Internet Provider")
self.provider[self.MUSICBRAINZ_SEARCH] = _("MusicBrainz Internet Provider")
self.provider[self.LASTFM_SEARCH] = _("LastFM Internet Provider")
self.provider[self.SPOTIFY_SEARCH] = _("Spotify Internet Provider")
#self.provider[self.DISCOGS_SEARCH] = _("Discogs Internet Provider")
self.provider[self.COVERARTARCHIVE_SEARCH] = _("Coverart Archive Internet Provider")
current_providers = copy.deepcopy(self.provider)
+6 -10
Ver Arquivo
@@ -27,6 +27,7 @@
import xml.dom.minidom as dom
import re
import rb3compat
from coverart_album_search import BaseSearch
if rb3compat.PYVER >= 3:
import configparser
@@ -77,9 +78,9 @@ def user_has_account():
except:
return False
class LastFMSearch (object):
class LastFMSearch (BaseSearch):
def __init__(self):
pass
super(LastFMSearch, self).__init__()
def search_url (self, artist, album, album_mbid):
# Remove variants of Disc/CD [1-9] from album title before search
@@ -157,11 +158,10 @@ class LastFMSearch (object):
(artist, album, album_mbid) = self.searches.pop(0)
self.current_key = RB.ExtDBKey.create_storage("album", album)
key_artist = self.key.get_field("artist")
if key_artist is not None:
if key_artist is None:
self.current_key.add_field("artist", artist)
print("####artist")
print(artist)
else:
self.current_key.add_field("artist", key_artist)
url = self.search_url(artist, album, album_mbid)
@@ -170,10 +170,6 @@ class LastFMSearch (object):
def search(self, key, last_time, store, callback, args):
if last_time > (time.time() - REPEAT_SEARCH_PERIOD):
print("we already tried this one")
callback (True)
return
if user_has_account() == False:
print("can't search: no last.fm account details")
+1 -4
Ver Arquivo
@@ -126,10 +126,7 @@ class MusicBrainzSearch(object):
loader.get_url(url, self.get_release_cb, (key, store, callback, args))
def search(self, key, last_time, store, callback, *args):
if time.time() - self.current_time < 1:
#enforce 1 second delay between requests otherwise musicbrainz will reject calls
time.sleep(1)
self.current_time = time.time()
key = key.copy() # ugh