-
Notifications
You must be signed in to change notification settings - Fork 0
Conditions
Conditions determine which torrents match a rule. Three logical groups are available: all, any, and none.
Condition Groups:
| Group | Logic | Description | Use When |
|---|---|---|---|
all |
AND | Every condition must be true | Need multiple criteria simultaneously |
any |
OR | At least one condition must be true | Match alternatives or broad filtering |
none |
NOT | No conditions can be true | Exclusions or inverse matching |
Combining Groups:
- All three groups can be used together
- All groups must pass for the rule to match
- Empty/missing groups are ignored (treated as pass)
Description: Every condition in the all list must be true for the group to pass.
Structure:
conditions:
all:
- field: info.name
operator: contains
value: "1080p"
- field: info.category
operator: ==
value: ""
- field: info.size
operator: ">"
value: 1073741824
# ALL three must be true: name has "1080p" AND no category AND size > 1GBUse Cases:
- Narrow down matches - Require multiple criteria
- Precise filtering - All conditions must align
- Most common pattern - Default choice for most rules
Examples:
# HD movies without category
conditions:
all:
- field: info.name
operator: matches
value: '(?i).*(1080p|2160p).*'
- field: info.category
operator: ==
value: ""# Private tracker torrents over 2.0 ratio
conditions:
all:
- field: info.ratio
operator: ">="
value: 2.0
- field: trackers.url
operator: contains
value: ".private"# Old completed torrents not in keep category
conditions:
all:
- field: info.completion_on
operator: older_than
value: 30 days
- field: info.ratio
operator: ">="
value: 1.0
- field: info.category
operator: "!="
value: keepDescription: At least one condition in the any list must be true for the group to pass.
Structure:
conditions:
any:
- field: info.state
operator: ==
value: error
- field: info.state
operator: ==
value: missingFiles
- field: info.state
operator: ==
value: stalledDL
# ANY one must be true: state=error OR state=missingFiles OR state=stalledDLUse Cases:
- Match alternatives - Multiple acceptable patterns
- Broad filtering - "Either this OR that"
- List of exceptions - Match any of several values
Examples:
# Remove torrents in error states
conditions:
any:
- field: info.state
operator: ==
value: error
- field: info.state
operator: ==
value: missingFiles# Match either 1080p or 2160p resolution
conditions:
any:
- field: info.name
operator: contains
value: "1080p"
- field: info.name
operator: contains
value: "2160p"# Block multiple file extensions
conditions:
any:
- field: files.name
operator: matches
value: '(?i)\.rar$'
- field: files.name
operator: matches
value: '(?i)\.zip$'
- field: files.name
operator: matches
value: '(?i)\.7z$'Tip: For list matching, use in operator instead:
# Simpler alternative to above
conditions:
any:
- field: info.state
operator: in
value: [error, missingFiles, stalledDL]Description: No conditions in the none list can be true for the group to pass.
Structure:
conditions:
none:
- field: info.category
operator: in
value: [keep, seedbox]
- field: info.tags
operator: contains
value: "permanent"
# NONE can be true: NOT (category in [keep, seedbox]) AND NOT (has "permanent" tag)Use Cases:
- Exclusions - Exclude specific cases
- Inverse filtering - "Everything except..."
- "Unless" clauses - Do action unless condition is true
Examples:
# Delete old torrents NOT in keep category
conditions:
all:
- field: info.completion_on
operator: older_than
value: 30 days
none:
- field: info.category
operator: ==
value: keep# Apply limits EXCEPT to private trackers
conditions:
all:
- field: info.ratio
operator: ">="
value: 2.0
none:
- field: trackers.url
operator: contains
value: ".private"# Stop seeding UNLESS in seedbox category
conditions:
all:
- field: info.ratio
operator: ">="
value: 3.0
- field: info.seeding_time
operator: ">"
value: 2592000 # 30 days
none:
- field: info.category
operator: ==
value: seedboxYou can use multiple groups together. All groups must pass for the rule to match.
Pattern 1: all + none ("Match these, except...")
conditions:
all:
- field: info.ratio
operator: ">="
value: 2.0
- field: info.completion_on
operator: older_than
value: 7 days
none:
- field: info.category
operator: in
value: [keep, seedbox, long-term]
# Match: ratio >= 2.0 AND completed > 7 days ago
# Except: NOT in categories keep/seedbox/long-termPattern 2: any + all ("Match any of these, but also require...")
conditions:
any:
- field: info.name
operator: contains
value: "1080p"
- field: info.name
operator: contains
value: "2160p"
all:
- field: info.size
operator: ">"
value: 5368709120 # > 5GB
- field: info.category
operator: ==
value: ""
# Match: (1080p OR 2160p) AND size > 5GB AND no categoryPattern 3: all + any + none (Complex filtering)
conditions:
all:
- field: info.completion_on
operator: older_than
value: 14 days
any:
- field: info.ratio
operator: ">="
value: 3.0
- field: info.num_leechs
operator: ==
value: 0
none:
- field: info.category
operator: in
value: [seedbox, permanent]
- field: trackers.url
operator: contains
value: ".private"
# Match: completed > 14 days ago
# AND (ratio >= 3.0 OR no leeches)
# AND NOT (in seedbox/permanent categories)
# AND NOT (private tracker)Equality Operators
| Operator | Description | Value Types | Example |
|---|---|---|---|
== |
Exact match (equals) | string, number, boolean | info.category == "movies" |
!= |
Not equal | string, number, boolean | info.state != "error" |
Comparison Operators
| Operator | Description | Value Types | Example |
|---|---|---|---|
> |
Greater than | number | info.ratio > 2.0 |
< |
Less than | number | info.size < 1073741824 |
>= |
Greater than or equal | number | info.ratio >= 1.0 |
<= |
Less than or equal | number | info.progress <= 0.5 |
String Operators
| Operator | Description | Case Sensitive | Example |
|---|---|---|---|
contains |
Substring match | Yes | info.name contains "1080p" |
not_contains |
Does not contain | Yes | info.name not_contains "sample" |
matches |
Regex pattern match | Depends on regex | info.name matches "(?i).*s\d{2}e\d{2}.*" |
List Operators
| Operator | Description | Example |
|---|---|---|
in |
Value is in list | info.state in ["error", "missingFiles"] |
not_in |
Value is not in list | info.category not_in ["keep", "seedbox"] |
Time Operators
| Operator | Description | Value Format | Example |
|---|---|---|---|
older_than |
Unix timestamp older than | "N days" or "N hours" | info.added_on older_than "30 days" |
newer_than |
Unix timestamp newer than | "N days" or "N hours" | info.completion_on newer_than "7 days" |
Time Value Formats:
- Days:
"7 days","30 days","1 day" - Hours:
"12 hours","48 hours","1 hour" - Minutes:
"30 minutes","90 minutes","1 minute"
Operator Behavior with None/Missing Values:
| Operator Type | Behavior when field is None/missing |
|---|---|
!=, not_in, not_contains
|
Returns true
|
| All others | Returns false
|
Collection Field Behavior:
For collection fields (trackers.*, files.*, peers.*, webseeds.*):
- Operators check if ANY item in the collection matches
- Returns
trueif at least one item matches
Examples:
# Equality
- field: info.category
operator: ==
value: "movies"
# Comparison
- field: info.ratio
operator: ">="
value: 2.0
# String contains
- field: info.name
operator: contains
value: "1080p"
# Regex (case-insensitive TV show pattern)
- field: info.name
operator: matches
value: '(?i).*s\d{2}e\d{2}.*'
# List membership
- field: info.state
operator: in
value: ["error", "missingFiles", "stalledDL"]
# Time-based (older than 30 days)
- field: info.added_on
operator: older_than
value: "30 days"
# Collection (ANY tracker contains ".private")
- field: trackers.url
operator: contains
value: ".private"qbt-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)