Pack volumes into CBR files
This commit is contained in:
parent
6202059a2e
commit
65e2c9f051
3
go.mod
3
go.mod
|
@ -3,6 +3,7 @@ module code.fmartingr.dev/fmartingr/mangadex2cbr
|
||||||
go 1.15
|
go 1.15
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.fmartingr.dev/fmartingr/go-mangadex v0.0.0-20210206105358-8cfcb7a013b8
|
code.fmartingr.dev/fmartingr/go-mangadex v0.0.0-20210209223856-e7c5b4489931
|
||||||
github.com/sirupsen/logrus v1.7.0
|
github.com/sirupsen/logrus v1.7.0
|
||||||
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect
|
||||||
)
|
)
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -1,5 +1,5 @@
|
||||||
code.fmartingr.dev/fmartingr/go-mangadex v0.0.0-20210206105358-8cfcb7a013b8 h1:JS8C40VcGUO1WdaAQfofvu4ROzDSJ1YCG0ycswOPfyY=
|
code.fmartingr.dev/fmartingr/go-mangadex v0.0.0-20210209223856-e7c5b4489931 h1:DqfEAJhJaP+DYVVrw9LjoDol4NLD14wLVyCe+8Cblsc=
|
||||||
code.fmartingr.dev/fmartingr/go-mangadex v0.0.0-20210206105358-8cfcb7a013b8/go.mod h1:C4HCcFpl4VDk4O5Huau2cdTAOuwqIP9NBXItWhaMZVo=
|
code.fmartingr.dev/fmartingr/go-mangadex v0.0.0-20210209223856-e7c5b4489931/go.mod h1:kcfwcGVuiSu/dloZwo/G8FxDzNHA/zanIr8DC5VResQ=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
@ -10,3 +10,5 @@ github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||||
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|
126
pkg/cli/cli.go
126
pkg/cli/cli.go
|
@ -1,9 +1,11 @@
|
||||||
package cli
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
@ -66,7 +68,7 @@ func DownloadFile(url string, destinationPath string) error {
|
||||||
|
|
||||||
_, errWrite := file.Write(body)
|
_, errWrite := file.Write(body)
|
||||||
if errWrite != nil {
|
if errWrite != nil {
|
||||||
logrus.Errorf("Error writting image: %s", errWrite)
|
return errWrite
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -108,6 +110,8 @@ func Start() {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Allow selecting a name from AlternativeNames
|
||||||
|
|
||||||
logrus.Infof("Found! %s", manga.Title)
|
logrus.Infof("Found! %s", manga.Title)
|
||||||
logrus.Infof("Getting chapter information...")
|
logrus.Infof("Getting chapter information...")
|
||||||
|
|
||||||
|
@ -181,10 +185,11 @@ func Start() {
|
||||||
// Usually chapters are just 1, 2, 3... but in some ocassions the chapters are sorted like
|
// Usually chapters are just 1, 2, 3... but in some ocassions the chapters are sorted like
|
||||||
// 1, 1.1, 1.2, 2, ... and that make a mess when sorting. Making the "non-decimal" chapters
|
// 1, 1.1, 1.2, 2, ... and that make a mess when sorting. Making the "non-decimal" chapters
|
||||||
// fake "decimals" solves this issue easily for us.
|
// fake "decimals" solves this issue easily for us.
|
||||||
|
|
||||||
// TODO Delete me
|
// TODO Delete me
|
||||||
if mangaChapters[chapter].Volume != "1" {
|
// if mangaChapters[chapter].Volume != "1" {
|
||||||
continue
|
// continue
|
||||||
}
|
// }
|
||||||
|
|
||||||
if !strings.Contains(mangaChapters[chapter].Chapter, ".") {
|
if !strings.Contains(mangaChapters[chapter].Chapter, ".") {
|
||||||
mangaChapters[chapter].Chapter += ".0"
|
mangaChapters[chapter].Chapter += ".0"
|
||||||
|
@ -219,10 +224,10 @@ func Start() {
|
||||||
var task tasks.Task
|
var task tasks.Task
|
||||||
task, downloadChaptersTasks = tasks.TaskPop(downloadChaptersTasks)
|
task, downloadChaptersTasks = tasks.TaskPop(downloadChaptersTasks)
|
||||||
|
|
||||||
// TODO: remove me
|
// TODO: Delete me
|
||||||
if task.Arguments["volume"] != "1" {
|
// if task.Arguments["volume"] != "1" {
|
||||||
continue
|
// continue
|
||||||
}
|
// }
|
||||||
|
|
||||||
chapter, errChapterDetail := manga.GetChapter(task.Arguments["chapterID"])
|
chapter, errChapterDetail := manga.GetChapter(task.Arguments["chapterID"])
|
||||||
if errChapterDetail != nil {
|
if errChapterDetail != nil {
|
||||||
|
@ -265,6 +270,8 @@ func Start() {
|
||||||
logrus.Tracef("Downlading page to %s", destinationPath)
|
logrus.Tracef("Downlading page to %s", destinationPath)
|
||||||
errDownload := DownloadFile(task.Arguments["url"], destinationPath)
|
errDownload := DownloadFile(task.Arguments["url"], destinationPath)
|
||||||
if errDownload != nil {
|
if errDownload != nil {
|
||||||
|
// TODO: Distinguish between 420 errors (GONE -> Use fallback) and other errors to keep retrying on the
|
||||||
|
// original (potentially MangaDex@HOME) urls.
|
||||||
_, exists := task.Arguments["urlFallback"]
|
_, exists := task.Arguments["urlFallback"]
|
||||||
if exists {
|
if exists {
|
||||||
logrus.Warnf("Using fallback for page %s", task.Arguments["filename"])
|
logrus.Warnf("Using fallback for page %s", task.Arguments["filename"])
|
||||||
|
@ -279,29 +286,110 @@ func Start() {
|
||||||
logrus.Errorf("Error downloading page: %s", errDownload)
|
logrus.Errorf("Error downloading page: %s", errDownload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
}
|
}
|
||||||
time.Sleep(100 * time.Millisecond)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logrus.Info("Downloading covers")
|
||||||
covers, errCovers := manga.GetCovers()
|
covers, errCovers := manga.GetCovers()
|
||||||
if errCovers != nil {
|
if errCovers != nil {
|
||||||
logrus.Errorf("Error getting cover information: %s", errCovers)
|
logrus.Errorf("Error getting cover information: %s", errCovers)
|
||||||
}
|
}
|
||||||
|
|
||||||
for cover := range covers {
|
for cover := range covers {
|
||||||
if covers[cover].Volume == "1" {
|
extension := path.Ext(covers[cover].URL)
|
||||||
extension := path.Ext(covers[cover].URL)
|
coverOutputPath := filepath.Join(mangaOutputPath, fmt.Sprintf("%s - Volume %s", manga.Title, covers[cover].Volume), fmt.Sprintf("0000%s", extension))
|
||||||
coverOutputPath := filepath.Join(mangaOutputPath, fmt.Sprintf("%s - Volume %s", manga.Title, covers[cover].Volume), fmt.Sprintf("0000%s", extension))
|
if !fileExists(coverOutputPath) {
|
||||||
if !fileExists(coverOutputPath) {
|
logrus.Tracef("Downloading cover from %s", covers[cover].URL)
|
||||||
logrus.Tracef("Downloading cover from %s", covers[cover].URL)
|
logrus.Tracef("Writting cover to: %s", coverOutputPath)
|
||||||
logrus.Tracef("Writting cover to: %s", coverOutputPath)
|
errDownload := DownloadFile(covers[cover].URL, coverOutputPath)
|
||||||
errDownload := DownloadFile(covers[cover].URL, coverOutputPath)
|
if errDownload != nil {
|
||||||
if errDownload != nil {
|
logrus.Errorf("Error downloading cover: %s", errDownload)
|
||||||
logrus.Errorf("Error downloading cover: %s", errDownload)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Zip folders into CBR files
|
// TODO: Zip folders into CBR files
|
||||||
|
logrus.Info("Compressing volumes")
|
||||||
|
|
||||||
|
files, errReadVolumes := ioutil.ReadDir(mangaOutputPath)
|
||||||
|
if errReadVolumes != nil {
|
||||||
|
logrus.Errorf("Error reading path with volume files: %s", errReadVolumes)
|
||||||
|
}
|
||||||
|
|
||||||
|
for file := range files {
|
||||||
|
if files[file].IsDir() {
|
||||||
|
destinationPath := filepath.Join(mangaOutputPath, files[file].Name()) + ".cbr"
|
||||||
|
if !fileExists(destinationPath) {
|
||||||
|
_, errZip := zipVolume(destinationPath)
|
||||||
|
if errZip != nil {
|
||||||
|
logrus.Errorf("Error packing CBR file: %s", errZip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func zipVolume(destinationPath string) (string, error) {
|
||||||
|
logrus.Tracef("Packing volume %s", path.Base(destinationPath))
|
||||||
|
pagesPath := strings.Replace(destinationPath, path.Ext(destinationPath), "", 1)
|
||||||
|
|
||||||
|
newZipFile, errCreate := os.Create(destinationPath)
|
||||||
|
if errCreate != nil {
|
||||||
|
return "", errCreate
|
||||||
|
}
|
||||||
|
defer newZipFile.Close()
|
||||||
|
|
||||||
|
zipWriter := zip.NewWriter(newZipFile)
|
||||||
|
defer zipWriter.Close()
|
||||||
|
|
||||||
|
files, errReadFiles := ioutil.ReadDir(pagesPath)
|
||||||
|
if errReadFiles != nil {
|
||||||
|
return "", errReadFiles
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
if errAddFile := AddFileToZip(zipWriter, filepath.Join(pagesPath, file.Name())); errAddFile != nil {
|
||||||
|
return "", errAddFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddFileToZip(zipWriter *zip.Writer, filename string) error {
|
||||||
|
|
||||||
|
fileToZip, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fileToZip.Close()
|
||||||
|
|
||||||
|
// Get the file information
|
||||||
|
info, err := fileToZip.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
header, err := zip.FileInfoHeader(info)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using FileInfoHeader() above only uses the basename of the file. If we want
|
||||||
|
// to preserve the folder structure we can overwrite this with the full path.
|
||||||
|
header.Name = filename
|
||||||
|
|
||||||
|
// Change to deflate to gain better compression
|
||||||
|
// see http://golang.org/pkg/archive/zip/#pkg-constants
|
||||||
|
header.Method = zip.Deflate
|
||||||
|
|
||||||
|
writer, err := zipWriter.CreateHeader(header)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = io.Copy(writer, fileToZip)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue