From 139de02d9a0ff672c28574e6f553ebbb9746fb96 Mon Sep 17 00:00:00 2001 From: krateng Date: Wed, 1 Nov 2023 17:01:03 +0100 Subject: [PATCH] Add album art fetching from Musicbrainz, fix GH-265 --- dev/releases/3.2.yml | 1 + maloja/pkg_global/conf.py | 2 +- maloja/thirdparty/musicbrainz.py | 62 ++++++++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/dev/releases/3.2.yml b/dev/releases/3.2.yml index 03880a2f..ca388eb7 100644 --- a/dev/releases/3.2.yml +++ b/dev/releases/3.2.yml @@ -23,6 +23,7 @@ minor_release_name: "Nicole" 3.2.1: notes: - "[Feature] Added setting for custom week offset" + - "[Feature] Added Musicbrainz album art fetching" - "[Bugfix] Fixed album entity rows being marked as track entity rows" - "[Bugfix] Fixed scrobbling of tracks when all artists have been removed by server parsing" - "[Bugfix] Fixed Spotify import of multiple files" diff --git a/maloja/pkg_global/conf.py b/maloja/pkg_global/conf.py index 2ff5026f..5ed60526 100644 --- a/maloja/pkg_global/conf.py +++ b/maloja/pkg_global/conf.py @@ -201,7 +201,7 @@ def find_good_folder(datatype,configobject): "display_art_icons":(tp.Boolean(), "Display Album/Artist Icons", True), "default_album_artist":(tp.String(), "Default Albumartist", "Various Artists"), "use_album_artwork_for_tracks":(tp.Boolean(), "Use Album Artwork for tracks", True), - "fancy_placeholder_art":(tp.Boolean(), "Use fancy placeholder artwork",True), + "fancy_placeholder_art":(tp.Boolean(), "Use fancy placeholder artwork",False), "discourage_cpu_heavy_stats":(tp.Boolean(), "Discourage CPU-heavy stats", False, "Prevent visitors from mindlessly clicking on CPU-heavy options. Does not actually disable them for malicious actors!"), "use_local_images":(tp.Boolean(), "Use Local Images", True), #"local_image_rotate":(tp.Integer(), "Local Image Rotate", 3600), diff --git a/maloja/thirdparty/musicbrainz.py b/maloja/thirdparty/musicbrainz.py index 56e0be16..6f1f2b1b 100644 --- a/maloja/thirdparty/musicbrainz.py +++ b/maloja/thirdparty/musicbrainz.py @@ -13,12 +13,14 @@ class MusicBrainz(MetadataInterface): lock = threading.Lock() useragent = USER_AGENT + + thumbnailsize_order = ['500','large','1200','250','small'] + settings = { } metadata = { "response_type":"json", - "response_parse_tree_track": ["images",0,"thumbnails","500"], "required_settings": [], } @@ -27,7 +29,57 @@ def get_image_artist(self,artist): # not supported def get_image_album(self,album): - return None + self.lock.acquire() + try: + artists, title = album + searchstr = f'release:"{title}"' + for artist in artists: + searchstr += f' artist:"{artist}"' + querystr = urllib.parse.urlencode({ + "fmt":"json", + "query":searchstr + }) + req = urllib.request.Request(**{ + "url":"https://musicbrainz.org/ws/2/release?" + querystr, + "method":"GET", + "headers":{ + "User-Agent":self.useragent + } + }) + response = urllib.request.urlopen(req) + responsedata = response.read() + data = json.loads(responsedata) + entity = data["releases"][0] + coverartendpoint = "release" + while True: + mbid = entity["id"] + try: + response = urllib.request.urlopen( + f"https://coverartarchive.org/{coverartendpoint}/{mbid}?fmt=json" + ) + responsedata = response.read() + data = json.loads(responsedata) + thumbnails = data['images'][0]['thumbnails'] + for size in self.thumbnailsize_order: + if thumbnails.get(size) is not None: + imgurl = thumbnails.get(size) + continue + except: + imgurl = None + if imgurl is None: + entity = entity["release-group"] + # this will raise an error so we don't stay in the while loop forever + coverartendpoint = "release-group" + continue + + imgurl = self.postprocess_url(imgurl) + return imgurl + + except Exception: + return None + finally: + time.sleep(2) + self.lock.release() def get_image_track(self,track): self.lock.acquire() @@ -60,7 +112,11 @@ def get_image_track(self,track): ) responsedata = response.read() data = json.loads(responsedata) - imgurl = self.metadata_parse_response_track(data) + thumbnails = data['images'][0]['thumbnails'] + for size in self.thumbnailsize_order: + if thumbnails.get(size) is not None: + imgurl = thumbnails.get(size) + continue except: imgurl = None if imgurl is None: