diff src/plugins/plugin_xep_0045.py @ 2066:09c18fcd8225

plugin XEP-0045, quick frontend (app,chat): various chat improvments: - (XEP-0045): join defered is now fired when room is full joined and history is available - (XEP-0045): mucJOIN signature has changed, it now returns the same arguments as mucRoomJoined and a boolean which is True if the room was alread joined - quick frontend (app, chat): adapted code to new changes
author Goffi <goffi@goffi.org>
date Fri, 09 Sep 2016 23:54:33 +0200
parents b4db946ddc89
children 1d3f73e065e1
line wrap: on
line diff
--- a/src/plugins/plugin_xep_0045.py	Fri Sep 09 23:54:33 2016 +0200
+++ b/src/plugins/plugin_xep_0045.py	Fri Sep 09 23:54:33 2016 +0200
@@ -64,6 +64,13 @@
 default_conf = {"default_muc": u'sat@chat.jabberfr.org'}
 
 
+class AlreadyJoined(exceptions.ConflictError):
+
+    def __init__(self, room):
+        super(AlreadyJoined, self).__init__()
+        self.room = room
+
+
 class XEP_0045(object):
     # TODO: handle invitations
 
@@ -71,7 +78,7 @@
         log.info(_("Plugin XEP_0045 initialization"))
         self.host = host
         self._sessions = memory.Sessions()
-        host.bridge.addMethod("mucJoin", ".plugin", in_sign='ssa{ss}s', out_sign='s', method=self._join, async=True)
+        host.bridge.addMethod("mucJoin", ".plugin", in_sign='ssa{ss}s', out_sign='(bsa{sa{ss}}sss)', method=self._join, async=True)  # return same arguments as mucRoomJoined + a boolean set to True is the room was already joined (first argument)
         host.bridge.addMethod("mucNick", ".plugin", in_sign='sss', out_sign='', method=self._nick)
         host.bridge.addMethod("mucLeave", ".plugin", in_sign='ss', out_sign='', method=self._leave, async=True)
         host.bridge.addMethod("mucSubject", ".plugin", in_sign='sss', out_sign='', method=self._subject)
@@ -140,6 +147,15 @@
         else:
             return True
 
+    def _getRoomJoinedArgs(self, room, profile):
+        return [
+            room.roomJID.userhost(),
+            XEP_0045._getOccupants(room),
+            room.nick,
+            room.subject,
+            profile
+            ]
+
     def _UIRoomJoinCb(self, data, profile):
         room_jid = jid.JID(data['index'])
         client = self.host.getClient(profile)
@@ -173,7 +189,7 @@
             log.debug(_(u"room locked !"))
             d = client._muc_client.configure(room.roomJID, {})
             d.addErrback(lambda dummy: log.error(_(u'Error while configuring the room')))
-        return room
+        return room.fully_joined
 
     def _joinEb(self, failure, client, room_jid, nick, password):
         """Called when something is going wrong when joining the room"""
@@ -389,6 +405,11 @@
         """
         return self.host.memory.getConfig(CONFIG_SECTION, 'default_muc', default_conf['default_muc'])
 
+    def _join_eb(self, failure_, client):
+        failure_.trap(AlreadyJoined)
+        room = failure_.value.room
+        return [True] + self._getRoomJoinedArgs(room, client.profile)
+
     def _join(self, room_jid_s, nick, options, profile_key=C.PROF_KEY_NONE):
         """join method used by bridge
 
@@ -407,7 +428,9 @@
             room_jid = self.getUniqueName(profile_key=client.profile)
         # TODO: error management + signal in bridge
         d = self.join(client, room_jid, nick, options or None)
-        return d.addCallback(lambda room: room.roomJID.userhost())
+        d.addCallback(lambda room: [False] + self._getRoomJoinedArgs(room, client.profile))
+        d.addErrback(self._join_eb, client)
+        return d
 
     def join(self, client, room_jid, nick=None, options=None):
         if not nick:
@@ -420,8 +443,9 @@
             return d
 
         if room_jid in client._muc_client.joined_rooms:
+            room = client._muc_client.joined_rooms[room_jid]
             log.warning(_(u'{profile} is already in room {room_jid}').format(profile=client.profile, room_jid = room_jid.userhost()))
-            raise failure.Failure(exceptions.ConflictError(_(u"The room has already been joined")))
+            return defer.fail(AlreadyJoined(room))
         log.info(_(u"[{profile}] is joining room {room} with nick {nick}").format(profile=client.profile, room=room_jid.userhost(), nick=nick))
 
         password = options["password"] if "password" in options else None
@@ -745,11 +769,13 @@
 
     def _addRoom(self, room):
         super(SatMUCClient, self)._addRoom(room)
-        room._roster_ok = False
+        room._roster_ok = False  # True when occupants list has been fully received
         room._room_ok = None  # False when roster, history and subject are available
                               # True when new messages are saved to database
-        room._history_d = defer.Deferred()  # use to send bridge signal once backlog are written in history
+        room._history_d = defer.Deferred()  # used to send bridge signal once backlog are written in history
         room._history_d.callback(None)
+        # FIXME: check if history_d is not redundant with fully_joined
+        room.fully_joined = defer.Deferred()  # called when everything is OK
         room._cache = []
 
     def _gotLastDbHistory(self, mess_data_list, room_jid, nick, password):
@@ -978,12 +1004,8 @@
         return muc.MUCClientProtocol.subject(self, room, subject)
 
     def _historyCb(self, dummy, room):
-        self.host.bridge.mucRoomJoined(
-            room.roomJID.userhost(),
-            XEP_0045._getOccupants(room),
-            room.nick,
-            room.subject,
-            self.parent.profile)
+        args = self.plugin_parent._getRoomJoinedArgs(room, self.parent.profile)
+        self.host.bridge.mucRoomJoined(*args)
         del room._history_d
         cache = room._cache
         del room._cache
@@ -991,7 +1013,6 @@
         for elem in cache:
             self.parent.xmlstream.dispatch(elem)
 
-
     def _historyEb(self, failure_, room):
         log.error(u"Error while managing history: {}".format(failure_))
         self._historyCb(None, room)
@@ -1006,6 +1027,7 @@
             # that mean that we have received everything we need
             room._room_ok = False
             room._history_d.addCallbacks(self._historyCb, self._historyEb, [room], errbackArgs=[room])
+            room.fully_joined.callback(room)
         else:
             # the subject has been changed
             log.debug(_(u"New subject for room ({room_id}): {subject}").format(room_id = room.roomJID.full(), subject = subject))