Mercurial > xib
diff participant.py @ 0:4c842d23d4ce
Initial commit, version 0.1
Signed-off-by: Charly COSTE <changaco@changaco.net>
author | Charly COSTE <changaco@changaco.net> |
---|---|
date | Sun, 16 Aug 2009 01:47:03 +0200 |
parents | |
children | 3f651f4fdb4f |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/participant.py @@ -0,0 +1,197 @@ +#!/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 + if protocol == 'xmpp': + self.createDuplicateOnIRC() + elif protocol == 'irc': + self.createDuplicateOnXMPP() + else: + raise Exception('Internal Error: bad protocol') + quit(1) + + + def createDuplicateOnXMPP(self): + if self.xmpp_c != None or self.irc_connection != None or self.protocol == 'both' or self.bridge.mode == 'minimal': + return + self.xmpp_c = xmpp.client.Client(self.bridge.bot.jid.getDomain(), debug=[]) + self.xmpp_c.connect() + self.xmpp_c.auth(self.bridge.bot.jid.getNode(), self.bridge.bot.password, resource=self.nickname) + self.xmpp_c.RegisterHandler('presence', self.bridge.bot._xmpp_presence_handler) + self.xmpp_c.RegisterHandler('iq', self.bridge.bot._xmpp_iq_handler) + self.xmpp_c.RegisterHandler('message', self.bridge.bot._xmpp_message_handler) + self.xmpp_thread = Thread(target=self._xmpp_loop) + self.xmpp_thread.start() + self.xmpp_c.sendInitPresence() + 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 createDuplicateOnIRC(self): + if self.irc_connection != None or self.xmpp_c != None or self.protocol == 'both' or self.bridge.mode != 'normal': + return + sleep(1) # try to prevent "reconnecting too fast" shit + self.irc_connection = self.bridge.bot.irc.server() + self.irc_connection.bridge = self.bridge + self.irc_connection.nick_callback = self._irc_nick_callback + self.irc_connection.connect(self.bridge.irc_server, self.bridge.irc_port, self.nickname) + + + def _irc_nick_callback(self, error): + if error == None: + self.irc_connection.join(self.bridge.irc_room) + self.irc_connection.nick_callback = None + self.bridge.bot.error('===> Debug: "'+self.nickname+'" duplicate succesfully created on IRC side of bridge "'+str(self.bridge)+'"', debug=True) + elif self.protocol != 'both': + 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, please avoid that if possible') + self.protocol = 'both' + 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 non-ASCII characters and cannot be used in the IRC channel, please avoid that if possible') + self.irc_connection.close() + self.irc_connection = None + + + 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) + elif self.protocol != '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') + self.protocol = 'both' + self.xmpp_c = None + + + def _xmpp_loop(self): + while True: + if self.xmpp_c != None: + self.xmpp_c.Process(5) + else: + sleep(5) + + + def changeNickname(self, newnick, on_protocol): + if self.protocol == 'xmpp': + if on_protocol == 'xmpp': + raise Exception('Internal Error: wanted to change nickname on bad protocol') + if self.irc_connection: + self.irc_connection.nick(newnick) + self.nickname = newnick + elif self.protocol == 'irc': + if on_protocol == 'irc': + raise Exception('Internal Error: wanted to change nickname on bad protocol') + if self.muc: + self.muc.change_nick(newnick, callback=self._xmpp_join_callback) + self.nickname = newnick + elif self.protocol == 'both': + if on_protocol == 'irc': + self.protocol = 'xmpp' + self.createDuplicateOnIRC() + elif on_protocol == 'xmpp': + self.protocol = 'irc' + self.createDuplicateOnXMPP() + + + def sayOnIRC(self, message): + try: + if self.protocol == 'irc': + raise Exception('Internal Error: "'+self.nickname+'" comes from IRC') + elif self.protocol == 'both' or 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') + elif 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') + elif self.protocol == 'both' or self.xmpp_c == None: + self.bridge.xmpp_room.say('<'+self.nickname+'> '+auto_decode(message)) + else: + try: + 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') + else: + 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 = '' + try: + self.muc.leave(message) + except AttributeError: + pass + try: + self.irc_connection.disconnect(message) + except AttributeError: + pass + self.nickname = None + + + def __del__(self): + if self.nickname != None: + self.leave('') \ No newline at end of file