From 3d22bbe87d4da949f0f0a202a9deec27df89034d Mon Sep 17 00:00:00 2001 From: Alexei Sorokin Date: Fri, 29 Jul 2016 16:19:05 +0300 Subject: [PATCH] Use UTF-8 in IRC --- lib/ircbot.py | 9 +++++++-- lib/irclib.py | 29 ++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/ircbot.py b/lib/ircbot.py index 46a8c67..2a539ad 100644 --- a/lib/ircbot.py +++ b/lib/ircbot.py @@ -45,7 +45,8 @@ class SingleServerIRCBot(SimpleIRCClient): have operator or voice modes. The "database" is kept in the self.channels attribute, which is an IRCDict of Channels. """ - def __init__(self, server_list, nickname, realname, reconnection_interval=60): + def __init__(self, server_list, nickname, realname, + reconnection_interval=60, encoding="utf-8"): """Constructor for SingleServerIRCBot objects. Arguments: @@ -61,6 +62,8 @@ class SingleServerIRCBot(SimpleIRCClient): reconnection_interval -- How long the bot should wait before trying to reconnect. + encoding -- An encoding to use. + dcc_connections -- A list of initiated/accepted DCC connections. """ @@ -74,6 +77,7 @@ class SingleServerIRCBot(SimpleIRCClient): self._nickname = nickname self._realname = realname + self._encoding = encoding for i in ["disconnect", "join", "kick", "mode", "namreply", "nick", "part", "quit"]: self.connection.add_global_handler(i, @@ -96,7 +100,8 @@ class SingleServerIRCBot(SimpleIRCClient): self.server_list[0][1], self._nickname, password, - ircname=self._realname) + ircname=self._realname, + encoding=self._encoding) except ServerConnectionError: pass diff --git a/lib/irclib.py b/lib/irclib.py index ab12909..76e2330 100644 --- a/lib/irclib.py +++ b/lib/irclib.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + # Copyright (C) 1999--2002 Joel Rosdahl # # This library is free software; you can redistribute it and/or @@ -380,7 +382,7 @@ class ServerConnection(Connection): self.socket = None def connect(self, server, port, nickname, password=None, username=None, - ircname=None, localaddress="", localport=0): + ircname=None, localaddress="", localport=0, encoding="utf-8"): """Connect/reconnect to a server. Arguments: @@ -401,6 +403,8 @@ class ServerConnection(Connection): localport -- Bind the connection to a specific local port. + encoding -- The encoding to use. + This function can be called to reconnect a closed connection. Returns the ServerConnection object. @@ -418,6 +422,7 @@ class ServerConnection(Connection): self.username = username or nickname self.ircname = ircname or nickname self.password = password + self.encoding = encoding self.localaddress = localaddress self.localport = localport self.localhost = socket.gethostname() @@ -489,7 +494,12 @@ class ServerConnection(Connection): self.disconnect("Connection reset by peer") return - lines = _linesep_regexp.split(self.previous_buffer + new_data.decode("latin-1", "replace")) + try: + new_data = new_data.decode(self.encoding, "strict") + except (UnicodeDecodeError, UnicodeEncodeError): + new_data = new_data.decode("latin-1", "replace") + + lines = _linesep_regexp.split(self.previous_buffer + new_data) # Save the last, unfinished line. self.previous_buffer = lines[-1] @@ -777,10 +787,17 @@ class ServerConnection(Connection): The string will be padded with appropriate CR LF. """ + if isinstance(string, bytes): + data = string + else: + try: + data = string.encode(self.encoding, "strict") + except (UnicodeEncodeError, UnicodeDecodeError): + data = string.encode("latin-1", "replace") if self.socket is None: raise ServerNotConnectedError("Not connected.") try: - self.socket.send(string.encode("latin-1", "replace") + b"\r\n") + self.socket.send(data + b"\r\n") if DEBUG: print("TO SERVER: %s\n" % string) except socket.error as x: @@ -1046,7 +1063,7 @@ class SimpleIRCClient: self.dcc_connections.remove(c) def connect(self, server, port, nickname, password=None, username=None, - ircname=None, localaddress="", localport=0): + ircname=None, localaddress="", localport=0, encoding="utf-8"): """Connect/reconnect to a server. Arguments: @@ -1067,11 +1084,13 @@ class SimpleIRCClient: localport -- Bind the connection to a specific local port. + encoding -- The encoding to use. + This function can be called to reconnect a closed connection. """ self.connection.connect(server, port, nickname, password, username, ircname, - localaddress, localport) + localaddress, localport, encoding) def dcc_connect(self, address, port, dcctype="chat"): """Connect to a DCC peer.