From da72fe18f48ed88ee4b427ec0cce2738263e0510 Mon Sep 17 00:00:00 2001 From: metafates Date: Sun, 21 Aug 2022 10:37:14 +0400 Subject: [PATCH 01/51] fix(tui): adjust help width --- tui/bubble.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tui/bubble.go b/tui/bubble.go index e9ab88c3..f2df9474 100644 --- a/tui/bubble.go +++ b/tui/bubble.go @@ -110,13 +110,25 @@ func (b *statefulBubble) resize(width, height int) { listHeight := height - yy b.scrapersInstallC.SetSize(listWidth, listHeight) + b.scrapersInstallC.Help.Width = listWidth + b.historyC.SetSize(listWidth, listHeight) + b.historyC.Help.Width = listWidth + b.sourcesC.SetSize(listWidth, listHeight) + b.sourcesC.Help.Width = listWidth + b.mangasC.SetSize(listWidth, listHeight) + b.mangasC.Help.Width = listWidth + b.chaptersC.SetSize(listWidth, listHeight) - b.progressC.Width = styledWidth + b.chaptersC.Help.Width = listWidth + + b.progressC.Width = listWidth + b.width = styledWidth b.height = styledHeight + b.helpC.Width = styledWidth } func (b *statefulBubble) startLoading() tea.Cmd { From 8fb9a1716041938742ce1175a212c062f5301111 Mon Sep 17 00:00:00 2001 From: metafates Date: Sun, 21 Aug 2022 18:33:01 +0400 Subject: [PATCH 02/51] refactor(tui): remove idle state, make error handling more consistent --- tui/bubble.go | 8 ++++++-- tui/keymap.go | 7 +------ tui/state.go | 3 +-- tui/update.go | 31 +++++++------------------------ tui/view.go | 6 ------ 5 files changed, 15 insertions(+), 40 deletions(-) diff --git a/tui/bubble.go b/tui/bubble.go index f2df9474..a57fad41 100644 --- a/tui/bubble.go +++ b/tui/bubble.go @@ -67,6 +67,12 @@ type statefulBubble struct { succededChapters []*source.Chapter } +func (b *statefulBubble) raiseError(err error) { + b.lastError = err + b.errorPlot = randomPlot() + b.newState(errorState) +} + func (b *statefulBubble) setState(s state) { b.state = s b.keymap.setState(s) @@ -80,7 +86,6 @@ func (b *statefulBubble) newState(s state) { // Transitioning to these states is not allowed (it makes no sense) if !lo.Contains([]state{ - idle, loadingState, readState, downloadDoneState, @@ -146,7 +151,6 @@ func (b *statefulBubble) stopLoading() tea.Cmd { func newBubble() *statefulBubble { keymap := newStatefulKeymap() bubble := statefulBubble{ - state: idle, statesHistory: util.Stack[state]{}, keymap: keymap, diff --git a/tui/keymap.go b/tui/keymap.go index 03e48038..3c3e552d 100644 --- a/tui/keymap.go +++ b/tui/keymap.go @@ -34,8 +34,6 @@ func newStatefulKeymap() *statefulKeymap { help := key.WithHelp return &statefulKeymap{ - state: idle, - quit: k( keys("q"), help("q", "quit"), @@ -131,8 +129,6 @@ func (k *statefulKeymap) help() ([]key.Binding, []key.Binding) { } switch k.state { - case idle: - return to2(h(k.forceQuit)) case scrapersInstallState: return to2(h(k.confirm, k.openURL)) case loadingState: @@ -158,8 +154,7 @@ func (k *statefulKeymap) help() ([]key.Binding, []key.Binding) { case errorState: return to2(h(k.back, k.quit)) default: - // unreachable - panic("unknown state") + return to2(h()) } } diff --git a/tui/state.go b/tui/state.go index 214b4227..e3a95cce 100644 --- a/tui/state.go +++ b/tui/state.go @@ -3,8 +3,7 @@ package tui type state int const ( - idle state = iota + 1 - scrapersInstallState + scrapersInstallState state = iota + 1 errorState loadingState historyState diff --git a/tui/update.go b/tui/update.go index c3b614c2..23b91823 100644 --- a/tui/update.go +++ b/tui/update.go @@ -23,8 +23,7 @@ func (b *statefulBubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case error: - b.errorPlot = randomPlot() - b.newState(errorState) + b.raiseError(msg) case tea.WindowSizeMsg: b.resize(msg.Width, msg.Height) case tea.KeyMsg: @@ -79,8 +78,6 @@ func (b *statefulBubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } switch b.state { - case idle: - return b.updateIdle(msg) case loadingState: return b.updateLoading(msg) case historyState: @@ -110,11 +107,6 @@ func (b *statefulBubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) { panic("unreachable") } -func (b *statefulBubble) updateIdle(_ tea.Msg) (tea.Model, tea.Cmd) { - panic("idle state must not be reached") - return b, nil -} - func (b *statefulBubble) updateScrapersInstall(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd @@ -256,9 +248,7 @@ func (b *statefulBubble) updateHistory(msg tea.Msg) (tea.Model, tea.Cmd) { chapter := b.historyC.SelectedItem().(*listItem).internal.(*history.SavedChapter) err := open.Run(chapter.URL) if err != nil { - b.lastError = err - b.errorPlot = randomPlot() - b.newState(errorState) + b.raiseError(err) } } case key.Matches(msg, b.keymap.remove): @@ -283,9 +273,8 @@ func (b *statefulBubble) updateHistory(msg tea.Msg) (tea.Model, tea.Cmd) { }) if !ok { - b.lastError = fmt.Errorf("provider %s not found", selected.SourceID) - b.errorPlot = randomPlot() - b.newState(errorState) + err := fmt.Errorf("provider %s not found", selected.SourceID) + b.raiseError(err) return b, nil } @@ -364,9 +353,7 @@ func (b *statefulBubble) updateMangas(msg tea.Msg) (tea.Model, tea.Cmd) { m, _ := b.mangasC.SelectedItem().(*listItem).internal.(*source.Manga) err := open.Start(m.URL) if err != nil { - b.lastError = err - b.errorPlot = randomPlot() - b.newState(errorState) + b.raiseError(err) } } case []*source.Chapter: @@ -405,9 +392,7 @@ func (b *statefulBubble) updateChapters(msg tea.Msg) (tea.Model, tea.Cmd) { chapter := b.chaptersC.SelectedItem().(*listItem).internal.(*source.Chapter) err := open.Start(chapter.URL) if err != nil { - b.errorPlot = randomPlot() - b.lastError = err - b.newState(errorState) + b.raiseError(err) } case key.Matches(msg, b.keymap.selectOne): if b.chaptersC.SelectedItem() == nil { @@ -546,9 +531,7 @@ func (b *statefulBubble) updateDownloadDone(msg tea.Msg) (tea.Model, tea.Cmd) { case key.Matches(msg, b.keymap.openFolder): err := open.Start(filepath.Dir(b.lastDownloadedChapterPath)) if err != nil { - b.errorPlot = randomPlot() - b.lastError = err - b.newState(errorState) + b.raiseError(err) } case key.Matches(msg, b.keymap.redownloadFailed): if len(b.failedChapters) == 0 { diff --git a/tui/view.go b/tui/view.go index 8b89b559..3cad4434 100644 --- a/tui/view.go +++ b/tui/view.go @@ -13,8 +13,6 @@ import ( func (b *statefulBubble) View() string { switch b.state { - case idle: - return b.viewIdle() case scrapersInstallState: return b.viewScrapersInstallState() case loadingState: @@ -44,10 +42,6 @@ func (b *statefulBubble) View() string { panic("unknown state") } -func (b *statefulBubble) viewIdle() string { - return "" -} - func (b *statefulBubble) viewLoading() string { return b.renderLines( true, From 46beadc8b12c8e06166fc00aac4d94dee61fbe56 Mon Sep 17 00:00:00 2001 From: metafates Date: Sun, 21 Aug 2022 18:37:15 +0400 Subject: [PATCH 03/51] refactor(tui): better help description --- tui/keymap.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tui/keymap.go b/tui/keymap.go index 3c3e552d..886c5f24 100644 --- a/tui/keymap.go +++ b/tui/keymap.go @@ -136,11 +136,11 @@ func (k *statefulKeymap) help() ([]key.Binding, []key.Binding) { case historyState: return to2(h(k.selectOne, k.remove, k.back, k.openURL)) case sourcesState: - return to2(h(k.selectOne)) + return to2(h(k.confirm)) case searchState: return to2(h(k.confirm, k.forceQuit)) case mangasState: - return to2(h(k.selectOne, k.back, k.openURL)) + return to2(h(k.confirm, k.back, k.openURL)) case chaptersState: return h(k.read, k.selectOne, k.selectAll, k.confirm, k.back), h(k.read, k.selectOne, k.selectAll, k.clearSelection, k.openURL, k.confirm, k.back) case confirmState: From 3e52a86cc103d0f4c5cccd79839bdd91fc461f97 Mon Sep 17 00:00:00 2001 From: metafates Date: Mon, 22 Aug 2022 10:35:18 +0400 Subject: [PATCH 04/51] feat(cmd): gen cmd added to generate lua source --- .goreleaser.yaml | 59 +++++++++++++++++++++++++--- cmd/gen.go | 71 ++++++++++++++++++++++++++++++++++ constant/constant.go | 33 ++++++++++++++++ go.mod | 9 +++-- go.sum | 24 ++++-------- provider/custom/chapters.go | 9 +++-- provider/custom/definitions.go | 12 ++---- provider/custom/pages.go | 7 ++-- provider/custom/search.go | 9 +++-- provider/custom/translator.go | 14 ++++++- 10 files changed, 201 insertions(+), 46 deletions(-) create mode 100644 cmd/gen.go diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 438d768c..33862bd2 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -2,6 +2,7 @@ before: hooks: - go mod tidy - go generate ./... + builds: - env: - CGO_ENABLED=0 @@ -9,13 +10,30 @@ builds: - linux - windows - darwin + goarch: + - "386" + - amd64 + - arm + - arm64 + flags: + - -trimpath + archives: - - replacements: + - + replacements: darwin: Darwin linux: Linux windows: Windows 386: i386 amd64: x86_64 + format_overrides: + - + goos: windows + format: zip + files: + - completions/* + - README.md + - LICENSE checksum: name_template: 'checksums.txt' @@ -43,8 +61,10 @@ changelog: order: 9999 filters: exclude: - - '^test:' + - '^test' - '^chore' + - '^refactor' + - '^build' - 'merge conflict' - Merge pull request - Merge remote-tracking branch @@ -57,7 +77,7 @@ dockers: goarch: amd64 image_templates: - "metafates/mangal:latest" - skip_push: false + skip_push: true use: docker brews: @@ -78,13 +98,16 @@ brews: homepage: "https://github.com/metafates/mangal" description: "The ultimate CLI manga downloader!" license: "MIT" - skip_upload: false + skip_upload: true test: | system "#{bin}/mangal -v" install: |- bin.install "mangal" + bash_completion.install "completions/mangal.bash" => "mangal" + zsh_completion.install "completions/mangal.zsh" => "_mangal" + fish_completion.install "completions/mangal.fish" scoop: bucket: @@ -103,7 +126,7 @@ scoop: homepage: "https://github.com/metafates/mangal" description: "The ultimate CLI manga downloader!" license: MIT - skip_upload: false + skip_upload: true release: @@ -111,8 +134,14 @@ release: owner: metafates name: mangal - draft: false + draft: true name_template: "{{.ProjectName}} v{{.Version}}" + footer: | + **Full Changelog**: https://github.com/metafates/mangal/compare/{{ .PreviousTag }}...{{ .Tag }} + + --- + + Bugs? Suggestions? [Open an issue](https://github.com/metafates/mangal/issues/new/choose) nfpms: - @@ -134,3 +163,21 @@ nfpms: lintian_overrides: - statically-linked-binary - changelog-file-missing-in-native-package + + contents: + - src: ./completions/mangal.bash + dst: /usr/share/bash-completion/completions/mangal + file_info: + mode: 0644 + - src: ./completions/mangal.fish + dst: /usr/share/fish/completions/mangal.fish + file_info: + mode: 0644 + - src: ./completions/mangal.zsh + dst: /usr/share/zsh/vendor-completions/_mangal + file_info: + mode: 0644 + - src: ./LICENSE + dst: /usr/share/doc/mangal/copyright + file_info: + mode: 0644 diff --git a/cmd/gen.go b/cmd/gen.go new file mode 100644 index 00000000..6abe4490 --- /dev/null +++ b/cmd/gen.go @@ -0,0 +1,71 @@ +package cmd + +import ( + "github.com/metafates/mangal/constant" + "github.com/metafates/mangal/filesystem" + "github.com/metafates/mangal/util" + "github.com/metafates/mangal/where" + "github.com/samber/lo" + "github.com/spf13/afero" + "github.com/spf13/cobra" + "os" + "path/filepath" + "text/template" +) + +func init() { + rootCmd.AddCommand(genCmd) + + genCmd.Flags().StringP("name", "n", "", "name of the source") + genCmd.Flags().StringP("url", "u", "", "url of the website") + + lo.Must0(genCmd.MarkFlagRequired("name")) + lo.Must0(genCmd.MarkFlagRequired("url")) +} + +var genCmd = &cobra.Command{ + Use: "gen", + Short: "Generate a new lua source", + Long: `Generate a new lua source.`, + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SetOut(os.Stdout) + + s := struct { + Name string + URL string + SearchMangaFn string + MangaChaptersFn string + ChapterPagesFn string + }{ + Name: lo.Must(cmd.Flags().GetString("name")), + URL: lo.Must(cmd.Flags().GetString("url")), + SearchMangaFn: constant.SearchMangaFn, + MangaChaptersFn: constant.MangaChaptersFn, + ChapterPagesFn: constant.ChapterPagesFn, + } + + tmpl, err := template.New("source").Parse(constant.SourceTemplate) + + if err != nil { + return err + } + + target := filepath.Join(where.Sources(), util.SanitizeFilename(s.Name)+".lua") + f, err := filesystem.Get().Create(target) + if err != nil { + return err + } + + defer func(f afero.File) { + _ = f.Close() + }(f) + + err = tmpl.Execute(f, s) + if err != nil { + return err + } + + cmd.Println(target) + return nil + }, +} diff --git a/constant/constant.go b/constant/constant.go index bd828988..943657e0 100644 --- a/constant/constant.go +++ b/constant/constant.go @@ -19,3 +19,36 @@ const AssciiArtLogo = ` \/ \/\__,_|_| |_|\__, |\__,_|_| |____/ |___/ ` + +const ( + SearchMangaFn = "SearchManga" + MangaChaptersFn = "MangaChapters" + ChapterPagesFn = "ChapterPages" +) + +const SourceTemplate = `-- {{ .Name }} +-- {{ .URL }} + +-- Searches for manga with given query +-- Must return a table of tables with the following fields: +-- name: name of the manga +-- url: url of the manga +function {{ .SearchMangaFn }}(query) +end + + +-- Gets the list of all manga chapters +-- Returns a table of tables with the following fields: +-- name: name of the chapter +-- url: url of the chapter +function {{ .MangaChaptersFn }}(manga_url) +end + + +-- Gets the list of all pages of a chapter +-- Returns a table of tables with the following fields: +-- url: url of the page +-- index: index of the page +function {{ .ChapterPagesFn }}(chapter_url) +end +` diff --git a/go.mod b/go.mod index 18392782..2199887a 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,10 @@ require ( github.com/AlecAivazis/survey/v2 v2.3.5 github.com/PuerkitoBio/goquery v1.8.0 github.com/charmbracelet/bubbles v0.13.0 - github.com/charmbracelet/bubbletea v0.22.0 + github.com/charmbracelet/bubbletea v0.22.1 github.com/charmbracelet/lipgloss v0.5.0 github.com/darylhjd/mangodex v0.0.0-20211231093527-e4a91c518fa0 + github.com/dustin/go-humanize v1.0.0 github.com/go-rod/rod v0.109.1 github.com/gocolly/colly v1.2.0 github.com/ivanpirog/coloredcobra v1.0.1 @@ -35,14 +36,13 @@ require ( github.com/antchfx/xmlquery v1.3.12 // indirect github.com/antchfx/xpath v1.2.1 // indirect github.com/atotto/clipboard v0.1.4 // indirect - github.com/aws/aws-sdk-go v1.44.78 // indirect + github.com/aws/aws-sdk-go v1.44.81 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cbroglie/mustache v1.4.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/charmbracelet/harmonica v0.2.0 // indirect github.com/cheggaaa/pb/v3 v3.1.0 // indirect github.com/containerd/console v1.0.3 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect github.com/fatih/color v1.13.0 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect @@ -63,6 +63,7 @@ require ( github.com/magiconair/properties v1.8.6 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-localereader v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect github.com/mattn/go-sqlite3 v1.14.15 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect @@ -96,7 +97,7 @@ require ( github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7 // indirect golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 // indirect golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect - golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 // indirect + golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect diff --git a/go.sum b/go.sum index 8351518b..be08a00a 100644 --- a/go.sum +++ b/go.sum @@ -69,10 +69,8 @@ github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdK github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aws/aws-sdk-go v1.32.1/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.44.76 h1:5e8yGO/XeNYKckOjpBKUd5wStf0So3CrQIiOMCVLpOI= -github.com/aws/aws-sdk-go v1.44.76/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.44.78 h1:B/V28YXFLmxjMQqJeyCt7NDRIJdep0sJixIAeee2BF0= -github.com/aws/aws-sdk-go v1.44.78/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws/aws-sdk-go v1.44.81 h1:C8oBZ+a+ka0qk3Q24MohQIFq0tkbO8IAu5tfpAMKVWE= +github.com/aws/aws-sdk-go v1.44.81/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -87,8 +85,8 @@ github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/charmbracelet/bubbles v0.13.0 h1:zP/ROH3wJEBqZWKIsD50ZKKlx3ydLInq3LdD/Nrlb8w= github.com/charmbracelet/bubbles v0.13.0/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc= github.com/charmbracelet/bubbletea v0.21.0/go.mod h1:GgmJMec61d08zXsOhqRC/AiOx4K4pmz+VIcRIm1FKr4= -github.com/charmbracelet/bubbletea v0.22.0 h1:E1BTNSE3iIrq0G0X6TjGAmrQ32cGCbFDPcIuImikrUc= -github.com/charmbracelet/bubbletea v0.22.0/go.mod h1:aoVIwlNlr5wbCB26KhxfrqAn0bMp4YpJcoOelbxApjs= +github.com/charmbracelet/bubbletea v0.22.1 h1:z66q0LWdJNOWEH9zadiAIXp2GN1AWrwNXU8obVY9X24= +github.com/charmbracelet/bubbletea v0.22.1/go.mod h1:8/7hVvbPN6ZZPkczLiB8YpLkLJ0n7DMho5Wvfd2X1C0= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8= @@ -289,14 +287,14 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= -github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw= -github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= @@ -319,7 +317,6 @@ github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBc github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA= github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= github.com/muesli/cancelreader v0.2.0/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= -github.com/muesli/cancelreader v0.2.1/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ= @@ -335,8 +332,6 @@ github.com/pdfcpu/pdfcpu v0.3.13 h1:VFon2Yo1PJt+sA57vPAeXWGLSZ7Ux3Jl4h02M0+s3dg= github.com/pdfcpu/pdfcpu v0.3.13/go.mod h1:UJc5xsXg0fpmjp1zOPdyYcAQArc/Zf3V0nv5URe+9fg= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw= -github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= github.com/pelletier/go-toml/v2 v2.0.3 h1:h9JoA60e1dVEOpp0PFwJSmt1Htu057NUq9/bUwaO61s= github.com/pelletier/go-toml/v2 v2.0.3/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -421,8 +416,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs= @@ -624,10 +617,9 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 h1:fqTvyMIIj+HRzMmnzr9NtpHP6uVpvB5fkHcgPDC4nu8= -golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 h1:Sx/u41w+OwrInGdEckYmEuU5gHoGSL4QbDz3S9s6j4U= +golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= diff --git a/provider/custom/chapters.go b/provider/custom/chapters.go index 472d56cf..549d4194 100644 --- a/provider/custom/chapters.go +++ b/provider/custom/chapters.go @@ -1,6 +1,7 @@ package custom import ( + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/source" lua "github.com/yuin/gopher-lua" "strconv" @@ -11,7 +12,7 @@ func (s *luaSource) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { return cached, nil } - _, err := s.call(mangaChaptersFn, lua.LTTable, lua.LString(manga.URL)) + _, err := s.call(constant.MangaChaptersFn, lua.LTTable, lua.LString(manga.URL)) if err != nil { return nil, err @@ -22,16 +23,16 @@ func (s *luaSource) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { table.ForEach(func(k lua.LValue, v lua.LValue) { if k.Type() != lua.LTNumber { - s.state.RaiseError(mangaChaptersFn + " was expected to return a table with numbers as keys, got " + k.Type().String() + " as a key") + s.state.RaiseError(constant.MangaChaptersFn + " was expected to return a table with numbers as keys, got " + k.Type().String() + " as a key") } if v.Type() != lua.LTTable { - s.state.RaiseError(mangaChaptersFn + " was expected to return a table with tables as values, got " + v.Type().String() + " as a value") + s.state.RaiseError(constant.MangaChaptersFn + " was expected to return a table with tables as values, got " + v.Type().String() + " as a value") } index, err := strconv.ParseUint(k.String(), 10, 16) if err != nil { - s.state.RaiseError(mangaChaptersFn + " was expected to return a table with unsigned integers as keys. " + err.Error()) + s.state.RaiseError(constant.MangaChaptersFn + " was expected to return a table with unsigned integers as keys. " + err.Error()) } chapter, err := chapterFromTable(v.(*lua.LTable), manga, uint16(index)) diff --git a/provider/custom/definitions.go b/provider/custom/definitions.go index 58aaa581..88fe1a13 100644 --- a/provider/custom/definitions.go +++ b/provider/custom/definitions.go @@ -1,13 +1,9 @@ package custom -const ( - searchMangaFn = "SearchManga" - mangaChaptersFn = "MangaChapters" - chapterPagesFn = "ChapterPages" -) +import "github.com/metafates/mangal/constant" var mustHave = []string{ - searchMangaFn, - mangaChaptersFn, - chapterPagesFn, + constant.SearchMangaFn, + constant.MangaChaptersFn, + constant.ChapterPagesFn, } diff --git a/provider/custom/pages.go b/provider/custom/pages.go index 603ad4b0..23054bde 100644 --- a/provider/custom/pages.go +++ b/provider/custom/pages.go @@ -1,6 +1,7 @@ package custom import ( + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/source" lua "github.com/yuin/gopher-lua" ) @@ -10,7 +11,7 @@ func (s *luaSource) PagesOf(chapter *source.Chapter) ([]*source.Page, error) { return cached, nil } - _, err := s.call(chapterPagesFn, lua.LTTable, lua.LString(chapter.URL)) + _, err := s.call(constant.ChapterPagesFn, lua.LTTable, lua.LString(chapter.URL)) if err != nil { return nil, err @@ -21,11 +22,11 @@ func (s *luaSource) PagesOf(chapter *source.Chapter) ([]*source.Page, error) { table.ForEach(func(k lua.LValue, v lua.LValue) { if k.Type() != lua.LTNumber { - s.state.RaiseError(chapterPagesFn + " was expected to return a table with numbers as keys, got " + k.Type().String() + " as a key") + s.state.RaiseError(constant.ChapterPagesFn + " was expected to return a table with numbers as keys, got " + k.Type().String() + " as a key") } if v.Type() != lua.LTTable { - s.state.RaiseError(chapterPagesFn + " was expected to return a table with tables as values, got " + v.Type().String() + " as a value") + s.state.RaiseError(constant.ChapterPagesFn + " was expected to return a table with tables as values, got " + v.Type().String() + " as a value") } page, err := pageFromTable(v.(*lua.LTable), chapter) diff --git a/provider/custom/search.go b/provider/custom/search.go index b9fc5b04..8e7fb5a0 100644 --- a/provider/custom/search.go +++ b/provider/custom/search.go @@ -1,6 +1,7 @@ package custom import ( + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/source" lua "github.com/yuin/gopher-lua" "strconv" @@ -11,7 +12,7 @@ func (s *luaSource) Search(query string) ([]*source.Manga, error) { return cached, nil } - _, err := s.call(searchMangaFn, lua.LTTable, lua.LString(query)) + _, err := s.call(constant.SearchMangaFn, lua.LTTable, lua.LString(query)) if err != nil { return nil, err @@ -22,16 +23,16 @@ func (s *luaSource) Search(query string) ([]*source.Manga, error) { table.ForEach(func(k lua.LValue, v lua.LValue) { if k.Type() != lua.LTNumber { - s.state.RaiseError(searchMangaFn + " was expected to return a table with numbers as keys, got " + k.Type().String() + " as a key") + s.state.RaiseError(constant.SearchMangaFn + " was expected to return a table with numbers as keys, got " + k.Type().String() + " as a key") } if v.Type() != lua.LTTable { - s.state.RaiseError(searchMangaFn + " was expected to return a table with tables as values, got " + v.Type().String() + " as a value") + s.state.RaiseError(constant.SearchMangaFn + " was expected to return a table with tables as values, got " + v.Type().String() + " as a value") } index, err := strconv.ParseUint(k.String(), 10, 16) if err != nil { - s.state.RaiseError(searchMangaFn + " was expected to return a table with unsigned integers as keys. " + err.Error()) + s.state.RaiseError(constant.SearchMangaFn + " was expected to return a table with unsigned integers as keys. " + err.Error()) } manga, err := mangaFromTable(v.(*lua.LTable), uint16(index)) diff --git a/provider/custom/translator.go b/provider/custom/translator.go index bececb93..e78977c1 100644 --- a/provider/custom/translator.go +++ b/provider/custom/translator.go @@ -71,11 +71,23 @@ func pageFromTable(table *lua.LTable, chapter *source.Chapter) (*source.Page, er return nil, errors.New("index must be an unsigned 16 bit integer") } + extension := table.RawGetString("extension") + + if extension.Type() != lua.LTNil && extension.Type() != lua.LTString { + return nil, errors.New("type of field \"extension\" should be string") + } + + if extension.String() == "" { + extension = lua.LString(".jpg") + } else if !strings.HasPrefix(extension.String(), ".") { + return nil, errors.New("extension must start with a dot") + } + page := &source.Page{ URL: strings.TrimSpace(url.String()), Index: uint16(num), Chapter: chapter, - Extension: ".jpg", + Extension: extension.String(), } chapter.Pages = append(chapter.Pages, page) From 27d27c9919ecfdb08ff94837043bb6c22cbe6c8c Mon Sep 17 00:00:00 2001 From: metafates Date: Mon, 22 Aug 2022 11:35:02 +0400 Subject: [PATCH 05/51] refactor(cmd): improve gen command --- cmd/gen.go | 22 +++++++++++++++++++++- config/config.go | 3 +++ config/fields.go | 4 ++++ constant/constant.go | 43 ++++++++++++++++++++++++++----------------- 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/cmd/gen.go b/cmd/gen.go index 6abe4490..1a138e27 100644 --- a/cmd/gen.go +++ b/cmd/gen.go @@ -1,6 +1,7 @@ package cmd import ( + "github.com/metafates/mangal/config" "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/util" @@ -8,8 +9,11 @@ import ( "github.com/samber/lo" "github.com/spf13/afero" "github.com/spf13/cobra" + "github.com/spf13/viper" "os" + "os/user" "path/filepath" + "strings" "text/template" ) @@ -30,21 +34,37 @@ var genCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { cmd.SetOut(os.Stdout) + author := viper.GetString(config.GenAuthor) + if author == "" { + usr, err := user.Current() + if err == nil { + author = usr.Username + } else { + author = "Anonymous" + } + } + s := struct { Name string URL string SearchMangaFn string MangaChaptersFn string ChapterPagesFn string + Author string }{ Name: lo.Must(cmd.Flags().GetString("name")), URL: lo.Must(cmd.Flags().GetString("url")), SearchMangaFn: constant.SearchMangaFn, MangaChaptersFn: constant.MangaChaptersFn, ChapterPagesFn: constant.ChapterPagesFn, + Author: author, + } + + funcMap := template.FuncMap{ + "repeat": strings.Repeat, } - tmpl, err := template.New("source").Parse(constant.SourceTemplate) + tmpl, err := template.New("source").Funcs(funcMap).Parse(constant.SourceTemplate) if err != nil { return err diff --git a/config/config.go b/config/config.go index d99defd7..5c77a95d 100644 --- a/config/config.go +++ b/config/config.go @@ -104,6 +104,9 @@ func setDefaults() { InstallerRepo: "mangal-scrapers", InstallerBranch: "main", + // Gen + GenAuthor: "", + // Logs LogsWrite: false, LogsLevel: "info", diff --git a/config/fields.go b/config/fields.go index cb446699..50281423 100644 --- a/config/fields.go +++ b/config/fields.go @@ -54,6 +54,10 @@ const ( InstallerBranch = "installer.branch" ) +const ( + GenAuthor = "gen.author" +) + const ( LogsWrite = "logs.write" LogsLevel = "logs.level" diff --git a/constant/constant.go b/constant/constant.go index 943657e0..4c59f5c1 100644 --- a/constant/constant.go +++ b/constant/constant.go @@ -26,29 +26,38 @@ const ( ChapterPagesFn = "ChapterPages" ) -const SourceTemplate = `-- {{ .Name }} --- {{ .URL }} +const SourceTemplate = `{{ repeat "-" (len .URL) }}--- +-- {{ .Name }} +-- {{ .URL }} +-- +-- @author {{ .Author }} +-- @license MIT +{{ repeat "-" (len .URL) }}--- --- Searches for manga with given query --- Must return a table of tables with the following fields: --- name: name of the manga --- url: url of the manga + +--- IMPORTS --- +-- ... + + +--- Searches for manga with given query. +-- @param query Query to search for +-- @return Table of tables with the following fields: name, url function {{ .SearchMangaFn }}(query) end --- Gets the list of all manga chapters --- Returns a table of tables with the following fields: --- name: name of the chapter --- url: url of the chapter -function {{ .MangaChaptersFn }}(manga_url) +--- Gets the list of all manga chapters. +-- @param mangaURL URL of the manga +-- @return Table of tables with the following fields: name, url +function {{ .MangaChaptersFn }}(mangaURL) end --- Gets the list of all pages of a chapter --- Returns a table of tables with the following fields: --- url: url of the page --- index: index of the page -function {{ .ChapterPagesFn }}(chapter_url) +--- Gets the list of all pages of a chapter. +-- @param chapterURL URL of the chapter +-- @return Table of tables with the following fields: url, index +function {{ .ChapterPagesFn }}(chapterURL) end -` + + +-- ex: ts=4 sw=4 et filetype=lua` From 533ec7d4f0c23c9892ac41f867eed49c1d810d2a Mon Sep 17 00:00:00 2001 From: metafates Date: Mon, 22 Aug 2022 11:37:27 +0400 Subject: [PATCH 06/51] refactor(cmd): return empty tables by default for gen cmd --- constant/constant.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/constant/constant.go b/constant/constant.go index 4c59f5c1..78bade62 100644 --- a/constant/constant.go +++ b/constant/constant.go @@ -43,6 +43,7 @@ const SourceTemplate = `{{ repeat "-" (len .URL) }}--- -- @param query Query to search for -- @return Table of tables with the following fields: name, url function {{ .SearchMangaFn }}(query) + return {} end @@ -50,6 +51,7 @@ end -- @param mangaURL URL of the manga -- @return Table of tables with the following fields: name, url function {{ .MangaChaptersFn }}(mangaURL) + return {} end @@ -57,6 +59,7 @@ end -- @param chapterURL URL of the chapter -- @return Table of tables with the following fields: url, index function {{ .ChapterPagesFn }}(chapterURL) + return {} end From 09175cd73df2d132e1c98830ae86e94a7379dd45 Mon Sep 17 00:00:00 2001 From: metafates Date: Mon, 22 Aug 2022 12:45:56 +0400 Subject: [PATCH 07/51] docs(readme): mention `gen` cmd --- README.md | 24 +++++++++++++++++------- cmd/gen.go | 7 +++++++ constant/constant.go | 9 ++++----- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d67d6a57..3fa18357 100644 --- a/README.md +++ b/README.md @@ -249,6 +249,11 @@ user = 'metafates' branch = 'main' +[gen] +# Name of author for gen command. +# Will use OS username if empty +author = '' + [logs] # write logs? @@ -272,13 +277,18 @@ For scraper examples, check the [mangal-scrapers repository](https://github.com/ ### Creating a custom scraper -1. Create a new lua file in the `mangal where --sources` folder -2. Filename will be used as a source name -3. Your script __must__ contain __3__ essential functions - - `SearchManga(query)` - must return a table of tables each having 2 fields `name` and `url` - - `MangaChapters(mangalUrl)` - must return a table of tables each having 2 fields `name` and `url` _(again)_ - - `ChapterPages(chapterUrl)` - must return a table of tables each having 2 fields `index` _(for ordering)_ and `url` _(to download image)_ -4. __That's it!__ You can test it by running `mangal run ...` where `...` is a filename +This command will create `example.lua` file in the `mangal where --sources` directory. + + mangal gen --name example --url https://example.com + +Open the file and edit it as you wish. +Take a look at the comments for more information. +See [mangal-scrapers repository](https://github.com/metafates/mangal-scrapers) for examples. + +You can test it by running `mangal run ` + +It should automatically appear in the list of available scrapers. + > New to Lua? [Quick start guide](https://learnxinyminutes.com/docs/lua/) diff --git a/cmd/gen.go b/cmd/gen.go index 1a138e27..69acbacc 100644 --- a/cmd/gen.go +++ b/cmd/gen.go @@ -62,6 +62,13 @@ var genCmd = &cobra.Command{ funcMap := template.FuncMap{ "repeat": strings.Repeat, + "max": func(a, b int) int { + if a > b { + return a + } + + return b + }, } tmpl, err := template.New("source").Funcs(funcMap).Parse(constant.SourceTemplate) diff --git a/constant/constant.go b/constant/constant.go index 78bade62..422d0c96 100644 --- a/constant/constant.go +++ b/constant/constant.go @@ -26,13 +26,12 @@ const ( ChapterPagesFn = "ChapterPages" ) -const SourceTemplate = `{{ repeat "-" (len .URL) }}--- --- {{ .Name }} --- {{ .URL }} --- +const SourceTemplate = `{{ repeat "-" (max (len .URL) (len .Name)) }}{{ repeat "-" 12 }} +-- @name {{ .Name }} +-- @url {{ .URL }} -- @author {{ .Author }} -- @license MIT -{{ repeat "-" (len .URL) }}--- +{{ repeat "-" (max (len .URL) (len .Name)) }}{{ repeat "-" 12 }} --- IMPORTS --- From 7a24adb7ef5126db905cbd4b2ee88675ad24c769 Mon Sep 17 00:00:00 2001 From: metafates Date: Mon, 22 Aug 2022 12:55:33 +0400 Subject: [PATCH 08/51] refactor(cmd): add `variables` section to `gen` cmd --- constant/constant.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/constant/constant.go b/constant/constant.go index 422d0c96..7f70f25e 100644 --- a/constant/constant.go +++ b/constant/constant.go @@ -38,6 +38,10 @@ const SourceTemplate = `{{ repeat "-" (max (len .URL) (len .Name)) }}{{ repeat " -- ... +--- VARIABLES --- +-- ... + + --- Searches for manga with given query. -- @param query Query to search for -- @return Table of tables with the following fields: name, url From fb0232cf1a656a8c53aad8f6daa2cd60f2d7684c Mon Sep 17 00:00:00 2001 From: metafates Date: Mon, 22 Aug 2022 13:16:36 +0400 Subject: [PATCH 09/51] fix: make page extension field optional --- provider/custom/translator.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/provider/custom/translator.go b/provider/custom/translator.go index e78977c1..73bb01fc 100644 --- a/provider/custom/translator.go +++ b/provider/custom/translator.go @@ -73,12 +73,10 @@ func pageFromTable(table *lua.LTable, chapter *source.Chapter) (*source.Page, er extension := table.RawGetString("extension") - if extension.Type() != lua.LTNil && extension.Type() != lua.LTString { - return nil, errors.New("type of field \"extension\" should be string") - } - - if extension.String() == "" { + if extension.Type() == lua.LTNil { extension = lua.LString(".jpg") + } else if extension.Type() != lua.LTString { + return nil, errors.New("type of field \"extension\" should be string") } else if !strings.HasPrefix(extension.String(), ".") { return nil, errors.New("extension must start with a dot") } From f45874960961c592dbf55e91795c3b9da742ab4f Mon Sep 17 00:00:00 2001 From: metafates Date: Mon, 22 Aug 2022 13:24:50 +0400 Subject: [PATCH 10/51] build: bump version --- constant/constant.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constant/constant.go b/constant/constant.go index 7f70f25e..1b6d05c7 100644 --- a/constant/constant.go +++ b/constant/constant.go @@ -2,7 +2,7 @@ package constant const ( Mangal = "mangal" - Version = "3.4.1" + Version = "3.4.2" UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" ) From 8a8aa0da4055fa3d74293350ec92400a4dc07076 Mon Sep 17 00:00:00 2001 From: metafates Date: Tue, 23 Aug 2022 13:25:50 +0400 Subject: [PATCH 11/51] refactor: move config fields to the constants module --- cmd/gen.go | 15 ++++--- cmd/integration.go | 26 ++++++------ cmd/root.go | 9 ++-- config/config.go | 58 +++++++++++++------------- config/env.go | 34 +++++++++++++++ config/fields.go => constant/config.go | 33 +-------------- constant/constant.go | 26 +++++++++--- converter/cbz/cbz.go | 29 +------------ converter/pdf/pdf.go | 30 ++----------- converter/plain/plain.go | 22 ++-------- converter/zip/zip.go | 29 +------------ downloader/download.go | 12 +++--- downloader/read.go | 24 +++++------ history/history.go | 4 +- icon/icon.go | 4 +- inline/inline.go | 4 +- installer/collector.go | 8 ++-- integration/anilist/anilist.go | 8 ++-- log/log.go | 6 +-- mini/states.go | 8 ++-- provider/mangadex/chapters.go | 8 ++-- provider/mangadex/search.go | 6 +-- source/chapter.go | 6 +-- tui/handlers.go | 4 +- tui/init.go | 4 +- where/where.go | 27 ++++++++++++ 26 files changed, 200 insertions(+), 244 deletions(-) create mode 100644 config/env.go rename config/fields.go => constant/config.go (77%) diff --git a/cmd/gen.go b/cmd/gen.go index 69acbacc..3faa6fd5 100644 --- a/cmd/gen.go +++ b/cmd/gen.go @@ -1,7 +1,6 @@ package cmd import ( - "github.com/metafates/mangal/config" "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/util" @@ -34,7 +33,7 @@ var genCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { cmd.SetOut(os.Stdout) - author := viper.GetString(config.GenAuthor) + author := viper.GetString(constant.GenAuthor) if author == "" { usr, err := user.Current() if err == nil { @@ -62,12 +61,16 @@ var genCmd = &cobra.Command{ funcMap := template.FuncMap{ "repeat": strings.Repeat, - "max": func(a, b int) int { - if a > b { - return a + "plus": func(a, b int) int { return a + b }, + "max": func(nums ...int) int { + max := nums[0] + for _, num := range nums { + if num > max { + max = num + } } - return b + return max }, } diff --git a/cmd/integration.go b/cmd/integration.go index cf835cd9..8ef5b92b 100644 --- a/cmd/integration.go +++ b/cmd/integration.go @@ -3,7 +3,7 @@ package cmd import ( "fmt" "github.com/AlecAivazis/survey/v2" - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/integration/anilist" "github.com/metafates/mangal/log" "github.com/samber/lo" @@ -30,15 +30,15 @@ var integrationAnilistCmd = &cobra.Command{ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more information`, RunE: func(cmd *cobra.Command, args []string) error { if lo.Must(cmd.Flags().GetBool("disable")) { - viper.Set(config.AnilistEnable, false) - viper.Set(config.AnilistCode, "") - viper.Set(config.AnilistSecret, "") - viper.Set(config.AnilistID, "") + viper.Set(constant.AnilistEnable, false) + viper.Set(constant.AnilistCode, "") + viper.Set(constant.AnilistSecret, "") + viper.Set(constant.AnilistID, "") log.Info("Anilist integration disabled") return viper.WriteConfig() } - if !viper.GetBool(config.AnilistEnable) { + if !viper.GetBool(constant.AnilistEnable) { confirm := survey.Confirm{ Message: "Anilist is disabled. Enable?", Default: false, @@ -54,7 +54,7 @@ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more inform return nil } - viper.Set(config.AnilistEnable, response) + viper.Set(constant.AnilistEnable, response) err = viper.WriteConfig() if err != nil { switch err.(type) { @@ -70,7 +70,7 @@ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more inform } } - if viper.GetString(config.AnilistID) == "" { + if viper.GetString(constant.AnilistID) == "" { input := survey.Input{ Message: "Anilsit client ID is not set. Please enter it:", Help: "", @@ -85,7 +85,7 @@ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more inform return nil } - viper.Set(config.AnilistID, response) + viper.Set(constant.AnilistID, response) err = viper.WriteConfig() if err != nil { log.Error(err) @@ -93,7 +93,7 @@ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more inform } } - if viper.GetString(config.AnilistSecret) == "" { + if viper.GetString(constant.AnilistSecret) == "" { input := survey.Input{ Message: "Anilsit client secret is not set. Please enter it:", Help: "", @@ -108,7 +108,7 @@ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more inform return nil } - viper.Set(config.AnilistSecret, response) + viper.Set(constant.AnilistSecret, response) err = viper.WriteConfig() if err != nil { log.Error(err) @@ -116,7 +116,7 @@ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more inform } } - if viper.GetString(config.AnilistCode) == "" { + if viper.GetString(constant.AnilistCode) == "" { fmt.Println(anilist.New().AuthURL()) input := survey.Input{ Message: "Anilsit code is not set. Please copy it from the link above and paste in here:", @@ -132,7 +132,7 @@ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more inform return nil } - viper.Set(config.AnilistCode, response) + viper.Set(constant.AnilistCode, response) err = viper.WriteConfig() if err != nil { log.Error(err) diff --git a/cmd/root.go b/cmd/root.go index c4f7ae0c..1fd0fcd3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,7 +3,6 @@ package cmd import ( "fmt" cc "github.com/ivanpirog/coloredcobra" - "github.com/metafates/mangal/config" "github.com/metafates/mangal/constant" "github.com/metafates/mangal/converter" "github.com/metafates/mangal/icon" @@ -21,16 +20,16 @@ func init() { lo.Must0(rootCmd.RegisterFlagCompletionFunc("format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return converter.Available(), cobra.ShellCompDirectiveDefault })) - lo.Must0(viper.BindPFlag(config.FormatsUse, rootCmd.PersistentFlags().Lookup("format"))) + lo.Must0(viper.BindPFlag(constant.FormatsUse, rootCmd.PersistentFlags().Lookup("format"))) rootCmd.PersistentFlags().StringP("icons", "I", "", "icons variant") lo.Must0(rootCmd.RegisterFlagCompletionFunc("icons", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return icon.AvailableVariants(), cobra.ShellCompDirectiveDefault })) - lo.Must0(viper.BindPFlag(config.IconsVariant, rootCmd.PersistentFlags().Lookup("icons"))) + lo.Must0(viper.BindPFlag(constant.IconsVariant, rootCmd.PersistentFlags().Lookup("icons"))) rootCmd.PersistentFlags().BoolP("history", "H", true, "write history of the read chapters") - lo.Must0(viper.BindPFlag(config.HistorySaveOnRead, rootCmd.PersistentFlags().Lookup("history"))) + lo.Must0(viper.BindPFlag(constant.HistorySaveOnRead, rootCmd.PersistentFlags().Lookup("history"))) rootCmd.PersistentFlags().StringP("source", "S", "", "source") lo.Must0(rootCmd.RegisterFlagCompletionFunc("source", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { @@ -39,7 +38,7 @@ func init() { return d, cobra.ShellCompDirectiveDefault })) - lo.Must0(viper.BindPFlag(config.DownloaderDefaultSource, rootCmd.PersistentFlags().Lookup("source"))) + lo.Must0(viper.BindPFlag(constant.DownloaderDefaultSource, rootCmd.PersistentFlags().Lookup("source"))) rootCmd.Flags().BoolP("continue", "c", false, "continue reading") diff --git a/config/config.go b/config/config.go index 5c77a95d..b47dbdf4 100644 --- a/config/config.go +++ b/config/config.go @@ -66,53 +66,53 @@ func setDefaults() { fields := map[string]any{ // Downloader - DownloaderPath: ".", - DownloaderChapterNameTemplate: "[{padded-index}] {chapter}", - DownloaderAsync: true, - DownloaderCreateMangaDir: true, - DownloaderDefaultSource: "", - DownloaderStopOnError: false, + constant.DownloaderPath: ".", + constant.DownloaderChapterNameTemplate: "[{padded-index}] {chapter}", + constant.DownloaderAsync: true, + constant.DownloaderCreateMangaDir: true, + constant.DownloaderDefaultSource: "", + constant.DownloaderStopOnError: false, // Formats - FormatsUse: "pdf", - FormatsSkipUnsupportedImages: true, + constant.FormatsUse: "pdf", + constant.FormatsSkipUnsupportedImages: true, // Mini-mode - MiniSearchLimit: 20, + constant.MiniSearchLimit: 20, // Icons - IconsVariant: "plain", + constant.IconsVariant: "plain", // Reader - ReaderPDF: "", - ReaderCBZ: "", - ReaderZIP: "", - RaderPlain: "", - ReaderReadInBrowser: false, + constant.ReaderPDF: "", + constant.ReaderCBZ: "", + constant.ReaderZIP: "", + constant.RaderPlain: "", + constant.ReaderReadInBrowser: false, // History - HistorySaveOnRead: true, - HistorySaveOnDownload: false, + constant.HistorySaveOnRead: true, + constant.HistorySaveOnDownload: false, // Mangadex - MangadexLanguage: "en", - MangadexNSFW: false, - MangadexShowUnavailableChapters: false, + constant.MangadexLanguage: "en", + constant.MangadexNSFW: false, + constant.MangadexShowUnavailableChapters: false, // Installer - InstallerUser: "metafates", - InstallerRepo: "mangal-scrapers", - InstallerBranch: "main", + constant.InstallerUser: "metafates", + constant.InstallerRepo: "mangal-scrapers", + constant.InstallerBranch: "main", // Gen - GenAuthor: "", + constant.GenAuthor: "", // Logs - LogsWrite: false, - LogsLevel: "info", + constant.LogsWrite: false, + constant.LogsLevel: "info", // Anilist - AnilistEnable: false, + constant.AnilistEnable: false, } for field, value := range fields { @@ -123,10 +123,10 @@ func setDefaults() { // resolveAliases resolves the aliases for the paths func resolveAliases() { home := lo.Must(os.UserHomeDir()) - path := viper.GetString(DownloaderPath) + path := viper.GetString(constant.DownloaderPath) path = strings.ReplaceAll(path, "$HOME", home) path = strings.ReplaceAll(path, "~", home) - viper.Set(DownloaderPath, path) + viper.Set(constant.DownloaderPath, path) } diff --git a/config/env.go b/config/env.go new file mode 100644 index 00000000..a4716986 --- /dev/null +++ b/config/env.go @@ -0,0 +1,34 @@ +package config + +import "github.com/metafates/mangal/constant" + +var EnvExposed = []string{ + // downloader + constant.DownloaderPath, + constant.DownloaderChapterNameTemplate, + constant.DownloaderCreateMangaDir, + constant.DownloaderDefaultSource, + + // formats + constant.FormatsUse, + + // reader + constant.ReaderCBZ, + constant.ReaderPDF, + constant.ReaderZIP, + constant.RaderPlain, + + // history + constant.HistorySaveOnRead, + constant.HistorySaveOnDownload, + + // Logs + constant.LogsWrite, + constant.LogsLevel, + + // Anilist + constant.AnilistEnable, + constant.AnilistID, + constant.AnilistSecret, + constant.AnilistCode, +} diff --git a/config/fields.go b/constant/config.go similarity index 77% rename from config/fields.go rename to constant/config.go index 50281423..49e483a1 100644 --- a/config/fields.go +++ b/constant/config.go @@ -1,4 +1,4 @@ -package config +package constant const ( DownloaderPath = "downloader.path" @@ -62,34 +62,3 @@ const ( LogsWrite = "logs.write" LogsLevel = "logs.level" ) - -var EnvExposed = []string{ - // downloader - DownloaderPath, - DownloaderChapterNameTemplate, - DownloaderCreateMangaDir, - DownloaderDefaultSource, - - // formats - FormatsUse, - - // reader - ReaderCBZ, - ReaderPDF, - ReaderZIP, - RaderPlain, - - // history - HistorySaveOnRead, - HistorySaveOnDownload, - - // Logs - LogsWrite, - LogsLevel, - - // Anilist - AnilistEnable, - AnilistID, - AnilistSecret, - AnilistCode, -} diff --git a/constant/constant.go b/constant/constant.go index 1b6d05c7..a85dc42d 100644 --- a/constant/constant.go +++ b/constant/constant.go @@ -26,22 +26,29 @@ const ( ChapterPagesFn = "ChapterPages" ) -const SourceTemplate = `{{ repeat "-" (max (len .URL) (len .Name)) }}{{ repeat "-" 12 }} +const SourceTemplate = `{{ $divider := repeat "-" (plus (max (len .URL) (len .Name) (len .Author) 3) 12) }}{{ $divider }} -- @name {{ .Name }} -- @url {{ .URL }} -- @author {{ .Author }} -- @license MIT -{{ repeat "-" (max (len .URL) (len .Name)) }}{{ repeat "-" 12 }} +{{ $divider }} ---- IMPORTS --- --- ... ---- VARIABLES --- --- ... +----- IMPORTS ----- +--- END IMPORTS --- + + +----- VARIABLES ----- +--- END VARIABLES --- + + + +----- MAIN ----- + --- Searches for manga with given query. -- @param query Query to search for -- @return Table of tables with the following fields: name, url @@ -65,5 +72,12 @@ function {{ .ChapterPagesFn }}(chapterURL) return {} end +--- END MAIN --- + + + + +----- HELPERS ----- +--- END HELPERS --- -- ex: ts=4 sw=4 et filetype=lua` diff --git a/converter/cbz/cbz.go b/converter/cbz/cbz.go index 69478553..3baed55f 100644 --- a/converter/cbz/cbz.go +++ b/converter/cbz/cbz.go @@ -3,15 +3,13 @@ package cbz import ( "archive/zip" "fmt" - "github.com/metafates/mangal/config" "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/source" "github.com/metafates/mangal/util" + "github.com/metafates/mangal/where" "github.com/spf13/afero" - "github.com/spf13/viper" "io" - "os" "path/filepath" "strings" ) @@ -40,7 +38,7 @@ func save(chapter *source.Chapter, temp bool) (string, error) { if temp { mangaDir, err = filesystem.Get().TempDir("", constant.TempPrefix) } else { - mangaDir, err = prepareMangaDir(chapter.Manga) + mangaDir = where.Manga(chapter.Manga.Name) } if err != nil { @@ -84,29 +82,6 @@ func save(chapter *source.Chapter, temp bool) (string, error) { return absPath, nil } -// prepareMangaDir will create manga direcotry if it doesn't exist -func prepareMangaDir(manga *source.Manga) (mangaDir string, err error) { - absDownloaderPath, err := filepath.Abs(viper.GetString(config.DownloaderPath)) - if err != nil { - return "", err - } - - if viper.GetBool(config.DownloaderCreateMangaDir) { - mangaDir = filepath.Join( - absDownloaderPath, - util.SanitizeFilename(manga.Name), - ) - } else { - mangaDir = absDownloaderPath - } - - if err = filesystem.Get().MkdirAll(mangaDir, os.ModePerm); err != nil { - return "", err - } - - return mangaDir, nil -} - func comicInfo(chapter *source.Chapter) string { return ` diff --git a/converter/pdf/pdf.go b/converter/pdf/pdf.go index 0c339a84..21b7f78e 100644 --- a/converter/pdf/pdf.go +++ b/converter/pdf/pdf.go @@ -1,18 +1,17 @@ package pdf import ( - "github.com/metafates/mangal/config" "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/source" "github.com/metafates/mangal/util" + "github.com/metafates/mangal/where" "github.com/pdfcpu/pdfcpu/pkg/api" "github.com/pdfcpu/pdfcpu/pkg/log" "github.com/pdfcpu/pdfcpu/pkg/pdfcpu" "github.com/spf13/afero" "github.com/spf13/viper" "io" - "os" "path/filepath" ) @@ -39,7 +38,7 @@ func save(chapter *source.Chapter, temp bool) (string, error) { if temp { mangaDir, err = filesystem.Get().TempDir("", constant.TempPrefix) } else { - mangaDir, err = prepareMangaDir(chapter.Manga) + mangaDir = where.Manga(chapter.Manga.Name) } if err != nil { @@ -69,29 +68,6 @@ func save(chapter *source.Chapter, temp bool) (string, error) { return chapterPdf, nil } -// prepareMangaDir will create manga direcotry if it doesn't exist -func prepareMangaDir(manga *source.Manga) (mangaDir string, err error) { - absDownloaderPath, err := filepath.Abs(viper.GetString(config.DownloaderPath)) - if err != nil { - return "", err - } - - if viper.GetBool(config.DownloaderCreateMangaDir) { - mangaDir = filepath.Join( - absDownloaderPath, - util.SanitizeFilename(manga.Name), - ) - } else { - mangaDir = absDownloaderPath - } - - if err = filesystem.Get().MkdirAll(mangaDir, os.ModePerm); err != nil { - return "", err - } - - return mangaDir, nil -} - // imagesToPDF will convert images to PDF and write to w func imagesToPDF(w io.Writer, images []io.Reader) error { conf := pdfcpu.NewDefaultConfiguration() @@ -123,7 +99,7 @@ func imagesToPDF(w io.Writer, images []io.Reader) error { indRef, err := pdfcpu.NewPageForImage(ctx.XRefTable, r, pagesIndRef, imp) if err != nil { - if viper.GetBool(config.FormatsSkipUnsupportedImages) { + if viper.GetBool(constant.FormatsSkipUnsupportedImages) { continue } diff --git a/converter/plain/plain.go b/converter/plain/plain.go index 90f7de52..1235b2eb 100644 --- a/converter/plain/plain.go +++ b/converter/plain/plain.go @@ -2,12 +2,11 @@ package plain import ( "fmt" - "github.com/metafates/mangal/config" "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/source" "github.com/metafates/mangal/util" - "github.com/spf13/viper" + "github.com/metafates/mangal/where" "io" "os" "path/filepath" @@ -74,23 +73,8 @@ func save(chapter *source.Chapter, temp bool) (string, error) { // prepareMangaDir will create manga direcotry if it doesn't exist func prepareChapterDir(chapter *source.Chapter) (chapterDir string, err error) { - absDownloaderPath, err := filepath.Abs(viper.GetString(config.DownloaderPath)) - if err != nil { - return "", err - } - - if viper.GetBool(config.DownloaderCreateMangaDir) { - chapterDir = filepath.Join( - absDownloaderPath, - util.SanitizeFilename(chapter.Manga.Name), - util.SanitizeFilename(chapter.FormattedName()), - ) - } else { - chapterDir = filepath.Join( - absDownloaderPath, - util.SanitizeFilename(chapter.FormattedName()), - ) - } + path := where.Manga(chapter.Manga.Name) + chapterDir = filepath.Join(path, util.SanitizeFilename(chapter.FormattedName())) if err = filesystem.Get().MkdirAll(chapterDir, os.ModePerm); err != nil { return "", err diff --git a/converter/zip/zip.go b/converter/zip/zip.go index 4b609ef0..4662b340 100644 --- a/converter/zip/zip.go +++ b/converter/zip/zip.go @@ -3,15 +3,13 @@ package zip import ( "archive/zip" "fmt" - "github.com/metafates/mangal/config" "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/source" "github.com/metafates/mangal/util" + "github.com/metafates/mangal/where" "github.com/spf13/afero" - "github.com/spf13/viper" "io" - "os" "path/filepath" "time" ) @@ -39,7 +37,7 @@ func save(chapter *source.Chapter, temp bool) (string, error) { if temp { mangaDir, err = filesystem.Get().TempDir("", constant.TempPrefix) } else { - mangaDir, err = prepareMangaDir(chapter.Manga) + mangaDir = where.Manga(chapter.Manga.Name) } if err != nil { @@ -73,29 +71,6 @@ func save(chapter *source.Chapter, temp bool) (string, error) { return chapterZip, nil } -// prepareMangaDir will create manga direcotry if it doesn't exist -func prepareMangaDir(manga *source.Manga) (mangaDir string, err error) { - absDownloaderPath, err := filepath.Abs(viper.GetString(config.DownloaderPath)) - if err != nil { - return "", err - } - - if viper.GetBool(config.DownloaderCreateMangaDir) { - mangaDir = filepath.Join( - absDownloaderPath, - util.SanitizeFilename(manga.Name), - ) - } else { - mangaDir = absDownloaderPath - } - - if err = filesystem.Get().MkdirAll(mangaDir, os.ModePerm); err != nil { - return "", err - } - - return mangaDir, nil -} - func addToZip(writer *zip.Writer, file io.Reader, name string) error { header := &zip.FileHeader{ Name: name, diff --git a/downloader/download.go b/downloader/download.go index 4e8b89a5..0bbbb4ad 100644 --- a/downloader/download.go +++ b/downloader/download.go @@ -2,7 +2,7 @@ package downloader import ( "fmt" - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/converter" "github.com/metafates/mangal/history" "github.com/metafates/mangal/log" @@ -30,27 +30,27 @@ func Download(src source.Source, chapter *source.Chapter, progress func(string)) return "", err } - log.Info("getting " + viper.GetString(config.FormatsUse) + " converter") + log.Info("getting " + viper.GetString(constant.FormatsUse) + " converter") progress(fmt.Sprintf( "Converting %d pages to %s %s", len(pages), - style.Yellow(viper.GetString(config.FormatsUse)), + style.Yellow(viper.GetString(constant.FormatsUse)), style.Faint(chapter.SizeHuman())), ) - conv, err := converter.Get(viper.GetString(config.FormatsUse)) + conv, err := converter.Get(viper.GetString(constant.FormatsUse)) if err != nil { log.Error(err) return "", err } - log.Info("converting " + viper.GetString(config.FormatsUse)) + log.Info("converting " + viper.GetString(constant.FormatsUse)) path, err := conv.Save(chapter) if err != nil { log.Error(err) return "", err } - if viper.GetBool(config.HistorySaveOnDownload) { + if viper.GetBool(constant.HistorySaveOnDownload) { go func() { err = history.Save(chapter) if err != nil { diff --git a/downloader/read.go b/downloader/read.go index 756364cb..c35e669a 100644 --- a/downloader/read.go +++ b/downloader/read.go @@ -2,7 +2,7 @@ package downloader import ( "fmt" - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/converter" "github.com/metafates/mangal/history" "github.com/metafates/mangal/log" @@ -17,7 +17,7 @@ import ( // and opening it with the configured reader. func Read(src source.Source, chapter *source.Chapter, progress func(string)) error { - if viper.GetBool(config.ReaderReadInBrowser) { + if viper.GetBool(constant.ReaderReadInBrowser) { return open.Start(chapter.URL) } @@ -38,18 +38,18 @@ func Read(src source.Source, chapter *source.Chapter, progress func(string)) err return err } - log.Info("getting " + viper.GetString(config.FormatsUse) + " converter") - conv, err := converter.Get(viper.GetString(config.FormatsUse)) + log.Info("getting " + viper.GetString(constant.FormatsUse) + " converter") + conv, err := converter.Get(viper.GetString(constant.FormatsUse)) if err != nil { log.Error(err) return err } - log.Info("converting " + viper.GetString(config.FormatsUse)) + log.Info("converting " + viper.GetString(constant.FormatsUse)) progress(fmt.Sprintf( "Converting %d pages to %s %s", len(pages), - style.Yellow(viper.GetString(config.FormatsUse)), + style.Yellow(viper.GetString(constant.FormatsUse)), style.Faint(chapter.SizeHuman())), ) path, err := conv.SaveTemp(chapter) @@ -63,7 +63,7 @@ func Read(src source.Source, chapter *source.Chapter, progress func(string)) err return err } - if viper.GetBool(config.HistorySaveOnRead) { + if viper.GetBool(constant.HistorySaveOnRead) { go func() { err := history.Save(chapter) if err != nil { @@ -84,15 +84,15 @@ func openRead(path string, progress func(string)) error { err error ) - switch viper.GetString(config.FormatsUse) { + switch viper.GetString(constant.FormatsUse) { case "pdf": - reader = viper.GetString(config.ReaderPDF) + reader = viper.GetString(constant.ReaderPDF) case "cbz": - reader = viper.GetString(config.ReaderCBZ) + reader = viper.GetString(constant.ReaderCBZ) case "zip": - reader = viper.GetString(config.ReaderZIP) + reader = viper.GetString(constant.ReaderZIP) case "plain": - reader = viper.GetString(config.RaderPlain) + reader = viper.GetString(constant.RaderPlain) } if reader != "" { diff --git a/history/history.go b/history/history.go index bdeccff4..7955aaae 100644 --- a/history/history.go +++ b/history/history.go @@ -3,7 +3,7 @@ package history import ( "encoding/json" "fmt" - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/integration" "github.com/metafates/mangal/log" @@ -55,7 +55,7 @@ func Get() (map[string]*SavedChapter, error) { // Save saves the chapter to the history file func Save(chapter *source.Chapter) error { - if viper.GetBool(config.AnilistEnable) { + if viper.GetBool(constant.AnilistEnable) { defer func() { log.Info("Saving chapter to anilist") err := integration.Anilist.MarkRead(chapter) diff --git a/icon/icon.go b/icon/icon.go index 6f10ddef..89b181d4 100644 --- a/icon/icon.go +++ b/icon/icon.go @@ -1,7 +1,7 @@ package icon import ( - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/spf13/viper" ) @@ -26,7 +26,7 @@ type iconDef struct { } func (i *iconDef) Get() string { - switch viper.GetString(config.IconsVariant) { + switch viper.GetString(constant.IconsVariant) { case emoji: return i.emoji case nerd: diff --git a/inline/inline.go b/inline/inline.go index 9cb42786..70a5317e 100644 --- a/inline/inline.go +++ b/inline/inline.go @@ -3,7 +3,7 @@ package inline import ( "errors" "fmt" - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/downloader" "github.com/spf13/viper" ) @@ -34,7 +34,7 @@ func Run(options *Options) error { for _, chapter := range chapters { if options.Download { path, err := downloader.Download(options.Source, chapter, func(string) {}) - if err != nil && viper.GetBool(config.DownloaderStopOnError) { + if err != nil && viper.GetBool(constant.DownloaderStopOnError) { return err } diff --git a/installer/collector.go b/installer/collector.go index 0c9c346f..d2a3c96d 100644 --- a/installer/collector.go +++ b/installer/collector.go @@ -1,7 +1,7 @@ package installer import ( - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/util" "github.com/samber/lo" "github.com/spf13/viper" @@ -36,8 +36,8 @@ func Scrapers() ([]*Scraper, error) { func setupCollector() { collector = &githubFilesCollector{ - user: viper.GetString(config.InstallerUser), - repo: viper.GetString(config.InstallerRepo), - branch: viper.GetString(config.InstallerBranch), + user: viper.GetString(constant.InstallerUser), + repo: viper.GetString(constant.InstallerRepo), + branch: viper.GetString(constant.InstallerBranch), } } diff --git a/integration/anilist/anilist.go b/integration/anilist/anilist.go index 8ec2b2d7..7f0ec66f 100644 --- a/integration/anilist/anilist.go +++ b/integration/anilist/anilist.go @@ -1,7 +1,7 @@ package anilist import ( - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/spf13/viper" ) @@ -17,15 +17,15 @@ func New() *Anilist { } func (a *Anilist) id() string { - return viper.GetString(config.AnilistID) + return viper.GetString(constant.AnilistID) } func (a *Anilist) secret() string { - return viper.GetString(config.AnilistSecret) + return viper.GetString(constant.AnilistSecret) } func (a *Anilist) code() string { - return viper.GetString(config.AnilistCode) + return viper.GetString(constant.AnilistCode) } func (a *Anilist) AuthURL() string { diff --git a/log/log.go b/log/log.go index a750bdc4..b2ecc1f1 100644 --- a/log/log.go +++ b/log/log.go @@ -3,7 +3,7 @@ package log import ( "errors" "fmt" - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/where" "github.com/samber/lo" @@ -17,7 +17,7 @@ import ( var writeLogs bool func Setup() error { - writeLogs = viper.GetBool(config.LogsWrite) + writeLogs = viper.GetBool(constant.LogsWrite) if !writeLogs { return nil @@ -41,7 +41,7 @@ func Setup() error { log.SetOutput(logFile) - switch viper.GetString(config.LogsLevel) { + switch viper.GetString(constant.LogsLevel) { case "panic": log.SetLevel(log.PanicLevel) case "fatal": diff --git a/mini/states.go b/mini/states.go index 522efbc9..592b5e21 100644 --- a/mini/states.go +++ b/mini/states.go @@ -2,7 +2,7 @@ package mini import ( "fmt" - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/downloader" "github.com/metafates/mangal/history" "github.com/metafates/mangal/provider" @@ -32,7 +32,7 @@ const ( func (m *mini) handleSourceSelectState() error { var err error - if name := viper.GetString(config.DownloaderDefaultSource); name != "" { + if name := viper.GetString(constant.DownloaderDefaultSource); name != "" { p, ok := provider.Get(name) if !ok { return fmt.Errorf("unknown source \"%s\"", name) @@ -100,7 +100,7 @@ func (m *mini) handleMangaSearchState() error { erase := progress("Searching Query..") m.cachedMangas[query], err = m.selectedSource.Search(query) - max := lo.Min([]int{len(m.cachedMangas[query]), viper.GetInt(config.MiniSearchLimit)}) + max := lo.Min([]int{len(m.cachedMangas[query]), viper.GetInt(constant.MiniSearchLimit)}) m.cachedMangas[query] = m.cachedMangas[query][:max] erase() @@ -333,7 +333,7 @@ func (m *mini) handleChaptersDownloadState() error { erase() - if err != nil && viper.GetBool(config.DownloaderStopOnError) { + if err != nil && viper.GetBool(constant.DownloaderStopOnError) { return err } diff --git a/provider/mangadex/chapters.go b/provider/mangadex/chapters.go index b717ec11..3fbc90f7 100644 --- a/provider/mangadex/chapters.go +++ b/provider/mangadex/chapters.go @@ -3,7 +3,7 @@ package mangadex import ( "fmt" "github.com/darylhjd/mangodex" - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/source" "github.com/spf13/viper" "golang.org/x/exp/slices" @@ -23,7 +23,7 @@ func (m *Mangadex) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { params.Add("contentRating[]", rating) } - if viper.GetBool(config.MangadexNSFW) { + if viper.GetBool(constant.MangadexNSFW) { params.Add("contentRating[]", mangodex.Porn) params.Add("contentRating[]", mangodex.Erotica) } @@ -44,12 +44,12 @@ func (m *Mangadex) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { for i, chapter := range list.Data { // Skip external chapters. Their pages cannot be downloaded. - if chapter.Attributes.ExternalURL != nil && !viper.GetBool(config.MangadexShowUnavailableChapters) { + if chapter.Attributes.ExternalURL != nil && !viper.GetBool(constant.MangadexShowUnavailableChapters) { continue } // skip chapters that are not in the current language - if chapter.Attributes.TranslatedLanguage != viper.GetString(config.MangadexLanguage) { + if chapter.Attributes.TranslatedLanguage != viper.GetString(constant.MangadexLanguage) { currOffset += 500 continue } diff --git a/provider/mangadex/search.go b/provider/mangadex/search.go index da06f281..34f8e24d 100644 --- a/provider/mangadex/search.go +++ b/provider/mangadex/search.go @@ -3,7 +3,7 @@ package mangadex import ( "fmt" "github.com/darylhjd/mangodex" - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/source" "github.com/spf13/viper" "log" @@ -25,7 +25,7 @@ func (m *Mangadex) Search(query string) ([]*source.Manga, error) { params.Add("contentRating[]", rating) } - if viper.GetBool(config.MangadexNSFW) { + if viper.GetBool(constant.MangadexNSFW) { params.Add("contentRating[]", mangodex.Porn) params.Add("contentRating[]", mangodex.Erotica) } @@ -43,7 +43,7 @@ func (m *Mangadex) Search(query string) ([]*source.Manga, error) { for i, manga := range mangaList.Data { m := source.Manga{ - Name: manga.GetTitle(viper.GetString(config.MangadexLanguage)), + Name: manga.GetTitle(viper.GetString(constant.MangadexLanguage)), URL: fmt.Sprintf("https://mangadex.org/title/%s", manga.ID), Index: uint16(i), SourceID: ID, diff --git a/source/chapter.go b/source/chapter.go index 45fde144..84b4b26f 100644 --- a/source/chapter.go +++ b/source/chapter.go @@ -3,7 +3,7 @@ package source import ( "fmt" "github.com/dustin/go-humanize" - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/util" "github.com/spf13/viper" "strings" @@ -51,7 +51,7 @@ func (c *Chapter) DownloadPages() error { err = page.Download() } - if viper.GetBool(config.DownloaderAsync) { + if viper.GetBool(constant.DownloaderAsync) { go d(page) } else { d(page) @@ -64,7 +64,7 @@ func (c *Chapter) DownloadPages() error { // FormattedName of the chapter according to the template in the config. func (c *Chapter) FormattedName() (name string) { - template := viper.GetString(config.DownloaderChapterNameTemplate) + template := viper.GetString(constant.DownloaderChapterNameTemplate) name = strings.ReplaceAll(template, "{manga}", c.Manga.Name) name = strings.ReplaceAll(name, "{chapter}", c.Name) name = strings.ReplaceAll(name, "{index}", fmt.Sprintf("%d", c.Index)) diff --git a/tui/handlers.go b/tui/handlers.go index bd564e3d..a9932ecc 100644 --- a/tui/handlers.go +++ b/tui/handlers.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/downloader" "github.com/metafates/mangal/installer" "github.com/metafates/mangal/log" @@ -209,7 +209,7 @@ func (b *statefulBubble) downloadChapter(chapter *source.Chapter) tea.Cmd { }) if err != nil { - if viper.GetBool(config.DownloaderStopOnError) { + if viper.GetBool(constant.DownloaderStopOnError) { b.errorChannel <- err } else { b.failedChapters = append(b.failedChapters, chapter) diff --git a/tui/init.go b/tui/init.go index 443ad412..ec0add11 100644 --- a/tui/init.go +++ b/tui/init.go @@ -4,13 +4,13 @@ import ( "fmt" "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/provider" "github.com/spf13/viper" ) func (b *statefulBubble) Init() tea.Cmd { - if name := viper.GetString(config.DownloaderDefaultSource); name != "" { + if name := viper.GetString(constant.DownloaderDefaultSource); name != "" { p, ok := provider.Get(name) if !ok { b.lastError = fmt.Errorf("provider %s not found", name) diff --git a/where/where.go b/where/where.go index 5c643165..49fd026c 100644 --- a/where/where.go +++ b/where/where.go @@ -3,7 +3,9 @@ package where import ( "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" + "github.com/metafates/mangal/util" "github.com/samber/lo" + "github.com/spf13/viper" "os" "path/filepath" ) @@ -55,3 +57,28 @@ func History() string { return path } + +func Download() string { + path, err := filepath.Abs(viper.GetString(constant.DownloaderPath)) + + if err != nil { + path = "." + } + + return mkdir(path) +} + +func Manga(mangaName string) string { + var path string + + if viper.GetBool(constant.DownloaderCreateMangaDir) { + path = filepath.Join( + Download(), + util.SanitizeFilename(mangaName), + ) + } else { + path = Download() + } + + return mkdir(path) +} From 880195db5fa5b91a5d3412c3b0520df245ba3fcc Mon Sep 17 00:00:00 2001 From: metafates Date: Tue, 23 Aug 2022 13:34:30 +0400 Subject: [PATCH 12/51] docs(readme): some improvements --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3fa18357..ce3d5793 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ Example of usage: mangal inline --source Manganelo --query "death note" --manga first --chapters "@Vol.1 @" -d -> This will download the first volume of "Death Note" from Mangalelo. +> This will download the first volume of "Death Note" from Manganelo. Type `mangal help inline` for more information @@ -145,8 +145,9 @@ See `mangal help` for more information ## Configuration Mangal uses [TOML](https://toml.io) format for configuration under the `mangal.toml` filename. -Config is expected to be at the OS default config directory. -For example, on Linux it would be `~/.config/mangal/mangal.toml`. +Config path depends on the OS. +To find yours, use `mangal where --config`. +For example, on __Linux__ it would be `~/.config/mangal/mangal.toml`. Use env variable `MANGAL_CONFIG_PATH` to set custom config path. > See `mangal env` to show all available env variables. From 1b0ed18aca65dbe46ea0cf3a9a6092bff261bee3 Mon Sep 17 00:00:00 2001 From: metafates Date: Tue, 23 Aug 2022 18:26:26 +0400 Subject: [PATCH 13/51] fix(tui): handle unknown state --- icon/icon_test.go | 2 +- mini/input.go | 2 +- tui/bubble.go | 5 ++++- util/stack_test.go | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/icon/icon_test.go b/icon/icon_test.go index c60bd325..be5c86b7 100644 --- a/icon/icon_test.go +++ b/icon/icon_test.go @@ -50,4 +50,4 @@ func TestGet(t *testing.T) { }) }) }) -} \ No newline at end of file +} diff --git a/mini/input.go b/mini/input.go index 0bd0f351..69f0c189 100644 --- a/mini/input.go +++ b/mini/input.go @@ -32,7 +32,7 @@ func getInput(validator func(string) bool) (*input, error) { if in == "" { in = "1" } - + if !validator(in) { fmt.Println(style.Red("Invalid choice entered")) return getInput(validator) diff --git a/tui/bubble.go b/tui/bubble.go index a57fad41..baa8e80e 100644 --- a/tui/bubble.go +++ b/tui/bubble.go @@ -100,7 +100,10 @@ func (b *statefulBubble) newState(s state) { func (b *statefulBubble) previousState() { if b.statesHistory.Len() > 0 { - b.setState(b.statesHistory.Pop()) + s := b.statesHistory.Pop() + if s != 0 { + b.setState(s) + } } } diff --git a/util/stack_test.go b/util/stack_test.go index 8fc14558..82846150 100644 --- a/util/stack_test.go +++ b/util/stack_test.go @@ -31,4 +31,4 @@ func TestStack(t *testing.T) { }) }) }) -} \ No newline at end of file +} From 4c790948ec322c90b9233f49a61a42d4bc5d707a Mon Sep 17 00:00:00 2001 From: metafates Date: Wed, 24 Aug 2022 00:30:48 +0400 Subject: [PATCH 14/51] refactor: minor changes --- .github/workflows/test.yml | 42 ++++++++++++++++++++++++----- CHANGELOG.md | 26 ++++++++++++++++++ config/config.go | 53 +------------------------------------ config/default.go | 54 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 59 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 config/default.go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3312bdb8..d5eaf5fe 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,17 +4,20 @@ on: push: branches: - main - tags: - - '*' - pull_request: - branches: - - main jobs: + test: + name: Test + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + env: + GOFLAGS: -mod=readonly - build: - runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -24,4 +27,29 @@ jobs: go-version: 1.18 - name: Test + run: go test -race -v ./... + if: runner.os != 'Windows' + + - name: Test (without race detector) run: go test -v ./... + if: runner.os == 'Windows' + + lint: + name: Lint + runs-on: ubuntu-latest + env: + GOFLAGS: -mod=readonly + + steps: + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.18 + + - name: Checkout code + uses: actions/checkout@v3 + + - name: Lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.45.2 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..a6ad425c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,26 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to +[Semantic Versioning](https://semver.org). + +## [3.5.0] + +- `gen` command added to generate a template for custom source + +## [3.4.1] + +- Option to continue downloading chapters after fail +- Option to redownload failed chapters +- Option to select custom reader app for each format +- Option to skip images with unsupported formats by converter (e.g. pdf converter will skip .gif images) (#77) +- Option to specify custom repository for `mangal install` command +- Fixed error when using custom readers was not possible +- Highlight read button in the chapters list +- Make `mangal env` more compact, add `--filter` argument to filter out unset variables +- Show `MANGAL_CONFIG_PATH` in the `env` command +- Show better error when chapter could not be opened by reader +- Fix chapters range selector in inline mode (#76) +- Show progress when initializing source from history +- Show size of a downloading chapter diff --git a/config/config.go b/config/config.go index b47dbdf4..cb4c50f2 100644 --- a/config/config.go +++ b/config/config.go @@ -64,58 +64,7 @@ func setEnvs() { func setDefaults() { viper.SetTypeByDefaultValue(true) - fields := map[string]any{ - // Downloader - constant.DownloaderPath: ".", - constant.DownloaderChapterNameTemplate: "[{padded-index}] {chapter}", - constant.DownloaderAsync: true, - constant.DownloaderCreateMangaDir: true, - constant.DownloaderDefaultSource: "", - constant.DownloaderStopOnError: false, - - // Formats - constant.FormatsUse: "pdf", - constant.FormatsSkipUnsupportedImages: true, - - // Mini-mode - constant.MiniSearchLimit: 20, - - // Icons - constant.IconsVariant: "plain", - - // Reader - constant.ReaderPDF: "", - constant.ReaderCBZ: "", - constant.ReaderZIP: "", - constant.RaderPlain: "", - constant.ReaderReadInBrowser: false, - - // History - constant.HistorySaveOnRead: true, - constant.HistorySaveOnDownload: false, - - // Mangadex - constant.MangadexLanguage: "en", - constant.MangadexNSFW: false, - constant.MangadexShowUnavailableChapters: false, - - // Installer - constant.InstallerUser: "metafates", - constant.InstallerRepo: "mangal-scrapers", - constant.InstallerBranch: "main", - - // Gen - constant.GenAuthor: "", - - // Logs - constant.LogsWrite: false, - constant.LogsLevel: "info", - - // Anilist - constant.AnilistEnable: false, - } - - for field, value := range fields { + for field, value := range defaultValues { viper.SetDefault(field, value) } } diff --git a/config/default.go b/config/default.go new file mode 100644 index 00000000..40f09433 --- /dev/null +++ b/config/default.go @@ -0,0 +1,54 @@ +package config + +import "github.com/metafates/mangal/constant" + +var defaultValues = map[string]any{ + // Downloader + constant.DownloaderPath: ".", + constant.DownloaderChapterNameTemplate: "[{padded-index}] {chapter}", + constant.DownloaderAsync: true, + constant.DownloaderCreateMangaDir: true, + constant.DownloaderDefaultSource: "", + constant.DownloaderStopOnError: false, + + // Formats + constant.FormatsUse: "pdf", + constant.FormatsSkipUnsupportedImages: true, + + // Mini-mode + constant.MiniSearchLimit: 20, + + // Icons + constant.IconsVariant: "plain", + + // Reader + constant.ReaderPDF: "", + constant.ReaderCBZ: "", + constant.ReaderZIP: "", + constant.RaderPlain: "", + constant.ReaderReadInBrowser: false, + + // History + constant.HistorySaveOnRead: true, + constant.HistorySaveOnDownload: false, + + // Mangadex + constant.MangadexLanguage: "en", + constant.MangadexNSFW: false, + constant.MangadexShowUnavailableChapters: false, + + // Installer + constant.InstallerUser: "metafates", + constant.InstallerRepo: "mangal-scrapers", + constant.InstallerBranch: "main", + + // Gen + constant.GenAuthor: "", + + // Logs + constant.LogsWrite: false, + constant.LogsLevel: "info", + + // Anilist + constant.AnilistEnable: false, +} From 110dd4e0fa3bb892c90fcbbe279d5cff8acadeec Mon Sep 17 00:00:00 2001 From: metafates Date: Wed, 24 Aug 2022 17:49:40 +0400 Subject: [PATCH 15/51] feat(cmd): add `--raw` flag for `sources` cmd --- cmd/sources.go | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/cmd/sources.go b/cmd/sources.go index 3d3dbd33..7f3fecd2 100644 --- a/cmd/sources.go +++ b/cmd/sources.go @@ -3,11 +3,15 @@ package cmd import ( "github.com/metafates/mangal/provider" "github.com/metafates/mangal/style" + "github.com/samber/lo" "github.com/spf13/cobra" + "os" ) func init() { rootCmd.AddCommand(sourcesCmd) + + sourcesCmd.Flags().BoolP("raw", "r", false, "do not print headers") } var sourcesCmd = &cobra.Command{ @@ -15,19 +19,26 @@ var sourcesCmd = &cobra.Command{ Short: "List an available sources", Example: "mangal sources", RunE: func(cmd *cobra.Command, args []string) error { + cmd.SetOut(os.Stdout) + + printHeader := !lo.Must(cmd.Flags().GetBool("raw")) headerStyle := style.Combined(style.Bold, style.HiBlue) - cmd.Println(headerStyle("Builtin:")) + h := func(s string) { + if printHeader { + cmd.Println(headerStyle(s)) + } + } + + h("Builtin:") for name := range provider.DefaultProviders() { cmd.Println(name) } - cmd.Println() - - cmd.Println(headerStyle("Custom:")) - custom := provider.CustomProviders() + h("") - for name := range custom { + h("Custom:") + for name := range provider.CustomProviders() { cmd.Println(name) } From 617d8f9c1f8c441f61b77f17ecf486d73675460a Mon Sep 17 00:00:00 2001 From: metafates Date: Thu, 25 Aug 2022 00:01:15 +0400 Subject: [PATCH 16/51] docs(changelog): add CHANGELOG.md --- CHANGELOG.md | 117 ++++++++++++++++++++++++++++++++++++- install => scripts/install | 0 scripts/install.ps1 | 40 +++++++++++++ run => scripts/run | 0 scripts/run.ps1 | 28 +++++++++ 5 files changed, 183 insertions(+), 2 deletions(-) rename install => scripts/install (100%) create mode 100644 scripts/install.ps1 rename run => scripts/run (100%) create mode 100644 scripts/run.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index a6ad425c..4044b142 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org). -## [3.5.0] +## 3.5.0 +- Add `--raw` flag for the `sources` command to print without headers - `gen` command added to generate a template for custom source -## [3.4.1] +## 3.4.1 - Option to continue downloading chapters after fail - Option to redownload failed chapters @@ -24,3 +25,115 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this - Fix chapters range selector in inline mode (#76) - Show progress when initializing source from history - Show size of a downloading chapter + +## 3.3.0 + +- Inline mode added. See `mangal help inline` +- Option to choose default source added +- Show `read` button in help menu +- Bug fixes and improvements + +## 3.2.1 + +- Fix home variable in config + +## 3.2.0 + +- New command added mangal install to install scrapers from mangal-scrapers repo +- Added an option to remove a single entry from history by pressing d +- Added an option to download chapters without creating manga directory +- Dependencies updated +- Bug fixes and improvements + +## 3.1.0 + +- `where` command now prints to stdout. It can be used like that: `cd $(mangal where --config)` +- Mini mode was completely rewritten to look exactly like [ani-cli](https://github.com/pystardust/ani-cli) +- PDF is a default export format now (was plain) +- Plain icons are default now (were emoji) +- New icons added - "squares" +- New command `mangal config remove` to... well... remove config +- Minor bug fixes and improvements + +## 3.0.3 + +- Better path handling +- Use pdf a default format + +## 3.0.2 + +- Fix bug where empty config would case errors + +## 3.0.1 + +- Bug fixes... + +## 3.0.0 + +- Full rewrite of the mangal +- Add support for Lua scrapers +- Better TUI +- Mini mode + +## 2.2.0 + +- History mode added. Now you can resume your readings by launching mangal with `mangal --resume` flag (`-r` for short) +- Support for new environment variables added +- `mangal env` command added to list all env variables and their values (if any set) +- ComicInfo.xml file fixed #53 + +## 2.1.1 + +- `doctor` command now shows more information about errors +- minor bug fixes and perfomance improvements + +## 2.1.0 + +- Significant performance improvements! ๐Ÿš€ +- Reduced disk usage +- Add support for env variables `MANGAL_CONFIG_PATH` and `MANGAL_DOWNLOAD_PATH` +- Improved config structure (breaking change, reinitialize your config if you have one) +- ComicInfo.xml support added for CBZ format #27 +- `config init --clean` flag added that creates config without additional comments +- `config remove` command added to delete user config + +## 2.0.1 + +- Fixed #36 +- Small shell completion improvements + +## 2.0.0 + +- Anilist integration BETA +- Diagnostics command `mangal doctor` +- `mangal check-update` renamed to `mangal latest` +- Custom naming templates for chapters (like this `[%d] %s`) +- Bug fixes +- Faster config parser (up to 5x faster!) +- Minor improvements + +## 1.5.2 + +- Command to check for update added `mangal check-update` #26 +- Scraper system improved +- Fixed bug where chapters with colon in title would not open for read on windows #24 +- Various bug fixes + +## 1.5.1 + +- Fixes #21, #20 + +## 1.5.0 + +- Epub format added +- Move UI related configurations to [ui] section in the config file +- New command `formats` added to show available formats and their description +- Minor improvements + +## 1.4.2 + +- Fixes #15 + +## 1.4.1 + +- Multiple formats support diff --git a/install b/scripts/install similarity index 100% rename from install rename to scripts/install diff --git a/scripts/install.ps1 b/scripts/install.ps1 new file mode 100644 index 00000000..6d2fae38 --- /dev/null +++ b/scripts/install.ps1 @@ -0,0 +1,40 @@ +# get latest release +$release_url = "https://api.github.com/repos/metafates/mangal/releases" +$tag = (Invoke-WebRequest -Uri $release_url -UseBasicParsing | ConvertFrom-Json)[0].tag_name +$loc = "$HOME\AppData\Local\mangal" +$url = "" +$arch = $env:PROCESSOR_ARCHITECTURE +$releases_api_url = "https://github.com/metafates/mangal/releases/download/$tag/mangal_${tag}_Windows" + +if ($arch -eq "AMD64") { + $url = "${releases_api_url}_x86_64.zip" +} elseif ($arch -eq "x86") { + $url = "${releases_api_url}_i386.zip" +} elseif ($arch -eq "arm64") { + $url = "${releases_api_url}_arm64.zip" +} + +if (Test-Path -path $loc) { + Remove-Item $loc -Recurse -Force +} + +Write-Host "Installing mangal version $tag" -ForegroundColor DarkCyan + +Invoke-WebRequest $url -outfile mangal.zip + +Expand-Archive mangal.zip + +New-Item -ItemType "directory" -Path $loc + +Move-Item -Path mangal\bin -Destination $loc + +Remove-Item mangal* -Recurse -Force + +[System.Environment]::SetEnvironmentVariable("Path", $Env:Path + ";$loc\bin", [System.EnvironmentVariableTarget]::User) + +if (Test-Path -path $loc) { + Write-Host "Mangal version $tag installed successfully" -ForegroundColor Green +} else { + Write-Host "Download failed" -ForegroundColor Red + Write-Host "Please try again later" -ForegroundColor Red +} diff --git a/run b/scripts/run similarity index 100% rename from run rename to scripts/run diff --git a/scripts/run.ps1 b/scripts/run.ps1 new file mode 100644 index 00000000..fa176aa1 --- /dev/null +++ b/scripts/run.ps1 @@ -0,0 +1,28 @@ + +# get latest release +$release_url = "https://api.github.com/repos/metafates/mangal/releases" +$tag = (Invoke-WebRequest -Uri $release_url -UseBasicParsing | ConvertFrom-Json)[0].tag_name +$loc = "$HOME\AppData\Local\mangal" +$url = "" +$arch = $env:PROCESSOR_ARCHITECTURE +$releases_api_url = "https://github.com/metafates/mangal/releases/download/$tag/mangal_${tag.substring(1)}_Windows" + +if ($arch -eq "AMD64") { + $url = "${releases_api_url}_x86_64.zip" +} elseif ($arch -eq "x86") { + $url = "${releases_api_url}_i386.zip" +} elseif ($arch -eq "arm64") { + $url = "${releases_api_url}_arm64.zip" +} + +if (Test-Path -path $loc) { + Remove-Item $loc -Recurse -Force +} + +Write-Host "Downloading Mangal version $tag" -ForegroundColor DarkCyan +Invoke-WebRequest $url -outfile mangal.zip +Expand-Archive mangal.zip + +.\mangal.exe + +Remove-Item mangal* -Recurse -Force From 91b4ed3237e6b4ad64c654f5f903e97e5396b2ed Mon Sep 17 00:00:00 2001 From: metafates Date: Thu, 25 Aug 2022 14:16:36 +0300 Subject: [PATCH 17/51] docs(readme): some improvements --- README.md | 4 ++-- go.mod | 10 +++++----- go.sum | 10 ++++++++++ scripts/install.ps1 | 10 ++++++---- scripts/run.ps1 | 7 ++++--- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index ce3d5793..acf9f78c 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ https://user-images.githubusercontent.com/62389790/183284495-86140f8b-d543-4bc4- ## Try it! - curl -sfL https://raw.githubusercontent.com/metafates/mangal/main/run | bash + curl -sfL https://raw.githubusercontent.com/metafates/mangal/main/scripts/run | bash > **Note** This script does not install anything, it just downloads, verifies and runs Mangal. > @@ -74,7 +74,7 @@ Install using [Homebrew](https://brew.sh/) Install using [this bash script](https://raw.githubusercontent.com/metafates/mangal/main/install) - curl -sfL https://raw.githubusercontent.com/metafates/mangal/main/install | bash + curl -sfL https://raw.githubusercontent.com/metafates/mangal/main/scripts/install | bash ### Windows diff --git a/go.mod b/go.mod index 2199887a..d52c01ee 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/spf13/viper v1.12.0 github.com/vadv/gopher-lua-libs v0.3.0 github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e + golang.org/x/exp v0.0.0-20220823124025-807a23277127 golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 ) @@ -36,7 +36,7 @@ require ( github.com/antchfx/xmlquery v1.3.12 // indirect github.com/antchfx/xpath v1.2.1 // indirect github.com/atotto/clipboard v0.1.4 // indirect - github.com/aws/aws-sdk-go v1.44.81 // indirect + github.com/aws/aws-sdk-go v1.44.83 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cbroglie/mustache v1.4.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect @@ -88,7 +88,7 @@ require ( github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/subosito/gotenv v1.4.0 // indirect + github.com/subosito/gotenv v1.4.1 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect github.com/temoto/robotstxt v1.1.2 // indirect github.com/ysmood/goob v0.4.0 // indirect @@ -96,8 +96,8 @@ require ( github.com/ysmood/leakless v0.8.0 // indirect github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7 // indirect golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 // indirect - golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect - golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect + golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c // indirect + golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24 // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect diff --git a/go.sum b/go.sum index be08a00a..c849523d 100644 --- a/go.sum +++ b/go.sum @@ -71,6 +71,8 @@ github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn github.com/aws/aws-sdk-go v1.32.1/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go v1.44.81 h1:C8oBZ+a+ka0qk3Q24MohQIFq0tkbO8IAu5tfpAMKVWE= github.com/aws/aws-sdk-go v1.44.81/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws/aws-sdk-go v1.44.83 h1:7+Rtc2Eio6EKUNoZeMV/IVxzVrY5oBQcNPtCcgIHYJA= +github.com/aws/aws-sdk-go v1.44.83/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -420,6 +422,8 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs= github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= +github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/temoto/robotstxt v1.1.2 h1:W2pOjSJ6SWvldyEuiFXNxz3xZ8aiWX5LbfDiOFd7Fxg= @@ -473,6 +477,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20220823124025-807a23277127 h1:S4NrSKDfihhl3+4jSTgwoIevKxX9p7Iv9x++OEIptDo= +golang.org/x/exp v0.0.0-20220823124025-807a23277127/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190823064033-3a9bac650e44/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -539,6 +545,8 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c h1:JVAXQ10yGGVbSyoer5VILysz6YKjdNT2bsvlayjqhes= +golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -620,6 +628,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 h1:Sx/u41w+OwrInGdEckYmEuU5gHoGSL4QbDz3S9s6j4U= golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24 h1:TyKJRhyo17yWxOMCTHKWrc5rddHORMlnZ/j57umaUd8= +golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= diff --git a/scripts/install.ps1 b/scripts/install.ps1 index 6d2fae38..c89c450f 100644 --- a/scripts/install.ps1 +++ b/scripts/install.ps1 @@ -1,10 +1,12 @@ -# get latest release +# WAS NOT TESTED + $release_url = "https://api.github.com/repos/metafates/mangal/releases" $tag = (Invoke-WebRequest -Uri $release_url -UseBasicParsing | ConvertFrom-Json)[0].tag_name +$version = $tag.substring(1) $loc = "$HOME\AppData\Local\mangal" $url = "" $arch = $env:PROCESSOR_ARCHITECTURE -$releases_api_url = "https://github.com/metafates/mangal/releases/download/$tag/mangal_${tag}_Windows" +$releases_api_url = "https://github.com/metafates/mangal/releases/download/$tag/mangal_${version}_Windows" if ($arch -eq "AMD64") { $url = "${releases_api_url}_x86_64.zip" @@ -26,11 +28,11 @@ Expand-Archive mangal.zip New-Item -ItemType "directory" -Path $loc -Move-Item -Path mangal\bin -Destination $loc +Move-Item -Path mangal\mangal.exe -Destination $loc Remove-Item mangal* -Recurse -Force -[System.Environment]::SetEnvironmentVariable("Path", $Env:Path + ";$loc\bin", [System.EnvironmentVariableTarget]::User) +[System.Environment]::SetEnvironmentVariable("Path", $Env:Path + ";$loc", [System.EnvironmentVariableTarget]::User) if (Test-Path -path $loc) { Write-Host "Mangal version $tag installed successfully" -ForegroundColor Green diff --git a/scripts/run.ps1 b/scripts/run.ps1 index fa176aa1..2353541a 100644 --- a/scripts/run.ps1 +++ b/scripts/run.ps1 @@ -1,11 +1,12 @@ +# WAS NOT TESTED -# get latest release $release_url = "https://api.github.com/repos/metafates/mangal/releases" $tag = (Invoke-WebRequest -Uri $release_url -UseBasicParsing | ConvertFrom-Json)[0].tag_name +$version = $tag.substring(1) $loc = "$HOME\AppData\Local\mangal" $url = "" $arch = $env:PROCESSOR_ARCHITECTURE -$releases_api_url = "https://github.com/metafates/mangal/releases/download/$tag/mangal_${tag.substring(1)}_Windows" +$releases_api_url = "https://github.com/metafates/mangal/releases/download/$tag/mangal_${version}_Windows" if ($arch -eq "AMD64") { $url = "${releases_api_url}_x86_64.zip" @@ -23,6 +24,6 @@ Write-Host "Downloading Mangal version $tag" -ForegroundColor DarkCyan Invoke-WebRequest $url -outfile mangal.zip Expand-Archive mangal.zip -.\mangal.exe +.\mangal\mangal.exe Remove-Item mangal* -Recurse -Force From b36e6bd363fc021756026c8a9123b43b146dabbc Mon Sep 17 00:00:00 2001 From: metafates Date: Thu, 25 Aug 2022 14:23:13 +0300 Subject: [PATCH 18/51] feat(cmd): add downloads path to `where` cmd --- cmd/where.go | 17 ++++++++++++++--- where/where.go | 6 +++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/cmd/where.go b/cmd/where.go index e1cbdbb7..309770a0 100644 --- a/cmd/where.go +++ b/cmd/where.go @@ -14,7 +14,8 @@ func init() { whereCmd.Flags().BoolP("config", "c", false, "configuration path") whereCmd.Flags().BoolP("sources", "s", false, "sources path") whereCmd.Flags().BoolP("logs", "l", false, "logs path") - whereCmd.MarkFlagsMutuallyExclusive("config", "sources", "logs") + whereCmd.Flags().BoolP("downloads", "d", false, "downloads path") + whereCmd.MarkFlagsMutuallyExclusive("config", "sources", "logs", "downloads") } var whereCmd = &cobra.Command{ @@ -27,7 +28,8 @@ var whereCmd = &cobra.Command{ whereConfig := lo.Must(cmd.Flags().GetBool("config")) whereSources := lo.Must(cmd.Flags().GetBool("sources")) - wherLogs := lo.Must(cmd.Flags().GetBool("logs")) + whereLogs := lo.Must(cmd.Flags().GetBool("logs")) + whereDownloads := lo.Must(cmd.Flags().GetBool("downloads")) title := func(do bool, what, arg string) { if do { @@ -50,19 +52,28 @@ var whereCmd = &cobra.Command{ cmd.Println(where.Logs()) } + printDownloadsPath := func(header bool) { + title(header, "Downloads", "--downloads") + cmd.Println(where.Downloads()) + } + switch { case whereConfig: printConfigPath(false) case whereSources: printSourcesPath(false) - case wherLogs: + case whereLogs: printLogsPath(false) + case whereDownloads: + printDownloadsPath(false) default: printConfigPath(true) cmd.Println() printSourcesPath(true) cmd.Println() printLogsPath(true) + cmd.Println() + printDownloadsPath(true) } }, } diff --git a/where/where.go b/where/where.go index 49fd026c..abdade12 100644 --- a/where/where.go +++ b/where/where.go @@ -58,7 +58,7 @@ func History() string { return path } -func Download() string { +func Downloads() string { path, err := filepath.Abs(viper.GetString(constant.DownloaderPath)) if err != nil { @@ -73,11 +73,11 @@ func Manga(mangaName string) string { if viper.GetBool(constant.DownloaderCreateMangaDir) { path = filepath.Join( - Download(), + Downloads(), util.SanitizeFilename(mangaName), ) } else { - path = Download() + path = Downloads() } return mkdir(path) From 63bba9d5d09b6b459730cdb4e279e46546006f49 Mon Sep 17 00:00:00 2001 From: metafates Date: Thu, 25 Aug 2022 14:24:57 +0300 Subject: [PATCH 19/51] fix(env): remove hardcoded duplicate of MANGAL_CONFIG_PATH --- cmd/env.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/env.go b/cmd/env.go index 50cbd831..32f7a1ee 100644 --- a/cmd/env.go +++ b/cmd/env.go @@ -4,6 +4,7 @@ import ( "github.com/metafates/mangal/config" "github.com/metafates/mangal/constant" "github.com/metafates/mangal/style" + "github.com/metafates/mangal/where" "github.com/samber/lo" "github.com/spf13/cobra" "os" @@ -22,9 +23,8 @@ var envCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { filter := lo.Must(cmd.Flags().GetBool("filter")) - config.EnvExposed = append(config.EnvExposed, "MANGAL_CONFIG_PATH") + config.EnvExposed = append(config.EnvExposed, where.EnvConfigPath) for _, env := range config.EnvExposed { - env = strings.ToUpper(constant.Mangal + "_" + config.EnvKeyReplacer.Replace(env)) value, present := os.LookupEnv(env) From 2a959745cf5acf09cb536db8633fb9a8e9c96a81 Mon Sep 17 00:00:00 2001 From: metafates Date: Thu, 25 Aug 2022 14:30:11 +0300 Subject: [PATCH 20/51] refactor(env): sort variables --- cmd/env.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cmd/env.go b/cmd/env.go index 32f7a1ee..6879ca4d 100644 --- a/cmd/env.go +++ b/cmd/env.go @@ -7,6 +7,7 @@ import ( "github.com/metafates/mangal/where" "github.com/samber/lo" "github.com/spf13/cobra" + "golang.org/x/exp/slices" "os" "strings" ) @@ -24,9 +25,11 @@ var envCmd = &cobra.Command{ filter := lo.Must(cmd.Flags().GetBool("filter")) config.EnvExposed = append(config.EnvExposed, where.EnvConfigPath) + slices.Sort(config.EnvExposed) for _, env := range config.EnvExposed { env = strings.ToUpper(constant.Mangal + "_" + config.EnvKeyReplacer.Replace(env)) - value, present := os.LookupEnv(env) + value := os.Getenv(env) + present := value != "" if !present && filter { continue @@ -35,7 +38,7 @@ var envCmd = &cobra.Command{ cmd.Print(style.Combined(style.Bold, style.Magenta)(env)) cmd.Print("=") - if present && value != "" { + if present { cmd.Println(style.Green(value)) } else { cmd.Println(style.Red("unset")) From 6e642038f463960ed1faa399daf1963f90cc22b4 Mon Sep 17 00:00:00 2001 From: metafates Date: Thu, 25 Aug 2022 19:05:14 +0300 Subject: [PATCH 21/51] feat(tui): show chapter index in the tui history list --- CHANGELOG.md | 2 ++ tui/bubble.go | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4044b142..280897ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this ## 3.5.0 - Add `--raw` flag for the `sources` command to print without headers +- Add `--downloads` flag for the `where` command to print location of the downloads directory - `gen` command added to generate a template for custom source +- Show chapter index in the tui history list ## 3.4.1 diff --git a/tui/bubble.go b/tui/bubble.go index baa8e80e..a5f1b682 100644 --- a/tui/bubble.go +++ b/tui/bubble.go @@ -1,6 +1,7 @@ package tui import ( + "fmt" "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/list" @@ -280,7 +281,7 @@ func (b *statefulBubble) loadHistory() (tea.Cmd, error) { for _, s := range saved { items = append(items, &listItem{ title: s.MangaName, - description: s.Name, + description: fmt.Sprintf("%s : %d / %d", s.Name, s.Index, s.MangaChaptersTotal), internal: s, }) } From cdc95d80ff063925618f0fb3c0c4e6760757c392 Mon Sep 17 00:00:00 2001 From: metafates Date: Fri, 26 Aug 2022 13:58:12 +0300 Subject: [PATCH 22/51] refactor: less boilerplate code --- cmd/gen.go | 5 +-- cmd/version.go | 6 +-- constant/formats.go | 8 ++++ converter/cbz/cbz.go | 80 +++++++++++++-------------------------- converter/converter.go | 24 +++++------- converter/pdf/pdf.go | 34 ++++------------- converter/plain/plain.go | 52 +++---------------------- converter/zip/zip.go | 41 +++++--------------- history/history.go | 9 ++--- installer/api.go | 5 +-- provider/custom/loader.go | 5 +-- source/chapter.go | 26 ++++++++++++- source/manga.go | 30 +++++++++++++++ source/page.go | 11 +++++- util/util.go | 13 +++++-- where/where.go | 25 +++--------- 16 files changed, 155 insertions(+), 219 deletions(-) create mode 100644 constant/formats.go diff --git a/cmd/gen.go b/cmd/gen.go index 3faa6fd5..23fd4a79 100644 --- a/cmd/gen.go +++ b/cmd/gen.go @@ -6,7 +6,6 @@ import ( "github.com/metafates/mangal/util" "github.com/metafates/mangal/where" "github.com/samber/lo" - "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/spf13/viper" "os" @@ -86,9 +85,7 @@ var genCmd = &cobra.Command{ return err } - defer func(f afero.File) { - _ = f.Close() - }(f) + util.Ignore(f.Close) err = tmpl.Execute(f, s) if err != nil { diff --git a/cmd/version.go b/cmd/version.go index 06bbd159..d7e1b4d4 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -3,8 +3,8 @@ package cmd import ( "encoding/json" "github.com/metafates/mangal/constant" + "github.com/metafates/mangal/util" "github.com/spf13/cobra" - "io" "net/http" ) @@ -32,9 +32,7 @@ var versionLatestCmd = &cobra.Command{ return err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(resp.Body) + defer util.Ignore(resp.Body.Close) var release struct { TagName string `json:"tag_name"` diff --git a/constant/formats.go b/constant/formats.go new file mode 100644 index 00000000..c1fc70d0 --- /dev/null +++ b/constant/formats.go @@ -0,0 +1,8 @@ +package constant + +const ( + Plain = "plain" + CBZ = "cbz" + PDF = "pdf" + ZIP = "zip" +) diff --git a/converter/cbz/cbz.go b/converter/cbz/cbz.go index 3baed55f..adc8edbc 100644 --- a/converter/cbz/cbz.go +++ b/converter/cbz/cbz.go @@ -2,16 +2,13 @@ package cbz import ( "archive/zip" - "fmt" - "github.com/metafates/mangal/constant" + "bytes" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/source" "github.com/metafates/mangal/util" - "github.com/metafates/mangal/where" - "github.com/spf13/afero" + "github.com/samber/lo" "io" - "path/filepath" - "strings" + "text/template" ) type CBZ struct{} @@ -28,69 +25,46 @@ func (*CBZ) SaveTemp(chapter *source.Chapter) (string, error) { return save(chapter, true) } -func save(chapter *source.Chapter, temp bool) (string, error) { - - var ( - mangaDir string - err error - ) - - if temp { - mangaDir, err = filesystem.Get().TempDir("", constant.TempPrefix) - } else { - mangaDir = where.Manga(chapter.Manga.Name) - } - +func save(chapter *source.Chapter, temp bool) (path string, err error) { + path, err = chapter.Path(temp) if err != nil { - return "", err + return } - chapterCbz := filepath.Join(mangaDir, util.SanitizeFilename(chapter.FormattedName())+".cbz") - cbzFile, err := filesystem.Get().Create(chapterCbz) + cbzFile, err := filesystem.Get().Create(path) if err != nil { - return "", err + return } - defer func(cbzFile afero.File) { - _ = cbzFile.Close() - }(cbzFile) + defer util.Ignore(cbzFile.Close) zipWriter := zip.NewWriter(cbzFile) - defer func(zipWriter *zip.Writer) { - _ = zipWriter.Close() - }(zipWriter) + defer util.Ignore(zipWriter.Close) for _, page := range chapter.Pages { - pageName := fmt.Sprintf("%d%s", page.Index, page.Extension) - pageName = util.PadZero(pageName, 10) - - if err = addToZip(zipWriter, page.Contents, pageName); err != nil { - return "", err + if err = addToZip(zipWriter, page.Contents, page.Filename()); err != nil { + return } } - err = addToZip(zipWriter, strings.NewReader(comicInfo(chapter)), "ComicInfo.xml") - if err != nil { - return "", err - } - - absPath, err := filepath.Abs(chapterCbz) - if err != nil { - return chapterCbz, nil - } - - return absPath, nil + err = addToZip(zipWriter, comicInfo(chapter), "ComicInfo.xml") + return } -func comicInfo(chapter *source.Chapter) string { - return ` - - ` + chapter.Name + ` - ` + chapter.Manga.Name + ` - Web Comic - ` + chapter.Manga.URL + ` - YesAndRightToLeft +func comicInfo(chapter *source.Chapter) *bytes.Buffer { + t := ` + {{ .Name }} + {{ .Manga.Name }} + Web Comic + {{ .Manga.URL }} + YesAndRightToLeft ` + + parsed := lo.Must(template.New("ComicInfo").Parse(t)) + buf := bytes.NewBufferString("") + lo.Must0(parsed.Execute(buf, chapter)) + + return buf } func addToZip(writer *zip.Writer, file io.Reader, name string) error { diff --git a/converter/converter.go b/converter/converter.go index 5d54a474..da0e70e6 100644 --- a/converter/converter.go +++ b/converter/converter.go @@ -2,6 +2,7 @@ package converter import ( "fmt" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/converter/cbz" "github.com/metafates/mangal/converter/pdf" "github.com/metafates/mangal/converter/plain" @@ -15,27 +16,20 @@ type Converter interface { SaveTemp(chapter *source.Chapter) (string, error) } -const ( - Plain = "plain" - CBZ = "cbz" - PDF = "pdf" - ZIP = "zip" -) - var converters = map[string]Converter{ - Plain: plain.New(), - CBZ: cbz.New(), - PDF: pdf.New(), - ZIP: zip.New(), + constant.Plain: plain.New(), + constant.CBZ: cbz.New(), + constant.PDF: pdf.New(), + constant.ZIP: zip.New(), } // Available returns a list of available converters. func Available() []string { return []string{ - Plain, - CBZ, - PDF, - ZIP, + constant.Plain, + constant.CBZ, + constant.PDF, + constant.ZIP, } } diff --git a/converter/pdf/pdf.go b/converter/pdf/pdf.go index 21b7f78e..5dd7f61c 100644 --- a/converter/pdf/pdf.go +++ b/converter/pdf/pdf.go @@ -5,14 +5,11 @@ import ( "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/source" "github.com/metafates/mangal/util" - "github.com/metafates/mangal/where" "github.com/pdfcpu/pdfcpu/pkg/api" "github.com/pdfcpu/pdfcpu/pkg/log" "github.com/pdfcpu/pdfcpu/pkg/pdfcpu" - "github.com/spf13/afero" "github.com/spf13/viper" "io" - "path/filepath" ) type PDF struct{} @@ -29,31 +26,18 @@ func (*PDF) SaveTemp(chapter *source.Chapter) (string, error) { return save(chapter, true) } -func save(chapter *source.Chapter, temp bool) (string, error) { - var ( - mangaDir string - err error - ) - - if temp { - mangaDir, err = filesystem.Get().TempDir("", constant.TempPrefix) - } else { - mangaDir = where.Manga(chapter.Manga.Name) - } - +func save(chapter *source.Chapter, temp bool) (path string, err error) { + path, err = chapter.Path(temp) if err != nil { - return "", err + return } - chapterPdf := filepath.Join(mangaDir, util.SanitizeFilename(chapter.FormattedName())+".pdf") - pdfFile, err := filesystem.Get().Create(chapterPdf) + pdfFile, err := filesystem.Get().Create(path) if err != nil { - return "", err + return } - defer func(pdfFile afero.File) { - _ = pdfFile.Close() - }(pdfFile) + defer util.Ignore(pdfFile.Close) var readers = make([]io.Reader, len(chapter.Pages)) for i, page := range chapter.Pages { @@ -61,11 +45,7 @@ func save(chapter *source.Chapter, temp bool) (string, error) { } err = imagesToPDF(pdfFile, readers) - if err != nil { - return "", err - } - - return chapterPdf, nil + return } // imagesToPDF will convert images to PDF and write to w diff --git a/converter/plain/plain.go b/converter/plain/plain.go index 1235b2eb..d2be502c 100644 --- a/converter/plain/plain.go +++ b/converter/plain/plain.go @@ -1,14 +1,9 @@ package plain import ( - "fmt" - "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/source" - "github.com/metafates/mangal/util" - "github.com/metafates/mangal/where" "io" - "os" "path/filepath" "sync" ) @@ -27,20 +22,10 @@ func (*Plain) SaveTemp(chapter *source.Chapter) (string, error) { return save(chapter, true) } -func save(chapter *source.Chapter, temp bool) (string, error) { - var ( - chapterDir string - err error - ) - - if temp { - chapterDir, err = filesystem.Get().TempDir("", constant.TempPrefix) - } else { - chapterDir, err = prepareChapterDir(chapter) - } - +func save(chapter *source.Chapter, temp bool) (path string, err error) { + path, err = chapter.Path(temp) if err != nil { - return "", err + return } wg := sync.WaitGroup{} @@ -53,41 +38,16 @@ func save(chapter *source.Chapter, temp bool) (string, error) { return } - err = savePage(page, chapterDir) + err = savePage(page, path) }(page) } wg.Wait() - - if err != nil { - return "", err - } - - abs, err := filepath.Abs(chapterDir) - if err != nil { - return chapterDir, nil - } - - return abs, nil -} - -// prepareMangaDir will create manga direcotry if it doesn't exist -func prepareChapterDir(chapter *source.Chapter) (chapterDir string, err error) { - path := where.Manga(chapter.Manga.Name) - chapterDir = filepath.Join(path, util.SanitizeFilename(chapter.FormattedName())) - - if err = filesystem.Get().MkdirAll(chapterDir, os.ModePerm); err != nil { - return "", err - } - - return chapterDir, nil + return } func savePage(page *source.Page, to string) error { - pageName := fmt.Sprintf("%d%s", page.Index, page.Extension) - pageName = util.PadZero(pageName, 10) - - file, err := filesystem.Get().Create(filepath.Join(to, pageName)) + file, err := filesystem.Get().Create(filepath.Join(to, page.Filename())) if err != nil { return err } diff --git a/converter/zip/zip.go b/converter/zip/zip.go index 4662b340..b53f43a7 100644 --- a/converter/zip/zip.go +++ b/converter/zip/zip.go @@ -2,15 +2,10 @@ package zip import ( "archive/zip" - "fmt" - "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/source" "github.com/metafates/mangal/util" - "github.com/metafates/mangal/where" - "github.com/spf13/afero" "io" - "path/filepath" "time" ) @@ -28,47 +23,29 @@ func (*ZIP) SaveTemp(chapter *source.Chapter) (string, error) { return save(chapter, true) } -func save(chapter *source.Chapter, temp bool) (string, error) { - var ( - mangaDir string - err error - ) - - if temp { - mangaDir, err = filesystem.Get().TempDir("", constant.TempPrefix) - } else { - mangaDir = where.Manga(chapter.Manga.Name) - } - +func save(chapter *source.Chapter, temp bool) (path string, err error) { + path, err = chapter.Path(temp) if err != nil { - return "", err + return } - chapterZip := filepath.Join(mangaDir, util.SanitizeFilename(chapter.FormattedName())+".zip") - zipFile, err := filesystem.Get().Create(chapterZip) + zipFile, err := filesystem.Get().Create(path) if err != nil { - return "", err + return } - defer func(zipFile afero.File) { - _ = zipFile.Close() - }(zipFile) + defer util.Ignore(zipFile.Close) zipWriter := zip.NewWriter(zipFile) - defer func() { - _ = zipWriter.Close() - }() + defer util.Ignore(zipWriter.Close) for _, page := range chapter.Pages { - pageName := fmt.Sprintf("%d%s", page.Index, page.Extension) - pageName = util.PadZero(pageName, 10) - - if err = addToZip(zipWriter, page.Contents, pageName); err != nil { + if err = addToZip(zipWriter, page.Contents, page.Filename()); err != nil { return "", err } } - return chapterZip, nil + return } func addToZip(writer *zip.Writer, file io.Reader, name string) error { diff --git a/history/history.go b/history/history.go index 7955aaae..95d72ce7 100644 --- a/history/history.go +++ b/history/history.go @@ -30,27 +30,26 @@ func (c *SavedChapter) String() string { } // Get returns all chapters from the history file -func Get() (map[string]*SavedChapter, error) { +func Get() (chapters map[string]*SavedChapter, err error) { log.Info("Getting history location") historyFile := where.History() // decode json into slice of structs log.Info("Reading history file") - var chapters map[string]*SavedChapter contents, err := filesystem.Get().ReadFile(historyFile) if err != nil { log.Error(err) - return nil, err + return } log.Info("Decoding history from json") err = json.Unmarshal(contents, &chapters) if err != nil { log.Error(err) - return nil, err + return } - return chapters, nil + return } // Save saves the chapter to the history file diff --git a/installer/api.go b/installer/api.go index 9dfade3a..f9710a2c 100644 --- a/installer/api.go +++ b/installer/api.go @@ -3,6 +3,7 @@ package installer import ( "encoding/json" "fmt" + "github.com/metafates/mangal/util" "io" "net/http" ) @@ -44,9 +45,7 @@ func (g *githubFilesCollector) collect() error { return err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer util.Ignore(res.Body.Close) err = json.Unmarshal(r, g) if err != nil { diff --git a/provider/custom/loader.go b/provider/custom/loader.go index c0e41864..0212670b 100644 --- a/provider/custom/loader.go +++ b/provider/custom/loader.go @@ -6,7 +6,6 @@ import ( "github.com/metafates/mangal/luamodules" "github.com/metafates/mangal/source" "github.com/metafates/mangal/util" - "github.com/spf13/afero" lua "github.com/yuin/gopher-lua" "github.com/yuin/gopher-lua/parse" ) @@ -58,9 +57,7 @@ func Compile(path string) (*lua.FunctionProto, error) { return nil, err } - defer func(file afero.File) { - _ = file.Close() - }(file) + defer util.Ignore(file.Close) chunk, err := parse.Parse(file, path) diff --git a/source/chapter.go b/source/chapter.go index 84b4b26f..955c37f6 100644 --- a/source/chapter.go +++ b/source/chapter.go @@ -6,6 +6,7 @@ import ( "github.com/metafates/mangal/constant" "github.com/metafates/mangal/util" "github.com/spf13/viper" + "path/filepath" "strings" "sync" ) @@ -62,8 +63,8 @@ func (c *Chapter) DownloadPages() error { return err } -// FormattedName of the chapter according to the template in the config. -func (c *Chapter) FormattedName() (name string) { +// formattedName of the chapter according to the template in the config. +func (c *Chapter) formattedName() (name string) { template := viper.GetString(constant.DownloaderChapterNameTemplate) name = strings.ReplaceAll(template, "{manga}", c.Manga.Name) name = strings.ReplaceAll(name, "{chapter}", c.Name) @@ -92,3 +93,24 @@ func (c *Chapter) SizeHuman() string { return humanize.Bytes(size) } } + +func (c *Chapter) Filename() string { + filename := util.SanitizeFilename(c.formattedName()) + extension := "" + + if f := viper.GetString(constant.FormatsUse); f != constant.Plain { + extension = "." + f + } + + return filename + extension +} + +func (c *Chapter) Path(temp bool) (path string, err error) { + path, err = c.Manga.Path(temp) + if err != nil { + return + } + + path = filepath.Join(path, c.Filename()) + return +} \ No newline at end of file diff --git a/source/manga.go b/source/manga.go index ca62b130..0659b9f4 100644 --- a/source/manga.go +++ b/source/manga.go @@ -1,5 +1,15 @@ package source +import ( + "github.com/metafates/mangal/constant" + "github.com/metafates/mangal/filesystem" + "github.com/metafates/mangal/util" + "github.com/metafates/mangal/where" + "github.com/spf13/viper" + "os" + "path/filepath" +) + // Manga is a manga from a source. type Manga struct { // Name of the manga @@ -19,3 +29,23 @@ type Manga struct { func (m *Manga) String() string { return m.Name } + +func (m *Manga) Filename() string { + return util.SanitizeFilename(m.Name) +} + +func (m *Manga) Path(temp bool) (path string, err error) { + if temp { + return filesystem.Get().TempDir("", constant.TempPrefix) + } + + path = where.Downloads() + + if viper.GetBool(constant.DownloaderCreateMangaDir) { + path = filepath.Join(path, m.Filename()) + } + + _ = filesystem.Get().MkdirAll(path, os.ModePerm) + + return +} diff --git a/source/page.go b/source/page.go index 3b868c81..ac673237 100644 --- a/source/page.go +++ b/source/page.go @@ -2,7 +2,9 @@ package source import ( "errors" + "fmt" "github.com/metafates/mangal/constant" + "github.com/metafates/mangal/util" "github.com/samber/lo" "io" "net/http" @@ -32,7 +34,7 @@ func (p *Page) Download() error { return nil } - req, err := http.NewRequest("GET", p.URL, nil) + req, err := http.NewRequest(http.MethodGet, p.URL, nil) if err != nil { return err } @@ -72,3 +74,10 @@ func (p *Page) Read(b []byte) (int, error) { return p.Contents.Read(b) } + +func (p *Page) Filename() string { + filename := fmt.Sprintf("%d%s", p.Index, p.Extension) + filename = util.PadZero(filename, 10) + + return filename +} diff --git a/util/util.go b/util/util.go index 57e8753b..50257e9c 100644 --- a/util/util.go +++ b/util/util.go @@ -98,17 +98,22 @@ func ClearScreen() { } } -// ReGroups parses url with the given regular expression and returns the +// ReGroups parses the string with the given regular expression and returns the // group values defined in the expression. -func ReGroups(pattern *regexp.Regexp, str string) map[string]string { +func ReGroups(pattern *regexp.Regexp, str string) (groups map[string]string) { match := pattern.FindStringSubmatch(str) - groups := make(map[string]string) for i, name := range pattern.SubexpNames() { if i > 0 && i <= len(match) { groups[name] = match[i] } } - return groups + + return +} + +// Ignore calls function and explicitely ignores error +func Ignore(f func() error) { + _ = f() } diff --git a/where/where.go b/where/where.go index abdade12..85942837 100644 --- a/where/where.go +++ b/where/where.go @@ -3,7 +3,6 @@ package where import ( "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" - "github.com/metafates/mangal/util" "github.com/samber/lo" "github.com/spf13/viper" "os" @@ -23,8 +22,7 @@ func mkdir(path string) string { func Config() string { var path string - customDir, present := os.LookupEnv(EnvConfigPath) - if present { + if customDir, present := os.LookupEnv(EnvConfigPath); present { path = customDir } else { path = filepath.Join(lo.Must(os.UserConfigDir()), constant.Mangal) @@ -58,26 +56,15 @@ func History() string { return path } +// Downloads path func Downloads() string { path, err := filepath.Abs(viper.GetString(constant.DownloaderPath)) if err != nil { - path = "." - } - - return mkdir(path) -} - -func Manga(mangaName string) string { - var path string - - if viper.GetBool(constant.DownloaderCreateMangaDir) { - path = filepath.Join( - Downloads(), - util.SanitizeFilename(mangaName), - ) - } else { - path = Downloads() + path, err = os.Getwd() + if err != nil { + path = "." + } } return mkdir(path) From 90efff7a44c20ebc96cb82d715fe0fa9b2278543 Mon Sep 17 00:00:00 2001 From: metafates Date: Fri, 26 Aug 2022 14:00:45 +0300 Subject: [PATCH 23/51] fix(tui): handle case where history is empty --- tui/keymap.go | 2 +- tui/update.go | 31 ++++++++++++++++--------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/tui/keymap.go b/tui/keymap.go index 886c5f24..299493e1 100644 --- a/tui/keymap.go +++ b/tui/keymap.go @@ -134,7 +134,7 @@ func (k *statefulKeymap) help() ([]key.Binding, []key.Binding) { case loadingState: return to2(h(k.forceQuit, k.back)) case historyState: - return to2(h(k.selectOne, k.remove, k.back, k.openURL)) + return to2(h(k.confirm, k.remove, k.back, k.openURL)) case sourcesState: return to2(h(k.confirm)) case searchState: diff --git a/tui/update.go b/tui/update.go index 23b91823..99087a81 100644 --- a/tui/update.go +++ b/tui/update.go @@ -263,24 +263,25 @@ func (b *statefulBubble) updateHistory(msg tea.Msg) (tea.Model, tea.Cmd) { return b, cmd } case key.Matches(msg, b.keymap.selectOne, b.keymap.confirm): - selected := b.historyC.SelectedItem().(*listItem).internal.(*history.SavedChapter) - providers := lo.Map(b.sourcesC.Items(), func(i list.Item, _ int) *provider.Provider { - return i.(*listItem).internal.(*provider.Provider) - }) - - p, ok := lo.Find(providers, func(p *provider.Provider) bool { - return p.ID == selected.SourceID - }) + if b.historyC.SelectedItem() != nil { + selected := b.historyC.SelectedItem().(*listItem).internal.(*history.SavedChapter) + providers := lo.Map(b.sourcesC.Items(), func(i list.Item, _ int) *provider.Provider { + return i.(*listItem).internal.(*provider.Provider) + }) - if !ok { - err := fmt.Errorf("provider %s not found", selected.SourceID) - b.raiseError(err) - return b, nil - } + p, ok := lo.Find(providers, func(p *provider.Provider) bool { + return p.ID == selected.SourceID + }) - b.newState(loadingState) - return b, tea.Batch(b.startLoading(), b.loadSource(p), b.waitForSourceLoaded()) + if !ok { + err := fmt.Errorf("provider %s not found", selected.SourceID) + b.raiseError(err) + return b, nil + } + b.newState(loadingState) + return b, tea.Batch(b.startLoading(), b.loadSource(p), b.waitForSourceLoaded()) + } } } From ed4e67bbd7b048693b25144aa1b637fbc05faacf Mon Sep 17 00:00:00 2001 From: metafates Date: Fri, 26 Aug 2022 14:02:29 +0300 Subject: [PATCH 24/51] build: bump version --- constant/constant.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constant/constant.go b/constant/constant.go index a85dc42d..7f58e3c6 100644 --- a/constant/constant.go +++ b/constant/constant.go @@ -2,7 +2,7 @@ package constant const ( Mangal = "mangal" - Version = "3.4.2" + Version = "3.5.0" UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" ) From 9bb9e0fbb6d5e492c805fa8906bd728db78a97e2 Mon Sep 17 00:00:00 2001 From: metafates Date: Fri, 26 Aug 2022 14:04:14 +0300 Subject: [PATCH 25/51] docs(changelog): update --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 280897ca..9aece55b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this - Add `--raw` flag for the `sources` command to print without headers - Add `--downloads` flag for the `where` command to print location of the downloads directory - `gen` command added to generate a template for custom source -- Show chapter index in the tui history list +- Show chapter index in the TUI history list +- Fixed bug where pressing confirm button with empty history would cause mangal to crash ## 3.4.1 From b1f80aa3c29ce65788685537083c5fe26e11fcbf Mon Sep 17 00:00:00 2001 From: metafates Date: Fri, 26 Aug 2022 14:25:37 +0300 Subject: [PATCH 26/51] fix(tui): wrap at screen width at error view --- tui/view.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tui/view.go b/tui/view.go index 3cad4434..75fcf2cb 100644 --- a/tui/view.go +++ b/tui/view.go @@ -167,10 +167,8 @@ func (b *statefulBubble) viewError() string { "", icon.Get(icon.Fail) + " Uggh, something went wrong. Maybe try again?", "", - style.Italic(util.Wrap(b.errorPlot, b.width)), - "", }, - strings.Split(errorMsg, "\n")..., + strings.Split(util.Wrap(style.Italic(b.errorPlot), b.width)+"\n\n"+errorMsg, "\n")..., ), ) } From 709eee11317c97f8ad40427d7ac32ceb8313d367 Mon Sep 17 00:00:00 2001 From: metafates Date: Fri, 26 Aug 2022 15:23:28 +0300 Subject: [PATCH 27/51] refactor(cmd): better error handling --- cmd/config.go | 10 ++++----- cmd/gen.go | 16 ++++---------- cmd/inline.go | 18 ++++++---------- cmd/install.go | 4 ++-- cmd/integration.go | 52 +++++++++++++--------------------------------- cmd/mini.go | 12 +++-------- cmd/root.go | 20 +++++++++++++----- cmd/run.go | 8 +------ cmd/sources.go | 4 +--- cmd/version.go | 12 ++++------- 10 files changed, 55 insertions(+), 101 deletions(-) diff --git a/cmd/config.go b/cmd/config.go index a28c6a9e..aa7d0e9d 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -29,27 +29,25 @@ var configInitCmd = &cobra.Command{ Use: "init", Short: "Initialize config", Long: `Initialize default config`, - RunE: func(cmd *cobra.Command, args []string) error { + Run: func(cmd *cobra.Command, args []string) { mangalDir := where.Config() if !lo.Must(filesystem.Get().Exists(mangalDir)) { _ = filesystem.Get().MkdirAll(mangalDir, os.ModePerm) } - return viper.SafeWriteConfig() + handleErr(viper.SafeWriteConfig()) }, } var configRemoveCmd = &cobra.Command{ Use: "remove", Short: "Removes config file", - RunE: func(cmd *cobra.Command, args []string) error { + Run: func(cmd *cobra.Command, args []string) { mangalDir := where.Config() configPath := filepath.Join(mangalDir, constant.Mangal+".toml") if lo.Must(filesystem.Get().Exists(configPath)) { - return filesystem.Get().Remove(configPath) + handleErr(filesystem.Get().Remove(configPath)) } - - return nil }, } diff --git a/cmd/gen.go b/cmd/gen.go index 23fd4a79..9e99430a 100644 --- a/cmd/gen.go +++ b/cmd/gen.go @@ -29,7 +29,7 @@ var genCmd = &cobra.Command{ Use: "gen", Short: "Generate a new lua source", Long: `Generate a new lua source.`, - RunE: func(cmd *cobra.Command, args []string) error { + Run: func(cmd *cobra.Command, args []string) { cmd.SetOut(os.Stdout) author := viper.GetString(constant.GenAuthor) @@ -74,25 +74,17 @@ var genCmd = &cobra.Command{ } tmpl, err := template.New("source").Funcs(funcMap).Parse(constant.SourceTemplate) - - if err != nil { - return err - } + handleErr(err) target := filepath.Join(where.Sources(), util.SanitizeFilename(s.Name)+".lua") f, err := filesystem.Get().Create(target) - if err != nil { - return err - } + handleErr(err) util.Ignore(f.Close) err = tmpl.Execute(f, s) - if err != nil { - return err - } + handleErr(err) cmd.Println(target) - return nil }, } diff --git a/cmd/inline.go b/cmd/inline.go index e13812ec..02b8f3a2 100644 --- a/cmd/inline.go +++ b/cmd/inline.go @@ -42,27 +42,21 @@ Chapter selectors: @[substring]@ - select chapters by name substring`, Example: "mangal inline --source Manganelo --query \"death note\" --manga first --chapters \"@Vol.1 @\" -d", - RunE: func(cmd *cobra.Command, args []string) error { + Run: func(cmd *cobra.Command, args []string) { sourceName := lo.Must(cmd.Flags().GetString("source")) p, ok := provider.Get(sourceName) if !ok { - return fmt.Errorf("source not found: %s", sourceName) + handleErr(fmt.Errorf("source not found: %s", sourceName)) } src, err := p.CreateSource() - if err != nil { - return err - } + handleErr(err) mangaPicker, err := inline.ParseMangaPicker(lo.Must(cmd.Flags().GetString("manga"))) - if err != nil { - return err - } + handleErr(err) chapterFilter, err := inline.ParseChaptersFilter(lo.Must(cmd.Flags().GetString("chapters"))) - if err != nil { - return err - } + handleErr(err) options := &inline.Options{ Source: src, @@ -72,6 +66,6 @@ Chapter selectors: ChapterFilter: chapterFilter, } - return inline.Run(options) + handleErr(inline.Run(options)) }, } diff --git a/cmd/install.go b/cmd/install.go index ea984e6b..37c513c9 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -14,7 +14,7 @@ var installCmd = &cobra.Command{ Short: "Browse and install custom scrapers", Long: `Browse and install custom scrapers from official GitHub repo. https://github.com/metafates/mangal-scrapers`, - RunE: func(cmd *cobra.Command, args []string) error { - return tui.Run(&tui.Options{Install: true}) + Run: func(cmd *cobra.Command, args []string) { + handleErr(tui.Run(&tui.Options{Install: true})) }, } diff --git a/cmd/integration.go b/cmd/integration.go index 8ef5b92b..88ab5360 100644 --- a/cmd/integration.go +++ b/cmd/integration.go @@ -28,14 +28,14 @@ var integrationAnilistCmd = &cobra.Command{ Short: "Integration with Anilist", Long: `Integration with Anilist. See https://github.com/metafates/mangal/wiki/Anilist-Integration for more information`, - RunE: func(cmd *cobra.Command, args []string) error { + Run: func(cmd *cobra.Command, args []string) { if lo.Must(cmd.Flags().GetBool("disable")) { viper.Set(constant.AnilistEnable, false) viper.Set(constant.AnilistCode, "") viper.Set(constant.AnilistSecret, "") viper.Set(constant.AnilistID, "") log.Info("Anilist integration disabled") - return viper.WriteConfig() + handleErr(viper.WriteConfig()) } if !viper.GetBool(constant.AnilistEnable) { @@ -45,13 +45,10 @@ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more inform } var response bool err := survey.AskOne(&confirm, &response) - if err != nil { - log.Error(err) - return err - } + handleErr(err) if !response { - return nil + return } viper.Set(constant.AnilistEnable, response) @@ -60,12 +57,10 @@ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more inform switch err.(type) { case viper.ConfigFileNotFoundError: err = viper.SafeWriteConfig() - if err != nil { - return err - } + handleErr(err) default: + handleErr(err) log.Error(err) - return err } } } @@ -77,20 +72,15 @@ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more inform } var response string err := survey.AskOne(&input, &response) - if err != nil { - return err - } + handleErr(err) if response == "" { - return nil + return } viper.Set(constant.AnilistID, response) err = viper.WriteConfig() - if err != nil { - log.Error(err) - return err - } + handleErr(err) } if viper.GetString(constant.AnilistSecret) == "" { @@ -100,20 +90,15 @@ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more inform } var response string err := survey.AskOne(&input, &response) - if err != nil { - return err - } + handleErr(err) if response == "" { - return nil + return } viper.Set(constant.AnilistSecret, response) err = viper.WriteConfig() - if err != nil { - log.Error(err) - return err - } + handleErr(err) } if viper.GetString(constant.AnilistCode) == "" { @@ -124,22 +109,15 @@ See https://github.com/metafates/mangal/wiki/Anilist-Integration for more inform } var response string err := survey.AskOne(&input, &response) - if err != nil { - return err - } + handleErr(err) if response == "" { - return nil + return } viper.Set(constant.AnilistCode, response) err = viper.WriteConfig() - if err != nil { - log.Error(err) - return err - } + handleErr(err) } - - return nil }, } diff --git a/cmd/mini.go b/cmd/mini.go index 0d7d31b4..7cadcb00 100644 --- a/cmd/mini.go +++ b/cmd/mini.go @@ -20,21 +20,15 @@ var miniCmd = &cobra.Command{ Short: "Launch in the mini mode", Long: `Launch mangal in the mini mode. Will try to mimic ani-cli.`, - RunE: func(cmd *cobra.Command, args []string) error { + Run: func(cmd *cobra.Command, args []string) { options := mini.Options{ Download: lo.Must(cmd.Flags().GetBool("download")), Continue: lo.Must(cmd.Flags().GetBool("continue")), } err := mini.Run(&options) - if err != nil { - if err.Error() == "interrupt" { - return nil - } - - return err + if err != nil && err.Error() != "interrupt" { + handleErr(err) } - - return nil }, } diff --git a/cmd/root.go b/cmd/root.go index 1fd0fcd3..35cf8ead 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -6,6 +6,7 @@ import ( "github.com/metafates/mangal/constant" "github.com/metafates/mangal/converter" "github.com/metafates/mangal/icon" + "github.com/metafates/mangal/log" "github.com/metafates/mangal/provider" "github.com/metafates/mangal/style" "github.com/metafates/mangal/tui" @@ -13,6 +14,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" "os" + "strings" ) func init() { @@ -48,17 +50,17 @@ func init() { // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ - Use: constant.Mangal, - Short: "The ultimate manga downloader", + Use: constant.Mangal, + Version: constant.Version, + Short: "The ultimate manga downloader", Long: style.Combined(style.Yellow, style.Bold)(constant.AssciiArtLogo) + "\n" + style.Combined(style.HiRed, style.Italic)(" - The ultimate cli manga downloader"), - RunE: func(cmd *cobra.Command, args []string) error { + Run: func(cmd *cobra.Command, args []string) { options := tui.Options{ Continue: lo.Must(cmd.Flags().GetBool("continue")), } - return tui.Run(&options) + handleErr(tui.Run(&options)) }, - Version: constant.Version, } // Execute adds all child commands to the root command and sets flags appropriately. @@ -79,3 +81,11 @@ func Execute() { os.Exit(1) } } + +func handleErr(err error) { + if err != nil { + log.Error(err) + _, _ = fmt.Fprintf(os.Stderr, "%s %s\n", icon.Get(icon.Fail), strings.Trim(err.Error(), " \n")) + os.Exit(1) + } +} diff --git a/cmd/run.go b/cmd/run.go index e27f68bd..fafe3e66 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -1,12 +1,9 @@ package cmd import ( - "fmt" - "github.com/metafates/mangal/icon" "github.com/metafates/mangal/provider/custom" "github.com/samber/lo" "github.com/spf13/cobra" - "os" ) func init() { @@ -27,9 +24,6 @@ Or you can use mangal as a standalone lua interpreter.`, // LoadSource runs file when it's loaded _, err := custom.LoadSource(sourcePath, !lo.Must(cmd.Flags().GetBool("lenient"))) - if err != nil { - fmt.Println(icon.Get(icon.Fail) + " " + err.Error()) - os.Exit(1) - } + handleErr(err) }, } diff --git a/cmd/sources.go b/cmd/sources.go index 7f3fecd2..fb573f6d 100644 --- a/cmd/sources.go +++ b/cmd/sources.go @@ -18,7 +18,7 @@ var sourcesCmd = &cobra.Command{ Use: "sources", Short: "List an available sources", Example: "mangal sources", - RunE: func(cmd *cobra.Command, args []string) error { + Run: func(cmd *cobra.Command, args []string) { cmd.SetOut(os.Stdout) printHeader := !lo.Must(cmd.Flags().GetBool("raw")) @@ -41,7 +41,5 @@ var sourcesCmd = &cobra.Command{ for name := range provider.CustomProviders() { cmd.Println(name) } - - return nil }, } diff --git a/cmd/version.go b/cmd/version.go index d7e1b4d4..aca08cd8 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -26,11 +26,9 @@ var versionLatestCmd = &cobra.Command{ Use: "latest", Short: "Print the latest version number of the mangal", Long: `It will fetch the latest version from the github and print it`, - RunE: func(cmd *cobra.Command, args []string) error { + Run: func(cmd *cobra.Command, args []string) { resp, err := http.Get("https://api.github.com/repos/metafates/mangal/releases/latest") - if err != nil { - return err - } + handleErr(err) defer util.Ignore(resp.Body.Close) @@ -38,14 +36,12 @@ var versionLatestCmd = &cobra.Command{ TagName string `json:"tag_name"` } - if err := json.NewDecoder(resp.Body).Decode(&release); err != nil { - return err - } + err = json.NewDecoder(resp.Body).Decode(&release) + handleErr(err) // remove the v from the tag name latestVersion := release.TagName[1:] cmd.Println("mangal latest version is " + latestVersion) - return nil }, } From 0c010cc9d827bbad9baeb6f42db4760014262061 Mon Sep 17 00:00:00 2001 From: metafates Date: Fri, 26 Aug 2022 15:40:03 +0300 Subject: [PATCH 28/51] fix(cmd): fix gen cmd --- CHANGELOG.md | 1 + cmd/gen.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9aece55b..d71811d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this - `gen` command added to generate a template for custom source - Show chapter index in the TUI history list - Fixed bug where pressing confirm button with empty history would cause mangal to crash +- Fixed bug where error message would not fit the screen ## 3.4.1 diff --git a/cmd/gen.go b/cmd/gen.go index 9e99430a..1f32ab56 100644 --- a/cmd/gen.go +++ b/cmd/gen.go @@ -80,7 +80,7 @@ var genCmd = &cobra.Command{ f, err := filesystem.Get().Create(target) handleErr(err) - util.Ignore(f.Close) + defer util.Ignore(f.Close) err = tmpl.Execute(f, s) handleErr(err) From a6b2491440f6f2f733bc29663941abb2a62e8108 Mon Sep 17 00:00:00 2001 From: metafates Date: Fri, 26 Aug 2022 17:24:15 +0300 Subject: [PATCH 29/51] fix(plain): create chapter dir --- converter/cbz/cbz_test.go | 3 +++ converter/pdf/pdf_test.go | 3 +++ converter/plain/plain.go | 6 ++++++ converter/plain/plain_test.go | 1 + converter/zip/zip_test.go | 3 +++ icon/icon_test.go | 12 ++++++------ source/chapter.go | 13 ++++++------- source/manga.go | 12 +++++++++--- 8 files changed, 37 insertions(+), 16 deletions(-) diff --git a/converter/cbz/cbz_test.go b/converter/cbz/cbz_test.go index 93562fbc..4645fe12 100644 --- a/converter/cbz/cbz_test.go +++ b/converter/cbz/cbz_test.go @@ -4,10 +4,12 @@ import ( "archive/zip" "bytes" "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/source" "github.com/samber/lo" . "github.com/smartystreets/goconvey/convey" + "github.com/spf13/viper" "io" "io/fs" "path/filepath" @@ -17,6 +19,7 @@ import ( func init() { filesystem.SetMemMapFs() lo.Must0(config.Setup()) + viper.Set(constant.FormatsUse, constant.CBZ) } func TestCBZ(t *testing.T) { diff --git a/converter/pdf/pdf_test.go b/converter/pdf/pdf_test.go index e238712d..e44e99ac 100644 --- a/converter/pdf/pdf_test.go +++ b/converter/pdf/pdf_test.go @@ -3,10 +3,12 @@ package pdf import ( "bytes" "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/source" "github.com/samber/lo" . "github.com/smartystreets/goconvey/convey" + "github.com/spf13/viper" "io" "io/fs" "path/filepath" @@ -16,6 +18,7 @@ import ( func init() { filesystem.SetMemMapFs() lo.Must0(config.Setup()) + viper.Set(constant.FormatsUse, constant.PDF) } func TestPDF(t *testing.T) { diff --git a/converter/plain/plain.go b/converter/plain/plain.go index d2be502c..b03f1ff9 100644 --- a/converter/plain/plain.go +++ b/converter/plain/plain.go @@ -4,6 +4,7 @@ import ( "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/source" "io" + "os" "path/filepath" "sync" ) @@ -28,6 +29,11 @@ func save(chapter *source.Chapter, temp bool) (path string, err error) { return } + err = filesystem.Get().Mkdir(path, os.ModePerm) + if err != nil { + return + } + wg := sync.WaitGroup{} wg.Add(len(chapter.Pages)) for _, page := range chapter.Pages { diff --git a/converter/plain/plain_test.go b/converter/plain/plain_test.go index 5665f4bd..3cc6f853 100644 --- a/converter/plain/plain_test.go +++ b/converter/plain/plain_test.go @@ -31,6 +31,7 @@ func Test(t *testing.T) { Convey("And the result should be a path pointing to a directory", func() { So(result, ShouldNotBeEmpty) isDir, err := filesystem.Get().IsDir(result) + if err != nil { t.Fatal(err) } diff --git a/converter/zip/zip_test.go b/converter/zip/zip_test.go index 07d715b7..293d591e 100644 --- a/converter/zip/zip_test.go +++ b/converter/zip/zip_test.go @@ -4,10 +4,12 @@ import ( "archive/zip" "bytes" "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/source" "github.com/samber/lo" . "github.com/smartystreets/goconvey/convey" + "github.com/spf13/viper" "io" "io/fs" "path/filepath" @@ -17,6 +19,7 @@ import ( func init() { filesystem.SetMemMapFs() lo.Must0(config.Setup()) + viper.Set(constant.FormatsUse, constant.ZIP) } func TestCBZ(t *testing.T) { diff --git a/icon/icon_test.go b/icon/icon_test.go index be5c86b7..3ef3fb69 100644 --- a/icon/icon_test.go +++ b/icon/icon_test.go @@ -1,7 +1,7 @@ package icon import ( - "github.com/metafates/mangal/config" + "github.com/metafates/mangal/constant" . "github.com/smartystreets/goconvey/convey" "github.com/spf13/viper" "testing" @@ -11,7 +11,7 @@ func TestGet(t *testing.T) { Convey("Given a icon", t, func() { i := Lua Convey("When getting the icon with emoji setting", func() { - viper.Set(config.IconsVariant, emoji) + viper.Set(constant.IconsVariant, emoji) result := Get(i) Convey("Then the result should be emoji icon", func() { So(result, ShouldEqual, icons[i].emoji) @@ -19,7 +19,7 @@ func TestGet(t *testing.T) { }) Convey("When getting the icon with nerd setting", func() { - viper.Set(config.IconsVariant, nerd) + viper.Set(constant.IconsVariant, nerd) result := Get(i) Convey("Then the result should be nerd icon", func() { So(result, ShouldEqual, icons[i].nerd) @@ -27,7 +27,7 @@ func TestGet(t *testing.T) { }) Convey("When getting the icon with plain setting", func() { - viper.Set(config.IconsVariant, plain) + viper.Set(constant.IconsVariant, plain) result := Get(i) Convey("Then the result should be plain icon", func() { So(result, ShouldEqual, icons[i].plain) @@ -35,7 +35,7 @@ func TestGet(t *testing.T) { }) Convey("When getting the icon with kaomoji setting", func() { - viper.Set(config.IconsVariant, kaomoji) + viper.Set(constant.IconsVariant, kaomoji) result := Get(i) Convey("Then the result should be kaomoji icon", func() { So(result, ShouldEqual, icons[i].kaomoji) @@ -43,7 +43,7 @@ func TestGet(t *testing.T) { }) Convey("When getting the icon with no setting", func() { - viper.Set(config.IconsVariant, "") + viper.Set(constant.IconsVariant, "") result := Get(i) Convey("Then the result should be empty icon", func() { So(result, ShouldBeEmpty) diff --git a/source/chapter.go b/source/chapter.go index 955c37f6..7688eabf 100644 --- a/source/chapter.go +++ b/source/chapter.go @@ -85,7 +85,7 @@ func (c *Chapter) Size() uint64 { return n } -// SizeHuman is the same as Size but returns a human readable string. +// SizeHuman is the same as Size but returns a human-readable string. func (c *Chapter) SizeHuman() string { if size := c.Size(); size == 0 { return "Unknown size" @@ -94,15 +94,14 @@ func (c *Chapter) SizeHuman() string { } } -func (c *Chapter) Filename() string { - filename := util.SanitizeFilename(c.formattedName()) - extension := "" +func (c *Chapter) Filename() (filename string) { + filename = util.SanitizeFilename(c.formattedName()) if f := viper.GetString(constant.FormatsUse); f != constant.Plain { - extension = "." + f + return filename + "." + f } - return filename + extension + return } func (c *Chapter) Path(temp bool) (path string, err error) { @@ -113,4 +112,4 @@ func (c *Chapter) Path(temp bool) (path string, err error) { path = filepath.Join(path, c.Filename()) return -} \ No newline at end of file +} diff --git a/source/manga.go b/source/manga.go index 0659b9f4..c5339049 100644 --- a/source/manga.go +++ b/source/manga.go @@ -23,7 +23,8 @@ type Manga struct { // ID of manga in the source. ID string // Chapters of the manga - Chapters []*Chapter + Chapters []*Chapter + cachedTempPath string } func (m *Manga) String() string { @@ -36,7 +37,13 @@ func (m *Manga) Filename() string { func (m *Manga) Path(temp bool) (path string, err error) { if temp { - return filesystem.Get().TempDir("", constant.TempPrefix) + if path = m.cachedTempPath; path != "" { + return + } + + path, err = filesystem.Get().TempDir("", constant.TempPrefix) + m.cachedTempPath = path + return } path = where.Downloads() @@ -46,6 +53,5 @@ func (m *Manga) Path(temp bool) (path string, err error) { } _ = filesystem.Get().MkdirAll(path, os.ModePerm) - return } From 858985dd2b8e53051ffe49dfc968688d222aee12 Mon Sep 17 00:00:00 2001 From: metafates Date: Fri, 26 Aug 2022 18:18:29 +0300 Subject: [PATCH 30/51] refactor: bind source pointer to the manga --- cmd/inline.go | 10 +++++++--- converter/cbz/cbz_test.go | 3 --- converter/pdf/pdf_test.go | 3 --- converter/plain/plain_test.go | 3 --- converter/zip/zip_test.go | 3 --- downloader/download.go | 4 ++-- downloader/read.go | 6 +++--- history/history.go | 4 ++-- history/history_test.go | 14 ++++++-------- inline/inline.go | 4 ++-- mini/states.go | 13 ++++++------- provider/custom/chapters.go | 1 - provider/custom/pages.go | 1 - provider/custom/search.go | 2 +- provider/mangadex/chapters.go | 11 +++++------ provider/mangadex/pages.go | 1 - provider/mangadex/search.go | 10 +++++----- provider/manganelo/new.go | 14 ++++++-------- source/chapter.go | 8 ++++++-- source/manga.go | 3 +-- source/page.go | 12 +++++++----- tui/handlers.go | 4 ++-- tui/update.go | 9 ++++----- util/util.go | 2 +- 24 files changed, 66 insertions(+), 79 deletions(-) diff --git a/cmd/inline.go b/cmd/inline.go index 02b8f3a2..b230fc3b 100644 --- a/cmd/inline.go +++ b/cmd/inline.go @@ -1,23 +1,24 @@ package cmd import ( + "errors" "fmt" + "github.com/metafates/mangal/constant" "github.com/metafates/mangal/inline" "github.com/metafates/mangal/provider" "github.com/samber/lo" "github.com/spf13/cobra" + "github.com/spf13/viper" ) func init() { rootCmd.AddCommand(inlineCmd) - inlineCmd.Flags().String("source", "", "source to use. see `mangal sources` for available sources") inlineCmd.Flags().String("query", "", "query to search for") inlineCmd.Flags().String("manga", "", "manga selector") inlineCmd.Flags().String("chapters", "", "chapter selector") inlineCmd.Flags().BoolP("download", "d", false, "download chapters") - lo.Must0(inlineCmd.MarkFlagRequired("source")) lo.Must0(inlineCmd.MarkFlagRequired("query")) lo.Must0(inlineCmd.MarkFlagRequired("manga")) lo.Must0(inlineCmd.MarkFlagRequired("chapters")) @@ -43,7 +44,10 @@ Chapter selectors: Example: "mangal inline --source Manganelo --query \"death note\" --manga first --chapters \"@Vol.1 @\" -d", Run: func(cmd *cobra.Command, args []string) { - sourceName := lo.Must(cmd.Flags().GetString("source")) + sourceName := viper.GetString(constant.DownloaderDefaultSource) + if sourceName == "" { + handleErr(errors.New("source not set")) + } p, ok := provider.Get(sourceName) if !ok { handleErr(fmt.Errorf("source not found: %s", sourceName)) diff --git a/converter/cbz/cbz_test.go b/converter/cbz/cbz_test.go index 4645fe12..86b5f5a2 100644 --- a/converter/cbz/cbz_test.go +++ b/converter/cbz/cbz_test.go @@ -77,12 +77,10 @@ func SampleChapter(t *testing.T) *source.Chapter { Name: "manga name", URL: "manga url", Index: 1337, - SourceID: "tester", ID: "wjakfkawgjj", Chapters: []*source.Chapter{&chapter}, } chapter.Manga = &manga - chapter.SourceID = manga.SourceID // to get images filesystem.SetOsFs() @@ -107,7 +105,6 @@ func SampleChapter(t *testing.T) *source.Chapter { URL: "dwadwaf", Index: 0, Extension: filepath.Ext(path), - SourceID: manga.SourceID, Chapter: &chapter, Contents: io.NopCloser(bytes.NewReader(image)), } diff --git a/converter/pdf/pdf_test.go b/converter/pdf/pdf_test.go index e44e99ac..82486637 100644 --- a/converter/pdf/pdf_test.go +++ b/converter/pdf/pdf_test.go @@ -63,12 +63,10 @@ func SampleChapter(t *testing.T) *source.Chapter { Name: "manga name", URL: "manga url", Index: 1337, - SourceID: "tester", ID: "wjakfkawgjj", Chapters: []*source.Chapter{&chapter}, } chapter.Manga = &manga - chapter.SourceID = manga.SourceID // to get images filesystem.SetOsFs() @@ -93,7 +91,6 @@ func SampleChapter(t *testing.T) *source.Chapter { URL: "dwadwaf", Index: 0, Extension: filepath.Ext(path), - SourceID: manga.SourceID, Chapter: &chapter, Contents: io.NopCloser(bytes.NewReader(image)), } diff --git a/converter/plain/plain_test.go b/converter/plain/plain_test.go index 3cc6f853..a3d32c7c 100644 --- a/converter/plain/plain_test.go +++ b/converter/plain/plain_test.go @@ -69,12 +69,10 @@ func SampleChapter(t *testing.T) *source.Chapter { Name: "manga name", URL: "manga url", Index: 1337, - SourceID: "tester", ID: "wjakfkawgjj", Chapters: []*source.Chapter{&chapter}, } chapter.Manga = &manga - chapter.SourceID = manga.SourceID // to get images filesystem.SetOsFs() @@ -99,7 +97,6 @@ func SampleChapter(t *testing.T) *source.Chapter { URL: "dwadwaf", Index: 0, Extension: filepath.Ext(path), - SourceID: manga.SourceID, Chapter: &chapter, Contents: io.NopCloser(bytes.NewReader(image)), } diff --git a/converter/zip/zip_test.go b/converter/zip/zip_test.go index 293d591e..584bb1f7 100644 --- a/converter/zip/zip_test.go +++ b/converter/zip/zip_test.go @@ -67,12 +67,10 @@ func SampleChapter(t *testing.T) *source.Chapter { Name: "manga name", URL: "manga url", Index: 1337, - SourceID: "tester", ID: "wjakfkawgjj", Chapters: []*source.Chapter{&chapter}, } chapter.Manga = &manga - chapter.SourceID = manga.SourceID // to get images filesystem.SetOsFs() @@ -97,7 +95,6 @@ func SampleChapter(t *testing.T) *source.Chapter { URL: "dwadwaf", Index: 0, Extension: filepath.Ext(path), - SourceID: manga.SourceID, Chapter: &chapter, Contents: io.NopCloser(bytes.NewReader(image)), } diff --git a/downloader/download.go b/downloader/download.go index 0bbbb4ad..b3d1ba06 100644 --- a/downloader/download.go +++ b/downloader/download.go @@ -12,10 +12,10 @@ import ( ) // Download the chapter using given source. -func Download(src source.Source, chapter *source.Chapter, progress func(string)) (string, error) { +func Download(chapter *source.Chapter, progress func(string)) (string, error) { log.Info("downloading " + chapter.Name) progress("Getting pages") - pages, err := src.PagesOf(chapter) + pages, err := chapter.Source().PagesOf(chapter) if err != nil { log.Error(err) return "", err diff --git a/downloader/read.go b/downloader/read.go index c35e669a..51ca71f2 100644 --- a/downloader/read.go +++ b/downloader/read.go @@ -15,16 +15,16 @@ import ( // Read the chapter by downloading it with the given source // and opening it with the configured reader. -func Read(src source.Source, chapter *source.Chapter, progress func(string)) error { +func Read(chapter *source.Chapter, progress func(string)) error { if viper.GetBool(constant.ReaderReadInBrowser) { return open.Start(chapter.URL) } - log.Info("downloading " + chapter.Name + " from " + chapter.Manga.Name + " for reading. Provider is " + src.ID()) + log.Info("downloading " + chapter.Name + " from " + chapter.Manga.Name + " for reading. Provider is " + chapter.Source().ID()) log.Info("getting pages of " + chapter.Name) progress("Getting pages") - pages, err := src.PagesOf(chapter) + pages, err := chapter.Source().PagesOf(chapter) if err != nil { log.Error(err) return err diff --git a/history/history.go b/history/history.go index 95d72ce7..e8175a73 100644 --- a/history/history.go +++ b/history/history.go @@ -85,7 +85,7 @@ func Save(chapter *source.Chapter) error { } jsonChapter := SavedChapter{ - SourceID: chapter.SourceID, + SourceID: chapter.Manga.Source.ID(), MangaName: chapter.Manga.Name, MangaURL: chapter.Manga.URL, Name: chapter.Name, @@ -96,7 +96,7 @@ func Save(chapter *source.Chapter) error { Index: int(chapter.Index), } - chapters[fmt.Sprintf("%s (%s)", chapter.Manga.Name, chapter.SourceID)] = &jsonChapter + chapters[fmt.Sprintf("%s (%s)", jsonChapter.MangaName, jsonChapter.SourceID)] = &jsonChapter // encode json log.Info("Encoding history to json") diff --git a/history/history_test.go b/history/history_test.go index 00db0fd2..06416ce5 100644 --- a/history/history_test.go +++ b/history/history_test.go @@ -15,18 +15,16 @@ func init() { func TestHistory(t *testing.T) { Convey("Given a chapter", t, func() { chapter := source.Chapter{ - Name: "adwad", - URL: "dwaofa", - Index: 42069, - SourceID: "fwaiog", - ID: "fawfa", - Pages: nil, + Name: "adwad", + URL: "dwaofa", + Index: 42069, + ID: "fawfa", + Pages: nil, } manga := source.Manga{ Name: "dawf", URL: "fwa", Index: 1337, - SourceID: "sajfioaw", ID: "wjakfkawgjj", Chapters: []*source.Chapter{&chapter}, } @@ -41,7 +39,7 @@ func TestHistory(t *testing.T) { chapters, err := Get() So(err, ShouldBeNil) So(len(chapters), ShouldBeGreaterThan, 0) - So(chapters[fmt.Sprintf("%s (%s)", chapter.Manga.Name, chapter.SourceID)].Name, ShouldEqual, chapter.Name) + So(chapters[fmt.Sprintf("%s (%s)", chapter.Manga.Name, chapter.Source().ID())].Name, ShouldEqual, chapter.Name) }) }) }) diff --git a/inline/inline.go b/inline/inline.go index 70a5317e..308d0ee2 100644 --- a/inline/inline.go +++ b/inline/inline.go @@ -33,14 +33,14 @@ func Run(options *Options) error { for _, chapter := range chapters { if options.Download { - path, err := downloader.Download(options.Source, chapter, func(string) {}) + path, err := downloader.Download(chapter, func(string) {}) if err != nil && viper.GetBool(constant.DownloaderStopOnError) { return err } fmt.Println(path) } else { - err := downloader.Read(options.Source, chapter, func(string) {}) + err := downloader.Read(chapter, func(string) {}) if err != nil { return err } diff --git a/mini/states.go b/mini/states.go index 592b5e21..01a9a325 100644 --- a/mini/states.go +++ b/mini/states.go @@ -237,7 +237,7 @@ func (m *mini) handleChapterReadState() error { util.ClearScreen() var erase = func() {} - err = downloader.Read(m.selectedSource, chapter, func(s string) { + err = downloader.Read(chapter, func(s string) { erase() erase = progress(s) }) @@ -326,7 +326,7 @@ func (m *mini) handleChaptersDownloadState() error { title(fmt.Sprintf("Currently downloading %s %s (%s)", chapter.Manga.Name, chapter.Name, m.selectedSource.Name())) - _, err := downloader.Download(m.selectedSource, chapter, func(s string) { + _, err := downloader.Download(chapter, func(s string) { erase() erase = progress(s) }) @@ -413,11 +413,10 @@ func (m *mini) handleHistorySelectState() error { erase = progress("Fetching Chapters..") manga := &source.Manga{ - Name: c.MangaName, - URL: c.MangaURL, - Index: 0, - SourceID: c.SourceID, - ID: c.MangaID, + Name: c.MangaName, + URL: c.MangaURL, + Index: 0, + ID: c.MangaID, } chaps, err := m.selectedSource.ChaptersOf(manga) erase() diff --git a/provider/custom/chapters.go b/provider/custom/chapters.go index 549d4194..0fe60757 100644 --- a/provider/custom/chapters.go +++ b/provider/custom/chapters.go @@ -41,7 +41,6 @@ func (s *luaSource) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { s.state.RaiseError(err.Error()) } - chapter.SourceID = s.ID() chapters = append(chapters, chapter) }) diff --git a/provider/custom/pages.go b/provider/custom/pages.go index 23054bde..1d0e2d7e 100644 --- a/provider/custom/pages.go +++ b/provider/custom/pages.go @@ -35,7 +35,6 @@ func (s *luaSource) PagesOf(chapter *source.Chapter) ([]*source.Page, error) { s.state.RaiseError(err.Error()) } - page.SourceID = s.ID() pages = append(pages, page) }) diff --git a/provider/custom/search.go b/provider/custom/search.go index 8e7fb5a0..9587810a 100644 --- a/provider/custom/search.go +++ b/provider/custom/search.go @@ -41,7 +41,7 @@ func (s *luaSource) Search(query string) ([]*source.Manga, error) { s.state.RaiseError(err.Error()) } - manga.SourceID = s.ID() + manga.Source = s mangas = append(mangas, manga) }) diff --git a/provider/mangadex/chapters.go b/provider/mangadex/chapters.go index 3fbc90f7..310f4a61 100644 --- a/provider/mangadex/chapters.go +++ b/provider/mangadex/chapters.go @@ -68,12 +68,11 @@ func (m *Mangadex) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { } chapters = append(chapters, &source.Chapter{ - Name: name, - Index: n + 1, - SourceID: ID, - ID: chapter.ID, - URL: fmt.Sprintf("https://mangadex.org/chapter/%s", chapter.ID), - Manga: manga, + Name: name, + Index: n + 1, + ID: chapter.ID, + URL: fmt.Sprintf("https://mangadex.org/chapter/%s", chapter.ID), + Manga: manga, }) } currOffset += 500 diff --git a/provider/mangadex/pages.go b/provider/mangadex/pages.go index e5e3192f..7f9c6f68 100644 --- a/provider/mangadex/pages.go +++ b/provider/mangadex/pages.go @@ -36,7 +36,6 @@ func (m *Mangadex) PagesOf(chapter *source.Chapter) ([]*source.Page, error) { Extension: filepath.Ext(name), Contents: io.NopCloser(bytes.NewReader(image)), Size: uint64(len(image)), - SourceID: ID, } chapter.Pages = append(chapter.Pages, &page) pages = append(pages, &page) diff --git a/provider/mangadex/search.go b/provider/mangadex/search.go index 34f8e24d..c09d34f9 100644 --- a/provider/mangadex/search.go +++ b/provider/mangadex/search.go @@ -43,11 +43,11 @@ func (m *Mangadex) Search(query string) ([]*source.Manga, error) { for i, manga := range mangaList.Data { m := source.Manga{ - Name: manga.GetTitle(viper.GetString(constant.MangadexLanguage)), - URL: fmt.Sprintf("https://mangadex.org/title/%s", manga.ID), - Index: uint16(i), - SourceID: ID, - ID: manga.ID, + Name: manga.GetTitle(viper.GetString(constant.MangadexLanguage)), + URL: fmt.Sprintf("https://mangadex.org/title/%s", manga.ID), + Index: uint16(i), + ID: manga.ID, + Source: m, } mangas = append(mangas, &m) diff --git a/provider/manganelo/new.go b/provider/manganelo/new.go index 2574143a..9a36f220 100644 --- a/provider/manganelo/new.go +++ b/provider/manganelo/new.go @@ -48,7 +48,7 @@ func New() source.Source { URL: e.Request.AbsoluteURL(link), Index: uint16(e.Index), Chapters: make([]*source.Chapter, 0), - SourceID: manganelo.ID(), + Source: &manganelo, } manganelo.mangas[path] = append(manganelo.mangas[path], &manga) @@ -75,12 +75,11 @@ func New() source.Source { path := e.Request.AbsoluteURL(e.Request.URL.Path) manga := e.Request.Ctx.GetAny("manga").(*source.Manga) chapter := source.Chapter{ - Name: e.Text, - URL: e.Request.AbsoluteURL(link), - Index: uint16(e.Index), - Pages: make([]*source.Page, 0), - Manga: manga, - SourceID: manganelo.ID(), + Name: e.Text, + URL: e.Request.AbsoluteURL(link), + Index: uint16(e.Index), + Pages: make([]*source.Page, 0), + Manga: manga, } manga.Chapters = append(manga.Chapters, &chapter) @@ -111,7 +110,6 @@ func New() source.Source { Index: uint16(e.Index), Chapter: chapter, Extension: ext, - SourceID: manganelo.ID(), } chapter.Pages = append(chapter.Pages, &page) diff --git a/source/chapter.go b/source/chapter.go index 7688eabf..a51826bf 100644 --- a/source/chapter.go +++ b/source/chapter.go @@ -19,8 +19,6 @@ type Chapter struct { URL string // Index of the chapter in the manga. Index uint16 - // SourceID of the source the chapter is from. - SourceID string // ID of the chapter in the source. ID string // Manga that the chapter belongs to. @@ -97,6 +95,8 @@ func (c *Chapter) SizeHuman() string { func (c *Chapter) Filename() (filename string) { filename = util.SanitizeFilename(c.formattedName()) + // plain format assumes that chapter is a directory with images + // rather than a single file. So no need to add extension to it if f := viper.GetString(constant.FormatsUse); f != constant.Plain { return filename + "." + f } @@ -113,3 +113,7 @@ func (c *Chapter) Path(temp bool) (path string, err error) { path = filepath.Join(path, c.Filename()) return } + +func (c *Chapter) Source() Source { + return c.Manga.Source +} diff --git a/source/manga.go b/source/manga.go index c5339049..2a2c6449 100644 --- a/source/manga.go +++ b/source/manga.go @@ -18,12 +18,11 @@ type Manga struct { URL string // Index of the manga in the source. Index uint16 - // SourceID of the source the manga is from. - SourceID string // ID of manga in the source. ID string // Chapters of the manga Chapters []*Chapter + Source Source cachedTempPath string } diff --git a/source/page.go b/source/page.go index ac673237..32c3ff15 100644 --- a/source/page.go +++ b/source/page.go @@ -18,8 +18,6 @@ type Page struct { Index uint16 // Extension of the page image. Extension string - // SourceID of the source the page is from. - SourceID string // Size of the page in bytes Size uint64 // Contents of the page @@ -75,9 +73,13 @@ func (p *Page) Read(b []byte) (int, error) { return p.Contents.Read(b) } -func (p *Page) Filename() string { - filename := fmt.Sprintf("%d%s", p.Index, p.Extension) +func (p *Page) Filename() (filename string) { + filename = fmt.Sprintf("%d%s", p.Index, p.Extension) filename = util.PadZero(filename, 10) - return filename + return +} + +func (p *Page) Source() Source { + return p.Chapter.Source() } diff --git a/tui/handlers.go b/tui/handlers.go index a9932ecc..76cd3f90 100644 --- a/tui/handlers.go +++ b/tui/handlers.go @@ -175,7 +175,7 @@ func (b *statefulBubble) waitForChapters() tea.Cmd { func (b *statefulBubble) readChapter(chapter *source.Chapter) tea.Cmd { return func() tea.Msg { b.currentDownloadingChapter = chapter - err := downloader.Read(b.selectedSource, chapter, func(s string) { + err := downloader.Read(chapter, func(s string) { b.progressStatus = s }) @@ -204,7 +204,7 @@ func (b *statefulBubble) waitForChapterRead() tea.Cmd { func (b *statefulBubble) downloadChapter(chapter *source.Chapter) tea.Cmd { return func() tea.Msg { b.currentDownloadingChapter = chapter - path, err := downloader.Download(b.selectedSource, chapter, func(s string) { + path, err := downloader.Download(chapter, func(s string) { b.progressStatus = s }) diff --git a/tui/update.go b/tui/update.go index 99087a81..bca7ba01 100644 --- a/tui/update.go +++ b/tui/update.go @@ -206,11 +206,10 @@ func (b *statefulBubble) updateHistory(msg tea.Msg) (tea.Model, tea.Cmd) { selected := b.historyC.SelectedItem().(*listItem).internal.(*history.SavedChapter) manga := &source.Manga{ - Name: selected.MangaName, - URL: selected.MangaURL, - Index: 0, - SourceID: selected.SourceID, - ID: selected.MangaID, + Name: selected.MangaName, + URL: selected.MangaURL, + Index: 0, + ID: selected.MangaID, } b.selectedManga = manga diff --git a/util/util.go b/util/util.go index 50257e9c..11e87f9e 100644 --- a/util/util.go +++ b/util/util.go @@ -101,7 +101,7 @@ func ClearScreen() { // ReGroups parses the string with the given regular expression and returns the // group values defined in the expression. func ReGroups(pattern *regexp.Regexp, str string) (groups map[string]string) { - + groups = make(map[string]string) match := pattern.FindStringSubmatch(str) for i, name := range pattern.SubexpNames() { From e4e0e5c5d6765060552e615280bfb234c5b8d736 Mon Sep 17 00:00:00 2001 From: metafates Date: Fri, 26 Aug 2022 19:41:44 +0300 Subject: [PATCH 31/51] refactor: add `util.Max` function --- cmd/gen.go | 11 +---------- history/history_test.go | 23 +++++++++++++++++++++++ source/page.go | 3 +-- util/util.go | 17 ++++++++++++----- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/cmd/gen.go b/cmd/gen.go index 1f32ab56..a3ffd360 100644 --- a/cmd/gen.go +++ b/cmd/gen.go @@ -61,16 +61,7 @@ var genCmd = &cobra.Command{ funcMap := template.FuncMap{ "repeat": strings.Repeat, "plus": func(a, b int) int { return a + b }, - "max": func(nums ...int) int { - max := nums[0] - for _, num := range nums { - if num > max { - max = num - } - } - - return max - }, + "max": util.Max[int], } tmpl, err := template.New("source").Funcs(funcMap).Parse(constant.SourceTemplate) diff --git a/history/history_test.go b/history/history_test.go index 06416ce5..b3125ac0 100644 --- a/history/history_test.go +++ b/history/history_test.go @@ -8,6 +8,28 @@ import ( "testing" ) +type testSource struct{} + +func (testSource) Name() string { + panic("") +} + +func (testSource) Search(_ string) ([]*source.Manga, error) { + panic("") +} + +func (testSource) ChaptersOf(_ *source.Manga) ([]*source.Chapter, error) { + panic("") +} + +func (testSource) PagesOf(_ *source.Chapter) ([]*source.Page, error) { + panic("") +} + +func (testSource) ID() string { + return "test source" +} + func init() { filesystem.SetMemMapFs() } @@ -26,6 +48,7 @@ func TestHistory(t *testing.T) { URL: "fwa", Index: 1337, ID: "wjakfkawgjj", + Source: testSource{}, Chapters: []*source.Chapter{&chapter}, } chapter.Manga = &manga diff --git a/source/page.go b/source/page.go index 32c3ff15..be3e0f3f 100644 --- a/source/page.go +++ b/source/page.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/metafates/mangal/constant" "github.com/metafates/mangal/util" - "github.com/samber/lo" "io" "net/http" ) @@ -54,7 +53,7 @@ func (p *Page) Download() error { } p.Contents = resp.Body - p.Size = lo.Max([]uint64{uint64(resp.ContentLength), 0}) + p.Size = uint64(util.Max(resp.ContentLength, 0)) return nil } diff --git a/util/util.go b/util/util.go index 11e87f9e..8d690402 100644 --- a/util/util.go +++ b/util/util.go @@ -3,6 +3,7 @@ package util import ( "fmt" "github.com/samber/lo" + "golang.org/x/exp/constraints" "golang.org/x/term" "os" "os/exec" @@ -14,11 +15,7 @@ import ( // PadZero pads a number with leading zeros. func PadZero(s string, l int) string { - for l > len(s) { - s = "0" + s - } - - return s + return strings.Repeat("0", Max(l-len(s), 0)) + s } // replacers is a list of regexp.Regexp pairs that will be used to sanitize filenames. @@ -117,3 +114,13 @@ func ReGroups(pattern *regexp.Regexp, str string) (groups map[string]string) { func Ignore(f func() error) { _ = f() } + +func Max[T constraints.Ordered](items ...T) (max T) { + for _, item := range items { + if item > max { + max = item + } + } + + return +} From 17dd8581ca929cdf12d11709b88ff6dfe8a71204 Mon Sep 17 00:00:00 2001 From: metafates Date: Fri, 26 Aug 2022 21:56:35 +0300 Subject: [PATCH 32/51] fix(mangadex): link chapters to the manga --- README.md | 8 ++++++-- converter/cbz/cbz.go | 2 ++ provider/mangadex/chapters.go | 7 +++++-- provider/mangadex/pages.go | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index acf9f78c..ade493c2 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ https://user-images.githubusercontent.com/62389790/183284495-86140f8b-d543-4bc4- ## Features - __Lua Scrapers!!!__ You can add any source you want by creating your own _(or using someone's else)_ scraper with __Lua 5.1__. See [mangal-scrapers repository](https://github.com/metafates/mangal-scrapers) +- [Mangadex](https://mangadex.org) + [Manganelo](https://m.manganelo.com/wwww) Built-In - __Download & Read Manga__ - I mean, it would be strange if you couldn't, right? - __4 Different export formats__ - PDF, CBZ, ZIP and plain images - __3 Different modes__ - TUI, Mini and Inline @@ -156,6 +157,9 @@ Run `mangal where` to show expected config paths Run `mangal config init` to generate a default config file +
+ Default config example (click to show) + ```toml # mangal.toml @@ -263,6 +267,7 @@ write = false # panic, fatal, error, warn, info, debug, trace level = "info" ``` +
## Custom scrapers @@ -290,7 +295,6 @@ You can test it by running `mangal run ` It should automatically appear in the list of available scrapers. - > New to Lua? [Quick start guide](https://learnxinyminutes.com/docs/lua/) ## Anilist @@ -301,4 +305,4 @@ It will mark chapters as read on Anilsit when you read them inside mangal. For more information see [wiki](https://github.com/metafates/mangal/wiki/Anilist-Integration) -> Maybe I'll add more sites in the future, like [myanimelist](https://myanimelist.net/). Open to suggestions! +> Maybe I'll add more sites in the future, like [myanimelist](https://myanimelist.net/). Open for suggestions! diff --git a/converter/cbz/cbz.go b/converter/cbz/cbz.go index adc8edbc..783f0511 100644 --- a/converter/cbz/cbz.go +++ b/converter/cbz/cbz.go @@ -57,6 +57,8 @@ func comicInfo(chapter *source.Chapter) *bytes.Buffer { {{ .Manga.Name }} Web Comic {{ .Manga.URL }} + {{ len .Pages }} + {{ len .Manga.Chapters }} YesAndRightToLeft
` diff --git a/provider/mangadex/chapters.go b/provider/mangadex/chapters.go index 310f4a61..e8aca0fc 100644 --- a/provider/mangadex/chapters.go +++ b/provider/mangadex/chapters.go @@ -35,6 +35,8 @@ func (m *Mangadex) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { var chapters []*source.Chapter var currOffset = 0 + language := viper.GetString(constant.MangadexLanguage) + for { params.Set("offset", strconv.Itoa(currOffset)) list, err := m.client.Chapter.GetMangaChapters(manga.ID, params) @@ -49,7 +51,7 @@ func (m *Mangadex) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { } // skip chapters that are not in the current language - if chapter.Attributes.TranslatedLanguage != viper.GetString(constant.MangadexLanguage) { + if language != "any" && chapter.Attributes.TranslatedLanguage != language { currOffset += 500 continue } @@ -69,7 +71,7 @@ func (m *Mangadex) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { chapters = append(chapters, &source.Chapter{ Name: name, - Index: n + 1, + Index: n, ID: chapter.ID, URL: fmt.Sprintf("https://mangadex.org/chapter/%s", chapter.ID), Manga: manga, @@ -89,6 +91,7 @@ func (m *Mangadex) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { return a.Index < b.Index }) + manga.Chapters = chapters m.cachedChapters[manga.URL] = chapters return chapters, nil } diff --git a/provider/mangadex/pages.go b/provider/mangadex/pages.go index 7f9c6f68..0acf94e9 100644 --- a/provider/mangadex/pages.go +++ b/provider/mangadex/pages.go @@ -37,9 +37,9 @@ func (m *Mangadex) PagesOf(chapter *source.Chapter) ([]*source.Page, error) { Contents: io.NopCloser(bytes.NewReader(image)), Size: uint64(len(image)), } - chapter.Pages = append(chapter.Pages, &page) pages = append(pages, &page) } + chapter.Pages = pages return pages, nil } From ec57c0e410e9fe8f114134d2bc8be8377f4244d5 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 10:42:15 +0300 Subject: [PATCH 33/51] perf: minor performance improvements and fixes --- CHANGELOG.md | 5 +++-- converter/pdf/pdf.go | 10 +++++----- downloader/read.go | 2 +- provider/custom/chapters.go | 6 ++++-- provider/custom/loader.go | 4 ++-- provider/custom/pages.go | 6 ++++-- provider/custom/search.go | 7 ++++--- provider/mangadex/pages.go | 7 ++++--- provider/manganelo/chapters.go | 3 ++- provider/manganelo/new.go | 21 ++++++++++++++------- provider/manganelo/pages.go | 3 ++- tui/handlers.go | 8 ++++---- tui/init.go | 4 +--- tui/update.go | 9 +++++---- 14 files changed, 55 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d71811d6..16f372ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this ## 3.5.0 -- Add `--raw` flag for the `sources` command to print without headers -- Add `--downloads` flag for the `where` command to print location of the downloads directory +- Added `--raw` flag for the `sources` command to print without headers +- Added `--downloads` flag for the `where` command to print location of the downloads directory +- Option to show all languages in mangadex by setting `mangadex.language = 'any'` in the config. - `gen` command added to generate a template for custom source - Show chapter index in the TUI history list - Fixed bug where pressing confirm button with empty history would cause mangal to crash diff --git a/converter/pdf/pdf.go b/converter/pdf/pdf.go index 5dd7f61c..d7a403dd 100644 --- a/converter/pdf/pdf.go +++ b/converter/pdf/pdf.go @@ -32,19 +32,19 @@ func save(chapter *source.Chapter, temp bool) (path string, err error) { return } - pdfFile, err := filesystem.Get().Create(path) + file, err := filesystem.Get().Create(path) if err != nil { return } - defer util.Ignore(pdfFile.Close) + defer util.Ignore(file.Close) - var readers = make([]io.Reader, len(chapter.Pages)) + var images = make([]io.Reader, len(chapter.Pages)) for i, page := range chapter.Pages { - readers[i] = page + images[i] = page } - err = imagesToPDF(pdfFile, readers) + err = imagesToPDF(file, images) return } diff --git a/downloader/read.go b/downloader/read.go index 51ca71f2..396378c0 100644 --- a/downloader/read.go +++ b/downloader/read.go @@ -21,7 +21,7 @@ func Read(chapter *source.Chapter, progress func(string)) error { return open.Start(chapter.URL) } - log.Info("downloading " + chapter.Name + " from " + chapter.Manga.Name + " for reading. Provider is " + chapter.Source().ID()) + log.Info(fmt.Sprintf("downloading %s for reading. Provider is %s", chapter.Name, chapter.Source().ID())) log.Info("getting pages of " + chapter.Name) progress("Getting pages") pages, err := chapter.Source().PagesOf(chapter) diff --git a/provider/custom/chapters.go b/provider/custom/chapters.go index 0fe60757..e26cb4dd 100644 --- a/provider/custom/chapters.go +++ b/provider/custom/chapters.go @@ -19,7 +19,8 @@ func (s *luaSource) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { } table := s.state.CheckTable(-1) - chapters := make([]*source.Chapter, 0) + chapters := make([]*source.Chapter, table.Len()) + var i uint16 table.ForEach(func(k lua.LValue, v lua.LValue) { if k.Type() != lua.LTNumber { @@ -41,7 +42,8 @@ func (s *luaSource) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { s.state.RaiseError(err.Error()) } - chapters = append(chapters, chapter) + chapters[i] = chapter + i++ }) s.cachedChapters[manga.URL] = chapters diff --git a/provider/custom/loader.go b/provider/custom/loader.go index 0212670b..2b810d0c 100644 --- a/provider/custom/loader.go +++ b/provider/custom/loader.go @@ -1,7 +1,7 @@ package custom import ( - "errors" + "fmt" "github.com/metafates/mangal/filesystem" "github.com/metafates/mangal/luamodules" "github.com/metafates/mangal/source" @@ -37,7 +37,7 @@ func LoadSource(path string, validate bool) (source.Source, error) { defined := state.GetGlobal(fn) if defined.Type() != lua.LTFunction { - return nil, errors.New("required function " + fn + " is not defined in the luaSource " + name) + return nil, fmt.Errorf("required function %s is not defined in the luaSource %s", fn, name) } } } diff --git a/provider/custom/pages.go b/provider/custom/pages.go index 1d0e2d7e..7b084866 100644 --- a/provider/custom/pages.go +++ b/provider/custom/pages.go @@ -18,7 +18,8 @@ func (s *luaSource) PagesOf(chapter *source.Chapter) ([]*source.Page, error) { } table := s.state.CheckTable(-1) - pages := make([]*source.Page, 0) + pages := make([]*source.Page, table.Len()) + var i uint16 table.ForEach(func(k lua.LValue, v lua.LValue) { if k.Type() != lua.LTNumber { @@ -35,7 +36,8 @@ func (s *luaSource) PagesOf(chapter *source.Chapter) ([]*source.Page, error) { s.state.RaiseError(err.Error()) } - pages = append(pages, page) + pages[i] = page + i++ }) s.cachedPages[chapter.URL] = pages diff --git a/provider/custom/search.go b/provider/custom/search.go index 9587810a..32796050 100644 --- a/provider/custom/search.go +++ b/provider/custom/search.go @@ -19,7 +19,8 @@ func (s *luaSource) Search(query string) ([]*source.Manga, error) { } table := s.state.CheckTable(-1) - mangas := make([]*source.Manga, 0) + mangas := make([]*source.Manga, table.Len()) + var i uint16 table.ForEach(func(k lua.LValue, v lua.LValue) { if k.Type() != lua.LTNumber { @@ -42,8 +43,8 @@ func (s *luaSource) Search(query string) ([]*source.Manga, error) { } manga.Source = s - - mangas = append(mangas, manga) + mangas[i] = manga + i++ }) s.cachedMangas[query] = mangas diff --git a/provider/mangadex/pages.go b/provider/mangadex/pages.go index 0acf94e9..eb0fac4a 100644 --- a/provider/mangadex/pages.go +++ b/provider/mangadex/pages.go @@ -14,12 +14,12 @@ func (m *Mangadex) PagesOf(chapter *source.Chapter) ([]*source.Page, error) { return nil, err } - var pages []*source.Page - if len(downloader.Pages) == 0 { return nil, errors.New("there were no pages for this chapter") } + var pages = make([]*source.Page, len(downloader.Pages)) + for i, name := range downloader.Pages { image, err := downloader.GetChapterPage(name) if err != nil { @@ -37,7 +37,8 @@ func (m *Mangadex) PagesOf(chapter *source.Chapter) ([]*source.Page, error) { Contents: io.NopCloser(bytes.NewReader(image)), Size: uint64(len(image)), } - pages = append(pages, &page) + + pages[i] = &page } chapter.Pages = pages diff --git a/provider/manganelo/chapters.go b/provider/manganelo/chapters.go index 50b14c11..0960157e 100644 --- a/provider/manganelo/chapters.go +++ b/provider/manganelo/chapters.go @@ -3,6 +3,7 @@ package manganelo import ( "github.com/gocolly/colly" "github.com/metafates/mangal/source" + "net/http" ) func (m *Manganelo) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { @@ -12,7 +13,7 @@ func (m *Manganelo) ChaptersOf(manga *source.Manga) ([]*source.Chapter, error) { ctx := colly.NewContext() ctx.Put("manga", manga) - err := m.chaptersCollector.Request("GET", manga.URL, nil, ctx, nil) + err := m.chaptersCollector.Request(http.MethodGet, manga.URL, nil, ctx, nil) if err != nil { return nil, err diff --git a/provider/manganelo/new.go b/provider/manganelo/new.go index 9a36f220..41ba0aa3 100644 --- a/provider/manganelo/new.go +++ b/provider/manganelo/new.go @@ -10,7 +10,14 @@ import ( "time" ) -var delay = time.Millisecond * 500 +var ( + delay = time.Millisecond * 500 + parallelism = 50 + + mangasSelector = ".search-story-item a.item-title" + chaptersSelector = ".chapter-name" + pageSelector = ".container-chapter-reader img" +) func New() source.Source { manganelo := Manganelo{ @@ -40,7 +47,7 @@ func New() source.Source { }) // Get mangas - mangasCollector.OnHTML(".search-story-item a.item-title", func(e *colly.HTMLElement) { + mangasCollector.OnHTML(mangasSelector, func(e *colly.HTMLElement) { link := e.Attr("href") path := e.Request.AbsoluteURL(e.Request.URL.Path) manga := source.Manga{ @@ -55,7 +62,7 @@ func New() source.Source { }) _ = mangasCollector.Limit(&colly.LimitRule{ - Parallelism: 50, + Parallelism: parallelism, RandomDelay: delay, DomainGlob: "*", }) @@ -70,7 +77,7 @@ func New() source.Source { }) // Get chapters - chaptersCollector.OnHTML(".chapter-name", func(e *colly.HTMLElement) { + chaptersCollector.OnHTML(chaptersSelector, func(e *colly.HTMLElement) { link := e.Attr("href") path := e.Request.AbsoluteURL(e.Request.URL.Path) manga := e.Request.Ctx.GetAny("manga").(*source.Manga) @@ -86,7 +93,7 @@ func New() source.Source { manganelo.chapters[path] = append(manganelo.chapters[path], &chapter) }) _ = chaptersCollector.Limit(&colly.LimitRule{ - Parallelism: 50, + Parallelism: parallelism, RandomDelay: delay, DomainGlob: "*", }) @@ -100,7 +107,7 @@ func New() source.Source { }) // Get pages - pagesCollector.OnHTML(".container-chapter-reader img", func(e *colly.HTMLElement) { + pagesCollector.OnHTML(pageSelector, func(e *colly.HTMLElement) { link := e.Attr("data-src") ext := filepath.Ext(link) path := e.Request.AbsoluteURL(e.Request.URL.Path) @@ -116,7 +123,7 @@ func New() source.Source { manganelo.pages[path] = append(manganelo.pages[path], &page) }) _ = pagesCollector.Limit(&colly.LimitRule{ - Parallelism: 50, + Parallelism: parallelism, RandomDelay: delay, DomainGlob: "*", }) diff --git a/provider/manganelo/pages.go b/provider/manganelo/pages.go index 72d1b6f3..121091ce 100644 --- a/provider/manganelo/pages.go +++ b/provider/manganelo/pages.go @@ -3,6 +3,7 @@ package manganelo import ( "github.com/gocolly/colly" "github.com/metafates/mangal/source" + "net/http" ) func (m *Manganelo) PagesOf(chapter *source.Chapter) ([]*source.Page, error) { @@ -12,7 +13,7 @@ func (m *Manganelo) PagesOf(chapter *source.Chapter) ([]*source.Page, error) { ctx := colly.NewContext() ctx.Put("chapter", chapter) - err := m.pagesCollector.Request("GET", chapter.URL, nil, ctx, nil) + err := m.pagesCollector.Request(http.MethodGet, chapter.URL, nil, ctx, nil) if err != nil { return nil, err diff --git a/tui/handlers.go b/tui/handlers.go index 76cd3f90..3c9602ee 100644 --- a/tui/handlers.go +++ b/tui/handlers.go @@ -30,13 +30,13 @@ func (b *statefulBubble) loadScrapers() tea.Cmd { return strings.Compare(a.Name, b.Name) < 0 }) - var items []list.Item - for _, s := range scrapers { - items = append(items, &listItem{ + var items = make([]list.Item, len(scrapers)) + for i, s := range scrapers { + items[i] = &listItem{ title: s.Name, description: s.GithubURL(), internal: s, - }) + } } cmd := b.scrapersInstallC.SetItems(items) diff --git a/tui/init.go b/tui/init.go index ec0add11..fdba66f6 100644 --- a/tui/init.go +++ b/tui/init.go @@ -13,9 +13,7 @@ func (b *statefulBubble) Init() tea.Cmd { if name := viper.GetString(constant.DownloaderDefaultSource); name != "" { p, ok := provider.Get(name) if !ok { - b.lastError = fmt.Errorf("provider %s not found", name) - b.errorPlot = randomPlot() - b.newState(errorState) + b.raiseError(fmt.Errorf("provider %s not found", name)) return nil } diff --git a/tui/update.go b/tui/update.go index bca7ba01..aa838306 100644 --- a/tui/update.go +++ b/tui/update.go @@ -206,10 +206,11 @@ func (b *statefulBubble) updateHistory(msg tea.Msg) (tea.Model, tea.Cmd) { selected := b.historyC.SelectedItem().(*listItem).internal.(*history.SavedChapter) manga := &source.Manga{ - Name: selected.MangaName, - URL: selected.MangaURL, - Index: 0, - ID: selected.MangaID, + Name: selected.MangaName, + URL: selected.MangaURL, + Index: 0, + ID: selected.MangaID, + Source: b.selectedSource, } b.selectedManga = manga From d6a393ab1199ed94b19743624dfae5c519f64f89 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 11:10:11 +0300 Subject: [PATCH 34/51] fix: minor fixes --- provider/provider.go | 4 ++-- tui/bubble.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/provider/provider.go b/provider/provider.go index b4092ee8..ce67d3f8 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -43,7 +43,7 @@ var defaultProviders = []*Provider{ } func DefaultProviders() map[string]*Provider { - providers := make(map[string]*Provider) + providers := make(map[string]*Provider, len(defaultProviders)) for _, provider := range defaultProviders { providers[provider.Name] = provider @@ -59,13 +59,13 @@ func CustomProviders() map[string]*Provider { return make(map[string]*Provider) } - providers := make(map[string]*Provider) paths := lo.FilterMap(files, func(f os.FileInfo, _ int) (string, bool) { if filepath.Ext(f.Name()) == customProviderExtension { return filepath.Join(where.Sources(), f.Name()), true } return "", false }) + providers := make(map[string]*Provider, len(paths)) for _, path := range paths { name := util.FileStem(path) diff --git a/tui/bubble.go b/tui/bubble.go index a5f1b682..fb88738f 100644 --- a/tui/bubble.go +++ b/tui/bubble.go @@ -137,7 +137,7 @@ func (b *statefulBubble) resize(width, height int) { b.width = styledWidth b.height = styledHeight - b.helpC.Width = styledWidth + b.helpC.Width = listWidth } func (b *statefulBubble) startLoading() tea.Cmd { From 7a7cb3acb414b25e7c8d006cf8b999ca60015af3 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 11:17:02 +0300 Subject: [PATCH 35/51] fix(tui): typo --- tui/view.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tui/view.go b/tui/view.go index 75fcf2cb..411a6c94 100644 --- a/tui/view.go +++ b/tui/view.go @@ -86,7 +86,7 @@ func (b *statefulBubble) viewConfirm() string { []string{ style.Title("Confirm"), "", - fmt.Sprintf(icon.Get(icon.Question)+" Download %d chapters?", len(b.selectedChapters)), + fmt.Sprintf("%s Download %s?", icon.Get(icon.Question), util.Quantity(len(b.selectedChapters), "chapter")), }, ) } From c33745103435dea2cf160641efaf32019d87f139 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 11:47:07 +0300 Subject: [PATCH 36/51] fix(scripts): aarch64 -> arm64 --- scripts/install | 8 +++++++- scripts/run | 9 ++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/scripts/install b/scripts/install index ba2ab6e0..5ca21dac 100755 --- a/scripts/install +++ b/scripts/install @@ -18,8 +18,14 @@ test -z "$VERSION" && { test -z "$TMPDIR" && TMPDIR="$(mktemp -d)" +OS=$(uname -s) +ARCH=$(uname -m) -TAR_NAME="${FILE_BASENAME}_${VERSION:1}_$(uname -s)_$(uname -m).tar.gz" +if [[ $OS -eq "Linux" && $ARCH -eq "aarch64" ]]; then + ARCH="arm64" +fi + +TAR_NAME="${FILE_BASENAME}_${VERSION:1}_${OS}_${ARCH}.tar.gz" TAR_FILE="$TMPDIR/${TAR_NAME}" export TAR_NAME diff --git a/scripts/run b/scripts/run index 66a8dc42..ce9400ae 100755 --- a/scripts/run +++ b/scripts/run @@ -17,7 +17,14 @@ test -z "$VERSION" && { test -z "$TMPDIR" && TMPDIR="$(mktemp -d)" -TAR_NAME="${FILE_BASENAME}_${VERSION:1}_$(uname -s)_$(uname -m).tar.gz" +OS=$(uname -s) +ARCH=$(uname -m) + +if [[ $OS -eq "Linux" && $ARCH -eq "aarch64" ]]; then + ARCH="arm64" +fi + +TAR_NAME="${FILE_BASENAME}_${VERSION:1}_${OS}_${ARCH}.tar.gz" TAR_FILE="$TMPDIR/${TAR_NAME}" export TAR_NAME From de9c74860057020f15652f265ca08f275a681630 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 11:57:21 +0300 Subject: [PATCH 37/51] chore(scripts): reformat --- .idea/codeStyles/codeStyleConfig.xml | 5 ++ scripts/install | 83 ++++++++++++++-------------- scripts/run | 36 ++++++------ 3 files changed, 64 insertions(+), 60 deletions(-) create mode 100644 .idea/codeStyles/codeStyleConfig.xml diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..a55e7a17 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/scripts/install b/scripts/install index 5ca21dac..15c2aa94 100755 --- a/scripts/install +++ b/scripts/install @@ -6,23 +6,22 @@ RELEASES_URL="https://github.com/metafates/mangal/releases" FILE_BASENAME="mangal" test -z "$VERSION" && VERSION="$(curl -sfL -o /dev/null -w "%{url_effective}" "$RELEASES_URL/latest" | - rev | - cut -f1 -d'/' | - rev)" + rev | + cut -f1 -d'/' | + rev)" test -z "$VERSION" && { - echo "Unable to get mangal version." >&2 - exit 1 + echo "Unable to get mangal version." >&2 + exit 1 } test -z "$TMPDIR" && TMPDIR="$(mktemp -d)" - OS=$(uname -s) ARCH=$(uname -m) if [[ $OS -eq "Linux" && $ARCH -eq "aarch64" ]]; then - ARCH="arm64" + ARCH="arm64" fi TAR_NAME="${FILE_BASENAME}_${VERSION:1}_${OS}_${ARCH}.tar.gz" @@ -32,54 +31,54 @@ export TAR_NAME export TAR_FILE ( - cd "$TMPDIR" - echo "Downloading Mangal $VERSION..." - curl -sfLo "$TAR_FILE" \ - "$RELEASES_URL/download/$VERSION/${TAR_NAME}" - - echo "Downloading checksums..." - curl -sfLo "checksums.txt" "$RELEASES_URL/download/$VERSION/checksums.txt" - - echo "Verifying checksums..." - if command -v sha256sum &>/dev/null; then - sha256sum --ignore-missing --quiet --check checksums.txt - else - shasum -a 256 --ignore-missing --quiet --check checksums.txt - fi + cd "$TMPDIR" + echo "Downloading Mangal $VERSION..." + curl -sfLo "$TAR_FILE" \ + "$RELEASES_URL/download/$VERSION/${TAR_NAME}" + + echo "Downloading checksums..." + curl -sfLo "checksums.txt" "$RELEASES_URL/download/$VERSION/checksums.txt" + + echo "Verifying checksums..." + if command -v sha256sum &>/dev/null; then + sha256sum --ignore-missing --quiet --check checksums.txt + else + shasum -a 256 --ignore-missing --quiet --check checksums.txt + fi ) tar -xf "$TAR_FILE" -C "$TMPDIR" echo "Installing..." -case $(uname) in +case $OS in Darwin) - echo "macOS detected. Checking if brew is installed..." - if command -v brew &>/dev/null; then - OUT="$(brew --prefix)/bin/" - echo "Brew is installed. Moving to ${OUT}" - echo "But I would recommend installing it with brew directly" - cp "${TMPDIR}/${FILE_BASENAME}" "${OUT}" - else - OUT="/usr/local/bin/" - echo "Brew is not installed. Moving to ${OUT}" - sudo cp "${TMPDIR}/${FILE_BASENAME}" "${OUT}" - fi - ;; + echo "macOS detected. Checking if brew is installed..." + if command -v brew &>/dev/null; then + OUT="$(brew --prefix)/bin/" + echo "Brew is installed. Moving to ${OUT}" + echo "But I would recommend installing it with brew directly" + cp "${TMPDIR}/${FILE_BASENAME}" "${OUT}" + else + OUT="/usr/local/bin/" + echo "Brew is not installed. Moving to ${OUT}" + sudo cp "${TMPDIR}/${FILE_BASENAME}" "${OUT}" + fi + ;; *) - OUT="/usr/local/bin/" - echo "Linux detected. Moving to ${OUT}" - sudo cp "${TMPDIR}/${FILE_BASENAME}" "${OUT}" - ;; + OUT="/usr/local/bin/" + echo "Linux detected. Moving to ${OUT}" + sudo cp "${TMPDIR}/${FILE_BASENAME}" "${OUT}" + ;; esac echo "Checking if it's available in the PATH..." if ! command -v mangal &>/dev/null; then - echo "Looks like it's not :(" + echo "Looks like it's not :(" - cp "${TMPDIR}/${FILE_BASENAME}" ./ - echo "I've moved mangal to your current directory, try installing it manually" - exit 1 + cp "${TMPDIR}/${FILE_BASENAME}" ./ + echo "I've moved mangal to your current directory, try installing it manually" + exit 1 fi echo "Mangal is now installed. You can run this script again to update it" diff --git a/scripts/run b/scripts/run index ce9400ae..cc0284bf 100755 --- a/scripts/run +++ b/scripts/run @@ -6,13 +6,13 @@ RELEASES_URL="https://github.com/metafates/mangal/releases" FILE_BASENAME="mangal" test -z "$VERSION" && VERSION="$(curl -sfL -o /dev/null -w "%{url_effective}" "$RELEASES_URL/latest" | - rev | - cut -f1 -d'/' | - rev)" + rev | + cut -f1 -d'/' | + rev)" test -z "$VERSION" && { - echo "Unable to get mangal version." >&2 - exit 1 + echo "Unable to get mangal version." >&2 + exit 1 } test -z "$TMPDIR" && TMPDIR="$(mktemp -d)" @@ -21,7 +21,7 @@ OS=$(uname -s) ARCH=$(uname -m) if [[ $OS -eq "Linux" && $ARCH -eq "aarch64" ]]; then - ARCH="arm64" + ARCH="arm64" fi TAR_NAME="${FILE_BASENAME}_${VERSION:1}_${OS}_${ARCH}.tar.gz" @@ -31,21 +31,21 @@ export TAR_NAME export TAR_FILE ( - cd "$TMPDIR" + cd "$TMPDIR" - echo "Downloading Mangal $VERSION..." - curl -sfLo "$TAR_FILE" \ - "$RELEASES_URL/download/$VERSION/${TAR_NAME}" + echo "Downloading Mangal $VERSION..." + curl -sfLo "$TAR_FILE" \ + "$RELEASES_URL/download/$VERSION/${TAR_NAME}" - echo "Downloading checksums..." - curl -sfLo "checksums.txt" "$RELEASES_URL/download/$VERSION/checksums.txt" + echo "Downloading checksums..." + curl -sfLo "checksums.txt" "$RELEASES_URL/download/$VERSION/checksums.txt" - echo "Verifying checksums..." - if command -v sha256sum &>/dev/null; then - sha256sum --ignore-missing --quiet --check checksums.txt - else - shasum -a 256 --ignore-missing --quiet --check checksums.txt - fi + echo "Verifying checksums..." + if command -v sha256sum &>/dev/null; then + sha256sum --ignore-missing --quiet --check checksums.txt + else + shasum -a 256 --ignore-missing --quiet --check checksums.txt + fi ) tar -xf "$TAR_FILE" -C "$TMPDIR" From c717c0ae9eca4049d6ed3aad7aa550f9e5f1e904 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 12:07:16 +0300 Subject: [PATCH 38/51] fix(cmd): fixed bug where `config init` cmd would ignore `--force` flag --- CHANGELOG.md | 4 +++- cmd/config.go | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16f372ed..8fc9dd8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this - Show chapter index in the TUI history list - Fixed bug where pressing confirm button with empty history would cause mangal to crash - Fixed bug where error message would not fit the screen +- Fixed bug when `mangal config init --force` would ignore `--force` flag +- Internal performance improvements ## 3.4.1 @@ -90,7 +92,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this ## 2.1.1 - `doctor` command now shows more information about errors -- minor bug fixes and perfomance improvements +- minor bug fixes and performance improvements ## 2.1.0 diff --git a/cmd/config.go b/cmd/config.go index aa7d0e9d..f413a0f5 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -7,7 +7,6 @@ import ( "github.com/samber/lo" "github.com/spf13/cobra" "github.com/spf13/viper" - "os" "path/filepath" ) @@ -30,9 +29,10 @@ var configInitCmd = &cobra.Command{ Short: "Initialize config", Long: `Initialize default config`, Run: func(cmd *cobra.Command, args []string) { - mangalDir := where.Config() - if !lo.Must(filesystem.Get().Exists(mangalDir)) { - _ = filesystem.Get().MkdirAll(mangalDir, os.ModePerm) + force := lo.Must(cmd.Flags().GetBool("force")) + if force { + err := filesystem.Get().Remove(filepath.Join(where.Config(), "mangal.toml")) + handleErr(err) } handleErr(viper.SafeWriteConfig()) From b3f41cc1afadf1886749728a46ebc61470318d8f Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 14:37:41 +0300 Subject: [PATCH 39/51] refactor(scripts): improve shell scripts --- README.md | 32 +++++- scripts/install | 258 ++++++++++++++++++++++++++++++++++++------------ scripts/run | 106 ++++++++++++++------ 3 files changed, 296 insertions(+), 100 deletions(-) diff --git a/README.md b/README.md index ade493c2..40ad2222 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ https://user-images.githubusercontent.com/62389790/183284495-86140f8b-d543-4bc4- ## Try it! - curl -sfL https://raw.githubusercontent.com/metafates/mangal/main/scripts/run | bash + curl -sfL https://raw.githubusercontent.com/metafates/mangal/main/scripts/run | sh > **Note** This script does not install anything, it just downloads, verifies and runs Mangal. > @@ -62,20 +62,42 @@ Visit this link to install [Go](https://go.dev/doc/install) > And please open an issue if so -### Arch Linux +### Linux | MacOS + +Install using [this shell script](https://raw.githubusercontent.com/metafates/mangal/main/install) + + curl -sfL https://raw.githubusercontent.com/metafates/mangal/main/scripts/install | sh + +This script will automatically detect OS & Distro and use the best option available. +For example, on macOS it will try to use Homebrew, on Ubuntu it will install the `.deb` package and so on... + +
+๐Ÿ˜ก I hate scripts! Show me how to install it manually + + +#### Arch Linux [AUR package](https://aur.archlinux.org/packages/mangal-bin) (by [@balajsra](https://github.com/balajsra)) -### Linux / macOS +#### Ubuntu / Debian + +1. Download the `*.deb` file from [release page](https://github.com/metafates/mangal/releases/latest) +2. Run `sudo dpkg --install ...` where `...` is the name of the file you downloaded + +#### Fedora / Any other rpm based distro + +1. Download the `*.rpm` file from [release page](https://github.com/metafates/mangal/releases/latest) +2. Run `sudo rpm --install ...` where `...` is the name of the file you downloaded + +#### MacOS Install using [Homebrew](https://brew.sh/) brew tap metafates/mangal brew install mangal -Install using [this bash script](https://raw.githubusercontent.com/metafates/mangal/main/install) +
- curl -sfL https://raw.githubusercontent.com/metafates/mangal/main/scripts/install | bash ### Windows diff --git a/scripts/install b/scripts/install index 15c2aa94..0bc0dbd4 100755 --- a/scripts/install +++ b/scripts/install @@ -1,86 +1,216 @@ -#!/bin/bash +#!/bin/sh set -e -RELEASES_URL="https://github.com/metafates/mangal/releases" -FILE_BASENAME="mangal" +# Check if command is available +has() { + command -v "$1" > /dev/null 2>&1 +} + +info() { + printf "\033[1;35minfo:\033[0m %s\n" "$1" +} + +warn() { + echo "warn: $1" +} -test -z "$VERSION" && VERSION="$(curl -sfL -o /dev/null -w "%{url_effective}" "$RELEASES_URL/latest" | - rev | - cut -f1 -d'/' | - rev)" +err() { + printf "\33[2K\r\033[1;31m%s\033[0m\n" "$*" >&2 +} -test -z "$VERSION" && { - echo "Unable to get mangal version." >&2 +die() { + err "$1" exit 1 } -test -z "$TMPDIR" && TMPDIR="$(mktemp -d)" +# Download file. first argument is out path, second is URL +download() { + curl -sfLo "$1" "$2" +} -OS=$(uname -s) -ARCH=$(uname -m) +verify_checksums() { + info "Verifying checksums..." + if has sha256sum; then + sha256sum --ignore-missing --quiet --check checksums.txt + else + shasum -a 256 --ignore-missing --quiet --check checksums.txt + fi +} -if [[ $OS -eq "Linux" && $ARCH -eq "aarch64" ]]; then - ARCH="arm64" -fi +install_deb() { + if ! has dpkg; + then + warn "dpkg is not in path. Using alternative method..." + install_binary + return + fi -TAR_NAME="${FILE_BASENAME}_${VERSION:1}_${OS}_${ARCH}.tar.gz" -TAR_FILE="$TMPDIR/${TAR_NAME}" + if [ "$ARCH" = "aarch64" ]; + then + ARCH="arm64" + fi -export TAR_NAME -export TAR_FILE + RPM_NAME="${FILE_BASENAME}_${VERSION}_${ARCH}.deb" + RPM_FILE="$TMPDIR/$RPM_NAME" -( - cd "$TMPDIR" - echo "Downloading Mangal $VERSION..." - curl -sfLo "$TAR_FILE" \ - "$RELEASES_URL/download/$VERSION/${TAR_NAME}" + export RPM_FILE + export RPM_NAME - echo "Downloading checksums..." - curl -sfLo "checksums.txt" "$RELEASES_URL/download/$VERSION/checksums.txt" + ( + cd "$TMPDIR" - echo "Verifying checksums..." - if command -v sha256sum &>/dev/null; then - sha256sum --ignore-missing --quiet --check checksums.txt - else - shasum -a 256 --ignore-missing --quiet --check checksums.txt - fi -) - -tar -xf "$TAR_FILE" -C "$TMPDIR" - -echo "Installing..." -case $OS in -Darwin) - echo "macOS detected. Checking if brew is installed..." - if command -v brew &>/dev/null; then - OUT="$(brew --prefix)/bin/" - echo "Brew is installed. Moving to ${OUT}" - echo "But I would recommend installing it with brew directly" - cp "${TMPDIR}/${FILE_BASENAME}" "${OUT}" - else - OUT="/usr/local/bin/" - echo "Brew is not installed. Moving to ${OUT}" - sudo cp "${TMPDIR}/${FILE_BASENAME}" "${OUT}" + info "Downloading Mangal $VERSION..." + download "$RPM_FILE" "$RELEASES_URL/download/$TAG/$RPM_NAME" + + info "Downloading checksums..." + download "checksums.txt" "$RELEASES_URL/download/$TAG/checksums.txt" + + verify_checksums + ) + + info "Installing..." + sudo dpkg --install "$RPM_FILE" +} + +install_binary() { + info "Installing raw binary" + + if [ "$OS" = "Linux" ] && [ "$ARCH" = "aarch64" ]; + then + ARCH="arm64" fi - ;; -*) + TAR_NAME="${FILE_BASENAME}_${VERSION}_${OS}_${ARCH}.tar.gz" + TAR_FILE="$TMPDIR/$TAR_NAME" + + export TAR_NAME + export TAR_FILE + + ( + cd "$TMPDIR" + + info "Downloading Mangal $VERSION..." + download "$TAR_FILE" "$RELEASES_URL/download/$TAG/$TAR_NAME" + + info "Downloading checksums..." + download "checksums.txt" "$RELEASES_URL/download/$TAG/checksums.txt" + + verify_checksums + ) + + tar -xf "$TAR_FILE" -C "$TMPDIR" + + info "Installing..." OUT="/usr/local/bin/" - echo "Linux detected. Moving to ${OUT}" + info "Linux detected. Moving to ${OUT}" sudo cp "${TMPDIR}/${FILE_BASENAME}" "${OUT}" - ;; -esac +} + +install_macos() { + if ! has brew; then + warn "Homebrew is not installed. Using alternative method..." + install_binary + return + fi -echo "Checking if it's available in the PATH..." -if ! command -v mangal &>/dev/null; then - echo "Looks like it's not :(" + info "Installing with homebrew" + brew tap metafates/mangal + brew install mangal +} - cp "${TMPDIR}/${FILE_BASENAME}" ./ - echo "I've moved mangal to your current directory, try installing it manually" - exit 1 -fi +install_rpm() { + if ! has rpm; then + warn "rpm is not in path. Using alternative method..." + install_binary + return + fi + + RPM_NAME="${FILE_BASENAME}-${VERSION}.${ARCH}.rpm" + RPM_FILE="$TMPDIR/$RPM_NAME" + + export RPM_FILE + export RPM_NAME + + ( + cd "$TMPDIR" + + info "Downloading Mangal $VERSION..." + download "$RPM_FILE" "$RELEASES_URL/download/$TAG/$RPM_NAME" + + info "Downloading checksums..." + download "checksums.txt" "$RELEASES_URL/download/$TAG/checksums.txt" + + verify_checksums + ) + + info "Installing..." + sudo rpm --install "$RPM_FILE" +} + +check_path() { + info "Checking if it's available in the PATH..." + if ! has mangal; then + die "Looks like it's not :( Try installing it manually..." + fi +} + +pre_install() { + RELEASES_URL="https://github.com/metafates/mangal/releases" + FILE_BASENAME="mangal" + + info "Fetching latest version..." + TAG="$(curl -sfL -o /dev/null -w "%{url_effective}" "$RELEASES_URL/latest" | + rev | + cut -f1 -d'/' | + rev)" + + test -z "$TAG" && { + echo "Unable to get mangal version." >&2 + exit 1 + } + + test -z "$TMPDIR" && TMPDIR="$(mktemp -d)" + + OS=$(uname -s) + ARCH=$(uname -m) + VERSION=${TAG#?} + + export RELEASES_URL FILE_BASENAME VERSION TAG OS ARCH +} + +post_install() { + info "Mangal is now installed. You can run this script again to update it" +} + +install() { + pre_install + + case $OS in + Darwin) + info "macOS detected" + install_macos + ;; + *) + case $(cat /etc/*release | tr "[:upper:]" "[:lower:]") in + *ubuntu* | *debian*) + info "Debian detected" + install_deb + ;; + *fedora*) + info "Fedora detected" + install_rpm + ;; + *) + info "Unknown linux distro is detected" + install_binary + ;; + esac + ;; + esac + + check_path + post_install +} -echo "Mangal is now installed. You can run this script again to update it" -rm "${TMPDIR}/${FILE_BASENAME}" -exit 0 +install diff --git a/scripts/run b/scripts/run index cc0284bf..e65884dd 100755 --- a/scripts/run +++ b/scripts/run @@ -1,52 +1,96 @@ -#!/bin/bash +#!/bin/sh set -e -RELEASES_URL="https://github.com/metafates/mangal/releases" -FILE_BASENAME="mangal" +# Check if command is available +has() { + command -v "$1" >/dev/null 2>&1 +} + +info() { + printf "\033[1;35minfo:\033[0m %s\n" "$1" +} -test -z "$VERSION" && VERSION="$(curl -sfL -o /dev/null -w "%{url_effective}" "$RELEASES_URL/latest" | - rev | - cut -f1 -d'/' | - rev)" +warn() { + echo "warn: $1" +} + +err() { + printf "\33[2K\r\033[1;31m%s\033[0m\n" "$*" >&2 +} -test -z "$VERSION" && { - echo "Unable to get mangal version." >&2 +die() { + err "$1" exit 1 } -test -z "$TMPDIR" && TMPDIR="$(mktemp -d)" +# Download file. first argument is out path, second is URL +download() { + curl -sfLo "$1" "$2" +} -OS=$(uname -s) -ARCH=$(uname -m) +pre_run() { + RELEASES_URL="https://github.com/metafates/mangal/releases" + FILE_BASENAME="mangal" -if [[ $OS -eq "Linux" && $ARCH -eq "aarch64" ]]; then - ARCH="arm64" -fi + info "Fetching latest version..." + TAG="$(curl -sfL -o /dev/null -w "%{url_effective}" "$RELEASES_URL/latest" | + rev | + cut -f1 -d'/' | + rev)" -TAR_NAME="${FILE_BASENAME}_${VERSION:1}_${OS}_${ARCH}.tar.gz" -TAR_FILE="$TMPDIR/${TAR_NAME}" + test -z "$TAG" && { + echo "Unable to get mangal version." >&2 + exit 1 + } -export TAR_NAME -export TAR_FILE + test -z "$TMPDIR" && TMPDIR="$(mktemp -d)" -( - cd "$TMPDIR" + OS=$(uname -s) + ARCH=$(uname -m) + VERSION=${TAG#?} - echo "Downloading Mangal $VERSION..." - curl -sfLo "$TAR_FILE" \ - "$RELEASES_URL/download/$VERSION/${TAR_NAME}" + export RELEASES_URL FILE_BASENAME VERSION TAG OS ARCH +} - echo "Downloading checksums..." - curl -sfLo "checksums.txt" "$RELEASES_URL/download/$VERSION/checksums.txt" - echo "Verifying checksums..." - if command -v sha256sum &>/dev/null; then +verify_checksums() { + info "Verifying checksums..." + if has sha256sum; then sha256sum --ignore-missing --quiet --check checksums.txt else shasum -a 256 --ignore-missing --quiet --check checksums.txt fi -) +} + + +run() { + pre_run + + if [ "$OS" = "Linux" ] && [ "$ARCH" = "aarch64" ]; then + ARCH="arm64" + fi + + TAR_NAME="${FILE_BASENAME}_${VERSION}_${OS}_${ARCH}.tar.gz" + TAR_FILE="$TMPDIR/$TAR_NAME" + + export TAR_NAME + export TAR_FILE + + ( + cd "$TMPDIR" + + info "Downloading Mangal $VERSION..." + download "$TAR_FILE" "$RELEASES_URL/download/$TAG/$TAR_NAME" + + info "Downloading checksums..." + download "checksums.txt" "$RELEASES_URL/download/$TAG/checksums.txt" + + verify_checksums + ) + + tar -xf "$TAR_FILE" -C "$TMPDIR" + "${TMPDIR}/${FILE_BASENAME}" "$@" +} -tar -xf "$TAR_FILE" -C "$TMPDIR" -"${TMPDIR}/${FILE_BASENAME}" "$@" +run "$@" From 696ba745e61bb919bd511cd099fed6e9ce1374a8 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 15:55:35 +0300 Subject: [PATCH 40/51] refactor(scripts): use `install` instead of `cp` --- scripts/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/install b/scripts/install index 0bc0dbd4..ddacf4e3 100755 --- a/scripts/install +++ b/scripts/install @@ -104,7 +104,7 @@ install_binary() { info "Installing..." OUT="/usr/local/bin/" info "Linux detected. Moving to ${OUT}" - sudo cp "${TMPDIR}/${FILE_BASENAME}" "${OUT}" + sudo sh -c "install '$TMPDIR/$FILE_BASENAME' '${OUT}'" } install_macos() { From 2333ba700c386827f2b6f43346c65427f4585c0a Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 16:01:37 +0300 Subject: [PATCH 41/51] refactor(release): use /usr/local/bin as bindir for nfpms --- .goreleaser.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 33862bd2..2166904b 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -156,7 +156,7 @@ nfpms: - deb - rpm - bindir: /usr/bin + bindir: /usr/local/bin section: utils deb: From 80797c8670d58ea9f89ad98073bc372dbc5ea183 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 16:33:03 +0300 Subject: [PATCH 42/51] refactor(scripts): improve install script --- scripts/install | 64 ++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/scripts/install b/scripts/install index ddacf4e3..0472c881 100755 --- a/scripts/install +++ b/scripts/install @@ -8,15 +8,15 @@ has() { } info() { - printf "\033[1;35minfo:\033[0m %s\n" "$1" + printf "\033[1;35mInfo:\033[0m %s\n" "$1" } warn() { - echo "warn: $1" + printf "\033[1;33mWarning:\033[0m %s\n" "$1" } err() { - printf "\33[2K\r\033[1;31m%s\033[0m\n" "$*" >&2 + printf "\033[1;31mError:\033[0m %s\n" "$1" >&2 } die() { @@ -32,16 +32,21 @@ download() { verify_checksums() { info "Verifying checksums..." if has sha256sum; then - sha256sum --ignore-missing --quiet --check checksums.txt + OK=$(sha256sum --ignore-missing --quiet --check checksums.txt) else - shasum -a 256 --ignore-missing --quiet --check checksums.txt + OK=$(shasum -a 256 --ignore-missing --quiet --check checksums.txt) + fi + + if ! $OK; + then + die "Checksums mismatch. Abort" fi } install_deb() { if ! has dpkg; then - warn "dpkg is not in path. Using alternative method..." + warn "dpkg is not available. Using alternative method..." install_binary return fi @@ -54,8 +59,7 @@ install_deb() { RPM_NAME="${FILE_BASENAME}_${VERSION}_${ARCH}.deb" RPM_FILE="$TMPDIR/$RPM_NAME" - export RPM_FILE - export RPM_NAME + export RPM_FILE RPM_NAME ( cd "$TMPDIR" @@ -84,8 +88,7 @@ install_binary() { TAR_NAME="${FILE_BASENAME}_${VERSION}_${OS}_${ARCH}.tar.gz" TAR_FILE="$TMPDIR/$TAR_NAME" - export TAR_NAME - export TAR_FILE + export TAR_NAME TAR_FILE ( cd "$TMPDIR" @@ -101,9 +104,8 @@ install_binary() { tar -xf "$TAR_FILE" -C "$TMPDIR" - info "Installing..." OUT="/usr/local/bin/" - info "Linux detected. Moving to ${OUT}" + info "Moving to ${OUT}" sudo sh -c "install '$TMPDIR/$FILE_BASENAME' '${OUT}'" } @@ -114,14 +116,14 @@ install_macos() { return fi - info "Installing with homebrew" + info "Installing with homebrew..." brew tap metafates/mangal brew install mangal } install_rpm() { if ! has rpm; then - warn "rpm is not in path. Using alternative method..." + warn "rpm is not available. Using alternative method..." install_binary return fi @@ -129,8 +131,7 @@ install_rpm() { RPM_NAME="${FILE_BASENAME}-${VERSION}.${ARCH}.rpm" RPM_FILE="$TMPDIR/$RPM_NAME" - export RPM_FILE - export RPM_NAME + export RPM_FILE RPM_NAME ( cd "$TMPDIR" @@ -148,14 +149,9 @@ install_rpm() { sudo rpm --install "$RPM_FILE" } -check_path() { - info "Checking if it's available in the PATH..." - if ! has mangal; then - die "Looks like it's not :( Try installing it manually..." - fi -} - pre_install() { + has mangal && warn "mangal is installed already, reinstalling..." + RELEASES_URL="https://github.com/metafates/mangal/releases" FILE_BASENAME="mangal" @@ -166,21 +162,20 @@ pre_install() { rev)" test -z "$TAG" && { - echo "Unable to get mangal version." >&2 - exit 1 + die "Unable to get mangal version." } - test -z "$TMPDIR" && TMPDIR="$(mktemp -d)" - OS=$(uname -s) ARCH=$(uname -m) VERSION=${TAG#?} - export RELEASES_URL FILE_BASENAME VERSION TAG OS ARCH + info "Latest version is $VERSION" + + TMPDIR="$(mktemp -d)" } post_install() { - info "Mangal is now installed. You can run this script again to update it" + printf "\n๐ŸŽ‰ \033[1;32mMangal was installed successfully\033[0m\n" } install() { @@ -191,12 +186,16 @@ install() { info "macOS detected" install_macos ;; - *) + Linux) case $(cat /etc/*release | tr "[:upper:]" "[:lower:]") in - *ubuntu* | *debian*) + *debian*) info "Debian detected" install_deb ;; + *ubuntu*) + info "Ubuntu detected" + install_deb + ;; *fedora*) info "Fedora detected" install_rpm @@ -207,9 +206,10 @@ install() { ;; esac ;; + *) + die "Unknown OS: $OS" esac - check_path post_install } From 6ceb2164c593f37694fc44190afd8d12776582f5 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 16:39:44 +0300 Subject: [PATCH 43/51] refactor(scripts): improve install script --- scripts/install | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/scripts/install b/scripts/install index 0472c881..8e2f3c10 100755 --- a/scripts/install +++ b/scripts/install @@ -116,9 +116,15 @@ install_macos() { return fi - info "Installing with homebrew..." + info "Installing with Homebrew..." brew tap metafates/mangal - brew install mangal + + if has mangal; + then + brew reinstall mangal + else + brew install mangal + fi } install_rpm() { @@ -175,7 +181,12 @@ pre_install() { } post_install() { - printf "\n๐ŸŽ‰ \033[1;32mMangal was installed successfully\033[0m\n" + if has mangal; + then + printf "\n๐ŸŽ‰ \033[1;32mMangal was installed successfully\033[0m\n\n" + else + die "Mangal was not installed :(" + fi } install() { From 98a42f3686eb3b747fcc6b3ac3b2d7a543d8d9e4 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 18:02:04 +0300 Subject: [PATCH 44/51] feat(updater): add updater command draft --- README.md | 28 +++---------- cmd/update.go | 30 +++++++++++++ cmd/version.go | 20 ++------- updater/detect.go | 102 +++++++++++++++++++++++++++++++++++++++++++++ updater/update.go | 34 +++++++++++++++ updater/version.go | 29 +++++++++++++ 6 files changed, 203 insertions(+), 40 deletions(-) create mode 100644 cmd/update.go create mode 100644 updater/detect.go create mode 100644 updater/update.go create mode 100644 updater/version.go diff --git a/README.md b/README.md index 40ad2222..36bafeca 100644 --- a/README.md +++ b/README.md @@ -43,26 +43,12 @@ https://user-images.githubusercontent.com/62389790/183284495-86140f8b-d543-4bc4- ## Installation -- [Go (any OS)](#go-any-os) -- [Arch](#arch-linux) - [Linux / macOS](#linux--macos) - [Windows](#windows) - [Docker](#docker) - [Manual](#manual) -### Go (Any OS) - -Visit this link to install [Go](https://go.dev/doc/install) - - go install -ldflags="-s -w" github.com/metafates/mangal@latest - -> **Note** `-ldflags="-s -w"` makes the binary smaller -> -> Use this method if others are not working for some reason. -> And please open an issue if so - - -### Linux | MacOS +### Linux + MacOS Install using [this shell script](https://raw.githubusercontent.com/metafates/mangal/main/install) @@ -119,20 +105,16 @@ To run ### Manual -### Pre-compiled +#### Pre-compiled Download the pre-compiled binaries from the [releases page](https://github.com/metafates/mangal/releases/latest) and copy them to the desired location. -### From source +#### From source -You will need [Go](https://go.dev/doc/install) (and git) +Visit this link to install [Go](https://go.dev/doc/install) -```bash -git clone --depth 1 https://github.com/metafates/mangal.git -cd mangal -go install -ldflags="-s -w" -``` + go install -ldflags="-s -w" github.com/metafates/mangal@latest ## Usage diff --git a/cmd/update.go b/cmd/update.go new file mode 100644 index 00000000..65409fad --- /dev/null +++ b/cmd/update.go @@ -0,0 +1,30 @@ +package cmd + +import ( + "github.com/metafates/mangal/constant" + "github.com/metafates/mangal/icon" + "github.com/metafates/mangal/style" + "github.com/metafates/mangal/updater" + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(updateCmd) +} + +var updateCmd = &cobra.Command{ + Use: "update", + Short: "Update mangal", + Run: func(cmd *cobra.Command, args []string) { + latestVersion, err := updater.LatestVersion() + handleErr(err) + + if false && constant.Version >= latestVersion { + cmd.Printf("%s %s\n", icon.Get(icon.Success), style.Green("You are using the latest version")) + return + } + + err = updater.Update() + handleErr(err) + }, +} diff --git a/cmd/version.go b/cmd/version.go index aca08cd8..5f9817ab 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,11 +1,9 @@ package cmd import ( - "encoding/json" "github.com/metafates/mangal/constant" - "github.com/metafates/mangal/util" + "github.com/metafates/mangal/updater" "github.com/spf13/cobra" - "net/http" ) func init() { @@ -27,21 +25,9 @@ var versionLatestCmd = &cobra.Command{ Short: "Print the latest version number of the mangal", Long: `It will fetch the latest version from the github and print it`, Run: func(cmd *cobra.Command, args []string) { - resp, err := http.Get("https://api.github.com/repos/metafates/mangal/releases/latest") + version, err := updater.LatestVersion() handleErr(err) - defer util.Ignore(resp.Body.Close) - - var release struct { - TagName string `json:"tag_name"` - } - - err = json.NewDecoder(resp.Body).Decode(&release) - handleErr(err) - - // remove the v from the tag name - latestVersion := release.TagName[1:] - - cmd.Println("mangal latest version is " + latestVersion) + cmd.Println("mangal latest version is " + version) }, } diff --git a/updater/detect.go b/updater/detect.go new file mode 100644 index 00000000..6f990500 --- /dev/null +++ b/updater/detect.go @@ -0,0 +1,102 @@ +package updater + +import ( + "bytes" + "github.com/metafates/mangal/constant" + "github.com/samber/lo" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" +) + +type installationMethod int + +const ( + unknown installationMethod = iota + golang + homebrew + scoop + script +) + +func detectInstallationMethod() installationMethod { + for _, t := range []lo.Tuple2[installationMethod, func() bool]{ + {golang, isUnderGo}, + {scoop, isUnderScoop}, + {homebrew, isUnderHomebrew}, + } { + if t.B() { + return t.A + } + } + + if lo.Contains([]string{"darwin", "linux"}, runtime.GOOS) { + path, err := os.Executable() + if err != nil { + return unknown + } + + if path == "/usr/local/bin/"+constant.Mangal { + return script + } + } + + return unknown +} + +func isUnderGo() (ok bool) { + if !has("go") { + return false + } + + path, err := os.Executable() + if err != nil { + return false + } + + return strings.Contains(path, filepath.Join("go", "bin")) +} + +func isUnderHomebrew() (ok bool) { + if !has("brew") { + return + } + + out, err := execute("brew", "list", "--formula") + if err != nil { + return false + } + + ok = strings.Contains(out, constant.Mangal) + return true +} + +func isUnderScoop() (ok bool) { + if !has("scoop") { + return false + } + + path, err := os.Executable() + if err != nil { + return false + } + + return strings.Contains(path, filepath.Join("scoop", "shims")) +} + +func has(command string) bool { + ok, err := exec.LookPath(command) + return err != nil || ok != "" +} + +func execute(command string, arguments ...string) (output string, err error) { + stdout := bytes.NewBufferString("") + + cmd := exec.Command(command, arguments...) + cmd.Stdout = stdout + err = cmd.Run() + + return stdout.String(), err +} diff --git a/updater/update.go b/updater/update.go new file mode 100644 index 00000000..617fed8b --- /dev/null +++ b/updater/update.go @@ -0,0 +1,34 @@ +package updater + +import ( + "errors" + "fmt" + "os" + "os/exec" +) + +func Update() (err error) { + method := detectInstallationMethod() + + switch method { + case golang: + return updateGo() + case homebrew: + fmt.Println("homebrew") + case scoop: + fmt.Println("scoop") + case script: + fmt.Println("script") + case unknown: + return errors.New("unknown installation method, can't update") + } + + return +} + +func updateGo() (err error) { + cmd := exec.Command("go", "install", "github.com/metafates/mangal@latest") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} diff --git a/updater/version.go b/updater/version.go new file mode 100644 index 00000000..b307957e --- /dev/null +++ b/updater/version.go @@ -0,0 +1,29 @@ +package updater + +import ( + "encoding/json" + "github.com/metafates/mangal/util" + "net/http" +) + +func LatestVersion() (version string, err error) { + resp, err := http.Get("https://api.github.com/repos/metafates/mangal/releases/latest") + if err != nil { + return + } + + defer util.Ignore(resp.Body.Close) + + var release struct { + TagName string `json:"tag_name"` + } + + err = json.NewDecoder(resp.Body).Decode(&release) + if err != nil { + return + } + + // remove the v from the tag name + version = release.TagName[1:] + return +} From 240ed759be156e24950d0a235f9594eeea80edf2 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 18:25:55 +0300 Subject: [PATCH 45/51] feat(updater): add update command --- CHANGELOG.md | 1 + README.md | 6 +++++- cmd/update.go | 6 +++++- cmd/version.go | 14 -------------- icon/list.go | 2 +- updater/detect.go | 18 +----------------- updater/update.go | 39 ++++++++++++++++++++++++++++++++------- 7 files changed, 45 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fc9dd8f..ffe3e60d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this ## 3.5.0 +- `mangal update` command added - Added `--raw` flag for the `sources` command to print without headers - Added `--downloads` flag for the `where` command to print location of the downloads directory - Option to show all languages in mangadex by setting `mangadex.language = 'any'` in the config. diff --git a/README.md b/README.md index 36bafeca..87e0b4e0 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,11 @@ and copy them to the desired location. Visit this link to install [Go](https://go.dev/doc/install) - go install -ldflags="-s -w" github.com/metafates/mangal@latest +```bash +git clone --depth 1 https://github.com/metafates/mangal.git +cd mangal +go install -ldflags="-s -w" +``` ## Usage diff --git a/cmd/update.go b/cmd/update.go index 65409fad..bfcdff71 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -16,12 +16,16 @@ var updateCmd = &cobra.Command{ Use: "update", Short: "Update mangal", Run: func(cmd *cobra.Command, args []string) { + cmd.Printf("%s %s\n", icon.Get(icon.Progress), "Fetching latest version...") + latestVersion, err := updater.LatestVersion() handleErr(err) - if false && constant.Version >= latestVersion { + if constant.Version >= latestVersion { cmd.Printf("%s %s\n", icon.Get(icon.Success), style.Green("You are using the latest version")) return + } else { + cmd.Printf("%s New version is available: %s\n", icon.Get(icon.Success), latestVersion) } err = updater.Update() diff --git a/cmd/version.go b/cmd/version.go index 5f9817ab..2508906c 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -2,13 +2,11 @@ package cmd import ( "github.com/metafates/mangal/constant" - "github.com/metafates/mangal/updater" "github.com/spf13/cobra" ) func init() { rootCmd.AddCommand(versionCmd) - versionCmd.AddCommand(versionLatestCmd) } var versionCmd = &cobra.Command{ @@ -19,15 +17,3 @@ var versionCmd = &cobra.Command{ cmd.Println("mangal version " + constant.Version) }, } - -var versionLatestCmd = &cobra.Command{ - Use: "latest", - Short: "Print the latest version number of the mangal", - Long: `It will fetch the latest version from the github and print it`, - Run: func(cmd *cobra.Command, args []string) { - version, err := updater.LatestVersion() - handleErr(err) - - cmd.Println("mangal latest version is " + version) - }, -} diff --git a/icon/list.go b/icon/list.go index 8c0b7321..6b605ae8 100644 --- a/icon/list.go +++ b/icon/list.go @@ -39,7 +39,7 @@ var icons = map[Icon]*iconDef{ Success: { emoji: "๐ŸŽ‰", nerd: style.Green("\uF65F "), - plain: style.Green(":)"), + plain: style.Green("โœ“"), kaomoji: style.Green("(แต”โ—กแต”)"), squares: style.Green("โ–ฃ"), }, diff --git a/updater/detect.go b/updater/detect.go index 6f990500..b9934d8c 100644 --- a/updater/detect.go +++ b/updater/detect.go @@ -15,7 +15,6 @@ type installationMethod int const ( unknown installationMethod = iota - golang homebrew scoop script @@ -23,7 +22,6 @@ const ( func detectInstallationMethod() installationMethod { for _, t := range []lo.Tuple2[installationMethod, func() bool]{ - {golang, isUnderGo}, {scoop, isUnderScoop}, {homebrew, isUnderHomebrew}, } { @@ -46,19 +44,6 @@ func detectInstallationMethod() installationMethod { return unknown } -func isUnderGo() (ok bool) { - if !has("go") { - return false - } - - path, err := os.Executable() - if err != nil { - return false - } - - return strings.Contains(path, filepath.Join("go", "bin")) -} - func isUnderHomebrew() (ok bool) { if !has("brew") { return @@ -69,8 +54,7 @@ func isUnderHomebrew() (ok bool) { return false } - ok = strings.Contains(out, constant.Mangal) - return true + return strings.Contains(out, constant.Mangal) } func isUnderScoop() (ok bool) { diff --git a/updater/update.go b/updater/update.go index 617fed8b..e99e7429 100644 --- a/updater/update.go +++ b/updater/update.go @@ -3,6 +3,7 @@ package updater import ( "errors" "fmt" + "net/http" "os" "os/exec" ) @@ -11,14 +12,12 @@ func Update() (err error) { method := detectInstallationMethod() switch method { - case golang: - return updateGo() case homebrew: - fmt.Println("homebrew") + return updateHomebrew() case scoop: - fmt.Println("scoop") + return updateScoop() case script: - fmt.Println("script") + return updateScript() case unknown: return errors.New("unknown installation method, can't update") } @@ -26,8 +25,34 @@ func Update() (err error) { return } -func updateGo() (err error) { - cmd := exec.Command("go", "install", "github.com/metafates/mangal@latest") +func updateHomebrew() (err error) { + cmd := exec.Command("brew", "upgrade", "mangal") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +func updateScoop() (err error) { + cmd := exec.Command("scoop", "update", "mangal") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +func updateScript() (err error) { + res, err := http.Get("https://raw.githubusercontent.com/metafates/mangal/main/install") + if err != nil { + return err + } + + if res.StatusCode != http.StatusOK { + return fmt.Errorf("error fetching script: status code %d", res.StatusCode) + } + + var scriptSource []byte + _, err = res.Body.Read(scriptSource) + + cmd := exec.Command("sh", "-c", string(scriptSource)) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run() From 0b2e1634c59f2466272137a23b3dd41581d29180 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 18:35:45 +0300 Subject: [PATCH 46/51] docs: update --- CHANGELOG.md | 4 ++-- README.md | 35 +++++++++++++++-------------------- cmd/update.go | 3 +++ updater/update.go | 4 ++++ 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffe3e60d..beecb3db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this ## 3.5.0 -- `mangal update` command added +- `mangal update` command added to update itself +- `mangal gen` command added to generate a template for custom source - Added `--raw` flag for the `sources` command to print without headers - Added `--downloads` flag for the `where` command to print location of the downloads directory - Option to show all languages in mangadex by setting `mangadex.language = 'any'` in the config. -- `gen` command added to generate a template for custom source - Show chapter index in the TUI history list - Fixed bug where pressing confirm button with empty history would cause mangal to crash - Fixed bug where error message would not fit the screen diff --git a/README.md b/README.md index 87e0b4e0..8f73c3d3 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,6 @@ https://user-images.githubusercontent.com/62389790/183284495-86140f8b-d543-4bc4- - [Linux / macOS](#linux--macos) - [Windows](#windows) - [Docker](#docker) -- [Manual](#manual) ### Linux + MacOS @@ -60,7 +59,6 @@ For example, on macOS it will try to use Homebrew, on Ubuntu it will install the
๐Ÿ˜ก I hate scripts! Show me how to install it manually - #### Arch Linux [AUR package](https://aur.archlinux.org/packages/mangal-bin) (by [@balajsra](https://github.com/balajsra)) @@ -82,6 +80,21 @@ Install using [Homebrew](https://brew.sh/) brew tap metafates/mangal brew install mangal +#### Pre-compiled + +Download the pre-compiled binaries from the [releases page](https://github.com/metafates/mangal/releases/latest) +and copy them to the desired location. + +#### From source + +Visit this link to install [Go](https://go.dev/doc/install) + +```bash +git clone --depth 1 https://github.com/metafates/mangal.git +cd mangal +go install -ldflags="-s -w" +``` +
@@ -102,24 +115,6 @@ To run docker run --rm -ti -e "TERM=xterm-256color" -v $(PWD)/mangal/downloads:/downloads -v $(PWD)/mangal/config:/config metafates/mangal -### Manual - - -#### Pre-compiled - -Download the pre-compiled binaries from the [releases page](https://github.com/metafates/mangal/releases/latest) -and copy them to the desired location. - -#### From source - -Visit this link to install [Go](https://go.dev/doc/install) - -```bash -git clone --depth 1 https://github.com/metafates/mangal.git -cd mangal -go install -ldflags="-s -w" -``` - ## Usage ### TUI diff --git a/cmd/update.go b/cmd/update.go index bfcdff71..3518130d 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -6,6 +6,7 @@ import ( "github.com/metafates/mangal/style" "github.com/metafates/mangal/updater" "github.com/spf13/cobra" + "os" ) func init() { @@ -16,6 +17,8 @@ var updateCmd = &cobra.Command{ Use: "update", Short: "Update mangal", Run: func(cmd *cobra.Command, args []string) { + cmd.SetOut(os.Stdout) + cmd.Printf("%s %s\n", icon.Get(icon.Progress), "Fetching latest version...") latestVersion, err := updater.LatestVersion() diff --git a/updater/update.go b/updater/update.go index e99e7429..c2a0e24e 100644 --- a/updater/update.go +++ b/updater/update.go @@ -3,6 +3,7 @@ package updater import ( "errors" "fmt" + "github.com/metafates/mangal/icon" "net/http" "os" "os/exec" @@ -13,10 +14,13 @@ func Update() (err error) { switch method { case homebrew: + fmt.Printf("%s Homebrew installation detected", icon.Get(icon.Progress)) return updateHomebrew() case scoop: + fmt.Printf("%s Scoop installation detected", icon.Get(icon.Progress)) return updateScoop() case script: + fmt.Printf("%s Script installation detected", icon.Get(icon.Progress)) return updateScript() case unknown: return errors.New("unknown installation method, can't update") From 059fb7affc367d0d18ed2b9fffbf031b22b5cbd4 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 18:38:30 +0300 Subject: [PATCH 47/51] fix(scripts): typo --- scripts/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/install b/scripts/install index 8e2f3c10..b9490bb3 100755 --- a/scripts/install +++ b/scripts/install @@ -212,7 +212,7 @@ install() { install_rpm ;; *) - info "Unknown linux distro is detected" + info "Unknown linux distro detected" install_binary ;; esac From f91ab22b1ee11ea3b2b38c768634a29f8a399bdb Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 18:42:21 +0300 Subject: [PATCH 48/51] docs(readme): update --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8f73c3d3..ff5c4d33 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,7 @@ https://user-images.githubusercontent.com/62389790/183284495-86140f8b-d543-4bc4- curl -sfL https://raw.githubusercontent.com/metafates/mangal/main/scripts/run | sh > **Note** This script does not install anything, it just downloads, verifies and runs Mangal. -> -> Linux / macOS only +> Linux + MacOS only ## Table of contents - [Features](#features) @@ -49,7 +48,7 @@ https://user-images.githubusercontent.com/62389790/183284495-86140f8b-d543-4bc4- ### Linux + MacOS -Install using [this shell script](https://raw.githubusercontent.com/metafates/mangal/main/install) +Install using [this shell script](https://github.com/metafates/mangal/blob/main/scripts/install) curl -sfL https://raw.githubusercontent.com/metafates/mangal/main/scripts/install | sh From 5f1a3bfe1228caa2712d87a44b9957d101a71cb7 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 18:48:18 +0300 Subject: [PATCH 49/51] chore: update deps, reformat files --- .github/ISSUE_TEMPLATE/bug_report.yaml | 2 +- .github/ISSUE_TEMPLATE/feature_request.yaml | 2 +- .github/workflows/release.yml | 22 +++++++---------- .github/workflows/test.yml | 26 ++++++++++----------- .goreleaser.yaml | 21 +++++++---------- CHANGELOG.md | 10 ++++---- Dockerfile | 2 -- README.md | 12 ++++++---- go.mod | 12 +++++----- go.sum | 22 +++++++++-------- 10 files changed, 61 insertions(+), 70 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 419b4ebc..d31b7cf0 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -1,6 +1,6 @@ name: Bug Report description: File a bug report -labels: ["bug"] +labels: [ "bug" ] body: - type: textarea attributes: diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index 00a047f8..a21c2757 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -1,6 +1,6 @@ name: Feature request description: Suggest an idea for this project -labels: ["feature"] +labels: [ "feature" ] body: - type: textarea attributes: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3669003a..8be1667b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,8 +3,8 @@ name: goreleaser on: workflow_dispatch: push: - tags: - - '*' + tags: + - '*' permissions: contents: write @@ -15,30 +15,24 @@ jobs: goreleaser: runs-on: ubuntu-latest steps: - - - name: Checkout + - name: Checkout uses: actions/checkout@v2 with: fetch-depth: 0 - - - name: Fetch all tags + - name: Fetch all tags run: git fetch --force --tags - - - name: Set up Go + - name: Set up Go uses: actions/setup-go@v2 with: go-version: 1.18 - - - name: Login to Docker Hub + - name: Login to Docker Hub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - - - name: Set up Docker Buildx + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - - - name: Run GoReleaser + - name: Run GoReleaser uses: goreleaser/goreleaser-action@v2 with: distribution: goreleaser diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d5eaf5fe..fc1c5a89 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,7 +2,7 @@ name: Test on: push: - branches: + branches: - main pull_request: @@ -13,26 +13,26 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [ ubuntu-latest, macos-latest, windows-latest ] env: GOFLAGS: -mod=readonly steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v3 - - name: Set up Go - uses: actions/setup-go@v3 - with: - go-version: 1.18 + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.18 - - name: Test - run: go test -race -v ./... - if: runner.os != 'Windows' + - name: Test + run: go test -race -v ./... + if: runner.os != 'Windows' - - name: Test (without race detector) - run: go test -v ./... - if: runner.os == 'Windows' + - name: Test (without race detector) + run: go test -v ./... + if: runner.os == 'Windows' lint: name: Lint diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 2166904b..10a0524f 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -19,17 +19,15 @@ builds: - -trimpath archives: - - - replacements: + - replacements: darwin: Darwin linux: Linux windows: Windows 386: i386 amd64: x86_64 format_overrides: - - - goos: windows - format: zip + - goos: windows + format: zip files: - completions/* - README.md @@ -72,17 +70,15 @@ changelog: - go mod tidy dockers: - - - goos: linux + - goos: linux goarch: amd64 image_templates: - - "metafates/mangal:latest" + - "metafates/mangal:latest" skip_push: true use: docker brews: - - - name: mangal + - name: mangal tap: owner: metafates @@ -144,8 +140,7 @@ release: Bugs? Suggestions? [Open an issue](https://github.com/metafates/mangal/issues/new/choose) nfpms: - - - file_name_template: "{{ .ConventionalFileName }}" + - file_name_template: "{{ .ConventionalFileName }}" homepage: https://github.com/metafates/mangal maintainer: metafates description: |- @@ -174,7 +169,7 @@ nfpms: file_info: mode: 0644 - src: ./completions/mangal.zsh - dst: /usr/share/zsh/vendor-completions/_mangal + dst: /usr/share/zsh/vendor-completions/_mangal file_info: mode: 0644 - src: ./LICENSE diff --git a/CHANGELOG.md b/CHANGELOG.md index beecb3db..cfe4a104 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this - Option to continue downloading chapters after fail - Option to redownload failed chapters -- Option to select custom reader app for each format +- Option to select custom reader app for each format - Option to skip images with unsupported formats by converter (e.g. pdf converter will skip .gif images) (#77) - Option to specify custom repository for `mangal install` command - Fixed error when using custom readers was not possible @@ -43,7 +43,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this ## 3.2.1 -- Fix home variable in config +- Fix home variable in config ## 3.2.0 @@ -88,7 +88,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this - History mode added. Now you can resume your readings by launching mangal with `mangal --resume` flag (`-r` for short) - Support for new environment variables added - `mangal env` command added to list all env variables and their values (if any set) -- ComicInfo.xml file fixed #53 +- ComicInfo.xml file fixed #53 ## 2.1.1 @@ -122,9 +122,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this ## 1.5.2 -- Command to check for update added `mangal check-update` #26 +- Command to check for update added `mangal check-update` #26 - Scraper system improved -- Fixed bug where chapters with colon in title would not open for read on windows #24 +- Fixed bug where chapters with colon in title would not open for read on windows #24 - Various bug fixes ## 1.5.1 diff --git a/Dockerfile b/Dockerfile index 0acd0132..9b97a3c1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,3 @@ -# To run this image -# docker run --rm -ti -e "TERM=xterm-256color" -v (PWD)/mangal/downloads:/downloads -v (PWD)/mangal/config:/config metafates/mangal FROM alpine:latest ENV MANGAL_DOWNLOADER_PATH=/downloads diff --git a/README.md b/README.md index ff5c4d33..f4f87781 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ https://user-images.githubusercontent.com/62389790/183284495-86140f8b-d543-4bc4- > Linux + MacOS only ## Table of contents + - [Features](#features) - [Installation](#installation) - [Usage](#usage) @@ -29,7 +30,8 @@ https://user-images.githubusercontent.com/62389790/183284495-86140f8b-d543-4bc4- ## Features -- __Lua Scrapers!!!__ You can add any source you want by creating your own _(or using someone's else)_ scraper with __Lua 5.1__. See [mangal-scrapers repository](https://github.com/metafates/mangal-scrapers) +- __Lua Scrapers!!!__ You can add any source you want by creating your own _(or using someone's else)_ scraper with __ + Lua 5.1__. See [mangal-scrapers repository](https://github.com/metafates/mangal-scrapers) - [Mangadex](https://mangadex.org) + [Manganelo](https://m.manganelo.com/wwww) Built-In - __Download & Read Manga__ - I mean, it would be strange if you couldn't, right? - __4 Different export formats__ - PDF, CBZ, ZIP and plain images @@ -96,7 +98,6 @@ go install -ldflags="-s -w" - ### Windows Install using [Scoop](https://scoop.sh/) @@ -140,7 +141,6 @@ Example of usage: Type `mangal help inline` for more information - ### Other See `mangal help` for more information @@ -149,7 +149,7 @@ See `mangal help` for more information Mangal uses [TOML](https://toml.io) format for configuration under the `mangal.toml` filename. Config path depends on the OS. -To find yours, use `mangal where --config`. +To find yours, use `mangal where --config`. For example, on __Linux__ it would be `~/.config/mangal/mangal.toml`. Use env variable `MANGAL_CONFIG_PATH` to set custom config path. @@ -269,11 +269,13 @@ write = false # panic, fatal, error, warn, info, debug, trace level = "info" ``` + ## Custom scrapers -TLDR; To browse and install a custom scraper from [mangal-scrapers repository](https://github.com/metafates/mangal-scrapers) run +TLDR; To browse and install a custom scraper +from [mangal-scrapers repository](https://github.com/metafates/mangal-scrapers) run mangal install diff --git a/go.mod b/go.mod index d52c01ee..75cdb277 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/charmbracelet/lipgloss v0.5.0 github.com/darylhjd/mangodex v0.0.0-20211231093527-e4a91c518fa0 github.com/dustin/go-humanize v1.0.0 - github.com/go-rod/rod v0.109.1 + github.com/go-rod/rod v0.109.2 github.com/gocolly/colly v1.2.0 github.com/ivanpirog/coloredcobra v1.0.1 github.com/ka-weihe/fast-levenshtein v0.0.0-20201227151214-4c99ee36a1ba @@ -24,7 +24,7 @@ require ( github.com/spf13/viper v1.12.0 github.com/vadv/gopher-lua-libs v0.3.0 github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 - golang.org/x/exp v0.0.0-20220823124025-807a23277127 + golang.org/x/exp v0.0.0-20220826205824-bd9bcdd0b820 golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 ) @@ -36,7 +36,7 @@ require ( github.com/antchfx/xmlquery v1.3.12 // indirect github.com/antchfx/xpath v1.2.1 // indirect github.com/atotto/clipboard v0.1.4 // indirect - github.com/aws/aws-sdk-go v1.44.83 // indirect + github.com/aws/aws-sdk-go v1.44.86 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cbroglie/mustache v1.4.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect @@ -75,7 +75,7 @@ require ( github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.12.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.3 // indirect + github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.13.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect @@ -96,8 +96,8 @@ require ( github.com/ysmood/leakless v0.8.0 // indirect github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7 // indirect golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 // indirect - golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c // indirect - golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24 // indirect + golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b // indirect + golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect diff --git a/go.sum b/go.sum index c849523d..2319fcdb 100644 --- a/go.sum +++ b/go.sum @@ -69,10 +69,10 @@ github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdK github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aws/aws-sdk-go v1.32.1/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.44.81 h1:C8oBZ+a+ka0qk3Q24MohQIFq0tkbO8IAu5tfpAMKVWE= -github.com/aws/aws-sdk-go v1.44.81/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.44.83 h1:7+Rtc2Eio6EKUNoZeMV/IVxzVrY5oBQcNPtCcgIHYJA= github.com/aws/aws-sdk-go v1.44.83/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws/aws-sdk-go v1.44.86 h1:Zls97WY9N2c2H85//B88CmSlYYNxS3Zf3k4ds5zAf5A= +github.com/aws/aws-sdk-go v1.44.86/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -145,6 +145,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-rod/rod v0.109.1 h1:658X/G9xyQKjFUNo5apMsIyHpEb/KJnJ5LkAl6a62AI= github.com/go-rod/rod v0.109.1/go.mod h1:GZDtmEs6RpF6kBRYpGCZXxXlKNneKVPiKOjaMbmVVjE= +github.com/go-rod/rod v0.109.2 h1:c8R0uLZbA5gZ7Ekl6gUSQTOzw0kFRYU2UouoloyXdRA= +github.com/go-rod/rod v0.109.2/go.mod h1:GZDtmEs6RpF6kBRYpGCZXxXlKNneKVPiKOjaMbmVVjE= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -336,6 +338,8 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.3 h1:h9JoA60e1dVEOpp0PFwJSmt1Htu057NUq9/bUwaO61s= github.com/pelletier/go-toml/v2 v2.0.3/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -420,8 +424,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs= -github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= @@ -475,10 +477,10 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/exp v0.0.0-20220823124025-807a23277127 h1:S4NrSKDfihhl3+4jSTgwoIevKxX9p7Iv9x++OEIptDo= golang.org/x/exp v0.0.0-20220823124025-807a23277127/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/exp v0.0.0-20220826205824-bd9bcdd0b820 h1:X3V+zzJ9x4fA8jyAW0sk6T4NtY6+Z9uu/rAQxNwDYEM= +golang.org/x/exp v0.0.0-20220826205824-bd9bcdd0b820/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190823064033-3a9bac650e44/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -543,10 +545,10 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= -golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c h1:JVAXQ10yGGVbSyoer5VILysz6YKjdNT2bsvlayjqhes= golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY= +golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -626,10 +628,10 @@ golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 h1:Sx/u41w+OwrInGdEckYmEuU5gHoGSL4QbDz3S9s6j4U= -golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24 h1:TyKJRhyo17yWxOMCTHKWrc5rddHORMlnZ/j57umaUd8= golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM= +golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= From c7f5b2254c68f84dafe1eff7a712f1cbe7516418 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 18:54:59 +0300 Subject: [PATCH 50/51] ci: remove lint job --- .github/workflows/test.yml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fc1c5a89..2cf94e18 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,22 +34,3 @@ jobs: run: go test -v ./... if: runner.os == 'Windows' - lint: - name: Lint - runs-on: ubuntu-latest - env: - GOFLAGS: -mod=readonly - - steps: - - name: Set up Go - uses: actions/setup-go@v3 - with: - go-version: 1.18 - - - name: Checkout code - uses: actions/checkout@v3 - - - name: Lint - uses: golangci/golangci-lint-action@v3 - with: - version: v1.45.2 From c6432bcbd126d572f49f2e70f4ace7dcc75907d6 Mon Sep 17 00:00:00 2001 From: metafates Date: Sat, 27 Aug 2022 20:56:29 +0300 Subject: [PATCH 51/51] ci(release): fix --- .goreleaser.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 10a0524f..ae085964 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -74,7 +74,7 @@ dockers: goarch: amd64 image_templates: - "metafates/mangal:latest" - skip_push: true + skip_push: false use: docker brews: @@ -94,7 +94,7 @@ brews: homepage: "https://github.com/metafates/mangal" description: "The ultimate CLI manga downloader!" license: "MIT" - skip_upload: true + skip_upload: false test: | system "#{bin}/mangal -v" @@ -122,7 +122,7 @@ scoop: homepage: "https://github.com/metafates/mangal" description: "The ultimate CLI manga downloader!" license: MIT - skip_upload: true + skip_upload: false release: @@ -130,7 +130,7 @@ release: owner: metafates name: mangal - draft: true + draft: false name_template: "{{.ProjectName}} v{{.Version}}" footer: | **Full Changelog**: https://github.com/metafates/mangal/compare/{{ .PreviousTag }}...{{ .Tag }}