A powerful Python-based rules engine for qBittorrent automation
Project description
qbt-rules
A powerful Python-based rules engine for automating torrent management in qBittorrent using declarative YAML configuration.
What is qbt-rules?
qbt-rules is a Python-based rules engine that automates torrent management through the qBittorrent Web API v5.0+. Define YAML-based rules to automatically categorize, tag, pause, resume, delete, and manage torrents based on flexible conditions.
Key Features:
- Declarative YAML Rules - No coding required, just write rules
- Multiple Trigger Types - Manual, scheduled (cron), webhooks (on_added, on_completed)
- Powerful Conditions - Complex logic with AND/OR/NOT groups, 17+ operators
- Rich Field Access - Dot notation access to all torrent metadata (info., trackers., files.*, etc.)
- Idempotent Actions - Safe to run repeatedly, actions skip if already applied
- Dry-Run Mode - Test rules without making changes
- Comprehensive Logging - Trace mode for debugging
Quick Start
Installation
Option 1: Install from PyPI (recommended)
# Install the package
pip install qbt-rules
# Create config directory
mkdir -p ~/.config/qbt-rules
# Download example configs
curl -o ~/.config/qbt-rules/config.yml \
https://raw.githubusercontent.com/andronics/qbt-rules/main/config/config.example.yml
curl -o ~/.config/qbt-rules/rules.yml \
https://raw.githubusercontent.com/andronics/qbt-rules/main/config/rules.example.yml
# Edit config with your qBittorrent credentials
nano ~/.config/qbt-rules/config.yml
Option 2: Install from source
# Clone the repository
git clone https://github.com/andronics/qbt-rules.git
cd qbt-rules
# Install in editable mode with development dependencies
pip install -e ".[dev]"
# Copy example configs
cp config/config.example.yml config/config.yml
cp config/rules.example.yml config/rules.yml
# Edit config with your qBittorrent credentials
nano config/config.yml
Your First Rule
Create a simple rule in config/rules.yml:
rules:
- name: "Auto-categorize HD movies"
enabled: true
stop_on_match: true
conditions:
trigger: on_added
all:
- field: info.name
operator: matches
value: '(?i).*(1080p|2160p|4k).*'
actions:
- type: set_category
params:
category: "Movies-HD"
- type: add_tag
params:
tag: "movies"
Run It
Using console script (after pip install):
# Test with dry-run (shows what would happen)
qbt-rules --dry-run
# Apply rules (defaults to manual trigger)
qbt-rules
# Enable trace logging for debugging
qbt-rules --trace
# Run with specific trigger
qbt-rules --trigger scheduled
# Process specific torrent
qbt-rules --trigger on_completed --torrent-hash abc123...
Using Python module:
python -m qbt_rules.cli --dry-run
How It Works
┌─────────────────────────────────────────────────────────────┐
│ TRIGGER ACTIVATION │
│ (Manual, Scheduled, on_added, on_completed) │
└────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ FETCH TORRENTS FROM qBittorrent │
│ (Optional: Apply filters by category/state) │
└────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ FOR EACH TORRENT: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Evaluate Rules in File Order │ │
│ │ ┌────────────────────────────────────────────────┐ │ │
│ │ │ Check Conditions (all/any/none groups) │ │ │
│ │ │ ├─ Access fields (info.*, trackers.*, etc.) │ │ │
│ │ │ ├─ Apply operators (==, >, contains, etc.) │ │ │
│ │ │ └─ Combine with AND/OR/NOT logic │ │ │
│ │ └────────────┬───────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ├─ Match? ──► Execute Actions │ │
│ │ │ (stop, categorize, etc.) │ │
│ │ │ │ │
│ │ └─ No Match? ──► Next Rule │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Rules execute top-to-bottom. Use stop_on_match: true to prevent later rules from running after a match.
Core Concepts
Triggers
| Trigger | Description | Use Case |
|---|---|---|
| manual | Run on-demand via CLI | Testing, one-time bulk operations |
| scheduled | Run by cron/systemd timer | Regular cleanup, maintenance |
| on_added | Webhook when torrent added | Auto-categorize new downloads |
| on_completed | Webhook when download completes | Post-processing, seeding rules |
📖 Detailed Trigger Documentation
Conditions
Combine conditions with logical groups:
- all - AND logic (all conditions must match)
- any - OR logic (at least one condition must match)
- none - NOT logic (no conditions can match)
Available Operators:
==, !=, >, <, >=, <=, contains, not_contains, matches, in, not_in, older_than, newer_than, smaller_than, larger_than
📖 Detailed Condition Documentation
Available Fields
Access torrent data using dot notation across 8 API categories:
| Prefix | Description | Example Fields |
|---|---|---|
info.* |
Main torrent info | info.name, info.size, info.ratio, info.state |
trackers.* |
Tracker data (collection) | trackers.url, trackers.status, trackers.msg |
files.* |
File list (collection) | files.name, files.size, files.progress |
properties.* |
Extended properties | properties.save_path, properties.comment |
transfer.* |
Global transfer stats | transfer.dl_speed_global, transfer.up_speed_global |
app.* |
Application info | app.version, app.api_version |
peers.* |
Peer data (collection) | peers.ip, peers.client, peers.progress |
webseeds.* |
Web seed data (collection) | webseeds.url |
Actions
Execute one or more actions when conditions match:
| Action | Description |
|---|---|
stop / start / force_start |
Control torrent state |
recheck / reannounce |
Maintenance operations |
delete_torrent |
Remove torrent (optionally with files) |
set_category |
Set torrent category |
add_tag / remove_tag / set_tags |
Manage tags |
set_upload_limit / set_download_limit |
Speed limiting |
📖 Detailed Action Documentation
Example Rules
Auto-Categorize by Content Type
- name: "Categorize TV shows"
enabled: true
stop_on_match: true
conditions:
trigger: on_added
all:
- field: info.name
operator: matches
value: '(?i).*[Ss]\d{2}[Ee]\d{2}.*'
actions:
- type: set_category
params:
category: "TV-Shows"
Cleanup Old Completed Torrents
- name: "Delete old seeded torrents"
enabled: true
conditions:
trigger: scheduled
all:
- field: info.state
operator: in
value: ["uploading", "pausedUP", "stalledUP"]
- field: info.completion_on
operator: older_than
value: 2592000 # 30 days
- field: info.ratio
operator: ">="
value: 2.0
actions:
- type: delete_torrent
params:
delete_files: false
Force Seed Low-Seeded Content
- name: "Force start underseded torrents"
enabled: true
conditions:
trigger: scheduled
all:
- field: info.num_complete
operator: "<="
value: 2
- field: info.state
operator: in
value: ["pausedUP", "stalledUP"]
actions:
- type: force_start
Pause Large Downloads
- name: "Pause very large downloads"
enabled: true
conditions:
trigger: on_added
all:
- field: info.size
operator: larger_than
value: "50 GB"
- field: info.state
operator: in
value: ["downloading", "metaDL"]
actions:
- type: stop
- type: add_tag
params:
tag: "large-download"
Deployment
Scheduled Execution with Cron
# Run every hour
0 * * * * qbt-rules --trigger scheduled
# Run daily at 3 AM
0 3 * * * qbt-rules --trigger scheduled
# Custom trigger at midnight
0 0 * * * qbt-rules --trigger nightly_cleanup
Systemd Timer
Create /etc/systemd/system/qbt-rules.service:
[Unit]
Description=qbt-rules - qBittorrent Automation
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/qbt-rules --trigger scheduled
User=qbittorrent
Environment="PATH=/usr/local/bin:/usr/bin:/bin"
Create /etc/systemd/system/qbt-rules.timer:
[Unit]
Description=Run qbt-rules hourly
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
Enable:
sudo systemctl enable qbt-rules.timer
sudo systemctl start qbt-rules.timer
Docker
FROM python:3.11-slim
WORKDIR /app
# Install the package
RUN pip install qbt-rules
# Copy configuration files
COPY config/ /app/config/
# Run scheduled trigger every hour
CMD ["sh", "-c", "while true; do qbt-rules --trigger scheduled; sleep 3600; done"]
Documentation
Complete documentation is available on the GitHub Wiki:
- Getting Started - Installation and first rule
- Configuration Reference - config.yml and rules.yml
- Rules Architecture - How rules are evaluated
- Triggers - Manual, scheduled, webhooks
- Conditions - Operators and logical groups
- Available Fields - Complete field reference
- Actions - All available actions
- Examples - Real-world use cases
- FAQ - Common questions
- Troubleshooting - Debug and fix issues
- Advanced Topics - Performance, security, extending
Requirements
- Python 3.8+
- qBittorrent v5.0+ with Web UI enabled
- Dependencies:
requests,pyyaml
Contributing
Contributions are welcome! Please see the Contributing Guide on the wiki.
Changelog
See CHANGELOG.md for version history and release notes.
Latest Release: v0.3.0 - 2024-12-13
License
This project is released into the public domain under the Unlicense.
You are free to use, modify, and distribute this software for any purpose without attribution.
Happy automating! 🚀
For detailed documentation, visit the GitHub Wiki.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qbt_rules-0.3.2rc2.tar.gz.
File metadata
- Download URL: qbt_rules-0.3.2rc2.tar.gz
- Upload date:
- Size: 28.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a76c531db43e4d8f046df6689803b030828f5ed1b0140af502493e54118114b4
|
|
| MD5 |
361dc5c6cce191d9731f9f45aced75fd
|
|
| BLAKE2b-256 |
2269b48dfbbdc2a64c0bffb32587d486971206c335f044ae0cf780bb53184046
|
Provenance
The following attestation bundles were made for qbt_rules-0.3.2rc2.tar.gz:
Publisher:
release.yml on andronics/qbt-rules
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qbt_rules-0.3.2rc2.tar.gz -
Subject digest:
a76c531db43e4d8f046df6689803b030828f5ed1b0140af502493e54118114b4 - Sigstore transparency entry: 763534755
- Sigstore integration time:
-
Permalink:
andronics/qbt-rules@be1f3bcbe898a221131f3c1c8e4a2625a4d151fc -
Branch / Tag:
refs/tags/v0.3.2rc2 - Owner: https://github.com/andronics
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@be1f3bcbe898a221131f3c1c8e4a2625a4d151fc -
Trigger Event:
push
-
Statement type:
File details
Details for the file qbt_rules-0.3.2rc2-py3-none-any.whl.
File metadata
- Download URL: qbt_rules-0.3.2rc2-py3-none-any.whl
- Upload date:
- Size: 26.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
509f52d5aac5859111001b51e3dec5c6ef96647bd84880fa6b816163a695de11
|
|
| MD5 |
c01fc8adddc752ad6a1d2f9f076123f7
|
|
| BLAKE2b-256 |
b4bef342133e5df738b01a944259a11eaed508befa68a58bfe27a18a3c17704d
|
Provenance
The following attestation bundles were made for qbt_rules-0.3.2rc2-py3-none-any.whl:
Publisher:
release.yml on andronics/qbt-rules
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qbt_rules-0.3.2rc2-py3-none-any.whl -
Subject digest:
509f52d5aac5859111001b51e3dec5c6ef96647bd84880fa6b816163a695de11 - Sigstore transparency entry: 763534759
- Sigstore integration time:
-
Permalink:
andronics/qbt-rules@be1f3bcbe898a221131f3c1c8e4a2625a4d151fc -
Branch / Tag:
refs/tags/v0.3.2rc2 - Owner: https://github.com/andronics
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@be1f3bcbe898a221131f3c1c8e4a2625a4d151fc -
Trigger Event:
push
-
Statement type: