mirror of
https://github.com/navidrome/navidrome.git
synced 2026-06-19 07:37:15 +00:00
fix(scrobbler): proxy NowPlaying even when ignoreScrobble is set (#5559)
* fix(scrobbler): proxy NowPlaying even when ignoreScrobble is set When a client reports playback with ignoreScrobble=true, the reportPlayback handler suppressed both the scrobble submission and the NowPlaying update sent to external agents (Last.fm, ListenBrainz, plugins). These are independent concerns: ignoring the scrobble submission should not stop Navidrome from telling external services what is currently playing. The !params.IgnoreScrobble guard now applies only to the scrobble submission and play-count path; the NowPlaying dispatch is gated solely by the player's ScrobbleEnabled flag. This mirrors the legacy scrobble endpoint, where submission=false has always still set NowPlaying. * test(scrobbler): assert no scrobble dispatch when ignoreScrobble=true Address PR review feedback: explicitly verify that ignoreScrobble=true suppresses the scrobble submission (not just the play count) while NowPlaying is still dispatched, so the flag cannot regress into ignoring nothing. Also expand the NowPlaying gating comment to spell out the IgnoreScrobble vs ScrobbleEnabled rules and identify the external agents involved.
This commit is contained in:
@@ -371,7 +371,14 @@ func (p *playTracker) ReportPlayback(ctx context.Context, params ReportPlaybackP
|
||||
p.broker.SendBroadcastMessage(ctx, &events.NowPlayingCount{Count: p.playMap.Len()})
|
||||
}
|
||||
|
||||
if !params.IgnoreScrobble && player.ScrobbleEnabled &&
|
||||
// NowPlaying gating, by design distinct from scrobble submission:
|
||||
// - IgnoreScrobble=true -> still send NowPlaying (suppresses only the
|
||||
// scrobble submission/play-count above), mirroring the legacy scrobble
|
||||
// endpoint's submission=false behavior.
|
||||
// - player.ScrobbleEnabled=false -> never send NowPlaying.
|
||||
// External agents here are the active scrobblers (Last.fm, ListenBrainz, and
|
||||
// scrobbler plugins) returned by getActiveScrobblers; see dispatchNowPlaying.
|
||||
if player.ScrobbleEnabled &&
|
||||
(params.State == StateStarting || params.State == StatePlaying) {
|
||||
if info, err := p.playMap.Get(clientId); err == nil {
|
||||
p.enqueueNowPlaying(ctx, clientId, user.ID, &info.MediaFile, int(params.PositionMs/1000))
|
||||
|
||||
@@ -521,6 +521,7 @@ var _ = Describe("PlayTracker", func() {
|
||||
})
|
||||
|
||||
It("does NOT scrobble when ignoreScrobble=true even if threshold met", func() {
|
||||
fake.ScrobbleCalled.Store(false)
|
||||
err := tracker.ReportPlayback(ctx, ReportPlaybackParams{
|
||||
MediaId: "123", PositionMs: 0, State: "starting", PlaybackRate: 1.0, ClientId: defaultClientId,
|
||||
})
|
||||
@@ -531,6 +532,7 @@ var _ = Describe("PlayTracker", func() {
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(track.PlayCount).To(Equal(int64(0)))
|
||||
Consistently(func() bool { return fake.ScrobbleCalled.Load() }).Should(BeFalse())
|
||||
})
|
||||
|
||||
It("does NOT scrobble when player ScrobbleEnabled=false even if threshold met", func() {
|
||||
@@ -715,14 +717,14 @@ var _ = Describe("PlayTracker", func() {
|
||||
Consistently(func() bool { return fake.GetNowPlayingCalled() }).Should(BeFalse())
|
||||
})
|
||||
|
||||
It("does NOT dispatch when ignoreScrobble=true", func() {
|
||||
It("still dispatches NowPlaying when ignoreScrobble=true", func() {
|
||||
fake.nowPlayingCalled.Store(false)
|
||||
err := tracker.ReportPlayback(ctx, ReportPlaybackParams{
|
||||
MediaId: "123", PositionMs: 0, State: "starting", PlaybackRate: 1.0, ClientId: defaultClientId,
|
||||
IgnoreScrobble: true,
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Consistently(func() bool { return fake.GetNowPlayingCalled() }).Should(BeFalse())
|
||||
Eventually(func() bool { return fake.GetNowPlayingCalled() }).Should(BeTrue())
|
||||
})
|
||||
|
||||
It("does NOT dispatch when ScrobbleEnabled=false", func() {
|
||||
|
||||
Reference in New Issue
Block a user