Skip to content

feat(downloaders): Add WebUI API key support for qBittorrent - #2860

Open
hymccord wants to merge 1 commit into
TRaSH-Guides:masterfrom
hymccord:feat/downloaders-qbit-allow-webapi-key
Open

feat(downloaders): Add WebUI API key support for qBittorrent#2860
hymccord wants to merge 1 commit into
TRaSH-Guides:masterfrom
hymccord:feat/downloaders-qbit-allow-webapi-key

Conversation

@hymccord

@hymccord hymccord commented Aug 18, 2026

Copy link
Copy Markdown

Pull Request

Purpose

Adds optional WebUI API key support for qBittorrent mover tuning

Approach

  • Adds optional API_KEYS array support alongside existing NAMES, HOSTS, USERS, PASSWORDS and CA_BUNDLES arrays.
  • Allows each qBittorrent instance to define its own WebUI API key (introduced in qBittorrent 5.2.0)
  • Validates API_KEYS, when configured, matches the number of HOSTS.
  • Passes --api-key to mover.py only when an API key is configured for that instance

This depends on mover.py supporting the new --api-key option.

Open Questions and Pre-Merge TODOs

Requirements

Summary by Sourcery

Support qBittorrent WebUI API key authentication across the cache mover start and end workflows.

New Features:

  • Add optional per-instance qBittorrent WebUI API key configuration for mover tuning.

Enhancements:

  • Use API-key authentication when configured while retaining username/password authentication as a fallback.
  • Validate configured API key arrays against the number of qBittorrent hosts and support the setting in both legacy and array-based configurations.

Documentation:

  • Document API key configuration and authentication precedence in the mover tuning configuration.

Chores:

  • Bump mover script and configuration versions.

Copilot AI lite review requested due to automatic review settings August 18, 2026 01:51
@sourcery-ai

sourcery-ai Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Add optional per-instance qBittorrent WebUI API key support to the mover tuning start/end scripts and configuration, with validation and argument wiring to pass --api-key to mover.py when configured, while preserving legacy username/password authentication and updating script/config version metadata.

Sequence diagram for mover.py authentication selection with optional WebUI API key

sequenceDiagram
    actor Admin
    participant mover_tuning_start_sh as mover-tuning-start.sh
    participant process_qbit_instance
    participant mover_py as mover.py

    Admin->>mover_tuning_start_sh: main()
    mover_tuning_start_sh->>process_qbit_instance: process_qbit_instance(INSTANCE_NAME, INSTANCE_HOST, INSTANCE_USER, INSTANCE_PASSWORD, INSTANCE_API_KEY, INSTANCE_CA_BUNDLE)

    alt [INSTANCE_API_KEY non-empty]
        process_qbit_instance->>mover_py: python_cmd MOVER_SCRIPT --api-key INSTANCE_API_KEY
    else [INSTANCE_API_KEY empty]
        process_qbit_instance->>mover_py: python_cmd MOVER_SCRIPT --user INSTANCE_USER --password INSTANCE_PASSWORD
    end

    mover_py-->>process_qbit_instance: stdout/stderr
    process_qbit_instance-->>mover_tuning_start_sh: log()/notify()
Loading

Flow diagram for qBittorrent authentication precedence in mover-tuning scripts

flowchart TD
    A["process_qbit_instance start"] --> B{api_key non-empty?}
    B -->|Yes| C["mover_args += --api-key api_key"]
    B -->|No| D["mover_args += --user user --password password"]
    C --> E["optional: mover_args += --ca-bundle ca_bundle"]
    D --> E
    E --> F["python_cmd MOVER_SCRIPT mover_args"]
Loading

File-Level Changes

Change Details Files
Add per-instance API key handling and pass-through in mover-tuning start script.
  • Extend instance details resolution to read API_KEYS array entries and legacy QBIT_API_KEY_* variables.
  • Validate API_KEYS array length against HOSTS when array-based configuration is used.
  • Update process_qbit_instance to accept an API key parameter, build a unified mover_args array, and prefer --api-key over --user/--password when invoking mover.py.
  • Adjust main loop to pass INSTANCE_API_KEY into process_qbit_instance and bump script version metadata.
