irc.py
changeset 6 614161f85d9b
parent 4 34d7897bd0f5
child 9 75cc996c6ba1
--- a/irc.py	Thu Mar 20 18:47:58 2008 +0200
+++ b/irc.py	Thu Mar 20 19:46:04 2008 +0200
@@ -1,6 +1,7 @@
 from twisted.words.protocols import irc
 from twisted.internet import protocol
 from twisted.python import log
+import traceback
 
 import buffer
 
@@ -10,6 +11,10 @@
 USERNAME        = "fixme"
 CHANNEL         = "#fixme-test"
 
+class ReplyException (Exception) :
+    def __init__ (self, reply) :
+        self.reply = reply
+
 class BotProtocol (irc.IRCClient, object) :
     """
         Fixme IRC bot
@@ -23,6 +28,8 @@
     def connectionMade (self) :
         log.msg("Connected")
         super(BotProtocol, self).connectionMade()
+        
+        self.nexus = self.factory.nexus
 
     def connectionLost (self, reason) :
         log.msg("Connection lost: %s" % reason)
@@ -57,5 +64,76 @@
 
     def moduleDisconnected (self, module, reason) :
         self.send("{modules.%s} disconnected: %s" % (module.name, reason))
+    
+    class _noDefault : pass
 
+    def _lookupCommand (self, command, default=_noDefault) :
+        if '.' in command :
+            raise ReplyException("No support for module commands yet :P")
+        else :
+            method = getattr(self, "cmd_%s" % command, None)
 
+        if method :
+            return method
+        elif default is self._noDefault :
+            raise ReplyException("No such command '%s'. See `help commands'" % command)
+        else :
+            return default
+
+    def privmsg (self, user, channel, message) :
+        if message.lower().startswith(self.nickname.lower()) :
+            me, command = message.split(":", 1)
+
+            args = command.strip().split()
+            command = args.pop(0)
+            
+            try :
+                method = self._lookupCommand(command)
+
+                reply = method(*args)
+
+                if reply :
+                    self.send(reply)
+            
+            except ReplyException, e :
+                self.send(e.reply)
+
+            except Exception, e :
+                self.send("Error: %s: %s" % (e.__class__.__name__, e))
+                traceback.print_exc()
+
+    def cmd_help (self, cmd="help") :
+        """help <command|module> - Display help about the given command or module"""
+
+        method = self._lookupCommand(cmd, None)
+        
+        if method :
+            return method.__doc__
+        else :
+            try :
+                module, addr = self.nexus.getModuleInfo(cmd)
+
+                return "%s is version %d from %s:%d. Events: %s. See `commands %s' for a list of commands" % (module.name, module.version, addr.host, addr.port, ', '.join(module.event_types), module.name)
+
+            except KeyError :
+                raise ReplyException("No command/module called `%s'. See `help commands'" % cmd)
+
+    def cmd_commands (self, module=None) :
+        """commands [<module>] - Show primary commands, or commands in the given module (see `help modules')"""
+
+        if module :
+            raise ReplyException("No support for module commands yet :P")
+        else :
+            return "Commands: %s" % ', '.join(
+                attr_name.split('_', 1)[1]
+                for attr_name in BotProtocol.__dict__.iterkeys()
+                if attr_name.startswith("cmd_")
+            )
+
+    def cmd_modules (self) :
+        """modules - Show a list of connected modules"""
+
+        return "Modules: %s" % ', '.join(
+            module.name
+            for module in self.nexus.getModules()
+        )