From 9cfb34bdc56d392aa76a3e7102b319120ce2aa6f Mon Sep 17 00:00:00 2001 From: streambinder Date: Sat, 7 Sep 2024 11:51:31 +0200 Subject: [PATCH] ci(push): replace golangci-lint with super-linter --- .github/README.md | 2 +- .github/linters/.golangci.yml | 28 ++++++++++++++++++++++++ .github/linters/.hadolint.yaml | 6 ++++++ .github/linters/.jscpd.json | 6 ++++++ .github/workflows/push.yml | 38 ++++++++++++++++++++++++++++----- .github/workflows/scrape.yml | 2 +- .github/workflows/tag.yml | 18 ++++++++++++++-- Dockerfile | 15 +++++++------ cmd/attach.go | 6 +++--- cmd/auth.go | 6 +++--- cmd/lookup.go | 12 +++++------ cmd/lookup_test.go | 4 ++-- cmd/reset.go | 4 ++-- cmd/reset_test.go | 2 +- cmd/root.go | 4 +++- cmd/root_test.go | 2 +- cmd/show.go | 2 +- cmd/sync.go | 39 ++++++++++++++++++---------------- docs/README.md | 2 ++ docs/about.md | 6 +++--- docs/design.md | 3 +-- downloader/youtubedl.go | 2 +- entity/track.go | 22 +++++++++---------- provider/youtube.go | 6 +++--- spotify/auth.go | 11 +++++++--- spotify/id_test.go | 10 ++++----- 26 files changed, 177 insertions(+), 81 deletions(-) create mode 100644 .github/linters/.golangci.yml create mode 100644 .github/linters/.hadolint.yaml create mode 100644 .github/linters/.jscpd.json diff --git a/.github/README.md b/.github/README.md index 5a641a5..9084b46 100644 --- a/.github/README.md +++ b/.github/README.md @@ -1,3 +1,3 @@ -# Spotitube +# Spotitube documentation Documentation available at [davidepucci.it/doc/spotitube](https://davidepucci.it/doc/spotitube). diff --git a/.github/linters/.golangci.yml b/.github/linters/.golangci.yml new file mode 100644 index 0000000..16573a0 --- /dev/null +++ b/.github/linters/.golangci.yml @@ -0,0 +1,28 @@ +--- +issues: + exclude-rules: + - path: _test\.go + linters: + - dupl + - gosec + - goconst +linters: + enable: + - gosec + - unconvert + - gocyclo + - goconst + - goimports + - gocritic + - govet + - revive +linters-settings: + errcheck: + check-blank: true + govet: + enable: + - shadowing + gocyclo: + min-complexity: 20 + maligned: + suggest-new: true diff --git a/.github/linters/.hadolint.yaml b/.github/linters/.hadolint.yaml new file mode 100644 index 0000000..2200bac --- /dev/null +++ b/.github/linters/.hadolint.yaml @@ -0,0 +1,6 @@ +--- +failure-threshold: warning + +ignored: + - DL3018 # Pin versions in apk add + - SC2215 # This flag is used as a command name diff --git a/.github/linters/.jscpd.json b/.github/linters/.jscpd.json new file mode 100644 index 0000000..d015e48 --- /dev/null +++ b/.github/linters/.jscpd.json @@ -0,0 +1,6 @@ +{ + "threshold": 3, + "reporters": ["consoleFull"], + "ignore": ["**/__snapshots__/**", "**/node_modules/**", "**/*_test.go"], + "absolute": true +} diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 64d973d..a57c3c7 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -8,7 +8,21 @@ on: branches: - master -permissions: write-all +permissions: + actions: read + attestations: none + checks: none + contents: read + deployments: none + id-token: none + issues: none + discussions: none + packages: write + pages: none + pull-requests: read + repository-projects: none + security-events: none + statuses: none jobs: commitlint: @@ -25,18 +39,23 @@ jobs: - uses: codespell-project/actions-codespell@v2 with: check_filenames: true - golangci-lint: + super-linter: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: golangci/golangci-lint-action@v6 + - uses: super-linter/super-linter@latest + env: + GITHUB_TOKEN: ${{ secrets.GH_ACTIONS_SPOTITUBE }} + VALIDATE_ALL_CODEBASE: false + VALIDATE_GO: false gofumpt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 - run: | - export PATH=$PATH:$(go env GOPATH)/bin + PATH="$PATH:$(go env GOPATH)/bin" + export PATH go install mvdan.cc/gofumpt@latest if gofumpt -l -e . | grep '^' -q; then exit 1; fi go-channel-closure: @@ -56,7 +75,16 @@ jobs: - run: test "$(grep -cr 'defer gomonkey\.')" = "$(grep -cr 'Reset()$')" test: runs-on: ubuntu-latest - needs: [commitlint, codespell, golangci-lint, gofumpt, go-channel-closure, go-http-body-closure, go-monkey-unpatch] + needs: + [ + commitlint, + codespell, + super-linter, + gofumpt, + go-channel-closure, + go-http-body-closure, + go-monkey-unpatch, + ] if: success() steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/scrape.yml b/.github/workflows/scrape.yml index a1ebcc8..174286c 100644 --- a/.github/workflows/scrape.yml +++ b/.github/workflows/scrape.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 - - run: go test -v -run ^TestScraping$ ./... + - run: go test -v -run ^TestScraping$ ./... env: TEST_SCRAPING: true GENIUS_TOKEN: ${{ secrets.GENIUS_TOKEN }} diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index 465fbc2..c3ae169 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -3,9 +3,23 @@ name: tag on: push: tags: - - 'v*.*.*' + - "v*.*.*" -permissions: write-all +permissions: + actions: read + attestations: none + checks: none + contents: read + deployments: none + id-token: none + issues: none + discussions: none + packages: write + pages: none + pull-requests: read + repository-projects: none + security-events: none + statuses: none jobs: test: diff --git a/Dockerfile b/Dockerfile index 012a343..b66c9b2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,20 +2,23 @@ FROM golang:alpine AS builder WORKDIR /workspace COPY . . -RUN go mod download -RUN --mount=type=secret,id=SPOTIFY_ID \ +RUN go mod download && \ + --mount=type=secret,id=SPOTIFY_ID \ --mount=type=secret,id=SPOTIFY_KEY \ --mount=type=secret,id=GENIUS_TOKEN \ go build -ldflags="-s -w -X github.com/streambinder/spotitube/spotify.fallbackSpotifyID=$(cat /run/secrets/SPOTIFY_ID) -X github.com/streambinder/spotitube/spotify.fallbackSpotifyKey=$(cat /run/secrets/SPOTIFY_KEY) -X github.com/streambinder/spotitube/lyrics.fallbackGeniusToken=$(cat /run/secrets/GENIUS_TOKEN)" -FROM alpine:latest -RUN apk add --no-cache ffmpeg yt-dlp -RUN mkdir /data -RUN mkdir /cache +FROM alpine:3 +RUN apk add --no-cache ffmpeg yt-dlp && \ + mkdir /data && \ + mkdir /cache && \ + useradd -m spotitube +USER spotitube WORKDIR /data ENV XDG_MUSIC_DIR=/data ENV XDG_CACHE_HOME=/cache COPY --from=builder /workspace/spotitube /usr/sbin/ +HEALTHCHECK CMD [ "/usr/sbin/spotitube", "--help" ] EXPOSE 65535/tcp ENTRYPOINT ["/usr/sbin/spotitube"] LABEL org.opencontainers.image.source=https://github.com/streambinder/spotitube diff --git a/cmd/attach.go b/cmd/attach.go index f8d5b8e..208d274 100644 --- a/cmd/attach.go +++ b/cmd/attach.go @@ -26,9 +26,9 @@ func cmdAttach() *cobra.Command { Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { var ( - path = args[0] - id = args[1] - rename, _ = cmd.Flags().GetBool("rename") + path = args[0] + id = args[1] + rename = util.ErrWrap(false)(cmd.Flags().GetBool("rename")) ) localTrack, err := id3.Open(path, id3v2.Options{Parse: false}) diff --git a/cmd/auth.go b/cmd/auth.go index 3a039ac..21383f4 100644 --- a/cmd/auth.go +++ b/cmd/auth.go @@ -25,10 +25,10 @@ func cmdAuth() *cobra.Command { Use: "auth", Short: "Establish a Spotify session for future uses", SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { var ( - remote, _ = cmd.Flags().GetBool("remote") - logout, _ = cmd.Flags().GetBool("logout") + remote = util.ErrWrap(false)(cmd.Flags().GetBool("remote")) + logout = util.ErrWrap(false)(cmd.Flags().GetBool("logout")) callback = "127.0.0.1" processor = spotify.BrowserProcessor ) diff --git a/cmd/lookup.go b/cmd/lookup.go index ef0944f..afb1ec7 100644 --- a/cmd/lookup.go +++ b/cmd/lookup.go @@ -30,10 +30,10 @@ func cmdLookup() *cobra.Command { Short: "Utility to lookup for tracks in order to investigate general querying behaviour", SilenceUsage: true, RunE: func(cmd *cobra.Command, args []string) error { - library, _ := cmd.Flags().GetBool("library") - random, _ := cmd.Flags().GetBool("random") - randomSize, _ := cmd.Flags().GetInt("random-size") - libraryLimit, _ := cmd.Flags().GetInt("library-limit") + library := util.ErrWrap(false)(cmd.Flags().GetBool("library")) + random := util.ErrWrap(false)(cmd.Flags().GetBool("random")) + randomSize := util.ErrWrap(defaultRandomSize)(cmd.Flags().GetInt("random-size")) + libraryLimit := util.ErrWrap(0)(cmd.Flags().GetInt("library-limit")) if !library && !random && len(args) == 0 { return errors.New("no track has been issued") } @@ -48,7 +48,7 @@ func cmdLookup() *cobra.Command { lyricsChannel = make(chan interface{}, 1) ) return nursery.RunConcurrently( - func(ctx context.Context, ch chan error) { + func(_ context.Context, ch chan error) { defer close(providerChannel) defer close(lyricsChannel) if random { @@ -70,7 +70,7 @@ func cmdLookup() *cobra.Command { } } }, - func(ctx context.Context, ch chan error) { + func(_ context.Context, _ chan error) { prefix := "[P]" for event := range providerChannel { track := event.(*entity.Track) diff --git a/cmd/lookup_test.go b/cmd/lookup_test.go index 701fdb5..58e2ffc 100644 --- a/cmd/lookup_test.go +++ b/cmd/lookup_test.go @@ -110,7 +110,7 @@ func TestCmdLookupLibraryFailure(t *testing.T) { ApplyFunc(spotify.Authenticate, func() (*spotify.Client, error) { return &spotify.Client{}, nil }). - ApplyMethod(&spotify.Client{}, "Library", func(_ *spotify.Client, _ int, ch ...chan interface{}) error { + ApplyMethod(&spotify.Client{}, "Library", func(_ *spotify.Client, _ int, _ ...chan interface{}) error { return errors.New("ko") }). Reset() @@ -125,7 +125,7 @@ func TestCmdLookupTrackFailure(t *testing.T) { ApplyFunc(spotify.Authenticate, func() (*spotify.Client, error) { return &spotify.Client{}, nil }). - ApplyMethod(&spotify.Client{}, "Track", func(_ *spotify.Client, _ string, ch ...chan interface{}) (*entity.Track, error) { + ApplyMethod(&spotify.Client{}, "Track", func(_ *spotify.Client, _ string, _ ...chan interface{}) (*entity.Track, error) { return nil, errors.New("ko") }).Reset() diff --git a/cmd/reset.go b/cmd/reset.go index e40b0e7..4fcd533 100644 --- a/cmd/reset.go +++ b/cmd/reset.go @@ -20,9 +20,9 @@ func cmdReset() *cobra.Command { Short: "Clear cached objects", SilenceUsage: true, Args: cobra.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { var ( - session, _ = cmd.Flags().GetBool("session") + session = util.ErrWrap(false)(cmd.Flags().GetBool("session")) cacheDirectory = util.CacheDirectory() ) return filepath.WalkDir(cacheDirectory, func(path string, entry fs.DirEntry, err error) error { diff --git a/cmd/reset_test.go b/cmd/reset_test.go index ea90390..c1a2d63 100644 --- a/cmd/reset_test.go +++ b/cmd/reset_test.go @@ -43,7 +43,7 @@ func BenchmarkReset(b *testing.B) { func TestCmdReset(t *testing.T) { // monkey patching defer gomonkey.NewPatches(). - ApplyFunc(filepath.WalkDir, func(path string, f func(string, fs.DirEntry, error) error) error { + ApplyFunc(filepath.WalkDir, func(_ string, f func(string, fs.DirEntry, error) error) error { _ = f("", DirEntry{name: "", isDir: false}, errors.New("some error")) _ = f(spotify.TokenBasename, DirEntry{name: spotify.TokenBasename, isDir: false}, nil) _ = f("fname.txt", DirEntry{name: "fname.txt", isDir: false}, nil) diff --git a/cmd/root.go b/cmd/root.go index 702fcea..7fbf54d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -10,5 +10,7 @@ var cmdRoot = &cobra.Command{ } func Execute() { - _ = cmdRoot.Execute() + if err := cmdRoot.Execute(); err != nil { + cmdRoot.Println(err) + } } diff --git a/cmd/root_test.go b/cmd/root_test.go index d306db2..7dc3703 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -25,7 +25,7 @@ func testExecute(cmd *cobra.Command, args ...string) error { return cmdTest.Execute() } -func TestExecute(t *testing.T) { +func TestExecute(_ *testing.T) { cmdRoot.SetOut(io.Discard) cmdRoot.SetErr(io.Discard) cmdRoot.SetOutput(io.Discard) diff --git a/cmd/show.go b/cmd/show.go index 6e8a518..c29478b 100644 --- a/cmd/show.go +++ b/cmd/show.go @@ -24,7 +24,7 @@ func cmdShow() *cobra.Command { Short: "Show local tracks data", SilenceUsage: true, Args: cobra.MinimumNArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { bold := color.New(color.Bold) for _, path := range args { if err := func() error { diff --git a/cmd/sync.go b/cmd/sync.go index 7c8118d..71fe018 100644 --- a/cmd/sync.go +++ b/cmd/sync.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "log" "os" "path/filepath" "strconv" @@ -54,18 +55,18 @@ func cmdSync() *cobra.Command { Short: "Synchronize collections", SilenceUsage: true, Args: cobra.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { var ( - path, _ = cmd.Flags().GetString("output") - playlistEncoding, _ = cmd.Flags().GetString("playlist-encoding") - manual, _ = cmd.Flags().GetBool("manual") - library, _ = cmd.Flags().GetBool("library") - playlists, _ = cmd.Flags().GetStringArray("playlist") - playlistsTracks, _ = cmd.Flags().GetStringArray("playlist-tracks") - albums, _ = cmd.Flags().GetStringArray("album") - tracks, _ = cmd.Flags().GetStringArray("track") - fixes, _ = cmd.Flags().GetStringArray("fix") - libraryLimit, _ = cmd.Flags().GetInt("library-limit") + path = util.ErrWrap(xdg.UserDirs.Music)(cmd.Flags().GetString("output")) + playlistEncoding = util.ErrWrap("m3u")(cmd.Flags().GetString("playlist-encoding")) + manual = util.ErrWrap(false)(cmd.Flags().GetBool("manual")) + library = util.ErrWrap(false)(cmd.Flags().GetBool("library")) + playlists = util.ErrWrap([]string{})(cmd.Flags().GetStringArray("playlist")) + playlistsTracks = util.ErrWrap([]string{})(cmd.Flags().GetStringArray("playlist-tracks")) + albums = util.ErrWrap([]string{})(cmd.Flags().GetStringArray("album")) + tracks = util.ErrWrap([]string{})(cmd.Flags().GetStringArray("track")) + fixes = util.ErrWrap([]string{})(cmd.Flags().GetStringArray("fix")) + libraryLimit = util.ErrWrap(0)(cmd.Flags().GetInt("library-limit")) ) for index, path := range fixes { @@ -89,7 +90,7 @@ func cmdSync() *cobra.Command { routineMix(playlistEncoding), ) }, - PreRun: func(cmd *cobra.Command, args []string) { + PreRun: func(cmd *cobra.Command, _ []string) { routineSemaphores = map[int](chan bool){ routineTypeIndex: make(chan bool, 1), routineTypeAuth: make(chan bool, 1), @@ -104,16 +105,18 @@ func cmdSync() *cobra.Command { } var ( - playlists, _ = cmd.Flags().GetStringArray("playlist") - playlistsTracks, _ = cmd.Flags().GetStringArray("playlist-tracks") - albums, _ = cmd.Flags().GetStringArray("album") - tracks, _ = cmd.Flags().GetStringArray("track") - fixes, _ = cmd.Flags().GetStringArray("fix") + playlists = util.ErrWrap([]string{})(cmd.Flags().GetStringArray("playlist")) + playlistsTracks = util.ErrWrap([]string{})(cmd.Flags().GetStringArray("playlist-tracks")) + albums = util.ErrWrap([]string{})(cmd.Flags().GetStringArray("album")) + tracks = util.ErrWrap([]string{})(cmd.Flags().GetStringArray("track")) + fixes = util.ErrWrap([]string{})(cmd.Flags().GetStringArray("fix")) ) if len(playlists)+len(playlistsTracks)+len(albums)+len(tracks)+len(fixes) == 0 { cmd.LocalFlags().VisitAll(func(f *pflag.Flag) { if f.Name == "library" { - _ = f.Value.Set("true") + if err := f.Value.Set("true"); err != nil { + log.Fatal(err) + } } }) } diff --git a/docs/README.md b/docs/README.md index dd802bf..1bd8ed2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,3 +1,5 @@ +# Documentation + 1. [About](about.md) 2. [Installation](installation.md) 3. [Design](design.md) diff --git a/docs/about.md b/docs/about.md index ea3c064..89bd6b7 100644 --- a/docs/about.md +++ b/docs/about.md @@ -1,6 +1,6 @@ # About -![](assets/demo.gif) +![demo](assets/demo.gif) Spotitube is a CLI application to authenticate to Spotify account, fetch music collections — such as account library, playlists, albums or specific tracks —, look them up on a defined set of providers — such as YouTube —, download them and inflate the downloaded assets with metadata collected from Spotify, further enriched with lyrics. @@ -55,8 +55,8 @@ docker run -it --rm \ The only real issue to be addressed when working with Spotitube running in headless mode, is the redirect during Spotify authentication. -By default, once authenticated to Spotify via web, Spotify itself redirects to a predefined callback URL, which corresponds to http://localhost:65535. -In order to make that redirect go against a custom server, on Spotitube Spotify app, a further callback URL has been defined, i.e. http://spotitube.local:65535. +By default, once authenticated to Spotify via web, Spotify itself redirects to a predefined callback URL, which corresponds to `http://localhost:65535`. +In order to make that redirect go against a custom server, on Spotitube Spotify app, a further callback URL has been defined, i.e. `http://spotitube.local:65535`. This is the one that is set as callback at runtime when Spotitube goes through authentication with the `--remote` flag. So, assuming the server on which Spotitube is running is reachable at 1.2.3.4, make sure the client can correctly resolve `spotitube.local` as 1.2.3.4. diff --git a/docs/design.md b/docs/design.md index 771e84b..d82575a 100644 --- a/docs/design.md +++ b/docs/design.md @@ -8,8 +8,7 @@ Such queues usually carry a specific track (be it part of synchronization of use The assembly line is made of the following routines: - -![](assets/design.svg) +![design](assets/design.svg) ## Indexer diff --git a/downloader/youtubedl.go b/downloader/youtubedl.go index b386b10..47467f4 100644 --- a/downloader/youtubedl.go +++ b/downloader/youtubedl.go @@ -19,7 +19,7 @@ func (youTubeDl) supports(url string) bool { return strings.Contains(url, "://youtu.be") || strings.Contains(url, "://youtube.com") } -func (youTubeDl) download(url, path string, processor processor.Processor, channels ...chan []byte) error { +func (youTubeDl) download(url, path string, _ processor.Processor, channels ...chan []byte) error { // in this case, data won't be passed through channels // as too heavy for _, ch := range channels { diff --git a/entity/track.go b/entity/track.go index 92d3d69..d2bfc5f 100644 --- a/entity/track.go +++ b/entity/track.go @@ -27,7 +27,7 @@ type Track struct { UpstreamURL string // URL to the upstream blob the song's been downloaded from } -type trackPath struct { +type TrackPath struct { track *Track } @@ -53,28 +53,28 @@ func (track *Track) Song() (song string) { return } -func (track *Track) Path() trackPath { - return trackPath{track} +func (track *Track) Path() TrackPath { + return TrackPath{track} } -func (trackPath trackPath) Final() string { - return util.LegalizeFilename(fmt.Sprintf("%s - %s.%s", trackPath.track.Artists[0], trackPath.track.Title, TrackFormat)) +func (TrackPath TrackPath) Final() string { + return util.LegalizeFilename(fmt.Sprintf("%s - %s.%s", TrackPath.track.Artists[0], TrackPath.track.Title, TrackFormat)) } -func (trackPath trackPath) Download() string { +func (TrackPath TrackPath) Download() string { return util.CacheFile( - util.LegalizeFilename(fmt.Sprintf("%s.%s", slug.Make(trackPath.track.ID), TrackFormat)), + util.LegalizeFilename(fmt.Sprintf("%s.%s", slug.Make(TrackPath.track.ID), TrackFormat)), ) } -func (trackPath trackPath) Artwork() string { +func (TrackPath TrackPath) Artwork() string { return util.CacheFile( - util.LegalizeFilename(fmt.Sprintf("%s.%s", slug.Make(path.Base(trackPath.track.Artwork.URL)), ArtworkFormat)), + util.LegalizeFilename(fmt.Sprintf("%s.%s", slug.Make(path.Base(TrackPath.track.Artwork.URL)), ArtworkFormat)), ) } -func (trackPath trackPath) Lyrics() string { +func (TrackPath TrackPath) Lyrics() string { return util.CacheFile( - util.LegalizeFilename(fmt.Sprintf("%s.%s", slug.Make(trackPath.track.ID), LyricsFormat)), + util.LegalizeFilename(fmt.Sprintf("%s.%s", slug.Make(TrackPath.track.ID), LyricsFormat)), ) } diff --git a/provider/youtube.go b/provider/youtube.go index c340aaf..9a41212 100644 --- a/provider/youtube.go +++ b/provider/youtube.go @@ -30,7 +30,7 @@ type youTubeInitialData struct { ItemSectionRenderer struct { Contents []struct { VideoRenderer struct { - VideoId string + VideoID string Title struct { Runs []Run } @@ -123,7 +123,7 @@ func (provider youTube) search(track *entity.Track) ([]*Match, error) { return nil, err } - json := strings.Join(document.Find("script").Map(func(i int, selection *goquery.Selection) string { + json := strings.Join(document.Find("script").Map(func(_ int, selection *goquery.Selection) string { prefix := "var ytInitialData =" if !strings.HasPrefix(strings.TrimPrefix(selection.Text(), " "), prefix) { return "" @@ -147,7 +147,7 @@ func (provider youTube) search(track *entity.Track) ([]*Match, error) { match := youTubeResult{ track: track, query: query, - id: result.VideoRenderer.VideoId, + id: result.VideoRenderer.VideoID, title: title.Text, owner: result.VideoRenderer.OwnerText.Runs[run].Text, description: util.First(result.VideoRenderer.DetailedMetadataSnippets, DetailedMetadataSnippet{ diff --git a/spotify/auth.go b/spotify/auth.go index de47ab2..97df3a8 100644 --- a/spotify/auth.go +++ b/spotify/auth.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "path/filepath" + "time" "github.com/arunsworld/nursery" "github.com/streambinder/spotitube/util" @@ -39,9 +40,13 @@ type Client struct { func Authenticate(urlProcessor func(string) error, callbacks ...string) (*Client, error) { var ( - client Client - serverMux = http.NewServeMux() - server = &http.Server{Addr: fmt.Sprintf("0.0.0.0:%d", port), Handler: serverMux} + client Client + serverMux = http.NewServeMux() + server = &http.Server{ + Addr: fmt.Sprintf("0.0.0.0:%d", port), + Handler: serverMux, + ReadHeaderTimeout: 2 * time.Second, + } state = randstr.Hex(20) callback = "127.0.0.1" clientChannel = make(chan *spotify.Client, 1) diff --git a/spotify/id_test.go b/spotify/id_test.go index 2da5359..90d1f98 100644 --- a/spotify/id_test.go +++ b/spotify/id_test.go @@ -16,10 +16,10 @@ func BenchmarkID(b *testing.B) { func TestID(t *testing.T) { var ( target = "1234567890123456789012" - spotifyId = spotify.ID(target) + spotifyID = spotify.ID(target) ) - assert.Equal(t, id(target), spotifyId) - assert.Equal(t, id("spotify:track:"+target), spotifyId) - assert.Equal(t, id("https://open.spotify.com/track/"+target), spotifyId) - assert.Equal(t, id("https://open.spotify.com/track/"+target+"?si=abcdefghijklmnop"), spotifyId) + assert.Equal(t, id(target), spotifyID) + assert.Equal(t, id("spotify:track:"+target), spotifyID) + assert.Equal(t, id("https://open.spotify.com/track/"+target), spotifyID) + assert.Equal(t, id("https://open.spotify.com/track/"+target+"?si=abcdefghijklmnop"), spotifyID) }