238 lines
6.9 KiB
Markdown
238 lines
6.9 KiB
Markdown
# ani-cli web
|
|
|
|
Local web UI for a system-wide `ani-cli` install.
|
|
|
|
Current version: `0.48.3`
|
|
|
|
## 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 tracked background handoff jobs that also appear in the Queue page
|
|
- Send optional Discord webhook notifications
|
|
- Serve a checked-in `favicon.png` as the site favicon
|
|
|
|
## 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 downloads and Jellyfin handoff jobs, inspect logs, retry failed downloads, avoid duplicate re-queues for the same failed download, clear failed jobs, and 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`, `botan`, 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
|
|
- `botan` is installed inside the container for providers or scripts that need Botan cryptography tooling
|
|
- `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
|
|
|
|
### Queue retries
|
|
|
|
- Adding a download that exactly matches an existing failed queue job reuses that failed entry and sets it back to `pending`
|
|
- This avoids stacking multiple failed rows for the same episode when you queue the same job again
|
|
|
|
### 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
|
|
```
|