diff --git a/allstarr/Controllers/JellyfinController.cs b/allstarr/Controllers/JellyfinController.cs
index 95f74fc..13e2fc8 100644
--- a/allstarr/Controllers/JellyfinController.cs
+++ b/allstarr/Controllers/JellyfinController.cs
@@ -1130,11 +1130,20 @@ public class JellyfinController : ControllerBase
///
/// Marks an item as favorite. For playlists, triggers a full download.
+ /// Supports both /Users/{userId}/FavoriteItems/{itemId} and /UserFavoriteItems/{itemId}?userId=xxx
///
[HttpPost("Users/{userId}/FavoriteItems/{itemId}")]
- public async Task MarkFavorite(string userId, string itemId)
+ [HttpPost("UserFavoriteItems/{itemId}")]
+ public async Task MarkFavorite(string itemId, string? userId = null)
{
- _logger.LogInformation("MarkFavorite called: userId={UserId}, itemId={ItemId}", userId, itemId);
+ // Get userId from query string if not in path
+ if (string.IsNullOrEmpty(userId))
+ {
+ userId = Request.Query["userId"].ToString();
+ }
+
+ _logger.LogInformation("MarkFavorite called: userId={UserId}, itemId={ItemId}, route={Route}",
+ userId, itemId, Request.Path);
// Check if this is an external playlist - trigger download
if (PlaylistIdHelper.IsExternalPlaylist(itemId))
@@ -1195,7 +1204,13 @@ public class JellyfinController : ControllerBase
}
// For local Jellyfin items, proxy the request through
- var endpoint = $"Users/{userId}/FavoriteItems/{itemId}";
+ // Use the official Jellyfin endpoint format
+ var endpoint = $"UserFavoriteItems/{itemId}";
+ if (!string.IsNullOrEmpty(userId))
+ {
+ endpoint = $"{endpoint}?userId={userId}";
+ }
+
_logger.LogInformation("Proxying favorite request to Jellyfin: {Endpoint}", endpoint);
var result = await _proxyService.PostJsonAsync(endpoint, "{}", Request.Headers);
@@ -1211,11 +1226,20 @@ public class JellyfinController : ControllerBase
///
/// Removes an item from favorites.
+ /// Supports both /Users/{userId}/FavoriteItems/{itemId} and /UserFavoriteItems/{itemId}?userId=xxx
///
[HttpDelete("Users/{userId}/FavoriteItems/{itemId}")]
- public async Task UnmarkFavorite(string userId, string itemId)
+ [HttpDelete("UserFavoriteItems/{itemId}")]
+ public async Task UnmarkFavorite(string itemId, string? userId = null)
{
- _logger.LogInformation("UnmarkFavorite called: userId={UserId}, itemId={ItemId}", userId, itemId);
+ // Get userId from query string if not in path
+ if (string.IsNullOrEmpty(userId))
+ {
+ userId = Request.Query["userId"].ToString();
+ }
+
+ _logger.LogInformation("UnmarkFavorite called: userId={UserId}, itemId={ItemId}, route={Route}",
+ userId, itemId, Request.Path);
// External items can't be unfavorited (they're not really favorited in Jellyfin)
var (isExternal, _, _) = _localLibraryService.ParseSongId(itemId);
@@ -1230,7 +1254,13 @@ public class JellyfinController : ControllerBase
}
// Proxy to Jellyfin to unfavorite
- var endpoint = $"Users/{userId}/FavoriteItems/{itemId}";
+ // Use the official Jellyfin endpoint format
+ var endpoint = $"UserFavoriteItems/{itemId}";
+ if (!string.IsNullOrEmpty(userId))
+ {
+ endpoint = $"{endpoint}?userId={userId}";
+ }
+
_logger.LogInformation("Proxying unfavorite request to Jellyfin: {Endpoint}", endpoint);
var result = await _proxyService.DeleteAsync(endpoint, Request.Headers);