All pastes #1678107 Raw Edit

IbLib

public python v1 · immutable
#1678107 ·published 2009-11-19 18:36 UTC
rendered paste body
'''	Copyright (C) 2009 by Keith Morrow	    IbLib is free software: you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation, either version 3 of the License, or    (at your option) any later version.    IbLib is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with IbLib.  If not, see <http://www.gnu.org/licenses/>.'''import socket, asyncore, asynchat, sys, timePASS=0SKIP=1CANCEL=2QUIT=3def ircsplit(string):	if string[0] == ':': #Not from server		resultA=False		string=string[1:]	else:		resultA=True	if ":" in string:		resultB,resultC=string.split(":",1)	else:		resultB,resultC=string,None	resultB=resultB.split(" ")	while "" in resultB:		resultB.remove("")	return [resultA,resultB,resultC]	quotes=["'",'"']def quotesplit(string):	result=[]	a=string.split()	i=0	while i < len(a):		isquote = False		for j in quotes:			if j == a[i][0]:				isquote = True				findendquote = False				for k in range(i+1,len(a)):					if a[k][-1] == j:						if len(a[k]) != 1:							if a[k][-2] == "\\":								a[k]								continue						findendquote = True						result.append(" ".join(a[i:k+1])[1:-1])						i = k+1						break				if not findendquote:					print "ERROR: could not parse input"					return False				print "got ending quote"				break		if not isquote:			result.append(a[i])			i = i+1	return resultdef nicksplit(string):	resultA,resultB = string.split("!",1)	resultB,resultC = resultB.split("@",1)	return [resultA,resultB,resultC]	def commandsplit(string):	if not " " in string:		return string[len(config['prefix']):], []	command,args = string.split(" ",1)	args=quotesplit(args)	return [command[len(config['prefix']):],args]config = {	'port': 6667,	'channels': [],	'user': 'iblib',	'prefix': '!',	'flooddelay': 0,	'floodtimeout': 0,	'floodcontrol': 0,	'debug': False}hook = {	#initialization hooks	'beforeconnect': [], #Before a connection is established (good for setting config data last-minute)	'afterconnect': [], #Right after a connection is established (if you need to send a server password (This will be implemented better eventually))	'afterun': [], #After USER and NICK are sent (good for sending a nickserv password)	'afterinit': [], #After all channels have been joined	#various session hooks	'join': [], #If you or someone else joins (good for an intro message)	'part': [], #If you or someone else parts (dunno what this would be good for)	'kick': [], #If you or someone else is kicked (good for automatically having the bot re-join)	'quit': [], #If you or someone else quits (only from the server)	'mode': [], #If there is a mode change on you or the channel (so you can react to a mute if needed)	'getmessage': [], #When someone says something that you can see (good for annoying regex bots)	'getcommand': [], #When someone sends a command to the bot (before it's parsed, so you can filter input if needed)	'sendmessage': [], #Just before you send a message (good for filtering output)	#ending hooks	'beforedc': [], #Before disconnecting, (good for sending a quit message)	'afterdc': [] #After disconnected}def cfgDefaults(rootClass, userConfig):		if not 'server' in userConfig:		print "You need to specify a server to connect to. Exiting..."		exit()	else:		config['server'] = userConfig['server']			if 'port' in config:		config['port'] = userConfig['port']			if 'channels' in config:		config['channels'] = userConfig['channels']		if not 'nick' in userConfig:		config['nick'] = rootClass.__class__._name__	else:		config['nick'] = userConfig['nick']		if 'user' in userConfig:		config['user'] = userConfig['user']			if not 'real' in userConfig:		config['real'] = rootClass.__class__._name__ + ' in iblib'	else:		config['real'] = userConfig['real']		if 'prefix' in userConfig:		config['prefix'] = userConfig['prefix']			if 'flooddelay' in userConfig:		config['flooddelay'] = userConfig['flooddelay']			if 'floodcontrol' in userConfig:		config['floodcontrol'] = userConfig['floodcontrol']			if 'debug' in userConfig:		config['debug'] = userConfig['debug']		def handleHooks(name):	global hook	for i in hook[name]:		retval = i()		if retval == QUIT:			print "Hook %s in %s requested to quit." % (i.__name__, name)			exit(1)		elif retval == CANCEL:			print "Hook %s in %s requested to cancel this event." % (i.__name__, name)			return CANCEL		elif retval == SKIP:			print "Hook %s in %s requested to skip all other hooks" % (i.__name__, name)			breakdef join(channel):	conn.write("JOIN %s" % channel)def part(channel, message=None):	if message:		conn.write("PART %s :%s" % (channel, message))def privmsg(destination,message):	for i in message.splitlines():		conn.write("PRIVMSG %s :%s" % (destination, i))def notice(destination,message):	for i in message.splitlines():		conn.write("NOTICE %s :%s" % (destination, i))class request:	nick=None	user=None	host=None	dest=None #only on kicks	channel=None	message=None	method=None	command=None	args=None	class response:	destination=None	message=None	method=Nonedef fillRequest(data):	if len(data[1]) > 1:		command = data[1][1].upper()		if command in ['PRIVMSG','NOTICE','JOIN','PART','KICK','QUIT']:			request.nick, request.user, request.host = nicksplit(data[1][0])			request.method=command			if command in ['PRIVMSG','NOTICE','PART','KICK','QUIT']:				request.message=data[2]			else: request.message=None			if command in ['PRIVMSG','NOTICE','PART','KICK']:				request.channel=data[1][2]			elif command=='JOIN':				request.channel=data[2]			else: request.channel=None			if command=='KICK':				request.dest=data[1][3]		else:			request.nick=None			request.user=None			request.host=None			request.method=None		request.command=None		request.args=Nonedef dispatch(rootClass,command,args):	response.method='PRIVMSG'	if request.channel == None: response.destination = request.nick	else: response.destination = request.channel		try:		response.message=getattr(rootClass, command)(*args)	except AttributeError:		response.message="Command %s does not exist" % command	except:		exc = sys.exc_info()		response.message="%s: %s in %s line %d" % (exc[1].__class__.__name__,exc[1].args[0],exc[2].tb_frame.f_code.co_filename,exc[2].tb_lineno)	def ircHandler(data,rootClass):	fillRequest(data)	if request.method==None: return	elif request.method in ['PRIVMSG','NOTICE']:		handleHooks('getmessage')		if data[2][:len(config['prefix'])] == config['prefix']:			command,args = commandsplit(data[2])			request.command = command			request.args = args			handleHooks('getcommand')			dispatch(rootClass,command,args)			handleHooks('sendmessage')			for i in response.message.splitlines():				conn.write("%s %s :%s" % (response.method, response.destination, i))	elif request.method=='JOIN':		handleHooks('join')	elif request.method=='PART':		handleHooks('part')	elif request.method=='KICK':		handleHooks('kick')	elif request.method=='QUIT':		handleHooks('quit')conn = Nonedef start(rootClass, config):	global conn	print "Setting up internal configuration..."	cfgDefaults(rootClass, config)	print "Initializing and connecting..."	conn = ircConnection(rootClass)	print "We have now started."	try:		asyncore.loop()	except KeyboardInterrupt:		print "Quitting..."		handleHooks('beforedc')		conn.flush()		conn.close()		handleHooks('afterdc')class ircConnection(asynchat.async_chat):	global config, request, response	def __init__(self,root):		if not 'server' in config:			print "You need to specify a server to connect to. Exiting..."			exit()		asynchat.async_chat.__init__(self)		self.set_terminator('\r\n')		self.ibuffer=[]		self.buffer=''		self.initialized = False		self.rootClass = root		self.create_socket(socket.AF_INET, socket.SOCK_STREAM)		handleHooks('beforeconnect')		self.connect((config['server'],config['port']))		def write(self,data):		self.buffer += data+'\r\n'		def flush(self):		while self.writable():			self.handle_write()		def handle_connect(self):		handleHooks('afterconnect')		self.write("USER %s * * :%s" % (config['user'],config['real']))		self.write("NICK %s" % config['nick'])		handleHooks('afterun')		def collect_incoming_data(self, data):		self.ibuffer.append(data)	def writable(self):		return (len(self.buffer) > 0)	def found_terminator(self):		data = "".join(self.ibuffer)		idata = ircsplit(data)		if config['debug']:			print "PS: %s" % idata		self.ibuffer=[]		if self.initialized:			ircHandler(idata,self.rootClass)		else:			if idata[0] == False and idata[1][1] == "001":				self.initialized = True				for i in config['channels']:					join(i)				handleHooks('afterinit')	def handle_write(self):		sent = self.send(self.buffer)		print "OUT: %s" % self.buffer[:sent].replace("\r\n","\\r\\n")		self.buffer = self.buffer[sent:]