refactor remove_unregistered

This commit is contained in:
bobokun 2023-04-10 14:55:14 -04:00
parent c89c6e2ca2
commit 5935b5448d
No known key found for this signature in database
GPG key ID: B73932169607D927
5 changed files with 242 additions and 213 deletions

View file

@ -16,8 +16,6 @@ class Category:
def category(self): def category(self):
"""Update category for torrents that don't have any category defined and returns total number categories updated""" """Update category for torrents that don't have any category defined and returns total number categories updated"""
self.stats = 0
logger.separator("Updating Categories", space=False, border=False) logger.separator("Updating Categories", space=False, border=False)
torrent_list = self.qbt.get_torrents({"category": "", "status_filter": "completed"}) torrent_list = self.qbt.get_torrents({"category": "", "status_filter": "completed"})
for torrent in torrent_list: for torrent in torrent_list:

View file

@ -0,0 +1,232 @@
from qbittorrentapi import NotFound404Error
from modules import util
from modules.util import list_in_text
logger = util.logger
class RemoveUnregistered:
UNREGISTERED_MSGS = [
"UNREGISTERED",
"TORRENT NOT FOUND",
"TORRENT IS NOT FOUND",
"NOT REGISTERED",
"NOT EXIST",
"UNKNOWN TORRENT",
"TRUMP",
"RETITLED",
"TRUNCATED",
"TORRENT IS NOT AUTHORIZED FOR USE ON THIS TRACKER",
]
IGNORE_MSGS = [
"YOU HAVE REACHED THE CLIENT LIMIT FOR THIS TORRENT",
"MISSING PASSKEY",
"MISSING INFO_HASH",
"PASSKEY IS INVALID",
"INVALID PASSKEY",
"EXPECTED VALUE (LIST, DICT, INT OR STRING) IN BENCODED STRING",
"COULD NOT PARSE BENCODED DATA",
"STREAM TRUNCATED",
]
# Tracker has been contacted, but it is not working (or doesn't send proper replies)
TORRENT_STATUS_NOT_WORKING = 4
def __init__(self, qbit_manager):
self.qbt = qbit_manager
self.config = qbit_manager.config
self.client = qbit_manager.client
self.stats_deleted = 0
self.stats_deleted_contents = 0
self.stats_tagged = 0
self.stats_untagged = 0
self.tor_error_summary = ""
self.tag_error = self.config.tracker_error_tag
self.cfg_rem_unregistered = self.config.commands["rem_unregistered"]
self.cfg_tag_error = self.config.commands["tag_tracker_error"]
if self.cfg_tag_error:
logger.separator("Tagging Torrents with Tracker Errors", space=False, border=False)
elif self.cfg_rem_unregistered:
logger.separator("Removing Unregistered Torrents", space=False, border=False)
self.rem_unregistered()
def remove_previous_errors(self):
"""Removes any previous torrents that were tagged as an error but are now working."""
for torrent in self.qbt.torrentvalid:
check_tags = util.get_list(torrent.tags)
# Remove any error torrents Tags that are no longer unreachable.
if self.tag_error in check_tags:
tracker = self.get_tags(torrent.trackers)
self.stats_untagged += 1
body = []
body += logger.print_line(
f"Previous Tagged {self.tag_error} torrent currently has a working tracker.", self.config.loglevel
)
body += logger.print_line(logger.insert_space(f"Torrent Name: {torrent.name}", 3), self.config.loglevel)
body += logger.print_line(logger.insert_space(f"Removed Tag: {self.tag_error}", 4), self.config.loglevel)
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=self.tag_error)
attr = {
"function": "untag_tracker_error",
"title": "Untagging Tracker Error Torrent",
"body": "\n".join(body),
"torrent_name": torrent.name,
"torrent_category": torrent.category,
"torrent_tag": self.tag_error,
"torrent_tracker": tracker["url"],
"notifiarr_indexer": tracker["notifiarr"],
}
self.config.send_notifications(attr)
def process_torrent_issues(self):
for torrent in self.qbt.torrentissue:
self.t_name = torrent.name
self.t_cat = self.qbt.torrentinfo[self.t_name]["Category"]
self.t_msg = self.qbt.torrentinfo[self.t_name]["msg"]
self.t_status = self.qbt.torrentinfo[self.t_name]["status"]
check_tags = util.get_list(torrent.tags)
try:
for trk in torrent.trackers:
if trk.url.startswith("http"):
tracker = self.qbt.get_tags([trk])
msg_up = trk.msg.upper()
msg = trk.msg
# Tag any error torrents
if self.cfg_tag_error:
if trk.status == self.TORRENT_STATUS_NOT_WORKING and self.tag_error not in check_tags:
self.tag_tracker_error()
if self.cfg_rem_unregistered:
# Tag any error torrents that are not unregistered
if (
not list_in_text(msg_up, self.UNREGISTERED_MSGS)
and trk.status == self.TORRENT_STATUS_NOT_WORKING
and self.tag_error not in check_tags
):
# Check for unregistered torrents using BHD API if the tracker is BHD
if (
"tracker.beyond-hd.me" in tracker["url"]
and self.config.beyond_hd is not None
and not list_in_text(msg_up, self.IGNORE_MSGS)
):
json = {"info_hash": torrent.hash}
response = self.config.beyond_hd.search(json)
if response["total_results"] == 0:
self.del_unregistered(msg, tracker, torrent)
break
self.tag_tracker_error()
if (
list_in_text(msg_up, self.UNREGISTERED_MSGS)
and not list_in_text(msg_up, self.IGNORE_MSGS)
and trk.status == self.TORRENT_STATUS_NOT_WORKING
):
self.del_unregistered()
break
except NotFound404Error:
continue
except Exception as ex:
logger.stacktrace()
self.config.notify(ex, "Remove Unregistered Torrents", False)
logger.error(f"Remove Unregistered Torrents Error: {ex}")
def rem_unregistered(self):
"""Remove torrents with unregistered trackers."""
self.remove_previous_errors()
self.process_torrent_issues()
if self.cfg_rem_unregistered:
if self.stats_deleted >= 1 or self.stats_deleted_contents >= 1:
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,
)
else:
logger.print_line("No unregistered torrents found.", self.config.loglevel)
if self.stats_untagged >= 1:
logger.print_line(
f"{'Did not delete' if self.config.dry_run else 'Deleted'} {self.tag_error} tags for {self.stats_untagged} "
f".torrent{'s.' if self.stats_untagged > 1 else '.'}",
self.config.loglevel,
)
if self.stats_tagged >= 1:
logger.separator(
f"{self.stats_tagged} Torrents with tracker errors found",
space=False,
border=False,
loglevel=self.config.loglevel,
)
logger.print_line(self.tor_error_summary.rstrip(), self.config.loglevel)
def tag_tracker_error(self, msg, tracker, torrent):
"""Tags any trackers with errors"""
tor_error = ""
tor_error += logger.insert_space(f"Torrent Name: {self.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: {self.tag_error}", 6) + "\n"
self.tor_error_summary += tor_error
self.stats_tagged += 1
attr = {
"function": "tag_tracker_error",
"title": "Tag Tracker Error Torrents",
"body": tor_error,
"torrent_name": self.t_name,
"torrent_category": self.t_cat,
"torrent_tag": self.tag_error,
"torrent_status": msg,
"torrent_tracker": tracker["url"],
"notifiarr_indexer": tracker["notifiarr"],
}
self.config.send_notifications(attr)
if not self.config.dry_run:
torrent.add_tags(tags=self.tag_error)
def del_unregistered(self, msg, tracker, torrent):
"""Deletes unregistered torrents"""
body = []
body += logger.print_line(logger.insert_space(f"Torrent Name: {self.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 = {
"function": "rem_unregistered",
"title": "Removing Unregistered Torrents",
"torrent_name": self.t_name,
"torrent_category": self.t_cat,
"torrent_status": msg,
"torrent_tracker": tracker["url"],
"notifiarr_indexer": tracker["notifiarr"],
}
if self.qbt.torrentinfo[self.t_name]["count"] > 1:
# Checks if any of the original torrents are working
if "" in self.t_msg or 2 in self.t_status:
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)
self.stats_deleted += 1
else:
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)
self.stats_deleted_contents += 1
else:
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)
self.stats_deleted_contents += 1
attr["body"] = "\n".join(body)
self.config.send_notifications(attr)
self.qbt.torrentinfo[self.t_name]["count"] -= 1

