changeset 2822:5284be4c601b

plugin XEP-0045: cache presences if they are received before the room is fully joined: presences are then replayed (only the last one) once the room is fully joined.
author Goffi <goffi@goffi.org>
date Fri, 01 Mar 2019 12:16:57 +0100
parents 3d735e0ab2fa
children 11afbbce40d1
files sat/plugins/plugin_xep_0045.py
diffstat 1 files changed, 33 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/sat/plugins/plugin_xep_0045.py	Fri Mar 01 12:13:55 2019 +0100
+++ b/sat/plugins/plugin_xep_0045.py	Fri Mar 01 12:16:57 2019 +0100
@@ -116,6 +116,7 @@
         self._si = self.host.plugins[u"XEP-0359"]
 
         host.trigger.add("presence_available", self.presenceTrigger)
+        host.trigger.add("presence_received", self.presenceReceivedTrigger)
         host.trigger.add("MessageReceived", self.messageReceivedTrigger, priority=1000000)
         host.trigger.add("message_parse", self._message_parseTrigger)
 
@@ -765,6 +766,32 @@
             client.presence.send(elt)
         return True
 
+    def presenceReceivedTrigger(self, client, entity, show, priority, statuses):
+        entity_bare = entity.userhostJID()
+        muc_client = client._muc_client
+        if entity_bare in muc_client.joined_rooms:
+            room = muc_client.joined_rooms[entity_bare]
+            if hasattr(room, "_cache_presence"):
+                # room has a cache for presence, meaning it has not been fully
+                # joined yet. So we put presence in cache, and stop workflow.
+                # Or delete current presence and continue workflow if it's an
+                # "unavailable" presence
+                cache = room._cache_presence
+                if show == C.PRESENCE_UNAVAILABLE:
+                    try:
+                        del cache[entity]
+                    except KeyError:
+                        pass
+                    return True
+                else:
+                    cache[entity] = {
+                        "entity": entity,
+                        "show": show,
+                        "statuses": statuses,
+                        "priority": priority}
+                    return False
+        return True
+
 
 class SatMUCClient(muc.MUCClient):
     implements(iwokkel.IDisco)
@@ -827,6 +854,8 @@
         # cache data until room is ready
         # list of elements which will be re-injected in stream
         room._cache = []
+        # we only need to keep last presence status for each jid, so a dict is suitable
+        room._cache_presence = {}
 
     @defer.inlineCallbacks
     def _joinLegacy(self, client, room_jid, nick, password):
@@ -1195,8 +1224,12 @@
         del room._history_type
         cache = room._cache
         del room._cache
+        cache_presence = room._cache_presence
+        del room._cache_presence
         for elem in cache:
             self.client.xmlstream.dispatch(elem)
+        for __, presence_data in cache_presence.iteritems():
+            self.client.presence.availableReceived(**presence_data)
 
     def _historyEb(self, failure_, room):
         log.error(u"Error while managing history: {}".format(failure_))