From 57fc18f9942b3e810cf146a287c08ea8a456db15 Mon Sep 17 00:00:00 2001 From: Broque Thomas <26755000+Nezreka@users.noreply.github.com> Date: Fri, 10 Apr 2026 11:43:06 -0700 Subject: [PATCH] Respect configured primary source in seasonal, playlists, and explorer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seasonal discovery, personalized playlists, and playlist explorer all defaulted to Spotify when authenticated, ignoring the user's configured primary source. Now they read from config first. Spotify's related_artists API (no Deezer/iTunes equivalent) is preserved as a fallback for all users in personalized playlists. Artist discography endpoint intentionally unchanged — ID-based lookups need the source that owns the ID. --- core/personalized_playlists.py | 21 ++++++++++----------- core/seasonal_discovery.py | 14 ++++++++------ web_server.py | 7 +++---- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/core/personalized_playlists.py b/core/personalized_playlists.py index 6fd3c8cd..9bd97388 100644 --- a/core/personalized_playlists.py +++ b/core/personalized_playlists.py @@ -102,17 +102,16 @@ class PersonalizedPlaylistsService: def _get_active_source(self) -> str: """ - Determine which music source is active for discovery. - Returns 'spotify' if Spotify is authenticated, otherwise the configured fallback ('itunes' or 'deezer'). + Determine which music source is active — respects user's configured primary source. """ - if self.spotify_client and hasattr(self.spotify_client, 'is_spotify_authenticated'): - if self.spotify_client.is_spotify_authenticated(): - return 'spotify' try: from config.settings import config_manager - return config_manager.get('metadata.fallback_source', 'itunes') or 'itunes' + source = config_manager.get('metadata.fallback_source', 'deezer') or 'deezer' + if source == 'spotify' and not (self.spotify_client and hasattr(self.spotify_client, 'is_spotify_authenticated') and self.spotify_client.is_spotify_authenticated()): + return 'deezer' + return source except Exception: - return 'itunes' + return 'deezer' def _build_track_dict(self, row, source: str) -> Dict: """Build a standardized track dictionary from a database row.""" @@ -882,8 +881,8 @@ class PersonalizedPlaylistsService: logger.error(f"Invalid seed artists count: {len(seed_artist_ids)}") return {'tracks': [], 'error': 'Must provide 1-5 seed artists'} - use_spotify = self.spotify_client and self.spotify_client.sp - active_source = 'spotify' if use_spotify else self._get_active_source() + active_source = self._get_active_source() + use_spotify = (active_source == 'spotify') and self.spotify_client and self.spotify_client.sp logger.info(f"Building custom playlist from {len(seed_artist_ids)} seed artists (source: {active_source})") # Step 1: Get similar artists for each seed @@ -914,8 +913,8 @@ class PersonalizedPlaylistsService: seen_artist_ids.add(artist_id) if len(all_similar_artists) >= 25: break - elif use_spotify: - # Fallback: fetch related artists from Spotify API + elif self.spotify_client and self.spotify_client.sp: + # Fallback: fetch related artists from Spotify API (no Deezer/iTunes equivalent) logger.info(f"No cached similar artists for {seed_artist_id}, trying Spotify related artists API") try: related = self.spotify_client.sp.artist_related_artists(seed_artist_id) diff --git a/core/seasonal_discovery.py b/core/seasonal_discovery.py index a3295d4e..827da764 100644 --- a/core/seasonal_discovery.py +++ b/core/seasonal_discovery.py @@ -96,14 +96,16 @@ class SeasonalDiscoveryService: self._ensure_database_schema() def _get_source(self): - """Determine active music source (matches _get_active_discovery_source in web_server)""" - if self.spotify_client and self.spotify_client.is_spotify_authenticated(): - return 'spotify' + """Determine active music source — respects user's configured primary source""" try: - from core.metadata_service import _get_configured_fallback_source - return _get_configured_fallback_source() + from config.settings import config_manager + source = config_manager.get('metadata.fallback_source', 'deezer') or 'deezer' + # If user selected spotify, verify it's actually authenticated + if source == 'spotify' and not (self.spotify_client and self.spotify_client.is_spotify_authenticated()): + return 'deezer' + return source except Exception: - return 'itunes' + return 'deezer' def _ensure_database_schema(self): """Create seasonal content tables if they don't exist""" diff --git a/web_server.py b/web_server.py index 00d2f520..8da844fe 100644 --- a/web_server.py +++ b/web_server.py @@ -47377,11 +47377,10 @@ def playlist_explorer_build_tree(): if not tracks: return jsonify({"success": False, "error": "Playlist has no tracks"}), 400 - # Determine active metadata source - spotify_available = spotify_client and spotify_client.is_spotify_authenticated() - if spotify_available: + # Determine active metadata source — respect user's configured primary + source_name = _get_active_discovery_source() + if source_name == 'spotify' and spotify_client and spotify_client.is_spotify_authenticated(): active_client = spotify_client - source_name = 'spotify' else: active_client = _get_metadata_fallback_client() source_name = _get_metadata_fallback_source()