diff --git a/weechat-matrix.py b/weechat-matrix.py index 49aa3ca..058f0ac 100644 --- a/weechat-matrix.py +++ b/weechat-matrix.py @@ -516,6 +516,327 @@ class MatrixServer: "", "server_config_change_cb", self.name, "", "") +FormatedString = namedtuple( + 'FormatedString', + ['text', 'attributes'], + verbose=True +) + +Default_format_attributes = { + "bold": False, + "italic": False, + "underline": False, + "fgcolor": None, + "bgcolor": None +} + + +def line_color_to_sgr(color_string): + # type: (str) -> str + line_colors = { + "0": "white", + "1": "black", + "2": "blue", + "3": "green", + "4": "lightred", + "5": "red", + "6": "magenta", + "7": "brown", + "8": "yellow", + "9": "lightgreen", + "10": "cyan", + "11": "lightcyan", + "12": "lightblue", + "13": "lightmagenta", + "14": "darkgray", + "15": "gray", + "16": "52", + "17": "94", + "18": "100", + "19": "58", + "20": "22", + "21": "29", + "22": "23", + "23": "24", + "24": "17", + "25": "54", + "26": "53", + "27": "89", + "28": "88", + "29": "130", + "30": "142", + "31": "64", + "32": "28", + "33": "35", + "34": "30", + "35": "25", + "36": "18", + "37": "91", + "38": "90", + "39": "125", + "40": "124", + "41": "166", + "42": "184", + "43": "106", + "44": "34", + "45": "49", + "46": "37", + "47": "33", + "48": "19", + "49": "129", + "50": "127", + "51": "161", + "52": "196", + "53": "208", + "54": "226", + "55": "154", + "56": "46", + "57": "86", + "58": "51", + "59": "75", + "60": "21", + "61": "171", + "62": "201", + "63": "198", + "64": "203", + "65": "215", + "66": "227", + "67": "191", + "68": "83", + "69": "122", + "70": "87", + "71": "111", + "72": "63", + "73": "177", + "74": "207", + "75": "205", + "76": "217", + "77": "223", + "78": "229", + "79": "193", + "80": "157", + "81": "158", + "82": "159", + "83": "153", + "84": "147", + "85": "183", + "86": "219", + "87": "212", + "88": "16", + "89": "233", + "90": "235", + "91": "237", + "92": "239", + "93": "241", + "94": "244", + "95": "247", + "96": "250", + "97": "254", + "98": "231", + "99": "default" + } + + assert color_string in line_colors + + return line_colors[color_string] + + +def html_color_to_sgr(color): + pass + + +def sgr_to_rgb(color): + pass + + +# TODO reverse video +def parse_input_line(line): + """Parses the weechat input line and produces formated strings that can be + later converted to HTML or to a string for weechat's print functions + """ + # type: (str) -> List[FormatedString] + text = "" # type: str + substrings = [] # type: List[FormatedString] + attributes = Default_format_attributes.copy() + + i = 0 + while i < len(line): + # Bold + if line[i] == "\x02": + if text: + substrings.append(FormatedString(text, attributes.copy())) + text = "" + attributes["bold"] = not attributes["bold"] + i = i + 1 + + # Color + elif line[i] == "\x03": + if text: + substrings.append(FormatedString(text, attributes.copy())) + text = "" + i = i + 1 + + # check if it's a valid color, add it to the attributes + if line[i].isdigit(): + color_string = line[i] + i = i + 1 + + if line[i].isdigit(): + if color_string == "0": + color_string = line[i] + else: + color_string = color_string + line[i] + i = i + 1 + + attributes["fgcolor"] = line_color_to_sgr(color_string) + else: + attributes["fgcolor"] = None + + # check if we have a background color + if line[i] == "," and line[i+1].isdigit(): + color_string = line[i+1] + i = i + 2 + + if line[i].isdigit(): + if color_string == "0": + color_string = line[i] + else: + color_string = color_string + line[i] + i = i + 1 + + attributes["bgcolor"] = line_color_to_sgr(color_string) + else: + attributes["bgcolor"] = None + # Reset + elif line[i] == "\x0F": + if text: + substrings.append(FormatedString(text, attributes.copy())) + text = "" + # Reset all the attributes + attributes = Default_format_attributes.copy() + i = i + 1 + # Italic + elif line[i] == "0\x1D": + if text: + substrings.append(FormatedString(text, attributes.copy())) + text = "" + attributes["italic"] = not attributes["italic"] + i = i + 1 + + # Underline + elif line[i] == "0\x1F": + if text: + substrings.append(FormatedString(text, attributes.copy())) + text = "" + attributes["underline"] = not attributes["underline"] + i = i + 1 + + # Normal text + else: + text = text + line[i] + i = i + 1 + + substrings.append(FormatedString(text, attributes)) + return substrings + + +def formated(strings): + for string in strings: + if string.attributes != Default_format_attributes: + return True + return False + + +def formated_to_weechat(strings): + # type: (List[FormatedString]) -> str + # TODO BG COLOR + def add_attribute(string, name, value): + if name == "bold" and value: + return "{bold_on}{text}{bold_off}".format( + bold_on=W.color("bold"), + text=string, + bold_off=W.color("-bold")) + elif name == "italic" and value: + return "{italic_on}{text}{italic_off}".format( + italic_on=W.color("italic"), + text=string, + italic_off=W.color("-italic")) + elif name == "underline" and value: + return "{underline_on}{text}{underline_off}".format( + underline_on=W.color("underline"), + text=string, + underline_off=W.color("-underline")) + elif name == "fgcolor" and value: + return "{color_on}{text}{color_off}".format( + color_on=W.color(value), + text=string, + color_off=W.color("resetcolor")) + elif name == "bgcolor" and value: + return "{color_on}{text}{color_off}".format( + color_on=W.color("," + value), + text=string, + color_off=W.color("resetcolor")) + + return string + + def format_string(formated_string): + text = formated_string.text + attributes = formated_string.attributes + + for key, value in attributes.items(): + text = add_attribute(text, key, value) + return text + + weechat_strings = map(format_string, strings) + return "".join(weechat_strings) + + +def formated_to_html(strings): + # type: (List[FormatedString]) -> str + # TODO BG COLOR + def add_attribute(string, name, value): + if name == "bold" and value: + return "{bold_on}{text}{bold_off}".format( + bold_on="", + text=string, + bold_off="") + elif name == "italic" and value: + return "{italic_on}{text}{italic_off}".format( + italic_on="", + text=string, + italic_off="") + elif name == "underline" and value: + return "{underline_on}{text}{underline_off}".format( + underline_on="", + text=string, + underline_off="") + elif name == "fgcolor" and value: + return "{underline_on}{text}{underline_off}".format( + underline_on="".format(color=value), + text=string, + underline_off="") + + return string + + def strip_atribute(string, name, value): + return string + + def format_string(formated_string): + text = formated_string.text + attributes = formated_string.attributes + + for key, value in attributes.items(): + text = strip_atribute(text, key, value) + return text + + html_string = map(format_string, strings) + return "".join(html_string) + + +def html_to_formated(): + pass + + def wrap_socket(server, file_descriptor): # type: (MatrixServer, int) -> socket.socket sock = None # type: socket.socket @@ -1613,10 +1934,14 @@ def room_input_cb(server_name, buffer, input_data): if room.encrypted: return W.WEECHAT_RC_OK - body = {"msgtype": "m.text", "body": input_data} + # TODO if the input line contains any formating we need to send out a + # message of type html + formated_data = parse_input_line(input_data) + + body = {"msgtype": "m.text", "body": formated_to_html(formated_data)} extra_data = { "author": server.user, - "message": input_data, + "message": formated_to_weechat(formated_data), "room_id": room_id }