]> 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'
 
 
 __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 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 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)
 # 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
 
 
 class XmlFMError(Exception):  # Errors
@@ -107,49 +100,28 @@ class XmlFMTimeOut(XmlFMError):
         self.expression = (message)
 
 
         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():
     """
     """
 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&' +\
     request = dict({'similar': '?method=artist.getsimilar&artist=%s&' +\
-                                'api_key=%s' % api_key,
+                                'api_key={apikey}'.format(**LFM),
                     'top': '?method=artist.gettoptracks&artist=%s&' +\
                     'top': '?method=artist.gettoptracks&artist=%s&' +\
-                            'api_key=%s' % api_key,
+                                'api_key={apikey}'.format(**LFM),
                     'track': '?method=track.getsimilar&artist=%s' +\
                     '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' +\
                     '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()
                     })
     cache = dict({})
     timestamp = datetime.utcnow()
@@ -177,6 +149,10 @@ class SimaFM():
             return
         self._fetch_lfm()
 
             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"""
     @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:
             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.
 
     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 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):
             raise XmlFMNotFound(errormsg)
 
     def _controls_artist(self, artist):
@@ -250,6 +223,21 @@ class SimaFM():
             if now - timestamp > delta:
                 cache.pop(url)
 
             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):
         """
         """
     def get_similar(self, artist=None):
         """
         """