diff --git a/.github/workflows/nightly-release.yaml b/.github/workflows/nightly-release.yaml index 3395aae..93cc2b9 100644 --- a/.github/workflows/nightly-release.yaml +++ b/.github/workflows/nightly-release.yaml @@ -33,10 +33,9 @@ jobs: sudo apt update -qq sudo apt install -y -qq build-essential git sqlite libtag1-dev ffmpeg mpv zlib1g-dev - name: Lint - uses: golangci/golangci-lint-action@v2 + uses: golangci/golangci-lint-action@v3 with: - version: v1.50.1 - skip-go-installation: true + version: v1.52.2 args: --timeout=5m - name: Test run: go test ./... diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a940dc3..1285f55 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -19,10 +19,9 @@ jobs: sudo apt update -qq sudo apt install -y -qq build-essential git sqlite libtag1-dev ffmpeg mpv zlib1g-dev - name: Lint - uses: golangci/golangci-lint-action@v2 + uses: golangci/golangci-lint-action@v3 with: - version: v1.50.1 - skip-go-installation: true + version: v1.52.2 args: --timeout=5m - name: Test run: go test ./... diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ad94f44..85e69a3 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -20,10 +20,9 @@ jobs: sudo apt update -qq sudo apt install -y -qq build-essential git sqlite libtag1-dev ffmpeg mpv zlib1g-dev - name: Lint - uses: golangci/golangci-lint-action@v2 + uses: golangci/golangci-lint-action@v3 with: - version: v1.50.1 - skip-go-installation: true + version: v1.52.2 args: --timeout=5m - name: Test run: go test ./... diff --git a/db/migrations.go b/db/migrations.go index e14502d..c560c02 100644 --- a/db/migrations.go +++ b/db/migrations.go @@ -314,11 +314,11 @@ func migrateAlbumRootDir(tx *gorm.DB, ctx MigrationContext) error { return nil } -func migrateArtistGuessedFolder(tx *gorm.DB, ctx MigrationContext) error { +func migrateArtistGuessedFolder(tx *gorm.DB, _ MigrationContext) error { return tx.AutoMigrate(Artist{}).Error } -func migrateArtistCover(tx *gorm.DB, ctx MigrationContext) error { +func migrateArtistCover(tx *gorm.DB, _ MigrationContext) error { step := tx.AutoMigrate( Artist{}, ) @@ -344,7 +344,7 @@ func migrateAlbumRootDirAgain(tx *gorm.DB, ctx MigrationContext) error { return migrateAlbumRootDir(tx, ctx) } -func migratePublicPlaylist(tx *gorm.DB, ctx MigrationContext) error { +func migratePublicPlaylist(tx *gorm.DB, _ MigrationContext) error { if !tx.HasTable("playlists") { return nil } diff --git a/mockfs/mockfs.go b/mockfs/mockfs.go index cd16649..06d9136 100644 --- a/mockfs/mockfs.go +++ b/mockfs/mockfs.go @@ -27,13 +27,13 @@ type MockFS struct { db *db.DB } -func New(t testing.TB) *MockFS { return new(t, []string{""}, "") } -func NewWithDirs(t testing.TB, dirs []string) *MockFS { return new(t, dirs, "") } +func New(t testing.TB) *MockFS { return newMockFS(t, []string{""}, "") } +func NewWithDirs(t testing.TB, dirs []string) *MockFS { return newMockFS(t, dirs, "") } func NewWithExcludePattern(t testing.TB, excludePattern string) *MockFS { - return new(t, []string{""}, excludePattern) + return newMockFS(t, []string{""}, excludePattern) } -func new(t testing.TB, dirs []string, excludePattern string) *MockFS { +func newMockFS(t testing.TB, dirs []string, excludePattern string) *MockFS { dbc, err := db.NewMock() if err != nil { t.Fatalf("create db: %v", err) diff --git a/podcasts/podcasts.go b/podcasts/podcasts.go index dcaaa94..3e47b6e 100644 --- a/podcasts/podcasts.go +++ b/podcasts/podcasts.go @@ -235,7 +235,7 @@ func (p *Podcasts) AddEpisode(podcastID int, item *gofeed.Item) (*db.PodcastEpis return nil, ErrNoAudioInFeedItem } -func isAudio(mediaType, rawItemURL string) (bool, error) { +func isAudio(rawItemURL string) (bool, error) { itemURL, err := url.Parse(rawItemURL) if err != nil { return false, err @@ -260,7 +260,7 @@ func itemToEpisode(podcastID, size, duration int, audio string, func (p *Podcasts) findEnclosureAudio(podcastID, duration int, item *gofeed.Item) (*db.PodcastEpisode, bool) { for _, enc := range item.Enclosures { - if t, err := isAudio(enc.Type, enc.URL); !t || err != nil { + if t, err := isAudio(enc.URL); !t || err != nil { continue } size, _ := strconv.Atoi(enc.Length) @@ -275,7 +275,7 @@ func (p *Podcasts) findMediaAudio(podcastID, duration int, item *gofeed.Item) (* return nil, false } for _, ext := range extensions { - if t, err := isAudio(ext.Attrs["type"], ext.Attrs["url"]); !t || err != nil { + if t, err := isAudio(ext.Attrs["url"]); !t || err != nil { continue } return itemToEpisode(podcastID, 0, duration, ext.Attrs["url"], item), true diff --git a/scanner/scanner.go b/scanner/scanner.go index 5eabefa..6e236f7 100644 --- a/scanner/scanner.go +++ b/scanner/scanner.go @@ -354,14 +354,14 @@ func (s *Scanner) populateTrackAndAlbumArtists(tx *db.DB, c *Context, i int, par } genreNames := strings.Split(trags.SomeGenre(), s.genreSplit) - genreIDs, err := populateGenres(tx, &track, genreNames) + genreIDs, err := populateGenres(tx, genreNames) if err != nil { return fmt.Errorf("populate genres: %w", err) } // metadata for the album table comes only from the the first track's tags if i == 0 || album.TagArtist == nil { - albumArtist, err := populateAlbumArtist(tx, album, parent, trags.SomeAlbumArtist()) + albumArtist, err := populateAlbumArtist(tx, parent, trags.SomeAlbumArtist()) if err != nil { return fmt.Errorf("populate album artist: %w", err) } @@ -453,7 +453,7 @@ func populateTrack(tx *db.DB, album *db.Album, track *db.Track, trags tags.Parse return nil } -func populateAlbumArtist(tx *db.DB, album, parent *db.Album, artistName string) (*db.Artist, error) { +func populateAlbumArtist(tx *db.DB, parent *db.Album, artistName string) (*db.Artist, error) { var update db.Artist update.Name = artistName update.NameUDec = decoded(artistName) @@ -467,7 +467,7 @@ func populateAlbumArtist(tx *db.DB, album, parent *db.Album, artistName string) return &artist, nil } -func populateGenres(tx *db.DB, track *db.Track, names []string) ([]int, error) { +func populateGenres(tx *db.DB, names []string) ([]int, error) { var filteredNames []string for _, name := range names { if clean := strings.TrimSpace(name); clean != "" { diff --git a/scrobble/listenbrainz/listenbrainz_test.go b/scrobble/listenbrainz/listenbrainz_test.go index 10eade0..c6e5c46 100644 --- a/scrobble/listenbrainz/listenbrainz_test.go +++ b/scrobble/listenbrainz/listenbrainz_test.go @@ -17,7 +17,7 @@ import ( func httpClientMock(handler http.Handler) (http.Client, func()) { server := httptest.NewTLSServer(handler) - client := http.Client{ + shutdown := http.Client{ Transport: &http.Transport{ DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { return net.Dial(network, server.Listener.Addr().String()) @@ -28,7 +28,7 @@ func httpClientMock(handler http.Handler) (http.Client, func()) { }, } - return client, server.Close + return shutdown, server.Close } //go:embed testdata/submit_listens_request.json @@ -39,7 +39,7 @@ func TestScrobble(t *testing.T) { require := require.New(t) // arrange - client, close := httpClientMock(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + client, shutdown := httpClientMock(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { require.Equal(http.MethodPost, r.Method) require.Equal("/1/submit-listens", r.URL.Path) require.Equal("application/json", r.Header.Get("Content-Type")) @@ -51,7 +51,7 @@ func TestScrobble(t *testing.T) { w.WriteHeader(http.StatusOK) w.Write([]byte(`{"accepted": 1}`)) })) - defer close() + defer shutdown() scrobbler := Scrobbler{ httpClient: &client, @@ -79,7 +79,7 @@ func TestScrobbleUnauthorized(t *testing.T) { require := require.New(t) // arrange - client, close := httpClientMock(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + client, shutdown := httpClientMock(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { require.Equal(http.MethodPost, r.Method) require.Equal("/1/submit-listens", r.URL.Path) require.Equal("application/json", r.Header.Get("Content-Type")) @@ -88,7 +88,7 @@ func TestScrobbleUnauthorized(t *testing.T) { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte(`{"code": 401, "error": "Invalid authorization token."}`)) })) - defer close() + defer shutdown() scrobbler := Scrobbler{ httpClient: &client, @@ -116,7 +116,7 @@ func TestScrobbleServerError(t *testing.T) { require := require.New(t) // arrange - client, close := httpClientMock(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + client, shutdown := httpClientMock(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { require.Equal(http.MethodPost, r.Method) require.Equal("/1/submit-listens", r.URL.Path) require.Equal("application/json", r.Header.Get("Content-Type")) @@ -124,7 +124,7 @@ func TestScrobbleServerError(t *testing.T) { w.WriteHeader(http.StatusInternalServerError) })) - defer close() + defer shutdown() scrobbler := Scrobbler{ httpClient: &client, diff --git a/server/ctrladmin/handlers.go b/server/ctrladmin/handlers.go index e046cf1..2f4a202 100644 --- a/server/ctrladmin/handlers.go +++ b/server/ctrladmin/handlers.go @@ -33,11 +33,11 @@ func doScan(scanner *scanner.Scanner, opts scanner.ScanOptions) { }() } -func (c *Controller) ServeNotFound(r *http.Request) *Response { +func (c *Controller) ServeNotFound(_ *http.Request) *Response { return &Response{template: "not_found.tmpl", code: 404} } -func (c *Controller) ServeLogin(r *http.Request) *Response { +func (c *Controller) ServeLogin(_ *http.Request) *Response { return &Response{template: "login.tmpl"} } @@ -303,7 +303,7 @@ func (c *Controller) ServeDeleteUserDo(r *http.Request) *Response { return &Response{redirect: "/admin/home"} } -func (c *Controller) ServeCreateUser(r *http.Request) *Response { +func (c *Controller) ServeCreateUser(_ *http.Request) *Response { return &Response{template: "create_user.tmpl"} } @@ -369,7 +369,7 @@ func (c *Controller) ServeUpdateLastFMAPIKeyDo(r *http.Request) *Response { return &Response{redirect: "/admin/home"} } -func (c *Controller) ServeStartScanIncDo(r *http.Request) *Response { +func (c *Controller) ServeStartScanIncDo(_ *http.Request) *Response { defer doScan(c.Scanner, scanner.ScanOptions{}) return &Response{ redirect: "/admin/home", @@ -377,7 +377,7 @@ func (c *Controller) ServeStartScanIncDo(r *http.Request) *Response { } } -func (c *Controller) ServeStartScanFullDo(r *http.Request) *Response { +func (c *Controller) ServeStartScanFullDo(_ *http.Request) *Response { defer doScan(c.Scanner, scanner.ScanOptions{IsFull: true}) return &Response{ redirect: "/admin/home", diff --git a/server/ctrlsubsonic/ctrl_test.go b/server/ctrlsubsonic/ctrl_test.go index ca33f12..e296f80 100644 --- a/server/ctrlsubsonic/ctrl_test.go +++ b/server/ctrlsubsonic/ctrl_test.go @@ -78,22 +78,6 @@ func makeHTTPMockWithAdmin(query url.Values) (*httptest.ResponseRecorder, *http. return rr, req } -func serveRaw(t *testing.T, contr *Controller, h handlerSubsonicRaw, rr *httptest.ResponseRecorder, req *http.Request) { - type middleware func(http.Handler) http.Handler - middlewares := []middleware{ - contr.WithParams, - contr.WithRequiredParams, - contr.WithUser, - } - - handler := contr.HR(h) - for _, m := range middlewares { - handler = m(handler) - } - - handler.ServeHTTP(rr, req) -} - func runQueryCases(t *testing.T, contr *Controller, h handlerSubsonic, cases []*queryCase) { t.Helper() for _, qc := range cases { diff --git a/server/ctrlsubsonic/handlers_by_folder.go b/server/ctrlsubsonic/handlers_by_folder.go index b23cfb2..558b311 100644 --- a/server/ctrlsubsonic/handlers_by_folder.go +++ b/server/ctrlsubsonic/handlers_by_folder.go @@ -279,7 +279,7 @@ func (c *Controller) ServeSearchTwo(r *http.Request) *spec.Response { return sub } -func (c *Controller) ServeGetArtistInfo(r *http.Request) *spec.Response { +func (c *Controller) ServeGetArtistInfo(_ *http.Request) *spec.Response { return spec.NewResponse() } diff --git a/server/ctrlsubsonic/handlers_by_tags.go b/server/ctrlsubsonic/handlers_by_tags.go index 0669e1d..1f90ce8 100644 --- a/server/ctrlsubsonic/handlers_by_tags.go +++ b/server/ctrlsubsonic/handlers_by_tags.go @@ -382,7 +382,7 @@ func (c *Controller) ServeGetArtistInfoTwo(r *http.Request) *spec.Response { return sub } -func (c *Controller) ServeGetGenres(r *http.Request) *spec.Response { +func (c *Controller) ServeGetGenres(_ *http.Request) *spec.Response { var genres []*db.Genre c.DB. Select(`*, diff --git a/server/ctrlsubsonic/handlers_common.go b/server/ctrlsubsonic/handlers_common.go index 4853aa9..050862d 100644 --- a/server/ctrlsubsonic/handlers_common.go +++ b/server/ctrlsubsonic/handlers_common.go @@ -40,7 +40,7 @@ func getMusicFolder(musicPaths []MusicPath, p params.Params) string { return musicPaths[idx].Path } -func (c *Controller) ServeGetLicence(r *http.Request) *spec.Response { +func (c *Controller) ServeGetLicence(_ *http.Request) *spec.Response { sub := spec.NewResponse() sub.Licence = &spec.Licence{ Valid: true, @@ -48,7 +48,7 @@ func (c *Controller) ServeGetLicence(r *http.Request) *spec.Response { return sub } -func (c *Controller) ServePing(r *http.Request) *spec.Response { +func (c *Controller) ServePing(_ *http.Request) *spec.Response { return spec.NewResponse() } @@ -86,7 +86,7 @@ func (c *Controller) ServeScrobble(r *http.Request) *spec.Response { return spec.NewResponse() } -func (c *Controller) ServeGetMusicFolders(r *http.Request) *spec.Response { +func (c *Controller) ServeGetMusicFolders(_ *http.Request) *spec.Response { sub := spec.NewResponse() sub.MusicFolders = &spec.MusicFolders{} for i, mp := range c.MusicPaths { @@ -108,7 +108,7 @@ func (c *Controller) ServeStartScan(r *http.Request) *spec.Response { return c.ServeGetScanStatus(r) } -func (c *Controller) ServeGetScanStatus(r *http.Request) *spec.Response { +func (c *Controller) ServeGetScanStatus(_ *http.Request) *spec.Response { var trackCount int if err := c.DB.Model(db.Track{}).Count(&trackCount).Error; err != nil { return spec.NewError(0, "error finding track count: %v", err) @@ -140,7 +140,7 @@ func (c *Controller) ServeGetUser(r *http.Request) *spec.Response { return sub } -func (c *Controller) ServeNotFound(r *http.Request) *spec.Response { +func (c *Controller) ServeNotFound(_ *http.Request) *spec.Response { return spec.NewError(70, "view not found") } @@ -420,7 +420,7 @@ func (c *Controller) ServeJukebox(r *http.Request) *spec.Response { // nolint:go return sub } -func (c *Controller) ServeGetLyrics(r *http.Request) *spec.Response { +func (c *Controller) ServeGetLyrics(_ *http.Request) *spec.Response { sub := spec.NewResponse() sub.Lyrics = &spec.Lyrics{} return sub diff --git a/server/ctrlsubsonic/handlers_internet_radio.go b/server/ctrlsubsonic/handlers_internet_radio.go index 7927a49..9804197 100644 --- a/server/ctrlsubsonic/handlers_internet_radio.go +++ b/server/ctrlsubsonic/handlers_internet_radio.go @@ -9,7 +9,7 @@ import ( "go.senan.xyz/gonic/server/ctrlsubsonic/spec" ) -func (c *Controller) ServeGetInternetRadioStations(r *http.Request) *spec.Response { +func (c *Controller) ServeGetInternetRadioStations(_ *http.Request) *spec.Response { var stations []*db.InternetRadioStation if err := c.DB.Find(&stations).Error; err != nil { return spec.NewError(0, "find stations: %v", err) diff --git a/transcode/transcoder_none.go b/transcode/transcoder_none.go index e9b8544..18be3a0 100644 --- a/transcode/transcoder_none.go +++ b/transcode/transcoder_none.go @@ -15,7 +15,7 @@ func NewNoneTranscoder() *NoneTranscoder { return &NoneTranscoder{} } -func (*NoneTranscoder) Transcode(ctx context.Context, _ Profile, in string, out io.Writer) error { +func (*NoneTranscoder) Transcode(_ context.Context, _ Profile, in string, out io.Writer) error { file, err := os.Open(in) if err != nil { return fmt.Errorf("open file: %w", err)