empty
This commit is contained in:
parent
26ac36a164
commit
fca54f8952
152
README.md
152
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 |
|
@ -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
|
||||
}
|
170
qbit-maid.py
Normal file → Executable file
170
qbit-maid.py
Normal file → Executable file
@ -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()
|
68
qlist.py
68
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)
|
148
qlogging.py
148
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
|
86
qprocess.py
86
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)
|
Loading…
x
Reference in New Issue
Block a user