changeset 2635:8ec6cc1a909f

Change argument passing in notifications; some pylint and event.name fixes too
author Karol 'grzywacz' Nowak <grzywacz@sul.uni.lodz.pl>
date Thu, 26 Jul 2007 04:38:12 +0200
parents 53a79ea2ad93
children e76789b0e537
files MoinMoin/events/jabbernotify.py jabberbot/commands.py jabberbot/oob.py jabberbot/xmlrpcbot.py jabberbot/xmppbot.py
diffstat 5 files changed, 104 insertions(+), 93 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/events/jabbernotify.py	Thu Jul 26 04:19:37 2007 +0200
+++ b/MoinMoin/events/jabbernotify.py	Thu Jul 26 04:38:12 2007 +0200
@@ -72,7 +72,7 @@
     names = set()
     request = event.request
     page = Page(request, event.pagename)
-    event_name = event.__class__.__name__
+    event_name = event.name
 
     subscribers = page.getSubscribers(request, return_users=1)
     notification.filter_subscriber_list(event, subscribers, True)
@@ -131,7 +131,7 @@
 
     jids = []
     user_ids = getUserList(event.request)
-    event_name = event.__class__.__name__
+    event_name = event.name
 
     email = event.user.email or u"NOT SET"
     sitename = event.request.cfg.sitename
@@ -169,17 +169,21 @@
         if recipients:
             return notification.Success(recipients)
 
-def send_notification(request, jids, message, subject=""):
+def send_notification(request, jids, message, subject="", url_list=[]):
     """ Send notifications for a single language.
 
-    @param comment: editor's comment given when saving the page
     @param jids: an iterable of Jabber IDs to send the message to
+    @param message: message text
+    @param subject: subject of the message, makes little sense for chats
+    @param url_list: a list of dicts containing URLs and their descriptions
+
     """
     _ = request.getText
     server = request.cfg.notification_server
 
     try:
-        server.send_notification(request.cfg.secret, jids, message, subject)
+        cmd_data = {'text': message, 'subject': subject, 'url_list': url_list}
+        server.send_notification(request.cfg.secret, jids, cmd_data)
         return True
     except xmlrpclib.Error, err:
         ev.logger.error(_("XML RPC error: %s"), str(err))
--- a/jabberbot/commands.py	Thu Jul 26 04:19:37 2007 +0200
+++ b/jabberbot/commands.py	Thu Jul 26 04:38:12 2007 +0200
@@ -12,7 +12,7 @@
 # First, XML RPC -> XMPP commands
 class NotificationCommand:
     """Class representing a notification request"""
-    def __init__(self, jids, text, subject="", async=True):
+    def __init__(self, jids, notification, msg_type="message", async=True):
         """A constructor
 
         @param jids: a list of jids to sent this message to
@@ -23,25 +23,20 @@
         if type(jids) != list:
             raise Exception("jids argument must be a list!")
 
+        self.notification = notification
         self.jids = jids
-        self.text = text
-        self.subject = subject
         self.async = async
+        self.msg_type = msg_type
 
 class NotificationCommandI18n(NotificationCommand):
     """Notification request that should be translated by the XMPP bot"""
-    def __init__(self, jids, text, data={}, subject="", async=True):
+    def __init__(self, jids, notification, msg_type="message", async=True):
         """A constructor
 
         Params as in NotificationCommand.
 
-        @param text: text to send, use %(foo)s syntax to interpolate it with data
-        @param data: dictionary of strings to interpolate into a translated message
-        @type data: dict
-
         """
-        NotificationCommand.__init__(self, jids, text, subject, async)
-        self.data = data
+        NotificationCommand.__init__(self, jids, notification, msg_type, async)
 
     def translate(self, gettext_func):
         """Translate the message using a provided gettext function