includes/downloaders/mover-tuning-start.sh
Add per-instance API key handling and pass-through in mover-tuning end script.
  • Extend instance details resolution to read API_KEYS array entries and legacy QBIT_API_KEY_* variables.
  • Validate API_KEYS array length against HOSTS when array-based configuration is used.
  • Update process_qbit_instance to accept an API key parameter, build a unified mover_args array, and prefer --api-key over --user/--password when invoking mover.py.
  • Adjust main loop to pass INSTANCE_API_KEY into process_qbit_instance and bump script version metadata.
includes/downloaders/mover-tuning-end.sh
Extend mover-tuning configuration to document and configure API key support and update config version.
  • Bump CONFIG_VERSION to reflect configuration format changes.
  • Update configuration comments to describe optional API_KEYS, precedence over USER/PASSWORD, and array length requirements.
  • Provide example USERS/PASSWORDS/API_KEYS values illustrating mixed auth modes across instances.
includes/downloaders/mover-tuning.cfg

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions github-actions Bot added the Area: Guide Guide documentation related label Aug 18, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • In mover-tuning-end.sh, the refactor to mover_args dropped the explicit --resume flag that was previously passed to mover.py; if this flag is still required to resume torrents, it should be added to mover_args to preserve behavior.
  • The config comment says API_KEYS "override username/password authentication if provided", but both scripts still always pass --user/--password alongside --api-key; consider either omitting credentials when an API key is set or adjusting the comment to reflect the actual behavior.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `mover-tuning-end.sh`, the refactor to `mover_args` dropped the explicit `--resume` flag that was previously passed to `mover.py`; if this flag is still required to resume torrents, it should be added to `mover_args` to preserve behavior.
- The config comment says `API_KEYS` "override username/password authentication if provided", but both scripts still always pass `--user`/`--password` alongside `--api-key`; consider either omitting credentials when an API key is set or adjusting the comment to reflect the actual behavior.

## Individual Comments

### Comment 1
<location path="includes/downloaders/mover-tuning-end.sh" line_range="458-465" />
<code_context>
     fi

-    local ca_bundle_args=()
+    local mover_args=(
+        --pause
+        --host "$host"
+        --user "$user"
+        --password "$password"
+        --cache-mount "$CACHE_MOUNT"
+        --days_from "$DAYS_FROM"
+        --days_to "$DAYS_TO"
+    )
+
</code_context>
<issue_to_address>
**issue (bug_risk):** End script is still using `--pause` and `--cache-mount`, and never passes `--resume` to `mover.py`.

Here you’re still passing `--pause` and `--cache-mount` and never `--resume`. The end script used to call `mover.py` with `--resume` (and without `--cache-mount`), which matches its role of resuming torrents. This looks like a copy from the start script and will likely invert the behavior. Please switch `--pause` to `--resume` here and drop any flags not needed for the resume flow.
</issue_to_address>

### Comment 2
<location path="includes/downloaders/mover-tuning.cfg" line_range="22-27" />
<code_context>
 # qBittorrent instances
 # Supports unlimited qBittorrent instances
-# Arrays NAMES, HOSTS, USERS and PASSWORDS must all have the same length
+# Arrays NAMES, HOSTS, USERS, PASSWORDS and API_KEYS must all have the same length
 # NAMES array is optional - if omitted, instances will be named "qBit-Instance-1", "qBit-Instance-2", etc.
+# API_KEYS array is optional but will override username/password authentication if provided
 readonly NAMES=("qBit-Movies" "qBit-TV" "qBit-Music")  # qBittorrent instance names
 readonly HOSTS=("192.168.2.200:8088" "192.168.2.200:8811" "192.168.2.200:8822")  # qBittorrent host:port
</code_context>
<issue_to_address>
**suggestion:** Config comments about API_KEYS length are slightly misleading versus the actual validation logic.

The updated comment says all arrays, including `API_KEYS`, must have the same length, but the scripts treat `API_KEYS` as optional and only validate its length when it’s present and non-empty. Please adjust the comment to state that `API_KEYS` is optional and only needs to match the other arrays when defined, to better reflect the actual behavior and avoid config confusion.

