--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ExtensionIrc/IrcUtilities.py Fri Apr 18 18:36:48 2025 +0200 @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 - 2025 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing functions used by several IRC objects. +""" + +import re + +from PyQt6.QtCore import QCoreApplication, QTime +from PyQt6.QtWidgets import QApplication + +from eric7 import EricUtilities +from PluginExtensionIrc import ircExtensionPluginObject + +__UrlRe = re.compile( + r"""((?:http|ftp|https):\/\/[\w\-_]+(?:\.[\w\-_]+)+""" + r"""(?:[\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)""" +) +__ColorRe = re.compile( + r"""((?:\x03(?:0[0-9]|1[0-5]|[0-9])?(?:,(?:0[0-9]|1[0-5]|[0-9]))?)""" + r"""|\x02|\x03|\x13|\x15|\x16|\x17|\x1d|\x1f)""" +) + + +def ircTimestamp(): + """ + Module method to generate a time stamp string. + + @return time stamp + @rtype str + """ + if ircExtensionPluginObject.getPreferences("ShowTimestamps"): + if ircExtensionPluginObject.getPreferences("TimestampIncludeDate"): + if QApplication.isLeftToRight(): + f = "{0} {1}" + else: + f = "{1} {0}" + formatString = f.format( + ircExtensionPluginObject.getPreferences("DateFormat"), + ircExtensionPluginObject.getPreferences("TimeFormat"), + ) + else: + formatString = ircExtensionPluginObject.getPreferences("TimeFormat") + return '<font color="{0}">[{1}]</font> '.format( + ircExtensionPluginObject.getPreferences("TimestampColour"), + QTime.currentTime().toString(formatString), + ) + else: + return "" + + +def ircFilter(msg): + """ + Module method to make the message HTML compliant and detect URLs. + + @param msg message to process + @type str + @return processed message + @rtype str + """ + # step 1: cleanup message + msg = EricUtilities.html_encode(msg) + + # step 2: replace IRC formatting characters + openTags = [] + parts = __ColorRe.split(msg) + msgParts = [] + for part in parts: + if part == "\x02": # bold + if openTags and openTags[-1] == "b": + msgParts.append("</" + openTags.pop(-1) + ">") + else: + msgParts.append("<b>") + openTags.append("b") + elif part in ["\x03", "\x17"]: + if ircExtensionPluginObject.getPreferences("EnableIrcColours"): + if openTags and openTags[-1] == "span": + msgParts.append("</" + openTags.pop(-1) + ">") + else: + continue + else: + continue + elif part == "\x0f": # reset + while openTags: + msgParts.append("</" + openTags.pop(-1) + ">") + elif part == "\x13": # strikethru + if openTags and openTags[-1] == "s": + msgParts.append("</" + openTags.pop(-1) + ">") + else: + msgParts.append("<s>") + openTags.append("s") + elif part in ["\x15", "\x1f"]: # underline + if openTags and openTags[-1] == "u": + msgParts.append("</" + openTags.pop(-1) + ">") + else: + msgParts.append("<u>") + openTags.append("u") + elif part == "\x16": + # revert color not supported + continue + elif part == "\x1d": # italic + if openTags and openTags[-1] == "i": + msgParts.append("</" + openTags.pop(-1) + ">") + else: + msgParts.append("<i>") + openTags.append("i") + elif part.startswith("\x03"): + if ircExtensionPluginObject.getPreferences("EnableIrcColours"): + colors = part[1:].split(",", 1) + if len(colors) == 1: + # foreground color only + tag = '<span style="color:{0}">'.format( + ircExtensionPluginObject.getPreferences( + "IrcColor{0}".format(int(colors[0])) + ) + ) + else: + if colors[0]: + # foreground and background + tag = '<span style="background-color:{0};color={1}">'.format( + ircExtensionPluginObject.getPreferences( + "IrcColor{0}".format(int(colors[0])) + ), + ircExtensionPluginObject.getPreferences( + "IrcColor{0}".format(int(colors[1])) + ), + ) + else: + # background only + tag = '<span style="background-color:{0}">'.format( + ircExtensionPluginObject.getPreferences( + "IrcColor{0}".format(int(colors[1])) + ) + ) + msgParts.append(tag) + openTags.append("span") + else: + continue + else: + msgParts.append(part) + msg = "".join(msgParts) + + # step 3: find http and https links + parts = __UrlRe.split(msg) + msgParts = [] + for part in parts: + if part.startswith(("http://", "https://", "ftp://")): + msgParts.append( + '<a href="{0}" style="color:{1}">{0}</a>'.format( + part, ircExtensionPluginObject.getPreferences("HyperlinkColour") + ) + ) + else: + msgParts.append(part) + + return "".join(msgParts) + + +__channelModesDict = None + + +def __initChannelModesDict(): + """ + Private module function to initialize the channels modes dictionary. + """ + global __channelModesDict + + modesDict = { + "a": QCoreApplication.translate("IrcUtilities", "anonymous"), + "b": QCoreApplication.translate("IrcUtilities", "ban mask"), + "c": QCoreApplication.translate("IrcUtilities", "no colors allowed"), + "e": QCoreApplication.translate("IrcUtilities", "ban exception mask"), + "i": QCoreApplication.translate("IrcUtilities", "invite only"), + "k": QCoreApplication.translate("IrcUtilities", "password protected"), + "l": QCoreApplication.translate("IrcUtilities", "user limit"), + "m": QCoreApplication.translate("IrcUtilities", "moderated"), + "n": QCoreApplication.translate("IrcUtilities", "no messages from outside"), + "p": QCoreApplication.translate("IrcUtilities", "private"), + "q": QCoreApplication.translate("IrcUtilities", "quiet"), + "r": QCoreApplication.translate("IrcUtilities", "reop channel"), + "s": QCoreApplication.translate("IrcUtilities", "secret"), + "t": QCoreApplication.translate("IrcUtilities", "topic protection"), + "I": QCoreApplication.translate("IrcUtilities", "invitation mask"), + } + __channelModesDict = modesDict + + +def getChannelModesDict(): + """ + Module function to get the dictionary with the channel modes mappings. + + @return dictionary with channel modes mapping + @rtype dict + """ + global __channelModesDict + + if __channelModesDict is None: + __initChannelModesDict() + + return __channelModesDict