From 32f2da75c99b2731674a0a6c292fb00ee4e21111 Mon Sep 17 00:00:00 2001 From: Bakerboy448 <55419169+bakerboy448@users.noreply.github.com> Date: Tue, 4 Apr 2023 17:23:30 -0500 Subject: [PATCH 1/9] (fix) qbit nohardlinks ratio/seed time if tracker not set (fix) not falling back to default for nohardlinks goals if not set Fixes #255 --- modules/qbittorrent.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/qbittorrent.py b/modules/qbittorrent.py index 27e82b9..e0d8a9e 100755 --- a/modules/qbittorrent.py +++ b/modules/qbittorrent.py @@ -547,22 +547,26 @@ class Qbt: # If neither set, use 0 (no limit) min_seeding_time = 0 if ( - tracker["min_seeding_time"] + tracker["min_seeding_time"] is not None and tracker["min_seeding_time"] >= nohardlinks[category]["min_seeding_time"] ): min_seeding_time = tracker["min_seeding_time"] elif nohardlinks[category]["min_seeding_time"]: min_seeding_time = nohardlinks[category]["min_seeding_time"] + else: + min_seeding_time = min_seeding_time # Determine max_ratio. # If only tracker setting is set, use tracker's max_ratio # If only nohardlinks category setting is set, use nohardlinks category's max_ratio # If both tracker and nohardlinks category setting is set, use the larger of the two # If neither set, use -1 (no limit) max_ratio = -1 - if tracker["max_ratio"] and tracker["max_ratio"] >= nohardlinks[category]["max_ratio"]: + if tracker["max_ratio"] is not None and tracker["max_ratio"] >= nohardlinks[category]["max_ratio"]: max_ratio = tracker["max_ratio"] elif nohardlinks[category]["max_ratio"]: max_ratio = nohardlinks[category]["max_ratio"] + else: + max_ratio = max_ratio # Determine max_seeding_time. # If only tracker setting is set, use tracker's max_seeding_time # If only nohardlinks category setting is set, use nohardlinks category's max_seeding_time @@ -570,13 +574,14 @@ class Qbt: # If neither set, use -1 (no limit) max_seeding_time = -1 if ( - tracker["max_seeding_time"] + tracker["max_seeding_time"] is not None and tracker["max_seeding_time"] >= nohardlinks[category]["max_seeding_time"] ): max_seeding_time = tracker["max_seeding_time"] elif nohardlinks[category]["max_seeding_time"]: max_seeding_time = nohardlinks[category]["max_seeding_time"] - + else: + max_seeding_time = max_seeding_time # Will only tag new torrents that don't have nohardlinks_tag tag if self.config.nohardlinks_tag not in torrent.tags: add_tag_no_hl(add_tag=True) From d67a7bf9416d5f6139e540f16fa350a4ee7045e9 Mon Sep 17 00:00:00 2001 From: Bakerboy448 <55419169+bakerboy448@users.noreply.github.com> Date: Tue, 4 Apr 2023 17:26:34 -0500 Subject: [PATCH 2/9] bump to v3.5.1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 1545d96..d5c0c99 100755 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.5.0 +3.5.1 From 43aebb7e32d91c6bc867a920c7258b8dae8b3521 Mon Sep 17 00:00:00 2001 From: bakerboy448 <55419169+bakerboy448@users.noreply.github.com> Date: Tue, 4 Apr 2023 21:49:09 -0500 Subject: [PATCH 3/9] Fixup! --- modules/qbittorrent.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/qbittorrent.py b/modules/qbittorrent.py index e0d8a9e..c26a274 100755 --- a/modules/qbittorrent.py +++ b/modules/qbittorrent.py @@ -553,8 +553,6 @@ class Qbt: min_seeding_time = tracker["min_seeding_time"] elif nohardlinks[category]["min_seeding_time"]: min_seeding_time = nohardlinks[category]["min_seeding_time"] - else: - min_seeding_time = min_seeding_time # Determine max_ratio. # If only tracker setting is set, use tracker's max_ratio # If only nohardlinks category setting is set, use nohardlinks category's max_ratio @@ -565,8 +563,6 @@ class Qbt: max_ratio = tracker["max_ratio"] elif nohardlinks[category]["max_ratio"]: max_ratio = nohardlinks[category]["max_ratio"] - else: - max_ratio = max_ratio # Determine max_seeding_time. # If only tracker setting is set, use tracker's max_seeding_time # If only nohardlinks category setting is set, use nohardlinks category's max_seeding_time @@ -580,8 +576,6 @@ class Qbt: max_seeding_time = tracker["max_seeding_time"] elif nohardlinks[category]["max_seeding_time"]: max_seeding_time = nohardlinks[category]["max_seeding_time"] - else: - max_seeding_time = max_seeding_time # Will only tag new torrents that don't have nohardlinks_tag tag if self.config.nohardlinks_tag not in torrent.tags: add_tag_no_hl(add_tag=True) From d053a66816e3d27d57914a95068402cdcaf8e511 Mon Sep 17 00:00:00 2001 From: bakerboy448 <55419169+bakerboy448@users.noreply.github.com> Date: Wed, 5 Apr 2023 02:34:34 -0500 Subject: [PATCH 4/9] (fix) actually finally fix no hardlink seed/ --- modules/qbittorrent.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/modules/qbittorrent.py b/modules/qbittorrent.py index c26a274..6e81813 100755 --- a/modules/qbittorrent.py +++ b/modules/qbittorrent.py @@ -546,36 +546,39 @@ class Qbt: # If both tracker and nohardlinks category setting is set, use the larger of the two # If neither set, use 0 (no limit) min_seeding_time = 0 - if ( - tracker["min_seeding_time"] is not None - and tracker["min_seeding_time"] >= nohardlinks[category]["min_seeding_time"] - ): - min_seeding_time = tracker["min_seeding_time"] + if (tracker["min_seeding_time"] is not None and nohardlinks[category]["min_seeding_time"] is not None: + if tracker["min_seeding_time"] >= nohardlinks[category]["min_seeding_time"]: + min_seeding_time = tracker["min_seeding_time"] elif nohardlinks[category]["min_seeding_time"]: min_seeding_time = nohardlinks[category]["min_seeding_time"] + elif tracker["min_seeding_time"]: + min_seeding_time = tracker["min_seeding_time"] # Determine max_ratio. # If only tracker setting is set, use tracker's max_ratio # If only nohardlinks category setting is set, use nohardlinks category's max_ratio # If both tracker and nohardlinks category setting is set, use the larger of the two # If neither set, use -1 (no limit) max_ratio = -1 - if tracker["max_ratio"] is not None and tracker["max_ratio"] >= nohardlinks[category]["max_ratio"]: - max_ratio = tracker["max_ratio"] + if tracker["max_ratio"] is not None and nohardlinks[category]["max_ratio"] is not None: + if tracker["max_ratio"] >= nohardlinks[category]["max_ratio"]: + max_ratio = tracker["max_ratio"] elif nohardlinks[category]["max_ratio"]: max_ratio = nohardlinks[category]["max_ratio"] + elif tracker["max_ratio"]: + max_ratio = tracker["max_ratio"] # Determine max_seeding_time. # If only tracker setting is set, use tracker's max_seeding_time # If only nohardlinks category setting is set, use nohardlinks category's max_seeding_time # If both tracker and nohardlinks category setting is set, use the larger of the two # If neither set, use -1 (no limit) max_seeding_time = -1 - if ( - tracker["max_seeding_time"] is not None - and tracker["max_seeding_time"] >= nohardlinks[category]["max_seeding_time"] - ): - max_seeding_time = tracker["max_seeding_time"] + if tracker["max_seeding_time"] is not None and nohardlinks[category]["max_seeding_time"] is not None: + if tracker["max_seeding_time"] >= nohardlinks[category]["max_seeding_time"]: + max_seeding_time = tracker["max_seeding_time"] elif nohardlinks[category]["max_seeding_time"]: max_seeding_time = nohardlinks[category]["max_seeding_time"] + elif tracker["max_seeding_time"]: + max_seeding_time = tracker["max_seeding_time"] # Will only tag new torrents that don't have nohardlinks_tag tag if self.config.nohardlinks_tag not in torrent.tags: add_tag_no_hl(add_tag=True) From 23ab49081ae2e8e355ae716708b7fac2f135e32d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 5 Apr 2023 07:34:53 +0000 Subject: [PATCH 5/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- modules/qbittorrent.py | 304 ++++++++++++++++++++--------------------- 1 file changed, 152 insertions(+), 152 deletions(-) diff --git a/modules/qbittorrent.py b/modules/qbittorrent.py index 6e81813..5ab14ca 100755 --- a/modules/qbittorrent.py +++ b/modules/qbittorrent.py @@ -548,44 +548,44 @@ class Qbt: min_seeding_time = 0 if (tracker["min_seeding_time"] is not None and nohardlinks[category]["min_seeding_time"] is not None: if tracker["min_seeding_time"] >= nohardlinks[category]["min_seeding_time"]: - min_seeding_time = tracker["min_seeding_time"] + min_seeding_time=tracker["min_seeding_time"] elif nohardlinks[category]["min_seeding_time"]: - min_seeding_time = nohardlinks[category]["min_seeding_time"] + min_seeding_time=nohardlinks[category]["min_seeding_time"] elif tracker["min_seeding_time"]: - min_seeding_time = tracker["min_seeding_time"] + min_seeding_time=tracker["min_seeding_time"] # Determine max_ratio. # If only tracker setting is set, use tracker's max_ratio # If only nohardlinks category setting is set, use nohardlinks category's max_ratio # If both tracker and nohardlinks category setting is set, use the larger of the two # If neither set, use -1 (no limit) - max_ratio = -1 + max_ratio=-1 if tracker["max_ratio"] is not None and nohardlinks[category]["max_ratio"] is not None: if tracker["max_ratio"] >= nohardlinks[category]["max_ratio"]: - max_ratio = tracker["max_ratio"] + max_ratio=tracker["max_ratio"] elif nohardlinks[category]["max_ratio"]: - max_ratio = nohardlinks[category]["max_ratio"] + max_ratio=nohardlinks[category]["max_ratio"] elif tracker["max_ratio"]: - max_ratio = tracker["max_ratio"] + max_ratio=tracker["max_ratio"] # Determine max_seeding_time. # If only tracker setting is set, use tracker's max_seeding_time # If only nohardlinks category setting is set, use nohardlinks category's max_seeding_time # If both tracker and nohardlinks category setting is set, use the larger of the two # If neither set, use -1 (no limit) - max_seeding_time = -1 + max_seeding_time=-1 if tracker["max_seeding_time"] is not None and nohardlinks[category]["max_seeding_time"] is not None: if tracker["max_seeding_time"] >= nohardlinks[category]["max_seeding_time"]: - max_seeding_time = tracker["max_seeding_time"] + max_seeding_time=tracker["max_seeding_time"] elif nohardlinks[category]["max_seeding_time"]: - max_seeding_time = nohardlinks[category]["max_seeding_time"] + max_seeding_time=nohardlinks[category]["max_seeding_time"] elif tracker["max_seeding_time"]: - max_seeding_time = tracker["max_seeding_time"] + max_seeding_time=tracker["max_seeding_time"] # Will only tag new torrents that don't have nohardlinks_tag tag if self.config.nohardlinks_tag not in torrent.tags: add_tag_no_hl(add_tag=True) # Deletes torrent with data if cleanup is set to true and meets the ratio/seeding requirements if nohardlinks[category]["cleanup"] and len(nohardlinks[category]) > 0: - tor_reach_seed_limit = self.has_reached_seed_limit( + tor_reach_seed_limit=self.has_reached_seed_limit( torrent, max_ratio, max_seeding_time, @@ -595,20 +595,20 @@ class Qbt: ) if tor_reach_seed_limit: if torrent.hash not in tdel_dict: - tdel_dict[torrent.hash] = {} - tdel_dict[torrent.hash]["content_path"] = torrent["content_path"].replace( + tdel_dict[torrent.hash]={} + tdel_dict[torrent.hash]["content_path"]=torrent["content_path"].replace( root_dir, remote_dir ) - tdel_dict[torrent.hash]["body"] = tor_reach_seed_limit + tdel_dict[torrent.hash]["body"]=tor_reach_seed_limit else: # Updates torrent to see if "MinSeedTimeNotReached" tag has been added - torrent = self.get_torrents({"torrent_hashes": [torrent.hash]}).data[0] + torrent=self.get_torrents({"torrent_hashes": [torrent.hash]}).data[0] # Checks to see if previously nohardlinks_tag share limits have changed. add_tag_no_hl(add_tag=False) # Checks to see if previous nohardlinks_tag tagged torrents now have hardlinks. if not (has_nohardlinks) and (self.config.nohardlinks_tag in torrent.tags): num_untag += 1 - body = [] + body=[] body += logger.print_line( f"Previous Tagged {self.config.nohardlinks_tag} " f"Torrent Name: {torrent.name} has hardlinks found now.", @@ -622,15 +622,15 @@ class Qbt: f"{'Not Reverting' if self.config.dry_run else 'Reverting'} to tracker or Global share limits.", self.config.loglevel, ) - restore_max_ratio = tracker["max_ratio"] - restore_max_seeding_time = tracker["max_seeding_time"] - restore_limit_upload_speed = tracker["limit_upload_speed"] + restore_max_ratio=tracker["max_ratio"] + restore_max_seeding_time=tracker["max_seeding_time"] + restore_limit_upload_speed=tracker["limit_upload_speed"] if restore_max_ratio is None: - restore_max_ratio = -2 + restore_max_ratio=-2 if restore_max_seeding_time is None: - restore_max_seeding_time = -2 + restore_max_seeding_time=-2 if restore_limit_upload_speed is None: - restore_limit_upload_speed = -1 + restore_limit_upload_speed=-1 if not self.config.dry_run: torrent.remove_tags(tags=self.config.nohardlinks_tag) body.extend( @@ -640,7 +640,7 @@ class Qbt: ) if torrent.state_enum.is_complete and nohardlinks[category]["resume_torrent_after_untagging_noHL"]: torrent.resume() - attr = { + attr={ "function": "untag_nohardlinks", "title": "Untagging Previous Torrents that now have hardlinks", "body": "\n".join(body), @@ -656,18 +656,18 @@ class Qbt: self.config.send_notifications(attr) # loop through torrent list again for cleanup purposes if nohardlinks[category]["cleanup"]: - torrent_list = self.get_torrents({"category": category, "status_filter": "completed"}) + torrent_list=self.get_torrents({"category": category, "status_filter": "completed"}) for torrent in torrent_list: - t_name = torrent.name - t_hash = torrent.hash + t_name=torrent.name + t_hash=torrent.hash if t_hash in tdel_dict and self.config.nohardlinks_tag in torrent.tags: - t_count = self.torrentinfo[t_name]["count"] - t_msg = self.torrentinfo[t_name]["msg"] - t_status = self.torrentinfo[t_name]["status"] + t_count=self.torrentinfo[t_name]["count"] + t_msg=self.torrentinfo[t_name]["msg"] + t_status=self.torrentinfo[t_name]["status"] # Double check that the content path is the same before we delete anything if torrent["content_path"].replace(root_dir, remote_dir) == tdel_dict[t_hash]["content_path"]: - tracker = self.config.get_tags(torrent.trackers) - body = [] + tracker=self.config.get_tags(torrent.trackers) + body=[] body += logger.print_line(logger.insert_space(f"Torrent Name: {t_name}", 3), self.config.loglevel) body += logger.print_line( logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel @@ -677,7 +677,7 @@ class Qbt: logger.insert_space("Cleanup: True [No hardlinks found and meets Share Limits.]", 8), self.config.loglevel, ) - attr = { + attr={ "function": "cleanup_tag_nohardlinks", "title": "Removing NoHL Torrents and meets Share Limits", "torrent_name": t_name, @@ -690,7 +690,7 @@ class Qbt: # Checks if any of the original torrents are working if t_count > 1 and ("" in t_msg or 2 in t_status): del_tor += 1 - attr["torrents_deleted_and_contents"] = False + attr["torrents_deleted_and_contents"]=False if not self.config.dry_run: self.tor_delete_recycle(torrent, attr) body += logger.print_line( @@ -699,7 +699,7 @@ class Qbt: ) else: del_tor_cont += 1 - attr["torrents_deleted_and_contents"] = True + attr["torrents_deleted_and_contents"]=True if not self.config.dry_run: self.tor_delete_recycle(torrent, attr) body += logger.print_line( @@ -707,13 +707,13 @@ class Qbt: ) else: del_tor += 1 - attr["torrents_deleted_and_contents"] = False + attr["torrents_deleted_and_contents"]=False if not self.config.dry_run: self.tor_delete_recycle(torrent, attr) body += logger.print_line( logger.insert_space("Deleted .torrent but NOT content files.", 8), self.config.loglevel ) - attr["body"] = "\n".join(body) + attr["body"]="\n".join(body) self.config.send_notifications(attr) self.torrentinfo[t_name]["count"] -= 1 if num_tags >= 1: @@ -747,25 +747,25 @@ class Qbt: def rem_unregistered(self): """Remove torrents with unregistered trackers.""" - del_tor = 0 - del_tor_cont = 0 - num_tor_error = 0 - num_untag = 0 - tor_error_summary = "" - tag_error = self.config.tracker_error_tag - cfg_rem_unregistered = self.config.commands["rem_unregistered"] - cfg_tag_error = self.config.commands["tag_tracker_error"] + del_tor=0 + del_tor_cont=0 + num_tor_error=0 + num_untag=0 + tor_error_summary="" + tag_error=self.config.tracker_error_tag + cfg_rem_unregistered=self.config.commands["rem_unregistered"] + cfg_tag_error=self.config.commands["tag_tracker_error"] def tag_tracker_error(): nonlocal t_name, msg_up, msg, tracker, t_cat, torrent, tag_error, tor_error_summary, num_tor_error - tor_error = "" + tor_error="" tor_error += logger.insert_space(f"Torrent Name: {t_name}", 3) + "\n" tor_error += logger.insert_space(f"Status: {msg}", 9) + "\n" tor_error += logger.insert_space(f'Tracker: {tracker["url"]}', 8) + "\n" tor_error += logger.insert_space(f"Added Tag: {tag_error}", 6) + "\n" tor_error_summary += tor_error num_tor_error += 1 - attr = { + attr={ "function": "tag_tracker_error", "title": "Tag Tracker Error Torrents", "body": tor_error, @@ -782,11 +782,11 @@ class Qbt: def del_unregistered(): nonlocal del_tor, del_tor_cont, t_name, msg_up, msg, tracker, t_cat, t_msg, t_status, torrent - body = [] + body=[] body += logger.print_line(logger.insert_space(f"Torrent Name: {t_name}", 3), self.config.loglevel) body += logger.print_line(logger.insert_space(f"Status: {msg}", 9), self.config.loglevel) body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) - attr = { + attr={ "function": "rem_unregistered", "title": "Removing Unregistered Torrents", "torrent_name": t_name, @@ -798,7 +798,7 @@ class Qbt: if t_count > 1: # Checks if any of the original torrents are working if "" in t_msg or 2 in t_status: - attr["torrents_deleted_and_contents"] = False + attr["torrents_deleted_and_contents"]=False if not self.config.dry_run: self.tor_delete_recycle(torrent, attr) body += logger.print_line( @@ -806,18 +806,18 @@ class Qbt: ) del_tor += 1 else: - attr["torrents_deleted_and_contents"] = True + attr["torrents_deleted_and_contents"]=True if not self.config.dry_run: self.tor_delete_recycle(torrent, attr) body += logger.print_line(logger.insert_space("Deleted .torrent AND content files.", 8), self.config.loglevel) del_tor_cont += 1 else: - attr["torrents_deleted_and_contents"] = True + attr["torrents_deleted_and_contents"]=True if not self.config.dry_run: self.tor_delete_recycle(torrent, attr) body += logger.print_line(logger.insert_space("Deleted .torrent AND content files.", 8), self.config.loglevel) del_tor_cont += 1 - attr["body"] = "\n".join(body) + attr["body"]="\n".join(body) self.config.send_notifications(attr) self.torrentinfo[t_name]["count"] -= 1 @@ -826,7 +826,7 @@ class Qbt: logger.separator("Tagging Torrents with Tracker Errors", space=False, border=False) elif cfg_rem_unregistered: logger.separator("Removing Unregistered Torrents", space=False, border=False) - unreg_msgs = [ + unreg_msgs=[ "UNREGISTERED", "TORRENT NOT FOUND", "TORRENT IS NOT FOUND", @@ -838,7 +838,7 @@ class Qbt: "TRUNCATED", "TORRENT IS NOT AUTHORIZED FOR USE ON THIS TRACKER", ] - ignore_msgs = [ + ignore_msgs=[ "YOU HAVE REACHED THE CLIENT LIMIT FOR THIS TORRENT", "MISSING PASSKEY", "MISSING INFO_HASH", @@ -849,12 +849,12 @@ class Qbt: "STREAM TRUNCATED", ] for torrent in self.torrentvalid: - check_tags = util.get_list(torrent.tags) + check_tags=util.get_list(torrent.tags) # Remove any error torrents Tags that are no longer unreachable. if tag_error in check_tags: - tracker = self.config.get_tags(torrent.trackers) + tracker=self.config.get_tags(torrent.trackers) num_untag += 1 - body = [] + body=[] body += logger.print_line( f"Previous Tagged {tag_error} torrent currently has a working tracker.", self.config.loglevel ) @@ -863,7 +863,7 @@ class Qbt: body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) if not self.config.dry_run: torrent.remove_tags(tags=tag_error) - attr = { + attr={ "function": "untag_tracker_error", "title": "Untagging Tracker Error Torrent", "body": "\n".join(body), @@ -875,18 +875,18 @@ class Qbt: } self.config.send_notifications(attr) for torrent in self.torrentissue: - t_name = torrent.name - t_cat = self.torrentinfo[t_name]["Category"] - t_count = self.torrentinfo[t_name]["count"] - t_msg = self.torrentinfo[t_name]["msg"] - t_status = self.torrentinfo[t_name]["status"] - check_tags = util.get_list(torrent.tags) + t_name=torrent.name + t_cat=self.torrentinfo[t_name]["Category"] + t_count=self.torrentinfo[t_name]["count"] + t_msg=self.torrentinfo[t_name]["msg"] + t_status=self.torrentinfo[t_name]["status"] + check_tags=util.get_list(torrent.tags) try: for trk in torrent.trackers: if trk.url.startswith("http"): - tracker = self.config.get_tags([trk]) - msg_up = trk.msg.upper() - msg = trk.msg + tracker=self.config.get_tags([trk]) + msg_up=trk.msg.upper() + msg=trk.msg # Tag any error torrents if cfg_tag_error: if trk.status == 4 and tag_error not in check_tags: @@ -900,8 +900,8 @@ class Qbt: and self.config.beyond_hd is not None and not list_in_text(msg_up, ignore_msgs) ): - json = {"info_hash": torrent.hash} - response = self.config.beyond_hd.search(json) + json={"info_hash": torrent.hash} + response=self.config.beyond_hd.search(json) if response["total_results"] == 0: del_unregistered() break @@ -949,35 +949,35 @@ class Qbt: def cross_seed(self): """Move torrents from cross seed directory to correct save directory.""" - added = 0 # Keep track of total torrents tagged - tagged = 0 # Track # of torrents tagged that are not cross-seeded + added=0 # Keep track of total torrents tagged + tagged=0 # Track # of torrents tagged that are not cross-seeded if self.config.commands["cross_seed"]: logger.separator("Checking for Cross-Seed Torrents", space=False, border=False) # List of categories for all torrents moved - categories = [] + categories=[] # Only get torrent files - cs_files = [f for f in os.listdir(self.config.cross_seed_dir) if f.endswith("torrent")] - dir_cs = self.config.cross_seed_dir - dir_cs_out = os.path.join(dir_cs, "qbit_manage_added") + cs_files=[f for f in os.listdir(self.config.cross_seed_dir) if f.endswith("torrent")] + dir_cs=self.config.cross_seed_dir + dir_cs_out=os.path.join(dir_cs, "qbit_manage_added") os.makedirs(dir_cs_out, exist_ok=True) for file in cs_files: - tr_name = file.split("]", 2)[2].split(".torrent")[0] - t_tracker = file.split("]", 2)[1][1:] + tr_name=file.split("]", 2)[2].split(".torrent")[0] + t_tracker=file.split("]", 2)[1][1:] # Substring Key match in dictionary (used because t_name might not match exactly with torrentdict key) # Returned the dictionary of filtered item - torrentdict_file = dict(filter(lambda item: tr_name in item[0], self.torrentinfo.items())) + torrentdict_file=dict(filter(lambda item: tr_name in item[0], self.torrentinfo.items())) if torrentdict_file: # Get the exact torrent match name from torrentdict - t_name = next(iter(torrentdict_file)) - dest = os.path.join(self.torrentinfo[t_name]["save_path"], "") - src = os.path.join(dir_cs, file) - dir_cs_out = os.path.join(dir_cs, "qbit_manage_added", file) - category = self.config.get_category(dest) + t_name=next(iter(torrentdict_file)) + dest=os.path.join(self.torrentinfo[t_name]["save_path"], "") + src=os.path.join(dir_cs, file) + dir_cs_out=os.path.join(dir_cs, "qbit_manage_added", file) + category=self.config.get_category(dest) # Only add cross-seed torrent if original torrent is complete if self.torrentinfo[t_name]["is_complete"]: categories.append(category) - body = [] + body=[] body += logger.print_line( f"{'Not Adding' if self.config.dry_run else 'Adding'} to qBittorrent:", self.config.loglevel ) @@ -985,7 +985,7 @@ class Qbt: body += logger.print_line(logger.insert_space(f"Category: {category}", 7), self.config.loglevel) body += logger.print_line(logger.insert_space(f"Save_Path: {dest}", 6), self.config.loglevel) body += logger.print_line(logger.insert_space(f"Tracker: {t_tracker}", 8), self.config.loglevel) - attr = { + attr={ "function": "cross_seed", "title": "Adding New Cross-Seed Torrent", "body": "\n".join(body), @@ -1008,7 +1008,7 @@ class Qbt: ) logger.print_line("Not adding to qBittorrent", self.config.loglevel) else: - error = f"{t_name} not found in torrents. Cross-seed Torrent not added to qBittorrent." + error=f"{t_name} not found in torrents. Cross-seed Torrent not added to qBittorrent." if self.config.dry_run: logger.print_line(error, self.config.loglevel) else: @@ -1016,19 +1016,19 @@ class Qbt: self.config.notify(error, "cross-seed", False) # Tag missing cross-seed torrents tags for torrent in self.torrent_list: - t_name = torrent.name - t_cat = torrent.category + t_name=torrent.name + t_cat=torrent.category if ( "cross-seed" not in torrent.tags and self.torrentinfo[t_name]["count"] > 1 and self.torrentinfo[t_name]["first_hash"] != torrent.hash ): - tracker = self.config.get_tags(torrent.trackers) + tracker=self.config.get_tags(torrent.trackers) tagged += 1 - body = logger.print_line( + body=logger.print_line( f"{'Not Adding' if self.config.dry_run else 'Adding'} 'cross-seed' tag to {t_name}", self.config.loglevel ) - attr = { + attr={ "function": "tag_cross_seed", "title": "Tagging Cross-Seed Torrent", "body": body, @@ -1041,7 +1041,7 @@ class Qbt: if not self.config.dry_run: torrent.add_tags(tags="cross-seed") - numcategory = Counter(categories) + numcategory=Counter(categories) for cat in numcategory: if numcategory[cat] > 0: logger.print_line( @@ -1061,24 +1061,24 @@ class Qbt: def recheck(self): """Function used to recheck paused torrents sorted by size and resume torrents that are completed""" - resumed = 0 - rechecked = 0 + resumed=0 + rechecked=0 if self.config.commands["recheck"]: logger.separator("Rechecking Paused Torrents", space=False, border=False) # sort by size and paused - torrent_list = self.get_torrents({"status_filter": "paused", "sort": "size"}) + torrent_list=self.get_torrents({"status_filter": "paused", "sort": "size"}) if torrent_list: for torrent in torrent_list: - tracker = self.config.get_tags(torrent.trackers) + tracker=self.config.get_tags(torrent.trackers) # Resume torrent if completed if torrent.progress == 1: if torrent.max_ratio < 0 and torrent.max_seeding_time < 0: resumed += 1 - body = logger.print_line( + body=logger.print_line( f"{'Not Resuming' if self.config.dry_run else 'Resuming'} [{tracker['tag']}] - {torrent.name}", self.config.loglevel, ) - attr = { + attr={ "function": "recheck", "title": "Resuming Torrent", "body": body, @@ -1119,12 +1119,12 @@ class Qbt: ) ): resumed += 1 - body = logger.print_line( + body=logger.print_line( f"{'Not Resuming' if self.config.dry_run else 'Resuming'} [{tracker['tag']}] - " f"{torrent.name}", self.config.loglevel, ) - attr = { + attr={ "function": "recheck", "title": "Resuming Torrent", "body": body, @@ -1143,11 +1143,11 @@ class Qbt: and not torrent.state_enum.is_checking ): rechecked += 1 - body = logger.print_line( + body=logger.print_line( f"{'Not Rechecking' if self.config.dry_run else 'Rechecking'} [{tracker['tag']}] - {torrent.name}", self.config.loglevel, ) - attr = { + attr={ "function": "recheck", "title": "Rechecking Torrent", "body": body, @@ -1163,26 +1163,26 @@ class Qbt: def rem_orphaned(self): """Remove orphaned files from remote directory""" - orphaned = 0 + orphaned=0 if self.config.commands["rem_orphaned"]: logger.separator("Checking for Orphaned Files", space=False, border=False) - torrent_files = [] - root_files = [] - orphaned_files = [] - excluded_orphan_files = [] - orphaned_parent_path = set() - remote_path = self.config.remote_dir - root_path = self.config.root_dir - orphaned_path = self.config.orphaned_dir + torrent_files=[] + root_files=[] + orphaned_files=[] + excluded_orphan_files=[] + orphaned_parent_path=set() + remote_path=self.config.remote_dir + root_path=self.config.root_dir + orphaned_path=self.config.orphaned_dir if remote_path != root_path: - root_files = [ + root_files=[ os.path.join(path.replace(remote_path, root_path), name) for path, subdirs, files in os.walk(remote_path) for name in files if orphaned_path.replace(remote_path, root_path) not in path ] else: - root_files = [ + root_files=[ os.path.join(path, name) for path, subdirs, files in os.walk(root_path) for name in files @@ -1190,32 +1190,32 @@ class Qbt: ] # Get an updated list of torrents - torrent_list = self.get_torrents({"sort": "added_on"}) + torrent_list=self.get_torrents({"sort": "added_on"}) for torrent in torrent_list: for file in torrent.files: - fullpath = os.path.join(torrent.save_path, file.name) + fullpath=os.path.join(torrent.save_path, file.name) # Replace fullpath with \\ if qbm is running in docker (linux) but qbt is on windows - fullpath = fullpath.replace(r"/", "\\") if ":\\" in fullpath else fullpath + fullpath=fullpath.replace(r"/", "\\") if ":\\" in fullpath else fullpath torrent_files.append(fullpath) - orphaned_files = set(root_files) - set(torrent_files) - orphaned_files = sorted(orphaned_files) + orphaned_files=set(root_files) - set(torrent_files) + orphaned_files=sorted(orphaned_files) if self.config.orphaned["exclude_patterns"]: - exclude_patterns = self.config.orphaned["exclude_patterns"] - excluded_orphan_files = [ + exclude_patterns=self.config.orphaned["exclude_patterns"] + excluded_orphan_files=[ file for file in orphaned_files for exclude_pattern in exclude_patterns if fnmatch(file, exclude_pattern.replace(remote_path, root_path)) ] - orphaned_files = set(orphaned_files) - set(excluded_orphan_files) + orphaned_files=set(orphaned_files) - set(excluded_orphan_files) if orphaned_files: os.makedirs(orphaned_path, exist_ok=True) - body = [] - num_orphaned = len(orphaned_files) + body=[] + num_orphaned=len(orphaned_files) logger.print_line(f"{num_orphaned} Orphaned files found", self.config.loglevel) body += logger.print_line("\n".join(orphaned_files), self.config.loglevel) body += logger.print_line( @@ -1224,7 +1224,7 @@ class Qbt: self.config.loglevel, ) - attr = { + attr={ "function": "rem_orphaned", "title": f"Removing {num_orphaned} Orphaned Files", "body": "\n".join(body), @@ -1237,8 +1237,8 @@ class Qbt: logger.info("Cleaning up any empty directories...") if not self.config.dry_run: for file in orphaned_files: - src = file.replace(root_path, remote_path) - dest = os.path.join(orphaned_path, file.replace(root_path, "")) + src=file.replace(root_path, remote_path) + dest=os.path.join(orphaned_path, file.replace(root_path, "")) util.move_files(src, dest, True) orphaned_parent_path.add(os.path.dirname(file).replace(root_path, remote_path)) for parent_path in orphaned_parent_path: @@ -1250,10 +1250,10 @@ class Qbt: def tor_delete_recycle(self, torrent, info): """Move torrent to recycle bin""" if self.config.recyclebin["enabled"]: - tor_files = [] + tor_files=[] try: - info_hash = torrent.hash - save_path = torrent.save_path.replace(self.config.root_dir, self.config.remote_dir) + info_hash=torrent.hash + save_path=torrent.save_path.replace(self.config.root_dir, self.config.remote_dir) # Define torrent files/folders for file in torrent.files: tor_files.append(os.path.join(save_path, file.name)) @@ -1261,12 +1261,12 @@ class Qbt: return if self.config.recyclebin["split_by_category"]: - recycle_path = os.path.join(save_path, os.path.basename(self.config.recycle_dir.rstrip(os.sep))) + recycle_path=os.path.join(save_path, os.path.basename(self.config.recycle_dir.rstrip(os.sep))) else: - recycle_path = self.config.recycle_dir + recycle_path=self.config.recycle_dir # Create recycle bin if not exists - torrent_path = os.path.join(recycle_path, "torrents") - torrents_json_path = os.path.join(recycle_path, "torrents_json") + torrent_path=os.path.join(recycle_path, "torrents") + torrents_json_path=os.path.join(recycle_path, "torrents_json") os.makedirs(recycle_path, exist_ok=True) if self.config.recyclebin["save_torrents"]: @@ -1274,15 +1274,15 @@ class Qbt: os.makedirs(torrent_path) if os.path.isdir(torrents_json_path) is False: os.makedirs(torrents_json_path) - torrent_json_file = os.path.join(torrents_json_path, f"{info['torrent_name']}.json") - torrent_json = util.load_json(torrent_json_file) + torrent_json_file=os.path.join(torrents_json_path, f"{info['torrent_name']}.json") + torrent_json=util.load_json(torrent_json_file) if not torrent_json: logger.info(f"Saving Torrent JSON file to {torrent_json_file}") - torrent_json["torrent_name"] = info["torrent_name"] - torrent_json["category"] = info["torrent_category"] + torrent_json["torrent_name"]=info["torrent_name"] + torrent_json["category"]=info["torrent_category"] else: logger.info(f"Adding {info['torrent_tracker']} to existing {os.path.basename(torrent_json_file)}") - dot_torrent_files = [] + dot_torrent_files=[] for file in os.listdir(self.config.torrents_dir): if file.startswith(info_hash): dot_torrent_files.append(file) @@ -1293,12 +1293,12 @@ class Qbt: self.config.notify(ex, "Deleting Torrent", False) logger.warning(f"RecycleBin Warning: {ex}") if "tracker_torrent_files" in torrent_json: - tracker_torrent_files = torrent_json["tracker_torrent_files"] + tracker_torrent_files=torrent_json["tracker_torrent_files"] else: - tracker_torrent_files = {} - tracker_torrent_files[info["torrent_tracker"]] = dot_torrent_files + tracker_torrent_files={} + tracker_torrent_files[info["torrent_tracker"]]=dot_torrent_files if dot_torrent_files: - backup_str = "Backing up " + backup_str="Backing up " for idx, val in enumerate(dot_torrent_files): if idx == 0: backup_str += val @@ -1306,15 +1306,15 @@ class Qbt: backup_str += f" and {val.replace(info_hash,'')}" backup_str += f" to {torrent_path}" logger.info(backup_str) - torrent_json["tracker_torrent_files"] = tracker_torrent_files + torrent_json["tracker_torrent_files"]=tracker_torrent_files if "files" not in torrent_json: - files_cleaned = [f.replace(self.config.remote_dir, "") for f in tor_files] - torrent_json["files"] = files_cleaned + files_cleaned=[f.replace(self.config.remote_dir, "") for f in tor_files] + torrent_json["files"]=files_cleaned if "deleted_contents" not in torrent_json: - torrent_json["deleted_contents"] = info["torrents_deleted_and_contents"] + torrent_json["deleted_contents"]=info["torrents_deleted_and_contents"] else: if torrent_json["deleted_contents"] is False and info["torrents_deleted_and_contents"] is True: - torrent_json["deleted_contents"] = info["torrents_deleted_and_contents"] + torrent_json["deleted_contents"]=info["torrents_deleted_and_contents"] logger.debug("") logger.debug(f"JSON: {torrent_json}") util.save_json(torrent_json, torrent_json_file) @@ -1330,13 +1330,13 @@ class Qbt: # Move files from torrent contents to Recycle bin for file in tor_files: - src = file - dest = os.path.join(recycle_path, file.replace(self.config.remote_dir, "")) + src=file + dest=os.path.join(recycle_path, file.replace(self.config.remote_dir, "")) # Move files and change date modified try: - to_delete = util.move_files(src, dest, True) + to_delete=util.move_files(src, dest, True) except FileNotFoundError: - ex = logger.print_line(f"RecycleBin Warning - FileNotFound: No such file or directory: {src} ", "WARNING") + ex=logger.print_line(f"RecycleBin Warning - FileNotFound: No such file or directory: {src} ", "WARNING") self.config.notify(ex, "Deleting Torrent", False) # Delete torrent and files torrent.delete(delete_files=to_delete) From acc02e80cdec54e2ce6d5aa646667286cf4b4a41 Mon Sep 17 00:00:00 2001 From: bakerboy448 <55419169+bakerboy448@users.noreply.github.com> Date: Wed, 5 Apr 2023 02:35:54 -0500 Subject: [PATCH 6/9] fixup! --- modules/qbittorrent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/qbittorrent.py b/modules/qbittorrent.py index 5ab14ca..2128319 100755 --- a/modules/qbittorrent.py +++ b/modules/qbittorrent.py @@ -546,7 +546,7 @@ class Qbt: # If both tracker and nohardlinks category setting is set, use the larger of the two # If neither set, use 0 (no limit) min_seeding_time = 0 - if (tracker["min_seeding_time"] is not None and nohardlinks[category]["min_seeding_time"] is not None: + if tracker["min_seeding_time"] is not None and nohardlinks[category]["min_seeding_time"] is not None: if tracker["min_seeding_time"] >= nohardlinks[category]["min_seeding_time"]: min_seeding_time=tracker["min_seeding_time"] elif nohardlinks[category]["min_seeding_time"]: From 6796e989d9e9ae8b20a837e64315f9bde21569b2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 5 Apr 2023 07:36:04 +0000 Subject: [PATCH 7/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- modules/qbittorrent.py | 304 ++++++++++++++++++++--------------------- 1 file changed, 152 insertions(+), 152 deletions(-) diff --git a/modules/qbittorrent.py b/modules/qbittorrent.py index 2128319..297f4c9 100755 --- a/modules/qbittorrent.py +++ b/modules/qbittorrent.py @@ -548,44 +548,44 @@ class Qbt: min_seeding_time = 0 if tracker["min_seeding_time"] is not None and nohardlinks[category]["min_seeding_time"] is not None: if tracker["min_seeding_time"] >= nohardlinks[category]["min_seeding_time"]: - min_seeding_time=tracker["min_seeding_time"] + min_seeding_time = tracker["min_seeding_time"] elif nohardlinks[category]["min_seeding_time"]: - min_seeding_time=nohardlinks[category]["min_seeding_time"] + min_seeding_time = nohardlinks[category]["min_seeding_time"] elif tracker["min_seeding_time"]: - min_seeding_time=tracker["min_seeding_time"] + min_seeding_time = tracker["min_seeding_time"] # Determine max_ratio. # If only tracker setting is set, use tracker's max_ratio # If only nohardlinks category setting is set, use nohardlinks category's max_ratio # If both tracker and nohardlinks category setting is set, use the larger of the two # If neither set, use -1 (no limit) - max_ratio=-1 + max_ratio = -1 if tracker["max_ratio"] is not None and nohardlinks[category]["max_ratio"] is not None: if tracker["max_ratio"] >= nohardlinks[category]["max_ratio"]: - max_ratio=tracker["max_ratio"] + max_ratio = tracker["max_ratio"] elif nohardlinks[category]["max_ratio"]: - max_ratio=nohardlinks[category]["max_ratio"] + max_ratio = nohardlinks[category]["max_ratio"] elif tracker["max_ratio"]: - max_ratio=tracker["max_ratio"] + max_ratio = tracker["max_ratio"] # Determine max_seeding_time. # If only tracker setting is set, use tracker's max_seeding_time # If only nohardlinks category setting is set, use nohardlinks category's max_seeding_time # If both tracker and nohardlinks category setting is set, use the larger of the two # If neither set, use -1 (no limit) - max_seeding_time=-1 + max_seeding_time = -1 if tracker["max_seeding_time"] is not None and nohardlinks[category]["max_seeding_time"] is not None: if tracker["max_seeding_time"] >= nohardlinks[category]["max_seeding_time"]: - max_seeding_time=tracker["max_seeding_time"] + max_seeding_time = tracker["max_seeding_time"] elif nohardlinks[category]["max_seeding_time"]: - max_seeding_time=nohardlinks[category]["max_seeding_time"] + max_seeding_time = nohardlinks[category]["max_seeding_time"] elif tracker["max_seeding_time"]: - max_seeding_time=tracker["max_seeding_time"] + max_seeding_time = tracker["max_seeding_time"] # Will only tag new torrents that don't have nohardlinks_tag tag if self.config.nohardlinks_tag not in torrent.tags: add_tag_no_hl(add_tag=True) # Deletes torrent with data if cleanup is set to true and meets the ratio/seeding requirements if nohardlinks[category]["cleanup"] and len(nohardlinks[category]) > 0: - tor_reach_seed_limit=self.has_reached_seed_limit( + tor_reach_seed_limit = self.has_reached_seed_limit( torrent, max_ratio, max_seeding_time, @@ -595,20 +595,20 @@ class Qbt: ) if tor_reach_seed_limit: if torrent.hash not in tdel_dict: - tdel_dict[torrent.hash]={} - tdel_dict[torrent.hash]["content_path"]=torrent["content_path"].replace( + tdel_dict[torrent.hash] = {} + tdel_dict[torrent.hash]["content_path"] = torrent["content_path"].replace( root_dir, remote_dir ) - tdel_dict[torrent.hash]["body"]=tor_reach_seed_limit + tdel_dict[torrent.hash]["body"] = tor_reach_seed_limit else: # Updates torrent to see if "MinSeedTimeNotReached" tag has been added - torrent=self.get_torrents({"torrent_hashes": [torrent.hash]}).data[0] + torrent = self.get_torrents({"torrent_hashes": [torrent.hash]}).data[0] # Checks to see if previously nohardlinks_tag share limits have changed. add_tag_no_hl(add_tag=False) # Checks to see if previous nohardlinks_tag tagged torrents now have hardlinks. if not (has_nohardlinks) and (self.config.nohardlinks_tag in torrent.tags): num_untag += 1 - body=[] + body = [] body += logger.print_line( f"Previous Tagged {self.config.nohardlinks_tag} " f"Torrent Name: {torrent.name} has hardlinks found now.", @@ -622,15 +622,15 @@ class Qbt: f"{'Not Reverting' if self.config.dry_run else 'Reverting'} to tracker or Global share limits.", self.config.loglevel, ) - restore_max_ratio=tracker["max_ratio"] - restore_max_seeding_time=tracker["max_seeding_time"] - restore_limit_upload_speed=tracker["limit_upload_speed"] + restore_max_ratio = tracker["max_ratio"] + restore_max_seeding_time = tracker["max_seeding_time"] + restore_limit_upload_speed = tracker["limit_upload_speed"] if restore_max_ratio is None: - restore_max_ratio=-2 + restore_max_ratio = -2 if restore_max_seeding_time is None: - restore_max_seeding_time=-2 + restore_max_seeding_time = -2 if restore_limit_upload_speed is None: - restore_limit_upload_speed=-1 + restore_limit_upload_speed = -1 if not self.config.dry_run: torrent.remove_tags(tags=self.config.nohardlinks_tag) body.extend( @@ -640,7 +640,7 @@ class Qbt: ) if torrent.state_enum.is_complete and nohardlinks[category]["resume_torrent_after_untagging_noHL"]: torrent.resume() - attr={ + attr = { "function": "untag_nohardlinks", "title": "Untagging Previous Torrents that now have hardlinks", "body": "\n".join(body), @@ -656,18 +656,18 @@ class Qbt: self.config.send_notifications(attr) # loop through torrent list again for cleanup purposes if nohardlinks[category]["cleanup"]: - torrent_list=self.get_torrents({"category": category, "status_filter": "completed"}) + torrent_list = self.get_torrents({"category": category, "status_filter": "completed"}) for torrent in torrent_list: - t_name=torrent.name - t_hash=torrent.hash + t_name = torrent.name + t_hash = torrent.hash if t_hash in tdel_dict and self.config.nohardlinks_tag in torrent.tags: - t_count=self.torrentinfo[t_name]["count"] - t_msg=self.torrentinfo[t_name]["msg"] - t_status=self.torrentinfo[t_name]["status"] + t_count = self.torrentinfo[t_name]["count"] + t_msg = self.torrentinfo[t_name]["msg"] + t_status = self.torrentinfo[t_name]["status"] # Double check that the content path is the same before we delete anything if torrent["content_path"].replace(root_dir, remote_dir) == tdel_dict[t_hash]["content_path"]: - tracker=self.config.get_tags(torrent.trackers) - body=[] + tracker = self.config.get_tags(torrent.trackers) + body = [] body += logger.print_line(logger.insert_space(f"Torrent Name: {t_name}", 3), self.config.loglevel) body += logger.print_line( logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel @@ -677,7 +677,7 @@ class Qbt: logger.insert_space("Cleanup: True [No hardlinks found and meets Share Limits.]", 8), self.config.loglevel, ) - attr={ + attr = { "function": "cleanup_tag_nohardlinks", "title": "Removing NoHL Torrents and meets Share Limits", "torrent_name": t_name, @@ -690,7 +690,7 @@ class Qbt: # Checks if any of the original torrents are working if t_count > 1 and ("" in t_msg or 2 in t_status): del_tor += 1 - attr["torrents_deleted_and_contents"]=False + attr["torrents_deleted_and_contents"] = False if not self.config.dry_run: self.tor_delete_recycle(torrent, attr) body += logger.print_line( @@ -699,7 +699,7 @@ class Qbt: ) else: del_tor_cont += 1 - attr["torrents_deleted_and_contents"]=True + attr["torrents_deleted_and_contents"] = True if not self.config.dry_run: self.tor_delete_recycle(torrent, attr) body += logger.print_line( @@ -707,13 +707,13 @@ class Qbt: ) else: del_tor += 1 - attr["torrents_deleted_and_contents"]=False + attr["torrents_deleted_and_contents"] = False if not self.config.dry_run: self.tor_delete_recycle(torrent, attr) body += logger.print_line( logger.insert_space("Deleted .torrent but NOT content files.", 8), self.config.loglevel ) - attr["body"]="\n".join(body) + attr["body"] = "\n".join(body) self.config.send_notifications(attr) self.torrentinfo[t_name]["count"] -= 1 if num_tags >= 1: @@ -747,25 +747,25 @@ class Qbt: def rem_unregistered(self): """Remove torrents with unregistered trackers.""" - del_tor=0 - del_tor_cont=0 - num_tor_error=0 - num_untag=0 - tor_error_summary="" - tag_error=self.config.tracker_error_tag - cfg_rem_unregistered=self.config.commands["rem_unregistered"] - cfg_tag_error=self.config.commands["tag_tracker_error"] + del_tor = 0 + del_tor_cont = 0 + num_tor_error = 0 + num_untag = 0 + tor_error_summary = "" + tag_error = self.config.tracker_error_tag + cfg_rem_unregistered = self.config.commands["rem_unregistered"] + cfg_tag_error = self.config.commands["tag_tracker_error"] def tag_tracker_error(): nonlocal t_name, msg_up, msg, tracker, t_cat, torrent, tag_error, tor_error_summary, num_tor_error - tor_error="" + tor_error = "" tor_error += logger.insert_space(f"Torrent Name: {t_name}", 3) + "\n" tor_error += logger.insert_space(f"Status: {msg}", 9) + "\n" tor_error += logger.insert_space(f'Tracker: {tracker["url"]}', 8) + "\n" tor_error += logger.insert_space(f"Added Tag: {tag_error}", 6) + "\n" tor_error_summary += tor_error num_tor_error += 1 - attr={ + attr = { "function": "tag_tracker_error", "title": "Tag Tracker Error Torrents", "body": tor_error, @@ -782,11 +782,11 @@ class Qbt: def del_unregistered(): nonlocal del_tor, del_tor_cont, t_name, msg_up, msg, tracker, t_cat, t_msg, t_status, torrent - body=[] + body = [] body += logger.print_line(logger.insert_space(f"Torrent Name: {t_name}", 3), self.config.loglevel) body += logger.print_line(logger.insert_space(f"Status: {msg}", 9), self.config.loglevel) body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) - attr={ + attr = { "function": "rem_unregistered", "title": "Removing Unregistered Torrents", "torrent_name": t_name, @@ -798,7 +798,7 @@ class Qbt: if t_count > 1: # Checks if any of the original torrents are working if "" in t_msg or 2 in t_status: - attr["torrents_deleted_and_contents"]=False + attr["torrents_deleted_and_contents"] = False if not self.config.dry_run: self.tor_delete_recycle(torrent, attr) body += logger.print_line( @@ -806,18 +806,18 @@ class Qbt: ) del_tor += 1 else: - attr["torrents_deleted_and_contents"]=True + attr["torrents_deleted_and_contents"] = True if not self.config.dry_run: self.tor_delete_recycle(torrent, attr) body += logger.print_line(logger.insert_space("Deleted .torrent AND content files.", 8), self.config.loglevel) del_tor_cont += 1 else: - attr["torrents_deleted_and_contents"]=True + attr["torrents_deleted_and_contents"] = True if not self.config.dry_run: self.tor_delete_recycle(torrent, attr) body += logger.print_line(logger.insert_space("Deleted .torrent AND content files.", 8), self.config.loglevel) del_tor_cont += 1 - attr["body"]="\n".join(body) + attr["body"] = "\n".join(body) self.config.send_notifications(attr) self.torrentinfo[t_name]["count"] -= 1 @@ -826,7 +826,7 @@ class Qbt: logger.separator("Tagging Torrents with Tracker Errors", space=False, border=False) elif cfg_rem_unregistered: logger.separator("Removing Unregistered Torrents", space=False, border=False) - unreg_msgs=[ + unreg_msgs = [ "UNREGISTERED", "TORRENT NOT FOUND", "TORRENT IS NOT FOUND", @@ -838,7 +838,7 @@ class Qbt: "TRUNCATED", "TORRENT IS NOT AUTHORIZED FOR USE ON THIS TRACKER", ] - ignore_msgs=[ + ignore_msgs = [ "YOU HAVE REACHED THE CLIENT LIMIT FOR THIS TORRENT", "MISSING PASSKEY", "MISSING INFO_HASH", @@ -849,12 +849,12 @@ class Qbt: "STREAM TRUNCATED", ] for torrent in self.torrentvalid: - check_tags=util.get_list(torrent.tags) + check_tags = util.get_list(torrent.tags) # Remove any error torrents Tags that are no longer unreachable. if tag_error in check_tags: - tracker=self.config.get_tags(torrent.trackers) + tracker = self.config.get_tags(torrent.trackers) num_untag += 1 - body=[] + body = [] body += logger.print_line( f"Previous Tagged {tag_error} torrent currently has a working tracker.", self.config.loglevel ) @@ -863,7 +863,7 @@ class Qbt: body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) if not self.config.dry_run: torrent.remove_tags(tags=tag_error) - attr={ + attr = { "function": "untag_tracker_error", "title": "Untagging Tracker Error Torrent", "body": "\n".join(body), @@ -875,18 +875,18 @@ class Qbt: } self.config.send_notifications(attr) for torrent in self.torrentissue: - t_name=torrent.name - t_cat=self.torrentinfo[t_name]["Category"] - t_count=self.torrentinfo[t_name]["count"] - t_msg=self.torrentinfo[t_name]["msg"] - t_status=self.torrentinfo[t_name]["status"] - check_tags=util.get_list(torrent.tags) + t_name = torrent.name + t_cat = self.torrentinfo[t_name]["Category"] + t_count = self.torrentinfo[t_name]["count"] + t_msg = self.torrentinfo[t_name]["msg"] + t_status = self.torrentinfo[t_name]["status"] + check_tags = util.get_list(torrent.tags) try: for trk in torrent.trackers: if trk.url.startswith("http"): - tracker=self.config.get_tags([trk]) - msg_up=trk.msg.upper() - msg=trk.msg + tracker = self.config.get_tags([trk]) + msg_up = trk.msg.upper() + msg = trk.msg # Tag any error torrents if cfg_tag_error: if trk.status == 4 and tag_error not in check_tags: @@ -900,8 +900,8 @@ class Qbt: and self.config.beyond_hd is not None and not list_in_text(msg_up, ignore_msgs) ): - json={"info_hash": torrent.hash} - response=self.config.beyond_hd.search(json) + json = {"info_hash": torrent.hash} + response = self.config.beyond_hd.search(json) if response["total_results"] == 0: del_unregistered() break @@ -949,35 +949,35 @@ class Qbt: def cross_seed(self): """Move torrents from cross seed directory to correct save directory.""" - added=0 # Keep track of total torrents tagged - tagged=0 # Track # of torrents tagged that are not cross-seeded + added = 0 # Keep track of total torrents tagged + tagged = 0 # Track # of torrents tagged that are not cross-seeded if self.config.commands["cross_seed"]: logger.separator("Checking for Cross-Seed Torrents", space=False, border=False) # List of categories for all torrents moved - categories=[] + categories = [] # Only get torrent files - cs_files=[f for f in os.listdir(self.config.cross_seed_dir) if f.endswith("torrent")] - dir_cs=self.config.cross_seed_dir - dir_cs_out=os.path.join(dir_cs, "qbit_manage_added") + cs_files = [f for f in os.listdir(self.config.cross_seed_dir) if f.endswith("torrent")] + dir_cs = self.config.cross_seed_dir + dir_cs_out = os.path.join(dir_cs, "qbit_manage_added") os.makedirs(dir_cs_out, exist_ok=True) for file in cs_files: - tr_name=file.split("]", 2)[2].split(".torrent")[0] - t_tracker=file.split("]", 2)[1][1:] + tr_name = file.split("]", 2)[2].split(".torrent")[0] + t_tracker = file.split("]", 2)[1][1:] # Substring Key match in dictionary (used because t_name might not match exactly with torrentdict key) # Returned the dictionary of filtered item - torrentdict_file=dict(filter(lambda item: tr_name in item[0], self.torrentinfo.items())) + torrentdict_file = dict(filter(lambda item: tr_name in item[0], self.torrentinfo.items())) if torrentdict_file: # Get the exact torrent match name from torrentdict - t_name=next(iter(torrentdict_file)) - dest=os.path.join(self.torrentinfo[t_name]["save_path"], "") - src=os.path.join(dir_cs, file) - dir_cs_out=os.path.join(dir_cs, "qbit_manage_added", file) - category=self.config.get_category(dest) + t_name = next(iter(torrentdict_file)) + dest = os.path.join(self.torrentinfo[t_name]["save_path"], "") + src = os.path.join(dir_cs, file) + dir_cs_out = os.path.join(dir_cs, "qbit_manage_added", file) + category = self.config.get_category(dest) # Only add cross-seed torrent if original torrent is complete if self.torrentinfo[t_name]["is_complete"]: categories.append(category) - body=[] + body = [] body += logger.print_line( f"{'Not Adding' if self.config.dry_run else 'Adding'} to qBittorrent:", self.config.loglevel ) @@ -985,7 +985,7 @@ class Qbt: body += logger.print_line(logger.insert_space(f"Category: {category}", 7), self.config.loglevel) body += logger.print_line(logger.insert_space(f"Save_Path: {dest}", 6), self.config.loglevel) body += logger.print_line(logger.insert_space(f"Tracker: {t_tracker}", 8), self.config.loglevel) - attr={ + attr = { "function": "cross_seed", "title": "Adding New Cross-Seed Torrent", "body": "\n".join(body), @@ -1008,7 +1008,7 @@ class Qbt: ) logger.print_line("Not adding to qBittorrent", self.config.loglevel) else: - error=f"{t_name} not found in torrents. Cross-seed Torrent not added to qBittorrent." + error = f"{t_name} not found in torrents. Cross-seed Torrent not added to qBittorrent." if self.config.dry_run: logger.print_line(error, self.config.loglevel) else: @@ -1016,19 +1016,19 @@ class Qbt: self.config.notify(error, "cross-seed", False) # Tag missing cross-seed torrents tags for torrent in self.torrent_list: - t_name=torrent.name - t_cat=torrent.category + t_name = torrent.name + t_cat = torrent.category if ( "cross-seed" not in torrent.tags and self.torrentinfo[t_name]["count"] > 1 and self.torrentinfo[t_name]["first_hash"] != torrent.hash ): - tracker=self.config.get_tags(torrent.trackers) + tracker = self.config.get_tags(torrent.trackers) tagged += 1 - body=logger.print_line( + body = logger.print_line( f"{'Not Adding' if self.config.dry_run else 'Adding'} 'cross-seed' tag to {t_name}", self.config.loglevel ) - attr={ + attr = { "function": "tag_cross_seed", "title": "Tagging Cross-Seed Torrent", "body": body, @@ -1041,7 +1041,7 @@ class Qbt: if not self.config.dry_run: torrent.add_tags(tags="cross-seed") - numcategory=Counter(categories) + numcategory = Counter(categories) for cat in numcategory: if numcategory[cat] > 0: logger.print_line( @@ -1061,24 +1061,24 @@ class Qbt: def recheck(self): """Function used to recheck paused torrents sorted by size and resume torrents that are completed""" - resumed=0 - rechecked=0 + resumed = 0 + rechecked = 0 if self.config.commands["recheck"]: logger.separator("Rechecking Paused Torrents", space=False, border=False) # sort by size and paused - torrent_list=self.get_torrents({"status_filter": "paused", "sort": "size"}) + torrent_list = self.get_torrents({"status_filter": "paused", "sort": "size"}) if torrent_list: for torrent in torrent_list: - tracker=self.config.get_tags(torrent.trackers) + tracker = self.config.get_tags(torrent.trackers) # Resume torrent if completed if torrent.progress == 1: if torrent.max_ratio < 0 and torrent.max_seeding_time < 0: resumed += 1 - body=logger.print_line( + body = logger.print_line( f"{'Not Resuming' if self.config.dry_run else 'Resuming'} [{tracker['tag']}] - {torrent.name}", self.config.loglevel, ) - attr={ + attr = { "function": "recheck", "title": "Resuming Torrent", "body": body, @@ -1119,12 +1119,12 @@ class Qbt: ) ): resumed += 1 - body=logger.print_line( + body = logger.print_line( f"{'Not Resuming' if self.config.dry_run else 'Resuming'} [{tracker['tag']}] - " f"{torrent.name}", self.config.loglevel, ) - attr={ + attr = { "function": "recheck", "title": "Resuming Torrent", "body": body, @@ -1143,11 +1143,11 @@ class Qbt: and not torrent.state_enum.is_checking ): rechecked += 1 - body=logger.print_line( + body = logger.print_line( f"{'Not Rechecking' if self.config.dry_run else 'Rechecking'} [{tracker['tag']}] - {torrent.name}", self.config.loglevel, ) - attr={ + attr = { "function": "recheck", "title": "Rechecking Torrent", "body": body, @@ -1163,26 +1163,26 @@ class Qbt: def rem_orphaned(self): """Remove orphaned files from remote directory""" - orphaned=0 + orphaned = 0 if self.config.commands["rem_orphaned"]: logger.separator("Checking for Orphaned Files", space=False, border=False) - torrent_files=[] - root_files=[] - orphaned_files=[] - excluded_orphan_files=[] - orphaned_parent_path=set() - remote_path=self.config.remote_dir - root_path=self.config.root_dir - orphaned_path=self.config.orphaned_dir + torrent_files = [] + root_files = [] + orphaned_files = [] + excluded_orphan_files = [] + orphaned_parent_path = set() + remote_path = self.config.remote_dir + root_path = self.config.root_dir + orphaned_path = self.config.orphaned_dir if remote_path != root_path: - root_files=[ + root_files = [ os.path.join(path.replace(remote_path, root_path), name) for path, subdirs, files in os.walk(remote_path) for name in files if orphaned_path.replace(remote_path, root_path) not in path ] else: - root_files=[ + root_files = [ os.path.join(path, name) for path, subdirs, files in os.walk(root_path) for name in files @@ -1190,32 +1190,32 @@ class Qbt: ] # Get an updated list of torrents - torrent_list=self.get_torrents({"sort": "added_on"}) + torrent_list = self.get_torrents({"sort": "added_on"}) for torrent in torrent_list: for file in torrent.files: - fullpath=os.path.join(torrent.save_path, file.name) + fullpath = os.path.join(torrent.save_path, file.name) # Replace fullpath with \\ if qbm is running in docker (linux) but qbt is on windows - fullpath=fullpath.replace(r"/", "\\") if ":\\" in fullpath else fullpath + fullpath = fullpath.replace(r"/", "\\") if ":\\" in fullpath else fullpath torrent_files.append(fullpath) - orphaned_files=set(root_files) - set(torrent_files) - orphaned_files=sorted(orphaned_files) + orphaned_files = set(root_files) - set(torrent_files) + orphaned_files = sorted(orphaned_files) if self.config.orphaned["exclude_patterns"]: - exclude_patterns=self.config.orphaned["exclude_patterns"] - excluded_orphan_files=[ + exclude_patterns = self.config.orphaned["exclude_patterns"] + excluded_orphan_files = [ file for file in orphaned_files for exclude_pattern in exclude_patterns if fnmatch(file, exclude_pattern.replace(remote_path, root_path)) ] - orphaned_files=set(orphaned_files) - set(excluded_orphan_files) + orphaned_files = set(orphaned_files) - set(excluded_orphan_files) if orphaned_files: os.makedirs(orphaned_path, exist_ok=True) - body=[] - num_orphaned=len(orphaned_files) + body = [] + num_orphaned = len(orphaned_files) logger.print_line(f"{num_orphaned} Orphaned files found", self.config.loglevel) body += logger.print_line("\n".join(orphaned_files), self.config.loglevel) body += logger.print_line( @@ -1224,7 +1224,7 @@ class Qbt: self.config.loglevel, ) - attr={ + attr = { "function": "rem_orphaned", "title": f"Removing {num_orphaned} Orphaned Files", "body": "\n".join(body), @@ -1237,8 +1237,8 @@ class Qbt: logger.info("Cleaning up any empty directories...") if not self.config.dry_run: for file in orphaned_files: - src=file.replace(root_path, remote_path) - dest=os.path.join(orphaned_path, file.replace(root_path, "")) + src = file.replace(root_path, remote_path) + dest = os.path.join(orphaned_path, file.replace(root_path, "")) util.move_files(src, dest, True) orphaned_parent_path.add(os.path.dirname(file).replace(root_path, remote_path)) for parent_path in orphaned_parent_path: @@ -1250,10 +1250,10 @@ class Qbt: def tor_delete_recycle(self, torrent, info): """Move torrent to recycle bin""" if self.config.recyclebin["enabled"]: - tor_files=[] + tor_files = [] try: - info_hash=torrent.hash - save_path=torrent.save_path.replace(self.config.root_dir, self.config.remote_dir) + info_hash = torrent.hash + save_path = torrent.save_path.replace(self.config.root_dir, self.config.remote_dir) # Define torrent files/folders for file in torrent.files: tor_files.append(os.path.join(save_path, file.name)) @@ -1261,12 +1261,12 @@ class Qbt: return if self.config.recyclebin["split_by_category"]: - recycle_path=os.path.join(save_path, os.path.basename(self.config.recycle_dir.rstrip(os.sep))) + recycle_path = os.path.join(save_path, os.path.basename(self.config.recycle_dir.rstrip(os.sep))) else: - recycle_path=self.config.recycle_dir + recycle_path = self.config.recycle_dir # Create recycle bin if not exists - torrent_path=os.path.join(recycle_path, "torrents") - torrents_json_path=os.path.join(recycle_path, "torrents_json") + torrent_path = os.path.join(recycle_path, "torrents") + torrents_json_path = os.path.join(recycle_path, "torrents_json") os.makedirs(recycle_path, exist_ok=True) if self.config.recyclebin["save_torrents"]: @@ -1274,15 +1274,15 @@ class Qbt: os.makedirs(torrent_path) if os.path.isdir(torrents_json_path) is False: os.makedirs(torrents_json_path) - torrent_json_file=os.path.join(torrents_json_path, f"{info['torrent_name']}.json") - torrent_json=util.load_json(torrent_json_file) + torrent_json_file = os.path.join(torrents_json_path, f"{info['torrent_name']}.json") + torrent_json = util.load_json(torrent_json_file) if not torrent_json: logger.info(f"Saving Torrent JSON file to {torrent_json_file}") - torrent_json["torrent_name"]=info["torrent_name"] - torrent_json["category"]=info["torrent_category"] + torrent_json["torrent_name"] = info["torrent_name"] + torrent_json["category"] = info["torrent_category"] else: logger.info(f"Adding {info['torrent_tracker']} to existing {os.path.basename(torrent_json_file)}") - dot_torrent_files=[] + dot_torrent_files = [] for file in os.listdir(self.config.torrents_dir): if file.startswith(info_hash): dot_torrent_files.append(file) @@ -1293,12 +1293,12 @@ class Qbt: self.config.notify(ex, "Deleting Torrent", False) logger.warning(f"RecycleBin Warning: {ex}") if "tracker_torrent_files" in torrent_json: - tracker_torrent_files=torrent_json["tracker_torrent_files"] + tracker_torrent_files = torrent_json["tracker_torrent_files"] else: - tracker_torrent_files={} - tracker_torrent_files[info["torrent_tracker"]]=dot_torrent_files + tracker_torrent_files = {} + tracker_torrent_files[info["torrent_tracker"]] = dot_torrent_files if dot_torrent_files: - backup_str="Backing up " + backup_str = "Backing up " for idx, val in enumerate(dot_torrent_files): if idx == 0: backup_str += val @@ -1306,15 +1306,15 @@ class Qbt: backup_str += f" and {val.replace(info_hash,'')}" backup_str += f" to {torrent_path}" logger.info(backup_str) - torrent_json["tracker_torrent_files"]=tracker_torrent_files + torrent_json["tracker_torrent_files"] = tracker_torrent_files if "files" not in torrent_json: - files_cleaned=[f.replace(self.config.remote_dir, "") for f in tor_files] - torrent_json["files"]=files_cleaned + files_cleaned = [f.replace(self.config.remote_dir, "") for f in tor_files] + torrent_json["files"] = files_cleaned if "deleted_contents" not in torrent_json: - torrent_json["deleted_contents"]=info["torrents_deleted_and_contents"] + torrent_json["deleted_contents"] = info["torrents_deleted_and_contents"] else: if torrent_json["deleted_contents"] is False and info["torrents_deleted_and_contents"] is True: - torrent_json["deleted_contents"]=info["torrents_deleted_and_contents"] + torrent_json["deleted_contents"] = info["torrents_deleted_and_contents"] logger.debug("") logger.debug(f"JSON: {torrent_json}") util.save_json(torrent_json, torrent_json_file) @@ -1330,13 +1330,13 @@ class Qbt: # Move files from torrent contents to Recycle bin for file in tor_files: - src=file - dest=os.path.join(recycle_path, file.replace(self.config.remote_dir, "")) + src = file + dest = os.path.join(recycle_path, file.replace(self.config.remote_dir, "")) # Move files and change date modified try: - to_delete=util.move_files(src, dest, True) + to_delete = util.move_files(src, dest, True) except FileNotFoundError: - ex=logger.print_line(f"RecycleBin Warning - FileNotFound: No such file or directory: {src} ", "WARNING") + ex = logger.print_line(f"RecycleBin Warning - FileNotFound: No such file or directory: {src} ", "WARNING") self.config.notify(ex, "Deleting Torrent", False) # Delete torrent and files torrent.delete(delete_files=to_delete) From 7b8aa3b015d8e3f0553c77c174dd7c5896e017ac Mon Sep 17 00:00:00 2001 From: bobokun Date: Sun, 9 Apr 2023 15:37:23 -0400 Subject: [PATCH 8/9] Fixes #260 --- CHANGELOG | 16 +++------------- modules/qbittorrent.py | 5 +++++ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 60d8910..7a14d0c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,15 +1,5 @@ -# Requirements Updated -- Adds check for minimum python requirement of 3.8.1+ (Fixes #221) -- Updates qbitorrent api to 2023.3.44 - -# New Features -- Adds support for custom noHL tag (closes #210) - # Bug Fixes -- Fix wrapped JSON Decod error from requests (#245) - Thanks @USA-RedDragon -- Code Refactor / lint - Thanks @bakerboy448 -- Adds docstrings - Thanks @bakerboy448 -- Fixes #229 - Thanks @bakerboy448 -- Fixes #218 - Thanks @bakerboy448 +- Fixes #255 +- Fixes #260 -**Full Changelog**: https://github.com/StuffAnThings/qbit_manage/compare/v3.4.4...v3.5.0 +**Full Changelog**: https://github.com/StuffAnThings/qbit_manage/compare/v3.5.0...v3.5.1 diff --git a/modules/qbittorrent.py b/modules/qbittorrent.py index 297f4c9..812af84 100755 --- a/modules/qbittorrent.py +++ b/modules/qbittorrent.py @@ -1349,3 +1349,8 @@ class Qbt: torrent.delete(delete_files=True) else: torrent.delete(delete_files=False) + try: + if torrent in self.torrent_list: + self.torrent_list.remove(torrent) + except ValueError: + logger.debug(f"Torrent {torrent.name} has already been deleted from torrent list.") From fab58de5a298b5a862177b739c341b45a1be4951 Mon Sep 17 00:00:00 2001 From: bobokun Date: Sun, 9 Apr 2023 20:51:13 -0400 Subject: [PATCH 9/9] Fixes #258 --- CHANGELOG | 1 + modules/logs.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7a14d0c..d6b7023 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ # Bug Fixes - Fixes #255 - Fixes #260 +- Fixes #258 **Full Changelog**: https://github.com/StuffAnThings/qbit_manage/compare/v3.5.0...v3.5.1 diff --git a/modules/logs.py b/modules/logs.py index 27a43d3..f580dfd 100755 --- a/modules/logs.py +++ b/modules/logs.py @@ -46,7 +46,7 @@ class MyLogger: self.save_errors = False self.saved_errors = [] self.config_handlers = {} - self.secrets = [] + self.secrets = set() self.spacing = 0 os.makedirs(self.log_dir, exist_ok=True) self._logger = logging.getLogger(self.logger_name) @@ -220,7 +220,7 @@ class MyLogger: def secret(self, text): """Add secret""" if str(text) not in self.secrets and str(text): - self.secrets.append(str(text)) + self.secrets.add(str(text)) def insert_space(self, display_title, space_length=0): """Insert space""" @@ -246,7 +246,7 @@ class MyLogger: if isinstance(handler, RotatingFileHandler): handler.setFormatter(logging.Formatter("[%(asctime)s] %(filename)-27s %(levelname)-10s | %(message)s")) else: - for secret in self.secrets: + for secret in sorted(self.secrets, reverse=True): if secret in msg: msg = msg.replace(secret, "(redacted)") if "HTTPConnectionPool" in msg: