mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-09 15:45:10 -05:00
Fix scrobbling: track playing item in session and send proper PlaybackStopped data on cleanup
This commit is contained in:
@@ -2006,6 +2006,7 @@ public class JellyfinController : ControllerBase
|
||||
var doc = JsonDocument.Parse(body);
|
||||
string? itemId = null;
|
||||
string? itemName = null;
|
||||
long? positionTicks = null;
|
||||
|
||||
if (doc.RootElement.TryGetProperty("ItemId", out var itemIdProp))
|
||||
{
|
||||
@@ -2016,6 +2017,18 @@ public class JellyfinController : ControllerBase
|
||||
{
|
||||
itemName = itemNameProp.GetString();
|
||||
}
|
||||
|
||||
if (doc.RootElement.TryGetProperty("PositionTicks", out var posProp))
|
||||
{
|
||||
positionTicks = posProp.GetInt64();
|
||||
}
|
||||
|
||||
// Track the playing item for scrobbling on session cleanup
|
||||
var (deviceId, client, device, version) = ExtractDeviceInfo(Request.Headers);
|
||||
if (!string.IsNullOrEmpty(deviceId) && !string.IsNullOrEmpty(itemId))
|
||||
{
|
||||
_sessionManager.UpdatePlayingItem(deviceId, itemId, positionTicks);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(itemId))
|
||||
{
|
||||
@@ -2050,7 +2063,7 @@ public class JellyfinController : ControllerBase
|
||||
var playbackStart = new
|
||||
{
|
||||
ItemId = itemId,
|
||||
PositionTicks = doc.RootElement.TryGetProperty("PositionTicks", out var posProp) ? posProp.GetInt64() : 0,
|
||||
PositionTicks = positionTicks ?? 0,
|
||||
// Let Jellyfin fetch the item details - don't include NowPlayingItem
|
||||
};
|
||||
|
||||
@@ -2064,7 +2077,6 @@ public class JellyfinController : ControllerBase
|
||||
_logger.LogInformation("✓ Playback start forwarded to Jellyfin ({StatusCode})", statusCode);
|
||||
|
||||
// NOW ensure session exists with capabilities (after playback is reported)
|
||||
var (deviceId, client, device, version) = ExtractDeviceInfo(Request.Headers);
|
||||
if (!string.IsNullOrEmpty(deviceId))
|
||||
{
|
||||
var sessionCreated = await _sessionManager.EnsureSessionAsync(deviceId, client ?? "Unknown", device ?? "Unknown", version ?? "1.0", Request.Headers);
|
||||
@@ -2155,6 +2167,12 @@ public class JellyfinController : ControllerBase
|
||||
positionTicks = posProp.GetInt64();
|
||||
}
|
||||
|
||||
// Track the playing item for scrobbling on session cleanup
|
||||
if (!string.IsNullOrEmpty(deviceId) && !string.IsNullOrEmpty(itemId))
|
||||
{
|
||||
_sessionManager.UpdatePlayingItem(deviceId, itemId, positionTicks);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(itemId))
|
||||
{
|
||||
var (isExternal, provider, externalId) = _localLibraryService.ParseSongId(itemId);
|
||||
|
||||
@@ -142,6 +142,21 @@ public class JellyfinSessionManager : IDisposable
|
||||
_logger.LogDebug("⚠️ SESSION: Cannot update activity - device {DeviceId} not found", deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the currently playing item for a session (for scrobbling on cleanup).
|
||||
/// </summary>
|
||||
public void UpdatePlayingItem(string deviceId, string? itemId, long? positionTicks)
|
||||
{
|
||||
if (_sessions.TryGetValue(deviceId, out var session))
|
||||
{
|
||||
session.LastPlayingItemId = itemId;
|
||||
session.LastPlayingPositionTicks = positionTicks;
|
||||
session.LastActivity = DateTime.UtcNow;
|
||||
_logger.LogDebug("🎵 SESSION: Updated playing item for {DeviceId}: {ItemId} at {Position}",
|
||||
deviceId, itemId, positionTicks);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks a session as potentially ended (e.g., after playback stops).
|
||||
@@ -230,10 +245,19 @@ public class JellyfinSessionManager : IDisposable
|
||||
|
||||
try
|
||||
{
|
||||
// Report playback stopped to Jellyfin
|
||||
var stopPayload = JsonSerializer.Serialize(new { });
|
||||
await _proxyService.PostJsonAsync("Sessions/Playing/Stopped", stopPayload, session.Headers);
|
||||
_logger.LogDebug("🛑 SESSION: Reported playback stopped for {DeviceId}", deviceId);
|
||||
// Report playback stopped to Jellyfin if we have a playing item (for scrobbling)
|
||||
if (!string.IsNullOrEmpty(session.LastPlayingItemId))
|
||||
{
|
||||
var stopPayload = new
|
||||
{
|
||||
ItemId = session.LastPlayingItemId,
|
||||
PositionTicks = session.LastPlayingPositionTicks ?? 0
|
||||
};
|
||||
var stopJson = JsonSerializer.Serialize(stopPayload);
|
||||
await _proxyService.PostJsonAsync("Sessions/Playing/Stopped", stopJson, session.Headers);
|
||||
_logger.LogInformation("🛑 SESSION: Reported playback stopped for {DeviceId} (ItemId: {ItemId}, Position: {Position})",
|
||||
deviceId, session.LastPlayingItemId, session.LastPlayingPositionTicks);
|
||||
}
|
||||
|
||||
// Notify Jellyfin that the session is ending
|
||||
await _proxyService.PostJsonAsync("Sessions/Logout", "{}", session.Headers);
|
||||
@@ -500,6 +524,8 @@ public class JellyfinSessionManager : IDisposable
|
||||
public DateTime LastActivity { get; set; }
|
||||
public required IHeaderDictionary Headers { get; init; }
|
||||
public ClientWebSocket? WebSocket { get; set; }
|
||||
public string? LastPlayingItemId { get; set; }
|
||||
public long? LastPlayingPositionTicks { get; set; }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
Reference in New Issue
Block a user