refactor nohardlinks

This commit is contained in:
bobokun 2023-04-10 16:30:57 -04:00
parent 3c1410f8af
commit 5cfb0cd4b3
No known key found for this signature in database
GPG key ID: B73932169607D927
3 changed files with 358 additions and 291 deletions

View file

@ -0,0 +1,350 @@
import os
from modules import util
logger = util.logger
class TagNoHardLinks:
def __init__(self, qbit_manager):
self.qbt = qbit_manager
self.config = qbit_manager.config
self.client = qbit_manager.client
self.stats_tagged = 0 # counter for the number of torrents that has no hardlinks
self.stats_untagged = 0 # counter for number of torrents that previously had no hardlinks but now have hardlinks
self.stats_deleted = 0 # counter for the number of torrents that has no hardlinks and \
# meets the criteria for ratio limit/seed limit for deletion
self.stats_deleted_contents = 0 # counter for the number of torrents that has no hardlinks and \
# meets the criteria for ratio limit/seed limit for deletion including contents
self.tdel_dict = {} # dictionary to track the torrent names and content path that meet the deletion criteria
self.root_dir = qbit_manager.config.root_dir
self.remote_dir = qbit_manager.config.remote_dir
self.nohardlinks = qbit_manager.config.nohardlinks
self.nohardlinks_tag = qbit_manager.config.nohardlinks_tag
self.tag_nohardlinks()
def add_tag_no_hl(self, torrent, tracker, category, max_ratio, max_seeding_time, add_tag=True):
"""Add tag nohardlinks_tag to torrents with no hardlinks"""
body = []
body.append(logger.insert_space(f"Torrent Name: {torrent.name}", 3))
if add_tag:
body.append(logger.insert_space(f"Added Tag: {self.nohardlinks_tag}", 6))
title = "Tagging Torrents with No Hardlinks"
else:
title = "Changing Share Ratio of Torrents with No Hardlinks"
body.append(logger.insert_space(f'Tracker: {tracker["url"]}', 8))
body_tags_and_limits = self.qbt.set_tags_and_limits(
torrent,
max_ratio,
max_seeding_time,
self.nohardlinks[category]["limit_upload_speed"],
tags=self.nohardlinks_tag,
do_print=False,
)
if body_tags_and_limits or add_tag:
self.stats_tagged += 1
# Resume torrent if it was paused now that the share limit has changed
if torrent.state_enum.is_complete and self.nohardlinks[category]["resume_torrent_after_untagging_noHL"]:
if not self.config.dry_run:
torrent.resume()
body.extend(body_tags_and_limits)
for rcd in body:
logger.print_line(rcd, self.config.loglevel)
attr = {
"function": "tag_nohardlinks",
"title": title,
"body": "\n".join(body),
"torrent_name": torrent.name,
"torrent_category": torrent.category,
"torrent_tag": self.nohardlinks_tag,
"torrent_tracker": tracker["url"],
"notifiarr_indexer": tracker["notifiarr"],
"torrent_max_ratio": max_ratio,
"torrent_max_seeding_time": max_seeding_time,
"torrent_limit_upload_speed": self.nohardlinks[category]["limit_upload_speed"],
}
self.config.send_notifications(attr)
def cleanup_tagged_torrents_with_no_hardlinks(self, category):
"""Delete any tagged torrents that meet noHL criteria"""
# loop through torrent list again for cleanup purposes
if self.nohardlinks[category]["cleanup"]:
torrent_list = self.qbt.get_torrents({"category": category, "status_filter": "completed"})
for torrent in torrent_list:
t_name = torrent.name
t_hash = torrent.hash
if t_hash in self.tdel_dict and self.nohardlinks_tag in torrent.tags:
t_count = self.qbt.torrentinfo[t_name]["count"]
t_msg = self.qbt.torrentinfo[t_name]["msg"]
t_status = self.qbt.torrentinfo[t_name]["status"]
# Double check that the content path is the same before we delete anything
if torrent["content_path"].replace(self.root_dir, self.remote_dir) == self.tdel_dict[t_hash]["content_path"]:
tracker = self.qbt.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)
body += logger.print_line(self.tdel_dict[t_hash]["body"], self.config.loglevel)
body += logger.print_line(
logger.insert_space("Cleanup: True [No hardlinks found and meets Share Limits.]", 8),
self.config.loglevel,
)
attr = {
"function": "cleanup_tag_nohardlinks",
"title": "Removing NoHL Torrents and meets Share Limits",
"torrent_name": t_name,
"torrent_category": torrent.category,
"cleanup": "True",
"torrent_tracker": tracker["url"],
"notifiarr_indexer": tracker["notifiarr"],
}
if os.path.exists(torrent["content_path"].replace(self.root_dir, self.remote_dir)):
# Checks if any of the original torrents are working
if t_count > 1 and ("" in t_msg or 2 in t_status):
self.stats_deleted += 1
attr["torrents_deleted_and_contents"] = False
if not self.config.dry_run:
self.qbt.tor_delete_recycle(torrent, attr)
body += logger.print_line(
logger.insert_space("Deleted .torrent but NOT content files.", 8),
self.config.loglevel,
)
else:
self.stats_deleted_contents += 1
attr["torrents_deleted_and_contents"] = True
if not self.config.dry_run:
self.qbt.tor_delete_recycle(torrent, attr)
body += logger.print_line(
logger.insert_space("Deleted .torrent AND content files.", 8), self.config.loglevel
)
else:
self.stats_deleted += 1
attr["torrents_deleted_and_contents"] = False
if not self.config.dry_run:
self.qbt.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)
self.config.send_notifications(attr)
self.qbt.torrentinfo[t_name]["count"] -= 1
def check_previous_nohardlinks_tagged_torrents(self, has_nohardlinks, torrent, tracker, category):
"""
Checks for any previous torrents that were tagged with the nohardlinks tag and have since had hardlinks added.
If any are found, the nohardlinks tag is removed from the torrent and the tracker or global share limits are restored.
If the torrent is complete and the option to resume after untagging is enabled, the torrent is resumed.
"""
if not (has_nohardlinks) and (self.nohardlinks_tag in torrent.tags):
self.stats_untagged += 1
body = []
body += logger.print_line(
f"Previous Tagged {self.nohardlinks_tag} " f"Torrent Name: {torrent.name} has hardlinks found now.",
self.config.loglevel,
)
body += logger.print_line(logger.insert_space(f"Removed Tag: {self.nohardlinks_tag}", 6), self.config.loglevel)
body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel)
body += logger.print_line(
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"]
if restore_max_ratio is None:
restore_max_ratio = -2
if restore_max_seeding_time is None:
restore_max_seeding_time = -2
if restore_limit_upload_speed is None:
restore_limit_upload_speed = -1
if not self.config.dry_run:
torrent.remove_tags(tags=self.nohardlinks_tag)
body.extend(
self.qbt.set_tags_and_limits(
torrent, restore_max_ratio, restore_max_seeding_time, restore_limit_upload_speed, restore=True
)
)
if torrent.state_enum.is_complete and self.nohardlinks[category]["resume_torrent_after_untagging_noHL"]:
torrent.resume()
attr = {
"function": "untag_nohardlinks",
"title": "Untagging Previous Torrents that now have hardlinks",
"body": "\n".join(body),
"torrent_name": torrent.name,
"torrent_category": torrent.category,
"torrent_tag": self.nohardlinks_tag,
"torrent_tracker": tracker["url"],
"notifiarr_indexer": tracker["notifiarr"],
"torrent_max_ratio": restore_max_ratio,
"torrent_max_seeding_time": restore_max_seeding_time,
"torrent_limit_upload_speed": restore_limit_upload_speed,
}
self.config.send_notifications(attr)
def tag_nohardlinks(self):
"""Tag torrents with no hardlinks"""
logger.separator("Tagging Torrents with No Hardlinks", space=False, border=False)
nohardlinks = self.nohardlinks
for category in nohardlinks:
torrent_list = self.qbt.get_torrents({"category": category, "status_filter": "completed"})
if len(torrent_list) == 0:
ex = (
"No torrents found in the category ("
+ category
+ ") defined under nohardlinks attribute in the config. "
+ "Please check if this matches with any category in qbittorrent and has 1 or more torrents."
)
logger.warning(ex)
continue
for torrent in torrent_list:
tracker = self.qbt.get_tags(torrent.trackers)
has_nohardlinks = util.nohardlink(
torrent["content_path"].replace(self.root_dir, self.remote_dir), self.config.notify
)
if any(tag in torrent.tags for tag in nohardlinks[category]["exclude_tags"]):
# Skip to the next torrent if we find any torrents that are in the exclude tag
continue
else:
# Checks for any hardlinks and not already tagged
# Cleans up previously tagged nohardlinks_tag torrents that no longer have hardlinks
if has_nohardlinks:
tracker = self.qbt.get_tags(torrent.trackers)
# Determine min_seeding_time.
# If only tracker setting is set, use tracker's min_seeding_time
# If only nohardlinks category setting is set, use nohardlinks category's min_seeding_time
# 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
logger.trace(f'tracker["min_seeding_time"] is {tracker["min_seeding_time"]}')
logger.trace(f'nohardlinks[category]["min_seeding_time"] is {nohardlinks[category]["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"]
logger.trace(f'Using tracker["min_seeding_time"] {min_seeding_time}')
else:
min_seeding_time = nohardlinks[category]["min_seeding_time"]
logger.trace(f'Using nohardlinks[category]["min_seeding_time"] {min_seeding_time}')
elif nohardlinks[category]["min_seeding_time"]:
min_seeding_time = nohardlinks[category]["min_seeding_time"]
logger.trace(f'Using nohardlinks[category]["min_seeding_time"] {min_seeding_time}')
elif tracker["min_seeding_time"]:
min_seeding_time = tracker["min_seeding_time"]
logger.trace(f'Using tracker["min_seeding_time"] {min_seeding_time}')
else:
logger.trace(f"Using default 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
logger.trace(f'tracker["max_ratio"] is {tracker["max_ratio"]}')
logger.trace(f'nohardlinks[category]["max_ratio"] is {nohardlinks[category]["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"]
logger.trace(f'Using (tracker["max_ratio"]) {max_ratio}')
else:
max_ratio = nohardlinks[category]["max_ratio"]
logger.trace(f'Using (nohardlinks[category]["max_ratio"]) {max_ratio}')
elif nohardlinks[category]["max_ratio"]:
max_ratio = nohardlinks[category]["max_ratio"]
logger.trace(f'Using (nohardlinks[category]["max_ratio"]) {max_ratio}')
elif tracker["max_ratio"]:
max_ratio = tracker["max_ratio"]
logger.trace(f'Using (tracker["max_ratio"]) {max_ratio}')
else:
logger.trace(f"Using default (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
# 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
logger.trace(f'tracker["max_seeding_time"] is {tracker["max_seeding_time"]}')
logger.trace(f'nohardlinks[category]["max_seeding_time"] is {nohardlinks[category]["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"]
logger.trace(f'Using (tracker["max_seeding_time"]) {max_seeding_time}')
else:
max_seeding_time = nohardlinks[category]["max_seeding_time"]
logger.trace(f'Using (nohardlinks[category]["max_seeding_time"]) {max_seeding_time}')
elif nohardlinks[category]["max_seeding_time"]:
max_seeding_time = nohardlinks[category]["max_seeding_time"]
logger.trace(f'Using (nohardlinks[category]["max_seeding_time"]) {max_seeding_time}')
elif tracker["max_seeding_time"]:
max_seeding_time = tracker["max_seeding_time"]
logger.trace(f'Using (tracker["max_seeding_time"]) {max_seeding_time}')
else:
logger.trace(f"Using default (max_seeding_time) {max_seeding_time}")
# Will only tag new torrents that don't have nohardlinks_tag tag
if self.nohardlinks_tag not in torrent.tags:
self.add_tag_no_hl(
torrent=torrent,
tracker=tracker,
category=category,
max_ratio=max_ratio,
max_seeding_time=max_seeding_time,
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.qbt.has_reached_seed_limit(
torrent,
max_ratio,
max_seeding_time,
min_seeding_time,
nohardlinks[category]["resume_torrent_after_untagging_noHL"],
tracker["url"],
)
if tor_reach_seed_limit:
if torrent.hash not in self.tdel_dict:
self.tdel_dict[torrent.hash] = {}
self.tdel_dict[torrent.hash]["content_path"] = torrent["content_path"].replace(
self.root_dir, self.remote_dir
)
self.tdel_dict[torrent.hash]["body"] = tor_reach_seed_limit
else:
# Updates torrent to see if "MinSeedTimeNotReached" tag has been added
torrent = self.qbt.get_torrents({"torrent_hashes": [torrent.hash]}).data[0]
# Checks to see if previously nohardlinks_tag share limits have changed.
self.add_tag_no_hl(
torrent=torrent,
tracker=tracker,
category=category,
max_ratio=max_ratio,
max_seeding_time=max_seeding_time,
add_tag=False,
)
self.check_previous_nohardlinks_tagged_torrents(has_nohardlinks, torrent, tracker, category)
self.cleanup_tagged_torrents_with_no_hardlinks(category)
if self.stats_tagged >= 1:
logger.print_line(
f"{'Did not Tag/set' if self.config.dry_run else 'Tag/set'} share limits for {self.stats_tagged} "
f".torrent{'s.' if self.stats_tagged > 1 else '.'}",
self.config.loglevel,
)
else:
logger.print_line("No torrents to tag with no hardlinks.", self.config.loglevel)
if self.stats_untagged >= 1:
logger.print_line(
f"{'Did not delete' if self.config.dry_run else 'Deleted'} "
f"{self.nohardlinks_tag} tags / share limits for {self.stats_untagged} "
f".torrent{'s.' if self.stats_untagged > 1 else '.'}",
self.config.loglevel,
)
if self.stats_deleted >= 1:
logger.print_line(
f"{'Did not delete' if self.config.dry_run else 'Deleted'} {self.stats_deleted} "
f".torrent{'s' if self.stats_deleted > 1 else ''} but not content files.",
self.config.loglevel,
)
if self.stats_deleted_contents >= 1:
logger.print_line(
f"{'Did not delete' if self.config.dry_run else 'Deleted'} {self.stats_deleted_contents} "
f".torrent{'s' if self.stats_deleted_contents > 1 else ''} AND content files.",
self.config.loglevel,
)

View file

@ -564,291 +564,6 @@ class Qbt:
logger.warning(e)
return category
def tag_nohardlinks(self):
"""Tag torrents with no hardlinks"""
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
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
num_untag = 0 # counter for number of torrents that previously had no hardlinks but now have hardlinks
def add_tag_no_hl(add_tag=True):
"""Add tag nohardlinks_tag to torrents with no hardlinks"""
nonlocal num_tags, torrent, tracker, nohardlinks, category, max_ratio, max_seeding_time
body = []
body.append(logger.insert_space(f"Torrent Name: {torrent.name}", 3))
if add_tag:
body.append(logger.insert_space(f"Added Tag: {self.config.nohardlinks_tag}", 6))
title = "Tagging Torrents with No Hardlinks"
else:
title = "Changing Share Ratio of Torrents with No Hardlinks"
body.append(logger.insert_space(f'Tracker: {tracker["url"]}', 8))
body_tags_and_limits = self.set_tags_and_limits(
torrent,
max_ratio,
max_seeding_time,
nohardlinks[category]["limit_upload_speed"],
tags=self.config.nohardlinks_tag,
do_print=False,
)
if body_tags_and_limits or add_tag:
num_tags += 1
# Resume torrent if it was paused now that the share limit has changed
if torrent.state_enum.is_complete and nohardlinks[category]["resume_torrent_after_untagging_noHL"]:
if not self.config.dry_run:
torrent.resume()
body.extend(body_tags_and_limits)
for rcd in body:
logger.print_line(rcd, self.config.loglevel)
attr = {
"function": "tag_nohardlinks",
"title": title,
"body": "\n".join(body),
"torrent_name": torrent.name,
"torrent_category": torrent.category,
"torrent_tag": self.config.nohardlinks_tag,
"torrent_tracker": tracker["url"],
"notifiarr_indexer": tracker["notifiarr"],
"torrent_max_ratio": max_ratio,
"torrent_max_seeding_time": max_seeding_time,
"torrent_limit_upload_speed": nohardlinks[category]["limit_upload_speed"],
}
self.config.send_notifications(attr)
if self.config.commands["tag_nohardlinks"]:
logger.separator("Tagging Torrents with No Hardlinks", space=False, border=False)
nohardlinks = self.config.nohardlinks
tdel_dict = {} # dictionary to track the torrent names and content path that meet the deletion criteria
root_dir = self.config.root_dir
remote_dir = self.config.remote_dir
for category in nohardlinks:
torrent_list = self.get_torrents({"category": category, "status_filter": "completed"})
if len(torrent_list) == 0:
ex = (
"No torrents found in the category ("
+ category
+ ") defined under nohardlinks attribute in the config. "
+ "Please check if this matches with any category in qbittorrent and has 1 or more torrents."
)
logger.warning(ex)
continue
for torrent in torrent_list:
tracker = self.get_tags(torrent.trackers)
has_nohardlinks = util.nohardlink(torrent["content_path"].replace(root_dir, remote_dir), self.config.notify)
if any(tag in torrent.tags for tag in nohardlinks[category]["exclude_tags"]):
# Skip to the next torrent if we find any torrents that are in the exclude tag
continue
else:
# Checks for any hardlinks and not already tagged
# Cleans up previously tagged nohardlinks_tag torrents that no longer have hardlinks
if has_nohardlinks:
tracker = self.get_tags(torrent.trackers)
# Determine min_seeding_time.
# If only tracker setting is set, use tracker's min_seeding_time
# If only nohardlinks category setting is set, use nohardlinks category's min_seeding_time
# 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"] >= 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 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 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)
# 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(
torrent,
max_ratio,
max_seeding_time,
min_seeding_time,
nohardlinks[category]["resume_torrent_after_untagging_noHL"],
tracker["url"],
)
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(
root_dir, remote_dir
)
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]
# 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 += logger.print_line(
f"Previous Tagged {self.config.nohardlinks_tag} "
f"Torrent Name: {torrent.name} has hardlinks found now.",
self.config.loglevel,
)
body += logger.print_line(
logger.insert_space(f"Removed Tag: {self.config.nohardlinks_tag}", 6), self.config.loglevel
)
body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel)
body += logger.print_line(
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"]
if restore_max_ratio is None:
restore_max_ratio = -2
if restore_max_seeding_time is None:
restore_max_seeding_time = -2
if restore_limit_upload_speed is None:
restore_limit_upload_speed = -1
if not self.config.dry_run:
torrent.remove_tags(tags=self.config.nohardlinks_tag)
body.extend(
self.set_tags_and_limits(
torrent, restore_max_ratio, restore_max_seeding_time, restore_limit_upload_speed, restore=True
)
)
if torrent.state_enum.is_complete and nohardlinks[category]["resume_torrent_after_untagging_noHL"]:
torrent.resume()
attr = {
"function": "untag_nohardlinks",
"title": "Untagging Previous Torrents that now have hardlinks",
"body": "\n".join(body),
"torrent_name": torrent.name,
"torrent_category": torrent.category,
"torrent_tag": self.config.nohardlinks_tag,
"torrent_tracker": tracker["url"],
"notifiarr_indexer": tracker["notifiarr"],
"torrent_max_ratio": restore_max_ratio,
"torrent_max_seeding_time": restore_max_seeding_time,
"torrent_limit_upload_speed": restore_limit_upload_speed,
}
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"})
for torrent in torrent_list:
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"]
# 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.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
)
body += logger.print_line(tdel_dict[t_hash]["body"], self.config.loglevel)
body += logger.print_line(
logger.insert_space("Cleanup: True [No hardlinks found and meets Share Limits.]", 8),
self.config.loglevel,
)
attr = {
"function": "cleanup_tag_nohardlinks",
"title": "Removing NoHL Torrents and meets Share Limits",
"torrent_name": t_name,
"torrent_category": torrent.category,
"cleanup": "True",
"torrent_tracker": tracker["url"],
"notifiarr_indexer": tracker["notifiarr"],
}
if os.path.exists(torrent["content_path"].replace(root_dir, remote_dir)):
# 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
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,
)
else:
del_tor_cont += 1
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
)
else:
del_tor += 1
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)
self.config.send_notifications(attr)
self.torrentinfo[t_name]["count"] -= 1
if num_tags >= 1:
logger.print_line(
f"{'Did not Tag/set' if self.config.dry_run else 'Tag/set'} share limits for {num_tags} "
f".torrent{'s.' if num_tags > 1 else '.'}",
self.config.loglevel,
)
else:
logger.print_line("No torrents to tag with no hardlinks.", self.config.loglevel)
if num_untag >= 1:
logger.print_line(
f"{'Did not delete' if self.config.dry_run else 'Deleted'} "
f"{self.config.nohardlinks_tag} tags / share limits for {num_untag} "
f".torrent{'s.' if num_untag > 1 else '.'}",
self.config.loglevel,
)
if del_tor >= 1:
logger.print_line(
f"{'Did not delete' if self.config.dry_run else 'Deleted'} {del_tor} "
f".torrent{'s' if del_tor > 1 else ''} but not content files.",
self.config.loglevel,
)
if del_tor_cont >= 1:
logger.print_line(
f"{'Did not delete' if self.config.dry_run else 'Deleted'} {del_tor_cont} "
f".torrent{'s' if del_tor_cont > 1 else ''} AND content files.",
self.config.loglevel,
)
return num_tags, num_untag, del_tor, del_tor_cont
def rem_orphaned(self):
"""Remove orphaned files from remote directory"""
orphaned = 0

