diff src/plugins/plugin_xep_0085.py @ 1290:faa1129559b8 frontends_multi_profiles

core, frontends: refactoring to base Libervia on QuickFrontend (big mixed commit): /!\ not finished, everything is still instable ! - bridge: DBus bridge has been modified to allow blocking call to be called in the same way as asynchronous calls - bridge: calls with a callback and no errback are now possible, default errback log the error - constants: removed hack to manage presence without OrderedDict, as an OrderedDict like class has been implemented in Libervia - core: getLastResource has been removed and replaced by getMainResource (there is a global better management of resources) - various style improvments: use of constants when possible, fixed variable overlaps, import of module instead of direct class import - frontends: printInfo and printMessage methods in (Quick)Chat are more generic (use of extra instead of timestamp) - frontends: bridge creation and option parsing (command line arguments) are now specified by the frontend in QuickApp __init__ - frontends: ProfileManager manage a more complete plug sequence (some stuff formerly manage in contact_list have moved to ProfileManager) - quick_frontend (quick_widgets): QuickWidgetsManager is now iterable (all widgets are then returned), or can return an iterator on a specific class (return all widgets of this class) with getWidgets - frontends: tools.jid can now be used in Pyjamas, with some care - frontends (XMLUI): profile is now managed - core (memory): big improvment on entities cache management (and specially resource management) - core (params/exceptions): added PermissionError - various fixes and improvments, check diff for more details
author Goffi <goffi@goffi.org>
date Sat, 24 Jan 2015 01:00:29 +0100
parents 60dfa2f5d61f
children be3a301540c0
line wrap: on
line diff
--- a/src/plugins/plugin_xep_0085.py	Sat Jan 24 00:15:01 2015 +0100
+++ b/src/plugins/plugin_xep_0085.py	Sat Jan 24 01:00:29 2015 +0100
@@ -39,6 +39,7 @@
 PARAM_KEY = "Notifications"
 PARAM_NAME = "Enable chat state notifications"
 ENTITY_KEY = PARAM_KEY + "_" + PARAM_NAME
+DELETE_VALUE = "DELETE"
 
 PLUGIN_INFO = {
     "name": "Chat State Notifications Protocol Plugin",
@@ -126,28 +127,31 @@
         del self.map[profile]
 
     def updateEntityData(self, entity_jid, value, profile):
-        """
-        Update the entity data of the given profile for one or all contacts.
+        """Update the entity data of the given profile for one or all contacts.
+
         Reset the chat state(s) display if the notification has been disabled.
-        @param entity_jid: contact's JID, or '@ALL@' to update all contacts.
-        @param value: True, False or C.PROF_KEY_NONE to delete the entity data
+        @param entity_jid: contact's JID, or C.ENTITY_ALL to update all contacts.
+        @param value: True, False or DELETE_VALUE to delete the entity data
         @param profile: current profile
         """
-        self.host.memory.updateEntityData(entity_jid, ENTITY_KEY, value, profile)
-        if not value or value == C.PROF_KEY_NONE:
-            # disable chat state for this or these contact(s)
-            self.host.bridge.chatStateReceived(unicode(entity_jid), "", profile)
+        if value == DELETE_VALUE:
+            self.host.memory.delEntityData(entity_jid, ENTITY_KEY, profile)
+        else:
+            self.host.memory.updateEntityData(entity_jid, ENTITY_KEY, value, profile)
+        if not value or value == DELETE_VALUE:
+            # reinit chat state UI for this or these contact(s)
+            self.host.bridge.chatStateReceived(entity_jid.full(), "", 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.
+        """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)
+            self.updateEntityData(C.ENTITY_ALL, True if bool("true") else DELETE_VALUE, profile)
             return False
         return True
 
@@ -160,7 +164,7 @@
             return True
 
         from_jid = JID(message.getAttribute("from"))
-        if self.__isMUC(from_jid, profile):
+        if self._isMUC(from_jid, profile):
             from_jid = from_jid.userhostJID()
         else:  # update entity data for one2one chat
             # assert from_jid.resource # FIXME: assert doesn't work on normal message from server (e.g. server announce), because there is no resource
@@ -200,27 +204,27 @@
         def treatment(mess_data):
             message = mess_data['xml']
             to_jid = JID(message.getAttribute("to"))
-            if not self.__checkActivation(to_jid, forceEntityData=True, profile=profile):
+            if not self._checkActivation(to_jid, forceEntityData=True, profile=profile):
                 return mess_data
             try:
                 # message with a body always mean active state
                 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):
+                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"]:
                     state = mess_data["extra"].pop("chat_state")
-                    assert(state in CHAT_STATES)
+                    assert state in CHAT_STATES
                     message.addElement(state, NS_CHAT_STATES)
             return mess_data
 
         post_xml_treatments.addCallback(treatment)
         return True
 
-    def __isMUC(self, to_jid, profile):
+    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
@@ -229,13 +233,13 @@
         """
         try:
             type_ = self.host.memory.getEntityDatum(to_jid.userhostJID(), 'type', profile)
-            if type_ == 'chatroom':
+            if type_ == 'chatroom': # FIXME: should not use disco instead ?
                 return True
         except (exceptions.UnknownEntityError, KeyError):
             pass
         return False
 
-    def __checkActivation(self, to_jid, forceEntityData, profile):
+    def _checkActivation(self, to_jid, forceEntityData, profile):
         """
         @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
@@ -247,9 +251,10 @@
         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):
+        if self._isMUC(to_jid, profile):
             return True
-        assert to_jid.resource or not self.host.memory.isContactConnected(to_jid, profile)
+        # FIXME: this assertion crash when we want to send a message to an online bare jid
+        # assert to_jid.resource or not self.host.memory.isEntityAvailable(to_jid, profile) # must either have a resource, or talk to an offline contact
         try:
             return self.host.memory.getEntityDatum(to_jid, ENTITY_KEY, profile)
         except (exceptions.UnknownEntityError, KeyError):
@@ -305,11 +310,11 @@
         if profile is None:
             raise exceptions.ProfileUnknownError
         to_jid = JID(to_jid_s)
-        if self.__isMUC(to_jid, profile):
+        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):
+            to_jid.resource = self.host.memory.getMainResource(to_jid, profile)
+        if not self._checkActivation(to_jid, forceEntityData=False, profile=profile):
             return
         try:
             self.map[profile][to_jid]._onEvent("composing")
@@ -347,9 +352,9 @@
         notification to the contact (the "active" state is
         automatically sent with each message) and set the timer.
         """
-        assert(state in TRANSITIONS)
+        assert state in TRANSITIONS
         transition = TRANSITIONS[state]
-        assert("next_state" in transition and "delay" in transition)
+        assert "next_state" in transition and "delay" in transition
 
         if state != self.state and state != "active":
             if state != 'gone' or self.mess_type != 'groupchat':