-
Notifications
You must be signed in to change notification settings - Fork 0
Advanced Topics
The system caches API responses per-torrent to minimize calls:
# First access to trackers.url: API call made and cached
if torrent["trackers.url"] contains "example.com":
...
# Second access to trackers.url: Uses cached data (no API call)
if torrent["trackers.url"] contains "private":
...Best practices:
-
Access fields in order of expense:
# Check cheap fields first all: - field: info.category # Free operator: "==" value: "Movies" - field: files.name # Expensive, but only if category matches operator: matches value: '.*\.mkv$'
-
Reuse field references:
# BAD: Multiple string operations any: - field: info.name operator: contains value: "1080p" - field: info.name operator: contains value: "2160p" # GOOD: Single regex any: - field: info.name operator: matches value: '(?i).*(1080p|2160p).*'
Rules execute top-to-bottom. Order matters for performance:
# GOOD: Specific rules first, then general
- name: "High-priority: Private trackers"
stop_on_match: true
conditions:
all:
- field: trackers.url
operator: contains
value: "privatehd.to"
- name: "General cleanup"
conditions:
# This only runs if private tracker rule didn't matchNever hardcode credentials in config files:
# BAD
qbittorrent:
username: admin
password: MyPassword123
# GOOD
qbittorrent:
username: ${QB_USERNAME}
password: ${QB_PASSWORD}Set environment variables:
export QB_USERNAME="admin"
export QB_PASSWORD="secure_password"Protect config files containing credentials:
# Restrict access to config files
chmod 600 ~/.config/qbt-rules/config.yml
chown $USER:$USER ~/.config/qbt-rules/config.ymlFor qBittorrent webhook integration:
-
Restrict command execution: Ensure qBittorrent process can only execute
qbt-rules - Validate config access: Ensure qBittorrent can only access its own config directory
- Use environment variables: Pass credentials via environment, not config files
- Monitor logs: Check qBittorrent logs for unauthorized webhook executions
Scenario: Auto-categorize torrents added by Sonarr/Radarr
-
Configure qBittorrent webhook:
- Open qBittorrent → Tools → Options → Downloads
- Set "Run external program on torrent added":
qbt-rules --trigger on_added --hash "%I" -
Create categorization rules:
- name: "Categorize Sonarr downloads" conditions: trigger: on_added all: - field: info.category operator: "==" value: "tv-sonarr" actions: - type: add_tag params: tag: "sonarr"
Scenario: Run custom script after specific condition
While the system doesn't directly support script execution, you can:
- Tag torrents with automation rules
-
Monitor tags with external script:
#!/bin/bash # Watch for "process-me" tag TAGGED=$(curl -s http://localhost:8080/api/v2/torrents/info | \ jq -r '.[] | select(.tags | contains("process-me")) | .hash') for hash in $TAGGED; do # Run your custom logic ./process-torrent.sh "$hash" done
Scenario: Send notifications when rules match
Implement custom action type (requires code modification):
# lib/actions.py
def send_notification(torrent, params):
import requests
message = params.get("message", "Rule matched")
requests.post("https://ntfy.sh/qbittorrent",
data=message.encode('utf-8'))Then use in rules:
actions:
- type: send_notification
params:
message: "Torrent {info.name} completed!"Edit src/qbt_rules/engine.py to add new comparison operators:
def evaluate_condition(torrent, condition):
# ... existing code ...
elif operator == "starts_with":
return str(field_value).startswith(str(value))
elif operator == "ends_with":
return str(field_value).endswith(str(value))Then use in rules:
- field: info.name
operator: starts_with
value: "Ubuntu"Note: If you extend the codebase, install in editable mode:
pip install -e .Edit src/qbt_rules/actions.py:
def set_priority(api, torrent_hash, params):
"""Set torrent priority"""
priority = params.get("priority", "normal")
# Implement priority logic
api.post(f"/api/v2/torrents/setPriority",
data={"hashes": torrent_hash, "priority": priority})Register in action mapping:
ACTION_MAP = {
# ... existing actions ...
"set_priority": set_priority,
}Use in rules:
actions:
- type: set_priority
params:
priority: "high"New in v0.3.0: Define custom trigger names without code changes!
Simply use --trigger with any name you want:
# Define custom triggers
qbt-rules --trigger hourly
qbt-rules --trigger weekend
qbt-rules --trigger low-bandwidth
qbt-rules --trigger maintenanceThen filter rules by your custom trigger:
- name: "Weekend high-bandwidth downloads"
conditions:
trigger: weekend
all:
- field: info.size
operator: larger_than
value: "50GB"
actions:
- type: force_start
- name: "Hourly cleanup"
conditions:
trigger: [hourly, manual] # Runs on multiple triggers
all:
- field: info.ratio
operator: ">="
value: 2.0
actions:
- type: delete_torrent
params:
keep_files: trueCron examples:
# Run hourly cleanup every hour
0 * * * * qbt-rules --trigger hourly
# Run weekend rules on Saturday/Sunday
0 0 * * 6,0 qbt-rules --trigger weekend
# Run maintenance at 3 AM
0 3 * * * qbt-rules --trigger maintenanceRun multiple instances with different config directories:
Instance 1 - Categorization (runs frequently):
# Cron: Every 15 minutes
*/15 * * * * qbt-rules --trigger scheduled --config-dir /config/categorizationInstance 2 - Cleanup (runs daily):
# Cron: Daily at 3 AM
0 3 * * * qbt-rules --trigger scheduled --config-dir /config/cleanupInstance 3 - Webhooks (qBittorrent configuration):
# In qBittorrent → Tools → Options → Downloads
qbt-rules --trigger on_added --hash "%I"
qbt-rules --trigger on_completed --hash "%I"For very large torrent libraries (10,000+), implement batch processing:
# Process torrents in chunks of 100
BATCH_SIZE = 100
for i in range(0, len(all_torrents), BATCH_SIZE):
batch = all_torrents[i:i+BATCH_SIZE]
engine.execute(api, batch)
time.sleep(1) # Rate limitingqbt-rules v0.3.0 | Python-based rules engine for qBittorrent automation
GitHub • PyPI • Issues • Discussions • Contributing • License
Requirements: Python 3.8+ • qBittorrent 5.0+
Made with ❤️ by the qbt-rules community | Licensed under MIT
v0.3.0 | GitHub
- ✅ Unified CLI (
qbt-rules) - ✅ Custom triggers
- ✅ Trigger-agnostic mode
- ✅ Size operators (
50GB)