fix: preserve user context in async NowPlaying dispatch

Fixed issue #4787 where plugin scrobblers received an empty username during NowPlaying events. The async worker was passing context.Background() which lost all user information.

Changed nowPlayingEntry to store the full context (with cancellation removed via context.WithoutCancel) and pass it to dispatchNowPlaying. This ensures plugin scrobblers can extract username from the context for authorization checks.

Updated tests to verify username is properly propagated through the async workflow, matching the actual plugin adapter behavior of checking both request.UsernameFrom and request.UserFrom.
This commit is contained in:
Deluan
2025-12-09 08:43:56 -05:00
parent cc3cca6077
commit 396eee48c6
2 changed files with 35 additions and 3 deletions
+6 -3
View File
@@ -32,6 +32,7 @@ type Submission struct {
}
type nowPlayingEntry struct {
ctx context.Context
userId string
track *model.MediaFile
position int
@@ -220,15 +221,17 @@ func (p *playTracker) NowPlaying(ctx context.Context, playerId string, playerNam
}
player, _ := request.PlayerFrom(ctx)
if player.ScrobbleEnabled {
p.enqueueNowPlaying(playerId, user.ID, mf, position)
p.enqueueNowPlaying(ctx, playerId, user.ID, mf, position)
}
return nil
}
func (p *playTracker) enqueueNowPlaying(playerId string, userId string, track *model.MediaFile, position int) {
func (p *playTracker) enqueueNowPlaying(ctx context.Context, playerId string, userId string, track *model.MediaFile, position int) {
p.npMu.Lock()
defer p.npMu.Unlock()
ctx = context.WithoutCancel(ctx) // Prevent cancellation from affecting background processing
p.npQueue[playerId] = nowPlayingEntry{
ctx: ctx,
userId: userId,
track: track,
position: position,
@@ -267,7 +270,7 @@ func (p *playTracker) nowPlayingWorker() {
// Process entries without holding lock
for _, entry := range entries {
p.dispatchNowPlaying(context.Background(), entry.userId, entry.track, entry.position)
p.dispatchNowPlaying(entry.ctx, entry.userId, entry.track, entry.position)
}
}
}