# HG changeset patch # User Goffi # Date 1551439017 -3600 # Node ID 5284be4c601b69a38d2ca0f444d3c8b8b3e5cbb8 # Parent 3d735e0ab2fa5dba6dab1c8d866712bc43772f69 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. diff -r 3d735e0ab2fa -r 5284be4c601b sat/plugins/plugin_xep_0045.py --- 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_))