Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0045.py @ 2581:395a3d1c2888
plugin XEP-0045: fixed joining workflow:
- room keep joining workflow state, and display warning when something is received at unexpected moment
- state is change immediatly when subject is received (which must be the last thing before live messages), avoiding timing issue if history storage in database is taking too much time
- user joined/left data are not saved anymore in history as it takes a lot of space for little interest. A future option may allow to re-enable it if needed.
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 11 May 2018 17:11:47 +0200 |
parents | 26edcf3a30eb |
children | 8378806a70fe |
comparison
equal
deleted
inserted
replaced
2580:5e54afd17321 | 2581:395a3d1c2888 |
---|---|
56 AFFILIATIONS = ('owner', 'admin', 'member', 'none', 'outcast') | 56 AFFILIATIONS = ('owner', 'admin', 'member', 'none', 'outcast') |
57 ROOM_USER_JOINED = 'ROOM_USER_JOINED' | 57 ROOM_USER_JOINED = 'ROOM_USER_JOINED' |
58 ROOM_USER_LEFT = 'ROOM_USER_LEFT' | 58 ROOM_USER_LEFT = 'ROOM_USER_LEFT' |
59 OCCUPANT_KEYS = ('nick', 'entity', 'affiliation', 'role') | 59 OCCUPANT_KEYS = ('nick', 'entity', 'affiliation', 'role') |
60 ENTITY_TYPE_MUC = "MUC" | 60 ENTITY_TYPE_MUC = "MUC" |
61 ROOM_STATE_OCCUPANTS = "occupants" | |
62 ROOM_STATE_SELF_PRESENCE = "self-presence" | |
63 ROOM_STATE_LIVE = "live" | |
64 ROOM_STATES = (ROOM_STATE_OCCUPANTS, ROOM_STATE_SELF_PRESENCE, ROOM_STATE_LIVE) | |
65 | |
61 | 66 |
62 CONFIG_SECTION = u'plugin muc' | 67 CONFIG_SECTION = u'plugin muc' |
63 | 68 |
64 default_conf = {"default_muc": u'sat@chat.jabberfr.org'} | 69 default_conf = {"default_muc": u'sat@chat.jabberfr.org'} |
65 | 70 |
103 else: | 108 else: |
104 self.text_cmds.registerTextCommands(self) | 109 self.text_cmds.registerTextCommands(self) |
105 self.text_cmds.addWhoIsCb(self._whois, 100) | 110 self.text_cmds.addWhoIsCb(self._whois, 100) |
106 | 111 |
107 host.trigger.add("presence_available", self.presenceTrigger) | 112 host.trigger.add("presence_available", self.presenceTrigger) |
108 host.trigger.add("MessageReceived", self.MessageReceivedTrigger, priority=1000000) | 113 host.trigger.add("MessageReceived", self.messageReceivedTrigger, priority=1000000) |
109 | 114 |
110 def profileConnected(self, client): | 115 def profileConnected(self, client): |
111 def assign_service(service): | 116 def assign_service(service): |
112 client.muc_service = service | 117 client.muc_service = service |
113 return self.getMUCService(client).addCallback(assign_service) | 118 return self.getMUCService(client).addCallback(assign_service) |
114 | 119 |
115 def MessageReceivedTrigger(self, client, message_elt, post_treat): | 120 def messageReceivedTrigger(self, client, message_elt, post_treat): |
116 if message_elt.getAttribute("type") == C.MESS_TYPE_GROUPCHAT: | 121 if message_elt.getAttribute("type") == C.MESS_TYPE_GROUPCHAT: |
117 if message_elt.subject or message_elt.delay: | 122 if message_elt.subject or message_elt.delay: |
118 return False | 123 return False |
119 from_jid = jid.JID(message_elt['from']) | 124 from_jid = jid.JID(message_elt['from']) |
120 room_jid = from_jid.userhostJID() | 125 room_jid = from_jid.userhostJID() |
121 if room_jid in client._muc_client.joined_rooms: | 126 if room_jid in client._muc_client.joined_rooms: |
122 room = client._muc_client.joined_rooms[room_jid] | 127 room = client._muc_client.joined_rooms[room_jid] |
123 if not room._room_ok: | 128 if room.state != ROOM_STATE_LIVE: |
124 log.warning(u"Received non delayed message in a room before its initialisation: {}".format(message_elt.toXml())) | 129 log.warning(_(u"Received non delayed message in a room before its initialisation: state={state}, msg={msg}").format( |
130 state=room.state, | |
131 msg=message_elt.toXml())) | |
125 room._cache.append(message_elt) | 132 room._cache.append(message_elt) |
126 return False | 133 return False |
127 else: | 134 else: |
128 log.warning(u"Received groupchat message for a room which has not been joined, ignoring it: {}".format(message_elt.toXml())) | 135 log.warning(u"Received groupchat message for a room which has not been joined, ignoring it: {}".format(message_elt.toXml())) |
129 return False | 136 return False |
232 | 239 |
233 def getRoomsJoined(self, client): | 240 def getRoomsJoined(self, client): |
234 """Return rooms where user is""" | 241 """Return rooms where user is""" |
235 result = [] | 242 result = [] |
236 for room in client._muc_client.joined_rooms.values(): | 243 for room in client._muc_client.joined_rooms.values(): |
237 if room._room_ok: | 244 if room.state == ROOM_STATE_LIVE: |
238 result.append((room.roomJID.userhost(), self._getOccupants(room), room.nick, room.subject)) | 245 result.append((room.roomJID.userhost(), self._getOccupants(room), room.nick, room.subject)) |
239 return result | 246 return result |
240 | 247 |
241 def _getRoomNick(self, room_jid_s, profile_key=C.PROF_KEY_NONE): | 248 def _getRoomNick(self, room_jid_s, profile_key=C.PROF_KEY_NONE): |
242 client = self.host.getClient(profile_key) | 249 client = self.host.getClient(profile_key) |
250 @return: nick or empty string in case of error | 257 @return: nick or empty string in case of error |
251 @raise exceptions.Notfound: use has not joined the room | 258 @raise exceptions.Notfound: use has not joined the room |
252 """ | 259 """ |
253 self.checkRoomJoined(client, room_jid) | 260 self.checkRoomJoined(client, room_jid) |
254 return client._muc_client.joined_rooms[room_jid].nick | 261 return client._muc_client.joined_rooms[room_jid].nick |
255 | |
256 # FIXME: broken, to be removed ! | |
257 # def getRoomEntityNick(self, client, room_jid, entity_jid, =True): | |
258 # """Returns the nick of the given user in the room. | |
259 | |
260 # @param room (wokkel.muc.Room): the room | |
261 # @param user (jid.JID): bare JID of the user | |
262 # @param secure (bool): set to True for a secure check | |
263 # @return: unicode or None if the user didn't join the room. | |
264 # """ | |
265 # for user in room.roster.values(): | |
266 # if user.entity is not None: | |
267 # if user.entity.userhostJID() == user_jid.userhostJID(): | |
268 # return user.nick | |
269 # elif not secure: | |
270 # # FIXME: this is NOT ENOUGH to check an identity!! | |
271 # # See in which conditions user.entity could be None. | |
272 # if user.nick == user_jid.user: | |
273 # return user.nick | |
274 # return None | |
275 | |
276 # def getRoomNicksOfUsers(self, room, users=[], secure=True): | |
277 # """Returns the nicks of the given users in the room. | |
278 | |
279 # @param room (wokkel.muc.Room): the room | |
280 # @param users (list[jid.JID]): list of users | |
281 # @param secure (True): set to True for a secure check | |
282 # @return: a couple (x, y) with: | |
283 # - x (list[unicode]): nicks of the users who are in the room | |
284 # - y (list[jid.JID]): JID of the missing users. | |
285 # """ | |
286 # nicks = [] | |
287 # missing = [] | |
288 # for user in users: | |
289 # nick = self.getRoomNickOfUser(room, user, secure) | |
290 # if nick is None: | |
291 # missing.append(user) | |
292 # else: | |
293 # nicks.append(nick) | |
294 # return nicks, missing | |
295 | 262 |
296 def _configureRoom(self, room_jid_s, profile_key=C.PROF_KEY_NONE): | 263 def _configureRoom(self, room_jid_s, profile_key=C.PROF_KEY_NONE): |
297 client = self.host.getClient(profile_key) | 264 client = self.host.getClient(profile_key) |
298 d = self.configureRoom(client, jid.JID(room_jid_s)) | 265 d = self.configureRoom(client, jid.JID(room_jid_s)) |
299 d.addCallback(lambda xmlui: xmlui.toXml()) | 266 d.addCallback(lambda xmlui: xmlui.toXml()) |
454 def join(self, client, room_jid, nick=None, options=None): | 421 def join(self, client, room_jid, nick=None, options=None): |
455 if not nick: | 422 if not nick: |
456 nick = client.jid.user | 423 nick = client.jid.user |
457 if options is None: | 424 if options is None: |
458 options = {} | 425 options = {} |
459 def _errDeferred(exc_obj=Exception, txt=u'Error while joining room'): | |
460 d = defer.Deferred() | |
461 d.errback(exc_obj(txt)) | |
462 return d | |
463 | |
464 if room_jid in client._muc_client.joined_rooms: | 426 if room_jid in client._muc_client.joined_rooms: |
465 room = client._muc_client.joined_rooms[room_jid] | 427 room = client._muc_client.joined_rooms[room_jid] |
466 log.warning(_(u'{profile} is already in room {room_jid}').format(profile=client.profile, room_jid = room_jid.userhost())) | 428 log.info(_(u'{profile} is already in room {room_jid}').format(profile=client.profile, room_jid = room_jid.userhost())) |
467 return defer.fail(AlreadyJoined(room)) | 429 return defer.fail(AlreadyJoined(room)) |
468 log.info(_(u"[{profile}] is joining room {room} with nick {nick}").format(profile=client.profile, room=room_jid.userhost(), nick=nick)) | 430 log.info(_(u"[{profile}] is joining room {room} with nick {nick}").format(profile=client.profile, room=room_jid.userhost(), nick=nick)) |
469 | 431 |
470 password = options["password"] if "password" in options else None | 432 password = options.get("password") |
471 | 433 |
472 return client._muc_client.join(room_jid, nick, password).addCallbacks(self._joinCb, self._joinEb, (client, room_jid, nick), errbackArgs=(client, room_jid, nick, password)) | 434 return client._muc_client.join(room_jid, nick, password).addCallbacks(self._joinCb, self._joinEb, (client, room_jid, nick), errbackArgs=(client, room_jid, nick, password)) |
473 | 435 |
474 def _nick(self, room_jid_s, nick, profile_key=C.PROF_KEY_NONE): | 436 def _nick(self, room_jid_s, nick, profile_key=C.PROF_KEY_NONE): |
475 client = self.host.getClient(profile_key) | 437 client = self.host.getClient(profile_key) |
774 | 736 |
775 def __init__(self, plugin_parent): | 737 def __init__(self, plugin_parent): |
776 self.plugin_parent = plugin_parent | 738 self.plugin_parent = plugin_parent |
777 self.host = plugin_parent.host | 739 self.host = plugin_parent.host |
778 muc.MUCClient.__init__(self) | 740 muc.MUCClient.__init__(self) |
779 self.rec_subjects = {} | |
780 self._changing_nicks = set() # used to keep trace of who is changing nick, | 741 self._changing_nicks = set() # used to keep trace of who is changing nick, |
781 # and to discard userJoinedRoom signal in this case | 742 # and to discard userJoinedRoom signal in this case |
782 print "init SatMUCClient OK" | 743 print "init SatMUCClient OK" |
783 | 744 |
784 @property | 745 @property |
785 def joined_rooms(self): | 746 def joined_rooms(self): |
786 return self._rooms | 747 return self._rooms |
787 | 748 |
749 def changeRoomState(self, room, new_state): | |
750 """Check that room is in expected state, and change it | |
751 | |
752 @param new_state: one of ROOM_STATE_* | |
753 """ | |
754 new_state_idx = ROOM_STATES.index(new_state) | |
755 if new_state_idx == -1: | |
756 raise exceptions.InternalError("unknown room state") | |
757 if new_state_idx < 1: | |
758 raise exceptions.InternalError("unexpected new room state ({room}): {state}".format( | |
759 room=room.userhost(), | |
760 state=new_state)) | |
761 expected_state = ROOM_STATES[new_state_idx-1] | |
762 if room.state != expected_state: | |
763 log.warning(_(u"room {room} is not in expected state: room is in state {current_state} while we were expecting {expected_state}").format( | |
764 room=room.userhost(), | |
765 current_state=room.state, | |
766 expected_state=expected_state)) | |
767 room.state = new_state | |
768 | |
788 def _addRoom(self, room): | 769 def _addRoom(self, room): |
789 super(SatMUCClient, self)._addRoom(room) | 770 super(SatMUCClient, self)._addRoom(room) |
790 room._roster_ok = False # True when occupants list has been fully received | 771 room._roster_ok = False # True when occupants list has been fully received |
791 room._room_ok = None # False when roster, history and subject are available | 772 room.state = ROOM_STATE_OCCUPANTS |
792 # True when new messages are saved to database | |
793 room._history_d = defer.Deferred() # used to send bridge signal once backlog are written in history | 773 room._history_d = defer.Deferred() # used to send bridge signal once backlog are written in history |
794 room._history_d.callback(None) | 774 room._history_d.callback(None) |
795 # FIXME: check if history_d is not redundant with fully_joined | 775 # FIXME: check if history_d is not redundant with fully_joined |
796 room.fully_joined = defer.Deferred() # called when everything is OK | 776 room.fully_joined = defer.Deferred() # called when everything is OK |
777 # cache data until room is ready | |
778 # list of elements which will be re-injected in stream | |
797 room._cache = [] | 779 room._cache = [] |
798 | 780 |
799 def _gotLastDbHistory(self, mess_data_list, room_jid, nick, password): | 781 @defer.inlineCallbacks |
782 def join(self, room_jid, nick, password=None): | |
783 mess_data_list = yield self.host.memory.historyGet(self.parent.jid.userhostJID(), | |
784 room_jid, | |
785 1, | |
786 True, | |
787 profile=self.parent.profile) | |
800 if mess_data_list: | 788 if mess_data_list: |
801 timestamp = mess_data_list[0][1] | 789 timestamp = mess_data_list[0][1] |
802 # we use seconds since last message to get backlog without duplicates | 790 # we use seconds since last message to get backlog without duplicates |
803 # and we remove 1 second to avoid getting the last message again | 791 # and we remove 1 second to avoid getting the last message again |
804 seconds = int(time.time() - timestamp) - 1 | 792 seconds = int(time.time() - timestamp) - 1 |
805 else: | 793 else: |
806 seconds = None | 794 seconds = None |
807 d = super(SatMUCClient, self).join(room_jid, nick, muc.HistoryOptions(seconds=seconds), password) | 795 room = yield super(SatMUCClient, self).join(room_jid, nick, muc.HistoryOptions(seconds=seconds), password) |
808 return d | 796 defer.returnValue(room) |
809 | |
810 def join(self, room_jid, nick, password=None): | |
811 d = self.host.memory.historyGet(self.parent.jid.userhostJID(), room_jid, 1, True, profile=self.parent.profile) | |
812 d.addCallback(self._gotLastDbHistory, room_jid, nick, password) | |
813 return d | |
814 | 797 |
815 ## presence/roster ## | 798 ## presence/roster ## |
816 | 799 |
817 def availableReceived(self, presence): | 800 def availableReceived(self, presence): |
818 """ | 801 """ |
826 if room is None: | 809 if room is None: |
827 return | 810 return |
828 | 811 |
829 if user is None: | 812 if user is None: |
830 nick = presence.sender.resource | 813 nick = presence.sender.resource |
814 if not nick: | |
815 log.warning(_(u"missing nick in presence: {xml}").format( | |
816 xml = presence.toElement().toXml())) | |
817 return | |
831 user = muc.User(nick, presence.entity) | 818 user = muc.User(nick, presence.entity) |
832 | 819 |
833 # Update user data | 820 # Update user data |
834 user.role = presence.role | 821 user.role = presence.role |
835 user.affiliation = presence.affiliation | 822 user.affiliation = presence.affiliation |
865 self.userLeftRoom(room, user) | 852 self.userLeftRoom(room, user) |
866 | 853 |
867 def userJoinedRoom(self, room, user): | 854 def userJoinedRoom(self, room, user): |
868 if user.nick == room.nick: | 855 if user.nick == room.nick: |
869 # we have received our own nick, this mean that the full room roster was received | 856 # we have received our own nick, this mean that the full room roster was received |
870 room._roster_ok = True | 857 self.changeRoomState(room, ROOM_STATE_SELF_PRESENCE) |
871 log.debug(u"room {room} joined with nick {nick}".format(room=room.occupantJID.userhost(), nick=user.nick)) | 858 log.debug(u"room {room} joined with nick {nick}".format(room=room.occupantJID.userhost(), nick=user.nick)) |
872 # We set type so we don't have use a deferred with disco to check entity type | 859 # We set type so we don't have to use a deferred with disco to check entity type |
873 self.host.memory.updateEntityData(room.roomJID, C.ENTITY_TYPE, ENTITY_TYPE_MUC, profile_key=self.parent.profile) | 860 self.host.memory.updateEntityData(room.roomJID, C.ENTITY_TYPE, ENTITY_TYPE_MUC, profile_key=self.parent.profile) |
874 elif not room._room_ok: | 861 elif room.state not in (ROOM_STATE_OCCUPANTS, ROOM_STATE_LIVE): |
875 log.warning(u"Received user presence data in a room before its initialisation (and after our own presence)," | 862 log.warning(u"Received user presence data in a room before its initialisation (current state: {state})," |
876 "this is not standard! Ignoring it: {} ({})".format( | 863 "this is not standard! Ignoring it: {room} ({nick})".format( |
877 room.roomJID.userhost(), | 864 state=room.state, |
878 user.nick)) | 865 room=room.roomJID.userhost(), |
866 nick=user.nick)) | |
879 return | 867 return |
880 elif room._roster_ok: | 868 else: |
869 if not room.fully_joined.called: | |
870 return | |
881 try: | 871 try: |
882 self._changing_nicks.remove(user.nick) | 872 self._changing_nicks.remove(user.nick) |
883 except KeyError: | 873 except KeyError: |
884 # this is a new user | 874 # this is a new user |
885 log.debug(_(u"user {nick} has joined room {room_id}").format(nick=user.nick, room_id=room.occupantJID.userhost())) | 875 log.debug(_(u"user {nick} has joined room {room_id}").format(nick=user.nick, room_id=room.occupantJID.userhost())) |
901 "subject": {}, | 891 "subject": {}, |
902 "type": C.MESS_TYPE_INFO, | 892 "type": C.MESS_TYPE_INFO, |
903 "extra": extra, | 893 "extra": extra, |
904 "timestamp": time.time(), | 894 "timestamp": time.time(), |
905 } | 895 } |
906 self.parent.messageAddToHistory(mess_data) | 896 # FIXME: we disable presence in history as it's taking a lot of space |
897 # while not indispensable. In the future an option may allow | |
898 # to re-enable it | |
899 # self.parent.messageAddToHistory(mess_data) | |
907 self.parent.messageSendToBridge(mess_data) | 900 self.parent.messageSendToBridge(mess_data) |
908 | 901 |
909 | 902 |
910 def userLeftRoom(self, room, user): | 903 def userLeftRoom(self, room, user): |
911 if not self.host.trigger.point("MUC user left", room, user, self.parent.profile): | 904 if not self.host.trigger.point("MUC user left", room, user, self.parent.profile): |
915 room_jid_s = room.roomJID.userhost() | 908 room_jid_s = room.roomJID.userhost() |
916 log.info(_(u"Room ({room}) left ({profile})").format( | 909 log.info(_(u"Room ({room}) left ({profile})").format( |
917 room = room_jid_s, profile = self.parent.profile)) | 910 room = room_jid_s, profile = self.parent.profile)) |
918 self.host.memory.delEntityCache(room.roomJID, profile_key=self.parent.profile) | 911 self.host.memory.delEntityCache(room.roomJID, profile_key=self.parent.profile) |
919 self.host.bridge.mucRoomLeft(room.roomJID.userhost(), self.parent.profile) | 912 self.host.bridge.mucRoomLeft(room.roomJID.userhost(), self.parent.profile) |
920 elif not room._room_ok: | 913 elif room.state != ROOM_STATE_LIVE: |
921 log.warning(u"Received user presence data in a room before its initialisation (and after our own presence)," | 914 log.warning(u"Received user presence data in a room before its initialisation (current state: {state})," |
922 "this is not standard! Ignoring it: {} ({})".format( | 915 "this is not standard! Ignoring it: {room} ({nick})".format( |
923 room.roomJID.userhost(), | 916 state=room.state, |
924 user.nick)) | 917 room=room.roomJID.userhost(), |
918 nick=user.nick)) | |
925 return | 919 return |
926 else: | 920 else: |
921 if not room.fully_joined.called: | |
922 return | |
927 log.debug(_(u"user {nick} left room {room_id}").format(nick=user.nick, room_id=room.occupantJID.userhost())) | 923 log.debug(_(u"user {nick} left room {room_id}").format(nick=user.nick, room_id=room.occupantJID.userhost())) |
928 extra = {'info_type': ROOM_USER_LEFT, | 924 extra = {'info_type': ROOM_USER_LEFT, |
929 'user_affiliation': user.affiliation, | 925 'user_affiliation': user.affiliation, |
930 'user_role': user.role, | 926 'user_role': user.role, |
931 'user_nick': user.nick | 927 'user_nick': user.nick |
940 "subject": {}, | 936 "subject": {}, |
941 "type": C.MESS_TYPE_INFO, | 937 "type": C.MESS_TYPE_INFO, |
942 "extra": extra, | 938 "extra": extra, |
943 "timestamp": time.time(), | 939 "timestamp": time.time(), |
944 } | 940 } |
945 self.parent.messageAddToHistory(mess_data) | 941 # FIXME: disable history, see userJoinRoom comment |
942 # self.parent.messageAddToHistory(mess_data) | |
946 self.parent.messageSendToBridge(mess_data) | 943 self.parent.messageSendToBridge(mess_data) |
947 | 944 |
948 def userChangedNick(self, room, user, new_nick): | 945 def userChangedNick(self, room, user, new_nick): |
949 self.host.bridge.mucRoomUserChangedNick(room.roomJID.userhost(), user.nick, new_nick, self.parent.profile) | 946 self.host.bridge.mucRoomUserChangedNick(room.roomJID.userhost(), user.nick, new_nick, self.parent.profile) |
950 | 947 |
990 @param room(muc.Room): room instance | 987 @param room(muc.Room): room instance |
991 @param user(muc.User, None): the user that sent the message | 988 @param user(muc.User, None): the user that sent the message |
992 None if the message come from the room | 989 None if the message come from the room |
993 @param message(muc.GroupChat): the parsed message | 990 @param message(muc.GroupChat): the parsed message |
994 """ | 991 """ |
992 if room.state != ROOM_STATE_SELF_PRESENCE: | |
993 log.warning(_(u"received history in unexpected state in room {room} (state: {state})").format( | |
994 room = room.userhost(), | |
995 state = room.state)) | |
995 room._history_d.addCallback(self._addToHistory, user, message) | 996 room._history_d.addCallback(self._addToHistory, user, message) |
996 room._history_d.addErrback(self._addToHistoryEb) | 997 room._history_d.addErrback(self._addToHistoryEb) |
997 | 998 |
998 ## subject ## | 999 ## subject ## |
999 | 1000 |
1020 | 1021 |
1021 def subject(self, room, subject): | 1022 def subject(self, room, subject): |
1022 return muc.MUCClientProtocol.subject(self, room, subject) | 1023 return muc.MUCClientProtocol.subject(self, room, subject) |
1023 | 1024 |
1024 def _historyCb(self, dummy, room): | 1025 def _historyCb(self, dummy, room): |
1026 """Called when history have been written to database and subject is received | |
1027 | |
1028 this method will finish joining by: | |
1029 - sending message to bridge | |
1030 - calling fully_joined deferred | |
1031 - sending stanza put in cache | |
1032 - cleaning variables not needed anymore | |
1033 """ | |
1025 args = self.plugin_parent._getRoomJoinedArgs(room, self.parent.profile) | 1034 args = self.plugin_parent._getRoomJoinedArgs(room, self.parent.profile) |
1026 self.host.bridge.mucRoomJoined(*args) | 1035 self.host.bridge.mucRoomJoined(*args) |
1036 room.fully_joined.callback(room) | |
1027 del room._history_d | 1037 del room._history_d |
1028 cache = room._cache | 1038 cache = room._cache |
1029 del room._cache | 1039 del room._cache |
1030 room._room_ok = True | |
1031 for elem in cache: | 1040 for elem in cache: |
1032 self.parent.xmlstream.dispatch(elem) | 1041 self.parent.xmlstream.dispatch(elem) |
1033 | 1042 |
1034 def _historyEb(self, failure_, room): | 1043 def _historyEb(self, failure_, room): |
1035 log.error(u"Error while managing history: {}".format(failure_)) | 1044 log.error(u"Error while managing history: {}".format(failure_)) |
1037 | 1046 |
1038 def receivedSubject(self, room, user, subject): | 1047 def receivedSubject(self, room, user, subject): |
1039 # when subject is received, we know that we have whole roster and history | 1048 # when subject is received, we know that we have whole roster and history |
1040 # cf. http://xmpp.org/extensions/xep-0045.html#enter-subject | 1049 # cf. http://xmpp.org/extensions/xep-0045.html#enter-subject |
1041 room.subject = subject # FIXME: subject doesn't handle xml:lang | 1050 room.subject = subject # FIXME: subject doesn't handle xml:lang |
1042 self.rec_subjects[room.roomJID.userhost()] = (room.roomJID.userhost(), subject) | 1051 if room.state != ROOM_STATE_LIVE: |
1043 if room._room_ok is None: | 1052 self.changeRoomState(room, ROOM_STATE_LIVE) |
1044 # this is the first subject we receive | |
1045 # that mean that we have received everything we need | |
1046 room._room_ok = False | |
1047 room._history_d.addCallbacks(self._historyCb, self._historyEb, [room], errbackArgs=[room]) | 1053 room._history_d.addCallbacks(self._historyCb, self._historyEb, [room], errbackArgs=[room]) |
1048 room.fully_joined.callback(room) | |
1049 else: | 1054 else: |
1050 # the subject has been changed | 1055 # the subject has been changed |
1051 log.debug(_(u"New subject for room ({room_id}): {subject}").format(room_id = room.roomJID.full(), subject = subject)) | 1056 log.debug(_(u"New subject for room ({room_id}): {subject}").format(room_id = room.roomJID.full(), subject = subject)) |
1052 self.host.bridge.mucRoomNewSubject(room.roomJID.userhost(), subject, self.parent.profile) | 1057 self.host.bridge.mucRoomNewSubject(room.roomJID.userhost(), subject, self.parent.profile) |
1053 | 1058 |