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