@@ -49,7 +44,10 @@
         @param gettext_func: a unary gettext function
         @return: translated message
         """
-        return gettext_func(self.text) % self.data
+        if self.notification.has_key('data'):
+            return gettext_func(self.notification['text']) % self.notification['data']
+        else:
+            return gettext_func(self.notification['text'])
 
 class AddJIDToRosterCommand:
     """Class representing a request to add a new jid to roster"""
--- a/jabberbot/oob.py	Thu Jul 26 04:19:37 2007 +0200
+++ b/jabberbot/oob.py	Thu Jul 26 04:38:12 2007 +0200
@@ -1,7 +1,7 @@
 # -*- coding: iso-8859-1 -*-
 """
     MoinMoin - Out Of Band Data (XEP-066) implementation
-    
+
     This is used by the xmpp thread to send URIs to clients
     in a structured manner.
 
@@ -14,15 +14,15 @@
 
 def add_urls(stanza, data):
     """Adds a URL to a message or presence stanza
-    
+
     Adds an <x> element qualified by the jabber:x:oob namespace
     to the stanza's payload
-    
+
     @param stanza: message or presence stanza to add the URL info to
     @type stanza: pyxmpp.message.Message or pyxmpp.presence.Presence
     @param data: a list of dictionaries containing (url, description), as unicode
     @type data: list
-    
+
     """
     if not (isinstance(stanza, Presence) or isinstance(stanza, Message)):
         raise TypeError("Stanza must be either of type Presence or Message!")
--- a/jabberbot/xmlrpcbot.py	Thu Jul 26 04:19:37 2007 +0200
+++ b/jabberbot/xmlrpcbot.py	Thu Jul 26 04:38:12 2007 +0200
@@ -12,13 +12,60 @@
 
 import jabberbot.commands as cmd
 from jabberbot.multicall import MultiCall
-from jabberbot.i18n import get_text
+
 
 class ConfigurationError(Exception):
     def __init__(self, message):
         Exception.__init__(self)
         self.message = message
 
+def _xmlrpc_decorator(function):
+    """A decorator function, which adds some maintenance code
+
+    This function takes care of preparing a MultiCall object and
+    an authentication token, and deleting them at the end.
+
+    """
+    def wrapped_func(self, command):
+        # Dummy function, so that the string appears in a .po file
+        _ = lambda x: x
+
+        self.token = None
+        self.multicall = MultiCall(self.connection)
+        jid = command.jid
+        if type(jid) is not list:
+            jid = [jid]
+
+        try:
+            try:
+                self.get_auth_token(command.jid)
+                if self.token:
+                    self.multicall.applyAuthToken(self.token)
+
+                if function(self, command) != u"SUCCESS":
+                    self.warn_no_credentials(command.jid)
+
+                self.commands_out.put_nowait(command)
+
+            except xmlrpclib.Fault, fault:
+                msg = _("Your request has failed. The reason is:\n%(error)s")
+                self.log.error(str(fault))
+                self.report_error(jid, msg, {'error': fault.faultString})
+            except xmlrpclib.Error, err:
+                msg = _("A serious error occured while processing your request:\n%(error)s")
+                self.log.error(str(err))
+                self.report_error(jid, msg, {'error': str(err)})
+            except Exception, exc:
+                msg = _("An internal error has occured, please contact the administrator.")
+                self.log.critical(str(exc))
+                self.report_error(jid, msg)
+
+        finally:
+            del self.token
+            del self.multicall
+
+    return wrapped_func
+
 class XMLRPCClient(Thread):
     """XMLRPC Client
 
@@ -80,7 +127,8 @@
         # Dummy function, so that the string appears in a .po file
         _ = lambda x: x
 
-        report = cmd.NotificationCommandI18n(jid, text, _("Error"), data, async=False)
+        cmddata = {'text': text, 'subject': _("Error"), 'data': data}
+        report = cmd.NotificationCommandI18n(jid, cmddata, async=False)
         self.commands_out.put_nowait(report)
 
     def get_auth_token(self, jid):
@@ -94,53 +142,6 @@
         if token:
             self.token = token
 
-    def _xmlrpc_decorator(function):
-        """A decorator function, which adds some maintenance code
-
-        This function takes care of preparing a MultiCall object and
-        an authentication token, and deleting them at the end.
-
-        """
-        def wrapped_func(self, command):
-            # Dummy function, so that the string appears in a .po file
-            _ = lambda x: x
-
-            self.token = None
-            self.multicall = MultiCall(self.connection)
-            jid = command.jid
-            if type(jid) is not list:
-                jid = [jid]
-
-            try:
-                try:
-                    self.get_auth_token(command.jid)
-                    if self.token:
-                        self.multicall.applyAuthToken(self.token)
-
-                    if function(self, command) != u"SUCCESS":
-                        self.warn_no_credentials(command.jid)
-
-                    self.commands_out.put_nowait(command)
-
-                except xmlrpclib.Fault, fault:
-                    msg = _("Your request has failed. The reason is:\n%(error)s")
-                    self.log.error(str(fault))
-                    self.report_error(jid, msg, {'error': fault.faultString})
-                except xmlrpclib.Error, err:
-                    msg = _("A serious error occured while processing your request:\n%(error)s")
-                    self.log.error(str(err))
-                    self.report_error(jid, msg, {'error': str(err)})
-                except Exception, exc:
-                    msg = _("An internal error has occured, please contact the administrator.")
-                    self.log.critical(str(exc))
-                    self.report_error(jid, msg)
-
-            finally:
-                del self.token
-                del self.multicall
-
-        return wrapped_func
-
     def warn_no_credentials(self, jid):
         """Warn a given JID that credentials check failed
 
