changeset 1252:5ff9f9af9d1f

plugin XEP-0085: use the full JID + fixes bad entity data "type" value
author souliane <souliane@mailoo.org>
date Mon, 20 Oct 2014 12:57:55 +0200
parents 51a85e8f599a
children c13a46207410
files src/plugins/plugin_xep_0085.py
diffstat 1 files changed, 65 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/plugin_xep_0085.py	Mon Oct 20 16:38:49 2014 +0200
+++ b/src/plugins/plugin_xep_0085.py	Mon Oct 20 12:57:55 2014 +0200
@@ -127,12 +127,13 @@
             # disable chat state for this or these contact(s)
             self.host.bridge.chatStateReceived(unicode(entity_jid), "", profile)
 
-    def paramUpdateTrigger(self, name, value, category, type, profile):
+    def paramUpdateTrigger(self, name, value, category, type_, profile):
         """
         Reset all the existing chat state entity data associated with this profile after a parameter modification.
         @param name: parameter name
         @param value: "true" to activate the notifications, or any other value to delete it
         @param category: parameter category
+        @param type_: parameter type
         """
         if (category, name) == (PARAM_KEY, PARAM_NAME):
             self.updateEntityData("@ALL@", True if value == "true" else C.PROF_KEY_NONE, profile)
@@ -148,19 +149,23 @@
             return True
 
         from_jid = JID(message.getAttribute("from"))
-        try:
-            domish.generateElementsNamed(message.elements(), name="body").next()
+        if self.__isMUC(from_jid, profile):
+            from_jid = from_jid.userhostJID()
+        else:  # update entity data for one2one chat
+            assert(from_jid.resource)
             try:
-                domish.generateElementsNamed(message.elements(), name="active").next()
-                # contact enabled Chat State Notifications
-                self.updateEntityData(from_jid, True, profile)
+                domish.generateElementsNamed(message.elements(), name="body").next()
+                try:
+                    domish.generateElementsNamed(message.elements(), name="active").next()
+                    # contact enabled Chat State Notifications
+                    self.updateEntityData(from_jid, True, profile)
+                except StopIteration:
+                    if message.getAttribute('type') == 'chat':
+                        # contact didn't enable Chat State Notifications
+                        self.updateEntityData(from_jid, False, profile)
+                        return True
             except StopIteration:
-                if message.getAttribute('type') == 'chat':
-                    # contact didn't enable Chat State Notifications
-                    self.updateEntityData(from_jid, False, profile)
-                    return True
-        except StopIteration:
-            pass
+                pass
 
         # send our next "composing" states to any MUC and to the contacts who enabled the feature
         self.__chatStateInit(from_jid, message.getAttribute("type"), profile)
@@ -191,6 +196,8 @@
                 domish.generateElementsNamed(message.elements(), name="body").next()
                 message.addElement('active', NS_CHAT_STATES)
                 # launch the chat state machine (init the timer)
+                if self.__isMUC(to_jid, profile):
+                    to_jid = to_jid.userhostJID()
                 self.__chatStateActive(to_jid, mess_data["type"], profile)
             except StopIteration:
                 if "chat_state" in mess_data["extra"]:
@@ -202,9 +209,24 @@
         post_xml_treatments.addCallback(treatment)
         return True
 
+    def __isMUC(self, to_jid, profile):
+        """Tell if that JID is a MUC or not
+
+        @param to_jid (JID): full or bare JID to check
+        @param profile (str): %(doc_profile)s
+        @return: bool
+        """
+        try:
+            type_ = self.host.memory.getEntityDatum(to_jid.userhostJID(), 'type', profile)
+            if type_ == 'chatroom':
+                return True
+        except (exceptions.UnknownEntityError, KeyError):
+            pass
+        return False
+
     def __checkActivation(self, to_jid, forceEntityData, profile):
         """
-        @param to_joid: the contact's JID
+        @param to_jid: the contact's full JID (or bare if you know it's a MUC)
         @param forceEntityData: if set to True, a non-existing
         entity data will be considered to be True (and initialized)
         @param: current profile
@@ -214,14 +236,11 @@
         if not self.host.memory.getParamA(PARAM_NAME, PARAM_KEY, profile_key=profile):
             return False
         # check if notifications should be sent to this contact
+        if self.__isMUC(to_jid, profile):
+            return True
+        assert(to_jid.resource or not self.host.memory.isContactConnected(to_jid, profile))
         try:
-            type_ = self.host.memory.getEntityData(to_jid, ['type'], profile)['type']
-            if type_ == 'groupchat':  # always send to groupchat
-                return True
-        except (exceptions.UnknownEntityError, KeyError):
-            pass  # private chat
-        try:
-            return self.host.memory.getEntityData(to_jid, [ENTITY_KEY], profile)[ENTITY_KEY]
+            return self.host.memory.getEntityDatum(to_jid, ENTITY_KEY, profile)
         except (exceptions.UnknownEntityError, KeyError):
             if forceEntityData:
                 # enable it for the first time
@@ -233,15 +252,17 @@
     def __chatStateInit(self, to_jid, mess_type, profile):
         """
         Data initialization for the chat state machine.
