diff --git a/beetsplug/fetchart.py b/beetsplug/fetchart.py index 4a9693e64..a50f98f01 100644 --- a/beetsplug/fetchart.py +++ b/beetsplug/fetchart.py @@ -15,24 +15,26 @@ """Fetches album art. """ -from contextlib import closing import os import re -from tempfile import NamedTemporaryFile from collections import OrderedDict +from contextlib import closing +from tempfile import NamedTemporaryFile -import requests - -from beets import plugins -from beets import importer -from beets import ui -from beets import util -from beets import config -from mediafile import image_mime_type -from beets.util.artresizer import ArtResizer -from beets.util import sorted_walk -from beets.util import syspath, bytestring_path, py3_path import confuse +import requests +from mediafile import image_mime_type + +from beets import config, importer, plugins, ui, util +from beets.util import bytestring_path, py3_path, sorted_walk, syspath +from beets.util.artresizer import ArtResizer + +try: + from bs4 import BeautifulSoup + HAS_BEAUTIFUL_SOUP = True +except ImportError: + HAS_BEAUTIFUL_SOUP = False + CONTENT_TYPES = { 'image/jpeg': [b'jpg', b'jpeg'], @@ -893,11 +895,35 @@ class LastFM(RemoteArtSource): .format(response.text)) return + +class Spotify(RemoteArtSource): + NAME = "Spotify" + + SPOTIFY_ALBUM_URL = 'https://open.spotify.com/album/' + + def get(self, album, plugin, paths): + url = self.SPOTIFY_ALBUM_URL + album.mb_albumid + try: + response = requests.get(url) + response.raise_for_status() + except requests.RequestException as e: + self._log.debug("Error: " + str(e)) + return + try: + html = response.text + soup = BeautifulSoup(html, 'html.parser') + image_url = soup.find('meta', + attrs={'property': 'og:image'})['content'] + yield self._candidate(url=image_url, + match=Candidate.MATCH_EXACT) + except ValueError: + self._log.debug('Spotify: error loading response: {}' + .format(response.text)) + return # Try each source in turn. -SOURCES_ALL = ['filesystem', - 'coverart', 'itunes', 'amazon', 'albumart', - 'wikipedia', 'google', 'fanarttv', 'lastfm'] +SOURCES_ALL = ['filesystem', 'coverart', 'itunes', 'amazon', 'albumart', + 'wikipedia', 'google', 'fanarttv', 'lastfm', 'spotify'] ART_SOURCES = { 'filesystem': FileSystem, @@ -909,6 +935,7 @@ ART_SOURCES = { 'google': GoogleImages, 'fanarttv': FanartTV, 'lastfm': LastFM, + 'spotify': Spotify, } SOURCE_NAMES = {v: k for k, v in ART_SOURCES.items()} @@ -997,6 +1024,12 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): if not self.config['lastfm_key'].get() and \ 'lastfm' in available_sources: available_sources.remove('lastfm') + if not HAS_BEAUTIFUL_SOUP and \ + 'spotify' in available_sources: + self._log.debug('To use Spotify as an album art source, ' + 'you must install the beautifulsoup4 module. See ' + 'the documentation for further details.') + available_sources.remove('spotify') available_sources = [(s, c) for s in available_sources for c in ART_SOURCES[s].VALID_MATCHING_CRITERIA] diff --git a/docs/changelog.rst b/docs/changelog.rst index b7aaa7dff..d7ddf6d03 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -11,6 +11,7 @@ for Python 3.6). New features: +* :doc:`/plugins/fetchart`: The plugin can now get album art from `spotify`. * Added option to specify a URL in the `embedart` plugin. :bug:`83` * :ref:`list-cmd` `singleton:true` queries have been made faster diff --git a/docs/plugins/fetchart.rst b/docs/plugins/fetchart.rst index 2b884c5ad..2dc8cbf21 100644 --- a/docs/plugins/fetchart.rst +++ b/docs/plugins/fetchart.rst @@ -50,7 +50,7 @@ file. The available options are: PIL defaults to 75. Default: 0 (disabled) - **max_filesize**: The maximum size of a target piece of cover art in bytes. - When using an ImageMagick backend this sets + When using an ImageMagick backend this sets ``-define jpeg:extent=max_filesize``. Using PIL this will reduce JPG quality by up to 50% to attempt to reach the target filesize. Neither method is *guaranteed* to reach the target size, however in most cases it should @@ -254,6 +254,18 @@ the list of sources in your configutation. .. _register for a Last.fm API key: https://www.last.fm/api/account/create +Spotify +''''''' + +Spotify backend requires `BeautifulSoup`_, which you can install using `pip`_ by typing:: + + pip install beautifulsoup4 + +Spotify backend is enabled by default and will update album art if a valid Spotify album id is found. + +.. _pip: https://pip.pypa.io +.. _BeautifulSoup: https://www.crummy.com/software/BeautifulSoup/bs4/doc/ + Storing the Artwork's Source ---------------------------- diff --git a/setup.py b/setup.py index a5c57cc7d..26cebaa87 100755 --- a/setup.py +++ b/setup.py @@ -135,7 +135,7 @@ setup( # Plugin (optional) dependencies: 'absubmit': ['requests'], - 'fetchart': ['requests', 'Pillow'], + 'fetchart': ['requests', 'Pillow', 'beautifulsoup4'], 'embedart': ['Pillow'], 'embyupdate': ['requests'], 'chroma': ['pyacoustid'],