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
+27 -2
View File
@@ -20,6 +20,7 @@ from pathlib import Path
from urllib.parse import parse_qs, unquote, urlencode, urlparse, urlunparse
from app_support import (
ANIKOTO_CLI,
ANI_CLI,
APP_NAME,
CHANGELOG_FILE,
@@ -85,9 +86,10 @@ def build_handler_class(context):
def dependency_status():
checks = ["curl", "sed", "grep", "openssl", "fzf", "aria2c", "ffmpeg", "yt-dlp"]
checks = ["curl", "sed", "grep", "openssl", "fzf", "aria2c", "ffmpeg", "yt-dlp", "jq", "mpv"]
result = {name: bool(shutil.which(name)) for name in checks}
result["ani-cli"] = bool(shutil.which(ANI_CLI) or (Path(ANI_CLI).exists() and os.access(ANI_CLI, os.X_OK)))
result["anikoto-cli"] = bool(shutil.which(ANIKOTO_CLI) or (Path(ANIKOTO_CLI).exists() and os.access(ANIKOTO_CLI, os.X_OK)))
return result
@@ -166,6 +168,22 @@ def installed_ani_cli_version():
return version or "Unavailable"
@lru_cache(maxsize=1)
def installed_anikoto_cli_version():
try:
completed = subprocess.run(
[ANIKOTO_CLI, "--version"],
check=True,
capture_output=True,
text=True,
timeout=6,
)
except (OSError, subprocess.SubprocessError):
return "Unavailable"
version = str(completed.stdout or completed.stderr or "").strip()
return version or "Unavailable"
class Handler(BaseHTTPRequestHandler):
server_version = "AniCliWeb/1.0"
remote_session_cookie_name = "ani_cli_web_session"
@@ -535,7 +553,14 @@ class Handler(BaseHTTPRequestHandler):
elif parsed.path == "/api/config":
self.json(sanitize_public_config(Handler._context(self).get_config_snapshot()))
elif parsed.path == "/api/version":
self.json({"name": APP_NAME, "version": VERSION, "ani_cli_version": installed_ani_cli_version()})
self.json(
{
"name": APP_NAME,
"version": VERSION,
"ani_cli_version": installed_ani_cli_version(),
"anikoto_cli_version": installed_anikoto_cli_version(),
}
)
elif parsed.path == "/api/changelog":
self.json({"content": load_project_text_file(CHANGELOG_FILE, default="Changelog unavailable.")})
elif parsed.path == "/api/dependencies":