```suggestion
# qBittorrent instances
# Supports unlimited qBittorrent instances
# Arrays NAMES, HOSTS, USERS and PASSWORDS must all have the same length; API_KEYS is optional and only needs to match when defined
# NAMES array is optional - if omitted, instances will be named "qBit-Instance-1", "qBit-Instance-2", etc.
# API_KEYS array is optional but will override username/password authentication if provided
readonly NAMES=("qBit-Movies" "qBit-TV" "qBit-Music")  # qBittorrent instance names
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread includes/downloaders/mover-tuning-end.sh
Comment thread includes/downloaders/mover-tuning.cfg
@github-actions

Copy link
Copy Markdown
Contributor

Deploying with ⚡ Cloudflare Pages

Latest commit:8dfae7e65dc6a159d9104d8bccedf7b643285813
Status: ✅  Deploy successful!
Preview URL:https://dde5c06c.trash-guides-6xu.pages.dev
Branch Preview URL:https://pr-2860.trash-guides-6xu.pages.dev

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds optional per-instance qBittorrent WebUI API key support to the mover-tuning configuration and start/end scripts, enabling API-key authentication (qBittorrent 5.2.0+) alongside the existing username/password flow.

Changes:

  • Add API_KEYS array support in mover-tuning.cfg, and legacy QBIT_API_KEY_1/2 support in the scripts.
  • Validate API_KEYS length (when present) matches HOSTS.
  • Pass --api-key through to mover.py when configured.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
includes/downloaders/mover-tuning.cfg Bumps config version and documents/adds the API_KEYS array example.
includes/downloaders/mover-tuning-start.sh Adds API key handling, validation, and forwards --api-key to mover.py for pause phase.
includes/downloaders/mover-tuning-end.sh Adds API key handling, validation, and forwards --api-key to mover.py for resume phase.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread includes/downloaders/mover-tuning.cfg Outdated
Comment thread includes/downloaders/mover-tuning-start.sh
Comment thread includes/downloaders/mover-tuning-end.sh
@hymccord

Copy link
Copy Markdown
Author

I did change the mover-tuning.cfg USERS and PASSWORDS to show that both setting a user/pass and api key at the same time is supported as well as not setting a user/pass but specifying an API key is as well.

Feedback appreciated.

Tested on my instance of unRaid with the updated mover.py in various permutations of user/pass & api keys.

@hymccord
hymccord force-pushed the feat/downloaders-qbit-allow-webapi-key branch from 8dfae7e to 079a88d Compare August 18, 2026 01:55
@github-actions

Copy link
Copy Markdown
Contributor

Deploying with ⚡ Cloudflare Pages

Latest commit:079a88d402e8e4698f56ed3a6f428f7bab2344bb
Status: ✅  Deploy successful!
Preview URL:https://360e4cd6.trash-guides-6xu.pages.dev
Branch Preview URL:https://pr-2860.trash-guides-6xu.pages.dev

@hymccord
hymccord force-pushed the feat/downloaders-qbit-allow-webapi-key branch from 079a88d to acb512c Compare August 18, 2026 14:25
@hymccord

Copy link
Copy Markdown
Author

@sourcery-ai review

@github-actions

Copy link
Copy Markdown
Contributor

Deploying with ⚡ Cloudflare Pages

Latest commit:acb512cc29b1aaa1da60db1c10eefa4095148357
Status: ✅  Deploy successful!
Preview URL:https://41125910.trash-guides-6xu.pages.dev
Branch Preview URL:https://pr-2860.trash-guides-6xu.pages.dev

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In process_qbit_instance for both start and end scripts, you now rely on api_key being non-empty to decide auth mode; consider explicitly handling the case where both API key and user/password are unset to fail fast with a clear error rather than relying on qBittorrent/mover.py behavior.
  • The config header comments now state that NAMES, API_KEYS and CA_BUNDLES must match HOSTS length, but validate_config only enforces that for API_KEYS and CA_BUNDLES; if NAMES mismatch should be allowed, reword the comment for clarity, otherwise add a length check for NAMES in start.sh to mirror end.sh.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `process_qbit_instance` for both start and end scripts, you now rely on `api_key` being non-empty to decide auth mode; consider explicitly handling the case where both API key and user/password are unset to fail fast with a clear error rather than relying on qBittorrent/mover.py behavior.
- The config header comments now state that NAMES, API_KEYS and CA_BUNDLES must match HOSTS length, but `validate_config` only enforces that for API_KEYS and CA_BUNDLES; if NAMES mismatch should be allowed, reword the comment for clarity, otherwise add a length check for NAMES in start.sh to mirror end.sh.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@TRaSH-

TRaSH- commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

@bz could you take a look at this one?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: Guide Guide documentation related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants