[Otfbot-svn] r122 - trunk

cato- at BerliOS cato-
So Jun 24 13:36:44 CEST 2007


Author: cato-
Date: 2007-06-24 13:36:42 +0200 (Sun, 24 Jun 2007)
New Revision: 122

Modified:
   trunk/chatMod.py
   trunk/control.py
   trunk/functions.py
   trunk/handyxml.py
   trunk/otfbot.py
   trunk/scheduler.py
Log:
* added some docstrings

Modified: trunk/chatMod.py
===================================================================
--- trunk/chatMod.py	2007-06-23 22:34:59 UTC (rev 121)
+++ trunk/chatMod.py	2007-06-24 11:36:42 UTC (rev 122)
@@ -16,11 +16,13 @@
 # 
 # (c) 2005, 2006 by Alexander Schier
 #
-
+""" contains a abstract class for a Bot-module """
 class chatMod:
+	""" abstract class for a botmodule	"""
 	def __init__(self, bot):
 		self.bot=bot
 	def setLogger(self,logger):
+		""" set the logger """
 		self.logger = logger
 	def auth(self, user):
 		"""check the authorisation of the user"""
@@ -88,4 +90,7 @@
 		"""called to reload the settings of the module"""
 		pass
 	def start(self):
+		"""called to start the work of the module
+			put your initialization stuff in here insteadof __init__
+		"""
 		pass

Modified: trunk/control.py
===================================================================
--- trunk/control.py	2007-06-23 22:34:59 UTC (rev 121)
+++ trunk/control.py	2007-06-24 11:36:42 UTC (rev 122)
@@ -16,198 +16,248 @@
 # 
 # (c) 2007 Robert Weidlich
 #
+
+""" Control the bot during runtime """
 class configShell:
-    DESTROY_ME=234
-    def __init__(self, bot):
-        self.bot=bot
-        self.configlevel=[]
+	""" Implements a shell-like Interface for manipulating the configuration """
+	DESTROY_ME=234
+	def __init__(self, bot):
+		"""
+			@type bot: a L{Bot}-Instance
+		"""
+		self.bot=bot
+		self.configlevel=[]
 
-    def _getlevellist(self):
-        if len(self.configlevel) == 0:
-            return self.bot.getNetworks()
-        elif len(self.configlevel) == 1:
-            return self.bot.getChannels(self.configlevel[0])
-        else:
-            return self.bot.getSubOptions(self.configlevel)
-    
-    def _ls(self):
-        out=""
-        lst=self._getlevellist()
-        for i in range(1,len(lst)):
-            out=out+str(i)+" "+lst[i-1]+" | "
-        return out
-        
-    def _cd(self, string):
-        if string == ".." and len(self.configlevel)>=0:
-            self.configlevel.pop()
-        else:
-            num=int(string)
-            if 0 < num and num < len(self._getlevellist())+1:
-                self.configlevel.append(self._getlevellist()[num-1])
-            else:
-                return "No such setting: "+str(num)
-    
-    def _get(self,string):
-        msg=string.split(" ")
-        #self.logger.debug(msg)
-        if len(msg) == 4:
-            res=self.bot.getConfig(msg[0], "",msg[1],msg[2],msg[3])
-        elif len(msg) == 3:
-            res=self.bot.getConfig(msg[0], "", msg[1], msg[2])
-        elif len(msg) == 2:
-            res=self.bot.getConfig(msg[0], "", msg[1])
-        elif len(msg) == 1:
-            res=self.bot.getConfig(msg[0], "")
-        if len(msg) == 0 or len(msg) > 4:
-            return "Syntax: config get key [modul] [network] [channel]"
-        else:
-            #self.logger.debug(".".join(msg))
-            #self.logger.debug(res)
-            return ".".join(msg)+"="+res
-    
-    def _set(self, string):
-        #FIXME: 
-        #msg=msg[4:]
-        #tmp=msg.split("=")
-        #if len(tmp) != 2:
-        #    self.bot.sendmsg(nick, "Syntax: config set key=value")
-        #    return
-        #self.bot.setConfig(tmp[0], tmp[1])
-        return "function is out of order"
-    
-    def input(self, request):
-        tmp = request.strip().split(" ",1)
-        if len(tmp) == 1:
-            command = tmp[0]
-            argument = ""
-        else:
-            (command, argument) = tmp
-        if command == "ls":
-            return self._ls()
-        elif command == "cd":
-            return self._cd(argument)
-        elif command == "quit":
-            return self.DESTROY_ME
-        elif command == "get":
-            return self._get(argument)
-        elif command == "set":
-            return self._set(argument)
-        else:
-            return "Some helpful text"
-            #self.bot.sendmsg(nick, "Syntax: config [get <key> [modul] [network] [channel]|set <key=value>]")
+	def _getlevellist(self):
+		""" get a list of items at the current level
+			@return: a list of items in the current level 
+			@rtype: list
+		"""
+		if len(self.configlevel) == 0:
+			return self.bot.getNetworks()
+		elif len(self.configlevel) == 1:
+			return self.bot.getChannels(self.configlevel[0])
+		else:
+			return self.bot.getSubOptions(self.configlevel)
+	
+	def _ls(self):
+		""" get the content of the current level
+			@rtype: string
+		"""
+		return " | ".join(self._getlevellist())
+		
+	def _cd(self, string):
+		""" change into C{string}
+			@param string: the item to change into (might be a network, a channel, a module or a level above (..))
+			@type string: string
+		"""
+		if string == ".." and len(self.configlevel)>=0:
+			self.configlevel.pop()
+		else:
+			num=int(string)
+			if 0 < num and num < len(self._getlevellist())+1:
+				self.configlevel.append(self._getlevellist()[num-1])
+			else:
+				return "No such setting: "+str(num)
+	
+	def _get(self,string):
+		""" get the value of a certain item
+			@param string: the identifier of the item to get
+			@type string: string
+			@return: the value of the requested item
+			@rtype: string
+		"""
+		msg=string.split(" ")
+		#self.logger.debug(msg)
+		if len(msg) == 4:
+			res=self.bot.getConfig(msg[0], "",msg[1],msg[2],msg[3])
+		elif len(msg) == 3:
+			res=self.bot.getConfig(msg[0], "", msg[1], msg[2])
+		elif len(msg) == 2:
+			res=self.bot.getConfig(msg[0], "", msg[1])
+		elif len(msg) == 1:
+			res=self.bot.getConfig(msg[0], "")
+		if len(msg) == 0 or len(msg) > 4:
+			return "Syntax: config get key [modul] [network] [channel]"
+		else:
+			#self.logger.debug(".".join(msg))
+			#self.logger.debug(res)
+			return ".".join(msg)+"="+res
+	
+	def _set(self, item, value):
+		"""
+			should set C{item} to C{value}
+			@param item: the item to update
+			@type item: string
+			@param value: the value to set
+			@type value: string
+			@note: this function does currently nothing.
+		"""
+		#FIXME: 
+		#msg=msg[4:]
+		#tmp=msg.split("=")
+		#if len(tmp) != 2:
+		#	self.bot.sendmsg(nick, "Syntax: config set key=value")
+		#	return
+		#self.bot.setConfig(tmp[0], tmp[1])
+		return "function is out of order"
+	
+	def input(self, request):
+		""" Pass all input to this function
+		
+			this function accepts the input, handles it to the right function and returns the result
+			@param request: the command and argument
+			@type request: string
+			@rtype: string
+			@return: the result of the command
+		"""
+		tmp = request.strip().split(" ",1)
+		if len(tmp) == 1:
+			command = tmp[0]
+			argument = ""
+		else:
+			(command, argument) = tmp
+		if command == "ls":
+			return self._ls()
+		elif command == "cd":
+			return self._cd(argument)
+		elif command == "quit":
+			return self.DESTROY_ME
+		elif command == "get":
+			return self._get(argument)
+		elif command == "set":
+			return self._set(argument)
+		else:
+			return "Some helpful text"
+			#self.bot.sendmsg(nick, "Syntax: config [get <key> [modul] [network] [channel]|set <key=value>]")
 
 
 class controlInterface:
