-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.py
180 lines (142 loc) · 5.17 KB
/
main.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import re, oursql, requests, sys, json, shlex, argparse, os, random
from sources.nzbindex import NzbindexSpider
from sources.binsearch import BinsearchSpider
from shared import NotFoundException
parser = argparse.ArgumentParser(description="Automatically download NZBs for releases")
parser.add_argument("--config", dest="config", action="store", help="Use a configuration file to match against the database as source")
parser.add_argument("--list", dest="list", action="store", help="Use a newline-delimited list of releases as source")
parser.add_argument("--target", dest="target", action="store", help="Where to save the NZBs (only needed in list mode)")
parser.add_argument("--iplist", dest="iplist", action="store", help="Bind every request to a random IP from a newline-delimited list")
parser.add_argument("--limit", dest="limit", action="store", help="How many records to select in configuration file mode, at most (default: 250)", default=250)
parser.add_argument("--skip", dest="skip", action="store", help="Optionally, a path to a newline-delimited list of release names to always skip")
args = parser.parse_args()
autoskip_file = "autoskip.lst"
def mark_autoskip(release_name):
f = open(autoskip_file, "a")
f.write("%s\n" % release_name)
f.close()
if args.config is not None:
mode = "config"
elif args.list is not None:
mode = "list"
else:
sys.stderr.write("You must specify either a configuration file or a release list.\n")
exit(1)
if args.iplist is not None:
iplist_file = open(args.iplist, "r")
iplist = iplist_file.read().splitlines()
else:
iplist = [""]
if args.skip is not None:
skip_file = open(args.skip, "r")
skiplist = skip_file.read().splitlines()
else:
skiplist = [""]
try:
f = open(autoskip_file, "r")
autoskiplist = f.read().splitlines()
f.close()
except IOError, e:
autoskiplist = []
if mode == "config":
try:
conf = json.load(open("config.json", "r"))
except IOError, e:
sys.stderr.write("You must have a valid config.json.\n")
exit(1)
if not re.match("^[a-zA-Z0-9_-]+$", conf['db']['table']):
sys.stderr.write("Table name must be a-z, A-Z, 0-9, _, -\n")
exit(1)
try:
searchconf_file = open(args.config, "r")
except IOError, e:
sys.stderr.write("The specified configuration file doesn't exist.\n")
exit(1)
queries = searchconf_file.read().splitlines()
searchconf_file.close()
db = oursql.connect(host=conf['db']['host'], user=conf['db']['user'], passwd=conf['db']['pass'], db=conf['db']['db'], autoreconnect=True)
c = db.cursor()
releases = []
for query in queries:
title, section, target = shlex.split(query)
fields = []
values = []
if title != "-":
fields.append("`release` LIKE ?")
values.append("%" + title + "%")
if section != "-":
fields.append("`section` LIKE ?")
values.append("%" + section + "%")
values.append(args.limit)
if len(fields) == 0:
db_query = "SELECT `release` FROM %s WHERE `time` < (UNIX_TIMESTAMP(NOW()) - 86400) ORDER BY `time` DESC LIMIT ?" % conf['db']['table']
else:
db_query = "SELECT `release` FROM %s WHERE %s AND `time` < (UNIX_TIMESTAMP(NOW()) - 86400) ORDER BY `time` DESC LIMIT ?" % (conf['db']['table'], " AND ".join(fields))
c.execute(db_query, values)
for row in c:
releases.append((row[0], target))
elif mode == "list":
if args.target is None:
sys.stderr.write("You did not specify a target directory with --target.\n")
exit(1)
try:
list_file = open(args.list, "r")
except IOError, e:
sys.stderr.write("The specified list file doesn't exist.\n")
exit(1)
releases = [(release, args.target) for release in list_file.read().splitlines()]
list_file.close()
sys.stdout.write("Found %d releases.\n" % len(releases))
downloaded = 0
skipped = 0
errors = 0
notfound = 0
notfound_list = []
for release in releases:
release_name, target_dir = release
target_path = os.path.join(target_dir, "%s.nzb" % release_name)
if os.path.exists(target_path):
# This NZB was already downloaded.
skipped += 1
continue
if release_name in notfound_list:
# This NZB couldn't be found before
notfound += 1
continue
if release_name in skiplist:
# This release should be skipped
skipped += 1
continue
if release_name in autoskiplist:
# This release should be skipped because it was downloaded previously
skipped += 1
continue
try:
os.makedirs(target_dir)
except OSError, e:
# Target directory already exists
pass
try:
spider = NzbindexSpider(random.choice(iplist))
results = spider.find(release_name)
except NotFoundException, e:
try:
spider = BinsearchSpider(random.choice(iplist))
results = spider.find(release_name)
except NotFoundException, e:
sys.stderr.write("Could not find release %s\n" % release_name)
notfound_list.append(release_name)
notfound += 1
continue
# Process result
result = results[0]
try:
result.download(target_path)
except Exception, e:
errors += 1
sys.stderr.write("Downloading NZB for %s failed: %s\n" % (release_name, repr(e)))
continue
sys.stdout.write("Downloaded NZB for %s.\n" % release_name)
downloaded += 1
mark_autoskip(release_name)
sys.stdout.write("Finished. %d downloaded, %d skipped, %d errors and %d not found.\n" % (downloaded, skipped, errors, notfound))