forked from Hundter/qBittorrent-Ratio-Manager
-
Notifications
You must be signed in to change notification settings - Fork 0
/
qbit_ratio_manager.py
executable file
·144 lines (113 loc) · 5.96 KB
/
qbit_ratio_manager.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import argparse
import os
import json
import logging
from jsonschema import validate
from jsonschema import ValidationError
from resources.CategoryProfile import CategoryProfile
from resources.QBitController import QBitController
print("Checking settings...")
qman_schema = {
"type" : "object",
"properties" : {
"category" : {"type" : "string"},
"public" : {
"type" : "object",
"properties" : {
"min_seed_ratio": {"type" : "number"},
"max_seed_ratio": {"type" : "number"},
"min_seed_time": {"type" : "integer"},
"max_seed_time": {"type" : "integer"},
"required_seeders" : {"type" : "integer"}
},
"required": ["min_seed_ratio", "max_seed_ratio", "min_seed_time", "max_seed_time"]
},
"private" : {
"type" : "object",
"properties" : {
"min_seed_ratio": {"type" : "number"},
"max_seed_ratio": {"type" : "number"},
"min_seed_time": {"type" : "integer"},
"max_seed_time": {"type" : "integer"},
"required_seeders" : {"type" : "integer"}
},
"required": ["min_seed_ratio", "max_seed_ratio", "min_seed_time", "max_seed_time"]
},
"tracker" : {"type" : "string"},
"delete_files" : {"type" : "boolean"},
"custom_delete_files_path" : {"type" : "string"}
},
"required": ["category", "public", "private", "delete_files"]
}
def load_category_files_into_classes(args):
categoryProfiles = {}
for file in os.listdir(args.config_folder):
if not file.endswith(".qman"):
continue
with open(args.config_folder + "/" + file) as json_file:
settings = json.load(json_file)
try:
validate(instance=settings, schema=qman_schema)
except ValidationError as e:
print("Failed to load '" + file + "'...\n*** " + e.message + " ***\n.qman example files can be found here: aaa")
sys.exit(1)
# Set default values
if 'tracker' not in settings: settings['tracker'] = ""
if 'custom_delete_files_path' not in settings: settings['custom_delete_files_path'] = ""
if 'required_seeders' not in settings['public']: settings['public']['required_seeders'] = -1
if 'required_seeders' not in settings['private']: settings['private']['required_seeders'] = -1
# Verify path availability
if settings['custom_delete_files_path']:
if not os.path.isdir(settings['custom_delete_files_path']):
print("Error while parsing '" + file + "'. custom_delete_files_path: specified path is not a valid directory")
sys.exit(1)
settings['delete_files'] = False # Override delete_files if custom_delete_files_path is set
categoryProfile = CategoryProfile(settings['category'], settings['tracker'], settings['delete_files'], settings['custom_delete_files_path'], settings['public'], settings['private'], file)
if settings['category'] not in categoryProfiles:
categoryProfiles[settings['category']] = []
categoryProfiles[settings['category']].append(categoryProfile)
return categoryProfiles
def construct_argument_parser():
parser = argparse.ArgumentParser(description='https://github.com/Hundter/qBittorrent-Ratio-Manager Reads .qman files for JSON settings on when and how to delete torrents from a qBittorrent client', usage="%(prog)s [options]", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--url', default="http://127.0.0.1:8080/api/v2/", dest="qbit_url", metavar='',
help='Set the qbit API url and path, most likely ends in /api/v2/')
parser.add_argument('--username', default="", dest="qbit_username", metavar='',
help='Set the qbit username')
parser.add_argument('--password', default="", dest="qbit_password", metavar='',
help='Set the qbit password')
parser.add_argument('--config_folder', default=os.path.dirname(os.path.realpath(__file__)) + "/configs/", metavar='',
help='Set the folder for category config files.')
parser.add_argument('--verbose', '-v', default=0, dest="verbose", help='Set the verbosity level. 0 = only warnings, 1 = info, 2 = debug.', action='count')
return parser.parse_args()
if __name__ == "__main__":
args = construct_argument_parser()
if not args.qbit_url.startswith("http://") and not args.qbit_url.startswith("https://"):
args.qbit_url = "http://" + args.qbit_url
levels = [logging.WARNING, logging.INFO, logging.DEBUG]
level = levels[min(2, args.verbose)]
logging.basicConfig(level=level)
print("Connecting...")
QBitController.connect_to_qbit(args.qbit_url, args.qbit_username, args.qbit_password)
categoryProfiles = load_category_files_into_classes(args)
torrents = QBitController.get_torrents()
print("Checking torrents...")
delete_counter = 0
torrents_checked = set()
for torrent in torrents:
if torrent["category"] in categoryProfiles.keys():
for matchingCategoryProfile in categoryProfiles[torrent["category"]]:
matchingCategoryProfile.process_torrent(torrent)
torrents_checked.add(torrent['hash'])
elif "*" in categoryProfiles.keys():
for matchingCategoryProfile in categoryProfiles["*"]:
matchingCategoryProfile.process_torrent(torrent)
torrents_checked.add(torrent['hash'])
for categoryProfileArray in categoryProfiles.values():
for categoryProfile in categoryProfileArray:
categoryProfile.delete_torrents_to_be_deleted()
delete_counter += len(categoryProfile.torrents_to_delete)
print("Tasks complete.")
print(str(len(torrents_checked)) + " torrents checked, " + str(delete_counter) + " torrents deleted")