mirror of
https://github.com/navidrome/navidrome.git
synced 2025-12-23 23:18:05 -05:00
feat(scrobble): add configuration option to enable scrobble history
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
@@ -102,7 +102,8 @@ type configOptions struct {
|
||||
Spotify spotifyOptions `json:",omitzero"`
|
||||
Deezer deezerOptions `json:",omitzero"`
|
||||
ListenBrainz listenBrainzOptions `json:",omitzero"`
|
||||
Tags map[string]TagConf `json:",omitempty"`
|
||||
EnableScrobbleHistory bool
|
||||
Tags map[string]TagConf `json:",omitempty"`
|
||||
Agents string
|
||||
|
||||
// DevFlags. These are used to enable/disable debugging and incomplete features
|
||||
@@ -598,6 +599,7 @@ func setViperDefaults() {
|
||||
viper.SetDefault("deezer.language", "en")
|
||||
viper.SetDefault("listenbrainz.enabled", true)
|
||||
viper.SetDefault("listenbrainz.baseurl", "https://api.listenbrainz.org/1/")
|
||||
viper.SetDefault("enablescrobblehistory", true)
|
||||
viper.SetDefault("httpsecurityheaders.customframeoptionsvalue", "DENY")
|
||||
viper.SetDefault("backup.path", "")
|
||||
viper.SetDefault("backup.schedule", "")
|
||||
|
||||
@@ -2,7 +2,6 @@ package scrobbler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"sort"
|
||||
"sync"
|
||||
@@ -335,10 +334,6 @@ func (p *playTracker) Submit(ctx context.Context, submissions []Submission) erro
|
||||
}
|
||||
|
||||
func (p *playTracker) incPlay(ctx context.Context, track *model.MediaFile, timestamp time.Time) error {
|
||||
user, ok := request.UserFrom(ctx)
|
||||
if !ok {
|
||||
return fmt.Errorf("user not found in context")
|
||||
}
|
||||
return p.ds.WithTx(func(tx model.DataStore) error {
|
||||
err := tx.MediaFile(ctx).IncPlayCount(track.ID, timestamp)
|
||||
if err != nil {
|
||||
@@ -354,7 +349,10 @@ func (p *playTracker) incPlay(ctx context.Context, track *model.MediaFile, times
|
||||
return err
|
||||
}
|
||||
}
|
||||
return tx.Scrobble(ctx).RecordScrobble(track.ID, user.ID, timestamp)
|
||||
if conf.Server.EnableScrobbleHistory {
|
||||
return tx.Scrobble(ctx).RecordScrobble(track.ID, timestamp)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ var _ = Describe("PlayTracker", func() {
|
||||
|
||||
BeforeEach(func() {
|
||||
DeferCleanup(configtest.SetupConfig())
|
||||
ctx = context.Background()
|
||||
ctx = GinkgoT().Context()
|
||||
ctx = request.WithUser(ctx, model.User{ID: "u-1"})
|
||||
ctx = request.WithPlayer(ctx, model.Player{ScrobbleEnabled: true})
|
||||
ds = &tests.MockDataStore{}
|
||||
@@ -177,9 +177,9 @@ var _ = Describe("PlayTracker", func() {
|
||||
track2 := track
|
||||
track2.ID = "456"
|
||||
_ = ds.MediaFile(ctx).Put(&track2)
|
||||
ctx = request.WithUser(context.Background(), model.User{UserName: "user-1"})
|
||||
ctx = request.WithUser(GinkgoT().Context(), model.User{UserName: "user-1"})
|
||||
_ = tracker.NowPlaying(ctx, "player-1", "player-one", "123", 0)
|
||||
ctx = request.WithUser(context.Background(), model.User{UserName: "user-2"})
|
||||
ctx = request.WithUser(GinkgoT().Context(), model.User{UserName: "user-2"})
|
||||
_ = tracker.NowPlaying(ctx, "player-2", "player-two", "456", 0)
|
||||
|
||||
playing, err := tracker.GetNowPlaying(ctx)
|
||||
@@ -235,6 +235,7 @@ var _ = Describe("PlayTracker", func() {
|
||||
})
|
||||
|
||||
It("records scrobble in repository", func() {
|
||||
conf.Server.EnableScrobbleHistory = true
|
||||
ctx = request.WithUser(ctx, model.User{ID: "u-1", UserName: "user-1"})
|
||||
ts := time.Now()
|
||||
|
||||
@@ -368,7 +369,7 @@ var _ = Describe("PlayTracker", func() {
|
||||
var mockedBS *mockBufferedScrobbler
|
||||
|
||||
BeforeEach(func() {
|
||||
ctx = context.Background()
|
||||
ctx = GinkgoT().Context()
|
||||
ctx = request.WithUser(ctx, model.User{ID: "u-1"})
|
||||
ctx = request.WithPlayer(ctx, model.Player{ScrobbleEnabled: true})
|
||||
ds = &tests.MockDataStore{}
|
||||
|
||||
@@ -9,5 +9,5 @@ type Scrobble struct {
|
||||
}
|
||||
|
||||
type ScrobbleRepository interface {
|
||||
RecordScrobble(mediaFileID, userID string, submissionTime time.Time) error
|
||||
RecordScrobble(mediaFileID string, submissionTime time.Time) error
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ func NewScrobbleRepository(ctx context.Context, db dbx.Builder) model.ScrobbleRe
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *scrobbleRepository) RecordScrobble(mediaFileID, userID string, submissionTime time.Time) error {
|
||||
func (r *scrobbleRepository) RecordScrobble(mediaFileID string, submissionTime time.Time) error {
|
||||
userID := loggedUser(r.ctx).ID
|
||||
values := map[string]interface{}{
|
||||
"media_file_id": mediaFileID,
|
||||
"user_id": userID,
|
||||
|
||||
@@ -23,7 +23,7 @@ var _ = Describe("ScrobbleRepository", func() {
|
||||
BeforeEach(func() {
|
||||
fileID = id.NewRandom()
|
||||
userID = id.NewRandom()
|
||||
ctx = request.WithUser(log.NewContext(context.TODO()), model.User{ID: "userid", UserName: "johndoe", IsAdmin: true})
|
||||
ctx = request.WithUser(log.NewContext(GinkgoT().Context()), model.User{ID: userID, UserName: "johndoe", IsAdmin: true})
|
||||
db := GetDBXBuilder()
|
||||
repo = NewScrobbleRepository(ctx, db)
|
||||
|
||||
@@ -63,7 +63,7 @@ var _ = Describe("ScrobbleRepository", func() {
|
||||
}).Execute()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
err = repo.RecordScrobble(fileID, userID, submissionTime)
|
||||
err = repo.RecordScrobble(fileID, submissionTime)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// Verify insertion
|
||||
|
||||
@@ -220,7 +220,7 @@ func (db *MockDataStore) Scrobble(ctx context.Context) model.ScrobbleRepository
|
||||
if db.RealDS != nil {
|
||||
db.MockedScrobble = db.RealDS.Scrobble(ctx)
|
||||
} else {
|
||||
db.MockedScrobble = &MockScrobbleRepo{}
|
||||
db.MockedScrobble = &MockScrobbleRepo{ctx: ctx}
|
||||
}
|
||||
}
|
||||
return db.MockedScrobble
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/request"
|
||||
)
|
||||
|
||||
type MockScrobbleRepo struct {
|
||||
RecordedScrobbles []model.Scrobble
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (m *MockScrobbleRepo) RecordScrobble(fileID, userID string, submissionTime time.Time) error {
|
||||
func (m *MockScrobbleRepo) RecordScrobble(fileID string, submissionTime time.Time) error {
|
||||
user, _ := request.UserFrom(m.ctx)
|
||||
m.RecordedScrobbles = append(m.RecordedScrobbles, model.Scrobble{
|
||||
MediaFileID: fileID,
|
||||
UserID: userID,
|
||||
UserID: user.ID,
|
||||
SubmissionTime: submissionTime,
|
||||
})
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user