__module_name__ = "channel_charset" __module_version__ = "1.2.1" __module_description__ = "Allows you to set per-channel encoding, different from server default" __module_author__ = "Maciej Katafiasz " # CL 20060806 # - settings saved by network+channel instead of server+channel if possible # - print message when setting charset # - check whether requested encoding is available # - fixed kill command # - added filtering of /me and /topic commands # CL 20060920 # - fixed a couple bugs in the saving and loading of channel settings # - improved reentrant logic to work better when other plugins filter the same # commands or events # CL 20061017 # - made saving and loading settings a little more robust # # the old logic, if there were n plugins that filtered the same command or # event, caused (2**(n+1) - 2) callback invocations import xchat import codecs help_msg = """Set charset specific to this channel, different from server charset. Usage: /ccharset [|off|kill] -- name of charset to set for this channel off -- disable previously set charset conversion kill -- disable conversion for all channels call with no arguments to see current charset """ encodings = {} class ChannelInfo: def __init__(self, encoding): codecs.lookup(encoding) self.encoding = encoding def load_settings(): global encodings try: conf = open(xchat.get_info("xchatdir") + "/ccharset1.conf", "r") for line in conf: try: chan, enc = line.rstrip().split(" ", 1) encodings[chan] = ChannelInfo(enc) except: continue conf.close() except: print "CCharset: couldn't load settings" def write_settings(w): global encodings try: conf = open(xchat.get_info("xchatdir") + "/ccharset1.conf", "w") try: for chan, info in encodings.items(): conf.write(chan + ' ' + info.encoding + '\n') finally: conf.close() except: print "CCharset: couldn't save settings" def channel_id(ct): return (ct.get_info("network") or ct.get_info("server")) + "@" + ct.get_info("channel") def ccharset_set(word, word_eol, userdata): global encodings ct = xchat.get_context() key = channel_id(ct) if len(word) == 1: try: info = encodings[key] print "Charset for current channel: " + info.encoding except: print "Current channel uses server encoding" elif len(word) == 2: if word[1] == "kill": encodings = {} elif word[1] == "off": try: del(encodings[key]) print "Channel-specific encoding removed" except: print "No channel-specific encoding set" else: try: encodings[key] = ChannelInfo(word[1]) print "Charset for current channel set to: " + word[1] except LookupError, e: print e else: print help_msg return xchat.EAT_ALL # CL: when your own text is sent, xchat immediately calls text_emit to display # it, so send and receive (actually command and emit) reentrancy must be handled # separately. send_reentry = [0] recv_reentry = [0] # it would be ok to use a boolean, but just in case someone wants to reuse this # code and make the reentry limit higher than 1... def codec_cb(word, word_eol, userdata): global encodings, send_reentry, recv_reentry event, send = userdata if send: reentry = send_reentry else: reentry = recv_reentry if reentry[0]: return xchat.EAT_NONE eat = xchat.EAT_ALL reentry[0] += 1 try: ct = xchat.get_context() info = encodings[channel_id(ct)] ct_encoding = ct.get_info("charset") if send: if event: text = word_eol[1] else: event = "say" text = word_eol[0] ct.command(event + " " + text.decode(ct_encoding).encode(info.encoding)) else: dec_word = [] for w in word: dec_word.append(w.decode(info.encoding).encode(ct_encoding)) ct.emit_print(event, *dec_word) except Exception, e: eat = xchat.EAT_NONE reentry[0] -= 1 return eat EVENTS = [ "Channel Action", "Channel Action Hilight", "Channel Message", "Channel Msg Hilight", "Channel Notice", "Generic Message", "Kick", "Killed", "Motd", "Notice", "Part with Reason", "Private Message", "Private Message to Dialog", "Quit", "Receive Wallops", "Server Notice", "Server Text", "Topic", "Topic Change", "Your Message" ] load_settings() xchat.hook_command("ccharset", ccharset_set, help=help_msg) xchat.hook_command("", codec_cb, ("", True)) xchat.hook_command("topic", codec_cb, ("topic", True)) xchat.hook_command("me", codec_cb, ("me", True)) xchat.hook_unload(write_settings) for event in EVENTS: xchat.hook_print(event, codec_cb, (event, False)) print "Plugin CCharset loaded."