]> kaliko git repositories - mpd-sima.git/blobdiff - sima/lib/simafm.py
Add toptrack method for Last.fm webservice
[mpd-sima.git] / sima / lib / simafm.py
index 5dafd2ce007890d576160b5fd7af63cdd600787c..8d82d52ccc90798b4a933d53a7f3737fc4945423 100644 (file)
@@ -25,12 +25,12 @@ __version__ = '0.5.1'
 __author__ = 'Jack Kaliko'
 
 
-from datetime import datetime, timedelta
 
 from requests import Session, Request, Timeout, ConnectionError
 
-from sima import LFM
+from sima import LFM, SOCKET_TIMEOUT, WAIT_BETWEEN_REQUESTS
 from sima.lib.meta import Artist
+from sima.lib.track import Track
 
 from sima.lib.http import CacheController
 from sima.utils.utils import WSError, WSNotFound, WSTimeout, WSHTTPError
@@ -38,10 +38,6 @@ from sima.utils.utils import getws, Throttle
 if len(LFM.get('apikey')) == 43:  # simple hack allowing imp.reload
     getws(LFM)
 
-# Some definitions
-WAIT_BETWEEN_REQUESTS = timedelta(0, 2)
-SOCKET_TIMEOUT = 6
-
 
 class SimaFM:
     """Last.fm http client
@@ -49,9 +45,12 @@ class SimaFM:
     root_url = 'http://{host}/{version}/'.format(**LFM)
     ratelimit = None
     name = 'Last.fm'
-    cache = {}
+    cache = False
+    stats = {'etag':0,
+            'ccontrol':0,
+            'total':0}
 
-    def __init__(self, cache=True):
+    def __init__(self):
         self.controller = CacheController(self.cache)
         self.artist = None
 
@@ -62,9 +61,11 @@ class SimaFM:
         """
         req = Request('GET', SimaFM.root_url, params=payload,
                       ).prepare()
+        SimaFM.stats.update(total=SimaFM.stats.get('total')+1)
         if self.cache:
             cached_response = self.controller.cached_request(req.url, req.headers)
             if cached_response:
+                SimaFM.stats.update(ccontrol=SimaFM.stats.get('ccontrol')+1)
                 return cached_response.json()
         try:
             return self._fetch_ws(req)
@@ -79,8 +80,10 @@ class SimaFM:
         """fetch from web service"""
         sess = Session()
         resp = sess.send(prepreq, timeout=SOCKET_TIMEOUT)
-        #self.__class__.ratelimit = resp.headers.get('x-ratelimit-remaining', None)
-        if resp.status_code is not 200:
+        if resp.status_code == 304:
+            SimaFM.stats.update(etag=SimaFM.stats.get('etag')+1)
+            resp = self.controller.update_cached_response(prepreq, resp)
+        elif resp.status_code != 200:
             raise WSHTTPError('{0.status_code}: {0.reason}'.format(resp))
         ans = resp.json()
         self._controls_answer(ans)
@@ -120,7 +123,9 @@ class SimaFM:
         payload.update(results=100)
         if method == 'track':
             payload.update(track=track)
-        return payload
+        # > hashing the URL into a cache key
+        # return a sorted list of 2-tuple to have consistent cache
+        return sorted(payload.items(), key=lambda param: param[0])
 
     def get_similar(self, artist=None):
         """Fetch similar artists
@@ -140,6 +145,26 @@ class SimaFM:
         for art in ans.get('similarartists').get('artist'):
             yield Artist(name=art.get('name'), mbid=art.get('mbid', None))
 
+    def get_toptrack(self, artist=None):
+        """Fetch artist top tracks
+        """
+        payload = self._forge_payload(artist, method='top')
+        ans = self._fetch(payload)
+        tops = ans.get('toptracks').get('track')
+        art = {
+                'artist': artist.name,
+                'musicbrainz_artistid': artist.mbid,
+                }
+        for song in tops:
+            for key in ['artist', 'streamable', 'listeners',
+                        'url', 'image', '@attr']:
+                if key in song:
+                    song.pop(key)
+            song.update(art)
+            song.update(title=song.pop('name'))
+            song.update(time=song.pop('duration'))
+            yield Track(**song)
+        #return tops
 
 # VIM MODLINE
 # vim: ai ts=4 sw=4 sts=4 expandtab