Add anikoto backup downloader

- add a config toggle for backup downloads and retry failed ani-cli jobs with anikoto-cli
- install anikoto-cli systemwide in the container with its required dependencies
- bump the project version to 0.46.1 and publish the release notes
This commit is contained in:
Dymas
2026-07-09 12:54:14 +02:00
parent 332ec670fc
commit 4dd56b72f6
10 changed files with 268 additions and 62 deletions
+23 -1
View File
@@ -23,6 +23,7 @@ from uuid import uuid4
PROJECT_ROOT = Path(__file__).resolve().parent
ANI_CLI = os.environ.get("ANI_CLI_BIN") or shutil.which("ani-cli") or "ani-cli"
ANIKOTO_CLI = os.environ.get("ANIKOTO_CLI_BIN") or shutil.which("anikoto-cli") or "anikoto-cli"
APP_NAME = "ani-cli-web"
VERSION_FILE = PROJECT_ROOT / "VERSION"
CHANGELOG_FILE = PROJECT_ROOT / "CHANGELOG.md"
@@ -290,6 +291,7 @@ DEFAULT_CONFIG = {
"download_dir": default_download_dir(),
"mode": os.environ.get("ANI_CLI_MODE", "sub"),
"quality": os.environ.get("ANI_CLI_QUALITY", "best"),
"download_backup_enabled": False,
"watchlist_auto_refresh_enabled": False,
"watchlist_auto_refresh_minutes": WATCHLIST_AUTO_REFRESH_DEFAULT_MINUTES,
"watchlist_refresh_delay_seconds": WATCHLIST_REFRESH_DELAY_DEFAULT_SECONDS,
@@ -448,6 +450,7 @@ def normalize_config(data):
auto_refresh_enabled = config.get("watchlist_auto_refresh_enabled")
auto_refresh_minutes = config.get("watchlist_auto_refresh_minutes")
refresh_delay_seconds = config.get("watchlist_refresh_delay_seconds")
download_backup_enabled = config.get("download_backup_enabled")
auto_download_enabled = config.get("auto_download_enabled")
auto_download_mode = str(config.get("auto_download_mode", "dub")).lower()
auto_download_quality = str(config.get("auto_download_quality", "best")).lower()
@@ -469,6 +472,10 @@ def normalize_config(data):
auto_download_enabled = auto_download_enabled.strip().lower() in {"1", "true", "yes", "on"}
else:
auto_download_enabled = bool(auto_download_enabled)
if isinstance(download_backup_enabled, str):
download_backup_enabled = download_backup_enabled.strip().lower() in {"1", "true", "yes", "on"}
else:
download_backup_enabled = bool(download_backup_enabled)
if isinstance(jellyfin_sync_enabled, str):
jellyfin_sync_enabled = jellyfin_sync_enabled.strip().lower() in {"1", "true", "yes", "on"}
else:
@@ -494,6 +501,7 @@ def normalize_config(data):
config["mode"] = mode if mode in MODE_CHOICES else "sub"
config["quality"] = quality if quality in QUALITY_CHOICES else "best"
config["download_dir"] = str(Path(download_dir).expanduser())
config["download_backup_enabled"] = download_backup_enabled
config["watchlist_auto_refresh_enabled"] = auto_refresh_enabled
config["watchlist_auto_refresh_minutes"] = auto_refresh_minutes
config["watchlist_refresh_delay_seconds"] = refresh_delay_seconds
@@ -1153,7 +1161,21 @@ def build_job(payload, config):
}
def command_for_job(job):
def command_for_job(job, downloader="ani-cli"):
if str(downloader or "ani-cli").strip().lower() == "anikoto-cli":
command = [
ANIKOTO_CLI,
"-d",
"-e",
job["episodes"],
]
if job["mode"] == "dub":
command.append("--dub")
else:
command.append("--sub")
command.append(job["query"])
return command
command = [
ANI_CLI,
"-d",