Files
Lyra/worker/lyra_worker/registry.py
T
Jonathan 146bf32f23 feat(worker): Last.fm artist.getSimilar as a second discovery SimilaritySource
Adds LastfmSource, resolving Last.fm's often-empty artist mbid via the
injected MB browser (name->mbid cached) so every emitted SimilarArtist.mbid
is a real MusicBrainz artist MBID. Registered in build_similarity_sources,
gated on lastfm.api_key so the ListenBrainz-only path is unchanged when
unset.
2026-07-13 19:23:18 +02:00

66 lines
2.5 KiB
Python

from lyra_worker._mbbrowser import MusicBrainzBrowser
from lyra_worker._musicbrainz import MusicBrainzResolver
from lyra_worker._mutagen import MutagenTagger
from lyra_worker._probe import MutagenProbe
from lyra_worker.adapters._slskd import SlskdClient
from lyra_worker.adapters._streamrip import StreamripClient
from lyra_worker.adapters._ytdlp import YtDlpClient
from lyra_worker.adapters.base import SourceAdapter
from lyra_worker.adapters.qobuz import QobuzAdapter
from lyra_worker.adapters.soulseek import SoulseekAdapter
from lyra_worker.adapters.youtube import YouTubeAdapter
from lyra_worker.browser import MbBrowser
from lyra_worker.probe import AudioProbe
from lyra_worker.resolver import MbResolver
from lyra_worker.similarity._lastfm import LastfmSource
from lyra_worker.similarity._listenbrainz import ListenBrainzSource
from lyra_worker.similarity.base import SimilaritySource
from lyra_worker.tagger import Tagger
def build_adapters(config: dict) -> list[SourceAdapter]:
"""Real source adapters, best-tier first, filtered to those that are configured.
An adapter is included only if its health() is true (Qobuz needs credentials,
Soulseek needs an slskd URL + API key). YouTube needs no config.
"""
candidates: list[SourceAdapter] = [
QobuzAdapter(StreamripClient(config)),
SoulseekAdapter(SlskdClient(config)),
YouTubeAdapter(YtDlpClient()),
]
return [a for a in candidates if a.health()]
def build_resolver() -> MbResolver:
"""The MusicBrainz resolver used to canonicalize requests in intake."""
return MusicBrainzResolver()
def build_tagger() -> Tagger:
"""The tagger that writes canonical metadata onto downloaded files."""
return MutagenTagger()
def build_browser() -> MbBrowser:
"""The MusicBrainz browser used by the background monitor."""
return MusicBrainzBrowser()
def build_probe() -> AudioProbe:
"""The audio probe used by the library scan."""
return MutagenProbe()
def build_similarity_sources(config: dict) -> list[SimilaritySource]:
"""Similarity sources for discovery. ListenBrainz needs no credentials, so it is
always constructed; per-run reachability is checked via each source's health().
Last.fm is added only when an API key is configured."""
sources: list[SimilaritySource] = [
ListenBrainzSource(base_url=config.get("discover.listenBrainzUrl") or "")
]
key = config.get("lastfm.api_key")
if key:
sources.append(LastfmSource(api_key=key, browser=MusicBrainzBrowser()))
return sources