-    MODUS_DEFAULT=0
-    MODUS_CONFIGSHELL=1
-    def __init__(self, bot):
-        self.bot=bot
-        self.modus=self.MODUS_DEFAULT
-        self.configshell=None
-        self.prompt=""
-    
-    def _output(self, string):
-        return unicode(self.prompt+string).encode("utf-8")
-    
-    def input(self, request):
-        tmp = request.strip().split(" ",1)
-        if len(tmp) == 1:
-            command=tmp[0]
-            argument=""
-        else:
-            (command, argument) = tmp
-        if command == "config":
-            self.configshell=configShell(self.bot)
-            return self._output("Entering configshell ...")
-        elif self.configshell:
-            output = self.configshell.input(request)
-            if (output == self.configshell.DESTROY_ME):
-                self.configshell=None
-                return self._output("Leaving configshell ...")
-            else:
-                return self._output(output)
-        elif command == "help":
-            return self._output("Available commands: reload, stop|quit, disconnect [network], connect network [port], listnetworks, currentnetwork, changenetwork network, changenick newnick, join channel, part channel [message], listchannels")
-        elif command == "shell":
-            if argument == "telnet":
-                self.prompt=self.bot.network+"> "
-            elif argument == "readline":
-                return self._output("01 +channels,"+",".join(self.bot.channels)+":+networks,"+",".join(self.bot.factory._getnetworkslist())+":config:help:reload:listmodules:stop:quit:disconnect,+networks:connect:listnetworks:currentnetwork:changenetwork,+networks:listchannels:changenick:join:part,+channels:kick")
-            elif argument == "prompt":
-                return self._output("02 "+self.bot.network)
-        elif command == "reload":
-            self.bot.reloadModules()
-            return self._output("Reloading all modules ...")
-        elif command == "listmodules":
-            module=[]
-            for mod in self.bot.mods:
-                module.append(mod.name)
-            return self._output(" ".join(module))
-        elif command == "stop" or command == "quit":
-            conns=self.bot.factory._getnetworkslist()
-            for c in conns:
-                self.bot.factory._getnetwork(c).quit()
-            return self._output("Disconnecting from all networks und exiting ...")
-        elif command == "disconnect":
-            conns=self.bot.factory._getnetworkslist()
-            if argument != "":
-                if argument in conns:
-                    self.bot.factory._getnetwork(argument).quit()
-                    return self._output("Disconnecting from "+str(argument))
-                else:
-                    return self._output("Not connected to "+str(argument))
-            else:
-                self.bot.quit("Bye.")
-                return self._output("Disconnecting from current network. Bye.")
-        elif command == "connect":
-            args = argument.split(" ")
-            if len(args) < 1 or len(args) > 2:
-                return self._output("Usage: connect irc.network.tld [port]")
-            else:
-                if len(args) == 2:
-                    port=args[1]
-                else:
-                    port=6667
-                c = self.bot.getReactor().connectTCP(args[0],port,self.bot.factory)
-                return self._output("Connecting to "+str(c))
-        elif command == "listnetworks":
-            return self._output("Currently connected to: "+" ".join(self.bot.factory._getnetworkslist()))
-        elif command == "currentnetwork":
-            return self._output("Current network: "+self.bot.network)
-        elif command == "changenetwork":
-            self.bot=self.bot.factory._getnetwork(argument)
-            return self._output("changed network to "+self.bot.network)
-        elif command == "listchannels":
-            return self._output("Currently in: "+" ".join(self.bot.channels))
-        elif command == "changenick":
-            if argument == "":
-                return self._output("Usage: changenick newnick")
-            else:
-                self.bot.setNick(argument)
-        elif command == "join":
-            if argument == "":
-                return self._output("Usage: join channel")
-            else:
-                self.bot.join(argument)
-                return self._output("Joined "+str(argument))
-        elif command == "part":
-            args=argument.split(" ",1)
-            if len(args) == 0:
-                return self._output("Usage: part channel [message]")
-            else:
-                if len(args) > 1:
-                    partmsg=args[1]
-                else:
-                    partmsg=""
-                self.bot.leave(args[0],partmsg)
-                return self._output("Left "+args[0])
-        elif command == "kick":
-            args=msg.split(" ",2)
-            if len(args) < 2:
-                return self._output("Usage: kick channel user [message]")
-            else:
-                if len(args) == 2:
-                    self.bot.kick(args[0],args[1])
-                else:
-                    self.bot.kick(args[0],args[1],args[3])
-                return self._output("Kicked "+args[1]+" from "+args[0]+".")
\ No newline at end of file
+	""" allows to control the behaviour of the bot during runtime
+	
+		this class only does the work, you need another class, most suitable is a bot-module, to have a userinterface
+	"""
+	MODUS_DEFAULT=0
+	MODUS_CONFIGSHELL=1
+	def __init__(self, bot):
+		"""
+			@type bot: a L{Bot} Instance
+		"""
+		self.bot=bot
+		self.modus=self.MODUS_DEFAULT
+		self.configshell=None
+		self.prompt=""
+	
+	def _output(self, string):
+		""" helper function which set the encoding to utf8
+		"""
+		return unicode(self.prompt+string).encode("utf-8")
+	
+	def input(self, request):
+		""" Pass your command to this function and get the output
+			@param request: command and arguments
+			@type request: string
+			@rtype: string
+			@return: the output of the command
+		"""
+		tmp = request.strip().split(" ",1)
+		if len(tmp) == 1:
+			command=tmp[0]
+			argument=""
+		else:
+			(command, argument) = tmp
+		if command == "config":
+			self.configshell=configShell(self.bot)
+			return self._output("Entering configshell ...")
+		elif self.configshell:
+			output = self.configshell.input(request)
+			if (output == self.configshell.DESTROY_ME):
+				self.configshell=None
+				return self._output("Leaving configshell ...")
+			else:
+				return self._output(output)
+		elif command == "help":
+			return self._output("Available commands: reload, stop|quit, disconnect [network], connect network [port], listnetworks, currentnetwork, changenetwork network, changenick newnick, join channel, part channel [message], listchannels")
+		elif command == "shell":
+			if argument == "telnet":
+				self.prompt=self.bot.network+"> "
+			elif argument == "readline":
+				return self._output("01 +channels,"+",".join(self.bot.channels)+":+networks,"+",".join(self.bot.factory._getnetworkslist())+":config:help:reload:listmodules:stop:quit:disconnect,+networks:connect:listnetworks:currentnetwork:changenetwork,+networks:listchannels:changenick:join:part,+channels:kick")
+			elif argument == "prompt":
+				return self._output("02 "+self.bot.network)
+		elif command == "reload":
+			self.bot.reloadModules()
+			return self._output("Reloading all modules ...")
+		elif command == "listmodules":
+			module=[]
+			for mod in self.bot.mods:
+				module.append(mod.name)
+			return self._output(" ".join(module))
+		elif command == "stop" or command == "quit":
+			conns=self.bot.factory._getnetworkslist()
+			for c in conns:
+				self.bot.factory._getnetwork(c).quit()
+			return self._output("Disconnecting from all networks und exiting ...")
+		elif command == "disconnect":
+			conns=self.bot.factory._getnetworkslist()
+			if argument != "":
+				if argument in conns:
+					self.bot.factory._getnetwork(argument).quit()
+					return self._output("Disconnecting from "+str(argument))
+				else:
+					return self._output("Not connected to "+str(argument))
+			else:
+				self.bot.quit("Bye.")
+				return self._output("Disconnecting from current network. Bye.")
+		elif command == "connect":
+			args = argument.split(" ")
+			if len(args) < 1 or len(args) > 2:
+				return self._output("Usage: connect irc.network.tld [port]")
+			else:
+				if len(args) == 2:
+					port=args[1]
+				else:
+					port=6667
+				c = self.bot.getReactor().connectTCP(args[0],port,self.bot.factory)
+				return self._output("Connecting to "+str(c))
+		elif command == "listnetworks":
+			return self._output("Currently connected to: "+" ".join(self.bot.factory._getnetworkslist()))
+		elif command == "currentnetwork":
+			return self._output("Current network: "+self.bot.network)
+		elif command == "changenetwork":
+			self.bot=self.bot.factory._getnetwork(argument)
+			return self._output("changed network to "+self.bot.network)
+		elif command == "listchannels":
+			return self._output("Currently in: "+" ".join(self.bot.channels))
+		elif command == "changenick":
+			if argument == "":
+				return self._output("Usage: changenick newnick")
+			else:
+				self.bot.setNick(argument)
+		elif command == "join":
+			if argument == "":
+				return self._output("Usage: join channel")
+			else:
+				self.bot.join(argument)
+				return self._output("Joined "+str(argument))
+		elif command == "part":
+			args=argument.split(" ",1)
+			if len(args) == 0:
+				return self._output("Usage: part channel [message]")
+			else:
+				if len(args) > 1:
+					partmsg=args[1]
+				else:
+					partmsg=""
+				self.bot.leave(args[0],partmsg)
+				return self._output("Left "+args[0])
+		elif command == "kick":
+			args=msg.split(" ",2)
+			if len(args) < 2:
+				return self._output("Usage: kick channel user [message]")
+			else:
+				if len(args) == 2:
+					self.bot.kick(args[0],args[1])
+				else:
+					self.bot.kick(args[0],args[1],args[3])
+				return self._output("Kicked "+args[1]+" from "+args[0]+".")
\ No newline at end of file

