diff --git a/allstarr/Models/Settings/SpotifyImportSettings.cs b/allstarr/Models/Settings/SpotifyImportSettings.cs index ab15df9..ce8a55e 100644 --- a/allstarr/Models/Settings/SpotifyImportSettings.cs +++ b/allstarr/Models/Settings/SpotifyImportSettings.cs @@ -28,8 +28,9 @@ public class SpotifyPlaylistConfig public string Name { get; set; } = string.Empty; /// - /// Jellyfin playlist ID (get from playlist URL) - /// Example: "4383a46d8bcac3be2ef9385053ea18df" + /// Spotify playlist ID (get from Spotify playlist URL) + /// Example: "37i9dQZF1DXcBWIGoYBM5M" (from open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M) + /// Required for personalized playlists like Discover Weekly, Release Radar, etc. /// public string Id { get; set; } = string.Empty; diff --git a/allstarr/Program.cs b/allstarr/Program.cs index ac3af6c..1750887 100644 --- a/allstarr/Program.cs +++ b/allstarr/Program.cs @@ -144,6 +144,9 @@ builder.Services.Configure(options => var playlistArrays = System.Text.Json.JsonSerializer.Deserialize(playlistsEnv); if (playlistArrays != null && playlistArrays.Length > 0) { + // Clear any playlists that Bind() may have incorrectly populated + options.Playlists.Clear(); + Console.WriteLine($"Parsed {playlistArrays.Length} playlists from JSON format"); foreach (var arr in playlistArrays) { diff --git a/allstarr/Services/Spotify/SpotifyPlaylistFetcher.cs b/allstarr/Services/Spotify/SpotifyPlaylistFetcher.cs index 109d4d7..051902b 100644 --- a/allstarr/Services/Spotify/SpotifyPlaylistFetcher.cs +++ b/allstarr/Services/Spotify/SpotifyPlaylistFetcher.cs @@ -90,37 +90,50 @@ public class SpotifyPlaylistFetcher : BackgroundService } } - // Need to fetch fresh - try to use cached Spotify playlist ID + // Need to fetch fresh - try to use cached or configured Spotify playlist ID if (!_playlistNameToSpotifyId.TryGetValue(playlistName, out var spotifyId)) { - _logger.LogDebug("Spotify playlist ID not cached for '{Name}', searching...", playlistName); - var playlists = await _spotifyClient.SearchUserPlaylistsAsync(playlistName); - - var exactMatch = playlists.FirstOrDefault(p => - p.Name.Equals(playlistName, StringComparison.OrdinalIgnoreCase)); - - if (exactMatch == null) + // Check if we have a configured Spotify ID for this playlist + var playlistConfig = _spotifyImportSettings.GetPlaylistByName(playlistName); + if (playlistConfig != null && !string.IsNullOrEmpty(playlistConfig.Id)) { - _logger.LogWarning("Could not find Spotify playlist named '{Name}'", playlistName); + // Use the configured Spotify playlist ID directly + spotifyId = playlistConfig.Id; + _playlistNameToSpotifyId[playlistName] = spotifyId; + _logger.LogInformation("Using configured Spotify playlist ID for '{Name}': {Id}", playlistName, spotifyId); + } + else + { + // No configured ID, try searching by name (works for public/followed playlists) + _logger.LogDebug("No configured Spotify ID for '{Name}', searching...", playlistName); + var playlists = await _spotifyClient.SearchUserPlaylistsAsync(playlistName); - // Return file cache even if expired, as a fallback - if (File.Exists(filePath)) + var exactMatch = playlists.FirstOrDefault(p => + p.Name.Equals(playlistName, StringComparison.OrdinalIgnoreCase)); + + if (exactMatch == null) { - var json = await File.ReadAllTextAsync(filePath); - var fallback = JsonSerializer.Deserialize(json); - if (fallback != null) + _logger.LogWarning("Could not find Spotify playlist named '{Name}' - try configuring the Spotify playlist ID", playlistName); + + // Return file cache even if expired, as a fallback + if (File.Exists(filePath)) { - _logger.LogWarning("Using expired file cache as fallback for '{Name}'", playlistName); - return fallback.Tracks; + var json = await File.ReadAllTextAsync(filePath); + var fallback = JsonSerializer.Deserialize(json); + if (fallback != null) + { + _logger.LogWarning("Using expired file cache as fallback for '{Name}'", playlistName); + return fallback.Tracks; + } } + + return new List(); } - return new List(); + spotifyId = exactMatch.SpotifyId; + _playlistNameToSpotifyId[playlistName] = spotifyId; + _logger.LogInformation("Found Spotify playlist '{Name}' with ID: {Id}", playlistName, spotifyId); } - - spotifyId = exactMatch.SpotifyId; - _playlistNameToSpotifyId[playlistName] = spotifyId; - _logger.LogInformation("Found Spotify playlist '{Name}' with ID: {Id}", playlistName, spotifyId); } // Fetch the full playlist