Fix playlist config: dedupe entries, use Spotify playlist ID for lookup

This commit is contained in:
2026-02-03 16:12:25 -05:00
parent df7f11e769
commit 2c1297ebec
3 changed files with 40 additions and 23 deletions

View File

@@ -28,8 +28,9 @@ public class SpotifyPlaylistConfig
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
/// <summary> /// <summary>
/// Jellyfin playlist ID (get from playlist URL) /// Spotify playlist ID (get from Spotify playlist URL)
/// Example: "4383a46d8bcac3be2ef9385053ea18df" /// Example: "37i9dQZF1DXcBWIGoYBM5M" (from open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M)
/// Required for personalized playlists like Discover Weekly, Release Radar, etc.
/// </summary> /// </summary>
public string Id { get; set; } = string.Empty; public string Id { get; set; } = string.Empty;

View File

@@ -144,6 +144,9 @@ builder.Services.Configure<SpotifyImportSettings>(options =>
var playlistArrays = System.Text.Json.JsonSerializer.Deserialize<string[][]>(playlistsEnv); var playlistArrays = System.Text.Json.JsonSerializer.Deserialize<string[][]>(playlistsEnv);
if (playlistArrays != null && playlistArrays.Length > 0) 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"); Console.WriteLine($"Parsed {playlistArrays.Length} playlists from JSON format");
foreach (var arr in playlistArrays) foreach (var arr in playlistArrays)
{ {

View File

@@ -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)) if (!_playlistNameToSpotifyId.TryGetValue(playlistName, out var spotifyId))
{ {
_logger.LogDebug("Spotify playlist ID not cached for '{Name}', searching...", playlistName); // Check if we have a configured Spotify ID for this playlist
var playlists = await _spotifyClient.SearchUserPlaylistsAsync(playlistName); var playlistConfig = _spotifyImportSettings.GetPlaylistByName(playlistName);
if (playlistConfig != null && !string.IsNullOrEmpty(playlistConfig.Id))
var exactMatch = playlists.FirstOrDefault(p =>
p.Name.Equals(playlistName, StringComparison.OrdinalIgnoreCase));
if (exactMatch == null)
{ {
_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 var exactMatch = playlists.FirstOrDefault(p =>
if (File.Exists(filePath)) p.Name.Equals(playlistName, StringComparison.OrdinalIgnoreCase));
if (exactMatch == null)
{ {
var json = await File.ReadAllTextAsync(filePath); _logger.LogWarning("Could not find Spotify playlist named '{Name}' - try configuring the Spotify playlist ID", playlistName);
var fallback = JsonSerializer.Deserialize<SpotifyPlaylist>(json);
if (fallback != null) // Return file cache even if expired, as a fallback
if (File.Exists(filePath))
{ {
_logger.LogWarning("Using expired file cache as fallback for '{Name}'", playlistName); var json = await File.ReadAllTextAsync(filePath);
return fallback.Tracks; var fallback = JsonSerializer.Deserialize<SpotifyPlaylist>(json);
if (fallback != null)
{
_logger.LogWarning("Using expired file cache as fallback for '{Name}'", playlistName);
return fallback.Tracks;
}
} }
return new List<SpotifyPlaylistTrack>();
} }
return new List<SpotifyPlaylistTrack>(); 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 // Fetch the full playlist