changeset 921:8dd168c7741c

plugin text commands: refactoring: - commands can now return a deferred - if commands return True, message is sent, else it is cancelled - the escape sequence is now '//' instead of '\/' - added software version to /whois command
author Goffi <goffi@goffi.org>
date Sat, 22 Mar 2014 13:47:33 +0100
parents 45dffd67a18a
children c897c8d321b3
files src/plugins/plugin_misc_text_commands.py
diffstat 1 files changed, 74 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/plugin_misc_text_commands.py	Sat Mar 22 13:44:33 2014 +0100
+++ b/src/plugins/plugin_misc_text_commands.py	Sat Mar 22 13:47:33 2014 +0100
@@ -18,7 +18,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from sat.core.i18n import _
+from sat.core.sat_main import MessageSentAndStored
 from twisted.words.protocols.jabber import jid
+from twisted.internet import defer
+from twisted.python.failure import Failure
 from logging import debug, info, warning, error
 
 PLUGIN_INFO = {
@@ -26,7 +29,7 @@
     "import_name": "TEXT-COMMANDS",
     "type": "Misc",
     "protocols": [],
-    "dependencies": ["XEP-0045", "EXP-PARROT"],
+    "dependencies": ["XEP-0045", "EXP-PARROT", "XEP-0092"],
     "main": "TextCommands",
     "handler": "no",
     "description": _("""IRC like text commands""")
@@ -44,25 +47,54 @@
         host.trigger.add("sendMessage", self.sendMessageTrigger)
 
     def sendMessageTrigger(self, mess_data, treatments, profile):
-        """ Check text commands in message, and react consequently """
+        """ Install SendMessage command hook """
+        treatments.addCallback(self._sendMessageCmdHook, profile)
+        return True
+
+    def _sendMessageCmdHook(self, mess_data, profile):
+        """ Check text commands in message, and react consequently
+        msg starting with / are potential command. If a command is found, it is executed, else message is sent normally
+        msg starting with // are escaped: they are sent with a single /
+        commands can abord message sending (if they return anything evaluating to False), or continue it (if they return True), eventually after modifying the message
+        an "unparsed" key is added to message, containing part of the message not yet parsed
+        commands can be deferred or not
+
+        """
         msg = mess_data["message"]
-        if msg:
-            if msg[0] == '/':
-                command = msg[1:].partition(' ')[0].lower()
-                if command.isalpha():
-                    # looks like an actual command, we try to call the corresponding method
-                    try:
-                        mess_data["unparsed"] = msg[1 + len(command):]  # part not yet parsed of the message
-                        return getattr(self, "cmd_%s" % command)(mess_data, profile)
-                    except AttributeError:
-                        pass
-            elif msg[0] == '\\':  # we have escape char
-                try:
-                    if msg[1] in ('/', '\\'):  # we have '\/' or '\\', we escape to '/' or '\'
-                        mess_data["message"] = msg[1:]
-                except IndexError:
-                    pass
-        return True
+        try:
+            if msg[:2] == '//':
+                # we have a double '/', it's the escape sequence
+                mess_data["message"] = msg[1:]
+                return mess_data
+            if msg[0] != '/':
+                return mess_data
+        except IndexError:
+            return mess_data
+
+        # we have a command
+        d = None
+        command = msg[1:].partition(' ')[0].lower()
+        if command.isalpha():
+            # looks like an actual command, we try to call the corresponding method
+            def retHandling(ret):
+                """ Handle command return value:
+                if ret is True, normally send message (possibly modified by command)
+                else, abord message sending
+
+                """
+                if ret:
+                    return mess_data
+                else:
+                    return Failure(MessageSentAndStored("text commands took over", mess_data))
+
+            try:
+                mess_data["unparsed"] = msg[1 + len(command):]  # part not yet parsed of the message
+                d = defer.maybeDeferred(getattr(self, "cmd_%s" % command), mess_data, profile)
+                d.addCallback(retHandling)
+            except AttributeError:
+                pass
+
+        return d or mess_data # if a command is detected, we should have a deferred, else be send the message normally
 
     def _getRoomJID(self, arg, service_jid):
         """Return a room jid with a shortcut
@@ -230,12 +262,32 @@
                 self._feedBack(_("Invalid jid, can't whois"), mess_data, profile)
                 return False
 
+        if not target_jid.resource:
+            target_jid.resource = self.host.memory.getLastResource(target_jid, profile)
+
         whois_msg = [_(u"whois for %(jid)s") % {'jid': target_jid}]
-        #TODO: add informations here (client version, vcard, etc)
 
-        self._feedBack(u"\n".join(whois_msg), mess_data, profile)
+        # version
+        def versionCb(version_data):
+            name, version, os = version_data
+            if name:
+                whois_msg.append(_("Client name: %s") % name)
+            if version:
+                whois_msg.append(_("Client version: %s") % version)
+            if os:
+                whois_msg.append(_("Operating system: %s") % os)
 
-        return False
+        d = self.host.plugins['XEP-0092'].getVersion(target_jid, profile)
+        d.addCallback(versionCb)
+
+        #TODO: add informations here (vcard, etc)
+
+        def feedBack(ignore):
+            self._feedBack(u"\n".join(whois_msg), mess_data, profile)
+            return False
+
+        d.addCallback(feedBack)
+        return d
 
     def cmd_help(self, mess_data, profile):
         """show help on available commands"""