comparison src/plugins/plugin_xep_0045.py @ 1358:bf3f669a6052 frontends_multi_profiles

plugins XEP-0045, XEP-0249, parrot: use JID instead of unicode in many methods + class attributes
author souliane <souliane@mailoo.org>
date Wed, 11 Mar 2015 12:35:21 +0100
parents c01cbd8fc8dd
children 876c9fbd0b3d
comparison
equal deleted inserted replaced
1357:f296a54af386 1358:bf3f669a6052
115 @return: the profile name 115 @return: the profile name
116 """ 116 """
117 profile = self.host.memory.getProfileName(profile_key) 117 profile = self.host.memory.getProfileName(profile_key)
118 if not self.checkClient(profile): 118 if not self.checkClient(profile):
119 raise exceptions.ProfileUnknownError("Unknown or disconnected profile") 119 raise exceptions.ProfileUnknownError("Unknown or disconnected profile")
120 if room_jid.userhost() not in self.clients[profile].joined_rooms: 120 if room_jid not in self.clients[profile].joined_rooms:
121 raise UnknownRoom("This room has not been joined") 121 raise UnknownRoom("This room has not been joined")
122 return profile 122 return profile
123 123
124 def __room_joined(self, room, profile): 124 def __room_joined(self, room, profile):
125 """Called when the user is in the requested room""" 125 """Called when the user is in the requested room"""
126 126
127 def _sendBridgeSignal(ignore=None): 127 def _sendBridgeSignal(ignore=None):
128 self.host.bridge.roomJoined(room.roomJID.userhost(), [user.nick for user in room.roster.values()], room.nick, profile) 128 self.host.bridge.roomJoined(room.roomJID.userhost(), [user.nick for user in room.roster.values()], room.nick, profile)
129 129
130 room_jid_s = room.roomJID.userhost() 130 self.clients[profile].joined_rooms[room.roomJID] = room
131 self.clients[profile].joined_rooms[room_jid_s] = room
132 if room.locked: 131 if room.locked:
133 #FIXME: the current behaviour is to create an instant room 132 # FIXME: the current behaviour is to create an instant room
134 #and send the signal only when the room is unlocked 133 # and send the signal only when the room is unlocked
135 #a proper configuration management should be done 134 # a proper configuration management should be done
136 print "room locked !" 135 print "room locked !"
137 self.clients[profile].configure(room.roomJID, {}).addCallbacks(_sendBridgeSignal, lambda x: log.error(_('Error while configuring the room'))) 136 self.clients[profile].configure(room.roomJID, {}).addCallbacks(_sendBridgeSignal, lambda x: log.error(_('Error while configuring the room')))
138 else: 137 else:
139 _sendBridgeSignal() 138 _sendBridgeSignal()
140 return room 139 return room
162 return result 161 return result
163 for room in self.clients[profile].joined_rooms.values(): 162 for room in self.clients[profile].joined_rooms.values():
164 result.append((room.roomJID.userhost(), [user.nick for user in room.roster.values()], room.nick)) 163 result.append((room.roomJID.userhost(), [user.nick for user in room.roster.values()], room.nick))
165 return result 164 return result
166 165
167 def getRoomNick(self, room_jid_s, profile_key=C.PROF_KEY_NONE): 166 def getRoomNick(self, room_jid, profile_key=C.PROF_KEY_NONE):
168 """return nick used in room by user 167 """return nick used in room by user
169 168
170 @param room_jid_s: unicode room id 169 @param room_jid (jid.JID): JID of the room
171 @profile_key: profile 170 @profile_key: profile
172 @return: nick or empty string in case of error""" 171 @return: nick or empty string in case of error"""
173 profile = self.host.memory.getProfileName(profile_key) 172 profile = self.host.memory.getProfileName(profile_key)
174 if not self.checkClient(profile) or room_jid_s not in self.clients[profile].joined_rooms: 173 if not self.checkClient(profile) or room_jid not in self.clients[profile].joined_rooms:
175 return '' 174 return ''
176 return self.clients[profile].joined_rooms[room_jid_s].nick 175 return self.clients[profile].joined_rooms[room_jid].nick
177 176
178 def getRoomNickOfUser(self, room, user_jid, secure=True): 177 def getRoomNickOfUser(self, room, user_jid, secure=True):
179 """Returns the nick of the given user in the room. 178 """Returns the nick of the given user in the room.
180 179
181 @room: instance of wokkel.muc.Room 180 @param room (wokkel.muc.Room): the room
182 @user: JID or unicode (JID userhost). 181 @param user (jid.JID): bare JID of the user
183 @param secure: set to True for a secure check 182 @param secure (bool): set to True for a secure check
184 @return: the nick or None if the user didn't join the room. 183 @return: unicode or None if the user didn't join the room.
185 """ 184 """
186 if not isinstance(user_jid, jid.JID):
187 user_jid = jid.JID(user_jid).userhostJID()
188 for user in room.roster.values(): 185 for user in room.roster.values():
189 if user.entity is not None: 186 if user.entity is not None:
190 if user.entity.userhostJID() == user_jid.userhostJID(): 187 if user.entity.userhostJID() == user_jid.userhostJID():
191 return user.nick 188 return user.nick
192 elif not secure: 189 elif not secure:
197 return None 194 return None
198 195
199 def getRoomNicksOfUsers(self, room, users=[], secure=True): 196 def getRoomNicksOfUsers(self, room, users=[], secure=True):
200 """Returns the nicks of the given users in the room. 197 """Returns the nicks of the given users in the room.
201 198
202 @room: instance of wokkel.muc.Room 199 @param room (wokkel.muc.Room): the room
203 @users: list of JID or unicode (JID userhost). 200 @param users (list[jid.JID]): list of users
204 @param secure: set to True for a secure check 201 @param secure (True): set to True for a secure check
205 @return: (x, y) with x a list containing the nicks of 202 @return: a couple (x, y) with:
206 the users who are in the room, and y the missing users. 203 - x (list[unicode]): nicks of the users who are in the room
204 - y (list[jid.JID]): JID of the missing users.
207 """ 205 """
208 nicks = [] 206 nicks = []
209 missing = [] 207 missing = []
210 for user in users: 208 for user in users:
211 nick = self.getRoomNickOfUser(room, user, secure) 209 nick = self.getRoomNickOfUser(room, user, secure)
229 try: 227 try:
230 room_jid = jid.JID(menu_data['room_jid']) 228 room_jid = jid.JID(menu_data['room_jid'])
231 except KeyError: 229 except KeyError:
232 log.error(_("room_jid key is not present !")) 230 log.error(_("room_jid key is not present !"))
233 return defer.fail(exceptions.DataError) 231 return defer.fail(exceptions.DataError)
232
234 def xmluiReceived(xmlui): 233 def xmluiReceived(xmlui):
235 return {"xmlui": xmlui.toXml()} 234 return {"xmlui": xmlui.toXml()}
236 return self.configureRoom(room_jid, profile).addCallback(xmluiReceived) 235 return self.configureRoom(room_jid, profile).addCallback(xmluiReceived)
237 236
238 def configureRoom(self, room_jid, profile_key=C.PROF_KEY_NONE): 237 def configureRoom(self, room_jid, profile_key=C.PROF_KEY_NONE):
275 return d 274 return d
276 275
277 def isNickInRoom(self, room_jid, nick, profile): 276 def isNickInRoom(self, room_jid, nick, profile):
278 """Tell if a nick is currently present in a room""" 277 """Tell if a nick is currently present in a room"""
279 profile = self.getProfileAssertInRoom(room_jid, profile) 278 profile = self.getProfileAssertInRoom(room_jid, profile)
280 return self.clients[profile].joined_rooms[room_jid.userhost()].inRoster(muc.User(nick)) 279 return self.clients[profile].joined_rooms[room_jid].inRoster(muc.User(nick))
281 280
282 def getRoomsSubjects(self, profile_key=C.PROF_KEY_NONE): 281 def getRoomsSubjects(self, profile_key=C.PROF_KEY_NONE):
283 """Return received subjects of rooms""" 282 """Return received subjects of rooms"""
284 profile = self.host.memory.getProfileName(profile_key) 283 profile = self.host.memory.getProfileName(profile_key)
285 if not self.checkClient(profile): 284 if not self.checkClient(profile):
294 @param profile_key: %(doc_profile_key)s 293 @param profile_key: %(doc_profile_key)s
295 """ 294 """
296 muc_service = None 295 muc_service = None
297 services = yield self.host.findServiceEntities("conference", "text", jid_, profile_key=profile_key) 296 services = yield self.host.findServiceEntities("conference", "text", jid_, profile_key=profile_key)
298 for service in services: 297 for service in services:
299 if not ".irc." in service.userhost(): 298 if ".irc." not in service.userhost():
300 # FIXME: 299 # FIXME:
301 # This ugly hack is here to avoid an issue with openfire: the IRC gateway 300 # This ugly hack is here to avoid an issue with openfire: the IRC gateway
302 # use "conference/text" identity (instead of "conference/irc") 301 # use "conference/text" identity (instead of "conference/irc")
303 muc_service = service 302 muc_service = service
304 break 303 break
311 """Return unique name for a room, avoiding collision 310 """Return unique name for a room, avoiding collision
312 311
313 @param muc_service (jid.JID) : leave empty string to use the default service 312 @param muc_service (jid.JID) : leave empty string to use the default service
314 @return: jid.JID (unique room bare JID) 313 @return: jid.JID (unique room bare JID)
315 """ 314 """
316 #TODO: we should use #RFC-0045 10.1.4 when available here 315 # TODO: we should use #RFC-0045 10.1.4 when available here
317 client = self.host.getClient(profile_key) 316 client = self.host.getClient(profile_key)
318 room_name = uuid.uuid1() 317 room_name = uuid.uuid1()
319 if muc_service is None: 318 if muc_service is None:
320 try: 319 try:
321 muc_service = client.muc_service 320 muc_service = client.muc_service
335 return d 334 return d
336 335
337 profile = self.host.memory.getProfileName(profile_key) 336 profile = self.host.memory.getProfileName(profile_key)
338 if not self.checkClient(profile): 337 if not self.checkClient(profile):
339 return _errDeferred() 338 return _errDeferred()
340 if room_jid.userhost() in self.clients[profile].joined_rooms: 339 if room_jid in self.clients[profile].joined_rooms:
341 log.warning(_('%(profile)s is already in room %(room_jid)s') % {'profile': profile, 'room_jid': room_jid.userhost()}) 340 log.warning(_('%(profile)s is already in room %(room_jid)s') % {'profile': profile, 'room_jid': room_jid.userhost()})
342 return _errDeferred() 341 return _errDeferred()
343 log.info(_("[%(profile)s] is joining room %(room)s with nick %(nick)s") % {'profile': profile, 'room': room_jid.userhost(), 'nick': nick}) 342 log.info(_("[%(profile)s] is joining room %(room)s with nick %(nick)s") % {'profile': profile, 'room': room_jid.userhost(), 'nick': nick})
344 343
345 if "history" in options: 344 if "history" in options:
470 if mess_data['type'] != "groupchat": 469 if mess_data['type'] != "groupchat":
471 self.host.plugins[C.TEXT_CMDS].feedBackWrongContext('join', 'groupchat', mess_data, profile) 470 self.host.plugins[C.TEXT_CMDS].feedBackWrongContext('join', 'groupchat', mess_data, profile)
472 return False 471 return False
473 472
474 if mess_data["unparsed"].strip(): 473 if mess_data["unparsed"].strip():
475 room = self.host.plugins[C.TEXT_CMDS].getRoomJID(mess_data["unparsed"].strip(), mess_data["to"].host) 474 room_jid = self.host.plugins[C.TEXT_CMDS].getRoomJID(mess_data["unparsed"].strip(), mess_data["to"].host)
476 nick = (self.getRoomNick(mess_data["to"].userhost(), profile) or 475 nick = (self.getRoomNick(room_jid, profile) or
477 self.host.getClient(profile).jid.user) 476 self.host.getClient(profile).jid.user)
478 self.join(room, nick, {}, profile) 477 self.join(room_jid, nick, {}, profile)
479 478
480 return False 479 return False
481 480
482 def cmd_leave(self, mess_data, profile): 481 def cmd_leave(self, mess_data, profile):
483 """quit a room""" 482 """quit a room"""
629 628
630 def _whois(self, whois_msg, mess_data, target_jid, profile): 629 def _whois(self, whois_msg, mess_data, target_jid, profile):
631 """ Add MUC user information to whois """ 630 """ Add MUC user information to whois """
632 if mess_data['type'] != "groupchat": 631 if mess_data['type'] != "groupchat":
633 return 632 return
634 if target_jid.userhost() not in self.clients[profile].joined_rooms: 633 if target_jid.userhostJID() not in self.clients[profile].joined_rooms:
635 log.warning(_("This room has not been joined")) 634 log.warning(_("This room has not been joined"))
636 return 635 return
637 user = self.clients[profile].joined_rooms[target_jid.userhost()].getUser(target_jid.resource) 636 user = self.clients[profile].joined_rooms[target_jid.userhostJID()].getUser(target_jid.resource)
638 whois_msg.append(_("Nickname: %s") % user.nick) 637 whois_msg.append(_("Nickname: %s") % user.nick)
639 if user.entity: 638 if user.entity:
640 whois_msg.append(_("Entity: %s") % user.entity) 639 whois_msg.append(_("Entity: %s") % user.entity)
641 if user.affiliation != 'none': 640 if user.affiliation != 'none':
642 whois_msg.append(_("Affiliation: %s") % user.affiliation) 641 whois_msg.append(_("Affiliation: %s") % user.affiliation)
648 whois_msg.append(_("Show: %s") % user.show) 647 whois_msg.append(_("Show: %s") % user.show)
649 648
650 def presenceTrigger(self, presence_elt, client): 649 def presenceTrigger(self, presence_elt, client):
651 # XXX: shouldn't it be done by the server ?!! 650 # XXX: shouldn't it be done by the server ?!!
652 muc_client = self.clients[client.profile] 651 muc_client = self.clients[client.profile]
653 for room_jid_s, room in muc_client.joined_rooms.items(): 652 for room_jid, room in muc_client.joined_rooms.iteritems():
654 elt = copy.deepcopy(presence_elt) 653 elt = copy.deepcopy(presence_elt)
655 elt['to'] = room_jid_s + '/' + room.nick 654 elt['to'] = room_jid.userhost() + '/' + room.nick
656 client.presence.send(elt) 655 client.presence.send(elt)
657 return True 656 return True
658 657
659 658
660 class SatMUCClient (muc.MUCClient): 659 class SatMUCClient (muc.MUCClient):
661 #implements(iwokkel.IDisco) 660 # implements(iwokkel.IDisco)
662 661
663 def __init__(self, plugin_parent): 662 def __init__(self, plugin_parent):
664 self.plugin_parent = plugin_parent 663 self.plugin_parent = plugin_parent
665 self.host = plugin_parent.host 664 self.host = plugin_parent.host
666 muc.MUCClient.__init__(self) 665 muc.MUCClient.__init__(self)
667 self.joined_rooms = {} # FIXME: seem to do the same thing as MUCClient's _rooms attribute, must be removed
668 self.rec_subjects = {} 666 self.rec_subjects = {}
669 self.__changing_nicks = set() # used to keep trace of who is changing nick, 667 self.__changing_nicks = set() # used to keep trace of who is changing nick,
670 # and to discard userJoinedRoom signal in this case 668 # and to discard userJoinedRoom signal in this case
671 print "init SatMUCClient OK" 669 print "init SatMUCClient OK"
672 670
671 @property
672 def joined_rooms(self):
673 return self._rooms
674
673 def subject(self, room, subject): 675 def subject(self, room, subject):
674 return muc.MUCClientProtocol.subject(self, room, subject) 676 return muc.MUCClientProtocol.subject(self, room, subject)
675 677
676 def unavailableReceived(self, presence): 678 def unavailableReceived(self, presence):
677 #XXX: we override this method to manage nickname change 679 # XXX: we override this method to manage nickname change
678 #TODO: feed this back to Wokkel 680 # TODO: feed this back to Wokkel
679 """ 681 """
680 Unavailable presence was received. 682 Unavailable presence was received.
681 683
682 If this was received from a MUC room occupant JID, that occupant has 684 If this was received from a MUC room occupant JID, that occupant has
683 left the room. 685 left the room.
712 return 714 return
713 if user.nick == room.nick: 715 if user.nick == room.nick:
714 # we left the room 716 # we left the room
715 room_jid_s = room.roomJID.userhost() 717 room_jid_s = room.roomJID.userhost()
716 log.info(_("Room [%(room)s] left (%(profile)s))") % {"room": room_jid_s, 718 log.info(_("Room [%(room)s] left (%(profile)s))") % {"room": room_jid_s,
717 "profile": self.parent.profile}) 719 "profile": self.parent.profile})
718 self.host.memory.delEntityCache(room.roomJID, profile_key=self.parent.profile) 720 self.host.memory.delEntityCache(room.roomJID, profile_key=self.parent.profile)
719 del self.plugin_parent.clients[self.parent.profile].joined_rooms[room_jid_s]
720 self.host.bridge.roomLeft(room.roomJID.userhost(), self.parent.profile) 721 self.host.bridge.roomLeft(room.roomJID.userhost(), self.parent.profile)
721 else: 722 else:
722 log.debug(_("user %(nick)s left room (%(room_id)s)") % {'nick': user.nick, 'room_id': room.occupantJID.userhost()}) 723 log.debug(_("user %(nick)s left room (%(room_id)s)") % {'nick': user.nick, 'room_id': room.occupantJID.userhost()})
723 user_data = {'entity': user.entity.full() if user.entity else '', 'affiliation': user.affiliation, 'role': user.role} 724 user_data = {'entity': user.entity.full() if user.entity else '', 'affiliation': user.affiliation, 'role': user.role}
724 self.host.bridge.roomUserLeft(room.roomJID.userhost(), user.nick, user_data, self.parent.profile) 725 self.host.bridge.roomUserLeft(room.roomJID.userhost(), user.nick, user_data, self.parent.profile)
732 def receivedGroupChat(self, room, user, body): 733 def receivedGroupChat(self, room, user, body):
733 log.debug('receivedGroupChat: room=%s user=%s body=%s' % (room.roomJID.full(), user, body)) 734 log.debug('receivedGroupChat: room=%s user=%s body=%s' % (room.roomJID.full(), user, body))
734 735
735 def receivedHistory(self, room, user, message): 736 def receivedHistory(self, room, user, message):
736 # http://xmpp.org/extensions/xep-0045.html#enter-history 737 # http://xmpp.org/extensions/xep-0045.html#enter-history
737 #log.debug('receivedHistory: room=%s user=%s body=%s' % (room.roomJID.full(), user, message)) 738 # log.debug('receivedHistory: room=%s user=%s body=%s' % (room.roomJID.full(), user, message))
738 pass 739 pass
739 740
740 def receivedSubject(self, room, user, subject): 741 def receivedSubject(self, room, user, subject):
741 # http://xmpp.org/extensions/xep-0045.html#enter-subject 742 # http://xmpp.org/extensions/xep-0045.html#enter-subject
742 log.debug(_("New subject for room (%(room_id)s): %(subject)s") % {'room_id': room.roomJID.full(), 'subject': subject}) 743 log.debug(_("New subject for room (%(room_id)s): %(subject)s") % {'room_id': room.roomJID.full(), 'subject': subject})