mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-01 07:21:17 +00:00
Merge 3e7d8bcef89a91d1c5a417a7e58fc8602290992a into 600ea5482c36d3705fbca1d9ab749d9bdafd6f80
This commit is contained in:
commit
68e9f6d330
@ -370,11 +370,26 @@ func (l *lastfmAgent) NowPlaying(ctx context.Context, userId string, track *mode
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn(ctx, "Last.fm client.updateNowPlaying returned error", "track", track.Title, err)
|
||||
l.dropSessionKeyIfInvalid(ctx, userId, err)
|
||||
return errors.Join(err, scrobbler.ErrUnrecoverable)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// dropSessionKeyIfInvalid discards a session key that Last.fm has rejected, so the
|
||||
// account stops reporting as linked and the user is prompted to re-authenticate
|
||||
// instead of scrobbles failing silently.
|
||||
func (l *lastfmAgent) dropSessionKeyIfInvalid(ctx context.Context, userId string, err error) {
|
||||
var lfErr *lastFMError
|
||||
if !errors.As(err, &lfErr) || lfErr.Code != errorInvalidSessionKey {
|
||||
return
|
||||
}
|
||||
log.Warn(ctx, "Last.fm session key was rejected, unlinking account", "userId", userId, err)
|
||||
if delErr := l.sessionKeys.Delete(ctx, userId); delErr != nil {
|
||||
log.Error(ctx, "Could not delete rejected Last.fm session key", "userId", userId, delErr)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *lastfmAgent) Scrobble(ctx context.Context, userId string, s scrobbler.Scrobble) error {
|
||||
sk, err := l.sessionKeys.Get(ctx, userId)
|
||||
if err != nil || sk == "" {
|
||||
@ -407,6 +422,7 @@ func (l *lastfmAgent) Scrobble(ctx context.Context, userId string, s scrobbler.S
|
||||
if lfErr.Code == 11 || lfErr.Code == 16 {
|
||||
return errors.Join(err, scrobbler.ErrRetryLater)
|
||||
}
|
||||
l.dropSessionKeyIfInvalid(ctx, userId, err)
|
||||
return errors.Join(err, scrobbler.ErrUnrecoverable)
|
||||
}
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@ import (
|
||||
const (
|
||||
lastfmError3 = `{"error":3,"message":"Invalid Method - No method with that name in this package","links":[]}`
|
||||
lastfmError6 = `{"error":6,"message":"The artist you supplied could not be found","links":[]}`
|
||||
lastfmError9 = `{"error":9,"message":"Invalid session key - Please re-authenticate","links":[]}`
|
||||
)
|
||||
|
||||
var _ = Describe("lastfmAgent", func() {
|
||||
@ -516,6 +517,32 @@ var _ = Describe("lastfmAgent", func() {
|
||||
err := agent.Scrobble(ctx, "user-1", scrobbler.Scrobble{MediaFile: *track, TimeStamp: time.Now()})
|
||||
Expect(err).To(MatchError(scrobbler.ErrUnrecoverable))
|
||||
})
|
||||
|
||||
It("unlinks the account when the session key is rejected", func() {
|
||||
httpClient.Res = http.Response{
|
||||
Body: io.NopCloser(bytes.NewBufferString(lastfmError9)),
|
||||
StatusCode: 403,
|
||||
}
|
||||
|
||||
err := agent.Scrobble(ctx, "user-1", scrobbler.Scrobble{MediaFile: *track, TimeStamp: time.Now()})
|
||||
|
||||
Expect(err).To(MatchError(scrobbler.ErrUnrecoverable))
|
||||
Expect(agent.IsAuthorized(ctx, "user-1")).To(BeFalse())
|
||||
})
|
||||
})
|
||||
|
||||
Describe("session key rejected during NowPlaying", func() {
|
||||
It("unlinks the account", func() {
|
||||
httpClient.Res = http.Response{
|
||||
Body: io.NopCloser(bytes.NewBufferString(lastfmError9)),
|
||||
StatusCode: 403,
|
||||
}
|
||||
|
||||
err := agent.NowPlaying(ctx, "user-1", track, 0)
|
||||
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(agent.IsAuthorized(ctx, "user-1")).To(BeFalse())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -19,6 +19,9 @@ import (
|
||||
|
||||
const (
|
||||
apiBaseUrl = "https://ws.audioscrobbler.com/2.0/"
|
||||
|
||||
// https://www.last.fm/api/errorcodes
|
||||
errorInvalidSessionKey = 9
|
||||
)
|
||||
|
||||
type lastFMError struct {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user