diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index f3c99d890..fe0344e25 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -46,13 +46,12 @@ func CreateSubsonicAPIRouter() (*subsonic.Router, error) { listGenerator := engine.NewListGenerator(dataStore, nowPlayingRepository) users := engine.NewUsers(dataStore) playlists := engine.NewPlaylists(dataStore) - scrobbler := engine.NewScrobbler(dataStore, nowPlayingRepository) transcoderTranscoder := transcoder.New() transcodingCache := core.NewTranscodingCache() mediaStreamer := core.NewMediaStreamer(dataStore, transcoderTranscoder, transcodingCache) archiver := core.NewArchiver(dataStore) players := engine.NewPlayers(dataStore) - router := subsonic.New(artwork, listGenerator, users, playlists, scrobbler, mediaStreamer, archiver, players, dataStore) + router := subsonic.New(artwork, listGenerator, users, playlists, mediaStreamer, archiver, players, dataStore) return router, nil } diff --git a/server/subsonic/api.go b/server/subsonic/api.go index e463aca4a..412f450ad 100644 --- a/server/subsonic/api.go +++ b/server/subsonic/api.go @@ -26,7 +26,6 @@ type Router struct { Artwork core.Artwork ListGenerator engine.ListGenerator Playlists engine.Playlists - Scrobbler engine.Scrobbler Users engine.Users Streamer core.MediaStreamer Archiver core.Archiver @@ -37,11 +36,10 @@ type Router struct { } func New(artwork core.Artwork, listGenerator engine.ListGenerator, users engine.Users, - playlists engine.Playlists, scrobbler engine.Scrobbler, streamer core.MediaStreamer, + playlists engine.Playlists, streamer core.MediaStreamer, archiver core.Archiver, players engine.Players, ds model.DataStore) *Router { r := &Router{Artwork: artwork, ListGenerator: listGenerator, Playlists: playlists, - Scrobbler: scrobbler, Users: users, Streamer: streamer, Archiver: archiver, - Players: players, DataStore: ds} + Users: users, Streamer: streamer, Archiver: archiver, Players: players, DataStore: ds} r.mux = r.routes() return r } diff --git a/server/subsonic/engine/scrobbler.go b/server/subsonic/engine/scrobbler.go deleted file mode 100644 index f4b697798..000000000 --- a/server/subsonic/engine/scrobbler.go +++ /dev/null @@ -1,70 +0,0 @@ -package engine - -import ( - "context" - "fmt" - "time" - - "github.com/deluan/navidrome/log" - "github.com/deluan/navidrome/model" -) - -type Scrobbler interface { - Register(ctx context.Context, playerId int, trackId string, playDate time.Time) (*model.MediaFile, error) - NowPlaying(ctx context.Context, playerId int, playerName, trackId, username string) (*model.MediaFile, error) -} - -func NewScrobbler(ds model.DataStore, npr NowPlayingRepository) Scrobbler { - return &scrobbler{ds: ds, npRepo: npr} -} - -type scrobbler struct { - ds model.DataStore - npRepo NowPlayingRepository -} - -func (s *scrobbler) Register(ctx context.Context, playerId int, trackId string, playTime time.Time) (*model.MediaFile, error) { - var mf *model.MediaFile - var err error - err = s.ds.WithTx(func(tx model.DataStore) error { - mf, err = s.ds.MediaFile(ctx).Get(trackId) - if err != nil { - return err - } - err = s.ds.MediaFile(ctx).IncPlayCount(trackId, playTime) - if err != nil { - return err - } - err = s.ds.Album(ctx).IncPlayCount(mf.AlbumID, playTime) - if err != nil { - return err - } - err = s.ds.Artist(ctx).IncPlayCount(mf.ArtistID, playTime) - return err - }) - - if err != nil { - log.Error("Error while scrobbling", "trackId", trackId, err) - } else { - log.Info("Scrobbled", "title", mf.Title, "artist", mf.Artist, "user", userName(ctx)) - } - - return mf, err -} - -// TODO Validate if NowPlaying still works after all refactorings -func (s *scrobbler) NowPlaying(ctx context.Context, playerId int, playerName, trackId, username string) (*model.MediaFile, error) { - mf, err := s.ds.MediaFile(ctx).Get(trackId) - if err != nil { - return nil, err - } - - if mf == nil { - return nil, fmt.Errorf(`ID "%s" not found`, trackId) - } - - log.Info("Now Playing", "title", mf.Title, "artist", mf.Artist, "user", userName(ctx)) - - info := &NowPlayingInfo{TrackID: trackId, Username: username, Start: time.Now(), PlayerId: playerId, PlayerName: playerName} - return mf, s.npRepo.Enqueue(info) -} diff --git a/server/subsonic/engine/wire_providers.go b/server/subsonic/engine/wire_providers.go index aa1f15c95..daec9ab74 100644 --- a/server/subsonic/engine/wire_providers.go +++ b/server/subsonic/engine/wire_providers.go @@ -7,7 +7,6 @@ import ( var Set = wire.NewSet( NewListGenerator, NewPlaylists, - NewScrobbler, NewNowPlayingRepository, NewUsers, NewPlayers, diff --git a/server/subsonic/media_annotation.go b/server/subsonic/media_annotation.go index f80fef5cd..ead758597 100644 --- a/server/subsonic/media_annotation.go +++ b/server/subsonic/media_annotation.go @@ -2,23 +2,25 @@ package subsonic import ( "context" + "fmt" "net/http" "time" "github.com/deluan/navidrome/log" "github.com/deluan/navidrome/model" + "github.com/deluan/navidrome/model/request" "github.com/deluan/navidrome/server/subsonic/engine" "github.com/deluan/navidrome/server/subsonic/responses" "github.com/deluan/navidrome/utils" ) type MediaAnnotationController struct { - scrobbler engine.Scrobbler - ds model.DataStore + ds model.DataStore + npRepo engine.NowPlayingRepository } -func NewMediaAnnotationController(scrobbler engine.Scrobbler, ds model.DataStore) *MediaAnnotationController { - return &MediaAnnotationController{scrobbler: scrobbler, ds: ds} +func NewMediaAnnotationController(ds model.DataStore, npr engine.NowPlayingRepository) *MediaAnnotationController { + return &MediaAnnotationController{ds: ds, npRepo: npr} } func (c *MediaAnnotationController) SetRating(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) { @@ -116,13 +118,13 @@ func (c *MediaAnnotationController) Scrobble(w http.ResponseWriter, r *http.Requ t = time.Now() } if submission { - _, err := c.scrobbler.Register(r.Context(), playerId, id, t) + _, err := c.scrobblerRegister(r.Context(), playerId, id, t) if err != nil { log.Error(r, "Error scrobbling track", "id", id, err) continue } } else { - _, err := c.scrobbler.NowPlaying(r.Context(), playerId, playerName, id, username) + _, err := c.scrobblerNowPlaying(r.Context(), playerId, playerName, id, username) if err != nil { log.Error(r, "Error setting current song", "id", id, err) continue @@ -132,6 +134,52 @@ func (c *MediaAnnotationController) Scrobble(w http.ResponseWriter, r *http.Requ return newResponse(), nil } +func (c *MediaAnnotationController) scrobblerRegister(ctx context.Context, playerId int, trackId string, playTime time.Time) (*model.MediaFile, error) { + var mf *model.MediaFile + var err error + err = c.ds.WithTx(func(tx model.DataStore) error { + mf, err = c.ds.MediaFile(ctx).Get(trackId) + if err != nil { + return err + } + err = c.ds.MediaFile(ctx).IncPlayCount(trackId, playTime) + if err != nil { + return err + } + err = c.ds.Album(ctx).IncPlayCount(mf.AlbumID, playTime) + if err != nil { + return err + } + err = c.ds.Artist(ctx).IncPlayCount(mf.ArtistID, playTime) + return err + }) + + username, _ := request.UsernameFrom(ctx) + if err != nil { + log.Error("Error while scrobbling", "trackId", trackId, "user", username, err) + } else { + log.Info("Scrobbled", "title", mf.Title, "artist", mf.Artist, "user", username) + } + + return mf, err +} + +func (c *MediaAnnotationController) scrobblerNowPlaying(ctx context.Context, playerId int, playerName, trackId, username string) (*model.MediaFile, error) { + mf, err := c.ds.MediaFile(ctx).Get(trackId) + if err != nil { + return nil, err + } + + if mf == nil { + return nil, fmt.Errorf(`ID "%s" not found`, trackId) + } + + log.Info("Now Playing", "title", mf.Title, "artist", mf.Artist, "user", username) + + info := &engine.NowPlayingInfo{TrackID: trackId, Username: username, Start: time.Now(), PlayerId: playerId, PlayerName: playerName} + return mf, c.npRepo.Enqueue(info) +} + func (c *MediaAnnotationController) setStar(ctx context.Context, star bool, ids ...string) error { if len(ids) == 0 { return nil diff --git a/server/subsonic/wire_gen.go b/server/subsonic/wire_gen.go index c635a85ee..58ccd13d7 100644 --- a/server/subsonic/wire_gen.go +++ b/server/subsonic/wire_gen.go @@ -6,6 +6,7 @@ package subsonic import ( + "github.com/deluan/navidrome/server/subsonic/engine" "github.com/google/wire" ) @@ -29,9 +30,9 @@ func initAlbumListController(router *Router) *AlbumListController { } func initMediaAnnotationController(router *Router) *MediaAnnotationController { - scrobbler := router.Scrobbler dataStore := router.DataStore - mediaAnnotationController := NewMediaAnnotationController(scrobbler, dataStore) + nowPlayingRepository := engine.NewNowPlayingRepository() + mediaAnnotationController := NewMediaAnnotationController(dataStore, nowPlayingRepository) return mediaAnnotationController } @@ -84,5 +85,5 @@ var allProviders = wire.NewSet( NewUsersController, NewMediaRetrievalController, NewStreamController, - NewBookmarksController, wire.FieldsOf(new(*Router), "Artwork", "ListGenerator", "Playlists", "Scrobbler", "Streamer", "Archiver", "DataStore"), + NewBookmarksController, engine.NewNowPlayingRepository, wire.FieldsOf(new(*Router), "Artwork", "ListGenerator", "Playlists", "Streamer", "Archiver", "DataStore"), ) diff --git a/server/subsonic/wire_injectors.go b/server/subsonic/wire_injectors.go index 2a621d978..019220f5f 100644 --- a/server/subsonic/wire_injectors.go +++ b/server/subsonic/wire_injectors.go @@ -3,6 +3,7 @@ package subsonic import ( + "github.com/deluan/navidrome/server/subsonic/engine" "github.com/google/wire" ) @@ -17,7 +18,8 @@ var allProviders = wire.NewSet( NewMediaRetrievalController, NewStreamController, NewBookmarksController, - wire.FieldsOf(new(*Router), "Artwork", "ListGenerator", "Playlists", "Scrobbler", "Streamer", "Archiver", "DataStore"), + engine.NewNowPlayingRepository, + wire.FieldsOf(new(*Router), "Artwork", "ListGenerator", "Playlists", "Streamer", "Archiver", "DataStore"), ) func initSystemController(router *Router) *SystemController {