Update Spotify playlist ChildCount to show actual track count

- Intercept playlist list responses and update ChildCount for Spotify playlists
- Shows the number of missing tracks found (local + matched external)
- Fixes playlist showing 0 songs when Jellyfin has no local files
- Reads from cache (Redis or file) to get accurate count
This commit is contained in:
2026-02-01 11:38:25 -05:00
parent eb46692b25
commit 24df910ffa

View File

@@ -1824,6 +1824,12 @@ public class JellyfinController : ControllerBase
return NoContent(); return NoContent();
} }
// Modify response if it contains Spotify playlists to update ChildCount
if (_spotifySettings.Enabled && result.RootElement.TryGetProperty("Items", out var items))
{
result = await UpdateSpotifyPlaylistCounts(result);
}
return new JsonResult(JsonSerializer.Deserialize<object>(result.RootElement.GetRawText())); return new JsonResult(JsonSerializer.Deserialize<object>(result.RootElement.GetRawText()));
} }
catch (Exception ex) catch (Exception ex)
@@ -1837,6 +1843,91 @@ public class JellyfinController : ControllerBase
#region Helpers #region Helpers
/// <summary>
/// Updates ChildCount for Spotify playlists in the response to show total tracks (local + matched).
/// </summary>
private async Task<JsonDocument> UpdateSpotifyPlaylistCounts(JsonDocument response)
{
try
{
if (!response.RootElement.TryGetProperty("Items", out var items))
{
return response;
}
var itemsArray = items.EnumerateArray().ToList();
var modified = false;
var updatedItems = new List<Dictionary<string, object>>();
foreach (var item in itemsArray)
{
var itemDict = JsonSerializer.Deserialize<Dictionary<string, object>>(item.GetRawText());
if (itemDict == null)
{
continue;
}
// Check if this is a Spotify playlist
if (item.TryGetProperty("Id", out var idProp))
{
var playlistId = idProp.GetString();
if (!string.IsNullOrEmpty(playlistId) &&
_spotifySettings.PlaylistIds.Any(id => id.Equals(playlistId, StringComparison.OrdinalIgnoreCase)))
{
// This is a Spotify playlist - get the actual track count
var playlistIndex = _spotifySettings.PlaylistIds.FindIndex(id =>
id.Equals(playlistId, StringComparison.OrdinalIgnoreCase));
if (playlistIndex >= 0 && playlistIndex < _spotifySettings.PlaylistNames.Count)
{
var playlistName = _spotifySettings.PlaylistNames[playlistIndex];
var missingTracksKey = $"spotify:missing:{playlistName}";
var missingTracks = await _cache.GetAsync<List<allstarr.Models.Spotify.MissingTrack>>(missingTracksKey);
// Fallback to file cache
if (missingTracks == null || missingTracks.Count == 0)
{
missingTracks = await LoadMissingTracksFromFile(playlistName);
}
if (missingTracks != null && missingTracks.Count > 0)
{
// Update ChildCount to show the number of tracks we'll provide
itemDict["ChildCount"] = missingTracks.Count;
modified = true;
_logger.LogDebug("Updated ChildCount for Spotify playlist {Name} to {Count}",
playlistName, missingTracks.Count);
}
}
}
}
updatedItems.Add(itemDict);
}
if (!modified)
{
return response;
}
// Rebuild the response with updated items
var responseDict = JsonSerializer.Deserialize<Dictionary<string, object>>(response.RootElement.GetRawText());
if (responseDict != null)
{
responseDict["Items"] = updatedItems;
var updatedJson = JsonSerializer.Serialize(responseDict);
return JsonDocument.Parse(updatedJson);
}
return response;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to update Spotify playlist counts");
return response;
}
}
private static string[]? ParseItemTypes(string? includeItemTypes) private static string[]? ParseItemTypes(string? includeItemTypes)
{ {
if (string.IsNullOrWhiteSpace(includeItemTypes)) if (string.IsNullOrWhiteSpace(includeItemTypes))