changeset 2067:3ca2b7065a05

Jabber bot - the beginning. Ommited the necessary config file, because it currently holds private information about jabber account used for testing. Will be added later.
author Karol 'grzywacz' Nowak <grzywacz@sul.uni.lodz.pl>
date Thu, 31 May 2007 01:05:09 +0200
parents b73b2b885b02
children 7e2a9b7d2bc6
files MoinMoin/jabber/__init__.py MoinMoin/jabber/main.py MoinMoin/jabber/xmppbot.py
diffstat 3 files changed, 202 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/jabber/__init__.py	Thu May 31 01:05:09 2007 +0200
@@ -0,0 +1,11 @@
+# -*- coding: iso-8859-1 -*-
+"""
+    MoinMoin - jabber bot
+
+    This is a bot for notification and simple editing
+    operations. Developed as a Google Summer of Code 
+    project.
+
+@copyright: 2007 by Karol Nowak <grywacz@gmail.com>
+@license: GNU GPL, see COPYING for details.
+"""
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/jabber/main.py	Thu May 31 01:05:09 2007 +0200
@@ -0,0 +1,30 @@
+# -*- coding: iso-8859-1 -*-
+"""
+    MoinMoin - jabber bot main file
+
+    This is a bot for notification and simple editing
+    operations. Developed as a Google Summer of Code 
+    project.
+
+@copyright: 2007 by Karol Nowak <grywacz@gmail.com>
+@license: GNU GPL, see COPYING for details.
+"""
+
+import sys
+from config import JabberConfig
+from xmppbot import XMPPBot
+from Queue import Queue
+
+def main():
+    commands = Queue()
+    results = Queue()
+    
+    try:
+        bot = XMPPBot(JabberConfig, commands, results)
+        bot.start()
+    
+    except KeyboardInterrupt, i:
+        print i
+        sys.exit(0)
+
+if __name__ == "__main__": main()
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/jabber/xmppbot.py	Thu May 31 01:05:09 2007 +0200
@@ -0,0 +1,161 @@
+# -*- coding: iso-8859-1 -*-
+"""
+    MoinMoin - a XMPP bot
+
+    This is a bot for notification and simple editing
+    operations. Developed as a Google Summer of Code 
+    project.
+
+@copyright: 2007 by Karol Nowak <grywacz@gmail.com>
+@license: GNU GPL, see COPYING for details.
+"""
+
+import time
+from threading import Thread
+
+from pyxmpp.client import Client
+from pyxmpp.jid import JID
+from pyxmpp.streamtls import TLSSettings
+from pyxmpp.message import Message
+from pyxmpp.presence import Presence
+
+class XMPPBot(Client, Thread):
+    """A simple XMPP bot"""
+    
+    def __init__(self, config, from_commands, to_commands):
+        """A constructor.
+        
+        @param from_commands: a Queue object used to send commands to other (xmlrpc) threads
+        @param to_commands: a Queue object used to receive commands from other threads
+        """
+        
+        Thread.__init__(self)
+        
+        self.from_commands = from_commands
+        self.to_commands = to_commands   
+        jid = "%s@%s/%s" % (config.node, config.server, config.resource)
+        
+        self.config = config
+        self.jid = JID(node_or_jid = jid, domain = config.server, resource = config.resource)
+        self.tlsconfig = TLSSettings(require = True, verify_peer = False)
+        Client.__init__(self, self.jid, self.config.password, self.config.server, tls_settings = self.tlsconfig)
+            
+    def run(self):
+        """Start the bot - enter the event loop"""
+        
+        if self.config.verbose == True:
+            self.log("Starting the jabber bot.")
+            
+        self.connect()
+        self.loop()
+        
+    def handle_message(self, message):
+        """Handles incoming messages"""
+        
+        if self.config.verbose == True:
+            self.log( "Received a message from %s." % (message.get_from_jid().as_utf8(),) )
+            
+        text = message.get_body()
+        sender = message.get_from_jid()
+        command = text.split()
+        
+        # Ignore empty commands
+        if len(command) == 0:
+            return
+        
+        response = self.reply_help()
+        
+        if not response == u"":
+            message = Message(to_jid = sender, body = response, stanza_type=u"chat")
+            self.get_stream().send(message)
+        
+    def handle_presence(self):
+        pass
+        
+    def reply_help(self):
+        """Constructs a generic help message
+        
+        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!)."""
+    
+    def check_availability(self, jid, type):
+        """Checks if a given contacts has its availability set to "type".
+        
+        Possible values of the "type" argument are: away, chat, dnd, xa"""
+        
+        if self.roster is None or jid not in self.roster:
+            return False
+        
+        # XXX: finish this!    
+    
+    def log(self, message):
+        """Logs a message and its timestamp"""
+        
+        t = time.localtime( time.time() )
+        print time.strftime("%H:%M:%S", t), message
+    
+    def authenticated(self):
+        """Called when authentication succeedes"""
+        
+        if self.config.verbose == True:
+            self.log("Authenticated.")
+            
+    def authorized(self):
+        """Called when authorization succeedes"""
+        
+        if self.config.verbose == True:
+            self.log("Authorized.")
+        
+        stream = self.get_stream()
+        stream.set_message_handler("normal", self.handle_message)
+        stream.set_presence_handler(None, self.handle_presence, "jabber:client", 0)
+        
+        self.request_session()
+  #      self.request_roster()
+        
+        # Make the bot oficially available
+  #      p = Presence(from_jid = stream.me, stanza_type=u"available", show=u"chat", status=self.config.status)
+  #      stream.send(p)
+            
+    def connected(self):
+        """Called when connections has been established"""
+        
+        if self.config.verbose == True:
+            self.log("Connected.")
+            
+    def disconnected(self):
+        """Called when disconnection occurs"""
+        
+        if self.config.verbose == True:
+            self.log("Disconnected.")
+            
+    def roster_updated(self, item = None):
+        """Called when roster gets updated"""
+        
+        if self.config.verbose == True:
+            self.log("Updating roster.")
+            
+ #   def session_started(self):
+ #       """Called when session has been successfully started"""
+ #       
+ #       if self.config.verbose == True:
+ #           self.log("Session started.")
+            
+    def stream_closed(self, stream):
+        """Called when stream closes"""
+        
+        if self.config.verbose == True:
+            self.log("Stream closed.")
+            
+    def stream_created(self, stream):
+        """Called when stream gets created"""
+        
+        if self.config.verbose == True:
+            self.log("Stream created.")
+            
+    def stream_error(self, error):
+        """Called when stream error gets received"""
+        
+        if self.config.verbose == True:
+            self.log("Received a stream error.")