feat(server): add option Lastfm.ScrobbleFirstArtistOnly to send only the first artist (#4131)
fixes #3791 Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
@@ -158,6 +158,7 @@ type lastfmOptions struct {
|
|||||||
ApiKey string
|
ApiKey string
|
||||||
Secret string
|
Secret string
|
||||||
Language string
|
Language string
|
||||||
|
ScrobbleFirstArtistOnly bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type spotifyOptions struct {
|
type spotifyOptions struct {
|
||||||
@@ -528,6 +529,7 @@ func setViperDefaults() {
|
|||||||
viper.SetDefault("lastfm.language", "en")
|
viper.SetDefault("lastfm.language", "en")
|
||||||
viper.SetDefault("lastfm.apikey", "")
|
viper.SetDefault("lastfm.apikey", "")
|
||||||
viper.SetDefault("lastfm.secret", "")
|
viper.SetDefault("lastfm.secret", "")
|
||||||
|
viper.SetDefault("lastfm.scrobblefirstartistonly", false)
|
||||||
viper.SetDefault("spotify.id", "")
|
viper.SetDefault("spotify.id", "")
|
||||||
viper.SetDefault("spotify.secret", "")
|
viper.SetDefault("spotify.secret", "")
|
||||||
viper.SetDefault("listenbrainz.enabled", true)
|
viper.SetDefault("listenbrainz.enabled", true)
|
||||||
|
|||||||
@@ -279,6 +279,13 @@ func (l *lastfmAgent) callArtistGetTopTracks(ctx context.Context, artistName str
|
|||||||
return t.Track, nil
|
return t.Track, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *lastfmAgent) getArtistForScrobble(track *model.MediaFile) string {
|
||||||
|
if conf.Server.LastFM.ScrobbleFirstArtistOnly && len(track.Participants[model.RoleArtist]) > 0 {
|
||||||
|
return track.Participants[model.RoleArtist][0].Name
|
||||||
|
}
|
||||||
|
return track.Artist
|
||||||
|
}
|
||||||
|
|
||||||
func (l *lastfmAgent) NowPlaying(ctx context.Context, userId string, track *model.MediaFile) error {
|
func (l *lastfmAgent) NowPlaying(ctx context.Context, userId string, track *model.MediaFile) error {
|
||||||
sk, err := l.sessionKeys.Get(ctx, userId)
|
sk, err := l.sessionKeys.Get(ctx, userId)
|
||||||
if err != nil || sk == "" {
|
if err != nil || sk == "" {
|
||||||
@@ -286,7 +293,7 @@ func (l *lastfmAgent) NowPlaying(ctx context.Context, userId string, track *mode
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = l.client.updateNowPlaying(ctx, sk, ScrobbleInfo{
|
err = l.client.updateNowPlaying(ctx, sk, ScrobbleInfo{
|
||||||
artist: track.Artist,
|
artist: l.getArtistForScrobble(track),
|
||||||
track: track.Title,
|
track: track.Title,
|
||||||
album: track.Album,
|
album: track.Album,
|
||||||
trackNumber: track.TrackNumber,
|
trackNumber: track.TrackNumber,
|
||||||
@@ -312,7 +319,7 @@ func (l *lastfmAgent) Scrobble(ctx context.Context, userId string, s scrobbler.S
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
err = l.client.scrobble(ctx, sk, ScrobbleInfo{
|
err = l.client.scrobble(ctx, sk, ScrobbleInfo{
|
||||||
artist: s.Artist,
|
artist: l.getArtistForScrobble(&s.MediaFile),
|
||||||
track: s.Title,
|
track: s.Title,
|
||||||
album: s.Album,
|
album: s.Album,
|
||||||
trackNumber: s.TrackNumber,
|
trackNumber: s.TrackNumber,
|
||||||
|
|||||||
@@ -196,6 +196,12 @@ var _ = Describe("lastfmAgent", func() {
|
|||||||
TrackNumber: 1,
|
TrackNumber: 1,
|
||||||
Duration: 180,
|
Duration: 180,
|
||||||
MbzRecordingID: "mbz-123",
|
MbzRecordingID: "mbz-123",
|
||||||
|
Participants: map[model.Role]model.ParticipantList{
|
||||||
|
model.RoleArtist: []model.Participant{
|
||||||
|
{Artist: model.Artist{ID: "ar-1", Name: "First Artist"}},
|
||||||
|
{Artist: model.Artist{ID: "ar-2", Name: "Second Artist"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -247,6 +253,23 @@ var _ = Describe("lastfmAgent", func() {
|
|||||||
Expect(sentParams.Get("timestamp")).To(Equal(strconv.FormatInt(ts.Unix(), 10)))
|
Expect(sentParams.Get("timestamp")).To(Equal(strconv.FormatInt(ts.Unix(), 10)))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
When("ScrobbleFirstArtistOnly is true", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
conf.Server.LastFM.ScrobbleFirstArtistOnly = true
|
||||||
|
})
|
||||||
|
|
||||||
|
It("uses only the first artist", func() {
|
||||||
|
ts := time.Now()
|
||||||
|
httpClient.Res = http.Response{Body: io.NopCloser(bytes.NewBufferString("{}")), StatusCode: 200}
|
||||||
|
|
||||||
|
err := agent.Scrobble(ctx, "user-1", scrobbler.Scrobble{MediaFile: *track, TimeStamp: ts})
|
||||||
|
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
sentParams := httpClient.SavedRequest.URL.Query()
|
||||||
|
Expect(sentParams.Get("artist")).To(Equal("First Artist"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
It("skips songs with less than 31 seconds", func() {
|
It("skips songs with less than 31 seconds", func() {
|
||||||
track.Duration = 29
|
track.Duration = 29
|
||||||
httpClient.Res = http.Response{Body: io.NopCloser(bytes.NewBufferString("{}")), StatusCode: 200}
|
httpClient.Res = http.Response{Body: io.NopCloser(bytes.NewBufferString("{}")), StatusCode: 200}
|
||||||
|
|||||||
Reference in New Issue
Block a user