fix: resolve the seven bugs pinned by the test audit
test / unit-tests (push) Successful in 14s
ci / docker (push) Successful in 23s
test / unit-tests (pull_request) Successful in 6s
test / komodo-deploy-script (push) Successful in 23s
test / komodo-deploy-script (pull_request) Successful in 16s

- read [ignored_tags] instead of [ignored_domains], so tag-based ignoring
  actually works
- match ignored tags as whole tags, not substrings ('ipt' no longer matches
  'iptorrents')
- send the login-error notification through the Pushover client instead of
  the non-existent module-level send_message()
- handle an empty torrent list instead of raising IndexError before any
  summary is sent
- tag a new torrent once instead of once per code path
- honour toml_path without DOCKER in AppriseClient
- close replaced log handlers so the file descriptor is released

Also add the missing [telemetry] section to config.toml.example, which
qbit-maid.py requires at startup.

The tests that pinned each bug now assert the fixed behaviour, and the
suite still reports 100% coverage.
This commit is contained in:
trex Bot committed 2026-11-03 16:10:19 -06:00
1 parent ab46ea1fb2
commit d8034278d8
10 files changed
+207 -92

No files matched your search

+27 -14
View File
@@ -22,24 +22,22 @@ def build_tor_list(self):
self.ignored_counter += 1
continue
if is_tag_blank(torrent['tags']):
self.tl.debug(f'Tagging new torrent: ["{torrent["name"][0:20]}..."] {torrent["tracker"]}hash: {torrent["hash"]}')
if is_protected_tracker(torrent['tracker'], self.tracker_whitelist.values()):
self.qbt_client.torrents_add_tags(self.tracker_protected_tag,torrent['hash'])
elif is_not_protected_tracker(torrent['tracker'], self.tracker_whitelist.values()):
self.qbt_client.torrents_add_tags(self.tracker_non_protected_tag,torrent['hash'])
tag = torrent_tag_for(
torrent['tracker'],
self.tracker_protected_tag,
self.tracker_non_protected_tag,
self.tracker_whitelist.values(),
)
if tag:
self.tl.debug(f'Tagging new torrent: ["{torrent["name"][0:20]}..."] {torrent["tracker"]}hash: {torrent["hash"]}')
self.qbt_client.torrents_add_tags(tag, torrent['hash'])
if is_preme(torrent['seeding_time'], self.min_age):
self.preme_tor_counter += 1
self.tl.debug(f'Premature torrent: ["{torrent["name"][0:20]}..."] Seconds Seeded: [{torrent["seeding_time"]}] hash: {torrent["hash"]}')
continue
elif is_protected_tracker(torrent['tracker'], self.tracker_whitelist.values()):
if is_tag_blank(torrent['tags']):
self.qbt_client.torrents_add_tags(self.tracker_protected_tag,torrent['hash'])
self.tl.debug(f'Tagging Protected torrent: ["{torrent["name"][0:20]}..."] {torrent["tracker"]}hash: {torrent["hash"]}')
self.tracker_list.append(torrent)
elif is_not_protected_tracker(torrent['tracker'], self.tracker_whitelist.values()):
if is_tag_blank(torrent['tags']):
self.qbt_client.torrents_add_tags(self.tracker_non_protected_tag,torrent['hash'])
self.tl.debug(f'Tagging Non-protected torrent: ["{torrent["name"][0:20]}..."] {torrent["tracker"]}hash: {torrent["hash"]}')
self.tracker_list.append(torrent)
@@ -67,11 +65,26 @@ def is_not_protected_tracker(tracker, trackerlist):
if tracker.split('/')[2] not in trackerlist:
return True
def torrent_tag_for(tracker, protected_tag, non_protected_tag, trackerlist):
"""Return the tag a torrent should carry, or None for an unknown tracker."""
if is_protected_tracker(tracker, trackerlist):
return protected_tag
if is_not_protected_tracker(tracker, trackerlist):
return non_protected_tag
return None
def is_tag_blank(tag):
if tag == '':
return True
def is_ignored_tag(igtags, tortags):
for igt in igtags:
if igt in tortags:
return True
"""True when the torrent carries one of the configured ignored tags.
qBittorrent returns tags as a comma-separated string, so the comparison is
per tag: a configured ``ipt`` must not match a torrent tagged
``iptorrents``.
"""
if not tortags:
return False
torrent_tags = {tag.strip() for tag in str(tortags).split(',') if tag.strip()}
return any(igt in torrent_tags for igt in igtags)