@@ -151,8 +152,8 @@
         # Dummy function, so that the string appears in a .po file
         _ = lambda x: x
 
-        msg = _("Credentials check failed, you may be unable to see all information.")
-        warning = cmd.NotificationCommandI18n([jid], msg, async=False)
+        cmddata = {'text': _("Credentials check failed, you may be unable to see all information.")}
+        warning = cmd.NotificationCommandI18n([jid], cmddata, async=False)
         self.commands_out.put_nowait(warning)
 
     def get_page(self, command):
@@ -169,7 +170,6 @@
         command.data = getpage_result
         return token_result
 
-
     get_page = _xmlrpc_decorator(get_page)
 
 
@@ -197,8 +197,8 @@
         _ = lambda x: x
 
         token_result = u"FAILURE"
-        txt = _("This command may take a while to complete, please be patient...")
-        info = cmd.NotificationCommandI18n([command.jid], txt, async=False)
+        cmd_data = {'text': _("This command may take a while to complete, please be patient...")}
+        info = cmd.NotificationCommandI18n([command.jid], cmd_data, async=False, msg_type=u"chat")
         self.commands_out.put_nowait(info)
 
         self.multicall.getAllPages()
@@ -268,7 +268,7 @@
         if config.secret:
             self.secret = config.secret
         else:
-            error = _("You must set a (long) secret string")
+            error = "You must set a (long) secret string"
             self.log.critical(error)
             raise ConfigurationError(error)
 
@@ -303,7 +303,7 @@
         return protected_func
 
 
-    def send_notification(self, jids, text, subject):
+    def send_notification(self, jids, notification):
         """Instructs the XMPP component to send a notification
 
         @param jids: a list of JIDs to send a message to (bare JIDs)
@@ -312,7 +312,7 @@
         @type text: unicode
 
         """
-        command = cmd.NotificationCommand(jids, text, subject)
+        command = cmd.NotificationCommand(jids, notification, async=True)
         self.commands.put_nowait(command)
         return True
     send_notification.export = True
