Mercurial > libervia-backend
diff src/plugins/plugin_xep_0045.py @ 507:f98bef71a918
frontends, core, plugin XEP-0045: leave implementation + better nick change
- memory: individual entity cache can be deleted
- plugin XEP-0045: nick change are now detected and userChangedNick signal is sent instead of joined/left
- plugin XEP-0045: leave implementation
- frontends: userChangedNick signal management
- Primitivus: an alert is shown in notification bar in case of error in sendMessage
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 28 Sep 2012 00:26:24 +0200 |
parents | 2402668b5d05 |
children | 64ff046dc201 |
line wrap: on
line diff
--- a/src/plugins/plugin_xep_0045.py Thu Sep 27 00:54:42 2012 +0200 +++ b/src/plugins/plugin_xep_0045.py Fri Sep 28 00:26:24 2012 +0200 @@ -20,24 +20,15 @@ """ from logging import debug, info, warning, error -from twisted.words.xish import domish -from twisted.internet import protocol, defer, threads, reactor -from twisted.words.protocols.jabber import client, jid, xmlstream -from twisted.words.protocols.jabber import error as jab_error -from twisted.words.protocols.jabber.xmlstream import IQ +from twisted.internet import defer +from twisted.words.protocols.jabber import jid from sat.core import exceptions -import os.path import uuid -from zope.interface import implements - -from wokkel import disco, iwokkel, muc +from wokkel import muc -from base64 import b64decode -from hashlib import sha1 -from time import sleep try: from twisted.words.protocols.xmlstream import XMPPHandler @@ -65,15 +56,19 @@ self.host = host self.clients={} host.bridge.addMethod("joinMUC", ".plugin", in_sign='ssa{ss}s', out_sign='', method=self._join) - host.bridge.addMethod("changeNick", ".plugin", in_sign='sss', out_sign='', method=self.changeNick) + host.bridge.addMethod("mucNick", ".plugin", in_sign='sss', out_sign='', method=self.mucNick) + host.bridge.addMethod("mucLeave", ".plugin", in_sign='ss', out_sign='', method=self.leave) host.bridge.addMethod("getRoomsJoined", ".plugin", in_sign='s', out_sign='a(sass)', method=self.getRoomsJoined) host.bridge.addMethod("getRoomsSubjects", ".plugin", in_sign='s', out_sign='a(ss)', method=self.getRoomsSubjects) host.bridge.addMethod("getUniqueRoomName", ".plugin", in_sign='s', out_sign='s', method=self.getUniqueName) host.bridge.addSignal("roomJoined", ".plugin", signature='sasss') #args: room_jid, room_nicks, user_nick, profile + host.bridge.addSignal("roomLeft", ".plugin", signature='ss') #args: room_jid, profile host.bridge.addSignal("roomUserJoined", ".plugin", signature='ssa{ss}s') #args: room_jid, user_nick, user_data, profile host.bridge.addSignal("roomUserLeft", ".plugin", signature='ssa{ss}s') #args: room_jid, user_nick, user_data, profile + host.bridge.addSignal("roomUserChangedNick", ".plugin", signature='ssss') #args: room_jid, old_nick, new_nick, profile host.bridge.addSignal("roomNewSubject", ".plugin", signature='sss') #args: room_jid, subject, profile + def __check_profile(self, profile): """check if profile is used and connected if profile known but disconnected, remove it from known profiles @@ -179,18 +174,30 @@ d = self.join(room_jid, nick, options, profile) d.addErrback(lambda x: warning(_('Error while joining room'))) #TODO: error management + signal in bridge - def nick(self, room_jid, nick, profile_key='@DEFAULT@'): + def nick(self, room_jid, nick, profile_key): profile = self.host.memory.getProfileName(profile_key) if not self.__check_profile(profile): raise exceptions.UnknownProfileError("Unknown or disconnected profile") if not self.clients[profile].joined_rooms.has_key(room_jid.userhost()): raise UnknownRoom("This room has not been joined") return self.clients[profile].nick(room_jid, nick) - - def changeNick(self, room_jid_s, nick, profile_key='@DEFAULT@'): + + def leave(self, room_jid, profile_key): + profile = self.host.memory.getProfileName(profile_key) + if not self.__check_profile(profile): + raise exceptions.UnknownProfileError("Unknown or disconnected profile") + if not self.clients[profile].joined_rooms.has_key(room_jid.userhost()): + raise UnknownRoom("This room has not been joined") + return self.clients[profile].leave(room_jid) + + def mucNick(self, room_jid_s, nick, profile_key='@DEFAULT@'): """Change nickname in a room""" return self.nick(jid.JID(room_jid_s), nick, profile_key) + def mucLeave(self, room_jid_s, profile_key='@DEFAULT@'): + """Leave a room""" + return self.leave(jid.JID(room_jid_s), profile_key) + def getHandler(self, profile): self.clients[profile] = SatMUCClient(self) return self.clients[profile] @@ -206,22 +213,62 @@ muc.MUCClient.__init__(self) self.joined_rooms = {} self.rec_subjects = {} + self.__changing_nicks = set() # used to keep trace of who is changing nick, + # and to discard userJoinedRoom signal in this case print "init SatMUCClient OK" + def unavailableReceived(self, presence): + #XXX: we override this method to manage nickname change + #TODO: feed this back to Wokkel + """ + Unavailable presence was received. + + If this was received from a MUC room occupant JID, that occupant has + left the room. + """ + room, user = self._getRoomUser(presence) + + if room is None or user is None: + return + + room.removeUser(user) + + if muc.STATUS_CODE.NEW_NICK in presence.mucStatuses: + self.__changing_nicks.add(presence.nick) + self.userChangedNick(room, user, presence.nick) + else: + self.__changing_nicks.discard(presence.nick) + self.userLeftRoom(room, user) + def receivedGroupChat(self, room, user, body): debug('receivedGroupChat: room=%s user=%s body=%s', room, user, body) def userJoinedRoom(self, room, user): - debug (_("user %(nick)s has joined room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()}) - if not self.host.trigger.point("MUC user joined", room, user, self.parent.profile): - return - user_data={'entity':user.entity.full() if user.entity else '', 'affiliation':user.affiliation, 'role':user.role} - self.host.bridge.roomUserJoined(room.roomJID.userhost(), user.nick, user_data, self.parent.profile) + if user.nick in self.__changing_nicks: + self.__changing_nicks.remove(user.nick) + else: + debug (_("user %(nick)s has joined room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()}) + if not self.host.trigger.point("MUC user joined", room, user, self.parent.profile): + return + user_data={'entity':user.entity.full() if user.entity else '', 'affiliation':user.affiliation, 'role':user.role} + self.host.bridge.roomUserJoined(room.roomJID.userhost(), user.nick, user_data, self.parent.profile) def userLeftRoom(self, room, user): - debug (_("user %(nick)s left room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()}) - user_data={'entity':user.entity.full() if user.entity else '', 'affiliation':user.affiliation, 'role':user.role} - self.host.bridge.roomUserLeft(room.roomJID.userhost(), user.nick, user_data, self.parent.profile) + if user.nick == room.nick: + # we left the room + room_jid_s = room.roomJID.userhost() + info (_("Room [%(room)s] left (%(profile)s))") % { "room": room_jid_s, + "profile": self.parent.profile }) + self.host.memory.delEntityCache(room.roomJID, self.parent.profile) + del self.plugin_parent.clients[self.parent.profile].joined_rooms[room_jid_s] + self.host.bridge.roomLeft(room.roomJID.userhost(), self.parent.profile) + else: + debug (_("user %(nick)s left room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()}) + user_data={'entity':user.entity.full() if user.entity else '', 'affiliation':user.affiliation, 'role':user.role} + self.host.bridge.roomUserLeft(room.roomJID.userhost(), user.nick, user_data, self.parent.profile) + + def userChangedNick(self, room, user, new_nick): + self.host.bridge.roomUserChangedNick(room.roomJID.userhost(), user.nick, new_nick, self.parent.profile) def userUpdatedStatus(self, room, user, show, status): print("FIXME: MUC status not managed yet") @@ -232,6 +279,7 @@ self.rec_subjects[room.roomJID.userhost()] = (room.roomJID.userhost(), subject) self.host.bridge.roomNewSubject(room.roomJID.userhost(), subject, self.parent.profile) + #def connectionInitialized(self): #pass