/mangal

📖 Advanced CLI manga downloader. Lua scrapers, export formats, anilist integration, fancy TUI and more.

Primary LanguageGoMIT LicenseMIT

Mangal

Work in progress...

Fork of metafates/mangal@v5.

Version 5 is now based on metafates' mangalorg suite, which I've forked to work on them myself:

Development

For now, just notes for myself while I work on this.

Requirements

The following needs to be installed before starting development:

  • go>=1.22
    • oapi-codegen: go install github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@latest
    • enumer: go install github.com/dmarkham/enumer@latest
  • just
  • npm

Setup

Update modules:

just update

Install openapi-typescript:

cd web/ui
npm i -D openapi-typescript
npm audit fix
cd ../..

Generate assets and code:

just generate

Then it can be used without compiling for testing purposes:

go run main.go ...

Or compiled/installed:

just build # or full or install
./mangal

Usage

By default if just executing the mangal command, it will start the TUI. To list all options:

mangal -h

Note: If the previous mangal (v4) was used, then remove the config (usually located at ~/.config/mangal) as otherwise these commands will fail.

Config

Mangal contains sensitive defaults that can be edited with some command flags or by editing a config file. By default no config is written to disk, to write the default config to disk run:

mangal config write

It will be written to $XDG_CONFIG_HOME/mangal/mangal.toml.

Then, the config can be set either by modifying the file itself or by running:

mangal config set <key> <value>

For example:

mangal config set download.path $HOME/downloads_test

Providers

These are either the native Go implementations already included (from mangoprovider) or Lua scripts that handle the site scrape logic (search mangas, list mangas/chapters/images, etc).

Lua providers

Some Lua providers are available at saturno. Do note that these are outdated and should only be used as starting points to create new missing providers until implemented in mangoprovider.

Each Lua provider is a directory with the main.lua (scraper) and mangal.toml (metadata) files inside. By default, they need to be placed in $XDG_CONFIG_HOME/mangal/providers.

A new provider can be created by running:

mangal providers new

It is automatically placed in the required path.

Templates

Special functions are available and can be shown by running:

mangal templates funcs

Run a template with custom functions available:

mangal templates exec <template> -v <values>

Where <template> is in the form of a go text/template and <values> a JSON. For example:

mangal templates exec "{{sanitizeWindows .Test}}" -v "{\"Test\":\"asdfg<>:?\"}"

Which will output asdfg.

Modes

Inline

Similar to mangal v4 inline mode. Two submodes available, download which is the expected option and json to fetch the metadata only useful to see what would be downloaded.

JSON

The minimal usage only fetches mangas found in the provider:

mangal inline json -p <provider-id> -q <query>

A more advanced use that fetches just some chapters with anilist output:

mangal inline json -p saturno-mangapill -q "Tengoku Daimakyou" -m exact -c 10-15 --chapter-populate

For more, use the -h flag.

Download

Works exactly like the json option but needs to select only one manga and has couple different flags:

mangal inline download -p saturno-mangapill -q "Tengoku Daimakyou" -m exact -c 10-15 -f CBZ -d "/custom/manga/root/path"

For more, use the -h flag.

Script

Similar to mangalorg/mangalcli where a run.lua and a "provider" is required:

mangal script -f run.lua -p mangapill -v "title=tengoku"

I'm using the sample mangapill.lua mentioned in Providers with the following modified run.lua:

local mangal = require('mangal')
local client = mangal.client
local fzf = mangal.prompt.fzf
local json = mangal.json

local mangas = client.search_mangas(Vars.title) -- search with the given title
local volumes = client.manga_volumes(fzf.find_one(mangas, function(manga)
  return manga:info().title
end)) -- select the first manga

local chapters = {}

-- get all chapters of the manga
for _, volume in ipairs(volumes) do
  for _, chapter in ipairs(client.volume_chapters(volume)) do
    table.insert(chapters, chapter)
  end
end

-- chapters encoded in json format for later use, e.g. pipe to jq
json.print(chapters)