# HG changeset patch # User Charly COSTE # Date 1265138390 -3600 # Node ID 64a0e9636ae68f13323ea0cc3b0631af176cb5f3 # Parent 489c157d9e8240e54fed5a7a2dfc84712249789d removed encoding.py, charsets handling is now in irclib and custom charsets can be set per server in the configuration file Signed-off-by: Charly COSTE diff --git a/bot.py b/bot.py --- a/bot.py +++ b/bot.py @@ -22,7 +22,6 @@ from time import sleep import traceback import xml.parsers.expat -from encoding import * import irclib import muc xmpp = muc.xmpp @@ -67,10 +66,7 @@ class Bot(threading.Thread): if send_to_admins == True: self._send_message_to_admins(s) if not debug or debug and self.debug: - try: - self.error_fd.write(auto_encode(s)+"\n") - except EncodingException: - self.error_fd.write('Error message cannot be transcoded.\n') + self.error_fd.write(s.encode('utf-8')+"\n") def _xmpp_loop(self): @@ -478,7 +474,7 @@ class Bot(threading.Thread): # A string representation of the event - event_str = '==> Debug: Received IRC event.\nconnection='+connection.__str__()+'\neventtype='+event.eventtype()+'\nsource='+auto_decode(event.source().__str__())+'\ntarget='+auto_decode(event.target().__str__())+'\narguments='+auto_decode(event.arguments().__str__()) + event_str = '==> Debug: Received IRC event.\nconnection='+connection.__str__()+'\neventtype='+event.eventtype()+'\nsource='+repr(event.source())+'\ntarget='+repr(event.target())+'\narguments='+repr(event.arguments()) if event.eventtype() in ['pubmsg', 'action', 'privmsg', 'quit', 'part', 'nick', 'kick']: @@ -676,9 +672,9 @@ class Bot(threading.Thread): pass - def new_bridge(self, xmpp_room, irc_room, irc_server, mode, say_level, irc_port=6667, irc_connection_interval=1): + def new_bridge(self, xmpp_room, irc_room, irc_server, mode, say_level, irc_port=6667, irc_connection_interval=1, irc_charsets=None): """Create a bridge between xmpp_room and irc_room at irc_server.""" - b = Bridge(self, xmpp_room, irc_room, irc_server, mode, say_level, irc_port=irc_port, irc_connection_interval=irc_connection_interval) + b = Bridge(self, xmpp_room, irc_room, irc_server, mode, say_level, irc_port=irc_port, irc_connection_interval=irc_connection_interval, irc_charsets=irc_charsets) self.bridges.append(b) return b diff --git a/bridge.py b/bridge.py --- a/bridge.py +++ b/bridge.py @@ -19,7 +19,6 @@ import re import threading import traceback -from encoding import * from irclib import ServerConnection import muc xmpp = muc.xmpp @@ -43,13 +42,14 @@ class Bridge: class NoSuchParticipantException(Exception): pass - def __init__(self, owner_bot, xmpp_room_jid, irc_room, irc_server, mode, say_level, irc_port=6667, irc_connection_interval=1): + def __init__(self, owner_bot, xmpp_room_jid, irc_room, irc_server, mode, say_level, irc_port=6667, irc_connection_interval=1, irc_charsets=None): """Create a new bridge.""" self.bot = owner_bot self.irc_server = irc_server self.irc_port = irc_port self.irc_room = irc_room.lower() self.irc_connection_interval = irc_connection_interval + self.irc_charsets = irc_charsets self.xmpp_room_jid = xmpp_room_jid if hasattr(self.__class__, '_'+say_level): self.say_level = getattr(self.__class__, '_'+say_level) @@ -78,7 +78,7 @@ class Bridge: try: self.irc_connections_limit = -1 self.irc_connection = self.bot.irc.open_connection(self.irc_server, self.irc_port, self.bot.nickname) - self.irc_connection.connect(nick_callback=self._irc_nick_callback) + self.irc_connection.connect(nick_callback=self._irc_nick_callback, charsets=self.irc_charsets) except: self.bot.error('[Error] joining IRC room failed') raise diff --git a/encoding.py b/encoding.py deleted file mode 100644 --- a/encoding.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/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 . - - -class EncodingException(Exception): pass - - -def auto_encode(s): - for codec in ['utf-8', 'iso8859_15']: - try: - return s.encode(codec) - except (UnicodeEncodeError, UnicodeDecodeError) as e: - print e - pass - raise EncodingException('no suitable codec found') - - -def auto_decode(s): - for codec in ['utf-8', 'iso8859_15']: - try: - return s.decode(codec) - except (UnicodeEncodeError, UnicodeDecodeError) as e: - print e - pass - raise EncodingException('no suitable codec found') \ No newline at end of file diff --git a/example_config.xml b/example_config.xml --- a/example_config.xml +++ b/example_config.xml @@ -6,11 +6,13 @@ - + + + - + diff --git a/irclib.py b/irclib.py --- a/irclib.py +++ b/irclib.py @@ -163,6 +163,7 @@ class IRC: self.connections = [] self.handlers = {} self.delayed_commands = [] # list of tuples in the format (time, function, arguments) + self.charsets = {'': ['utf-8']} self.add_global_handler("ping", _ping_ponger, -42) @@ -424,7 +425,17 @@ class ServerConnection(Connection): def __str__(self): - return self.real_nickname+' at '+self.server+':'+str(self.port) + return self.real_nickname+' at '+self._server_str() + + + def _decode(self, bytes): + charsets = self.irclibobj.charsets[self._server_str()] or self.irclibobj.charsets[''] + for codec in charsets: + try: + return bytes.decode(codec) + except (UnicodeEncodeError, UnicodeDecodeError): + pass + raise Exception, 'no suitable codec found for: '+repr(bytes)+'\ntried: '+' '.join(charsets) def _ping(self): @@ -435,8 +446,12 @@ class ServerConnection(Connection): self.ping(self.get_server_name()) + def _server_str(self): + return self.server+':'+str(self.port) + + def connect(self, password=None, username=None, - ircname=None, localaddress="", localport=0, ssl=False, ipv6=False, nick_callback=None): + ircname=None, localaddress="", localport=0, ssl=False, ipv6=False, nick_callback=None, charsets=None): """Connect to the server. Arguments: @@ -473,6 +488,8 @@ class ServerConnection(Connection): return self if self.socket != 'closed': + if charsets or not self.irclibobj.charsets.has_key(self._server_str()): + self.irclibobj.charsets[self._server_str()] = charsets self.nick_callbacks = [] self.irc_id = None self.previous_buffer = "" @@ -600,6 +617,8 @@ class ServerConnection(Connection): if not line: continue + line = self._decode(line) + prefix = None command = None arguments = None diff --git a/participant.py b/participant.py --- a/participant.py +++ b/participant.py @@ -18,7 +18,6 @@ import re from time import sleep -from encoding import * from irclib import ServerNotConnectedError, ServerConnection import muc xmpp = muc.xmpp @@ -317,12 +316,12 @@ class Participant: def sayOnXMPP(self, message): try: if isinstance(self.xmpp_c, xmpp.client.Client): - self.muc.say(auto_decode(message)) + self.muc.say(message) elif not isinstance(self.irc_connection, ServerConnection): if message[:4] == '/me ': - self.bridge.xmpp_room.say('* '+self.nickname+' '+auto_decode(message[4:])) + self.bridge.xmpp_room.say('* '+self.nickname+' '+message[4:]) else: - self.bridge.xmpp_room.say('<'+self.nickname+'> '+auto_decode(message)) + self.bridge.xmpp_room.say('<'+self.nickname+'> '+message) except EncodingException: self.bridge.say('[Warning] "'+self.nickname+'" is sending messages using an unknown encoding', log=True) @@ -330,7 +329,7 @@ class Participant: def sayOnXMPPTo(self, to, message): try: if isinstance(self.xmpp_c, xmpp.client.Client): - self.muc.sayTo(to, auto_decode(message)) + self.muc.sayTo(to, message) elif not isinstance(self.irc_connection, ServerConnection): if self.bridge.mode != 'normal': self.bridge.getParticipant(to).sayOnXMPPTo(self.nickname, 'Sorry but cross-protocol private messages are disabled in '+self.bridge.mode+' mode.') @@ -349,7 +348,7 @@ class Participant: def _close_xmpp_connection(self, message): if isinstance(self.xmpp_c, xmpp.client.Client): - self.muc.leave(auto_decode(message)) + self.muc.leave(message) self.xmpp_c = None self.bridge.bot.close_xmpp_connection(self.nickname) diff --git a/start_bots_from_xml_config.py b/start_bots_from_xml_config.py --- a/start_bots_from_xml_config.py +++ b/start_bots_from_xml_config.py @@ -65,6 +65,10 @@ for bot_el in config.getElementsByTagNam irc_connection_interval = float(irc.getAttribute('connection_interval')) except ValueError: print '[Error] the value of connection_interval must be a number' + if irc.hasAttribute('charsets'): + irc_charsets = irc.getAttribute('charsets').split() + else: + irc_charsets = None if bridge_el.hasAttribute('say_level'): say_level = bridge_el.getAttribute('say_level') @@ -76,7 +80,7 @@ for bot_el in config.getElementsByTagNam else: mode = 'normal' - bot.new_bridge(xmpp_room.getAttribute('jid'), irc.getAttribute('chan'), irc.getAttribute('server'), mode, say_level, irc_connection_interval=irc_connection_interval) + bot.new_bridge(xmpp_room.getAttribute('jid'), irc.getAttribute('chan'), irc.getAttribute('server'), mode, say_level, irc_connection_interval=irc_connection_interval, irc_charsets=irc_charsets) try: if len(bots) == 0: