changeset 2115:260d0dbded44

Checkpoint commit, to record progress on implementation of user commands.
author Karol 'grzywacz' Nowak <grzywacz@sul.uni.lodz.pl>
date Tue, 12 Jun 2007 02:34:50 +0200
parents 38ef27ddaa66
children 7f579f5fd44b
files jabberbot/commands.py jabberbot/xmppbot.py
diffstat 2 files changed, 99 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/jabberbot/commands.py	Tue Jun 12 00:29:47 2007 +0200
+++ b/jabberbot/commands.py	Tue Jun 12 02:34:50 2007 +0200
@@ -25,3 +25,43 @@
     """Class representing a request to remove a jid from roster"""
     def __init__(self, jid):
         self.jid = jid
+
+# XMPP <-> XML RPC commands
+# These commands are passed in both directions, with added data
+# payload when they return to the XMPP code. Naming convention
+# follows method names defined by the Wiki RPC Interface v2.
+
+class BaseDataCommand(object):
+    """Base class for all commands used by the XMPP component.
+    
+    It has to support an optional data payload and store JID the
+    request has come from and provide a help string for its parameters.
+    """
+    
+    # Description of what the command does
+    description = u""
+    
+    # Parameter list in a human-readable format
+    parameter_list = u""
+    
+    def __init__(self, jid):
+        self.jid = jid
+        self.payload = None
+        
+class GetPage(BaseDataCommand):
+    
+    description = u"retrieve raw content of a named page"
+    parameter_list = u"pagename"
+    
+    def __init__(self, jid, pagename):
+        BaseDataCommand.__init__(self, jid)
+        self.pagename = pagename
+        
+class GetPageHTML(BaseDataCommand):
+    
+    description = u"retrieve HTML-formatted content of a named page"
+    parameter_list = u"pagename"
+    
+    def __init__(self, jid, pagename):
+        BaseDataCommand.__init__(self, jid)
+        self.pagename = pagename
\ No newline at end of file
--- a/jabberbot/xmppbot.py	Tue Jun 12 00:29:47 2007 +0200
+++ b/jabberbot/xmppbot.py	Tue Jun 12 02:34:50 2007 +0200
@@ -16,6 +16,7 @@
 from pyxmpp.message import Message
 from pyxmpp.presence import Presence
 
+import jabberbot.commands as cmd
 from jabberbot.commands import NotificationCommand, AddJIDToRosterCommand
 from jabberbot.commands import RemoveJIDFromRosterCommand
 
@@ -111,9 +112,16 @@
         
         # A dictionary of contact objects, ordered by bare JID
         self.contacts = { }
+
+        self.known_xmlrpc_cmds = [cmd.GetPage, cmd.GetPageHTML] 
+        self.internal_commands = ["ping", "help"]
         
-        Client.__init__(self, self.jid, config.xmpp_password, config.xmpp_server, tls_settings=self.tlsconfig)
-            
+        self.xmlrpc_commands = {}
+        for command, name in [(command, command.__name__) for command in self.known_xmlrpc_cmds]:
+            self.xmlrpc_commands[name] = command
+        
+        Client.__init__(self, self.jid, config.xmpp_password, config.xmpp_server, tls_settings=self.tlsconfig)   
+    
     def run(self):
         """Start the bot - enter the event loop"""
         
@@ -227,11 +235,54 @@
         if not command:
             return
         
-        response = self.reply_help()
+        if command[0] in self.internal_commands:
+            response = self.handle_internal_command(command)
+        elif command[0] in self.xmlrpc_commands.keys():
+            response = self.handle_xmlrpc_command(command)
+        else:
+            response = self.reply_help()
         
         if not response == u"":
             self.send_message(sender, response)
             
+    def handle_internal_command(self, command):
+        if command[0] == "ping":
+            return "pong"
+        elif command[0] == "help":
+            if len(command) == 1:
+                return self.reply_help()
+            else:
+                return self.help_on(command[1])
+        else:
+            return self.reply_help()
+        
+    def help_on(self, command):
+        if command == "help":
+            return u"""The "help" command prints a short, helpful message about a given topic or function.\n\nUsage: help [topic_or_function]"""
+        
+        elif command == "ping":
+            return u"""The "ping" command returns a "pong" message as soon as it's received."""
+        
+        # Here we have to deal with help messages of external (xmlrpc) commands
+        else:
+            classobj = self.xmlrpc_commands[command]
+            help_str = u"%s - %s\n\nUsage: %s"
+            return help_str % (command, classobj.description, classobj.parameter_list)
+        
+        
+    def handle_xmlrpc_command(self, command):
+        command_class = self.xmlrpc_commands[command[0]]
+        
+        try:
+            instance = command_class.__new__(command_class)
+            instance.__init__(instance, *command[1:])
+            self.from_commands.put_nowait(instance)
+            
+        # This happens when user specifies wrong parameters
+        except TypeError:
+            help = u"You've specified a wrong parameter list. The call should look like:\n\n%s"
+            return help % (command_class.get_invocation_help(), )
+            
     def handle_unsubscribed_presence(self, stanza):
         """Handles unsubscribed presence stanzas"""
         
@@ -334,7 +385,11 @@
         
         It's sent in response to an uknown message or the "help" command."""
         
-        return u"""Hello there! I'm a MoinMoin Notification Bot. Too bad I can't say anything more (yet!)."""
+        help = u"""Hello there! I'm a MoinMoin Notification Bot. Available commands:\n\n%s\n%s"""
+        internal = ", ".join(self.internal_commands)
+        xmlrpc = ", ".join(self.xmlrpc_commands.keys())
+        
+        return help % (internal, xmlrpc)
     
     def log(self, message):
         """Logs a message and its timestamp"""