--- a/jabberbot/xmppbot.py	Thu Jul 26 04:19:37 2007 +0200
+++ b/jabberbot/xmppbot.py	Thu Jul 26 04:38:12 2007 +0200
@@ -6,7 +6,7 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-import logging, time, libxml2, Queue
+import logging, time, Queue
 from threading import Thread
 
 from pyxmpp.client import Client
@@ -19,6 +19,7 @@
 
 import jabberbot.commands as cmd
 import jabberbot.i18n as i18n
+import jabberbot.oob as oob
 
 
 class Contact:
@@ -259,12 +260,13 @@
                 jid = JID(recipient)
                 jid_text = jid.bare().as_utf8()
 
+                _ = self.get_text(jid_text)
+                text = command.notification['text']
+
                 if isinstance(command, cmd.NotificationCommandI18n):
                     # Translate&interpolate the message with data
                     gettext_func = self.get_text(recipient)
                     text = command.translate(gettext_func)
-                else:
-                    text = command.text
 
                 # Check if contact is DoNotDisturb.
                 # If so, queue the message for delayed delivery.
@@ -276,7 +278,7 @@
                 except KeyError:
                     pass
 
-                self.send_message(jid, text)
+                self.send_message(jid, command.notification, command.msg_type)
 
             return
 
@@ -294,16 +296,14 @@
         elif isinstance(command, cmd.GetPage) or isinstance(command, cmd.GetPageHTML):
             msg = _(u"""Here's the page "%(pagename)s" that you've requested:\n\n%(data)s""")
 
-            self.send_message(command.jid, msg % {
-                      'pagename': command.pagename,
-                      'data': command.data,
-            })
+            cmd_data = {'text': msg % {'pagename': command.pagename, 'data': command.data}}
+            self.send_message(command.jid, cmd_data)
 
         elif isinstance(command, cmd.GetPageList):
             msg = _("That's the list of pages accesible to you:\n\n%s")
             pagelist = u"\n".join(command.data)
 
-            self.send_message(command.jid, msg % (pagelist, ))
+            self.send_message(command.jid, {'text': msg % (pagelist, )})
 
         elif isinstance(command, cmd.GetPageInfo):
             intro = _("""Following detailed information on page "%(pagename)s" \
@@ -330,8 +330,8 @@
              'version': command.data['version'],
             }
 
-            self.send_message(command.jid, intro % {'pagename': command.pagename})
-            self.send_message(command.jid, msg)
+            self.send_message(command.jid, {'text': intro % {'pagename': command.pagename}})
+            self.send_message(command.jid, {'text': msg})
 
         elif isinstance(command, cmd.GetUserLanguage):
             if command.jid in self.contacts:
@@ -360,16 +360,25 @@
         stanza = Presence(to_jid=jid, stanza_type="unsubscribed")
         self.get_stream().send(stanza)
 
-    def send_message(self, jid, text, subject="", msg_type=u"chat"):
+    def send_message(self, jid, data, msg_type=u"chat"):
         """Sends a message
 
         @param jid: JID to send the message to
-        @param text: message's body:
-        @param type: message type, as defined in RFC
+        @param data: dictionary containing notification data
+        @param msg_type: message type, as defined in RFC
         @type jid: pyxmpp.jid.JID
 
         """
-        message = Message(to_jid=jid, body=text, stanza_type=msg_type, subject=subject)
+        if data.has_key('subject'):
+            subject = data['subject']
+        else:
+            subject = ''
+
+        message = Message(to_jid=jid, body=data['text'], stanza_type=msg_type, subject=subject)
+
+        if data.has_key('url_list'):
+            oob.add_urls(message, data['url_list'])
+
         self.get_stream().send(message)
 
     def send_form(self, jid, form):
@@ -450,7 +459,7 @@
             response = self.reply_help(sender)
 
         if response:
-            self.send_message(sender, response)
+            self.send_message(sender, {'text': response})
 
     def handle_internal_command(self, sender, command):
         """Handles internal commands, that can be completed by the XMPP bot itself