You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
5.2 KiB
Python

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))