From fa7a922d139085f93d6bc82b7e4ed9a6ce529538 Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 9 Aug 2026 13:42:51 +0200 Subject: [PATCH] Replace legacy branding with Kaizoku --- .dockerignore | 1 - .gitignore | 1 - CHANGELOG.md | 56 +++--- Dockerfile | 8 +- README.md | 19 +- VERSION | 2 +- app.py | 26 ++- app_support.py | 85 +++------ config_page.py | 2 +- docker-compose.yaml | 16 +- http_handler.py | 34 +--- search_page.py | 2 +- template_helpers.py | 2 +- test_app.py | 426 +++++++++++++------------------------------- watchlist_page.py | 2 +- 15 files changed, 223 insertions(+), 459 deletions(-) diff --git a/.dockerignore b/.dockerignore index ab2e61e..1a74dfd 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,4 @@ .git -.ani-cli-web .kaizoku downloads node_modules diff --git a/.gitignore b/.gitignore index 3662553..7c7bc33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -.ani-cli-web/ .kaizoku/ downloads/ node_modules/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 9418e1c..953e494 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.52.0 - 2026-08-09 + +- Removed remaining legacy app branding from the UI, runtime settings, cookies, Docker files, ignores, README, and active tests. +- Standardized exposed environment variables on the `KAIZOKU_*` namespace. +- Removed obsolete downloader fallback names from active config, dependency reporting, and queue tests. + ## 0.51.9 - 2026-08-09 - Closed the Search result floating window after successful Add to queue or Add to watchlist actions. @@ -87,7 +93,7 @@ ## 0.49.7 - 2026-07-21 - Ignored the local `_backup_/` folder in git and Docker build contexts so temporary backups do not get committed or copied into images. -- Added an agent note to preserve existing ani-cli-web configuration and watchlist data during future updates. +- Added an agent note to preserve existing Kaizoku configuration and watchlist data during future updates. ## 0.49.6 - 2026-07-21 @@ -103,13 +109,13 @@ ## 0.49.4 - 2026-07-19 -- Added optional download job stdout mirroring with `ANI_CLI_WEB_JOB_STDOUT`, enabled by default in Docker and Docker Compose so container log collectors can capture downloader output. +- Added optional download job stdout mirroring with `KAIZOKU_JOB_STDOUT`, enabled by default in Docker and Docker Compose so container log collectors can capture downloader output. ## 0.49.3 - 2026-07-19 -- Changed Docker builds to copy the current local `ani-cli-web` checkout into the image instead of cloning the configured remote branch, so rebuilt images include local Docker/runtime fixes immediately. +- Changed Docker builds to copy the current local `Kaizoku` checkout into the image instead of cloning the configured remote branch, so rebuilt images include local Docker/runtime fixes immediately. - Installed Docker `anipy-cli` and `animdl` in separate virtualenvs, with `animdl` pinned under Python 3.11 so its older native dependency pins resolve and remain executable. -- Removed the unused `ANI_CLI_WEB` compose build argument and updated Docker documentation to match the local-checkout build flow. +- Removed the unused `KAIZOKU` compose build argument and updated Docker documentation to match the local-checkout build flow. ## 0.49.2 - 2026-07-19 @@ -190,7 +196,7 @@ ## 0.45.12 - 2026-05-26 -- Changed `ani-cli-web` runtime version reporting to load directly from the project `VERSION` file instead of a duplicated hardcoded constant, which keeps Runtime info, API version responses, and startup logs in sync with release metadata. +- Changed `Kaizoku` runtime version reporting to load directly from the project `VERSION` file instead of a duplicated hardcoded constant, which keeps Runtime info, API version responses, and startup logs in sync with release metadata. - Added regression coverage to ensure the loaded runtime version matches the checked-in `VERSION` file. ## 0.45.11 - 2026-05-26 @@ -275,7 +281,7 @@ ## 0.41.0 - 2026-05-25 - Replaced the shared remote-access token flow with a classic single-user username/password login, backed by a persistent signed session cookie for browser sessions and HTTP Basic auth for API clients. -- Added `ANI_CLI_WEB_AUTH_USERNAME` and `ANI_CLI_WEB_AUTH_PASSWORD` support plus matching `config.json` fields, while keeping those private auth fields out of the public config API so the web UI does not leak or overwrite them. +- Added `KAIZOKU_AUTH_USERNAME` and `KAIZOKU_AUTH_PASSWORD` support plus matching `config.json` fields, while keeping those private auth fields out of the public config API so the web UI does not leak or overwrite them. ## 0.40.6 - 2026-05-25 @@ -413,23 +419,23 @@ ## 0.30.3 - 2026-05-17 -- Fixed container startup under `docker-compose` and custom `USER_UID`/`USER_GID` mappings by launching the web app with `python3 /app/app.py` directly instead of relying on the `./ani-cli-web` launcher file being executable inside the container. +- Fixed container startup under `docker-compose` and custom `USER_UID`/`USER_GID` mappings by launching the web app with `python3 /app/app.py` directly instead of relying on the `./Kaizoku` launcher file being executable inside the container. ## 0.30.2 - 2026-05-17 -- Added container runtime support for `USER_UID` and `USER_GID`, letting `ani-cli-web` run under a chosen numeric host user/group so files created in mounted folders are not owned by `root`. +- Added container runtime support for `USER_UID` and `USER_GID`, letting `Kaizoku` run under a chosen numeric host user/group so files created in mounted folders are not owned by `root`. - Updated the Docker and Compose documentation to show how to pass host UID/GID values into the container. ## 0.30.1 - 2026-05-17 -- Added a `docker-compose.yaml` file that builds the bundled Docker image, mounts `./downloads` and `./.ani-cli-web`, and exposes the ani-cli git remotes, branch, and startup flags through Compose environment defaults. +- Added a `docker-compose.yaml` file that builds the bundled Docker image, mounts `./downloads` and `./.Kaizoku`, and exposes the ani-cli git remotes, branch, and startup flags through Compose environment defaults. - Documented the Compose workflow alongside the existing Docker build and `docker run` setup. ## 0.30.0 - 2026-05-17 -- Added a Docker image build that clones `ani-cli` and `ani-cli-web` from configurable git remotes, installs `ani-cli` system-wide, and starts `ani-cli-web` from `/app`. +- Added a Docker image build that clones `ani-cli` and `Kaizoku` from configurable git remotes, installs `ani-cli` system-wide, and starts `Kaizoku` from `/app`. - Added container startup support for `UPDATE_ON_START=true`, which runs `sudo ani-cli --update` before launching the web app. -- Documented the Docker build arguments, runtime mounts for `./downloads` and `./.ani-cli-web`, and the default container networking and storage layout. +- Documented the Docker build arguments, runtime mounts for `./downloads` and `./.Kaizoku`, and the default container networking and storage layout. ## 0.29.5 - 2026-05-16 @@ -456,7 +462,7 @@ ## 0.29.1 - 2026-05-16 - Hardened download queue startup so a failed `ani-cli` process launch now marks the job as failed instead of crashing the background queue worker thread. -- Cleaned up per-job staging directories after canceled and failed download runs, preventing partial artifacts from piling up under `.ani-cli-web/staging/`. +- Cleaned up per-job staging directories after canceled and failed download runs, preventing partial artifacts from piling up under `.Kaizoku/staging/`. - Fixed thumbnail refresh fallback flow so stale stored AnimeSchedule routes and AniDB IDs now continue on to title-based lookups instead of aborting the whole cover refresh attempt early. - Expanded regression coverage for queue startup failures, failed-download staging cleanup, and stale thumbnail source fallback behavior. @@ -516,7 +522,7 @@ ## 0.22.0 - 2026-05-15 - Added explicit runtime shutdown and reset hooks so shared globals and background workers can be torn down cleanly between in-process runs and tests. -- Fixed deferred worker startup to keep respecting `ANI_CLI_WEB_DISABLE_WORKER`, preventing runtime-backed handler calls from silently enabling background workers in worker-disabled environments. +- Fixed deferred worker startup to keep respecting `KAIZOKU_DISABLE_WORKER`, preventing runtime-backed handler calls from silently enabling background workers in worker-disabled environments. - Split download-queue persistence into structured SQLite columns plus a separate log column, leaving JSON payload storage only for extra fields instead of rewriting the whole job record on routine state changes. - Reduced server-side exception noise by only printing full tracebacks in debug mode. - Centralized the shared browser `api()` fetch helper used by the Search, Config, and Watchlist pages. @@ -532,7 +538,7 @@ - Replaced the HTTP handler's old mutable string-key service locator with an explicit configured handler context, making route dependencies clearer and surfacing wiring issues at startup time instead of during later requests. - Moved watchlist add and successful-download sync off the hot request path by queueing per-show background refresh work instead of doing episode, AnimeSchedule, and thumbnail fetches synchronously before the request returns. -- Ensured runtime-backed HTTP requests start background workers when allowed, while still respecting `ANI_CLI_WEB_DISABLE_WORKER` in tests and intentionally worker-free runs. +- Ensured runtime-backed HTTP requests start background workers when allowed, while still respecting `KAIZOKU_DISABLE_WORKER` in tests and intentionally worker-free runs. - Expanded regression coverage for the new non-blocking watchlist add/download-sync flow. ## 0.19.0 - 2026-05-15 @@ -558,7 +564,7 @@ ## 0.16.0 - 2026-05-15 -- Hardened non-local access so `ANI_CLI_WEB_ALLOW_REMOTE=1` now also requires `ANI_CLI_WEB_REMOTE_TOKEN`, accepted through `Authorization: Bearer ...` or `X-AniCli-Web-Token`, before remote clients can use the web UI or JSON APIs. +- Hardened non-local access so `KAIZOKU_ALLOW_REMOTE=1` now also requires `KAIZOKU_REMOTE_TOKEN`, accepted through `Authorization: Bearer ...` or `X-Kaizoku-Token`, before remote clients can use the web UI or JSON APIs. - Removed import-time state migration side effects from `app_support.py`; legacy state migration now runs during runtime bootstrap instead of plain module import. - Narrowed watchlist persistence updates so refreshes, category changes, and download-sync writes stop rewriting the full row and are less likely to clobber unrelated fields. - Resolve missing queue `show_id` values when jobs are queued, making completed-download watchlist sync stable even if upstream search ordering changes later. @@ -606,14 +612,14 @@ - Fixed running-job cancellation so the worker now consistently finishes canceled downloads as `canceled` instead of drifting into failed or completed final states. - Fixed watchlist `Refresh All` to iterate every tracked show instead of silently stopping at the paged list limit. -- Added loopback-only request protection by default, with `ANI_CLI_WEB_ALLOW_REMOTE=1` available when remote/LAN access is intentionally desired. +- Added loopback-only request protection by default, with `KAIZOKU_ALLOW_REMOTE=1` available when remote/LAN access is intentionally desired. - Extracted shared sidebar branding and page-link helpers to reduce repeated inline page chrome across Search, Config, and Watchlist. - Added focused regression tests for cancellation propagation, full watchlist refresh coverage, local-access helpers, and shared template helpers. ## 0.9.0 - 2026-05-13 -- Reworked Search, Config, and Watchlist with a Tsuki-inspired visual refresh using violet accents, glassy surfaces, softer gradients, and calmer card styling. -- Kept the existing ani-cli-web behavior and routing intact while unifying the refreshed design language across the whole web UI. +- Reworked Search, Config, and Watchlist with a visual refresh using violet accents, glassy surfaces, softer gradients, and calmer card styling. +- Kept the existing Kaizoku behavior and routing intact while unifying the refreshed design language across the whole web UI. ## 0.8.16 - 2026-05-13 @@ -655,12 +661,12 @@ ## 0.8.8 - 2026-05-11 -- Moved `config.json` into the project-local `.ani-cli-web/` folder so app settings now live alongside the queue database, watchlist data, staging files, and thumbnail cache. +- Moved `config.json` into the project-local `.Kaizoku/` folder so app settings now live alongside the queue database, watchlist data, staging files, and thumbnail cache. - Added automatic migration from the legacy XDG config location so existing web app settings are preserved on first startup after the move. ## 0.8.7 - 2026-05-11 -- Moved all project runtime state that previously lived under `~/.local/state/ani-cli-web/` into the project-local `.ani-cli-web/` folder. +- Moved all project runtime state that previously lived under `~/.local/state/kaizoku/` into the project-local `.Kaizoku/` folder. - Added one-time migration for the legacy queue database, queue JSON, watchlist JSON, AniDB title dump, staging directory, and thumbnails so existing local data is carried into the project folder automatically. ## 0.8.6 - 2026-05-11 @@ -680,18 +686,18 @@ ## 0.8.3 - 2026-05-11 -- Migrated any legacy watchlist thumbnails from the old state-directory cache into the new project-local `.ani-cli-web/thumbnails/` folder on access. +- Migrated any legacy watchlist thumbnails from the old state-directory cache into the new project-local `.Kaizoku/thumbnails/` folder on access. - Fixed thumbnail retry gating so the app no longer skips refetch attempts when a thumbnail filename exists in the database but the actual cached file is missing on disk. - Expanded thumbnail debug logging to show whether the expected cached file actually exists before the retry-window decision is made. ## 0.8.2 - 2026-05-11 -- Moved watchlist thumbnail storage into the project-local `.ani-cli-web/thumbnails/` folder so cached images can be inspected directly from the repository tree. +- Moved watchlist thumbnail storage into the project-local `.Kaizoku/thumbnails/` folder so cached images can be inspected directly from the repository tree. - Added debug logs for the local `/api/watchlist/thumb/...` route and file-serving path so thumbnail cache hits, misses, and served files are visible in `--debug` output. ## 0.8.1 - 2026-05-11 -- Added a `--debug` runtime flag for `ani-cli-web` and `./ani-cli-web` that logs thumbnail-source request flow, match decisions, responses, cache writes, and failures while fetching watchlist images. +- Added a `--debug` runtime flag for `Kaizoku` and `./Kaizoku` that logs thumbnail-source request flow, match decisions, responses, cache writes, and failures while fetching watchlist images. - Added support for the typo-tolerant `---debug` form as well, so debugging still works if that form is used by mistake. ## 0.8.0 - 2026-05-11 @@ -779,7 +785,7 @@ ## 0.2.2 - 2026-05-11 - Fixed a broken watchlist merge that caused `app.py` to fail during startup with an `IndentationError`. -- Restored the web server entrypoint so `./ani-cli-web` starts the local HTTP server again. +- Restored the web server entrypoint so `./Kaizoku` starts the local HTTP server again. - Repaired watchlist POST routes, storage lookups, and embedded page script placement so the watchlist UI can load and update cleanly. ## 0.2.1 - 2026-05-11 @@ -803,6 +809,6 @@ ## 0.1.0 - 2026-05-11 -- Split `ani-cli-web` into a standalone project that uses system-wide `ani-cli`. +- Split `Kaizoku` into a standalone project that uses system-wide `ani-cli`. - Added project hygiene files: `.gitignore`, `VERSION`, and this changelog. - Documented runtime state handling and standalone project layout. diff --git a/Dockerfile b/Dockerfile index b4836ea..ae1c758 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,10 +2,10 @@ FROM python:3.12-slim-bookworm ENV DEBIAN_FRONTEND=noninteractive \ PATH=/usr/local/bin:/usr/bin:/bin \ - ANI_CLI_DOWNLOAD_DIR=/downloads \ - ANI_CLI_WEB_HOST=0.0.0.0 \ - ANI_CLI_WEB_PORT=8421 \ - ANI_CLI_WEB_JOB_STDOUT=true \ + KAIZOKU_DOWNLOAD_DIR=/downloads \ + KAIZOKU_HOST=0.0.0.0 \ + KAIZOKU_PORT=8421 \ + KAIZOKU_JOB_STDOUT=true \ UPDATE_ON_START=false \ USER_UID= \ USER_GID= diff --git a/README.md b/README.md index daa162d..a3ef7aa 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Kaizoku -Kaizoku is a local web app for searching, tracking, and downloading anime from Anikoto, AniNeko, and AnimePahe. It keeps the previous ani-cli-web style and management flows, but the downloader no longer uses `ani-cli`, `anipy-cli`, or AllManga/AllAnime. +Kaizoku is a local web app for searching, tracking, and downloading anime from Anikoto, AniNeko, and AnimePahe. ## Features @@ -47,15 +47,14 @@ http://127.0.0.1:8421/ Useful environment variables: -- `ANI_CLI_WEB_HOST=0.0.0.0` -- `ANI_CLI_WEB_PORT=8421` -- `ANI_CLI_WEB_ALLOW_REMOTE=1` -- `ANI_CLI_WEB_AUTH_USERNAME=admin` -- `ANI_CLI_WEB_AUTH_PASSWORD=choose-a-long-random-password` -- `ANI_CLI_WEB_JOB_STDOUT=true` -- `ANI_CLI_WEB_STATE_ROOT=/path/to/state` - -The `ANI_CLI_WEB_*` names are kept as compatibility aliases while the app transitions from the previous project. +- `KAIZOKU_HOST=0.0.0.0` +- `KAIZOKU_PORT=8421` +- `KAIZOKU_ALLOW_REMOTE=1` +- `KAIZOKU_AUTH_USERNAME=admin` +- `KAIZOKU_AUTH_PASSWORD=choose-a-long-random-password` +- `KAIZOKU_JOB_STDOUT=true` +- `KAIZOKU_STATE_ROOT=/path/to/state` +- `KAIZOKU_DOWNLOAD_DIR=/downloads` ## Docker diff --git a/VERSION b/VERSION index 4bbc119..4f9b378 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.51.9 +0.52.0 diff --git a/app.py b/app.py index 631bae2..e80490b 100644 --- a/app.py +++ b/app.py @@ -24,9 +24,6 @@ import app_support import provider_bridge from app_support import ( AGENT, - ALLANIME_API, - ALLANIME_REFERER, - ALLMANGA_SITE_BASE, ANIDB_ANIME_PAGE, ANIDB_TITLES_CACHE, ANIDB_TITLES_PATH, @@ -37,6 +34,9 @@ from app_support import ( CONFIG_PATH, DEFAULT_CONFIG, MAX_JSON_BODY_BYTES, + METADATA_API, + METADATA_REFERER, + METADATA_SITE_BASE, MODE_CHOICES, QUALITY_CHOICES, send_discord_webhook_event, @@ -104,11 +104,11 @@ WATCHLIST_BACKUP_FORMAT_VERSION = 1 def graph_request(query, variables, timeout=25): payload = json.dumps({"variables": variables, "query": query}).encode("utf-8") request = urllib.request.Request( - f"{ALLANIME_API}/api", + f"{METADATA_API}/api", data=payload, headers={ "Content-Type": "application/json", - "Referer": ALLANIME_REFERER, + "Referer": METADATA_REFERER, "User-Agent": AGENT, }, method="POST", @@ -117,17 +117,17 @@ def graph_request(query, variables, timeout=25): with urllib.request.urlopen(request, timeout=timeout) as response: raw = response.read().decode("utf-8") except urllib.error.URLError as exc: - raise RuntimeError(f"Could not reach AllAnime: {exc}") from exc + raise RuntimeError(f"Could not reach metadata service: {exc}") from exc except TimeoutError as exc: - raise RuntimeError("AllAnime request timed out") from exc + raise RuntimeError("Metadata request timed out") from exc try: data = json.loads(raw) except json.JSONDecodeError as exc: - raise RuntimeError("AllAnime returned an unreadable response") from exc + raise RuntimeError("Metadata service returned an unreadable response") from exc if data.get("errors"): - message = data["errors"][0].get("message", "AllAnime returned an error") + message = data["errors"][0].get("message", "Metadata service returned an error") raise RuntimeError(message) return data.get("data", {}) @@ -163,8 +163,8 @@ def search_thumbnail_cache_key(title): def anime_source_url(show_id, title): normalized_show_id = str(show_id or "").strip() if not normalized_show_id: - return f"{ALLMANGA_SITE_BASE}/search-anime?tr=sub&cty=ALL&query={quote(str(title or '').strip(), safe='')}" - return f"{ALLMANGA_SITE_BASE}/bangumi/{quote(normalized_show_id, safe='')}" + return f"{METADATA_SITE_BASE}/search-anime?tr=sub&cty=ALL&query={quote(str(title or '').strip(), safe='')}" + return f"{METADATA_SITE_BASE}/bangumi/{quote(normalized_show_id, safe='')}" def infer_image_extension(url, content_type): @@ -2318,7 +2318,7 @@ class WatchlistStore: def import_backup(self, backup): if not isinstance(backup, dict): raise ValueError("Watchlist backup must be a JSON object.") - if backup.get("format") not in {"kaizoku-watchlist-backup", "ani-cli-web-watchlist-backup"}: + if backup.get("format") != "kaizoku-watchlist-backup": raise ValueError("Backup format is not recognized.") try: format_version = int(backup.get("format_version") or 0) @@ -3120,8 +3120,6 @@ def save_runtime_config(config): current = get_config_snapshot(fallback=DEFAULT_CONFIG) merged = dict(current) if isinstance(config, dict): - if "anipy_cli_fallback_enabled" in config and "download_methods" not in config: - merged.pop("download_methods", None) merged.update(config) normalized = normalize_config(merged) previous_fingerprint = remote_access_session_fingerprint(current) diff --git a/app_support.py b/app_support.py index 20f743c..bba39b6 100644 --- a/app_support.py +++ b/app_support.py @@ -38,16 +38,13 @@ def configured_cli_command(env_name, executable_name): KAIZOKU_DOWNLOADER = configured_cli_command("KAIZOKU_DOWNLOADER_BIN", "provider_downloader.py") -ANI_CLI = configured_cli_command("ANI_CLI_BIN", "ani-cli") -ANIPY_CLI = configured_cli_command("ANIPY_CLI_BIN", "anipy-cli") -ANIMDL = configured_cli_command("ANIMDL_BIN", "animdl") APP_NAME = "Kaizoku" VERSION_FILE = PROJECT_ROOT / "VERSION" CHANGELOG_FILE = PROJECT_ROOT / "CHANGELOG.md" -ALLANIME_BASE = "allanime.day" -ALLANIME_API = f"https://api.{ALLANIME_BASE}" -ALLANIME_REFERER = "https://allmanga.to" -ALLMANGA_SITE_BASE = "https://allmanga.to" +METADATA_API_HOST = "allanime.day" +METADATA_API = f"https://api.{METADATA_API_HOST}" +METADATA_REFERER = "https://allmanga.to" +METADATA_SITE_BASE = "https://allmanga.to" ANIMESCHEDULE_API = "https://animeschedule.net/api/v3" ANIMESCHEDULE_IMAGE_BASE = "https://img.animeschedule.net/production/assets/public/img/" ANIDB_TITLES_URL = "https://anidb.net/api/anime-titles.xml.gz" @@ -125,16 +122,24 @@ def env_flag(name, default=False): return str(raw).strip().lower() in {"1", "true", "yes", "on"} +def env_value(name, default="", aliases=()): + for key in (name, *aliases): + raw = os.environ.get(key) + if raw is not None and str(raw).strip(): + return str(raw).strip() + return default + + def debug_enabled(): - return DEBUG_MODE or env_flag("ANI_CLI_WEB_DEBUG") + return DEBUG_MODE or env_flag("KAIZOKU_DEBUG") def remote_access_allowed(): - return env_flag("ANI_CLI_WEB_ALLOW_REMOTE") + return env_flag("KAIZOKU_ALLOW_REMOTE") def remote_access_username(config=None): - configured = str(os.environ.get("ANI_CLI_WEB_AUTH_USERNAME") or "").strip() + configured = env_value("KAIZOKU_AUTH_USERNAME") if configured: return configured if isinstance(config, dict): @@ -143,7 +148,7 @@ def remote_access_username(config=None): def remote_access_password(config=None): - configured = str(os.environ.get("ANI_CLI_WEB_AUTH_PASSWORD") or "").strip() + configured = env_value("KAIZOKU_AUTH_PASSWORD") if configured: return configured if isinstance(config, dict): @@ -270,11 +275,11 @@ def clear_remote_access_sessions(config=None): def background_workers_enabled(): - return not env_flag("ANI_CLI_WEB_DISABLE_WORKER") + return not env_flag("KAIZOKU_DISABLE_WORKER") def job_stdout_enabled(): - return env_flag("ANI_CLI_WEB_JOB_STDOUT") + return env_flag("KAIZOKU_JOB_STDOUT") def client_address_is_local(host): @@ -302,8 +307,9 @@ def debug_log(event, **fields): def default_download_dir(): - if os.environ.get("ANI_CLI_DOWNLOAD_DIR"): - return os.environ["ANI_CLI_DOWNLOAD_DIR"] + configured = env_value("KAIZOKU_DOWNLOAD_DIR") + if configured: + return configured home_downloads = Path.home() / "Downloads" / "Anime" if os.access(home_downloads.parent if home_downloads.parent.exists() else Path.home(), os.W_OK): return str(home_downloads) @@ -312,9 +318,8 @@ def default_download_dir(): DEFAULT_CONFIG = { "download_dir": default_download_dir(), - "mode": os.environ.get("ANI_CLI_MODE", "sub"), - "quality": os.environ.get("ANI_CLI_QUALITY", "best"), - "anipy_cli_fallback_enabled": False, + "mode": env_value("KAIZOKU_MODE", "sub"), + "quality": env_value("KAIZOKU_QUALITY", "best"), "download_methods": ["kaizoku"], "provider": "anikoto", "watchlist_auto_refresh_enabled": False, @@ -328,8 +333,8 @@ DEFAULT_CONFIG = { "jellyfin_movie_dir": "", "discord_webhook_url": "", "discord_webhook_events": [], - "auth_username": str(os.environ.get("ANI_CLI_WEB_AUTH_USERNAME") or "").strip(), - "auth_password": str(os.environ.get("ANI_CLI_WEB_AUTH_PASSWORD") or "").strip(), + "auth_username": env_value("KAIZOKU_AUTH_USERNAME"), + "auth_password": env_value("KAIZOKU_AUTH_PASSWORD"), } PRIVATE_CONFIG_KEYS = {"auth_username", "auth_password"} @@ -339,7 +344,7 @@ def now_iso(): def project_app_root(): - configured = str(os.environ.get("ANI_CLI_WEB_STATE_ROOT") or "").strip() + configured = env_value("KAIZOKU_STATE_ROOT") if configured: return Path(configured).expanduser() return PROJECT_ROOT / ".kaizoku" @@ -473,7 +478,6 @@ def normalize_config(data): if quality.endswith("p") and quality[:-1].isdigit(): quality = quality[:-1] download_dir = str(config.get("download_dir") or DEFAULT_CONFIG["download_dir"]) - anipy_cli_fallback_enabled = config.get("anipy_cli_fallback_enabled") download_methods = config.get("download_methods") auto_refresh_enabled = config.get("watchlist_auto_refresh_enabled") auto_refresh_minutes = config.get("watchlist_auto_refresh_minutes") @@ -491,10 +495,6 @@ def normalize_config(data): auth_username = str(config.get("auth_username") or "").strip() auth_password = str(config.get("auth_password") or "").strip() - if isinstance(anipy_cli_fallback_enabled, str): - anipy_cli_fallback_enabled = anipy_cli_fallback_enabled.strip().lower() in {"1", "true", "yes", "on"} - else: - anipy_cli_fallback_enabled = bool(anipy_cli_fallback_enabled) if isinstance(download_methods, str): method_values = [part.strip().lower() for part in re.split(r"[\s,]+", download_methods) if part.strip()] elif isinstance(download_methods, list): @@ -541,7 +541,6 @@ def normalize_config(data): config["quality"] = quality if quality in QUALITY_CHOICES else "best" config["download_dir"] = str(Path(download_dir).expanduser()) config["download_methods"] = ["kaizoku"] - config["anipy_cli_fallback_enabled"] = False provider = str(config.get("provider") or DEFAULT_CONFIG.get("provider") or "anikoto").strip().lower() config["provider"] = provider if provider in PROVIDER_CHOICES else "anikoto" config["watchlist_auto_refresh_enabled"] = auto_refresh_enabled @@ -577,7 +576,7 @@ def sanitize_public_config(config): def _env_remote_path_roots(): - raw = str(os.environ.get("ANI_CLI_WEB_REMOTE_PATH_ROOTS") or "").strip() + raw = env_value("KAIZOKU_REMOTE_PATH_ROOTS") if not raw: return [] roots = [] @@ -1122,26 +1121,6 @@ def extract_episode_from_filename(path): return match.group(1) if match else None -def episode_values_from_spec(value): - spec = str(value or "").strip() - if not spec: - return [] - values = [] - for part in re.split(r"\s+", spec): - if not part: - continue - if "-" in part: - start_text, end_text = [piece.strip() for piece in part.split("-", 1)] - if start_text.isdigit() and end_text.isdigit(): - start = int(start_text, 10) - end = int(end_text, 10) - if start <= end: - values.extend(str(number) for number in range(start, end + 1)) - continue - values.append(part) - return values - - def unique_destination(path): if not path.exists(): return path @@ -1170,15 +1149,11 @@ def finalize_library_files(job): moved = [] fallback_episode = 1 - requested_episode_values = episode_values_from_spec(job.get("episodes")) - backend = str(job.get("download_backend") or "").strip().lower() for source in files: if media_type == "movie": final_name = f"{library_name}{source.suffix}" else: ep = None - if backend in {"anipy-cli", "animdl"} and requested_episode_values: - ep = requested_episode_values.pop(0) if ep is None: ep = extract_episode_from_filename(source) if ep is None: @@ -1255,12 +1230,6 @@ def normalize_result_index(value): return index -def anipy_search_spec(job): - query = re.sub(r"\s+", " ", str(job.get("query") or "").replace(":", " ")).strip() - mode = "dub" if str(job.get("mode") or "").strip().lower() == "dub" else "sub" - return f"{query}:{job['episodes']}:{mode}" - - def command_for_job(job, backend="kaizoku", download_path=None): show_id = str(job.get("show_id") or job.get("query") or "").strip() provider = str(job.get("provider") or "").strip().lower() diff --git a/config_page.py b/config_page.py index a4cf46b..6c8e507 100644 --- a/config_page.py +++ b/config_page.py @@ -446,7 +446,7 @@ CONFIG_HTML = r"""