Naut/examples/README.md
ookami125 8dde48c05a webui: replace nautctl web server with a loadable plugin
Drop the web UI that was compiled into nautctl and serve the
torrent-ui front end (../torrent-ui/public) from a native plugin
(plugins/webui) loaded via `nautd --plugin`. The plugin talks to the
engine only through the host call_rpc ABI and adapts the daemon's RPC
surface to the qBittorrent-style contract the UI expects (snapshot/SSE,
torrent detail tabs, add/delete, cookie auth).

Also folds in the daemon refactor that owns per-torrent worker threads
and the swarm engine (naut_swarm) used by the plugin's data source.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 00:21:48 -04:00

83 lines
3 KiB
Markdown

# Examples
Drop-in Lua scripts for the `nautd` scripting layer (see
[`../docs/scripting.md`](../docs/scripting.md)).
## `anime_sort.lua` — sort anime into a library as it downloads
Files each episode into a clean, media-server-friendly tree **the moment its
file finishes verifying** — before the rest of the torrent completes — using
Naut-Torrent's `on_file_complete` hook + `naut.move_file()`:
```
<SORTED_ROOT>/<Anime Title>/Season NN/<Anime Title> - SNNENN.<ext>
```
Movies (no detectable episode) go to `<SORTED_ROOT>/<Title>/<Title> (year).<ext>`.
### Use it
```sh
# Start the engine, load the script, and add a download.
nautd --socket /tmp/nautd.sock
nautctl --socket /tmp/nautd.sock script examples/anime_sort.lua
nautctl --socket /tmp/nautd.sock add show.torrent /downloads/1
```
As each file completes you'll see, e.g.:
```
[anime_sort] [SubsPlease] Frieren - 12 [1080p].mkv -> /library/Frieren/Season 01/Frieren - S01E12.mkv
```
### Options (top of the script)
| Option | Default | Effect |
|---|---|---|
| `SORTED_ROOT` | `/sorted` | destination library root |
| `ONLY_VIDEO` | `true` | skip non-video files (subtitles, `.nfo`, samples) and leave them in place |
| `KEEP_ORIGINAL_NAME` | `false` | `true` keeps the original filename instead of `Title - SNNENN.ext` |
## `anitomy.lua` — the anime filename parser
A compact, dependency-free reimplementation of the ideas in
[Anitomy](https://github.com/erengy/anitomy): given a scene/fansub filename it
returns the anime **title**, **season**, **episode** (plus release group,
resolution, year, extension). Pure Lua, no `require`/`io`/`os`, so it can be
embedded verbatim in a sandboxed script — which is exactly what `anime_sort.lua`
does.
```lua
local anitomy = require("anitomy")
local p = anitomy.parse("[Erai-raws] Jujutsu Kaisen 2nd Season - 17 [1080p].mkv")
-- p.title = "Jujutsu Kaisen", p.season = 2, p.episode = 17, p.extension = "mkv"
```
`anime_sort.lua` carries a **verbatim copy** of this parser (the sandbox can't
`require`); `test_anime_sort.lua` asserts the two stay in agreement.
### What it recognizes
- `[Group] Title - 12 [1080p].mkv` (dash-delimited episode)
- `Title S04E28`, `Title S2 - 03`, `Title 2nd Season - 17`, `Title Season 2 - 14`
- `Title.S03E11.1080p.x264.mkv` (dotted delimiters)
- `Title_-_01v2_[720p].mkv` (underscores, version suffix)
- `Episode 25`, `Ep5`, `#07`, absolute numbering (`- 500`)
- ranges (`01-12`), release-group and CRC/resolution stripping, movie years
### Heuristic limitations (honest)
- A title that ends in a number with no episode marker (`Mob Psycho 100.mkv`)
treats the number as the episode — same as Anitomy.
- Absolute episode numbering reports season 1 (there is no season marker to read).
- Episode *titles* after the number (`- 05 - The Battle`) are dropped.
## Tests
```sh
lua examples/test_anitomy.lua # parser battery
lua examples/test_anime_sort.lua # end-to-end path building + drift guard
```
These also run under `ctest` (as `example_anitomy` / `example_anime_sort`) when a
`lua` interpreter is on `PATH`.