diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml new file mode 100644 index 0000000..aa7aa8d --- /dev/null +++ b/.github/workflows/docker.yaml @@ -0,0 +1,42 @@ +name: Docker + +on: + push: + branches: + - 'master' + tags: + - 'v*' + pull_request: + branches: + - 'master' +jobs: + publish: + name: Push docker image to docker hub + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Get short version and tag + run: | + echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_ENV + echo "tag=$(git describe --tags)" >> $GITHUB_ENV + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: elboletaire/manga-downloader + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d348d59 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +# Build from a golang based image +FROM golang:latest as builder + +LABEL maintainer="Òscar Casajuana " + +WORKDIR /app + +COPY go.mod go.sum ./ +RUN go mod download +COPY . . + +RUN make build/unix + +# Start a new stage from scratch +FROM alpine:latest + +WORKDIR /app + +RUN mkdir /downloads + +# Copy the pre-built binary file from the previous stage +COPY --from=builder /app/manga-downloader . + +# Set manga-downloader as the entrypoint +ENTRYPOINT ["./manga-downloader", "-o", "/downloads"] diff --git a/cmd/root.go b/cmd/root.go index d48adfc..3ac5cd2 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -150,7 +150,7 @@ Note arguments aren't really positional, you can specify them in any order: } if !settings.Bundle { - filename, err := packer.PackSingle(s, d) + filename, err := packer.PackSingle(settings.OutputDir, s, d) if err == nil { fmt.Printf("- %s %s\n", color.GreenString("saved file"), color.HiBlackString(filename)) } else { @@ -182,7 +182,7 @@ Note arguments aren't really positional, you can specify them in any order: dc = append(dc, d.(*packer.DownloadedChapter)) } - filename, err := packer.PackBundle(s, dc, settings.Range) + filename, err := packer.PackBundle(settings.OutputDir, s, dc, settings.Range) if err != nil { color.Red(err.Error()) os.Exit(1) @@ -220,6 +220,7 @@ func init() { rootCmd.Flags().Uint8VarP(&settings.MaxConcurrency.Pages, "concurrency-pages", "C", 10, "number of concurrent page downloads, hard-limited to 10") rootCmd.Flags().StringVarP(&settings.Language, "language", "l", "", "only download the specified language") rootCmd.Flags().StringVarP(&settings.FilenameTemplate, "filename-template", "t", packer.FilenameTemplateDefault, "template for the resulting filename") + rootCmd.Flags().StringVarP(&settings.OutputDir, "output-dir", "o", "./", "output directory for the downloaded files") } func cerr(err error, prefix string) { diff --git a/grabber/site.go b/grabber/site.go index b20096d..7ca0b80 100644 --- a/grabber/site.go +++ b/grabber/site.go @@ -31,6 +31,8 @@ type Settings struct { FilenameTemplate string // Range is the range to be downloaded (in string, i.e. "1-10,23,45-50") Range string + // OutputDir is the output directory for the downloaded files + OutputDir string } // MaxConcurrency is the max concurrency for a site diff --git a/makefile b/makefile index 034a0f7..5549285 100644 --- a/makefile +++ b/makefile @@ -21,7 +21,7 @@ build: clean test build/unix build/all: clean test build/unix build/win build/unix: - go build -o manga-downloader ${GOFLAGS} . + CGO_ENABLED=0 go build -o manga-downloader ${GOFLAGS} . build/win: go build -o manga-downloader.exe ${GOFLAGS} . diff --git a/packer/pack.go b/packer/pack.go index d895ddc..6d60383 100644 --- a/packer/pack.go +++ b/packer/pack.go @@ -2,6 +2,7 @@ package packer import ( "fmt" + "path/filepath" "github.com/elboletaire/manga-downloader/downloader" "github.com/elboletaire/manga-downloader/grabber" @@ -14,27 +15,27 @@ type DownloadedChapter struct { } // PackSingle packs a single downloaded chapter -func PackSingle(s grabber.Site, chapter *DownloadedChapter) (string, error) { +func PackSingle(outputdir string, s grabber.Site, chapter *DownloadedChapter) (string, error) { title, _ := s.FetchTitle() - return pack(s.GetFilenameTemplate(), title, NewChapterFileTemplateParts(title, chapter.Chapter), chapter.Files) + return pack(outputdir, s.GetFilenameTemplate(), title, NewChapterFileTemplateParts(title, chapter.Chapter), chapter.Files) } // PackBundle packs a bundle of downloaded chapters -func PackBundle(s grabber.Site, chapters []*DownloadedChapter, rng string) (string, error) { +func PackBundle(outputdir string, s grabber.Site, chapters []*DownloadedChapter, rng string) (string, error) { title, _ := s.FetchTitle() files := []*downloader.File{} for _, chapter := range chapters { files = append(files, chapter.Files...) } - return pack(s.GetFilenameTemplate(), title, FilenameTemplateParts{ + return pack(outputdir, s.GetFilenameTemplate(), title, FilenameTemplateParts{ Series: title, Number: rng, Title: "bundle", }, files) } -func pack(template, title string, parts FilenameTemplateParts, files []*downloader.File) (string, error) { +func pack(outputdir, template, title string, parts FilenameTemplateParts, files []*downloader.File) (string, error) { filename, err := NewFilenameFromTemplate(template, parts) if err != nil { return "", fmt.Errorf("- error creating filename for chapter %s: %s", title, err.Error()) @@ -42,7 +43,7 @@ func pack(template, title string, parts FilenameTemplateParts, files []*download filename += ".cbz" - if err = ArchiveCBZ(filename, files); err != nil { + if err = ArchiveCBZ(filepath.Join(outputdir, filename), files); err != nil { return "", fmt.Errorf("- error saving file %s: %s", filename, err.Error()) }