Refactor parsing external ids

This commit is contained in:
Šarūnas Nejus 2026-01-25 01:19:20 +00:00
parent 751c2c61c7
commit 99afdd3c04
No known key found for this signature in database

View file

@ -24,6 +24,7 @@ from typing import TYPE_CHECKING, Literal, TypedDict
from urllib.parse import urljoin
from confuse.exceptions import NotFoundError
from typing_extensions import NotRequired
import beets
import beets.autotag.hooks
@ -50,6 +51,7 @@ if TYPE_CHECKING:
Recording,
Release,
ReleaseGroup,
UrlRelation,
)
VARIOUS_ARTISTS_ID = "89ad4ac3-39f7-470e-963a-56509c546377"
@ -136,6 +138,15 @@ class LabelInfoInfo(TypedDict):
catalognum: str | None
class ExternalIdsInfo(TypedDict):
discogs_album_id: NotRequired[str | None]
bandcamp_album_id: NotRequired[str | None]
spotify_album_id: NotRequired[str | None]
deezer_album_id: NotRequired[str | None]
tidal_album_id: NotRequired[str | None]
beatport_album_id: NotRequired[str | None]
def _preferred_alias(
aliases: list[Alias], languages: list[str] | None = None
) -> Alias | None:
@ -468,6 +479,34 @@ class MusicBrainzPlugin(MusicBrainzAPIMixin, MetadataSourcePlugin):
return None
def _parse_external_ids(
self, url_relations: list[UrlRelation]
) -> ExternalIdsInfo:
"""Extract configured external release ids from MusicBrainz URLs.
MusicBrainz releases can include `url_relations` pointing to third-party
sites (for example Bandcamp or Discogs). This helper filters those URL
relations to only the sources enabled in configuration, then derives a
stable external identifier from each matching URL.
"""
external_ids = self.config["external_ids"].get()
wanted_sources: set[UrlSource] = {
site for site, wanted in external_ids.items() if wanted
}
url_by_source: dict[UrlSource, str] = {}
for source, url_relation in product(wanted_sources, url_relations):
if f"{source}.com" in (target := url_relation["url"]["resource"]):
url_by_source[source] = target
self._log.debug(
"Found link to {} release via MusicBrainz",
source.capitalize(),
)
return {
f"{source}_album_id": extract_release_id(source, url)
for source, url in url_by_source.items()
} # type: ignore[return-value]
def album_info(self, release: Release) -> beets.autotag.hooks.AlbumInfo:
"""Takes a MusicBrainz release result dictionary and returns a beets
AlbumInfo object containing the interesting data about that release.
@ -559,6 +598,7 @@ class MusicBrainzPlugin(MusicBrainzAPIMixin, MetadataSourcePlugin):
genre=genre if (genre := self._parse_genre(release)) else None,
**self._parse_release_group(release["release_group"]),
**self._parse_label_infos(release["label_info"]),
**self._parse_external_ids(release.get("url_relations", [])),
)
info.va = info.artist_id == VARIOUS_ARTISTS_ID
if info.va:
@ -596,29 +636,6 @@ class MusicBrainzPlugin(MusicBrainzAPIMixin, MetadataSourcePlugin):
else:
info.media = "Media"
# We might find links to external sources (Discogs, Bandcamp, ...)
external_ids = self.config["external_ids"].get()
wanted_sources: set[UrlSource] = {
site for site, wanted in external_ids.items() if wanted
}
if wanted_sources and (url_rels := release.get("url_relations")):
urls = {}
for url_source, url_relation in product(wanted_sources, url_rels):
if f"{url_source}.com" in (
target := url_relation["url"]["resource"]
):
urls[url_source] = target
self._log.debug(
"Found link to {} release via MusicBrainz",
url_source.capitalize(),
)
for source, url in urls.items():
setattr(
info, f"{source}_album_id", extract_release_id(source, url)
)
extra_albumdatas = plugins.send("mb_album_extract", data=release)
for extra_albumdata in extra_albumdatas:
info.update(extra_albumdata)