#!/usr/bin/python

##This is an updated version of my original proxy tumbling library
##but built to support the pE-api so managing lists of proxies is less
##of a pain.  For now, this only supports our basic 3 proxy list, but 
##eventually will support larger list modes

##todos
##*add support for POST in tumble()
##*add support for other API list types
##*add support for reporting back the proxy's status (up/down)

##autotumbler version 0.1
##10/15/2011 
##samurai@psych0tik.net
__version__ = "0.1"

##imports
import urllib2
import socket
from random import randint

##class
class autotumbler:
	def __init__(self,timeout=5):
		self.debug = 0
		self.timeout = timeout
		self.proxies = []
		self.version = __version__
		self.user_agents = ['autotumbler %s' % self.version]
		self.proxies += self.getPEProxies()

	def __repr__(self):
		return "autotumbler: version %s, proxies %d, agents %d" % (self.version, len(self.proxies), len(self.user_agents))

	def debugOn(self):
		self.debug = 1

	def debugPrint(self,msg):
		if self.debug == 1:
			print "[DEBUG] %s" % (msg)		
 
	##basic implementation (currently only supports get requests)
	##takes the URL to request and returns the string of the data returned
	##does basic error handling
	def tumble(self,url):
		socket.setdefaulttimeout(self.timeout)
		ret = ""
		attempts = 0
		while ret == "" and attempts < 3:
			try:
				request = urllib2.Request(url)
				request = self.buildAgent(request)
				opener = self.buildOpener()
				urllib2.install_opener(opener)
				result = urllib2.urlopen(request)
				return result.read()
			except:
				self.debugPrint("Request failed")
		self.debugPrint("Reached max attempts, all failed")
		return ""

	##this takes a request object and adds a user agent from our list
	def buildAgent(self,request):
		agent = self.user_agents[randint(0,len(self.user_agents)-1)]
		self.debugPrint("Added user agent '%s' to request object" % (agent))
		request.add_header('User-Agent',agent)
		return request

	##this builds and returns a proxy opener with one of the proxies in our list
	##https can be set to 1 to enable that mode (I dont believe urllib2 supports that tho..)
	def buildOpener(self,https=0):
		ip,port = self.proxies[randint(0,len(self.proxies)-1)]
		type = 'http'
		if https > 0:
			type = 'https'
		proxy = urllib2.ProxyHandler({type:"%s:%s" % (ip,port)})
		opener = urllib2.build_opener(proxy)
		self.debugPrint("built opener for %s:%s" % (ip,port))
		return opener


	##adds a new proxy to our usable list
	def addProxy(self,ip,port):
		self.proxies.append((ip,port))

	##addes a new user agent to our usable list
	def addAgent(self,agent):
		self.user_agents.append(agent)

	##resturns a list of tuples of proxies provied by proxyElite.net
	def getPEProxies(self):
		res = urllib2.urlopen("http://proxyElite.net/API/index.php")
		data = res.read()
		ret = []
		for line in data.split("\n"):
			if ':' in line:
				ip,port = line.split(":")
				ret.append((ip,port))
		return ret

	##returns the list of tuples that is the proxy list
	def getProxies(self):
		return self.proxies

	##returns the list of strings that is the user agent list
	def getAgents(self):
		return self.user_agents



