Use the queued episode spec when finalizing anipy-cli fallback TV downloads so retries keep the requested episode numbers instead of being renumbered from 1, and update tests plus release docs for the fix.
231 lines
6.4 KiB
Markdown
231 lines
6.4 KiB
Markdown
# ani-cli web
|
|
|
|
Local web UI for a system-wide `ani-cli` install.
|
|
|
|
Current version: `0.47.1`
|
|
|
|
## What it does
|
|
|
|
- Search anime in `sub` or `dub`, with poster-style results shown below the selection panel and the first English alternate title when available
|
|
- Queue downloads with folder, quality, media type, season, and episode controls
|
|
- Optionally retry failed `ani-cli` downloads with `anipy-cli`
|
|
- Track shows in a watchlist with `Watching`, `Planned`, `Finished`, and `Dropped` categories
|
|
- Expose a small JSON summary endpoint for Homepage dashboard widgets
|
|
- Refresh watchlist episode counts manually or on a schedule
|
|
- Auto-download missing episodes for `Watching` entries after later refreshes, with a per-show `Source name` override for `ani-cli` search
|
|
- Move fully completed libraries into Jellyfin TV or movie folders with a tracked background handoff job
|
|
- Send optional Discord webhook notifications
|
|
|
|
## Pages
|
|
|
|
- `/`: Search and queue downloads, with poster-card search results below the selection box and alternate English titles under the main name when available
|
|
- `/queue`: Monitor jobs, inspect logs, retry failed jobs, remove finished jobs
|
|
- `/watchlist`: Track shows, refresh them, download all available episodes, and manage auto-download settings such as `Source name`, library `Name`, season, and episode offset
|
|
- `/config`: Save defaults, toggle `anipy-cli` fallback retries, schedule refreshes, configure Jellyfin and Discord, monitor Jellyfin handoff progress, and view runtime info and the changelog
|
|
|
|
## Quick start
|
|
|
|
Requirements:
|
|
|
|
- `ani-cli` installed and available in `PATH`
|
|
- Optional: `anipy-cli` installed and available in `PATH` if you want automatic fallback retries outside Docker
|
|
- Common runtime tools used by `ani-cli`, especially `curl`, `ffmpeg`, `fzf`, `grep`, `openssl`, `sed`, `aria2c`, and `yt-dlp`
|
|
|
|
Run locally:
|
|
|
|
```sh
|
|
./ani-cli-web
|
|
```
|
|
|
|
Open:
|
|
|
|
```text
|
|
http://127.0.0.1:8421/
|
|
```
|
|
|
|
Useful flags and env:
|
|
|
|
- `./ani-cli-web --debug`
|
|
- `ANI_CLI_WEB_HOST=0.0.0.0`
|
|
- `ANI_CLI_WEB_PORT=8421`
|
|
- `ANI_CLI_BIN=/path/to/ani-cli`
|
|
- `ANIPY_CLI_BIN=/path/to/anipy-cli`
|
|
|
|
## Docker
|
|
|
|
Build:
|
|
|
|
```sh
|
|
docker build -t ani-cli-web .
|
|
```
|
|
|
|
Build a specific `ani-cli-web` branch:
|
|
|
|
```sh
|
|
docker build \
|
|
--build-arg ANI_CLI_WEB_BRANCH=anipy_backup \
|
|
-t ani-cli-web .
|
|
```
|
|
|
|
Run:
|
|
|
|
```sh
|
|
docker run --rm \
|
|
-p 8421:8421 \
|
|
-e USER_UID="$(id -u)" \
|
|
-e USER_GID="$(id -g)" \
|
|
-v "$(pwd)/downloads:/downloads" \
|
|
-v "$(pwd)/.ani-cli-web:/app/.ani-cli-web" \
|
|
ani-cli-web
|
|
```
|
|
|
|
Compose:
|
|
|
|
```sh
|
|
USER_UID="$(id -u)" USER_GID="$(id -g)" docker compose up --build -d
|
|
```
|
|
|
|
Docker notes:
|
|
|
|
- The container serves on `0.0.0.0:8421`
|
|
- Downloads are written under `/downloads`
|
|
- App state is stored under `/app/.ani-cli-web`
|
|
- `USER_UID` and `USER_GID` help keep mounted files owned by your host user
|
|
- `UPDATE_ON_START=true` runs `ani-cli --update` before startup
|
|
- `ANI_CLI_WEB_BRANCH` lets the image clone a specific `ani-cli-web` branch at build time
|
|
- `anipy-cli` is installed systemwide inside the container, so fallback retries are available without extra container setup
|
|
|
|
## Key behavior
|
|
|
|
### Watchlist
|
|
|
|
- Adding a show tracks it without downloading immediately
|
|
- Later manual refreshes or scheduled refreshes can queue missing episodes
|
|
- `Download all` queues every currently available episode for the chosen mode
|
|
- Successful downloads sync back into the watchlist
|
|
- TV entries move to `Finished` when the selected downloaded mode reaches the expected episode count
|
|
- Movie entries can be treated as complete after download and routed to movie storage
|
|
|
|
### Auto-download
|
|
|
|
- Runs only for entries in `Watching`
|
|
- Uses the per-show language, quality, `Source name` search override, season, library name, and optional episode offset settings
|
|
- Can queue backlog episodes that were already available before the show was first tracked
|
|
|
|
### Download fallback
|
|
|
|
- Optional and configured from `/config`
|
|
- When enabled, a failed `ani-cli` queue job retries once with `anipy-cli`
|
|
- Fallback retries keep the queued episode numbers when the downloaded `anipy-cli` filenames are renumbered from `1`
|
|
- Docker images install `anipy-cli` automatically; non-Docker installs should provide it in `PATH` themselves
|
|
|
|
### Jellyfin handoff
|
|
|
|
- Optional and configured from `/config`
|
|
- TV libraries move only after the show is finished and download-complete
|
|
- Movie libraries move after download completion
|
|
- Manual `Run now` scans the watchlist in a background job and shows live progress for processed entries, moved files, and the current destination path
|
|
- Recent Jellyfin handoff jobs survive page reloads and show their latest status after app restarts
|
|
|
|
## Homepage widget API
|
|
|
|
For Homepage's Custom API widget, use:
|
|
|
|
```text
|
|
http://127.0.0.1:8421/api/watchlist/homepage
|
|
```
|
|
|
|
Example response:
|
|
|
|
```json
|
|
{
|
|
"watchlist": 12,
|
|
"planned": 4,
|
|
"finished": 31,
|
|
"dropped": 2,
|
|
"total": 49
|
|
}
|
|
```
|
|
|
|
This endpoint is intentionally small so Homepage can map the returned values directly into its widget fields.
|
|
|
|
## Runtime info
|
|
|
|
The Config page runtime panel shows:
|
|
|
|
- `ani-cli-web` version loaded from `VERSION`
|
|
- Installed `ani-cli` version
|
|
- Installed `anipy-cli` version and dependency status
|
|
- A `Changelog` button that opens a scrollable viewer backed by `CHANGELOG.md`
|
|
|
|
## Remote access
|
|
|
|
By default the app only serves loopback clients.
|
|
|
|
To allow LAN or remote access:
|
|
|
|
```sh
|
|
ANI_CLI_WEB_ALLOW_REMOTE=1
|
|
ANI_CLI_WEB_AUTH_USERNAME=admin
|
|
ANI_CLI_WEB_AUTH_PASSWORD=choose-a-long-random-password
|
|
```
|
|
|
|
Optional remote path restriction:
|
|
|
|
```sh
|
|
ANI_CLI_WEB_REMOTE_PATH_ROOTS=/downloads:/srv/jellyfin-tv:/srv/jellyfin-movies
|
|
```
|
|
|
|
## State and storage
|
|
|
|
Project state is stored in:
|
|
|
|
```text
|
|
ani-cli-web/.ani-cli-web/
|
|
```
|
|
|
|
Main contents:
|
|
|
|
- `config.json`
|
|
- `remote-sessions.json`
|
|
- `state.sqlite3`
|
|
- `thumbnails/`
|
|
|
|
Downloaded files are organized like this:
|
|
|
|
```text
|
|
ANI_CLI_DOWNLOAD_DIR/tv/Show Name/Season 01/Show Name - S01E01.mp4
|
|
ANI_CLI_DOWNLOAD_DIR/movie/Movie Name/Movie Name.mp4
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Most users only need these environment variables:
|
|
|
|
- `ANI_CLI_BIN`
|
|
- `ANIPY_CLI_BIN`
|
|
- `ANI_CLI_WEB_HOST`
|
|
- `ANI_CLI_WEB_PORT`
|
|
- `ANI_CLI_WEB_ALLOW_REMOTE`
|
|
- `ANI_CLI_WEB_AUTH_USERNAME`
|
|
- `ANI_CLI_WEB_AUTH_PASSWORD`
|
|
- `ANI_CLI_WEB_REMOTE_PATH_ROOTS`
|
|
- `ANI_CLI_WEB_DEBUG`
|
|
- `ANI_CLI_WEB_STATE_ROOT`
|
|
|
|
Container-specific variables:
|
|
|
|
- `UPDATE_ON_START`
|
|
- `USER_UID`
|
|
- `USER_GID`
|
|
|
|
Everything else can usually be configured from `/config`.
|
|
|
|
## Testing
|
|
|
|
Run the regression suite with:
|
|
|
|
```sh
|
|
python3 -m unittest test_app.py
|
|
```
|