View file

@ -14,7 +14,6 @@ class Tags:
def tags(self): def tags(self):
"""Update tags for torrents""" """Update tags for torrents"""
self.stats = 0
ignore_tags = self.config.settings["ignoreTags_OnUpdate"] ignore_tags = self.config.settings["ignoreTags_OnUpdate"]
logger.separator("Updating Tags", space=False, border=False) logger.separator("Updating Tags", space=False, border=False)
for torrent in self.qbt.torrent_list: for torrent in self.qbt.torrent_list:

View file

@ -850,208 +850,6 @@ 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):
"""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"]
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 += 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 = {
"function": "tag_tracker_error",
"title": "Tag Tracker Error Torrents",
"body": tor_error,
"torrent_name": t_name,
"torrent_category": t_cat,
"torrent_tag": tag_error,
"torrent_status": msg,
"torrent_tracker": tracker["url"],
"notifiarr_indexer": tracker["notifiarr"],
}
self.config.send_notifications(attr)
if not self.config.dry_run:
torrent.add_tags(tags=tag_error)
def del_unregistered():
nonlocal del_tor, del_tor_cont, t_name, msg_up, msg, tracker, t_cat, t_msg, t_status, torrent
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 = {
"function": "rem_unregistered",
"title": "Removing Unregistered Torrents",
"torrent_name": t_name,
"torrent_category": t_cat,
"torrent_status": msg,
"torrent_tracker": tracker["url"],
"notifiarr_indexer": tracker["notifiarr"],
}
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
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
)
del_tor += 1
else:
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
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)
self.config.send_notifications(attr)
self.torrentinfo[t_name]["count"] -= 1
if cfg_rem_unregistered or cfg_tag_error:
if cfg_tag_error:
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 = [
"UNREGISTERED",
"TORRENT NOT FOUND",
"TORRENT IS NOT FOUND",
"NOT REGISTERED",
"NOT EXIST",
"UNKNOWN TORRENT",
"TRUMP",
"RETITLED",
"TRUNCATED",
"TORRENT IS NOT AUTHORIZED FOR USE ON THIS TRACKER",
]
ignore_msgs = [
"YOU HAVE REACHED THE CLIENT LIMIT FOR THIS TORRENT",
"MISSING PASSKEY",
"MISSING INFO_HASH",
"PASSKEY IS INVALID",
"INVALID PASSKEY",
"EXPECTED VALUE (LIST, DICT, INT OR STRING) IN BENCODED STRING",
"COULD NOT PARSE BENCODED DATA",
"STREAM TRUNCATED",
]
for torrent in self.torrentvalid:
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.get_tags(torrent.trackers)
num_untag += 1
body = []
body += logger.print_line(
f"Previous Tagged {tag_error} torrent currently has a working tracker.", self.config.loglevel
)
body += logger.print_line(logger.insert_space(f"Torrent Name: {torrent.name}", 3), self.config.loglevel)
body += logger.print_line(logger.insert_space(f"Removed Tag: {tag_error}", 4), self.config.loglevel)
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 = {
"function": "untag_tracker_error",
"title": "Untagging Tracker Error Torrent",
"body": "\n".join(body),
"torrent_name": torrent.name,
"torrent_category": torrent.category,
"torrent_tag": tag_error,
"torrent_tracker": tracker["url"],
"notifiarr_indexer": tracker["notifiarr"],
}
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)
try:
for trk in torrent.trackers:
if trk.url.startswith("http"):
tracker = self.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:
tag_tracker_error()
if cfg_rem_unregistered:
# Tag any error torrents that are not unregistered
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
if (
"tracker.beyond-hd.me" in tracker["url"]
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)
if response["total_results"] == 0:
del_unregistered()
break
tag_tracker_error()
if list_in_text(msg_up, unreg_msgs) and not list_in_text(msg_up, ignore_msgs) and trk.status == 4:
del_unregistered()
break
except NotFound404Error:
continue
except Exception as ex:
logger.stacktrace()
self.config.notify(ex, "Remove Unregistered Torrents", False)
logger.error(f"Remove Unregistered Torrents Error: {ex}")
if cfg_rem_unregistered:
if del_tor >= 1 or del_tor_cont >= 1:
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,
)
else:
logger.print_line("No unregistered torrents found.", self.config.loglevel)
if num_untag >= 1:
logger.print_line(
f"{'Did not delete' if self.config.dry_run else 'Deleted'} {tag_error} tags for {num_untag} "
f".torrent{'s.' if num_untag > 1 else '.'}",
self.config.loglevel,
)
if num_tor_error >= 1:
logger.separator(
f"{num_tor_error} Torrents with tracker errors found",
space=False,
border=False,
loglevel=self.config.loglevel,
)
logger.print_line(tor_error_summary.rstrip(), self.config.loglevel)
return del_tor, del_tor_cont, num_tor_error, num_untag
def cross_seed(self): def cross_seed(self):
"""Move torrents from cross seed directory to correct save directory.""" """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

