Mercurial > xib
diff participant.py @ 118:b29fd5696a78
new mode bypass and new method bridge.changeMode
Signed-off-by: Charly COSTE <changaco@changaco.net>
author | Charly COSTE <changaco@changaco.net> |
---|---|
date | Sat, 28 Nov 2009 23:47:11 +0100 |
parents | d062efcfbe9d |
children | 75a03f10a863 |
line wrap: on
line diff
--- a/participant.py +++ b/participant.py @@ -22,6 +22,7 @@ from irclib import ServerNotConnectedErr from encoding import * from threading import Thread from time import sleep +import re class participant: @@ -31,37 +32,70 @@ class participant: self.bridge = owner_bridge self.protocol = protocol self.nickname = nickname + self.duplicate_nickname = self.nickname self.irc_connection = None self.xmpp_c = None self.muc = None - if protocol == 'xmpp': + if protocol == 'xmpp' and self.bridge.mode in ['normal', 'bypass']: self.createDuplicateOnIRC() - elif protocol == 'irc': + elif protocol == 'irc' and self.bridge.mode != 'minimal': self.createDuplicateOnXMPP() - else: - raise Exception('[Internal Error] bad protocol') + + + def _get_new_duplicate_nickname(self): + new_duplicate_nickname = self.duplicate_nickname + for i in xrange(5): + new_duplicate_nickname = new_duplicate_nickname+'_' + if not self.bridge.hasParticipant(new_duplicate_nickname): + return new_duplicate_nickname + return None def createDuplicateOnXMPP(self): - if isinstance(self.xmpp_c, xmpp.client.Client) or isinstance(self.irc_connection, ServerConnection) or self.bridge.mode == 'minimal' or self.nickname == 'ChanServ': + if isinstance(self.xmpp_c, xmpp.client.Client) or isinstance(self.irc_connection, ServerConnection): return - self.xmpp_c = self.bridge.bot.get_xmpp_connection(self.nickname) + self.xmpp_c = self.bridge.bot.get_xmpp_connection(self.duplicate_nickname) self.muc = xmpp.muc(self.bridge.xmpp_room_jid) - self.muc.join(self.xmpp_c, self.nickname, status='From IRC', callback=self._xmpp_join_callback) + self.join_muc() + + + def join_muc(self): + self.muc.join(self.xmpp_c, self.duplicate_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) + m = '===> Debug: "'+self.nickname+'" duplicate succesfully created on XMPP side of bridge "'+str(self.bridge)+'"' + if self.nickname != self.duplicate_nickname: + m += ' using nickname "'+self.duplicate_nickname+'"' + self.bridge.say('[Info] "'+self.nickname+'" will appear as "'+self.duplicate_nickname+'" on XMPP because its real nickname is reserved or contains unauthorized characters') + self.bridge.bot.error(m, debug=True) elif self.xmpp_c != 'both': 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') - if self.muc.connected == True: - self.muc.leave('Changed nickname to "'+self.nickname+'"') + except xmpp.muc.NicknameConflict as e: + if xmpp.protocol.JID(e.args[0]).getResource() != self.duplicate_nickname: + return + + if self.bridge.mode == 'bypass': + new_duplicate_nickname = self._get_new_duplicate_nickname() + if new_duplicate_nickname != None: + self.bridge.bot.error('===> Debug: "'+self.duplicate_nickname+'" is already used in the XMPP MUC or reserved on the XMPP server of bridge "'+str(self.bridge)+'", trying "'+new_duplicate_nickname+'"', debug=True) + if self.duplicate_nickname == self.nickname: + self.bridge.say('[Info] The nickname "'+self.duplicate_nickname+'" is used on both rooms or reserved on the XMPP server, please avoid that if possible') + self.duplicate_nickname = new_duplicate_nickname + if isinstance(self.xmpp_c, xmpp.client.Client): + self.bridge.bot.close_xmpp_connection(self.nickname) + self.xmpp_c = None + self.createDuplicateOnXMPP() + return + + else: + 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') + if self.muc.connected == True: + self.muc.leave('Changed nickname to "'+self.nickname+'"') except xmpp.muc.RoomIsFull: self.bridge.bot.error('[Warning] XMPP MUC of bridge "'+str(self.bridge)+'" is full', send_to_admins=True) self.bridge.say('[Warning] XMPP room is full') @@ -72,30 +106,61 @@ class participant: def createDuplicateOnIRC(self): - if isinstance(self.xmpp_c, xmpp.client.Client) or isinstance(self.irc_connection, ServerConnection) or self.bridge.mode != 'normal': + if isinstance(self.xmpp_c, xmpp.client.Client) or isinstance(self.irc_connection, ServerConnection): 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 = self.bridge.bot.irc.server(self.bridge.irc_server, self.bridge.irc_port, self.duplicate_nickname) self.irc_connection.connect(nick_callback=self._irc_nick_callback) 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) + m = '===> Debug: "'+self.nickname+'" duplicate succesfully created on IRC side of bridge "'+str(self.bridge)+'"' + if self.nickname != self.duplicate_nickname: + m += ' using nickname "'+self.duplicate_nickname+'"' + self.bridge.say('[Info] "'+self.nickname+'" will appear as "'+self.duplicate_nickname+'" on IRC because its real nickname is reserved or contains unauthorized characters') + self.bridge.bot.error(m, debug=True) + elif self.irc_connection != 'both': - if error == 'nicknameinuse': - self.bridge.bot.error('===> Debug: "'+self.nickname+'" is used or reserved on the IRC server of bridge "'+str(self.bridge)+'"', debug=True) - self.bridge.say('[Warning] The nickname "'+self.nickname+'" is used or reserved on the IRC server, please avoid that if possible') - elif error == 'nickcollision': - self.bridge.bot.error('===> Debug: "'+self.nickname+'" is used or reserved on the IRC server of bridge "'+str(self.bridge)+'"', debug=True) - self.bridge.say('[Warning] The nickname "'+self.nickname+'" is used or reserved on the IRC server, please avoid that if possible') + + if error in ['nicknameinuse', 'nickcollision']: + if arguments[0].arguments()[0] != self.duplicate_nickname: + return + + if self.bridge.mode == 'bypass': + new_duplicate_nickname = self._get_new_duplicate_nickname() + if new_duplicate_nickname != None: + self.bridge.bot.error('===> Debug: "'+self.duplicate_nickname+'" is already used or reserved on the IRC server of bridge "'+str(self.bridge)+'", trying "'+new_duplicate_nickname+'"', debug=True) + if self.duplicate_nickname == self.nickname: + self.bridge.say('[Info] The nickname "'+self.duplicate_nickname+'" is used or reserved on the IRC server, please avoid that if possible') + self.duplicate_nickname = new_duplicate_nickname + if isinstance(self.irc_connection, ServerConnection): + self.irc_connection.close('') + self.irc_connection = error + self.createDuplicateOnIRC() + return + + else: + self.bridge.bot.error('===> Debug: "'+self.nickname+'" is used or reserved on the IRC server of bridge "'+str(self.bridge)+'"', debug=True) + self.bridge.say('[Warning] The nickname "'+self.nickname+'" is used or reserved on the IRC server, please avoid that if possible') + 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') + if self.bridge.mode == 'bypass': + self.duplicate_nickname = re.sub('[^a-zA-Z]', '', self.nickname) + if isinstance(self.irc_connection, ServerConnection): + self.irc_connection.close('') + self.irc_connection = error + self.createDuplicateOnIRC() + return + else: + 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') + 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') + else: self.bridge.bot.error('===> Debug: unknown error while adding "'+self.nickname+'" to IRC side of bridge "'+str(self.bridge)+'"', debug=True) self.bridge.say('[Warning] unknown error while adding "'+self.nickname+'" to IRC side of bridge') @@ -117,6 +182,7 @@ class participant: else: self.nickname = newnick + self.duplicate_nickname = newnick if isinstance(self.irc_connection, ServerConnection): if self.irc_connection.used_by == 1: self.irc_connection.nick(newnick, callback=self._irc_nick_callback) @@ -135,6 +201,7 @@ class participant: else: self.nickname = newnick + self.duplicate_nickname = newnick if isinstance(self.xmpp_c, xmpp.client.Client): for b in self.bridge.bot.bridges: if b.hasParticipant(oldnick) and b.irc_server != self.bridge.irc_server: @@ -227,7 +294,6 @@ class participant: message = '' self._close_xmpp_connection(message) self._close_irc_connection(message) - self.nickname = None def _close_xmpp_connection(self, message): @@ -256,5 +322,4 @@ class participant: def __del__(self): - if self.nickname != None: - self.leave('') \ No newline at end of file + self.leave('')