+
+        @param to_jid (JID): full JID for one2one, bare JID for MUC
+        @param mess_type (str): "one2one" or "groupchat"
+        @param profile (str): %(doc_profile)s
         """
-        # TODO: use also the resource in map key (not for groupchat)
-        to_jid = to_jid.userhostJID()
         if mess_type is None:
             return
         if not hasattr(self, "map"):
             self.map = {}
         profile_map = self.map.setdefault(profile, {})
-        if not to_jid in profile_map:
+        if to_jid not in profile_map:
             machine = ChatStateMachine(self.host, to_jid,
                                        mess_type, profile)
             self.map[profile][to_jid] = machine
@@ -249,30 +270,36 @@
     def __chatStateActive(self, to_jid, mess_type, profile_key):
         """
         Launch the chat state machine on "active" state.
+
+        @param to_jid (JID): full JID for one2one, bare JID for MUC
+        @param mess_type (str): "one2one" or "groupchat"
+        @param profile (str): %(doc_profile)s
         """
-        # TODO: use also the JID resource in the map key (not for groupchat)
-        to_jid = to_jid.userhostJID()
         profile = self.host.memory.getProfileName(profile_key)
         if profile is None:
             raise exceptions.ProfileUnknownError
-            return
         self.__chatStateInit(to_jid, mess_type, profile)
         self.map[profile][to_jid]._onEvent("active")
 
     def chatStateComposing(self, to_jid_s, profile_key):
-        """
-        Move to the "composing" state. Since this method is called
-        from the front-end, it needs to check the values of the
-        parameter "Send chat state notifications" and the entity
+        """Move to the "composing" state when required.
+
+        Since this method is called from the front-end, it needs to check the
+        values of the parameter "Send chat state notifications" and the entity
         data associated to the target JID.
-        TODO: try to optimize this method which is called often
+
+        @param to_jid_s (str): contact full JID as a string
+        @param profile_key (str): %(doc_profile_key)s
         """
-        # TODO: use also the JID resource in the map key (not for groupchat)
-        to_jid = JID(to_jid_s).userhostJID()
+        # TODO: try to optimize this method which is called often
         profile = self.host.memory.getProfileName(profile_key)
         if profile is None:
             raise exceptions.ProfileUnknownError
-            return
+        to_jid = JID(to_jid_s)
+        if self.__isMUC(to_jid, profile):
+            to_jid = to_jid.userhostJID()
+        elif not to_jid.resource:
+            to_jid.resource = self.host.memory.getLastResource(to_jid, profile)
         if not self.__checkActivation(to_jid, forceEntityData=False, profile=profile):
             return
         try:
@@ -318,14 +345,14 @@
                                       extra={"chat_state": state},
                                       profile_key=self.profile)
         self.state = state
-        if not self.timer is None:
+        if self.timer is not None:
             self.timer.cancel()
 
-        if not state in TRANSITIONS:
+        if state not in TRANSITIONS:
             return
-        if not "next_state" in TRANSITIONS[state]:
+        if "next_state" not in TRANSITIONS[state]:
             return
-        if not "delay" in TRANSITIONS[state]:
+        if "delay" not in TRANSITIONS[state]:
             return
         next_state = TRANSITIONS[state]["next_state"]
         delay = TRANSITIONS[state]["delay"]