examples: anime library sorter + pure-Lua Anitomy parser
Add a worked nautd scripting example that files each anime episode into a
media-server-friendly library the moment its file finishes verifying:
<SORTED_ROOT>/<Title>/Season NN/<Title> - SNNENN.<ext>
- examples/anitomy.lua: a compact, dependency-free reimplementation of Anitomy
(title/season/episode/release-group/resolution/year) in pure Lua — no
require/io/os, so it embeds in the sandbox.
- examples/anime_sort.lua: on_file_complete hook that parses the filename and
calls naut.move_file(); the embedded parser is a verbatim copy of anitomy.lua.
- examples/test_anitomy.lua, test_anime_sort.lua: parser battery + end-to-end
path-building test with an embedded-vs-module drift guard. Wired into ctest as
example_anitomy / example_anime_sort when a lua interpreter is present.
- docs: examples/README.md plus pointers from README and docs/scripting.md.
Verified end to end against a live nautd: file_complete -> move_file -> on-disk
relocate into the sorted tree.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
2178d6a70c
commit
50a357968a
8 changed files with 837 additions and 1 deletions
86
examples/README.md
Normal file
86
examples/README.md
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# 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
|
||||
# 1. edit SORTED_ROOT (and options) at the top of the script
|
||||
# 2. start the daemon with the script
|
||||
nautd --socket /tmp/nautd.sock --script examples/anime_sort.lua
|
||||
|
||||
# 3. register each torrent's storage so the move can resolve + relocate its files
|
||||
nautctl --socket /tmp/nautd.sock add_torrent \
|
||||
'{"torrent_id":1,"torrent":"show.torrent","root":"/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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue