diff --git a/main.py b/main.py index 561fdb4..49e5f3d 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -import re, oursql, requests, sys, json, shlex, argparse, os +import re, oursql, requests, sys, json, shlex, argparse, os, random from sources.nzbindex import NzbindexSpider from sources.binsearch import BinsearchSpider @@ -8,7 +8,7 @@ parser = argparse.ArgumentParser(description="Automatically download NZBs for re 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="list", action="store", help="Bind every request to a random IP from a newline-delimited list") +parser.add_argument("--iplist", dest="iplist", action="store", help="Bind every request to a random IP from a newline-delimited list") args = parser.parse_args() if args.config is not None: @@ -18,6 +18,12 @@ elif args.list is not None: 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 mode == "config": try: @@ -111,11 +117,11 @@ for release in releases: pass try: - spider = NzbindexSpider() + spider = NzbindexSpider(random.choice(iplist)) results = spider.find(release_name) except NotFoundException, e: try: - spider = BinsearchSpider() + spider = BinsearchSpider(random.choice(iplist)) results = spider.find(release_name) except NotFoundException, e: sys.stderr.write("Could not find release %s\n" % release_name) diff --git a/shared.py b/shared.py index 86af281..3daa11e 100644 --- a/shared.py +++ b/shared.py @@ -1,4 +1,4 @@ -import requests, random +import requests, random, socket # These are just some random useragents, you can replace these with a different list user_agents = [ @@ -16,10 +16,47 @@ user_agents = [ class NotFoundException(Exception): pass +# Very nasty monkeypatching ahead! +socket.real_create_connection = socket.create_connection + class ModifiedSession(requests.Session): def __init__(self, *args, **kwargs): + try: + self.bound_ip = kwargs['bound_ip'] + del kwargs['bound_ip'] + except KeyError, e: + self.bound_ip = "" + requests.Session.__init__(self, *args, **kwargs) self.headers['user-agent'] = random.choice(user_agents) + + def patch_socket(self): + socket.create_connection = get_patched_func(self.bound_ip) + + def unpatch_socket(self): + socket.create_connection = socket.real_create_connection + + def get(self, *args, **kwargs): + self.patch_socket() + response = requests.Session.get(self, *args, **kwargs) + self.unpatch_socket() + return response + + def post(self, *args, **kwargs): + self.patch_socket() + response = requests.Session.get(self, *args, **kwargs) + self.unpatch_socket() + return response + +def get_patched_func(bind_addr): + def set_src_addr(*args): + address, timeout = args[0], args[1] + source_address = (bind_addr, 0) + return socket.real_create_connection(address, timeout, source_address) + return set_src_addr + +# You're looking at duct tape and tie-wraps. It's like your local Home +# Depot, except in Python. def download_file(request, target): if request.status_code == 200: diff --git a/sources/binsearch.py b/sources/binsearch.py index 0402018..61d1b38 100644 --- a/sources/binsearch.py +++ b/sources/binsearch.py @@ -2,9 +2,12 @@ from shared import NotFoundException, ModifiedSession, download_file import requests, re, HTMLParser class BinsearchSpider(object): + def __init__(self, bound_ip): + self.bound_ip = bound_ip + def find(self, name): parser = HTMLParser.HTMLParser() - self.session = ModifiedSession() + self.session = ModifiedSession(bound_ip=self.bound_ip) response = self.session.get("https://binsearch.info/index.php", params={ "q": name, diff --git a/sources/nzbindex.py b/sources/nzbindex.py index 9d4f427..6a1f4ff 100644 --- a/sources/nzbindex.py +++ b/sources/nzbindex.py @@ -2,9 +2,12 @@ from shared import NotFoundException, ModifiedSession, download_file import requests, re, HTMLParser class NzbindexSpider(object): + def __init__(self, bound_ip): + self.bound_ip = bound_ip + def find(self, name): parser = HTMLParser.HTMLParser() - self.session = ModifiedSession() + self.session = ModifiedSession(bound_ip=self.bound_ip) self.session.post("https://nzbindex.com/agree/", data={"agree": "I agree"}, verify=False) response = self.session.get("https://nzbindex.com/search/", params={