Mercurial > libervia-backend
comparison 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 |
comparison
equal
deleted
inserted
replaced
2065:f3167c873e7b | 2066:09c18fcd8225 |
---|---|
62 CONFIG_SECTION = u'plugin muc' | 62 CONFIG_SECTION = u'plugin muc' |
63 | 63 |
64 default_conf = {"default_muc": u'sat@chat.jabberfr.org'} | 64 default_conf = {"default_muc": u'sat@chat.jabberfr.org'} |
65 | 65 |
66 | 66 |
67 class AlreadyJoined(exceptions.ConflictError): | |
68 | |
69 def __init__(self, room): | |
70 super(AlreadyJoined, self).__init__() | |
71 self.room = room | |
72 | |
73 | |
67 class XEP_0045(object): | 74 class XEP_0045(object): |
68 # TODO: handle invitations | 75 # TODO: handle invitations |
69 | 76 |
70 def __init__(self, host): | 77 def __init__(self, host): |
71 log.info(_("Plugin XEP_0045 initialization")) | 78 log.info(_("Plugin XEP_0045 initialization")) |
72 self.host = host | 79 self.host = host |
73 self._sessions = memory.Sessions() | 80 self._sessions = memory.Sessions() |
74 host.bridge.addMethod("mucJoin", ".plugin", in_sign='ssa{ss}s', out_sign='s', method=self._join, async=True) | 81 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) |
75 host.bridge.addMethod("mucNick", ".plugin", in_sign='sss', out_sign='', method=self._nick) | 82 host.bridge.addMethod("mucNick", ".plugin", in_sign='sss', out_sign='', method=self._nick) |
76 host.bridge.addMethod("mucLeave", ".plugin", in_sign='ss', out_sign='', method=self._leave, async=True) | 83 host.bridge.addMethod("mucLeave", ".plugin", in_sign='ss', out_sign='', method=self._leave, async=True) |
77 host.bridge.addMethod("mucSubject", ".plugin", in_sign='sss', out_sign='', method=self._subject) | 84 host.bridge.addMethod("mucSubject", ".plugin", in_sign='sss', out_sign='', method=self._subject) |
78 host.bridge.addMethod("mucGetRoomsJoined", ".plugin", in_sign='s', out_sign='a(sa{sa{ss}}ss)', method=self._getRoomsJoined) | 85 host.bridge.addMethod("mucGetRoomsJoined", ".plugin", in_sign='s', out_sign='a(sa{sa{ss}}ss)', method=self._getRoomsJoined) |
79 host.bridge.addMethod("mucGetUniqueRoomName", ".plugin", in_sign='ss', out_sign='s', method=self._getUniqueName) | 86 host.bridge.addMethod("mucGetUniqueRoomName", ".plugin", in_sign='ss', out_sign='s', method=self._getUniqueName) |
138 except exceptions.NotFound: | 145 except exceptions.NotFound: |
139 return False | 146 return False |
140 else: | 147 else: |
141 return True | 148 return True |
142 | 149 |
150 def _getRoomJoinedArgs(self, room, profile): | |
151 return [ | |
152 room.roomJID.userhost(), | |
153 XEP_0045._getOccupants(room), | |
154 room.nick, | |
155 room.subject, | |
156 profile | |
157 ] | |
158 | |
143 def _UIRoomJoinCb(self, data, profile): | 159 def _UIRoomJoinCb(self, data, profile): |
144 room_jid = jid.JID(data['index']) | 160 room_jid = jid.JID(data['index']) |
145 client = self.host.getClient(profile) | 161 client = self.host.getClient(profile) |
146 self.join(client, room_jid) | 162 self.join(client, room_jid) |
147 return {} | 163 return {} |
171 # and send the signal only when the room is unlocked | 187 # and send the signal only when the room is unlocked |
172 # a proper configuration management should be done | 188 # a proper configuration management should be done |
173 log.debug(_(u"room locked !")) | 189 log.debug(_(u"room locked !")) |
174 d = client._muc_client.configure(room.roomJID, {}) | 190 d = client._muc_client.configure(room.roomJID, {}) |
175 d.addErrback(lambda dummy: log.error(_(u'Error while configuring the room'))) | 191 d.addErrback(lambda dummy: log.error(_(u'Error while configuring the room'))) |
176 return room | 192 return room.fully_joined |
177 | 193 |
178 def _joinEb(self, failure, client, room_jid, nick, password): | 194 def _joinEb(self, failure, client, room_jid, nick, password): |
179 """Called when something is going wrong when joining the room""" | 195 """Called when something is going wrong when joining the room""" |
180 try: | 196 try: |
181 condition = failure.value.condition | 197 condition = failure.value.condition |
387 | 403 |
388 @return: unicode | 404 @return: unicode |
389 """ | 405 """ |
390 return self.host.memory.getConfig(CONFIG_SECTION, 'default_muc', default_conf['default_muc']) | 406 return self.host.memory.getConfig(CONFIG_SECTION, 'default_muc', default_conf['default_muc']) |
391 | 407 |
408 def _join_eb(self, failure_, client): | |
409 failure_.trap(AlreadyJoined) | |
410 room = failure_.value.room | |
411 return [True] + self._getRoomJoinedArgs(room, client.profile) | |
412 | |
392 def _join(self, room_jid_s, nick, options, profile_key=C.PROF_KEY_NONE): | 413 def _join(self, room_jid_s, nick, options, profile_key=C.PROF_KEY_NONE): |
393 """join method used by bridge | 414 """join method used by bridge |
394 | 415 |
395 @return (unicode): room bare jid | 416 @return (unicode): room bare jid |
396 """ | 417 """ |
405 room_jid.user, room_jid.host = room_jid.host, muc_service | 426 room_jid.user, room_jid.host = room_jid.host, muc_service |
406 else: | 427 else: |
407 room_jid = self.getUniqueName(profile_key=client.profile) | 428 room_jid = self.getUniqueName(profile_key=client.profile) |
408 # TODO: error management + signal in bridge | 429 # TODO: error management + signal in bridge |
409 d = self.join(client, room_jid, nick, options or None) | 430 d = self.join(client, room_jid, nick, options or None) |
410 return d.addCallback(lambda room: room.roomJID.userhost()) | 431 d.addCallback(lambda room: [False] + self._getRoomJoinedArgs(room, client.profile)) |
432 d.addErrback(self._join_eb, client) | |
433 return d | |
411 | 434 |
412 def join(self, client, room_jid, nick=None, options=None): | 435 def join(self, client, room_jid, nick=None, options=None): |
413 if not nick: | 436 if not nick: |
414 nick = client.jid.user | 437 nick = client.jid.user |
415 if options is None: | 438 if options is None: |
418 d = defer.Deferred() | 441 d = defer.Deferred() |
419 d.errback(exc_obj(txt)) | 442 d.errback(exc_obj(txt)) |
420 return d | 443 return d |
421 | 444 |
422 if room_jid in client._muc_client.joined_rooms: | 445 if room_jid in client._muc_client.joined_rooms: |
446 room = client._muc_client.joined_rooms[room_jid] | |
423 log.warning(_(u'{profile} is already in room {room_jid}').format(profile=client.profile, room_jid = room_jid.userhost())) | 447 log.warning(_(u'{profile} is already in room {room_jid}').format(profile=client.profile, room_jid = room_jid.userhost())) |
424 raise failure.Failure(exceptions.ConflictError(_(u"The room has already been joined"))) | 448 return defer.fail(AlreadyJoined(room)) |
425 log.info(_(u"[{profile}] is joining room {room} with nick {nick}").format(profile=client.profile, room=room_jid.userhost(), nick=nick)) | 449 log.info(_(u"[{profile}] is joining room {room} with nick {nick}").format(profile=client.profile, room=room_jid.userhost(), nick=nick)) |
426 | 450 |
427 password = options["password"] if "password" in options else None | 451 password = options["password"] if "password" in options else None |
428 | 452 |
429 return client._muc_client.join(room_jid, nick, password).addCallbacks(self._joinCb, self._joinEb, (client, room_jid, nick), errbackArgs=(client, room_jid, nick, password)) | 453 return client._muc_client.join(room_jid, nick, password).addCallbacks(self._joinCb, self._joinEb, (client, room_jid, nick), errbackArgs=(client, room_jid, nick, password)) |
743 def joined_rooms(self): | 767 def joined_rooms(self): |
744 return self._rooms | 768 return self._rooms |
745 | 769 |
746 def _addRoom(self, room): | 770 def _addRoom(self, room): |
747 super(SatMUCClient, self)._addRoom(room) | 771 super(SatMUCClient, self)._addRoom(room) |
748 room._roster_ok = False | 772 room._roster_ok = False # True when occupants list has been fully received |
749 room._room_ok = None # False when roster, history and subject are available | 773 room._room_ok = None # False when roster, history and subject are available |
750 # True when new messages are saved to database | 774 # True when new messages are saved to database |
751 room._history_d = defer.Deferred() # use to send bridge signal once backlog are written in history | 775 room._history_d = defer.Deferred() # used to send bridge signal once backlog are written in history |
752 room._history_d.callback(None) | 776 room._history_d.callback(None) |
777 # FIXME: check if history_d is not redundant with fully_joined | |
778 room.fully_joined = defer.Deferred() # called when everything is OK | |
753 room._cache = [] | 779 room._cache = [] |
754 | 780 |
755 def _gotLastDbHistory(self, mess_data_list, room_jid, nick, password): | 781 def _gotLastDbHistory(self, mess_data_list, room_jid, nick, password): |
756 if mess_data_list: | 782 if mess_data_list: |
757 timestamp = mess_data_list[0][1] | 783 timestamp = mess_data_list[0][1] |
976 | 1002 |
977 def subject(self, room, subject): | 1003 def subject(self, room, subject): |
978 return muc.MUCClientProtocol.subject(self, room, subject) | 1004 return muc.MUCClientProtocol.subject(self, room, subject) |
979 | 1005 |
980 def _historyCb(self, dummy, room): | 1006 def _historyCb(self, dummy, room): |
981 self.host.bridge.mucRoomJoined( | 1007 args = self.plugin_parent._getRoomJoinedArgs(room, self.parent.profile) |
982 room.roomJID.userhost(), | 1008 self.host.bridge.mucRoomJoined(*args) |
983 XEP_0045._getOccupants(room), | |
984 room.nick, | |
985 room.subject, | |
986 self.parent.profile) | |
987 del room._history_d | 1009 del room._history_d |
988 cache = room._cache | 1010 cache = room._cache |
989 del room._cache | 1011 del room._cache |
990 room._room_ok = True | 1012 room._room_ok = True |
991 for elem in cache: | 1013 for elem in cache: |
992 self.parent.xmlstream.dispatch(elem) | 1014 self.parent.xmlstream.dispatch(elem) |
993 | |
994 | 1015 |
995 def _historyEb(self, failure_, room): | 1016 def _historyEb(self, failure_, room): |
996 log.error(u"Error while managing history: {}".format(failure_)) | 1017 log.error(u"Error while managing history: {}".format(failure_)) |
997 self._historyCb(None, room) | 1018 self._historyCb(None, room) |
998 | 1019 |
1004 if room._room_ok is None: | 1025 if room._room_ok is None: |
1005 # this is the first subject we receive | 1026 # this is the first subject we receive |
1006 # that mean that we have received everything we need | 1027 # that mean that we have received everything we need |
1007 room._room_ok = False | 1028 room._room_ok = False |
1008 room._history_d.addCallbacks(self._historyCb, self._historyEb, [room], errbackArgs=[room]) | 1029 room._history_d.addCallbacks(self._historyCb, self._historyEb, [room], errbackArgs=[room]) |
1030 room.fully_joined.callback(room) | |
1009 else: | 1031 else: |
1010 # the subject has been changed | 1032 # the subject has been changed |
1011 log.debug(_(u"New subject for room ({room_id}): {subject}").format(room_id = room.roomJID.full(), subject = subject)) | 1033 log.debug(_(u"New subject for room ({room_id}): {subject}").format(room_id = room.roomJID.full(), subject = subject)) |
1012 self.host.bridge.mucRoomNewSubject(room.roomJID.userhost(), subject, self.parent.profile) | 1034 self.host.bridge.mucRoomNewSubject(room.roomJID.userhost(), subject, self.parent.profile) |
1013 | 1035 |