Listenbrainz scrobbling (#1424)

* Refactor session_keys to its own package

* Adjust play_tracker

- Don't send external NowPlaying/Scrobble for tracks with unknown artist
- Continue to the next agent on error

* Implement ListenBrainz Agent and Auth Router

* Implement frontend for ListenBrainz linking

* Update listenBrainzRequest

- Don't marshal Player to json
- Rename Track to Title

* Return ErrRetryLater on ListenBrainz server errors

* Add tests for listenBrainzAgent

* Add tests for ListenBrainz Client

* Adjust ListenBrainzTokenDialog to handle errors better

* Refactor listenbrainz.formatListen and listenBrainzRequest structs

* Refactor agent auth_routers

* Refactor session_keys to agents package

* Add test for listenBrainzResponse

* Add tests for ListenBrainz auth_router

* Update ListenBrainzTokenDialog and auth_router

* Adjust player scrobble toggle
This commit is contained in:
Steve Richter
2021-10-30 12:17:42 -04:00
committed by GitHub
parent ccc871d1f7
commit a56d5bc850
33 changed files with 1214 additions and 54 deletions
+7 -6
View File
@@ -12,6 +12,7 @@ import (
"github.com/go-chi/chi/v5/middleware"
"github.com/navidrome/navidrome/conf"
"github.com/navidrome/navidrome/consts"
"github.com/navidrome/navidrome/core/agents"
"github.com/navidrome/navidrome/log"
"github.com/navidrome/navidrome/model"
"github.com/navidrome/navidrome/model/request"
@@ -25,7 +26,7 @@ var tokenReceivedPage []byte
type Router struct {
http.Handler
ds model.DataStore
sessionKeys *sessionKeys
sessionKeys *agents.SessionKeys
client *Client
apiKey string
secret string
@@ -36,7 +37,7 @@ func NewRouter(ds model.DataStore) *Router {
ds: ds,
apiKey: conf.Server.LastFM.ApiKey,
secret: conf.Server.LastFM.Secret,
sessionKeys: &sessionKeys{ds: ds},
sessionKeys: &agents.SessionKeys{DataStore: ds, KeyName: sessionKeyProperty},
}
r.Handler = r.routes()
hc := &http.Client{
@@ -63,9 +64,9 @@ func (s *Router) routes() http.Handler {
}
func (s *Router) getLinkStatus(w http.ResponseWriter, r *http.Request) {
resp := map[string]interface{}{"status": true}
resp := map[string]interface{}{}
u, _ := request.UserFrom(r.Context())
key, err := s.sessionKeys.get(r.Context(), u.ID)
key, err := s.sessionKeys.Get(r.Context(), u.ID)
if err != nil && err != model.ErrNotFound {
resp["error"] = err
resp["status"] = false
@@ -78,7 +79,7 @@ func (s *Router) getLinkStatus(w http.ResponseWriter, r *http.Request) {
func (s *Router) unlink(w http.ResponseWriter, r *http.Request) {
u, _ := request.UserFrom(r.Context())
err := s.sessionKeys.delete(r.Context(), u.ID)
err := s.sessionKeys.Delete(r.Context(), u.ID)
if err != nil {
_ = rest.RespondWithError(w, http.StatusInternalServerError, err.Error())
} else {
@@ -119,7 +120,7 @@ func (s *Router) fetchSessionKey(ctx context.Context, uid, token string) error {
"requestId", middleware.GetReqID(ctx), err)
return err
}
err = s.sessionKeys.put(ctx, uid, sessionKey)
err = s.sessionKeys.Put(ctx, uid, sessionKey)
if err != nil {
log.Error("Could not save LastFM session key", "userId", uid, "requestId", middleware.GetReqID(ctx), err)
}