]> kaliko git repositories - mpd-sima.git/blobdiff - sima/lib/simafm.py
Move Cache & Throttle to utils
[mpd-sima.git] / sima / lib / simafm.py
index 12ca0d5c4a1547bd50f8a7d3c345f02dd08da4fe..170488b9ad00f1f6ad9fe05d7709c3ba0a2d6c05 100644 (file)
@@ -23,7 +23,7 @@ Consume last.fm web service
 
 """
 
-__version__ = '0.3.0'
+__version__ = '0.4.0'
 __author__ = 'Jack Kaliko'
 
 
@@ -32,24 +32,17 @@ import urllib.request, urllib.error, urllib.parse
 from datetime import datetime, timedelta
 from http.client import BadStatusLine
 from socket import timeout as SocketTimeOut
-from time import sleep
 from xml.etree.cElementTree import ElementTree
 
+from request import get
+
+from sima import LFM
+from sima.utils.utils import getws, Throttle, Cache
+if len(LFM.get('apikey')) == 43:  # simple hack allowing imp.reload
+    getws(LFM)
+
 # Some definitions
 WAIT_BETWEEN_REQUESTS = timedelta(0, 0.4)
-LFM_ERRORS = dict({'2': 'Invalid service -This service does not exist',
-    '3': 'Invalid Method - No method with that name in this package',
-    '4': 'Authentication Failed - You do not have permissions to access the service',
-    '5': "'Invalid format - This service doesn't exist in that format",
-    '6': 'Invalid parameters - Your request is missing a required parameter',
-    '7': 'Invalid resource specified',
-    '9': 'Invalid session key - Please re-authenticate',
-    '10': 'Invalid API key - You must be granted a valid key by last.fm',
-    '11': 'Service Offline - This service is temporarily offline. Try again later.',
-    '12': 'Subscription Error - The user needs to be subscribed in order to do that',
-    '13': 'Invalid method signature supplied',
-    '26': 'Suspended API key - Access for your account has been suspended, please contact Last.fm',
-    })
 
 
 class XmlFMError(Exception):  # Errors
@@ -107,49 +100,28 @@ class XmlFMTimeOut(XmlFMError):
         self.expression = (message)
 
 
-class Throttle():
-    def __init__(self, wait):
-        self.wait = wait
-        self.last_called = datetime.now()
-
-    def __call__(self, func):
-        def wrapper(*args, **kwargs):
-            while self.last_called + self.wait > datetime.now():
-                #print('waiting…')
-                sleep(0.1)
-            result = func(*args, **kwargs)
-            self.last_called = datetime.now()
-            return result
-        return wrapper
-
-
-class AudioScrobblerCache():
-    def __init__(self, elem, last):
-        self.elemtree = elem
-        self.requestdate = last
-
-    def created(self):
-        return self.requestdate
-
-    def gettree(self):
-        return self.elemtree
-
-
 class SimaFM():
     """
     """
-    api_key = '4a1c9ddec29816ed803d7be9113ba4cb'
-    host = 'ws.audioscrobbler.com'
-    version = '2.0'
-    root_url = 'http://%s/%s/' % (host, version)
+    root_url = 'http://{host}/{version}/'.format(**LFM)
     request = dict({'similar': '?method=artist.getsimilar&artist=%s&' +\
-                                'api_key=%s' % api_key,
+                                'api_key={apikey}'.format(**LFM),
                     'top': '?method=artist.gettoptracks&artist=%s&' +\
-                            'api_key=%s' % api_key,
+                                'api_key={apikey}'.format(**LFM),
                     'track': '?method=track.getsimilar&artist=%s' +\
-                            '&track=%s' + '&api_key=%s' % api_key,
+                            '&track=%s' + 'api_key={apikey}'.format(**LFM),
                     'info': '?method=artist.getinfo&artist=%s' +\
-                            '&api_key=%s' % api_key,
+                            'api_key={apikey}'.format(**LFM),
+                    })
+    payloads = dict({'similar': {'method':'artist.getsimilar',
+                                'artist':None, 'api_key':LFM.get('apikey'),},
+                    'top': {'method':'artist.gettoptracks',
+                            'artist':None, 'api_key':LFM.get('apikey'),},
+                    'track': {'method':'track.getsimilar',
+                              'artist':None, 'track':None,
+                              'api_key':LFM.get('apikey'),},
+                    'info': {'method':'artist.getinfo', 'artist':None,
+                             'api_key':LFM.get('apikey'),},
                     })
     cache = dict({})
     timestamp = datetime.utcnow()
@@ -177,6 +149,10 @@ class SimaFM():
             return
         self._fetch_lfm()
 
+    @Throttle(WAIT_BETWEEN_REQUESTS)
+    def _fetch_ws(self):
+        pass
+
     @Throttle(WAIT_BETWEEN_REQUESTS)
     def _fetch_lfm(self):
         """Get artists, fetch xml from last.fm"""
@@ -211,8 +187,7 @@ class SimaFM():
             fd.close()
         self._controls_lfm_answer()
         if self.caching:
-            SimaFM.cache[self._url] = AudioScrobblerCache(self.current_element,
-                    datetime.utcnow())
+            SimaFM.cache[self._url] = Cache(self.current_element)
 
     def _controls_lfm_answer(self):
         """Controls last.fm answer.
@@ -223,8 +198,6 @@ class SimaFM():
         if status == 'failed':
             error = self.current_element.find('error').attrib.get('code')
             errormsg = self.current_element.findtext('error')
-            #if error in LFM_ERRORS.keys():
-            #    print LFM_ERRORS.get(error)
             raise XmlFMNotFound(errormsg)
 
     def _controls_artist(self, artist):
@@ -250,6 +223,21 @@ class SimaFM():
             if now - timestamp > delta:
                 cache.pop(url)
 
+    def get_similar_ng(self, artist=None):
+        """
+        """
+        self._controls_artist(artist)
+        # Construct URL
+        self._req = get(SimaFM.root_url, params=None, timeout=5)
+        self._url = req.url
+        if self._is_in_cache():
+            self.current_element = SimaFM.cache.get(self._url).gettree()
+        else:
+            self._fetch_ws()
+        elem = self.current_element
+        for art in elem.getiterator(tag='artist'):
+            yield str(art.findtext('name')), 100 * float(art.findtext('match'))
+
     def get_similar(self, artist=None):
         """
         """