From 3d06b0aeae2d1c49476bb38981cfa5bd53587cd9 Mon Sep 17 00:00:00 2001 From: asardaes Date: Tue, 30 Dec 2025 21:51:50 +0100 Subject: [PATCH] Try simple MB search in case artist is an alias --- beetsplug/_utils/musicbrainz.py | 26 ++++++++++++++++++++------ beetsplug/musicbrainz.py | 21 +++++++++++++++++---- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/beetsplug/_utils/musicbrainz.py b/beetsplug/_utils/musicbrainz.py index 2fc821df9..dd865cbf9 100644 --- a/beetsplug/_utils/musicbrainz.py +++ b/beetsplug/_utils/musicbrainz.py @@ -13,7 +13,7 @@ from __future__ import annotations import operator from dataclasses import dataclass, field from functools import cached_property, singledispatchmethod, wraps -from itertools import groupby +from itertools import chain, groupby from typing import TYPE_CHECKING, Any, Literal, ParamSpec, TypedDict, TypeVar from requests_ratelimiter import LimiterMixin @@ -185,6 +185,8 @@ class MusicBrainzAPI(RequestHandler): self, entity: Entity, filters: dict[str, str], + advanced: bool = True, + *args: str, **kwargs: Unpack[SearchKwargs], ) -> list[JSONDict]: """Search for MusicBrainz entities matching the given filters. @@ -195,11 +197,23 @@ class MusicBrainzAPI(RequestHandler): - 'value' is empty, in which case the filter is ignored * Values are lowercased and stripped of whitespace. """ - query = " AND ".join( - ":".join(filter(None, (k, f'"{_v}"'))) - for k, v in filters.items() - if (_v := v.lower().strip()) - ) + if advanced: + query = " AND ".join( + f'{k}:"{_v}"' + for k, v in filters.items() + if (_v := v.lower().strip()) + ) + else: + params = chain( + (str(arg) for arg in args), + ( + f'{k}:"{_v}"' + for k, v in filters.items() + if (_v := v.lower().strip()) + ), + ) + query = " ".join(params) + log.debug("Searching for MusicBrainz {}s with: {!r}", entity, query) kwargs["query"] = query return self._get_resource(entity, **kwargs)[f"{entity}s"] diff --git a/beetsplug/musicbrainz.py b/beetsplug/musicbrainz.py index 063c3dbfd..0c0e0e525 100644 --- a/beetsplug/musicbrainz.py +++ b/beetsplug/musicbrainz.py @@ -821,15 +821,20 @@ class MusicBrainzPlugin(MusicBrainzAPIMixin, MetadataSourcePlugin): self, query_type: Literal["recording", "release"], filters: dict[str, str], + advanced: bool = True, + *args: str, ) -> list[JSONDict]: """Perform MusicBrainz API search and return results. Execute a search against the MusicBrainz API for recordings or releases - using the provided criteria. Handles API errors by converting them into - MusicBrainzAPIError exceptions with contextual information. + using the provided criteria. """ return self.mb_api.search( - query_type, filters, limit=self.config["search_limit"].get() + query_type, + filters, + advanced, + *args, + limit=self.config["search_limit"].get(), ) def candidates( @@ -840,7 +845,15 @@ class MusicBrainzPlugin(MusicBrainzAPIMixin, MetadataSourcePlugin): va_likely: bool, ) -> Iterable[AlbumInfo]: criteria = self.get_album_criteria(items, artist, album, va_likely) - release_ids = (r["id"] for r in self._search_api("release", criteria)) + release_ids = [r["id"] for r in self._search_api("release", criteria)] + + if len(release_ids) == 0 and "artist" in criteria: + # try a less advanced search if va_likely is False + del criteria["artist"] + release_ids = [ + r["id"] + for r in self._search_api("release", criteria, False, artist) + ] for id_ in release_ids: with suppress(HTTPNotFoundError):