Mercurial > xib
view participant.py @ 22:e2bd4de698e5
Solved an XMPP resource conflict that would have happened when someone on IRC changed its nickname and later its old nickname would be used again. In other words, the bot no longer uses nicknames as XMPP resources.
Signed-off-by: Charly COSTE <changaco@changaco.net>
author | Charly COSTE <changaco@changaco.net> |
---|---|
date | Thu, 20 Aug 2009 17:49:40 +0200 |
parents | c1b84196c100 |
children | 1691ab4d131f |
line wrap: on
line source
#!/usr/bin/env python # -*- coding: utf-8 -*- # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import muc xmpp = muc.xmpp del muc import irclib from encoding import * from threading import Thread from time import sleep class participant: def __init__(self, owner_bridge, protocol, nickname): self.bridge = owner_bridge self.protocol = protocol self.nickname = nickname self.irc_connection = None self.xmpp_c = None self.muc = None if protocol == 'xmpp': self.createDuplicateOnIRC() elif protocol == 'irc': self.createDuplicateOnXMPP() else: raise Exception('[Internal Error] bad protocol') def createDuplicateOnXMPP(self): if self.xmpp_c != None or self.irc_connection != None or self.bridge.mode == 'minimal': return self.xmpp_c = self.bridge.bot.get_xmpp_connection(self.nickname) self.muc = xmpp.muc(self.bridge.xmpp_room.room_jid) self.muc.join(self.xmpp_c, self.nickname, status='From IRC', callback=self._xmpp_join_callback) def _xmpp_join_callback(self, errors): if len(errors) == 0: self.bridge.bot.error('===> Debug: "'+self.nickname+'" duplicate succesfully created on XMPP side of bridge "'+str(self.bridge)+'"', debug=True) else: for error in errors: try: raise error except xmpp.muc.NicknameConflict: self.bridge.bot.error('===> Debug: "'+self.nickname+'" is already used in the XMPP MUC or reserved on the XMPP server of bridge "'+str(self.bridge)+'"', debug=True) self.bridge.say('[Warning] The nickname "'+self.nickname+'" is used on both rooms or reserved on the XMPP server, please avoid that if possible') self.bridge.bot.close_xmpp_connection(self.nickname) self.xmpp_c = None def createDuplicateOnIRC(self): if self.irc_connection != None or self.xmpp_c != None or self.bridge.mode != 'normal': return sleep(1) # try to prevent "reconnecting too fast" shit self.irc_connection = self.bridge.bot.irc.server(self.bridge.irc_server, self.bridge.irc_port, self.nickname) self.irc_connection.connect(nick_callback=self._irc_nick_callback) self.irc_connection.join(self.bridge.irc_room) def _irc_nick_callback(self, error, arguments=[]): if error == None: self.irc_connection.join(self.bridge.irc_room) self.bridge.bot.error('===> Debug: "'+self.nickname+'" duplicate succesfully created on IRC side of bridge "'+str(self.bridge)+'"', debug=True) else: if error == 'nicknameinuse': self.bridge.bot.error('===> Debug: "'+self.nickname+'" is already used in the IRC chan of bridge "'+str(self.bridge)+'"', debug=True) self.bridge.say('[Warning] The nickname "'+self.nickname+'" is used on both rooms or reserved on the IRC server, please avoid that if possible') self.irc_connection.close('') self.irc_connection = None elif error == 'erroneusnickname': self.bridge.bot.error('===> Debug: "'+self.nickname+'" got "erroneusnickname" on bridge "'+str(self.bridge)+'"', debug=True) self.bridge.say('[Warning] The nickname "'+self.nickname+'" contains unauthorized characters and cannot be used in the IRC channel, please avoid that if possible') self.irc_connection.close('') self.irc_connection = None elif error == 'nicknametoolong': self.bridge.bot.error('===> Debug: "'+self.nickname+'" got "nicknametoolong" on bridge "'+str(self.bridge)+'"', debug=True) self.bridge.say('[Warning] The nickname "'+self.nickname+'" is too long (limit seems to be '+str(arguments[0])+') and cannot be used in the IRC channel, please avoid that if possible') self.irc_connection.close('') self.irc_connection = None def changeNickname(self, newnick, on_protocol): if self.protocol == 'xmpp': if on_protocol == 'xmpp': self.bridge.removeParticipant('irc', self.nickname, '') self.bridge.addParticipant('irc', newnick) else: self.nickname = newnick if self.irc_connection != None: self.irc_connection.nick(newnick, callback=self._irc_nick_callback) else: self.createDuplicateOnIRC() elif self.protocol == 'irc': if on_protocol == 'irc': self.bridge.removeParticipant('xmpp', self.nickname, '') self.bridge.addParticipant('xmpp', newnick) else: self.nickname = newnick if self.muc != None: self.muc.change_nick(newnick, status='From IRC', callback=self._xmpp_join_callback) else: self.createDuplicateOnXMPP() def sayOnIRC(self, message): if self.protocol == 'irc': raise Exception('[Internal Error] "'+self.nickname+'" comes from IRC') try: if self.irc_connection == None: self.bridge.irc_connection.privmsg(self.bridge.irc_room, '<'+self.nickname+'> '+message) else: self.irc_connection.privmsg(self.bridge.irc_room, message) except EncodingException: self.bridge.say('[Warning] "'+self.nickname+'" is sending messages using an unknown encoding') def sayOnIRCTo(self, to, message): if self.protocol == 'irc': raise Exception('[Internal Error] "'+self.nickname+'" comes from IRC') if self.irc_connection == None: if self.bridge.mode != 'normal': self.bridge.getParticipant(to).sayOnXMPPTo(self.nickname, 'Sorry but cross-protocol private messages are disabled in limited mode.') else: self.bridge.getParticipant(to).sayOnXMPPTo(self.nickname, 'Sorry but you cannot send cross-protocol private messages because I don\'t have an IRC duplicate with your nickname.') else: try: self.irc_connection.privmsg(to, message) except EncodingException: self.bridge.say('[Warning] "'+self.nickname+'" is sending messages using an unknown encoding') def sayOnXMPP(self, message): if self.protocol == 'xmpp': raise Exception('[Internal Error] "'+self.nickname+'" comes from XMPP') try: if self.xmpp_c == None: self.bridge.xmpp_room.say('<'+self.nickname+'> '+auto_decode(message)) else: self.muc.say(auto_decode(message)) except EncodingException: self.bridge.say('[Warning] "'+self.nickname+'" is sending messages using an unknown encoding') def sayOnXMPPTo(self, to, message): if self.protocol == 'xmpp': raise Exception('[Internal Error] "'+self.nickname+'" comes from XMPP') try: self.muc.sayTo(to, auto_decode(message)) except EncodingException: self.bridge.say('[Warning] "'+self.nickname+'" is sending messages using an unknown encoding') def leave(self, message): if message == None: message = '' if self.xmpp_c != None: self.muc.leave(message) self.bridge.bot.close_xmpp_connection(self.nickname) if self.irc_connection != None: self.irc_connection.used_by -= 1 if self.irc_connection.used_by < 1: self.irc_connection.close(message) self.irc_connection = None self.nickname = None def __del__(self): if self.nickname != None: self.leave('')