Skip to content

Commit

Permalink
Add get_images support
Browse files Browse the repository at this point in the history
  • Loading branch information
adamcik committed Mar 23, 2015
1 parent 2498c85 commit 74ac793
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ v1.3.0 (UNRELEASED)

- Update to work with new playback API in Mopidy 1.0.

- Add ``get_images`` support for coverart in updated clients.

v1.2.0 (2014-07-21)
-------------------

Expand Down
96 changes: 96 additions & 0 deletions mopidy_spotify/images.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
from __future__ import unicode_literals

import itertools
import json
import logging
import operator
import urllib2
import urlparse

from mopidy import models
from mopidy.utils import encoding

# NOTE: This module is independent of libspotify and built using the Spotify
# Web APIs. As such it does not tie in with any of the regular code used
# elsewhere in the mopidy-spotify extensions. It is also intended to be used
# across both the 1.x and 2.x versions.

_API_MAX_IDS_PER_REQUEST = 50
_API_BASE_URI = 'https://api.spotify.com/v1/%ss/?ids=%s'

_cache = {} # (type, id) -> [Image(), ...]

logger = logging.getLogger(__name__)


def get_images(uris):
result = {}
uri_type_getter = operator.itemgetter('type')
uris = sorted((_parse_uri(u) for u in uris), key=uri_type_getter)
for uri_type, group in itertools.groupby(uris, uri_type_getter):
batch = []
for uri in group:
if uri['key'] in _cache:
result[uri['uri']] = _cache[uri['key']]
elif len(batch) < _API_MAX_IDS_PER_REQUEST:
batch.append(uri)
else:
result.update(_process_uris(uri_type, batch))
batch = []
result.update(_process_uris(uri_type, batch))
return result


def _parse_uri(uri):
parsed_uri = urlparse.urlparse(uri)
uri_type, uri_id = None, None

if parsed_uri.scheme == 'spotify':
uri_type, uri_id = parsed_uri.path.split(':')[:2]
elif parsed_uri.scheme in ('http', 'https'):
if parsed_uri.netloc in ('open.spotify.com', 'play.spotify.com'):
uri_type, uri_id = parsed_uri.path.split('/')[1:3]

if uri_type and uri_type in ('track', 'album', 'artist') and uri_id:
return {'uri': uri, 'type': uri_type, 'id': uri_id,
'key': (uri_type, uri_id)}

raise ValueError('Could not parse %r as a spotify URI' % uri)


def _process_uris(uri_type, uris):
result = {}
ids_to_uris = {u['id']: u for u in uris}

if not uris:
return result

try:
lookup_uri = _API_BASE_URI % (uri_type, ','.join(ids_to_uris.keys()))
data = json.load(urllib2.urlopen(lookup_uri))
except (ValueError, IOError) as e:
error_msg = encoding.locale_decode(e)
logger.debug('Fetching %s failed: %s', lookup_uri, error_msg)
return result

for item in data.get(uri_type + 's', []):
if not item:
continue
uri = ids_to_uris[item['id']]
if uri['key'] not in _cache:
if uri_type == 'track':
album_key = _parse_uri(item['album']['uri'])['key']
if album_key not in _cache:
_cache[album_key] = tuple(
_translate_image(i) for i in item['album']['images'])
_cache[uri['key']] = _cache[album_key]
else:
_cache[uri['key']] = tuple(
_translate_image(i) for i in item['images'])
result[uri['uri']] = _cache[uri['key']]

return result


def _translate_image(i):
return models.Image(uri=i['url'], height=i['height'], width=i['width'])
5 changes: 4 additions & 1 deletion mopidy_spotify/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from spotify import Link, SpotifyError, ToplistBrowser

from mopidy_spotify import translator, utils
from mopidy_spotify import images, translator, utils

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -298,3 +298,6 @@ def _translate_search_query(self, mopidy_query):
spotify_query.append('%s:"%s"' % (field, value))
spotify_query = ' '.join(spotify_query)
return spotify_query

def get_images(self, uris):
return images.get_images(uris)

0 comments on commit 74ac793

Please sign in to comment.