qbit module

- pylint and misc variable/naming cleanup
- add docstrings
This commit is contained in:
Bakerboy448 2023-03-31 09:56:55 -05:00
parent b7be46b5f8
commit 44d21d0c65

View file

@ -1,3 +1,4 @@
"""Qbittorrent Module"""
import os import os
import sys import sys
from collections import Counter from collections import Counter
@ -11,14 +12,18 @@ from qbittorrentapi import LoginFailed
from qbittorrentapi import NotFound404Error from qbittorrentapi import NotFound404Error
from qbittorrentapi import Version from qbittorrentapi import Version
from .util import Failed
from .util import list_in_text
from modules import util from modules import util
from modules.util import Failed
from modules.util import list_in_text
logger = util.logger logger = util.logger
class Qbt: class Qbt:
"""
Qbittorrent Class
"""
def __init__(self, config, params): def __init__(self, config, params):
self.config = config self.config = config
self.host = params["host"] self.host = params["host"]
@ -26,50 +31,50 @@ class Qbt:
self.password = params["password"] self.password = params["password"]
logger.secret(self.username) logger.secret(self.username)
logger.secret(self.password) logger.secret(self.password)
logger.debug(f"Host: {self.host}, Username: {self.username}, Password: {self.password}") logger.debug("Host: %s, Username: %s, Password: %s", self.host, self.username, self.password)
e = "" ex = ""
try: try:
self.client = Client(host=self.host, username=self.username, password=self.password, VERIFY_WEBUI_CERTIFICATE=False) self.client = Client(host=self.host, username=self.username, password=self.password, VERIFY_WEBUI_CERTIFICATE=False)
self.client.auth_log_in() self.client.auth_log_in()
SUPPORTED_VERSION = Version.latest_supported_app_version() supported_version = Version.latest_supported_app_version()
CURRENT_VERSION = self.client.app.version current_version = self.client.app.version
MIN_SUPPORTED_VERSION = "v4.3.0" min_supported_version = "v4.3.0"
logger.debug(f"qBittorrent: {self.client.app.version}") logger.debug("qBittorrent: %s", self.client.app.version)
logger.debug(f"qBittorrent Web API: {self.client.app.web_api_version}") logger.debug("qBittorrent Web API: %s", self.client.app.web_api_version)
logger.debug(f"qbit_manage support versions: {MIN_SUPPORTED_VERSION} - {SUPPORTED_VERSION}") logger.debug("qbit_manage support versions: %s - %s", min_supported_version, supported_version)
if CURRENT_VERSION < MIN_SUPPORTED_VERSION: if current_version < min_supported_version:
e = ( ex = (
f"Qbittorrent Error: qbit_manage is only comaptible with {MIN_SUPPORTED_VERSION} or higher. " f"Qbittorrent Error: qbit_manage is only compatible with {min_supported_version} or higher. "
f"You are currently on {CURRENT_VERSION}." f"You are currently on {current_version}."
+ "\n" + "\n"
+ f"Please upgrade to your Qbittorrent version to {MIN_SUPPORTED_VERSION} or higher to use qbit_manage." + f"Please upgrade to your Qbittorrent version to {min_supported_version} or higher to use qbit_manage."
) )
elif not Version.is_app_version_supported(CURRENT_VERSION): elif not Version.is_app_version_supported(current_version):
e = ( ex = (
f"Qbittorrent Error: qbit_manage is only comaptible with {SUPPORTED_VERSION} or lower. " f"Qbittorrent Error: qbit_manage is only compatible with {supported_version} or lower. "
f"You are currently on {CURRENT_VERSION}." f"You are currently on {current_version}."
+ "\n" + "\n"
+ f"Please downgrade to your Qbittorrent version to {SUPPORTED_VERSION} to use qbit_manage." + f"Please downgrade to your Qbittorrent version to {supported_version} to use qbit_manage."
) )
if e: if ex:
self.config.notify(e, "Qbittorrent") self.config.notify(ex, "Qbittorrent")
logger.print_line(e, "CRITICAL") logger.print_line(ex, "CRITICAL")
sys.exit(0) sys.exit(0)
else: else:
logger.info("Qbt Connection Successful") logger.info("Qbt Connection Successful")
except LoginFailed: except LoginFailed as exc:
e = "Qbittorrent Error: Failed to login. Invalid username/password." ex = "Qbittorrent Error: Failed to login. Invalid username/password."
self.config.notify(e, "Qbittorrent") self.config.notify(ex, "Qbittorrent")
raise Failed(e) raise Failed(ex) from exc
except APIConnectionError: except APIConnectionError as exc:
e = "Qbittorrent Error: Unable to connect to the client." ex = "Qbittorrent Error: Unable to connect to the client."
self.config.notify(e, "Qbittorrent") self.config.notify(ex, "Qbittorrent")
raise Failed(e) raise Failed(ex) from exc
except Exception: except Exception as exc:
e = "Qbittorrent Error: Unable to connect to the client." ex = "Qbittorrent Error: Unable to connect to the client."
self.config.notify(e, "Qbittorrent") self.config.notify(ex, "Qbittorrent")
raise Failed(e) raise Failed(ex) from exc
logger.separator("Getting Torrent List", space=False, border=False) logger.separator("Getting Torrent List", space=False, border=False)
self.torrent_list = self.get_torrents({"sort": "added_on"}) self.torrent_list = self.get_torrents({"sort": "added_on"})
@ -130,9 +135,9 @@ class Qbt:
save_path = torrent.save_path save_path = torrent.save_path
category = torrent.category category = torrent.category
torrent_trackers = torrent.trackers torrent_trackers = torrent.trackers
except Exception as e: except Exception as ex:
self.config.notify(e, "Get Torrent Info", False) self.config.notify(ex, "Get Torrent Info", False)
logger.warning(e) logger.warning(ex)
if torrent_name in torrentdict: if torrent_name in torrentdict:
t_obj_list.append(torrent) t_obj_list.append(torrent)
t_count = torrentdict[torrent_name]["count"] + 1 t_count = torrentdict[torrent_name]["count"] + 1
@ -147,10 +152,10 @@ class Qbt:
status_list = [] status_list = []
is_complete = torrent_is_complete is_complete = torrent_is_complete
first_hash = torrent_hash first_hash = torrent_hash
for x in torrent_trackers: for trk in torrent_trackers:
if x.url.startswith("http"): if trk.url.startswith("http"):
status = x.status status = trk.status
msg = x.msg.upper() msg = trk.msg.upper()
exception = [ exception = [
"DOWN", "DOWN",
"DOWN.", "DOWN.",
@ -160,11 +165,11 @@ class Qbt:
"BAD GATEWAY", "BAD GATEWAY",
"TRACKER UNAVAILABLE", "TRACKER UNAVAILABLE",
] ]
if x.status == 2: if trk.status == 2:
working_tracker = True working_tracker = True
break break
# Add any potential unregistered torrents to a list # Add any potential unregistered torrents to a list
if x.status == 4 and not list_in_text(msg, exception): if trk.status == 4 and not list_in_text(msg, exception):
issue["potential"] = True issue["potential"] = True
issue["msg"] = msg issue["msg"] = msg
issue["status"] = status issue["status"] = status
@ -207,9 +212,11 @@ class Qbt:
self.torrentinfo, self.torrentissue, self.torrentvalid = get_torrent_info(self.torrent_list) self.torrentinfo, self.torrentissue, self.torrentvalid = get_torrent_info(self.torrent_list)
def get_torrents(self, params): def get_torrents(self, params):
"""Get torrents from qBittorrent"""
return self.client.torrents.info(**params) return self.client.torrents.info(**params)
def category(self): def category(self):
"""Update category for torrents"""
num_cat = 0 num_cat = 0
def update_cat(new_cat, cat_change): def update_cat(new_cat, cat_change):
@ -222,11 +229,11 @@ class Qbt:
if torrent.auto_tmm is False and self.config.settings["force_auto_tmm"]: if torrent.auto_tmm is False and self.config.settings["force_auto_tmm"]:
torrent.set_auto_management(True) torrent.set_auto_management(True)
except Conflict409Error: except Conflict409Error:
e = logger.print_line( ex = logger.print_line(
f'Existing category "{new_cat}" not found for save path {torrent.save_path}, category will be created.', f'Existing category "{new_cat}" not found for save path {torrent.save_path}, category will be created.',
self.config.loglevel, self.config.loglevel,
) )
self.config.notify(e, "Update Category", False) self.config.notify(ex, "Update Category", False)
self.client.torrent_categories.create_category(name=new_cat, save_path=torrent.save_path) self.client.torrent_categories.create_category(name=new_cat, save_path=torrent.save_path)
torrent.set_category(category=new_cat) torrent.set_category(category=new_cat)
body = [] body = []
@ -274,13 +281,14 @@ class Qbt:
return num_cat return num_cat
def tags(self): def tags(self):
"""Update tags for torrents"""
num_tags = 0 num_tags = 0
ignore_tags = self.config.settings["ignoreTags_OnUpdate"] ignore_tags = self.config.settings["ignoreTags_OnUpdate"]
if self.config.commands["tag_update"]: if self.config.commands["tag_update"]:
logger.separator("Updating Tags", space=False, border=False) logger.separator("Updating Tags", space=False, border=False)
for torrent in self.torrent_list: for torrent in self.torrent_list:
check_tags = util.get_list(torrent.tags) check_tags = util.get_list(torrent.tags)
if torrent.tags == "" or (len([x for x in check_tags if x not in ignore_tags]) == 0): if torrent.tags == "" or (len([trk for trk in check_tags if trk not in ignore_tags]) == 0):
tracker = self.config.get_tags(torrent.trackers) tracker = self.config.get_tags(torrent.trackers)
if tracker["tag"]: if tracker["tag"]:
num_tags += len(tracker["tag"]) num_tags += len(tracker["tag"])
@ -328,6 +336,7 @@ class Qbt:
def set_tags_and_limits( def set_tags_and_limits(
self, torrent, max_ratio, max_seeding_time, limit_upload_speed=None, tags=None, restore=False, do_print=True self, torrent, max_ratio, max_seeding_time, limit_upload_speed=None, tags=None, restore=False, do_print=True
): ):
"""Set tags and limits for a torrent"""
body = [] body = []
if limit_upload_speed: if limit_upload_speed:
if limit_upload_speed != -1: if limit_upload_speed != -1:
@ -388,6 +397,7 @@ class Qbt:
return body return body
def has_reached_seed_limit(self, torrent, max_ratio, max_seeding_time, min_seeding_time, resume_torrent, tracker): def has_reached_seed_limit(self, torrent, max_ratio, max_seeding_time, min_seeding_time, resume_torrent, tracker):
"""Check if torrent has reached seed limit"""
body = "" body = ""
def _has_reached_min_seeding_time_limit(): def _has_reached_min_seeding_time_limit():
@ -450,14 +460,16 @@ class Qbt:
return False return False
def tag_nohardlinks(self): def tag_nohardlinks(self):
num_tags = 0 # counter for the number of torrents that has no hard links """Tag torrents with no hardlinks"""
del_tor = 0 # counter for the number of torrents that has no hard links and \ num_tags = 0 # counter for the number of torrents that has no hardlinks
del_tor = 0 # counter for the number of torrents that has no hardlinks and \
# meets the criteria for ratio limit/seed limit for deletion # meets the criteria for ratio limit/seed limit for deletion
del_tor_cont = 0 # counter for the number of torrents that has no hard links and \ del_tor_cont = 0 # counter for the number of torrents that has no hardlinks and \
# meets the criteria for ratio limit/seed limit for deletion including contents # meets the criteria for ratio limit/seed limit for deletion including contents
num_untag = 0 # counter for number of torrents that previously had no hard links but now have hard links num_untag = 0 # counter for number of torrents that previously had no hardlinks but now have hardlinks
def add_tag_noHL(add_tag=True): def add_tag_no_hl(add_tag=True):
"""Add tag noHL to torrents with no hardlinks"""
nonlocal num_tags, torrent, tracker, nohardlinks, category nonlocal num_tags, torrent, tracker, nohardlinks, category
body = [] body = []
body.append(logger.insert_space(f"Torrent Name: {torrent.name}", 3)) body.append(logger.insert_space(f"Torrent Name: {torrent.name}", 3))
@ -482,8 +494,8 @@ class Qbt:
if not self.config.dry_run: if not self.config.dry_run:
torrent.resume() torrent.resume()
body.extend(body_tags_and_limits) body.extend(body_tags_and_limits)
for b in body: for rcd in body:
logger.print_line(b, self.config.loglevel) logger.print_line(rcd, self.config.loglevel)
attr = { attr = {
"function": "tag_nohardlinks", "function": "tag_nohardlinks",
"title": title, "title": title,
@ -508,13 +520,13 @@ class Qbt:
for category in nohardlinks: for category in nohardlinks:
torrent_list = self.get_torrents({"category": category, "status_filter": "completed"}) torrent_list = self.get_torrents({"category": category, "status_filter": "completed"})
if len(torrent_list) == 0: if len(torrent_list) == 0:
e = ( ex = (
"No torrents found in the category (" "No torrents found in the category ("
+ category + category
+ ") defined under nohardlinks attribute in the config. " + ") defined under nohardlinks attribute in the config. "
+ "Please check if this matches with any category in qbittorrent and has 1 or more torrents." + "Please check if this matches with any category in qbittorrent and has 1 or more torrents."
) )
logger.warning(e) logger.warning(ex)
continue continue
for torrent in torrent_list: for torrent in torrent_list:
tracker = self.config.get_tags(torrent.trackers) tracker = self.config.get_tags(torrent.trackers)
@ -523,13 +535,14 @@ class Qbt:
# Skip to the next torrent if we find any torrents that are in the exclude tag # Skip to the next torrent if we find any torrents that are in the exclude tag
continue continue
else: else:
# Checks for any hard links and not already tagged # Checks for any hardlinks and not already tagged
if has_nohardlinks: if has_nohardlinks:
# Will only tag new torrents that don't have noHL tag # Will only tag new torrents that don't have noHL tag
if "noHL" not in torrent.tags: if "noHL" not in torrent.tags:
add_tag_noHL(add_tag=True) add_tag_no_hl(add_tag=True)
# Cleans up previously tagged noHL torrents # Cleans up previously tagged noHL torrents
# Determine min_seeding_time. noHl > Tracker w/ default 0 # Determine min_seeding_time.
# If min_seeding_time is not set in the category, use the tracker's min_seeding_time
min_seeding_time = 0 min_seeding_time = 0
tracker = self.config.get_tags(torrent.trackers) tracker = self.config.get_tags(torrent.trackers)
if nohardlinks[category]["min_seeding_time"]: if nohardlinks[category]["min_seeding_time"]:
@ -558,13 +571,13 @@ class Qbt:
# Updates torrent to see if "MinSeedTimeNotReached" tag has been added # 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 noHL share limits have changed. # Checks to see if previously noHL share limits have changed.
add_tag_noHL(add_tag=False) add_tag_no_hl(add_tag=False)
# Checks to see if previous noHL tagged torrents now have hard links. # Checks to see if previous noHL tagged torrents now have hardlinks.
if not (has_nohardlinks) and ("noHL" in torrent.tags): if not (has_nohardlinks) and ("noHL" in torrent.tags):
num_untag += 1 num_untag += 1
body = [] body = []
body += logger.print_line( body += logger.print_line(
f"Previous Tagged noHL Torrent Name: {torrent.name} has hard links found now.", self.config.loglevel f"Previous Tagged noHL Torrent Name: {torrent.name} has hardlinks found now.", self.config.loglevel
) )
body += logger.print_line(logger.insert_space("Removed Tag: noHL", 6), self.config.loglevel) body += logger.print_line(logger.insert_space("Removed Tag: noHL", 6), self.config.loglevel)
body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel)
@ -591,7 +604,7 @@ class Qbt:
torrent.resume() torrent.resume()
attr = { attr = {
"function": "untag_nohardlinks", "function": "untag_nohardlinks",
"title": "Untagging Previous Torrents that now have Hard Links", "title": "Untagging Previous Torrents that now have hardlinks",
"body": "\n".join(body), "body": "\n".join(body),
"torrent_name": torrent.name, "torrent_name": torrent.name,
"torrent_category": torrent.category, "torrent_category": torrent.category,
@ -609,7 +622,7 @@ class Qbt:
for torrent in torrent_list: for torrent in torrent_list:
t_name = torrent.name t_name = torrent.name
t_hash = torrent.hash t_hash = torrent.hash
if t_hash in tdel_dict.keys() and "noHL" in torrent.tags: if t_hash in tdel_dict and "noHL" in torrent.tags:
t_count = self.torrentinfo[t_name]["count"] t_count = self.torrentinfo[t_name]["count"]
t_msg = self.torrentinfo[t_name]["msg"] t_msg = self.torrentinfo[t_name]["msg"]
t_status = self.torrentinfo[t_name]["status"] t_status = self.torrentinfo[t_name]["status"]
@ -623,7 +636,7 @@ class Qbt:
) )
body += logger.print_line(tdel_dict[t_hash]["body"], self.config.loglevel) body += logger.print_line(tdel_dict[t_hash]["body"], self.config.loglevel)
body += logger.print_line( body += logger.print_line(
logger.insert_space("Cleanup: True [No hard links found and meets Share Limits.]", 8), logger.insert_space("Cleanup: True [No hardlinks found and meets Share Limits.]", 8),
self.config.loglevel, self.config.loglevel,
) )
attr = { attr = {
@ -672,7 +685,7 @@ class Qbt:
self.config.loglevel, self.config.loglevel,
) )
else: else:
logger.print_line("No torrents to tag with no hard links.", self.config.loglevel) logger.print_line("No torrents to tag with no hardlinks.", self.config.loglevel)
if num_untag >= 1: if num_untag >= 1:
logger.print_line( logger.print_line(
f"{'Did not delete' if self.config.dry_run else 'Deleted'} noHL tags / share limits for {num_untag} " f"{'Did not delete' if self.config.dry_run else 'Deleted'} noHL tags / share limits for {num_untag} "
@ -694,6 +707,7 @@ class Qbt:
return num_tags, num_untag, del_tor, del_tor_cont return num_tags, num_untag, del_tor, del_tor_cont
def rem_unregistered(self): def rem_unregistered(self):
"""Remove torrents with unregistered trackers."""
del_tor = 0 del_tor = 0
del_tor_cont = 0 del_tor_cont = 0
num_tor_error = 0 num_tor_error = 0
@ -829,18 +843,18 @@ class Qbt:
t_status = self.torrentinfo[t_name]["status"] t_status = self.torrentinfo[t_name]["status"]
check_tags = util.get_list(torrent.tags) check_tags = util.get_list(torrent.tags)
try: try:
for x in torrent.trackers: for trk in torrent.trackers:
if x.url.startswith("http"): if trk.url.startswith("http"):
tracker = self.config.get_tags([x]) tracker = self.config.get_tags([trk])
msg_up = x.msg.upper() msg_up = trk.msg.upper()
msg = x.msg msg = trk.msg
# Tag any error torrents # Tag any error torrents
if cfg_tag_error: if cfg_tag_error:
if x.status == 4 and tag_error not in check_tags: if trk.status == 4 and tag_error not in check_tags:
tag_tracker_error() tag_tracker_error()
if cfg_rem_unregistered: if cfg_rem_unregistered:
# Tag any error torrents that are not unregistered # Tag any error torrents that are not unregistered
if not list_in_text(msg_up, unreg_msgs) and x.status == 4 and tag_error not in check_tags: if not list_in_text(msg_up, unreg_msgs) and trk.status == 4 and tag_error not in check_tags:
# Check for unregistered torrents using BHD API if the tracker is BHD # Check for unregistered torrents using BHD API if the tracker is BHD
if ( if (
"tracker.beyond-hd.me" in tracker["url"] "tracker.beyond-hd.me" in tracker["url"]
@ -853,15 +867,15 @@ class Qbt:
del_unregistered() del_unregistered()
break break
tag_tracker_error() tag_tracker_error()
if list_in_text(msg_up, unreg_msgs) and not list_in_text(msg_up, ignore_msgs) and x.status == 4: if list_in_text(msg_up, unreg_msgs) and not list_in_text(msg_up, ignore_msgs) and trk.status == 4:
del_unregistered() del_unregistered()
break break
except NotFound404Error: except NotFound404Error:
continue continue
except Exception as e: except Exception as ex:
logger.stacktrace() logger.stacktrace()
self.config.notify(e, "Remove Unregistered Torrents", False) self.config.notify(ex, "Remove Unregistered Torrents", False)
logger.error(f"Unknown Error: {e}") logger.error("Unknown Error: %s", ex)
if cfg_rem_unregistered: if cfg_rem_unregistered:
if del_tor >= 1 or del_tor_cont >= 1: if del_tor >= 1 or del_tor_cont >= 1:
if del_tor >= 1: if del_tor >= 1:
@ -894,8 +908,8 @@ class Qbt:
logger.print_line(tor_error_summary.rstrip(), self.config.loglevel) logger.print_line(tor_error_summary.rstrip(), self.config.loglevel)
return del_tor, del_tor_cont, num_tor_error, num_untag return del_tor, del_tor_cont, num_tor_error, num_untag
# Function used to move any torrents from the cross seed directory to the correct save directory
def cross_seed(self): def cross_seed(self):
"""Move torrents from cross seed directory to correct save directory."""
added = 0 # Keep track of total torrents tagged added = 0 # Keep track of total torrents tagged
tagged = 0 # Track # of torrents tagged that are not cross-seeded tagged = 0 # Track # of torrents tagged that are not cross-seeded
if self.config.commands["cross_seed"]: if self.config.commands["cross_seed"]:
@ -989,10 +1003,10 @@ class Qbt:
torrent.add_tags(tags="cross-seed") torrent.add_tags(tags="cross-seed")
numcategory = Counter(categories) numcategory = Counter(categories)
for c in numcategory: for cat in numcategory:
if numcategory[c] > 0: if numcategory[cat] > 0:
logger.print_line( logger.print_line(
f"{numcategory[c]} {c} cross-seed .torrents {'not added' if self.config.dry_run else 'added'}.", f"{numcategory[cat]} {cat} cross-seed .torrents {'not added' if self.config.dry_run else 'added'}.",
self.config.loglevel, self.config.loglevel,
) )
if added > 0: if added > 0:
@ -1006,8 +1020,8 @@ class Qbt:
) )
return added, tagged return added, tagged
# Function used to recheck paused torrents sorted by size and resume torrents that are completed
def recheck(self): def recheck(self):
"""Function used to recheck paused torrents sorted by size and resume torrents that are completed"""
resumed = 0 resumed = 0
rechecked = 0 rechecked = 0
if self.config.commands["recheck"]: if self.config.commands["recheck"]:
@ -1109,6 +1123,7 @@ class Qbt:
return resumed, rechecked return resumed, rechecked
def rem_orphaned(self): def rem_orphaned(self):
"""Remove orphaned files from remote directory"""
orphaned = 0 orphaned = 0
if self.config.commands["rem_orphaned"]: if self.config.commands["rem_orphaned"]:
logger.separator("Checking for Orphaned Files", space=False, border=False) logger.separator("Checking for Orphaned Files", space=False, border=False)
@ -1140,7 +1155,7 @@ class Qbt:
for torrent in torrent_list: for torrent in torrent_list:
for file in torrent.files: 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 runnig in docker (linux) but qbt is on windows # 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) torrent_files.append(fullpath)
@ -1194,6 +1209,7 @@ class Qbt:
return orphaned return orphaned
def tor_delete_recycle(self, torrent, info): def tor_delete_recycle(self, torrent, info):
"""Move torrent to recycle bin"""
if self.config.recyclebin["enabled"]: if self.config.recyclebin["enabled"]:
tor_files = [] tor_files = []
try: try:
@ -1222,21 +1238,21 @@ class Qbt:
torrent_json_file = os.path.join(torrents_json_path, f"{info['torrent_name']}.json") torrent_json_file = os.path.join(torrents_json_path, f"{info['torrent_name']}.json")
torrent_json = util.load_json(torrent_json_file) torrent_json = util.load_json(torrent_json_file)
if not torrent_json: if not torrent_json:
logger.info(f"Saving Torrent JSON file to {torrent_json_file}") logger.info("Saving Torrent JSON file to %s", torrent_json_file)
torrent_json["torrent_name"] = info["torrent_name"] torrent_json["torrent_name"] = info["torrent_name"]
torrent_json["category"] = info["torrent_category"] torrent_json["category"] = info["torrent_category"]
else: else:
logger.info(f"Adding {info['torrent_tracker']} to existing {os.path.basename(torrent_json_file)}") logger.info("Adding %s to existing %s", info['torrent_tracker'], {os.path.basename(torrent_json_file)})
dot_torrent_files = [] dot_torrent_files = []
for File in os.listdir(self.config.torrents_dir): for file in os.listdir(self.config.torrents_dir):
if File.startswith(info_hash): if file.startswith(info_hash):
dot_torrent_files.append(File) dot_torrent_files.append(file)
try: try:
util.copy_files(os.path.join(self.config.torrents_dir, File), os.path.join(torrent_path, File)) util.copy_files(os.path.join(self.config.torrents_dir, file), os.path.join(torrent_path, file))
except Exception as e: except Exception as ex:
logger.stacktrace() logger.stacktrace()
self.config.notify(e, "Deleting Torrent", False) self.config.notify(ex, "Deleting Torrent", False)
logger.warning(f"RecycleBin Warning: {e}") logger.warning("RecycleBin Warning: %s", ex)
if "tracker_torrent_files" in torrent_json: if "tracker_torrent_files" in torrent_json:
tracker_torrent_files = torrent_json["tracker_torrent_files"] tracker_torrent_files = torrent_json["tracker_torrent_files"]
else: else:
@ -1261,7 +1277,7 @@ class Qbt:
if torrent_json["deleted_contents"] is False and info["torrents_deleted_and_contents"] is True: 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("")
logger.debug(f"JSON: {torrent_json}") logger.debug("JSON: %s", torrent_json)
util.save_json(torrent_json, torrent_json_file) util.save_json(torrent_json, torrent_json_file)
if info["torrents_deleted_and_contents"] is True: if info["torrents_deleted_and_contents"] is True:
logger.separator(f"Moving {len(tor_files)} files to RecycleBin", space=False, border=False, loglevel="DEBUG") logger.separator(f"Moving {len(tor_files)} files to RecycleBin", space=False, border=False, loglevel="DEBUG")
@ -1270,7 +1286,7 @@ class Qbt:
else: else:
logger.print_line("\n".join(tor_files), "DEBUG") logger.print_line("\n".join(tor_files), "DEBUG")
logger.debug( logger.debug(
f"Moved {len(tor_files)} files to {recycle_path.replace(self.config.remote_dir,self.config.root_dir)}" "Moved %s files to %s", len(tor_files), recycle_path.replace(self.config.remote_dir, self.config.root_dir)
) )
# Move files from torrent contents to Recycle bin # Move files from torrent contents to Recycle bin
@ -1279,12 +1295,12 @@ class Qbt:
dest = os.path.join(recycle_path, file.replace(self.config.remote_dir, "")) dest = os.path.join(recycle_path, file.replace(self.config.remote_dir, ""))
# Move files and change date modified # Move files and change date modified
try: try:
toDelete = util.move_files(src, dest, True) to_delete = util.move_files(src, dest, True)
except FileNotFoundError: except FileNotFoundError:
e = 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(e, "Deleting Torrent", False) self.config.notify(ex, "Deleting Torrent", False)
# Delete torrent and files # Delete torrent and files
torrent.delete(delete_files=toDelete) torrent.delete(delete_files=to_delete)
# Remove any empty directories # Remove any empty directories
util.remove_empty_directories(save_path, "**/*") util.remove_empty_directories(save_path, "**/*")
else: else: