Add Amazon Music as a primary metadata source
Wires AmazonClient into the metadata source registry following the exact same pattern as DeezerClient. No existing source paths touched. - Add get_album_metadata / get_artist_info / get_artist_albums_list aliases to AmazonClient (mirrors DeezerClient interface aliases) - Register amazon in METADATA_SOURCE_PRIORITY and METADATA_SOURCE_LABELS - Add _get_amazon_factory() + get_amazon_client() to registry.py - Add amazon branch to get_client_for_source(); thread amazon_client_factory kwarg through get_primary_client() and get_primary_source_status() - Re-export get_amazon_client from the core.metadata_service shim - Add Amazon Music option to Settings metadata source dropdown - 3530 tests pass
This commit is contained in:
parent
e8b9f80597
commit
1f579cede8
5 changed files with 40 additions and 2 deletions
|
|
@ -511,6 +511,11 @@ class AmazonClient:
|
|||
"""Not available from Amazon Music — returns None for compatibility."""
|
||||
return None
|
||||
|
||||
# ==================== Interface Aliases (match DeezerClient method names) ====================
|
||||
get_album_metadata = get_album
|
||||
get_artist_info = get_artist
|
||||
get_artist_albums_list = get_artist_albums
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Private helpers
|
||||
# ------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -18,13 +18,14 @@ logger = get_logger("metadata.registry")
|
|||
|
||||
MetadataClientFactory = Callable[[], Any]
|
||||
|
||||
METADATA_SOURCE_PRIORITY = ("deezer", "itunes", "spotify", "discogs", "hydrabase")
|
||||
METADATA_SOURCE_PRIORITY = ("deezer", "itunes", "spotify", "discogs", "hydrabase", "amazon")
|
||||
METADATA_SOURCE_LABELS = {
|
||||
"spotify": "Spotify",
|
||||
"itunes": "iTunes",
|
||||
"deezer": "Deezer",
|
||||
"discogs": "Discogs",
|
||||
"hydrabase": "Hydrabase",
|
||||
"amazon": "Amazon Music",
|
||||
}
|
||||
|
||||
_UNSET = object()
|
||||
|
|
@ -140,6 +141,14 @@ def _get_discogs_factory(client_factory: Optional[MetadataClientFactory]) -> Met
|
|||
return DiscogsClient
|
||||
|
||||
|
||||
def _get_amazon_factory(client_factory: Optional[MetadataClientFactory]) -> MetadataClientFactory:
|
||||
if client_factory is not None:
|
||||
return client_factory
|
||||
from core.amazon_client import AmazonClient
|
||||
|
||||
return AmazonClient
|
||||
|
||||
|
||||
def get_spotify_client(client_factory: Optional[MetadataClientFactory] = None):
|
||||
"""Get shared Spotify client.
|
||||
|
||||
|
|
@ -260,6 +269,18 @@ def get_discogs_client(
|
|||
return client
|
||||
|
||||
|
||||
def get_amazon_client(client_factory: Optional[MetadataClientFactory] = None):
|
||||
"""Get cached Amazon Music client."""
|
||||
cache_key = "amazon"
|
||||
factory = _get_amazon_factory(client_factory)
|
||||
with _client_cache_lock:
|
||||
client = _client_cache.get(cache_key)
|
||||
if client is None:
|
||||
client = factory()
|
||||
_client_cache[cache_key] = client
|
||||
return client
|
||||
|
||||
|
||||
def is_hydrabase_enabled() -> bool:
|
||||
"""Return True when Hydrabase is connected and app-enabled."""
|
||||
try:
|
||||
|
|
@ -331,6 +352,7 @@ def get_primary_client(
|
|||
itunes_client_factory: Optional[MetadataClientFactory] = None,
|
||||
deezer_client_factory: Optional[MetadataClientFactory] = None,
|
||||
discogs_client_factory: Optional[MetadataClientFactory] = None,
|
||||
amazon_client_factory: Optional[MetadataClientFactory] = None,
|
||||
):
|
||||
"""Return client for configured primary source."""
|
||||
return get_client_for_source(
|
||||
|
|
@ -339,6 +361,7 @@ def get_primary_client(
|
|||
itunes_client_factory=itunes_client_factory,
|
||||
deezer_client_factory=deezer_client_factory,
|
||||
discogs_client_factory=discogs_client_factory,
|
||||
amazon_client_factory=amazon_client_factory,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -348,6 +371,7 @@ def get_primary_source_status(
|
|||
itunes_client_factory: Optional[MetadataClientFactory] = None,
|
||||
deezer_client_factory: Optional[MetadataClientFactory] = None,
|
||||
discogs_client_factory: Optional[MetadataClientFactory] = None,
|
||||
amazon_client_factory: Optional[MetadataClientFactory] = None,
|
||||
) -> Dict[str, Any]:
|
||||
"""Return a generic status snapshot for the active primary metadata source."""
|
||||
source = _get_config_value("metadata.fallback_source", "deezer") or "deezer"
|
||||
|
|
@ -361,6 +385,7 @@ def get_primary_source_status(
|
|||
itunes_client_factory=itunes_client_factory,
|
||||
deezer_client_factory=deezer_client_factory,
|
||||
discogs_client_factory=discogs_client_factory,
|
||||
amazon_client_factory=amazon_client_factory,
|
||||
)
|
||||
if source == "spotify":
|
||||
connected = bool(client and client.is_spotify_authenticated())
|
||||
|
|
@ -387,6 +412,7 @@ def get_client_for_source(
|
|||
itunes_client_factory: Optional[MetadataClientFactory] = None,
|
||||
deezer_client_factory: Optional[MetadataClientFactory] = None,
|
||||
discogs_client_factory: Optional[MetadataClientFactory] = None,
|
||||
amazon_client_factory: Optional[MetadataClientFactory] = None,
|
||||
):
|
||||
"""Return exact client for a source, or None if unavailable."""
|
||||
if source == "spotify":
|
||||
|
|
@ -410,4 +436,7 @@ def get_client_for_source(
|
|||
if source == "itunes":
|
||||
return get_itunes_client(client_factory=itunes_client_factory)
|
||||
|
||||
if source == "amazon":
|
||||
return get_amazon_client(client_factory=amazon_client_factory)
|
||||
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ from core.metadata.registry import (
|
|||
clear_cached_metadata_client,
|
||||
clear_cached_metadata_clients,
|
||||
clear_cached_profile_spotify_client,
|
||||
get_amazon_client,
|
||||
get_client_for_source,
|
||||
get_deezer_client,
|
||||
get_discogs_client,
|
||||
|
|
@ -75,6 +76,7 @@ except Exception: # pragma: no cover - optional dependency fallback
|
|||
|
||||
__all__ = [
|
||||
"METADATA_SOURCE_PRIORITY",
|
||||
"get_amazon_client",
|
||||
"MetadataCache",
|
||||
"MetadataLookupOptions",
|
||||
"MetadataProvider",
|
||||
|
|
|
|||
|
|
@ -3632,10 +3632,11 @@
|
|||
<option value="itunes">iTunes / Apple Music</option>
|
||||
<option value="deezer">Deezer</option>
|
||||
<option value="discogs">Discogs</option>
|
||||
<option value="amazon">Amazon Music</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="callback-info">
|
||||
<div class="callback-help">Choose the primary source for artist, album, and track metadata. Spotify can only be selected while an active Spotify session exists. Discogs requires a personal token.</div>
|
||||
<div class="callback-help">Choose the primary source for artist, album, and track metadata. Spotify can only be selected while an active Spotify session exists. Discogs requires a personal token. Amazon Music uses the T2Tunes proxy — no account needed.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -3415,6 +3415,7 @@ function closeHelperSearch() {
|
|||
const WHATS_NEW = {
|
||||
'2.5.3': [
|
||||
{ unreleased: true },
|
||||
{ title: 'Amazon Music Metadata Source', desc: 'Amazon Music is now a selectable primary metadata source alongside Spotify, iTunes, Deezer, and Discogs. backed by the same T2Tunes proxy as the download source — no account needed. covers track search, album lookup with cover art, and artist discography. select it under Settings → Connections → Metadata Source.', page: 'settings' },
|
||||
{ title: 'Amazon Music Download Source', desc: 'new download source backed by T2Tunes proxy. searches the Amazon Music catalog, downloads 24-bit/48kHz FLAC (or Opus 320kbps / Dolby Atmos EAC3 fallback). codec waterfall mirrors Tidal/Qobuz — best quality first, auto-fallback. selectable as a standalone or hybrid source from Settings.', page: 'settings' },
|
||||
],
|
||||
'2.5.2': [
|
||||
|
|
|
|||
Loading…
Reference in a new issue