diff --git a/beetsplug/fetchart.py b/beetsplug/fetchart.py index 0e106694db..cb62059cd3 100644 --- a/beetsplug/fetchart.py +++ b/beetsplug/fetchart.py @@ -35,12 +35,6 @@ from beets.util import syspath, bytestring_path, py3_path import six -try: - import itunes - HAVE_ITUNES = True -except ImportError: - HAVE_ITUNES = False - CONTENT_TYPES = { 'image/jpeg': [b'jpg', b'jpeg'], 'image/png': [b'png'] @@ -458,37 +452,65 @@ def get(self, album, plugin, paths): class ITunesStore(RemoteArtSource): NAME = u"iTunes Store" + API_URL = u'https://itunes.apple.com/search' def get(self, album, plugin, paths): """Return art URL from iTunes Store given an album title. """ if not (album.albumartist and album.album): return - search_string = (album.albumartist + ' ' + album.album).encode('utf-8') + + payload = { + 'term': album.albumartist + u' ' + album.album, + 'entity': u'album', + 'media': u'music', + 'limit': 200 + } try: - # Isolate bugs in the iTunes library while searching. - try: - results = itunes.search_album(search_string) - except Exception as exc: - self._log.debug(u'iTunes search failed: {0}', exc) - return + r = self.request(self.API_URL, params=payload) + r.raise_for_status() + except requests.RequestException as e: + self._log.debug(u'iTunes search failed: {0}', e) + return - # Get the first match. - if results: - itunes_album = results[0] - else: - self._log.debug(u'iTunes search for {:r} got no results', - search_string) - return + try: + candidates = r.json()['results'] + except ValueError as e: + self._log.debug(u'Could not decode json response: {0}', e) + return + except KeyError as e: + self._log.debug(u'{} not found in json. Fields are {} ', + e, + list(r.json().keys())) + return - if itunes_album.get_artwork()['100']: - small_url = itunes_album.get_artwork()['100'] - big_url = small_url.replace('100x100', '1200x1200') - yield self._candidate(url=big_url, match=Candidate.MATCH_EXACT) - else: - self._log.debug(u'album has no artwork in iTunes Store') - except IndexError: - self._log.debug(u'album not found in iTunes Store') + if not candidates: + self._log.debug(u'iTunes search for {!r} got no results', + payload['term']) + return + + for c in candidates: + try: + if (c['artistName'] == album.albumartist + and c['collectionName'] == album.album): + art_url = c['artworkUrl100'] + art_url = art_url.replace('100x100', '1200x1200') + yield self._candidate(url=art_url, + match=Candidate.MATCH_EXACT) + except KeyError as e: + self._log.debug(u'Malformed itunes candidate: {} not found in {}', # NOQA E501 + e, + list(c.keys())) + + try: + fallback_art_url = candidates[0]['artworkUrl100'] + fallback_art_url = fallback_art_url.replace('100x100', '1200x1200') + yield self._candidate(url=fallback_art_url, + match=Candidate.MATCH_FALLBACK) + except KeyError as e: + self._log.debug(u'Malformed itunes candidate: {} not found in {}', + e, + list(c.keys())) class Wikipedia(RemoteArtSource): @@ -756,8 +778,6 @@ def __init__(self): self.register_listener('import_task_files', self.assign_art) available_sources = list(SOURCES_ALL) - if not HAVE_ITUNES and u'itunes' in available_sources: - available_sources.remove(u'itunes') if not self.config['google_key'].get() and \ u'google' in available_sources: available_sources.remove(u'google') diff --git a/docs/changelog.rst b/docs/changelog.rst index 4a8b9daf35..1c6b6d3584 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -21,6 +21,11 @@ New features: Fixes: +* Restore iTunes Store album art source, and remove the dependency on + python-itunes_, which had gone unmaintained and was not py3 compatible. + Thanks to :user:`ocelma` for creating python-itunes_ in the first place. + Thanks to :user:`nathdwek`. + :bug:`2371` :bug:`2551` :bug:`2718` * Fix compatibility Python 3.7 and its change to a name in the ``re`` module. :bug:`2978` * R128 normalization tags are now properly deleted from files when the values @@ -41,6 +46,8 @@ Fixes: Thanks to :user:`rveachkc`. :bug:`2979`: :bug:`2980` +.. _python-itunes: https://github.com/ocelma/python-itunes + 1.4.7 (May 29, 2018) -------------------- diff --git a/docs/plugins/fetchart.rst b/docs/plugins/fetchart.rst index d6d9adeff1..002471ec15 100644 --- a/docs/plugins/fetchart.rst +++ b/docs/plugins/fetchart.rst @@ -16,12 +16,13 @@ The plugin uses `requests`_ to fetch album art from the Web. Fetching Album Art During Import -------------------------------- -When the plugin is enabled, it automatically gets album art for every album -you import. +When the plugin is enabled, it automatically tries to get album art for every +album you import. By default, beets stores album art image files alongside the music files for an album in a file called ``cover.jpg``. To customize the name of this file, use -the :ref:`art-filename` config option. +the :ref:`art-filename` config option. To embed the art into the files' tags, +use the :doc:`/plugins/embedart`. (You'll want to have both plugins enabled.) Configuration ------------- @@ -49,7 +50,7 @@ file. The available options are: (``enforce_ratio: 0.5%``). Default: ``no``. - **sources**: List of sources to search for images. An asterisk `*` expands to all available sources. - Default: ``filesystem coverart amazon albumart``, i.e., everything but + Default: ``filesystem coverart itunes amazon albumart``, i.e., everything but ``wikipedia``, ``google`` and ``fanarttv``. Enable those sources for more matches at the cost of some speed. They are searched in the given order, thus in the default config, no remote (Web) art source are queried if @@ -83,13 +84,13 @@ or `Pillow`_. .. _ImageMagick: http://www.imagemagick.org/ Here's an example that makes plugin select only images that contain *front* or -*back* keywords in their filenames and prioritizes the Amazon source over +*back* keywords in their filenames and prioritizes the iTunes source over others:: fetchart: cautious: true cover_names: front back - sources: amazon * + sources: itunes * Manually Fetching Album Art @@ -142,7 +143,7 @@ Album Art Sources ----------------- By default, this plugin searches for art in the local filesystem as well as on -the Cover Art Archive, Amazon, and AlbumArt.org, in that +the Cover Art Archive, the iTunes Store, Amazon, and AlbumArt.org, in that order. You can reorder the sources or remove some to speed up the process using the ``sources`` configuration option. @@ -222,10 +223,3 @@ album art fetch, you could do The values written to ``art_source`` are the same names used in the ``sources`` configuration value. - -Embedding Album Art -------------------- - -This plugin fetches album art but does not embed images into files' tags. To do -that, use the :doc:`/plugins/embedart`. (You'll want to have both plugins -enabled.)