Modified: trunk/functions.py
===================================================================
--- trunk/functions.py	2007-06-23 22:34:59 UTC (rev 121)
+++ trunk/functions.py	2007-06-24 11:36:42 UTC (rev 122)
@@ -18,44 +18,64 @@
 # (c) 2006 by Robert Weidlich
 #
 
+""" Contains some helper functions """
+
 import os
 
 def loadProperties(propertiesFile):
-    properties={}
-    if propertiesFile=="":
-        return {}
-    try:
-        propFile = open(propertiesFile, "r")
-        content = propFile.read()
-        propFile.close()
-        for line in content.split("\n"):
-            if len(line) >1 and line[0] != "#":
-                pair = line.split("=", 1)
-                if len(pair)==2:
-                    properties[pair[0]] = pair[1]
-    except IOError:
-        print "loadProperties: Creating", propertiesFile
-        if (not os.path.isdir(os.path.dirname(propertiesFile))):
-            os.makedirs(os.path.dirname(propertiesFile))
-        propFile = open(propertiesFile, "w")
-        propFile.close()
-    return properties
-    
+	""" Loads data from a file into a dict
+		
+		The data in the file should have the format::
+			key=value
+		If the file doesn't exist, it will be created. If no filename is given an empty dict is returned
+		@param propertiesFile: The file to deal with
+		@type propertiesFile: string
+		@rtype: dict
+	"""
+	properties={}
+	if propertiesFile=="":
+		return {}
+	try:
+		propFile = open(propertiesFile, "r")
+		content = propFile.read()
+		propFile.close()
+		for line in content.split("\n"):
+			if len(line) >1 and line[0] != "#":
+				pair = line.split("=", 1)
+				if len(pair)==2:
+					properties[pair[0]] = pair[1]
+	except IOError:
+		print "loadProperties: Creating", propertiesFile
+		if (not os.path.isdir(os.path.dirname(propertiesFile))):
+			os.makedirs(os.path.dirname(propertiesFile))
+		propFile = open(propertiesFile, "w")
+		propFile.close()
+	return properties
+	
 def loadList(listFile):
-    if listFile=="":
-        return []
-    list=[]
-    try:
-        file = open(listFile, "r")
-        content = file.read()
-        file.close()
-        for word in content.split("\n"):
-            if word != "" and word[0] != '#':
-                list.append(word)
-    except IOError:
-        print "loadList: Creating", listFile
-        if (not os.path.isdir(os.path.dirname(listFile))):
-            os.makedirs(os.path.dirname(listFile))
-        file = open(listFile, "w")
-        file.close()
-    return list
+	""" loads data from a file into a list
+		
+		This function loads simply each line of the file into a list.
+		If the filename is empty, a empty list is returned. If the file given
+		doesn't exist, it will be created.
+		@param listFile: the file to deal with
+		@type listFile: string
+		@rtype: list
+	"""
+	if listFile=="":
+		return []
+	list=[]
+	try:
+		file = open(listFile, "r")
+		content = file.read()
+		file.close()
+		for word in content.split("\n"):
+			if word != "" and word[0] != '#':
+				list.append(word)
+	except IOError:
+		print "loadList: Creating", listFile
+		if (not os.path.isdir(os.path.dirname(listFile))):
+			os.makedirs(os.path.dirname(listFile))
+		file = open(listFile, "w")
+		file.close()
+	return list

Modified: trunk/handyxml.py
===================================================================
--- trunk/handyxml.py	2007-06-23 22:34:59 UTC (rev 121)
+++ trunk/handyxml.py	2007-06-24 11:36:42 UTC (rev 122)
@@ -38,14 +38,15 @@
 #
 
 class HandyXmlWrapper:
-    """ This class wraps an XML element to give it convenient
-        attribute access.
-        <element attr1='foo' attr2='bar'>
-            <child attr3='baz' />
-        </element>
-        element.attr1 == 'foo'
-        element.child.attr3 == 'baz'
     """