View file

@ -292,6 +292,7 @@ from modules.core.tags import Tags # noqa
from modules.core.remove_unregistered import RemoveUnregistered # noqa
from modules.core.cross_seed import CrossSeed # noqa
from modules.core.recheck import ReCheck # noqa
from modules.core.tag_nohardlinks import TagNoHardLinks # noqa
def my_except_hook(exctype, value, tbi):
@ -418,12 +419,13 @@ def start():
stats["rechecked"] += recheck.stats_rechecked
# Tag NoHardLinks
num_tagged, num_untagged, num_deleted, num_deleted_contents = cfg.qbt.tag_nohardlinks()
stats["tagged"] += num_tagged
stats["tagged_noHL"] += num_tagged
stats["untagged_noHL"] += num_untagged
stats["deleted"] += num_deleted
stats["deleted_contents"] += num_deleted_contents
if cfg.commands["tag_nohardlinks"]:
no_hardlinks = TagNoHardLinks(qbit_manager)
stats["tagged"] += no_hardlinks.stats_tagged
stats["tagged_noHL"] += no_hardlinks.stats_tagged
stats["untagged_noHL"] += no_hardlinks.stats_untagged
stats["deleted"] += no_hardlinks.stats_deleted
stats["deleted_contents"] += no_hardlinks.stats_deleted_contents
# Remove Orphaned Files
num_orphaned = cfg.qbt.rem_orphaned()