diff --git a/engine/cover.go b/engine/cover.go index 9aa6c45b..312f291e 100644 --- a/engine/cover.go +++ b/engine/cover.go @@ -74,7 +74,9 @@ func (c *cover) Get(ctx context.Context, id string, size int, out io.Writer) err log.Error(ctx, "Error loading cover art", "path", path, "size", size, err) return } - io.Copy(w, reader) + if _, err := io.Copy(w, reader); err != nil { + log.Error(ctx, "Error saving covert art to cache", "path", path, "size", size, err) + } }() } else { log.Trace(ctx, "Loading image from cache", "path", path, "size", size, "lastUpdate", lastUpdate) diff --git a/engine/nowplaying.go b/engine/nowplaying.go index 39a9da34..643ad029 100644 --- a/engine/nowplaying.go +++ b/engine/nowplaying.go @@ -110,7 +110,7 @@ func checkExpired(l *list.List, f func() *list.Element) *list.Element { return nil } start := e.Value.(*NowPlayingInfo).Start - if time.Now().Sub(start) < NowPlayingExpire { + if time.Since(start) < NowPlayingExpire { return e } l.Remove(e) diff --git a/engine/scrobbler.go b/engine/scrobbler.go index a55a2b97..01253c4e 100644 --- a/engine/scrobbler.go +++ b/engine/scrobbler.go @@ -2,7 +2,6 @@ package engine import ( "context" - "errors" "fmt" "time" @@ -57,7 +56,7 @@ func (s *scrobbler) NowPlaying(ctx context.Context, playerId int, playerName, tr } if mf == nil { - return nil, errors.New(fmt.Sprintf(`ID "%s" not found`, trackId)) + return nil, fmt.Errorf(`ID "%s" not found`, trackId) } log.Info("Now Playing", "title", mf.Title, "artist", mf.Artist, "user", userName(ctx)) diff --git a/engine/transcoder/ffmpeg.go b/engine/transcoder/ffmpeg.go index f3cbead5..a2630572 100644 --- a/engine/transcoder/ffmpeg.go +++ b/engine/transcoder/ffmpeg.go @@ -38,7 +38,9 @@ func (ff *ffmpeg) Start(ctx context.Context, command, path string, maxBitRate in if err = cmd.Start(); err != nil { return } - go cmd.Wait() // prevent zombies + + go func() { _ = cmd.Wait() }() // prevent zombies + return } diff --git a/persistence/persistence_suite_test.go b/persistence/persistence_suite_test.go index a05c9783..920a2651 100644 --- a/persistence/persistence_suite_test.go +++ b/persistence/persistence_suite_test.go @@ -22,7 +22,7 @@ func TestPersistence(t *testing.T) { //os.Remove("./test-123.db") //conf.Server.Path = "./test-123.db" conf.Server.DbPath = "file::memory:?cache=shared" - orm.RegisterDataBase("default", db.Driver, conf.Server.DbPath) + _ = orm.RegisterDataBase("default", db.Driver, conf.Server.DbPath) db.EnsureLatestVersion() log.SetLevel(log.LevelCritical) RegisterFailHandler(Fail) diff --git a/scanner/change_detector_test.go b/scanner/change_detector_test.go index a3f3d9b2..d68afb61 100644 --- a/scanner/change_detector_test.go +++ b/scanner/change_detector_test.go @@ -103,8 +103,8 @@ var _ = Describe("ChangeDetector", func() { Expect(changed).To(BeEmpty()) Expect(changed).To(BeEmpty()) - f, err := os.Create(filepath.Join(testFolder, "a", "b", "new.txt")) - f.Close() + f, _ := os.Create(filepath.Join(testFolder, "a", "b", "new.txt")) + _ = f.Close() changed, deleted, err = newScanner.Scan(lastModifiedSince) Expect(err).To(BeNil()) Expect(deleted).To(BeEmpty()) diff --git a/scanner/scanner.go b/scanner/scanner.go index 1f032f3f..1ebade79 100644 --- a/scanner/scanner.go +++ b/scanner/scanner.go @@ -72,7 +72,9 @@ func (s *Scanner) getLastModifiedSince(folder string) time.Time { func (s *Scanner) updateLastModifiedSince(folder string, t time.Time) { millis := t.UnixNano() / int64(time.Millisecond) - s.ds.Property(nil).Put(model.PropLastScan+"-"+folder, fmt.Sprint(millis)) + if err := s.ds.Property(context.TODO()).Put(model.PropLastScan+"-"+folder, fmt.Sprint(millis)); err != nil { + log.Error("Error updating DB after scan", err) + } } func (s *Scanner) loadFolders() { @@ -85,12 +87,6 @@ func (s *Scanner) loadFolders() { type Status int -const ( - StatusComplete Status = iota - StatusInProgress - StatusError -) - type StatusInfo struct { MediaFolder string Status Status diff --git a/server/app/app.go b/server/app/app.go index 13f27c61..52f7f8fc 100644 --- a/server/app/app.go +++ b/server/app/app.go @@ -49,7 +49,7 @@ func (app *Router) routes(path string) http.Handler { app.R(r, "/player", model.Player{}) // Keepalive endpoint to be used to keep the session valid (ex: while playing songs) - r.Get("/keepalive/*", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`{"response":"ok"}`)) }) + r.Get("/keepalive/*", func(w http.ResponseWriter, r *http.Request) { _, _ = w.Write([]byte(`{"response":"ok"}`)) }) }) // Serve UI app assets diff --git a/server/app/auth.go b/server/app/auth.go index 534f4491..e800ad58 100644 --- a/server/app/auth.go +++ b/server/app/auth.go @@ -6,7 +6,6 @@ import ( "errors" "net/http" "strings" - "sync" "time" "github.com/deluan/navidrome/consts" @@ -20,7 +19,6 @@ import ( ) var ( - once sync.Once ErrFirstTime = errors.New("no users created") ) @@ -31,7 +29,7 @@ func Login(ds model.DataStore) func(w http.ResponseWriter, r *http.Request) { username, password, err := getCredentialsFromBody(r) if err != nil { log.Error(r, "Parsing request body", err) - rest.RespondWithError(w, http.StatusUnprocessableEntity, err.Error()) + _ = rest.RespondWithError(w, http.StatusUnprocessableEntity, err.Error()) return } @@ -42,21 +40,21 @@ func Login(ds model.DataStore) func(w http.ResponseWriter, r *http.Request) { func handleLogin(ds model.DataStore, username string, password string, w http.ResponseWriter, r *http.Request) { user, err := validateLogin(ds.User(r.Context()), username, password) if err != nil { - rest.RespondWithError(w, http.StatusInternalServerError, "Unknown error authentication user. Please try again") + _ = rest.RespondWithError(w, http.StatusInternalServerError, "Unknown error authentication user. Please try again") return } if user == nil { log.Warn(r, "Unsuccessful login", "username", username, "request", r.Header) - rest.RespondWithError(w, http.StatusUnauthorized, "Invalid username or password") + _ = rest.RespondWithError(w, http.StatusUnauthorized, "Invalid username or password") return } tokenString, err := auth.CreateToken(user) if err != nil { - rest.RespondWithError(w, http.StatusInternalServerError, "Unknown error authenticating user. Please try again") + _ = rest.RespondWithError(w, http.StatusInternalServerError, "Unknown error authenticating user. Please try again") return } - rest.RespondWithJSON(w, http.StatusOK, + _ = rest.RespondWithJSON(w, http.StatusOK, map[string]interface{}{ "message": "User '" + username + "' authenticated successfully", "token": tokenString, @@ -71,7 +69,7 @@ func getCredentialsFromBody(r *http.Request) (username string, password string, decoder := json.NewDecoder(r.Body) if err = decoder.Decode(&data); err != nil { log.Error(r, "parsing request body", err) - err = errors.New("Invalid request payload") + err = errors.New("invalid request payload") return } username = data["username"] @@ -86,21 +84,21 @@ func CreateAdmin(ds model.DataStore) func(w http.ResponseWriter, r *http.Request username, password, err := getCredentialsFromBody(r) if err != nil { log.Error(r, "parsing request body", err) - rest.RespondWithError(w, http.StatusUnprocessableEntity, err.Error()) + _ = rest.RespondWithError(w, http.StatusUnprocessableEntity, err.Error()) return } c, err := ds.User(r.Context()).CountAll() if err != nil { - rest.RespondWithError(w, http.StatusInternalServerError, err.Error()) + _ = rest.RespondWithError(w, http.StatusInternalServerError, err.Error()) return } if c > 0 { - rest.RespondWithError(w, http.StatusForbidden, "Cannot create another first admin") + _ = rest.RespondWithError(w, http.StatusForbidden, "Cannot create another first admin") return } err = createDefaultUser(r.Context(), ds, username, password) if err != nil { - rest.RespondWithError(w, http.StatusInternalServerError, err.Error()) + _ = rest.RespondWithError(w, http.StatusInternalServerError, err.Error()) return } handleLogin(ds, username, password, w, r) @@ -186,11 +184,11 @@ func authenticator(ds model.DataStore) func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { token, err := getToken(ds, r.Context()) if err == ErrFirstTime { - rest.RespondWithJSON(w, http.StatusUnauthorized, map[string]string{"message": ErrFirstTime.Error()}) + _ = rest.RespondWithJSON(w, http.StatusUnauthorized, map[string]string{"message": ErrFirstTime.Error()}) return } if err != nil { - rest.RespondWithError(w, http.StatusUnauthorized, "Not authenticated") + _ = rest.RespondWithError(w, http.StatusUnauthorized, "Not authenticated") return } @@ -200,7 +198,7 @@ func authenticator(ds model.DataStore) func(next http.Handler) http.Handler { newTokenString, err := auth.TouchToken(token) if err != nil { log.Error(r, "signing new token", err) - rest.RespondWithError(w, http.StatusUnauthorized, "Not authenticated") + _ = rest.RespondWithError(w, http.StatusUnauthorized, "Not authenticated") return } diff --git a/server/subsonic/api.go b/server/subsonic/api.go index ae9c2c8e..7b36622a 100644 --- a/server/subsonic/api.go +++ b/server/subsonic/api.go @@ -162,7 +162,7 @@ func H(r chi.Router, path string, f Handler) { func HGone(r chi.Router, path string) { handle := func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(410) - w.Write([]byte("This endpoint will not be implemented")) + _, _ = w.Write([]byte("This endpoint will not be implemented")) } r.HandleFunc("/"+path, handle) r.HandleFunc("/"+path+".view", handle) @@ -207,5 +207,7 @@ func SendResponse(w http.ResponseWriter, r *http.Request, payload *responses.Sub } else { log.Warn(r.Context(), "API: Failed response", "error", payload.Error.Code, "message", payload.Error.Message) } - w.Write(response) + if _, err := w.Write(response); err != nil { + log.Error(r, "Error sending response to client", "payload", string(response), err) + } } diff --git a/server/subsonic/media_retrieval.go b/server/subsonic/media_retrieval.go index 697a684a..abeea1c7 100644 --- a/server/subsonic/media_retrieval.go +++ b/server/subsonic/media_retrieval.go @@ -27,7 +27,7 @@ func (c *MediaRetrievalController) GetAvatar(w http.ResponseWriter, r *http.Requ return nil, NewError(responses.ErrorDataNotFound, "Avatar image not found") } defer f.Close() - io.Copy(w, f) + _, _ = io.Copy(w, f) return nil, nil } diff --git a/server/subsonic/media_retrieval_test.go b/server/subsonic/media_retrieval_test.go index 9f5d969a..bd6b4ca8 100644 --- a/server/subsonic/media_retrieval_test.go +++ b/server/subsonic/media_retrieval_test.go @@ -24,8 +24,8 @@ func (c *fakeCover) Get(ctx context.Context, id string, size int, out io.Writer) } c.recvId = id c.recvSize = size - out.Write([]byte(c.data)) - return nil + _, err := out.Write([]byte(c.data)) + return err } var _ = Describe("MediaRetrievalController", func() { diff --git a/tests/init_tests.go b/tests/init_tests.go index 3ab445f6..bb43c166 100644 --- a/tests/init_tests.go +++ b/tests/init_tests.go @@ -22,7 +22,7 @@ func Init(t *testing.T, skipOnShort bool) { appPath, _ := filepath.Abs(filepath.Join(filepath.Dir(file), "..")) confPath, _ := filepath.Abs(filepath.Join(appPath, "tests", "navidrome-test.toml")) println("Loading test configuration file from " + confPath) - os.Chdir(appPath) + _ = os.Chdir(appPath) conf.LoadFromFile("tests/navidrome-test.toml", true) noLog := os.Getenv("NOLOG") diff --git a/utils/request_helpers.go b/utils/request_helpers.go index 156e534a..4ec7292e 100644 --- a/utils/request_helpers.go +++ b/utils/request_helpers.go @@ -68,5 +68,5 @@ func ParamBool(r *http.Request, param string, def bool) bool { if p == "" { return def } - return strings.Index("/true/on/1/", "/"+p+"/") != -1 + return strings.Contains("/true/on/1/", "/"+p+"/") }