update golangci lint linter list
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
|
// Package ctrladmin provides HTTP handlers for admin UI
|
||||||
package ctrladmin
|
package ctrladmin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
@@ -150,7 +152,6 @@ type (
|
|||||||
handlerAdminRaw func(w http.ResponseWriter, r *http.Request)
|
handlerAdminRaw func(w http.ResponseWriter, r *http.Request)
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gocognit
|
|
||||||
func (c *Controller) H(h handlerAdmin) http.Handler {
|
func (c *Controller) H(h handlerAdmin) http.Handler {
|
||||||
// TODO: break this up a bit
|
// TODO: break this up a bit
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -272,26 +273,33 @@ func sessLogSave(s *sessions.Session, w http.ResponseWriter, r *http.Request) {
|
|||||||
// ## begin validation
|
// ## begin validation
|
||||||
// ## begin validation
|
// ## begin validation
|
||||||
|
|
||||||
|
var (
|
||||||
|
errValiNoUsername = errors.New("please enter the password twice")
|
||||||
|
errValiPasswordAllFields = errors.New("please enter the password twice")
|
||||||
|
errValiPasswordsNotSame = errors.New("passwords entered were not the same")
|
||||||
|
errValiKeysAllFields = errors.New("please enter the api key and secret")
|
||||||
|
)
|
||||||
|
|
||||||
func validateUsername(username string) error {
|
func validateUsername(username string) error {
|
||||||
if username == "" {
|
if username == "" {
|
||||||
return fmt.Errorf("please enter the username")
|
return errValiNoUsername
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validatePasswords(pOne, pTwo string) error {
|
func validatePasswords(pOne, pTwo string) error {
|
||||||
if pOne == "" || pTwo == "" {
|
if pOne == "" || pTwo == "" {
|
||||||
return fmt.Errorf("please enter the password twice")
|
return errValiPasswordAllFields
|
||||||
}
|
}
|
||||||
if !(pOne == pTwo) {
|
if !(pOne == pTwo) {
|
||||||
return fmt.Errorf("the two passwords entered were not the same")
|
return errValiPasswordsNotSame
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateAPIKey(apiKey, secret string) error {
|
func validateAPIKey(apiKey, secret string) error {
|
||||||
if apiKey == "" || secret == "" {
|
if apiKey == "" || secret == "" {
|
||||||
return fmt.Errorf("please enter both the api key and secret")
|
return errValiKeysAllFields
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package ctrladmin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -12,6 +13,10 @@ import (
|
|||||||
"go.senan.xyz/gonic/server/db"
|
"go.senan.xyz/gonic/server/db"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errPlaylistNoMatch = errors.New("couldn't match track")
|
||||||
|
)
|
||||||
|
|
||||||
func playlistParseLine(c *Controller, path string) (int, error) {
|
func playlistParseLine(c *Controller, path string) (int, error) {
|
||||||
if strings.HasPrefix(path, "#") || strings.TrimSpace(path) == "" {
|
if strings.HasPrefix(path, "#") || strings.TrimSpace(path) == "" {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
@@ -25,7 +30,7 @@ func playlistParseLine(c *Controller, path string) (int, error) {
|
|||||||
err := query.First(&track).Error
|
err := query.First(&track).Error
|
||||||
switch {
|
switch {
|
||||||
case gorm.IsRecordNotFoundError(err):
|
case gorm.IsRecordNotFoundError(err):
|
||||||
return 0, fmt.Errorf("couldn't match track %q", path)
|
return 0, fmt.Errorf("%v: %w", err, errPlaylistNoMatch)
|
||||||
case err != nil:
|
case err != nil:
|
||||||
return 0, fmt.Errorf("while matching: %w", err)
|
return 0, fmt.Errorf("while matching: %w", err)
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Package ctrlsubsonic provides HTTP handlers for subsonic api
|
||||||
package ctrlsubsonic
|
package ctrlsubsonic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ func (c *Controller) ServeGetMusicDirectory(r *http.Request) *spec.Response {
|
|||||||
return sub
|
return sub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServeGetAlbumList handles the getAlbumList view.
|
||||||
// changes to this function should be reflected in in _by_tags.go's
|
// changes to this function should be reflected in in _by_tags.go's
|
||||||
// getAlbumListTwo() function
|
// getAlbumListTwo() function
|
||||||
func (c *Controller) ServeGetAlbumList(r *http.Request) *spec.Response {
|
func (c *Controller) ServeGetAlbumList(r *http.Request) *spec.Response {
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ func (c *Controller) ServeGetAlbum(r *http.Request) *spec.Response {
|
|||||||
return sub
|
return sub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServeGetAlbumListTwo handles the getAlbumList2 view.
|
||||||
// changes to this function should be reflected in in _by_folder.go's
|
// changes to this function should be reflected in in _by_folder.go's
|
||||||
// getAlbumList() function
|
// getAlbumList() function
|
||||||
func (c *Controller) ServeGetAlbumListTwo(r *http.Request) *spec.Response {
|
func (c *Controller) ServeGetAlbumListTwo(r *http.Request) *spec.Response {
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ func NewResponse() *Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// spec errors:
|
// Error represents a typed error
|
||||||
// 0 a generic error
|
// 0 a generic error
|
||||||
// 10 required parameter is missing
|
// 10 required parameter is missing
|
||||||
// 20 incompatible subsonic rest protocol version. client must upgrade
|
// 20 incompatible subsonic rest protocol version. client must upgrade
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
//nolint:deadcode,varcheck
|
|
||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Package db provides database helpers and models
|
||||||
//nolint:lll
|
//nolint:lll
|
||||||
package db
|
package db
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ func writeCmdOutput(out, cache io.Writer, pipeReader io.ReadCloser) {
|
|||||||
for {
|
for {
|
||||||
n, err := pipeReader.Read(buffer)
|
n, err := pipeReader.Read(buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pipeReader.Close()
|
_ = pipeReader.Close()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
data := buffer[0:n]
|
data := buffer[0:n]
|
||||||
@@ -91,7 +91,7 @@ func ffmpegCommand(filePath string, profile *Profile, bitrate string) *exec.Cmd
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
args = append(args, "-f", profile.Format, "-")
|
args = append(args, "-f", profile.Format, "-")
|
||||||
return exec.Command("/usr/bin/ffmpeg", args...)
|
return exec.Command("/usr/bin/ffmpeg", args...) //nolint:gosec
|
||||||
}
|
}
|
||||||
|
|
||||||
func Encode(out io.Writer, trackPath, cachePath string, profile *Profile, bitrate string) error {
|
func Encode(out io.Writer, trackPath, cachePath string, profile *Profile, bitrate string) error {
|
||||||
@@ -116,22 +116,22 @@ func Encode(out io.Writer, trackPath, cachePath string, profile *Profile, bitrat
|
|||||||
return fmt.Errorf("running ffmpeg: %w", err)
|
return fmt.Errorf("running ffmpeg: %w", err)
|
||||||
}
|
}
|
||||||
// close all pipes and flush cache file
|
// close all pipes and flush cache file
|
||||||
pipeWriter.Close()
|
_ = pipeWriter.Close()
|
||||||
if err := cacheFile.Sync(); err != nil {
|
if err := cacheFile.Sync(); err != nil {
|
||||||
return fmt.Errorf("flushing %q: %w", cachePath, err)
|
return fmt.Errorf("flushing %q: %w", cachePath, err)
|
||||||
}
|
}
|
||||||
cacheFile.Close()
|
_ = cacheFile.Close()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate cache key (file name). for, you know, encoded tracks cache
|
// CacheKey generates the filename for the new transcode save
|
||||||
func CacheKey(sourcePath string, profile, bitrate string) string {
|
func CacheKey(sourcePath string, profile, bitrate string) string {
|
||||||
format := Profiles[profile].Format
|
format := Profiles[profile].Format
|
||||||
hash := xxhash.Sum64String(sourcePath)
|
hash := xxhash.Sum64String(sourcePath)
|
||||||
return fmt.Sprintf("%x-%s-%s.%s", hash, profile, bitrate, format)
|
return fmt.Sprintf("%x-%s-%s.%s", hash, profile, bitrate, format)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if client forces bitrate lower than set in profile
|
// GetBitrate checks if the client forces bitrate lower than set in profile
|
||||||
func GetBitrate(clientBitrate int, profile *Profile) string {
|
func GetBitrate(clientBitrate int, profile *Profile) string {
|
||||||
bitrate := profile.Bitrate
|
bitrate := profile.Bitrate
|
||||||
if clientBitrate != 0 && clientBitrate < bitrate {
|
if clientBitrate != 0 && clientBitrate < bitrate {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package jukebox
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -89,7 +90,9 @@ func (j *Jukebox) Listen() error {
|
|||||||
case update := <-j.updates:
|
case update := <-j.updates:
|
||||||
j.doUpdate(update)
|
j.doUpdate(update)
|
||||||
case speaker := <-j.speaker:
|
case speaker := <-j.speaker:
|
||||||
j.doUpdateSpeaker(speaker)
|
if err := j.doUpdateSpeaker(speaker); err != nil {
|
||||||
|
log.Printf("error in jukebox: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -19,6 +20,7 @@ var (
|
|||||||
client = &http.Client{
|
client = &http.Client{
|
||||||
Timeout: 10 * time.Second,
|
Timeout: 10 * time.Second,
|
||||||
}
|
}
|
||||||
|
ErrLastFM = errors.New("last.fm error")
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: remove this package's dependency on models/db
|
// TODO: remove this package's dependency on models/db
|
||||||
@@ -54,7 +56,7 @@ func makeRequest(method string, params url.Values) (LastFM, error) {
|
|||||||
return LastFM{}, fmt.Errorf("decoding: %w", err)
|
return LastFM{}, fmt.Errorf("decoding: %w", err)
|
||||||
}
|
}
|
||||||
if lastfm.Error.Code != 0 {
|
if lastfm.Error.Code != 0 {
|
||||||
return LastFM{}, fmt.Errorf("parsing: %v", lastfm.Error.Value)
|
return LastFM{}, fmt.Errorf("%v: %w", lastfm.Error.Value, ErrLastFM)
|
||||||
}
|
}
|
||||||
return lastfm, nil
|
return lastfm, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,17 +23,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrStatingItem = errors.New("stating item")
|
ErrAlreadyScanning = errors.New("already scanning")
|
||||||
ErrReadingTags = errors.New("reading tags")
|
ErrStatingItem = errors.New("could not stat item")
|
||||||
|
ErrReadingTags = errors.New("could not read tags")
|
||||||
)
|
)
|
||||||
|
|
||||||
func durSince(t time.Time) time.Duration {
|
func durSince(t time.Time) time.Duration {
|
||||||
return time.Since(t).Truncate(10 * time.Microsecond)
|
return time.Since(t).Truncate(10 * time.Microsecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
// decoded converts a string to it's latin equivalent. it will
|
// decoded converts a string to it's latin equivalent.
|
||||||
// be used by the model's *UDec fields, and is only set if it
|
// it will be used by the model's *UDec fields, and is only set if it
|
||||||
// differs from the original. the fields are used for searching
|
// differs from the original. the fields are used for searching.
|
||||||
func decoded(in string) string {
|
func decoded(in string) string {
|
||||||
if u := unidecode.Unidecode(in); u != in {
|
if u := unidecode.Unidecode(in); u != in {
|
||||||
return u
|
return u
|
||||||
@@ -236,7 +237,7 @@ var coverFilenames = map[string]struct{}{
|
|||||||
func (s *Scanner) callbackItem(fullPath string, info *godirwalk.Dirent) error {
|
func (s *Scanner) callbackItem(fullPath string, info *godirwalk.Dirent) error {
|
||||||
stat, err := os.Stat(fullPath)
|
stat, err := os.Stat(fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("stating: %w", err)
|
return fmt.Errorf("%w: %v", ErrStatingItem, err)
|
||||||
}
|
}
|
||||||
relPath, err := filepath.Rel(s.musicPath, fullPath)
|
relPath, err := filepath.Rel(s.musicPath, fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -40,17 +40,17 @@ func resetTablesPause(db *db.DB, b *testing.B) {
|
|||||||
func BenchmarkScanFresh(b *testing.B) {
|
func BenchmarkScanFresh(b *testing.B) {
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
resetTablesPause(testScanner.db, b)
|
resetTablesPause(testScanner.db, b)
|
||||||
testScanner.Start(ScanOptions{})
|
_ = testScanner.Start(ScanOptions{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkScanIncremental(b *testing.B) {
|
func BenchmarkScanIncremental(b *testing.B) {
|
||||||
// do a full scan and reset
|
// do a full scan and reset
|
||||||
testScanner.Start(ScanOptions{})
|
_ = testScanner.Start(ScanOptions{})
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
// do the inc scans
|
// do the inc scans
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
testScanner.Start(ScanOptions{})
|
_ = testScanner.Start(ScanOptions{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -179,11 +179,11 @@ func setupSubsonic(r *mux.Router, ctrl *ctrlsubsonic.Controller) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
funcExecute func() error
|
FuncExecute func() error
|
||||||
funcInterrupt func(error)
|
FuncInterrupt func(error)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) StartHTTP(listenAddr string) (funcExecute, funcInterrupt) {
|
func (s *Server) StartHTTP(listenAddr string) (FuncExecute, FuncInterrupt) {
|
||||||
list := &http.Server{
|
list := &http.Server{
|
||||||
Addr: listenAddr,
|
Addr: listenAddr,
|
||||||
Handler: s.router,
|
Handler: s.router,
|
||||||
@@ -196,11 +196,11 @@ func (s *Server) StartHTTP(listenAddr string) (funcExecute, funcInterrupt) {
|
|||||||
return list.ListenAndServe()
|
return list.ListenAndServe()
|
||||||
}, func(_ error) {
|
}, func(_ error) {
|
||||||
// stop job
|
// stop job
|
||||||
list.Close()
|
_ = list.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) StartScanTicker(dur time.Duration) (funcExecute, funcInterrupt) {
|
func (s *Server) StartScanTicker(dur time.Duration) (FuncExecute, FuncInterrupt) {
|
||||||
ticker := time.NewTicker(dur)
|
ticker := time.NewTicker(dur)
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
waitFor := func() error {
|
waitFor := func() error {
|
||||||
@@ -225,7 +225,7 @@ func (s *Server) StartScanTicker(dur time.Duration) (funcExecute, funcInterrupt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) StartJukebox() (funcExecute, funcInterrupt) {
|
func (s *Server) StartJukebox() (FuncExecute, FuncInterrupt) {
|
||||||
return func() error {
|
return func() error {
|
||||||
log.Printf("starting job 'jukebox'\n")
|
log.Printf("starting job 'jukebox'\n")
|
||||||
return s.jukebox.Listen()
|
return s.jukebox.Listen()
|
||||||
|
|||||||
Reference in New Issue
Block a user