+    	This class wraps an XML element to give it convenient
+        attribute access.::
+        	<element attr1='foo' attr2='bar'>
+	            <child attr3='baz' />
+        	</element>
+        	element.attr1 == 'foo'
+        	element.child.attr3 == 'baz'
+    """
     def __init__(self, node):
         self.node = node
 

Modified: trunk/otfbot.py
===================================================================
--- trunk/otfbot.py	2007-06-23 22:34:59 UTC (rev 121)
+++ trunk/otfbot.py	2007-06-24 11:36:42 UTC (rev 122)
@@ -39,27 +39,27 @@
 
 (options,args)=parser.parse_args()
 if options.debug and options.debug not in (10,20,30,40,50):
-    parser.error("Unknown value for --debug")
+	parser.error("Unknown value for --debug")
 ###############################################################################
 #check for root rights
 if os.getuid()==0:
-    if options.userid and options.userid!=0 and options.groupid and options.groupid!=0:
-        from twisted.python.util import switchUID
-        #os.chroot(".") #DOES NOT WORK. pwd.getpwuid fails in switchUID, when chrooted.
-        switchUID(options.userid, options.groupid)
-    else:
-        print "Otfbot should not be run as root."
-        print "please use -u and -g to specify a userid/groupid"
-        sys.exit(1)
+	if options.userid and options.userid!=0 and options.groupid and options.groupid!=0:
+		from twisted.python.util import switchUID
+		#os.chroot(".") #DOES NOT WORK. pwd.getpwuid fails in switchUID, when chrooted.
+		switchUID(options.userid, options.groupid)
+	else:
+		print "Otfbot should not be run as root."
+		print "please use -u and -g to specify a userid/groupid"
+		sys.exit(1)
 ###############################################################################
 # Detaching from console
 if options.foreground == False and not options.debug > 0:
-    try:
-        import subprocess
-        subprocess.Popen([sys.argv[0],"-f"])
-        sys.exit(0)
-    except ImportError:
-        pass
+	try:
+		import subprocess
+		subprocess.Popen([sys.argv[0],"-f"])
+		sys.exit(0)
+	except ImportError:
+		pass
 ###############################################################################
 # Setup Logging
 import logging
@@ -75,93 +75,101 @@
 #corelogger.addHandler(filelogger)
 
 if options.debug > 0:
-    # logging to stdout
-    console = logging.StreamHandler()
-    logging.getLogger('').setLevel(options.debug)
-    formatter = logging.Formatter('%(asctime)s %(name)-10s %(module)-18s %(levelname)-8s %(message)s')
-    console.setFormatter(formatter)
-    logging.getLogger('').addHandler(console)
-    #corelogger.addHandler(console)
+	# logging to stdout
+	console = logging.StreamHandler()
+	logging.getLogger('').setLevel(options.debug)
+	formatter = logging.Formatter('%(asctime)s %(name)-10s %(module)-18s %(levelname)-8s %(message)s')
+	console.setFormatter(formatter)
+	logging.getLogger('').addHandler(console)
+	#corelogger.addHandler(console)
 corelogger = logging.getLogger('core')
 corelogger.info("Starting OtfBot - Version svn "+str(svnversion))
 
 def logerror(logger, module, exception):
-    logger.error("Exception in Module "+module+": "+str(exception))
-    tb_list = traceback.format_tb(sys.exc_info()[2])
-    for entry in tb_list:
-        for line in entry.strip().split("\n"):
-            logger.error(line)
+	""" format a exception nicely and pass it to the logger
+		@param logger: the logger instance to use
+		@param module: the module in which the exception occured
+		@type module: string
+		@param exception: the exception
+		@type exception: exception
+	"""
+	logger.error("Exception in Module "+module+": "+str(exception))
+	tb_list = traceback.format_tb(sys.exc_info()[2])
+	for entry in tb_list:
+		for line in entry.strip().split("\n"):
+			logger.error(line)
 
 ###############################################################################
-# Function which is called, when the program terminates.
+
 def exithook():
-    # remove Pidfile
-    os.remove(pidfile)
-    writeConfig()
-    corelogger.info("Bot shutted down")
-    corelogger.info("-------------------------")
+	""" This function is called, when the program terminates. """
+	# remove Pidfile
+	os.remove(pidfile)
+	writeConfig()
+	corelogger.info("Bot shutted down")
+	corelogger.info("-------------------------")
 
 # Load modules
 sys.path.insert(1,"modules")
 classes=[]
 for file in os.listdir("modules"):
-    if len(file)>=3 and file[-3:]==".py":
-        classes.append(__import__(file[:-3]))
-        classes[-1].datadir = "modules/"+classes[-1].__name__+"-data"
-        corelogger.debug("Loading module "+classes[-1].__name__)
+	if len(file)>=3 and file[-3:]==".py":
+		classes.append(__import__(file[:-3]))
+		classes[-1].datadir = "modules/"+classes[-1].__name__+"-data"
+		corelogger.debug("Loading module "+classes[-1].__name__)
 
 ###############################################################################
 # some config functions
 theconfig=None
 def setConfig(option, value, module=None, network=None, channel=None):
-    theconfig.set(option, value, module, network, channel)
-    writeConfig()
-        
+	theconfig.set(option, value, module, network, channel)
+	writeConfig()
+		
 def hasConfig(option, module=None):
-    return theconfig.has(option, module)
+	return theconfig.has(option, module)
 def getConfig(option, defaultvalue="", module=None, network=None, channel=None):
-    return theconfig.get(option, defaultvalue, module, network, channel)
+	return theconfig.get(option, defaultvalue, module, network, channel)
 def getBoolConfig(option, defaultvalue="", module=None, network=None, channel=None):
-    if theconfig.get(option, defaultvalue, module, network, channel) in ["True","true","On","on","1"]:
-        return True
-    return False
+	if theconfig.get(option, defaultvalue, module, network, channel) in ["True","true","On","on","1"]:
+		return True
+	return False
 
 def loadConfig(myconfigfile):
-    if os.path.exists(myconfigfile):
-        myconfig=config.config(logging, myconfigfile)
-    else:
-        myconfig=config.config(logging)
-        for myclass in classes:
-            try:
-                modconfig=myclass.default_settings()
-                for item in modconfig.keys():
-                    myconfig.set(item, modconfig[item])
-            except AttributeError:
-                pass
-        
-        myconfig.set('enabled', 'false', 'main', 'irc.samplenetwork')
-        myconfig.set('enabled', 'false', 'main', 'irc.samplenetwork', '#example')
-        myconfig.set('nickname', 'OtfBot', 'main')
-        myconfig.set('encoding', 'UTF-8', 'main')
-        myconfig.set('pidfile','otfbot.pid','main')
-        
-        file=open(myconfigfile, "w")
-        file.write(myconfig.exportxml())
-        file.close()
-        #no logger here: the user needs to read this on console, not in logfile
-        print "Default Settings loaded."
-        print "Edit config.xml to configure the bot."
-        sys.exit(0)
-    return myconfig
+	if os.path.exists(myconfigfile):
+		myconfig=config.config(logging, myconfigfile)
+	else:
+		myconfig=config.config(logging)
+		for myclass in classes:
+			try:
+				modconfig=myclass.default_settings()
+				for item in modconfig.keys():
+					myconfig.set(item, modconfig[item])
+			except AttributeError:
+				pass
+		
+		myconfig.set('enabled', 'false', 'main', 'irc.samplenetwork')
+		myconfig.set('enabled', 'false', 'main', 'irc.samplenetwork', '#example')
+		myconfig.set('nickname', 'OtfBot', 'main')
+		myconfig.set('encoding', 'UTF-8', 'main')
+		myconfig.set('pidfile','otfbot.pid','main')
+		
+		file=open(myconfigfile, "w")
+		file.write(myconfig.exportxml())
+		file.close()
+		#no logger here: the user needs to read this on console, not in logfile
+		print "Default Settings loaded."
+		print "Edit config.xml to configure the bot."
+		sys.exit(0)
+	return myconfig
 
 def writeConfig():
-    file=open(configfile, "w")
-    #options=config.keys()
-    #options.sort()
-    #for option in options:
-    #    file.write(option+"="+config[option]+"\n")
-    file.write(theconfig.exportxml())
-    file.close()
+	file=open(configfile, "w")
+	#options=config.keys()
+	#options.sort()
+	#for option in options:
+	#	file.write(option+"="+config[option]+"\n")
+	file.write(theconfig.exportxml())
+	file.close()
 
 
 # some constants, can be retrieved from serveranswer while connecting.
@@ -169,308 +177,453 @@
 modcharvals={'!':4,'@':3,'%':2,'+':1,' ':0}
 
 class Bot(irc.IRCClient):
-    """The Protocol of our IRC-Bot"""
-    def __init__(self):
-        #list of mods, which the bot should use
-        #you may need to configure them first
-        self.classes = classes
-        self.users={}
-        self.channels=[]
-        self.network=None
-    
-        self.mods = []
-        self.numMods = 0
+	""" The Protocol of our IRC-Bot
+		@ivar mods: contains references to all modules, which are loaded
+		@type mods: list
+		@ivar users: contains a dict of all users in the channels we are in
+		@type users: dict
+		@ivar channels: all channels we are currently in
+		@type channels: list
+		@ivar network: the name of the network we are connected to
+		@type network: string
+		@ivar logger: a instance of the standard python logger
+		@ivar scheduler: a instance of the L{Scheduler}
+		@ivar nickname: the nick of the bot
+	"""
+	def __init__(self):
+		#list of mods, which the bot should use
+		#you may need to configure them first
+		self.classes = classes
+		self.users={}
+		self.channels=[]
+		self.network=None
+	
+		self.mods = []
+		self.numMods = 0
 
-        self.versionName="OtfBot"
-        self.versionNum="svn "+"$Revision$".split(" ")[1]
-        self.logging = logging
-        self.logger = logging.getLogger("core")
-        self.logger.info("Starting new Botinstance")
-        self.scheduler = scheduler.Scheduler(self.getReactor())
-        self.startMods()
-    
-    def _apirunner(self,apifunction,args={}):
-        """Pass all calls to modules callbacks through this method, they are checked whether they should be execeted or not"""
-        for mod in self.mods:
-            if (args.has_key("channel") and args["channel"] in self.channels and self.getBoolConfig("enabled","True",mod.name,self.network,args["channel"])) or not args.has_key("channel") or args["channel"] not in self.channels:
-                try:
-                    getattr(mod,apifunction)(**args)
-                except Exception, e:
-                    logerror(self.logger, mod.name, e)
-    
-    # public API
-    def startMods(self):
-        workingdir=os.getcwd()
-        for chatModule in self.classes:
-            #if self.getConfig("enabled","true",chatModule.__name__,self.network)
-            self.mods.append( chatModule.chatMod(self) )
-            self.mods[-1].setLogger(self.logger)
-            self.mods[-1].name = chatModule.__name__
-            #try:
-            #    self.mods[-1].start()
-            #except AttributeError:
-            #    pass
-        self._apirunner("start")
-    # configstuff, should maybe be moved to a config-instance at self.config
-    def setConfig(self, option, value, module=None, network=None, channel=None):
-        return setConfig(option, value, module, network, channel)
-    def hasConfig(self, option, module=None):
-        return hasConfig(option, module)
-    def getConfig(self, option, defaultvalue="", module=None, network=None, channel=None):
-        return getConfig(option, defaultvalue, module, network, channel)
-    def getBoolConfig(self, option, defaultvalue="", module=None, network=None, channel=None):
-        return getBoolConfig(option, defaultvalue, module, network, channel)
-    def getSubOptions(self, list):
-        return theconfig.getsubopts(list)
-    def getNetworks(self):
-        return theconfig.getNetworks()
-    def getChannels(self,net):
-        return theconfig.getChannels(net)
-    def loadConfig(self):
-        return loadConfig(configfile)
-    def writeConfig(self):
-        return writeConfig()
-    def getUsers(self):
-        return self.users
-    def getReactor(self):
-        return reactor
-    def getFactory(self):
-        return self.factory
-    def auth(self, user):
-        """test if the user is privileged"""
-        level=0
-        for mod in self.mods:
-            try:
-                retval=mod.auth(user)
-                if retval > level:
-                    level=retval
-            except AttributeError:
-                pass
-        return level
-    
-    def sendmsg(self, channel, msg, encoding="iso-8859-15", fallback="iso-8859-15"):
-        """msg function, that converts from iso-8859-15 to a encoding given in the config"""
-        try:
-            msg=unicode(msg, encoding).encode(self.getConfig("encoding", "UTF-8", "main"))
-        except UnicodeDecodeError:
-            #self.logger.debug("Unicode Decode Error with String:"+str(msg))
-            #Try with Fallback encoding
-            msg=unicode(msg, fallback).encode(self.getConfig("encoding", "UTF-8", "main"))
-        except UnicodeEncodeError:
-            pass
-            #self.logger.debug("Unicode Encode Error with String:"+str(msg))
-            #use msg as is
-            
-        self.msg(channel, msg)
-        self.privmsg(self.nickname, channel, msg)
-        
-    def sendme(self, channel, action, encoding="iso-8859-15"):
-        """msg function, that converts from iso-8859-15 to a encoding given in the config"""
-        action=unicode(action, encoding).encode(self.getConfig("encoding", "UTF-8", "main"))
-            
-        self.me(channel, action)
-        self.action(self.nickname, channel, action)
-    
-    def reloadModules(self):
-        for chatModule in self.classes:
-            self.logger.info("reloading "+chatModule.__name__)
-            reload(chatModule)
-        for chatMod in self.mods:
-            try:
-                chatMod.stop()
-            except Exception, e:
-                logerror(self.logger, mod.name, e)
-        self.mods=[]
-        self.startMods()    
-    
-    # Callbacks
-    def connectionMade(self):
-        self.network=self.transport.addr[0]
-        tmp=self.getChannels(self.network)
-        if tmp:
-            self.channels=tmp
-        self.nickname=unicode(self.getConfig("nickname", "OtfBot", 'main', self.network)).encode("iso-8859-1")
-        if len(self.network.split(".")) < 2:
-            nw = self.network
-        else:
-            nw = self.network.split(".")[-2]
-        self.logger = self.logging.getLogger(nw)
-        self.logger.info("made connection to "+self.network)
-        irc.IRCClient.connectionMade(self)
-        for mod in self.mods:
-            mod.setLogger(self.logger)
-            mod.network=self.network
-        self._apirunner("connectionMade")
+		self.versionName="OtfBot"
+		self.versionNum="svn "+"$Revision$".split(" ")[1]
+		self.logging = logging
+		self.logger = logging.getLogger("core")
+		self.logger.info("Starting new Botinstance")
+		self.scheduler = scheduler.Scheduler(self.getReactor())
+		self.startMods()
+	
+	def _apirunner(self,apifunction,args={}):
+		"""
+			Pass all calls to modules callbacks through this method, they 
+			are checked whether they should be executed or not.
+			
+			Example C{self._apirunner("privmsg",{"user":user,"channel":channel,"msg":msg})}
+			
+			@type	apifunction: string
+			@param	apifunction: the name of the callback function
+			@type	args:	dict
+			@param	args:	the arguments for the callback
+		"""
+		for mod in self.mods:
+			if (args.has_key("channel") and args["channel"] in self.channels and self.getBoolConfig("enabled","True",mod.name,self.network,args["channel"])) or not args.has_key("channel") or args["channel"] not in self.channels:
+				try:
+					getattr(mod,apifunction)(**args)
+				except Exception, e:
+					logerror(self.logger, mod.name, e)
+	
+	# public API
+	def startMods(self):
+		"""
+			initializes all known modules
+		"""
+		for chatModule in self.classes:
+			#if self.getConfig("enabled","true",chatModule.__name__,self.network)
+			self.mods.append( chatModule.chatMod(self) )
+			self.mods[-1].setLogger(self.logger)
+			self.mods[-1].name = chatModule.__name__
+			#try:
+			#	self.mods[-1].start()
+			#except AttributeError:
+			#	pass
+		self._apirunner("start")
 
-    def connectionLost(self, reason):
-        #self.logger.info("lost connection: "+str(reason))
-        irc.IRCClient.connectionLost(self)
-        self._apirunner("connectionLost",{"reason": reason})
-    
-    def signedOn(self):
-        self.logger.info("signed on "+self.network+" as "+self.nickname)
-        channelstojoin=self.channels
-        self.channels=[]
-        for channel in channelstojoin:
-            if(getBoolConfig("enabled", "false", "main", self.network, channel)):
-                self.join(unicode(channel).encode("iso-8859-1"))
-        self._apirunner("signedOn")
+	# configstuff, should maybe be moved to a config-instance at self.config
+	def setConfig(self, option, value, module=None, network=None, channel=None):
+		return setConfig(option, value, module, network, channel)
+	def hasConfig(self, option, module=None):
+		return hasConfig(option, module)
+	def getConfig(self, option, defaultvalue="", module=None, network=None, channel=None):
+		return getConfig(option, defaultvalue, module, network, channel)
+	def getBoolConfig(self, option, defaultvalue="", module=None, network=None, channel=None):
+		return getBoolConfig(option, defaultvalue, module, network, channel)
+	def getSubOptions(self, list):
+		return theconfig.getsubopts(list)
+	def getNetworks(self):
+		return theconfig.getNetworks()
+	def getChannels(self,net):
+		return theconfig.getChannels(net)
+	def loadConfig(self):
+		return loadConfig(configfile)
+	def writeConfig(self):
+		return writeConfig()
 
-    def joined(self, channel):
-        self.logger.info("joined "+channel)
-        self.channels.append(channel)
-        self.users[channel]={}
-        self._apirunner("joined",{"channel":channel})
+	def getUsers(self):
+		""" Get a list of users
+			@rtype: dict
+			@return: a dict with the channelnames as keys
+		"""
+		return self.users
+	def getReactor(self):
+		""" get the reactor 
+			@rtype: twisted.internet.reactor
+			@return: the current reactor
+		"""
+		return reactor
+	def getFactory(self):
+		""" get the factory
+			@rtype: BotFactory
+			@return: the current factory
+		"""
+		return self.factory
+	def auth(self, user):
+		"""
+			call this, to see which rights C{user} has
+			@type user: string
+			@param user: the full hostmask of the user
+			@rtype: int
+			@return: the level of access rights (0 = nothing, 10 = everything)
+		"""
+		level=0
+		for mod in self.mods:
+			try:
+				retval=mod.auth(user)
+				if retval > level:
+					level=retval
+			except AttributeError:
+				pass
+		return level
+	
+	def sendmsg(self, channel, msg, encoding="iso-8859-15", fallback="iso-8859-15"):
+		"""
+			call B{only} this to send messages to channels or users
+			it converts the message from iso-8859-15 to a encoding given in the config
+			@type	channel:	string
+			@param	channel:	send the message to this channel or user
+			@type	msg:		string
+			@param	msg:		the message to send
+			@type	encoding:	string
+			@param	encoding:	the encoding of C{msg}
+			@type	fallback:	string
+			@param	fallback:	try this one as encoding for C{msg}, if C{encoding} doesn't work
+		"""
+		try:
+			msg=unicode(msg, encoding).encode(self.getConfig("encoding", "UTF-8", "main"))
+		except UnicodeDecodeError:
+			#self.logger.debug("Unicode Decode Error with String:"+str(msg))
+			#Try with Fallback encoding
+			msg=unicode(msg, fallback).encode(self.getConfig("encoding", "UTF-8", "main"))
+		except UnicodeEncodeError:
+			pass
+			#self.logger.debug("Unicode Encode Error with String:"+str(msg))
+			#use msg as is
+			
+		self.msg(channel, msg)
+		self.privmsg(self.nickname, channel, msg)
+		
+	def sendme(self, channel, action, encoding="iso-8859-15"):
+		"""
+			call B{only} this to send actions (/me) to channels
+			it converts the message from iso-8859-15 to a encoding given in the config
+			@type	channel:	string
+			@param	channel:	send the message to this channel or user
+			@type	action:		string
+			@param	action:		the message to send
+			@type	encoding:	string
+			@param	encoding:	the encoding of C{msg}
+		"""
+		action=unicode(action, encoding).encode(self.getConfig("encoding", "UTF-8", "main"))
+			
+		self.me(channel, action)
+		self.action(self.nickname, channel, action)
+	
+	def reloadModules(self):
+		"""
+			call this to reload all modules
+		"""
+		for chatModule in self.classes:
+			self.logger.info("reloading "+chatModule.__name__)
+			reload(chatModule)
+		for chatMod in self.mods:
+			try:
+				chatMod.stop()
+			except Exception, e:
+				logerror(self.logger, mod.name, e)
+		self.mods=[]
+		self.startMods()	
+	
+	# Callbacks
+	def connectionMade(self):
+		""" 
+			this is called by twisted
+			, when the connection to the irc-server was made
+		"""
+		self.network=self.transport.addr[0]
+		tmp=self.getChannels(self.network)
+		if tmp:
+			self.channels=tmp
+		self.nickname=unicode(self.getConfig("nickname", "OtfBot", 'main', self.network)).encode("iso-8859-1")
+		if len(self.network.split(".")) < 2:
+			nw = self.network
+		else:
+			nw = self.network.split(".")[-2]
+		self.logger = self.logging.getLogger(nw)
+		self.logger.info("made connection to "+self.network)
+		irc.IRCClient.connectionMade(self)
+		for mod in self.mods:
+			mod.setLogger(self.logger)
+			mod.network=self.network
+		self._apirunner("connectionMade")
 
-    def left(self, channel):
-        self.logger.info("left "+channel)
-        del self.users[channel]
-        self.channels.remove(channel)
-        self._apirunner("left",{"channel":channel})
+	def connectionLost(self, reason):
+		""" this is called by twisted,
+			if the connection to the IRC-Server was lost
+			@type reason:	twisted.python.failure.Failure
+		"""
+		#self.logger.info("lost connection: "+str(reason))
+		irc.IRCClient.connectionLost(self)
+		self._apirunner("connectionLost",{"reason": reason})
+	
+	def signedOn(self):
+		""" called by twisted,
+			when we signed on the IRC-Server
+		"""
+		self.logger.info("signed on "+self.network+" as "+self.nickname)
+		channelstojoin=self.channels
+		self.channels=[]
+		for channel in channelstojoin:
+			if(getBoolConfig("enabled", "false", "main", self.network, channel)):
+				self.join(unicode(channel).encode("iso-8859-1"))
+		self._apirunner("signedOn")
 
-    def privmsg(self, user, channel, msg):
-        self._apirunner("privmsg",{"user":user,"channel":channel,"msg":msg})
-        self._apirunner("msg",{"user":user,"channel":channel,"msg":msg})
-        #nick = user.split("!")[0]
-        #if channel == self.nickname and self.auth(nick) > 9:
-        #if msg == "!who":
-        #    self.sendLine("WHO "+channel)
-        #if msg[:6] == "!whois":
-        #    self.sendLine("WHOIS "+msg[7:])
-        #if msg == "!user":
-        #    self.sendmsg(channel,str(self.users))
+	def joined(self, channel):
+		""" called by twisted,
+			if we joined a channel
+			@param channel: the channel we joined
+			@type channel: string
+		"""
+		self.logger.info("joined "+channel)
+		self.channels.append(channel)
+		self.users[channel]={}
+		self._apirunner("joined",{"channel":channel})
 
-    def irc_unknown(self, prefix, command, params):
-        #self.logger.debug(str(prefix)+" : "+str(command)+" : "+str(params))
-        #parse /names-list which is sent when joining a channel
-        if command == "RPL_NAMREPLY":
-            for nick in params[3].strip().split(" "):
-                if nick[0] in "@%+!":
-                    s=nick[0]
-                    nick=nick[1:]
-                else:
-                    s=" "
-                self.users[params[2]][nick]={'modchar':s}
-        self._apirunner("irc_unknown",{"prefix":prefix,"command":command,"params":params})
+	def left(self, channel):
+		""" called by twisted,
+			if we left a channel
+			@param channel: the channel we left
+			@type channel: string
+		"""
+		self.logger.info("left "+channel)
+		del self.users[channel]
+		self.channels.remove(channel)
+		self._apirunner("left",{"channel":channel})
 
-    def noticed(self, user, channel, msg):
-        self._apirunner("noticed",{"user":user,"channel":channel,"msg":msg})
-                
-    def action(self, user, channel, message):
-        self._apirunner("action",{"user":user,"channel":channel,"message":message})
+	def privmsg(self, user, channel, msg):
+		""" called by twisted,
+			if we received a message
+			@param user: the user, which send the message
+			@type user: string
+			@param channel: the channel to which the message was sent or my nickname if it was a private message
+			@type channel: string
+			@param msg: the message
+			@type msg: string
+		"""
+		self._apirunner("privmsg",{"user":user,"channel":channel,"msg":msg})
+		self._apirunner("msg",{"user":user,"channel":channel,"msg":msg})
+		#nick = user.split("!")[0]
+		#if channel == self.nickname and self.auth(nick) > 9:
+		#if msg == "!who":
+		#	self.sendLine("WHO "+channel)
+		#if msg[:6] == "!whois":
+		#	self.sendLine("WHOIS "+msg[7:])
+		#if msg == "!user":
+		#	self.sendmsg(channel,str(self.users))
 
-    def modeChanged(self, user, channel, set, modes, args):
-        self._apirunner("modeChanged",{"user":user,"channel":channel,"set":set,"modes":modes,"args":args})
-        i=0
-        for arg in args:
-            if modes[i] in modchars.keys() and set == True:
-                if modcharvals[modchars[modes[i]]] > modcharvals[self.users[channel][arg]['modchar']]:
-                    self.users[channel][arg]['modchar'] = modchars[modes[i]]
-            elif modes[i] in modchars.keys() and set == False:
-                #FIXME: ask for the real mode
-                self.users[channel][arg]['modchar'] = ' '
-            i=i+1
+	def irc_unknown(self, prefix, command, params):
+		""" called by twisted
+			for every line that has no own callback
+		"""
+		#self.logger.debug(str(prefix)+" : "+str(command)+" : "+str(params))
+		#parse /names-list which is sent when joining a channel
+		if command == "RPL_NAMREPLY":
+			for nick in params[3].strip().split(" "):
+				if nick[0] in "@%+!":
+					s=nick[0]
+					nick=nick[1:]
+				else:
+					s=" "
+				self.users[params[2]][nick]={'modchar':s}
+		self._apirunner("irc_unknown",{"prefix":prefix,"command":command,"params":params})
 
-    def userKicked(self, kickee, channel, kicker, message):
-        self._apirunner("userKicked",{"kickee":kickee,"channel":channel,"kicker":kicker,"message":message})
+	def noticed(self, user, channel, msg):
+		""" called by twisted,
+			if we got a notice
+			@param user: the user which send the notice
+			@type user: string
+			@param channel: the channel to which the notice was sent (could be our nick, if the message was only sent to us)
+			@type channel: string
+			@param msg: the message
+			@type msg: string
+		"""
+		self._apirunner("noticed",{"user":user,"channel":channel,"msg":msg})
+				
+	def action(self, user, channel, message):
+		""" called by twisted,
+			if we received a action
+			@param user: the user which send the action
+			@type user: string
+			@param channel: the channel to which the action was sent (could be our nick, if the message was only sent to us)
+			@type channel: string
+			@param msg: the message
+			@type msg: string
+		"""		
+		self._apirunner("action",{"user":user,"channel":channel,"message":message})
 
-    def userJoined(self, user, channel):
-        self._apirunner("userJoined",{"user":user,"channel":channel})
-        self.users[channel][user.split("!")[0]]={'modchar':' '}
+	def modeChanged(self, user, channel, set, modes, args):
+		""" called by twisted
+			if a usermode was changed
+		"""
+		self._apirunner("modeChanged",{"user":user,"channel":channel,"set":set,"modes":modes,"args":args})
+		i=0
+		for arg in args:
+			if modes[i] in modchars.keys() and set == True:
+				if modcharvals[modchars[modes[i]]] > modcharvals[self.users[channel][arg]['modchar']]:
+					self.users[channel][arg]['modchar'] = modchars[modes[i]]
+			elif modes[i] in modchars.keys() and set == False:
+				#FIXME: ask for the real mode
+				self.users[channel][arg]['modchar'] = ' '
+			i=i+1
 
-    def userLeft(self, user, channel):
-        self._apirunner("userLeft",{"user":user,"channel":channel})
-        del self.users[channel][user.split("!")[0]]
+	def userKicked(self, kickee, channel, kicker, message):
+		""" called by twisted,
+			if a user was kicked
+		"""
+		self._apirunner("userKicked",{"kickee":kickee,"channel":channel,"kicker":kicker,"message":message})
 
-    def userQuit(self, user, quitMessage):
-        self._apirunner("userQuit",{"user":user,"quitMessage":quitMessage})
-        for chan in self.users:
-            if self.users[chan].has_key(user):
-                del self.users[chan][user]
+	def userJoined(self, user, channel):
+		""" called by twisted,
+			if a C{user} joined the C{channel}
+		"""
+		self._apirunner("userJoined",{"user":user,"channel":channel})
+		self.users[channel][user.split("!")[0]]={'modchar':' '}
 
-    def yourHost(self, info):
-        pass
-    
-    #def ctcpQuery(self, user, channel, messages):
-    #    (query,t) = messages[0]
-    #    answer = None
-    #    #if query == "VERSION":
-    #    #    answer = "chatBot - a python IRC-Bot"
-    #    if answer: 
-    #        self.ctcpMakeReply(user.split("!")[0], [(query,answer)])
-    #        self.logger.info("Answered to CTCP "+query+" Request from "+user.split("!")[0])
-        
-    def userRenamed(self, oldname, newname):
-        for chan in self.users:
-            if self.users[chan].has_key(oldname):
-                self.users[chan][newname]=self.users[chan][oldname]
-                del self.users[chan][oldname]
-        self._apirunner("userRenamed",{"oldname":oldname,"newname":newname})
+	def userLeft(self, user, channel):
+		""" called by twisted,
+			if a C{user} left the C{channel}
+		"""
+		self._apirunner("userLeft",{"user":user,"channel":channel})
+		del self.users[channel][user.split("!")[0]]
 
-    def topicUpdated(self, user, channel, newTopic):
-        self._apirunner("topicUpdated",{"user":user,"channel":channel,"newTopic":newTopic})
+	def userQuit(self, user, quitMessage):
+		""" called by twisted,
+			of a C{user} quits
+		"""
+		self._apirunner("userQuit",{"user":user,"quitMessage":quitMessage})
+		for chan in self.users:
+			if self.users[chan].has_key(user):
+				del self.users[chan][user]
 
-    def lineReceived(self, line):
-        #self.logger.debug(str(line))
-        # adding a correct hostmask for join, part and quit
-        if line.split(" ")[1] == "JOIN" and line[1:].split(" ")[0].split("!")[0] != self.nickname:
-            self.userJoined(line[1:].split(" ")[0],string.lower(line.split(" ")[2][1:]))
-            #self.joined(line[1:].split(" ")[0],line.split(" ")[2][1:])
-        elif line.split(" ")[1] == "PART" and line[1:].split(" ")[0].split("!")[0] != self.nickname:
-            self.userLeft(line[1:].split(" ")[0],line.split(" ")[2])
-        elif line.split(" ")[1] == "QUIT":
-            self.userQuit(line[1:].split(" ")[0],line.split("QUIT :")[1])
-        else:
-            irc.IRCClient.lineReceived(self,line)
+	def yourHost(self, info):
+		""" called by twisted
+			with information about the IRC-Server we are connected to
+		"""
+		pass
+	
+	#def ctcpQuery(self, user, channel, messages):
+	#	(query,t) = messages[0]
+	#	answer = None
+	#	#if query == "VERSION":
+	#	#	answer = "chatBot - a python IRC-Bot"
+	#	if answer: 
+	#		self.ctcpMakeReply(user.split("!")[0], [(query,answer)])
+	#		self.logger.info("Answered to CTCP "+query+" Request from "+user.split("!")[0])
+		
+	def userRenamed(self, oldname, newname):
+		""" called by twisted,
+			if a user changed his nick
+		"""
+		for chan in self.users:
+			if self.users[chan].has_key(oldname):
+				self.users[chan][newname]=self.users[chan][oldname]
+				del self.users[chan][oldname]
+		self._apirunner("userRenamed",{"oldname":oldname,"newname":newname})
 
+	def topicUpdated(self, user, channel, newTopic):
+		""" called by twisted
+			if the topic was updated
+		"""
+		self._apirunner("topicUpdated",{"user":user,"channel":channel,"newTopic":newTopic})
+
+	def lineReceived(self, line):
+		""" called by twisted
+			for every line which was received from the IRC-Server
+		"""
+		#self.logger.debug(str(line))
+		# adding a correct hostmask for join, part and quit
+		if line.split(" ")[1] == "JOIN" and line[1:].split(" ")[0].split("!")[0] != self.nickname:
+			self.userJoined(line[1:].split(" ")[0],string.lower(line.split(" ")[2][1:]))
+			#self.joined(line[1:].split(" ")[0],line.split(" ")[2][1:])
+		elif line.split(" ")[1] == "PART" and line[1:].split(" ")[0].split("!")[0] != self.nickname:
+			self.userLeft(line[1:].split(" ")[0],line.split(" ")[2])
+		elif line.split(" ")[1] == "QUIT":
+			self.userQuit(line[1:].split(" ")[0],line.split("QUIT :")[1])
+		else:
+			irc.IRCClient.lineReceived(self,line)
+
 class BotFactory(protocol.ReconnectingClientFactory):
-    """The Factory for the Bot"""
-    protocol = Bot
-    instances = {}
+	"""The Factory for the Bot"""
+	protocol = Bot
+	instances = {}
 
-    def _addnetwork(self,addr,nw):
-        self.instances[addr] = nw
+	def _addnetwork(self,addr,nw):
+		self.instances[addr] = nw
 
-    def _removenetwork(self,addr):
-        if self.instances.has_key(addr):
-            del self.instances[addr]
-    
-    def _getnetwork(self,addr):
-        return self.instances[addr]
+	def _removenetwork(self,addr):
+		if self.instances.has_key(addr):
+			del self.instances[addr]
+	
+	def _getnetwork(self,addr):
+		return self.instances[addr]
 
-    def _getnetworkslist(self):
-        return self.instances.keys()
+	def _getnetworkslist(self):
+		return self.instances.keys()
 
-    def _checkforshutdown(self):
-        if len(self.instances)==0:
-            corelogger.info("Not Connected to any network. Shutting down.")
-            #TODO: add sth to stop modules
-            reactor.stop()
-    
-    def clientConnectionLost(self, connector, reason):
-        clean = error.ConnectionDone()
-        if reason.getErrorMessage() == str(clean):
-            self._removenetwork(connector.host)
-            self._checkforshutdown()
-            corelogger.info("Cleanly disconnected from "+connector.host)
-        else:
-            corelogger.error("Disconnected from "+connector.host+": "+str(reason.getErrorMessage())+".")
-        #    connector.connect()
-        
-    def clientConnectionFailed(self, connector, reason):
-        corelogger.error("Connection to "+connector.host+" failed: "+str(reason.getErrorMessage()))
-        self._removenetwork(connector.host)
-        self._checkforshutdown()
-    
-    def buildProtocol(self,addr):
-        proto=protocol.ReconnectingClientFactory.buildProtocol(self,addr)
-        self._addnetwork(addr.host, proto)
-        return proto
+	def _checkforshutdown(self):
+		if len(self.instances)==0:
+			corelogger.info("Not Connected to any network. Shutting down.")
+			#TODO: add sth to stop modules
+			reactor.stop()
+	
+	def clientConnectionLost(self, connector, reason):
+		clean = error.ConnectionDone()
+		if reason.getErrorMessage() == str(clean):
+			self._removenetwork(connector.host)
+			self._checkforshutdown()
+			corelogger.info("Cleanly disconnected from "+connector.host)
+		else:
+			corelogger.error("Disconnected from "+connector.host+": "+str(reason.getErrorMessage())+".")
+		#	connector.connect()
+		
+	def clientConnectionFailed(self, connector, reason):
+		corelogger.error("Connection to "+connector.host+" failed: "+str(reason.getErrorMessage()))
+		self._removenetwork(connector.host)
+		self._checkforshutdown()
+	
+	def buildProtocol(self,addr):
+		proto=protocol.ReconnectingClientFactory.buildProtocol(self,addr)
+		self._addnetwork(addr.host, proto)
+		return proto
 
 try:
-    configfile=parser.configfile
+	configfile=parser.configfile
 except AttributeError:
-    configfile="config.xml"
+	configfile="config.xml"
 theconfig=loadConfig(configfile)
 
 # writing PID-File
@@ -485,18 +638,18 @@
 networks=theconfig.getNetworks()
 connections={}
 if networks:
-    f = BotFactory()
-    for network in networks:
-        if(getBoolConfig('enabled', 'unset', 'main', network)):
-            #channels=theconfig.getChannels(network)
-            #if not channels:
-            #    channels=[]
-            #for channel in channels:
-            #    if(not getBoolConfig('enabled','unset','main', network)):
-            #        channels.remove(channel)
-            if (getBoolConfig('ssl','False','main',network)):
-                s = ssl.ClientContextFactory()
-                connections[network]=reactor.connectSSL(unicode(network).encode("iso-8859-1"), int(getConfig('port','6697','main',network)), f,s);
-            else:
-                connections[network]=reactor.connectTCP(unicode(network).encode("iso-8859-1"), int(getConfig('port','6667','main',network)), f)
-    reactor.run()
+	f = BotFactory()
+	for network in networks:
+		if(getBoolConfig('enabled', 'unset', 'main', network)):
+			#channels=theconfig.getChannels(network)
+			#if not channels:
+			#	channels=[]
+			#for channel in channels:
+			#	if(not getBoolConfig('enabled','unset','main', network)):
+			#		channels.remove(channel)
+			if (getBoolConfig('ssl','False','main',network)):
+				s = ssl.ClientContextFactory()
+				connections[network]=reactor.connectSSL(unicode(network).encode("iso-8859-1"), int(getConfig('port','6697','main',network)), f,s);
+			else:
+				connections[network]=reactor.connectTCP(unicode(network).encode("iso-8859-1"), int(getConfig('port','6667','main',network)), f)
+	reactor.run()

Modified: trunk/scheduler.py
===================================================================
--- trunk/scheduler.py	2007-06-23 22:34:59 UTC (rev 121)
+++ trunk/scheduler.py	2007-06-24 11:36:42 UTC (rev 122)
@@ -18,19 +18,41 @@
 # 
 # (c) 2007 by Robert Weidlich
 
+""" Contains a Wrapperclass for the twisted Scheduler """
+
 class Scheduler:
-    """Wrapper class for the scheduling functions of twisted.internet.reactor.ReactorTime"""
-    def __init__(self,reactor):
-        self.reactor=reactor
-    def callLater(self,time,function,*args,**kwargs):
-        """executes the given function after time seconds with arguments (*args) and keyword arguments (**kwargs)"""
-        self.reactor.callLater(time,function,*args,**kwargs)
+	"""Wrapper class for the scheduling functions of twisted.internet.reactor.ReactorTime"""
+	def __init__(self,reactor):
+		"""
+			@type reactor: twisted.internet.reactor
+		"""
+		self.reactor=reactor
+	def callLater(self,time,function,*args,**kwargs):
+		""" executes C{function} after C{time} seconds with arguments C{*args} and keyword arguments C{**kwargs}
+			@param time: seconds to wait before executing C{function}
+			@type time: int
+			@param function: the function to call
+			@type function: callable
+			@param *args: arguments for the function
+			@type *args: tuple
+			@param **kwargs: keyworded arguments for the function
+			@type **kwargs: dict
+		"""
+		self.reactor.callLater(time,function,*args,**kwargs)
 
-    def callPeriodic(self,delay,function,kwargs={}):
-        """executes the given function every delay seconds with keyword arguments (**kwargs)"""
-        def func(delay,function,**kwargs):
-            args=(delay,function)
-            if function(**kwargs):
-                self.reactor.callLater(delay,func,*args,**kwargs)
-        args=(delay,function)
-        self.reactor.callLater(delay,func,*args,**kwargs)
+	def callPeriodic(self,delay,function,kwargs={}):
+		""" executes C{function} every C{delay} seconds with keyword arguments C{**kwargs}
+			@param delay: the delay between two runs of the C{function}
+			@type delay: int
+			@param function: the function to be called
+			@type function: callable
+			@param kwargs: the keyworded arguments for the function
+			@type kwargs: dict
+			@note: add the possibility to give a *args-tuple (need to know how to merge two tuples)
+		"""
+		def func(delay,function,**kwargs):
+			args=(delay,function)
+			if function(**kwargs):
+				self.reactor.callLater(delay,func,*args,**kwargs)
+		args=(delay,function)
+		self.reactor.callLater(delay,func,*args,**kwargs)




Mehr Informationen über die Mailingliste Otfbot-dev