View file

@ -289,6 +289,7 @@ from modules.util import GracefulKiller # noqa
from modules.util import Failed # noqa from modules.util import Failed # noqa
from modules.core.category import Category # noqa from modules.core.category import Category # noqa
from modules.core.tags import Tags # noqa from modules.core.tags import Tags # noqa
from modules.core.remove_unregistered import RemoveUnregistered # noqa
def my_except_hook(exctype, value, tbi): def my_except_hook(exctype, value, tbi):
@ -392,14 +393,15 @@ def start():
if cfg.commands["tag_update"]: if cfg.commands["tag_update"]:
stats["tagged"] += Tags(qbit_manager).stats stats["tagged"] += Tags(qbit_manager).stats
# Remove Unregistered Torrents # Remove Unregistered Torrents and tag errors
num_deleted, num_deleted_contents, num_tagged, num_untagged = cfg.qbt.rem_unregistered() if cfg.commands["rem_unregistered"] or cfg.commands["tag_tracker_error"]:
stats["rem_unreg"] += num_deleted + num_deleted_contents rem_unreg = RemoveUnregistered(qbit_manager)
stats["deleted"] += num_deleted stats["rem_unreg"] += rem_unreg.stats_deleted + rem_unreg.stats_deleted_contents
stats["deleted_contents"] += num_deleted_contents stats["deleted"] += rem_unreg.stats_deleted
stats["tagged_tracker_error"] += num_tagged stats["deleted_contents"] += rem_unreg.stats_deleted_contents
stats["untagged_tracker_error"] += num_untagged stats["tagged_tracker_error"] += rem_unreg.stats_tagged
stats["tagged"] += num_tagged stats["untagged_tracker_error"] += rem_unreg.stats_untagged
stats["tagged"] += rem_unreg.stats_tagged
# Set Cross Seed # Set Cross Seed
num_added, num_tagged = cfg.qbt.cross_seed() num_added, num_tagged = cfg.qbt.cross_seed()