From fca54f8952a76bac5781265d29f1abefca425c00 Mon Sep 17 00:00:00 2001 From: jblu Date: Fri, 29 Jul 2022 16:02:19 -0500 Subject: [PATCH] empty --- README.md | 152 +++++++++++++++++++-------------------- config.json.example | 32 ++++----- qbit-maid.py | 170 ++++++++++++++++++++++---------------------- qlist.py | 68 +++++++++--------- qlogging.py | 148 +++++++++++++++++++------------------- qprocess.py | 86 +++++++++++----------- 6 files changed, 328 insertions(+), 328 deletions(-) mode change 100644 => 100755 qbit-maid.py diff --git a/README.md b/README.md index 5c50cb3..d39a876 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,77 @@ -# qbit-maid - -Warning: This application removes torrents that aren't downloading and that aren't from iptorrents. Age in the config.json only controls the age for torrents from iptorrents. - -The objective is to remove torrents based on the following criteria: -- tracker domain name -- age -- ratio -- state - -```mermaid -graph TD; - qbit-maid.py-->qlogging.py; - qbit-maid.py-->qlist.py; - qbit-maid.py-->qprocess.py; - qlogging.py-->qbit-maid.py; - qlist.py-->qbit-maid.py; - qprocess.py-->qbit-maid.py; -``` - -| File | Purpose | -| --- | --- | -| qbit-maid.py | Client to the qbit api and calls functions from the other files | -| qlist.py | Builds out torrent lists | -| qlogging.py | Logging and push notification communication | -| qprocess.py | Submits qualifying torrents for deletion | - -You will need a config.json in the root directory. - -It should look something like this: -Config.json -``` -{ - "host": "192.168.1.1", - "port": 8080, - "username": "admin", - "password": "admin", - "loglevel": "INFO", - "logpath": "./qc.log", - "protected_tag": "ipt", - "non_protected_tag": "public", - "age": 2419200, - "minimum_age": 432000, - "use_pushover": false, - "use_log": true, - "po_key": "", - "po_token": "", - "delete_torrents": false -} -``` - -You will need a category-whitelist.json in the root directory. This will ignore any of the categories found in the values of the entries. -``` -{ - "example": "general", - "example2": "sonarr" -} -``` - - -| Key | Value | -| --- | --- | -| host | string, ip or hostname of qbittorrent server | -| port | number, port of admin gui(used for api aswell) | -| username | admin account for qbittorrent | -| password | password for admin account | -| loglevel | is what log messages are written to the log file. INFO or DEBUG are valid entries(case sensitive) | -| protected_tag | used to mark torrents to handle with care | -| non_protected_tag | we don't care about these torrents | -| logpath | will write a log in root directory if left as is other wise specify other path using forward slashes | -| age | number, seconds for how long we keep torrents from IPTORRENTS | -| minimum_age | age in seconds torrents should reached before they are removed | -| use_pushover | true or false to enable or disable pushover notification summary | -| use_log | true or false to enable or disable writing to alog file | -| po_key | pushover key | -| po_token | pushover api token | +# qbit-maid + +Warning: This application removes torrents that aren't downloading and that aren't from iptorrents. Age in the config.json only controls the age for torrents from iptorrents. + +The objective is to remove torrents based on the following criteria: +- tracker domain name +- age +- ratio +- state + +```mermaid +graph TD; + qbit-maid.py-->qlogging.py; + qbit-maid.py-->qlist.py; + qbit-maid.py-->qprocess.py; + qlogging.py-->qbit-maid.py; + qlist.py-->qbit-maid.py; + qprocess.py-->qbit-maid.py; +``` + +| File | Purpose | +| --- | --- | +| qbit-maid.py | Client to the qbit api and calls functions from the other files | +| qlist.py | Builds out torrent lists | +| qlogging.py | Logging and push notification communication | +| qprocess.py | Submits qualifying torrents for deletion | + +You will need a config.json in the root directory. + +It should look something like this: +Config.json +``` +{ + "host": "192.168.1.1", + "port": 8080, + "username": "admin", + "password": "admin", + "loglevel": "INFO", + "logpath": "./qc.log", + "protected_tag": "ipt", + "non_protected_tag": "public", + "age": 2419200, + "minimum_age": 432000, + "use_pushover": false, + "use_log": true, + "po_key": "", + "po_token": "", + "delete_torrents": false +} +``` + +You will need a category-whitelist.json in the root directory. This will ignore any of the categories found in the values of the entries. +``` +{ + "example": "general", + "example2": "sonarr" +} +``` + + +| Key | Value | +| --- | --- | +| host | string, ip or hostname of qbittorrent server | +| port | number, port of admin gui(used for api aswell) | +| username | admin account for qbittorrent | +| password | password for admin account | +| loglevel | is what log messages are written to the log file. INFO or DEBUG are valid entries(case sensitive) | +| protected_tag | used to mark torrents to handle with care | +| non_protected_tag | we don't care about these torrents | +| logpath | will write a log in root directory if left as is other wise specify other path using forward slashes | +| age | number, seconds for how long we keep torrents from IPTORRENTS | +| minimum_age | age in seconds torrents should reached before they are removed | +| use_pushover | true or false to enable or disable pushover notification summary | +| use_log | true or false to enable or disable writing to alog file | +| po_key | pushover key | +| po_token | pushover api token | | delete_torrents | true or false to enable or disable deletion. Useful for dry-runs | \ No newline at end of file diff --git a/config.json.example b/config.json.example index 6a9fb9b..6dba164 100644 --- a/config.json.example +++ b/config.json.example @@ -1,17 +1,17 @@ -{ - "host": "192.168.1.1", - "port": 8080, - "username": "admin", - "password": "admin", - "loglevel": "INFO", - "logpath": "./qc.log", - "protected_tag": "ipt", - "non_protected_tag": "public", - "age": 2419200, - "minimum_age": 432000, - "use_pushover": true, - "use_log": true, - "po_key": "", - "po_token": "", - "delete_torrents": false +{ + "host": "192.168.1.1", + "port": 8080, + "username": "admin", + "password": "admin", + "loglevel": "INFO", + "logpath": "./qc.log", + "protected_tag": "ipt", + "non_protected_tag": "public", + "age": 2419200, + "minimum_age": 432000, + "use_pushover": true, + "use_log": true, + "po_key": "", + "po_token": "", + "delete_torrents": false } \ No newline at end of file diff --git a/qbit-maid.py b/qbit-maid.py old mode 100644 new mode 100755 index b2ba598..6341ea4 --- a/qbit-maid.py +++ b/qbit-maid.py @@ -1,86 +1,86 @@ -#The first file shall contain an client to the qbit api and the processing of the torrents. -import qbittorrentapi -import pushover -from json import load -from qlist import * -from qlogging import * -from qprocess import * -import time -import logging -from collections import Counter - -class Qbt: - def __init__(self): - """Main object, should be calling functions from qlist.py, qlogging.py and qprocess.py""" - # Open the config. Needs a json file with the data in config.json.example - c = open('./config.json') - self.config = load(c) - w = open('./category-whitelist.json') - self.cat_whitelist = load(w) - # Create the api object - self.qbt_client = qbittorrentapi.Client( - host=self.config["host"], - port=self.config["port"], - username=self.config["username"], - password=self.config["password"], - ) - # Create the logging and pushover objects - self.tl = logging - self.po = pushover - self.ct = Counter - # Variables torlog uses from config.json - self.use_pushover = self.config["use_pushover"] - self.use_log = self.config["use_log"] - self.po_key = self.config["po_key"] - self.po_token = self.config["po_token"] - self.logpath = self.config["logpath"] - self.loglevel = self.config["loglevel"] - self.tracker_protected_tag = self.config["protected_tag"] - self.tracker_non_protected_tag = self.config["non_protected_tag"] - self.minimum_age = self.config["minimum_age"] - self.age = self.config["age"] - # Calling log and notify functions - torlog(self) - tornotify(self) - self.t = time - # Pulling domain names to treat carefully - f = open('./tracker-whitelist.json') - self.tracker_whitelist = load(f) - self.tracker_list = [] - self.up_tor_counter = 0 - self.preme_tor_counter = 0 - self.ignored_counter = 0 - self.torrent_hash_delete_list = [] - if self.use_log: - self.tl.debug(self.tracker_whitelist) - #logging in - try: - self.tl.info('Connecting to host.') - self.qbt_client.auth_log_in() - self.tl.info('Connected.') - except qbittorrentapi.APIError as e: - self.tl.exception(e) - self.poc.send_message(e, title="qbit-maid API ERROR") - self.torrentlist = {} - # Pulling all torrent data - self.torrentlist = self.qbt_client.torrents_info() - #Main process block - if self.use_log: - listqbitapiinfo(self) - listfirsttor(self) - buildtorlist(self) - processcounts(self) - #tordeletetags(self) - if self.use_log: - torrentcount(self) - torprocessor(self) - if self.use_log: - printprocessor(self) - if self.use_pushover: - tornotifysummary(self) - if self.config["delete_torrents"]: - tordelete(self) - -# Run -if __name__== "__main__": +#The first file shall contain an client to the qbit api and the processing of the torrents. +import qbittorrentapi +import pushover +from json import load +from qlist import * +from qlogging import * +from qprocess import * +import time +import logging +from collections import Counter + +class Qbt: + def __init__(self): + """Main object, should be calling functions from qlist.py, qlogging.py and qprocess.py""" + # Open the config. Needs a json file with the data in config.json.example + c = open('./config.json') + self.config = load(c) + w = open('./category-whitelist.json') + self.cat_whitelist = load(w) + # Create the api object + self.qbt_client = qbittorrentapi.Client( + host=self.config["host"], + port=self.config["port"], + username=self.config["username"], + password=self.config["password"], + ) + # Create the logging and pushover objects + self.tl = logging + self.po = pushover + self.ct = Counter + # Variables torlog uses from config.json + self.use_pushover = self.config["use_pushover"] + self.use_log = self.config["use_log"] + self.po_key = self.config["po_key"] + self.po_token = self.config["po_token"] + self.logpath = self.config["logpath"] + self.loglevel = self.config["loglevel"] + self.tracker_protected_tag = self.config["protected_tag"] + self.tracker_non_protected_tag = self.config["non_protected_tag"] + self.minimum_age = self.config["minimum_age"] + self.age = self.config["age"] + # Calling log and notify functions + torlog(self) + tornotify(self) + self.t = time + # Pulling domain names to treat carefully + f = open('./tracker-whitelist.json') + self.tracker_whitelist = load(f) + self.tracker_list = [] + self.up_tor_counter = 0 + self.preme_tor_counter = 0 + self.ignored_counter = 0 + self.torrent_hash_delete_list = [] + if self.use_log: + self.tl.debug(self.tracker_whitelist) + #logging in + try: + self.tl.info('Connecting to host.') + self.qbt_client.auth_log_in() + self.tl.info('Connected.') + except qbittorrentapi.APIError as e: + self.tl.exception(e) + self.poc.send_message(e, title="qbit-maid API ERROR") + self.torrentlist = {} + # Pulling all torrent data + self.torrentlist = self.qbt_client.torrents_info() + #Main process block + if self.use_log: + listqbitapiinfo(self) + listfirsttor(self) + buildtorlist(self) + processcounts(self) + #tordeletetags(self) + if self.use_log: + torrentcount(self) + torprocessor(self) + if self.use_log: + printprocessor(self) + if self.use_pushover: + tornotifysummary(self) + if self.config["delete_torrents"]: + tordelete(self) + +# Run +if __name__== "__main__": Qbt() \ No newline at end of file diff --git a/qlist.py b/qlist.py index 7b3f3f5..63b5577 100644 --- a/qlist.py +++ b/qlist.py @@ -1,35 +1,35 @@ -def buildtorlist(self): - """Builds multiple lists of torrents to be sorted. Also adds tags to the torents. - There are more effecient ways of doing things but I did this rather quickly. - V2 will certainly be more performant. The reason two lists were used was so that torrents - that are in public trackers woudln't be around as long as torrents from a private tracker. - """ - self.total_torrents = len(self.torrentlist) - while self.torrentlist: - torrent = self.torrentlist.pop() - if self.use_log: - self.tl.debug(f'["{torrent["name"][0:20]}..."] {torrent["infohash_v1"]}') - if torrent['added_on'] + self.minimum_age <= self.t.time(): - self.preme_tor_counter += 1 - continue - if torrent['category'] in self.cat_whitelist.values(): - self.tl.info(f'Ignored torrent:["{torrent["name"][0:20]}..."]') - self.ignored_counter += 1 - continue - if torrent['tracker'] == '': - if self.use_log: - self.tl.warning(f'Torrent doesn\'t have a tracker ["{torrent["name"][0:20]}..."] [{torrent["tracker"]}]hash: {torrent["hash"]}') - self.ignored_counter += 1 - continue - if torrent['tracker'].split('/')[2] in self.tracker_whitelist.values(): - if self.use_log: - self.tl.debug(f'Protected torrent: {torrent["tracker"]}hash: {torrent["hash"]}') - if torrent['tags'] == '': - self.qbt_client.torrents_add_tags(self.tracker_protected_tag,torrent['hash']) - self.tracker_list.append(torrent) - if torrent['tracker'].split('/')[2] not in self.tracker_whitelist.values(): - if self.use_log: - self.tl.debug(f'Non-protected torrent: {torrent["tracker"]}hash: {torrent["hash"]}') - if torrent['tags'] == '': - self.qbt_client.torrents_add_tags(self.tracker_non_protected_tag,torrent['hash']) +def buildtorlist(self): + """Builds multiple lists of torrents to be sorted. Also adds tags to the torents. + There are more effecient ways of doing things but I did this rather quickly. + V2 will certainly be more performant. The reason two lists were used was so that torrents + that are in public trackers woudln't be around as long as torrents from a private tracker. + """ + self.total_torrents = len(self.torrentlist) + while self.torrentlist: + torrent = self.torrentlist.pop() + if self.use_log: + self.tl.debug(f'["{torrent["name"][0:20]}..."] {torrent["infohash_v1"]}') + if torrent['added_on'] + self.minimum_age <= self.t.time(): + self.preme_tor_counter += 1 + continue + if torrent['category'] in self.cat_whitelist.values(): + self.tl.info(f'Ignored torrent:["{torrent["name"][0:20]}..."]') + self.ignored_counter += 1 + continue + if torrent['tracker'] == '': + if self.use_log: + self.tl.warning(f'Torrent doesn\'t have a tracker ["{torrent["name"][0:20]}..."] [{torrent["tracker"]}]hash: {torrent["hash"]}') + self.ignored_counter += 1 + continue + if torrent['tracker'].split('/')[2] in self.tracker_whitelist.values(): + if self.use_log: + self.tl.debug(f'Protected torrent: {torrent["tracker"]}hash: {torrent["hash"]}') + if torrent['tags'] == '': + self.qbt_client.torrents_add_tags(self.tracker_protected_tag,torrent['hash']) + self.tracker_list.append(torrent) + if torrent['tracker'].split('/')[2] not in self.tracker_whitelist.values(): + if self.use_log: + self.tl.debug(f'Non-protected torrent: {torrent["tracker"]}hash: {torrent["hash"]}') + if torrent['tags'] == '': + self.qbt_client.torrents_add_tags(self.tracker_non_protected_tag,torrent['hash']) self.tracker_list.append(torrent) \ No newline at end of file diff --git a/qlogging.py b/qlogging.py index 4a1f6dd..5c6627d 100644 --- a/qlogging.py +++ b/qlogging.py @@ -1,75 +1,75 @@ -def torlog(self): - """Setting up the log file, if self.use_log is set to true and self.loglevel is DEBUG OR INFO""" - if self.use_log: - if self.loglevel == 'DEBUG': - self.tl.basicConfig(filename=self.logpath, format='%(asctime)s:%(levelname)s:%(message)s', encoding='utf-8', datefmt='%m/%d/%Y %I:%M:%S %p',level=self.tl.DEBUG) - elif self.loglevel == 'INFO': - self.tl.basicConfig(filename=self.logpath, format='%(asctime)s:%(levelname)s:%(message)s', encoding='utf-8', datefmt='%m/%d/%Y %I:%M:%S %p',level=self.tl.INFO) - -def tornotify(self): - """Seting up to use pushover, if self.use_pushover is set to true and - if valid self.po_key and self.po_token is provided in the config file""" - if self.use_pushover: - self.poc = self.po.Client(self.po_key, api_token=self.po_token) - -def tornotifytest(self): - """Used to make sure tornotify is working and messages are getting to the client""" - self.poc.send_message("Test Message", title="qbit-maid") - -def processcounts(self): - self.c = self.ct() - for item in self.tracker_list: - self.c[item["tags"]] += 1 - -def printprocessor(self): - """Print summary of torrents""" - self.tl.info(f'Total: {self.total_torrents}') - self.tl.info(f'Premature: {self.preme_tor_counter}') - self.tl.info(f'Ignored: {self.ignored_counter}') - self.tl.info(f'Protected: {self.c[self.tracker_protected_tag]}') - self.tl.info(f'Non-protected: {self.c[self.tracker_non_protected_tag]}') - self.tl.info(f'Orphaned: {self.up_tor_counter}') - self.tl.info(f'Marked for deletion: {len(self.torrent_hash_delete_list)}') - -def tornotifysummary(self): - """Main notification method when the app is used in an automated fashion""" - self.poc.send_message(f" Total: {self.total_torrents}\n\ - Premature: {self.preme_tor_counter}\n\ - Ignored: {self.ignored_counter}\n\ - Protected: {self.c[self.tracker_protected_tag]}\n\ - Non-protected: {self.c[self.tracker_non_protected_tag]}\n\ - Orphaned: {self.up_tor_counter}\n\ - Marked for deletion: {len(self.torrent_hash_delete_list)}", title="--- qbit-maid summary ---") - -def getunixtimestamp(self): - """Used for debuging and development related to unixtimestamps, not used in main script but useful""" - self.uts = self.t.time() - self.tl.info(self.uts) - -def writetor(self, filepath='./torrentinfo.txt'): - """Write all torrent data to a file. - Useful for development of new features. - """ - with open(filepath, 'w') as fp: - fp.write(str(self.torrentlist)) - -def listfirsttor(self, index=0): - """Only lists the first torrent""" - self.tl.debug('First torrent in the list:') - torrent = self.torrentlist[index] - for k,v in torrent.items(): - self.tl.debug(f'{k}: {v}') - self.tl.debug('\n') - -def listqbitapiinfo(self): - """Writes torrent info to log file""" - self.tl.debug(f'qBittorrent: {self.qbt_client.app.version}') - self.tl.debug(f'qBittorrent Web API: {self.qbt_client.app.web_api_version}') - -def torrentcount(self): - """write torrent counts to log file""" - self.tl.debug(f'torrents that are protected {self.tracker_list.count("ipt")}') - self.tl.debug(f'torrents that aren\'t protected {self.tracker_list.count("public")}') - -def torlisttags(self): +def torlog(self): + """Setting up the log file, if self.use_log is set to true and self.loglevel is DEBUG OR INFO""" + if self.use_log: + if self.loglevel == 'DEBUG': + self.tl.basicConfig(filename=self.logpath, format='%(asctime)s:%(levelname)s:%(message)s', encoding='utf-8', datefmt='%m/%d/%Y %I:%M:%S %p',level=self.tl.DEBUG) + elif self.loglevel == 'INFO': + self.tl.basicConfig(filename=self.logpath, format='%(asctime)s:%(levelname)s:%(message)s', encoding='utf-8', datefmt='%m/%d/%Y %I:%M:%S %p',level=self.tl.INFO) + +def tornotify(self): + """Seting up to use pushover, if self.use_pushover is set to true and + if valid self.po_key and self.po_token is provided in the config file""" + if self.use_pushover: + self.poc = self.po.Client(self.po_key, api_token=self.po_token) + +def tornotifytest(self): + """Used to make sure tornotify is working and messages are getting to the client""" + self.poc.send_message("Test Message", title="qbit-maid") + +def processcounts(self): + self.c = self.ct() + for item in self.tracker_list: + self.c[item["tags"]] += 1 + +def printprocessor(self): + """Print summary of torrents""" + self.tl.info(f'Total: {self.total_torrents}') + self.tl.info(f'Premature: {self.preme_tor_counter}') + self.tl.info(f'Ignored: {self.ignored_counter}') + self.tl.info(f'Protected: {self.c[self.tracker_protected_tag]}') + self.tl.info(f'Non-protected: {self.c[self.tracker_non_protected_tag]}') + self.tl.info(f'Orphaned: {self.up_tor_counter}') + self.tl.info(f'Marked for deletion: {len(self.torrent_hash_delete_list)}') + +def tornotifysummary(self): + """Main notification method when the app is used in an automated fashion""" + self.poc.send_message(f" Total: {self.total_torrents}\n\ + Premature: {self.preme_tor_counter}\n\ + Ignored: {self.ignored_counter}\n\ + Protected: {self.c[self.tracker_protected_tag]}\n\ + Non-protected: {self.c[self.tracker_non_protected_tag]}\n\ + Orphaned: {self.up_tor_counter}\n\ + Marked for deletion: {len(self.torrent_hash_delete_list)}", title="--- qbit-maid summary ---") + +def getunixtimestamp(self): + """Used for debuging and development related to unixtimestamps, not used in main script but useful""" + self.uts = self.t.time() + self.tl.info(self.uts) + +def writetor(self, filepath='./torrentinfo.txt'): + """Write all torrent data to a file. + Useful for development of new features. + """ + with open(filepath, 'w') as fp: + fp.write(str(self.torrentlist)) + +def listfirsttor(self, index=0): + """Only lists the first torrent""" + self.tl.debug('First torrent in the list:') + torrent = self.torrentlist[index] + for k,v in torrent.items(): + self.tl.debug(f'{k}: {v}') + self.tl.debug('\n') + +def listqbitapiinfo(self): + """Writes torrent info to log file""" + self.tl.debug(f'qBittorrent: {self.qbt_client.app.version}') + self.tl.debug(f'qBittorrent Web API: {self.qbt_client.app.web_api_version}') + +def torrentcount(self): + """write torrent counts to log file""" + self.tl.debug(f'torrents that are protected {self.tracker_list.count("ipt")}') + self.tl.debug(f'torrents that aren\'t protected {self.tracker_list.count("public")}') + +def torlisttags(self): pass \ No newline at end of file diff --git a/qprocess.py b/qprocess.py index b58b5d9..bf6c2f4 100644 --- a/qprocess.py +++ b/qprocess.py @@ -1,44 +1,44 @@ -def torprocessor(self): - """Main logic to sort through both self.tracker_nonprotected_list and self.tracker_protected_list - If torrent meets criteria for deletion, its infohash_v1 will be appended to self.torrent_hash_delete_list - """ - for canidate in self.tracker_list: - if canidate['state'] == 'downloading': - if self.use_log: - self.tl.info(f'["{canidate["name"][0:20]}..."] is still downloading and will be skipped.') - continue - elif canidate['ratio'] < float(1.05) and self.tracker_protected_tag in canidate["tags"]: - if self.use_log: - self.tl.debug(f'["{canidate["name"][0:20]}..."] is below a 1.05 ratio({canidate["ratio"]})') - if canidate['added_on'] + self.age <= self.t.time(): - if self.use_log: - self.tl.debug(f'["{canidate["name"][0:20]}..."] Seconds old: {self.t.time() - self.age - canidate["added_on"]}') - self.torrent_hash_delete_list.append(canidate['infohash_v1']) - if self.use_log: - self.tl.info(f'Submitted ["{canidate["name"][0:20]}..."] for deletion from the protected list.') - elif canidate['ratio'] >= float(1.05) and self.tracker_protected_tag in canidate["tags"]: - if self.use_log: - self.tl.debug(f'["{canidate["name"][0:20]}..."] is above a 1.05 ratio({canidate["ratio"]}).') - self.torrent_hash_delete_list.append(canidate['infohash_v1']) - if self.use_log: - self.tl.info(f'Submitted ["{canidate["name"][0:20]}..."] for deletion from the protected list.') - elif self.tracker_non_protected_tag in canidate["tags"]: - self.torrent_hash_delete_list.append(canidate['infohash_v1']) - if self.use_log: - self.tl.info(f'Submitted ["{canidate["name"][0:20]}..."] for deletion.') - else: - self.tl.info(f'["{canidate["name"][0:20]}..."] is orphaned.') - self.up_tor_counter += 1 - continue - -def tordeletetags(self): - tag_list = [self.tracker_protected_tag, self.tracker_non_protected_tag] - self.qbt_client.torrents_delete_tags(tag_list) - -def tordelete(self): - """Remove torrents, will also delete files, this keeps the filesystem clean. - Only pass self.torrent_hash_delete_list if you would like to keep the files.""" - if self.use_log: - self.tl.debug('Hash list submitted for deletion:') - self.tl.debug(self.torrent_hash_delete_list) +def torprocessor(self): + """Main logic to sort through both self.tracker_nonprotected_list and self.tracker_protected_list + If torrent meets criteria for deletion, its infohash_v1 will be appended to self.torrent_hash_delete_list + """ + for canidate in self.tracker_list: + if canidate['state'] == 'downloading': + if self.use_log: + self.tl.info(f'["{canidate["name"][0:20]}..."] is still downloading and will be skipped.') + continue + elif canidate['ratio'] < float(1.05) and self.tracker_protected_tag in canidate["tags"]: + if self.use_log: + self.tl.debug(f'["{canidate["name"][0:20]}..."] is below a 1.05 ratio({canidate["ratio"]})') + if canidate['added_on'] + self.age <= self.t.time(): + if self.use_log: + self.tl.debug(f'["{canidate["name"][0:20]}..."] Seconds old: {self.t.time() - self.age - canidate["added_on"]}') + self.torrent_hash_delete_list.append(canidate['infohash_v1']) + if self.use_log: + self.tl.info(f'Submitted ["{canidate["name"][0:20]}..."] for deletion from the protected list.') + elif canidate['ratio'] >= float(1.05) and self.tracker_protected_tag in canidate["tags"]: + if self.use_log: + self.tl.debug(f'["{canidate["name"][0:20]}..."] is above a 1.05 ratio({canidate["ratio"]}).') + self.torrent_hash_delete_list.append(canidate['infohash_v1']) + if self.use_log: + self.tl.info(f'Submitted ["{canidate["name"][0:20]}..."] for deletion from the protected list.') + elif self.tracker_non_protected_tag in canidate["tags"]: + self.torrent_hash_delete_list.append(canidate['infohash_v1']) + if self.use_log: + self.tl.info(f'Submitted ["{canidate["name"][0:20]}..."] for deletion.') + else: + self.tl.info(f'["{canidate["name"][0:20]}..."] is orphaned.') + self.up_tor_counter += 1 + continue + +def tordeletetags(self): + tag_list = [self.tracker_protected_tag, self.tracker_non_protected_tag] + self.qbt_client.torrents_delete_tags(tag_list) + +def tordelete(self): + """Remove torrents, will also delete files, this keeps the filesystem clean. + Only pass self.torrent_hash_delete_list if you would like to keep the files.""" + if self.use_log: + self.tl.debug('Hash list submitted for deletion:') + self.tl.debug(self.torrent_hash_delete_list) self.qbt_client.torrents_delete(True, self.torrent_hash_delete_list) \ No newline at end of file