From 05a413f7cbe89a44f2e8d3cde9fb17f2c267bac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Wed, 29 Aug 2018 19:40:59 +0200 Subject: [PATCH] matrix: Style fixes and cleanup. --- .pylintrc | 3 +- main.py | 97 +++---- matrix/_weechat.py | 53 ++-- matrix/bar_items.py | 40 +-- matrix/buffer.py | 498 ++++++++++++++++------------------ matrix/colors.py | 127 +++++---- matrix/commands.py | 631 ++++++++++++++++++++++++------------------- matrix/completion.py | 157 +++++++---- matrix/config.py | 272 ++++++++++++------- matrix/globals.py | 8 +- matrix/server.py | 386 +++++++++++++++----------- matrix/utf.py | 11 +- matrix/utils.py | 273 +------------------ 13 files changed, 1278 insertions(+), 1278 deletions(-) diff --git a/.pylintrc b/.pylintrc index 3059c6d..0caa73e 100644 --- a/.pylintrc +++ b/.pylintrc @@ -130,7 +130,8 @@ disable=print-statement, bad-whitespace, too-few-public-methods, too-many-lines, - missing-docstring + missing-docstring, + bad-continuation, # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/main.py b/main.py index 91abc9e..323e572 100644 --- a/main.py +++ b/main.py @@ -19,72 +19,51 @@ from __future__ import unicode_literals import socket import ssl -import time -import pprint -import OpenSSL.crypto as crypto import textwrap -from itertools import chain - # pylint: disable=redefined-builtin from builtins import str -from future.utils import bytes_to_native_str as n - +from itertools import chain # pylint: disable=unused-import -from typing import (List, Set, Dict, Tuple, Text, Optional, AnyStr, Deque, Any) +from typing import Any, AnyStr, Deque, Dict, List, Optional, Set, Text, Tuple + import logbook -from logbook import Logger, StderrHandler, StreamHandler - -import nio -from nio import TransportType, RemoteTransportError, RemoteProtocolError - -from matrix.colors import Formatted -from matrix.utf import utf8_decode - -# Weechat searches for the registered callbacks in the scope of the main script -# file, import the callbacks here so weechat can find them. -from matrix.commands import (hook_commands, hook_page_up, matrix_command_cb, - matrix_topic_command_cb, matrix_join_command_cb, - matrix_part_command_cb, matrix_invite_command_cb, - matrix_command_pgup_cb, matrix_redact_command_cb, - matrix_command_buf_clear_cb, matrix_me_command_cb, - matrix_kick_command_cb) -from matrix.buffer import room_buffer_input_cb, room_buffer_close_cb - -from matrix.server import ( - MatrixServer, - create_default_server, - send_cb, - matrix_timer_cb, - matrix_config_server_read_cb, - matrix_config_server_write_cb, - matrix_config_server_change_cb, -) - -from matrix.bar_items import (init_bar_items, matrix_bar_item_name, - matrix_bar_item_plugin, matrix_bar_item_lag, - matrix_bar_item_buffer_modes) - -from matrix.completion import ( - init_completion, matrix_command_completion_cb, - matrix_server_command_completion_cb, matrix_debug_completion_cb, - matrix_message_completion_cb, matrix_server_completion_cb, - matrix_olm_user_completion_cb, matrix_olm_device_completion_cb, - matrix_user_completion_cb) - -from matrix.utils import (key_from_value, server_buffer_prnt, - server_buffer_set_title) - -from matrix.config import ( - matrix_config_reload_cb, - MatrixConfig, - config_log_level_cb, - config_log_category_cb, - config_server_buffer_cb -) +import OpenSSL.crypto as crypto +from future.utils import bytes_to_native_str as n +from logbook import Logger, StreamHandler +from nio import RemoteProtocolError, RemoteTransportError, TransportType from matrix import globals as G - -from matrix.globals import W, SERVERS, SCRIPT_NAME +from matrix.bar_items import (init_bar_items, matrix_bar_item_buffer_modes, + matrix_bar_item_lag, matrix_bar_item_name, + matrix_bar_item_plugin) +from matrix.buffer import room_buffer_close_cb, room_buffer_input_cb +# Weechat searches for the registered callbacks in the scope of the main script +# file, import the callbacks here so weechat can find them. +from matrix.commands import (hook_commands, hook_page_up, + matrix_command_buf_clear_cb, matrix_command_cb, + matrix_command_pgup_cb, matrix_invite_command_cb, + matrix_join_command_cb, matrix_kick_command_cb, + matrix_me_command_cb, matrix_part_command_cb, + matrix_redact_command_cb, matrix_topic_command_cb) +from matrix.completion import (init_completion, matrix_command_completion_cb, + matrix_debug_completion_cb, + matrix_message_completion_cb, + matrix_olm_device_completion_cb, + matrix_olm_user_completion_cb, + matrix_server_command_completion_cb, + matrix_server_completion_cb, + matrix_user_completion_cb) +from matrix.config import (MatrixConfig, config_log_category_cb, + config_log_level_cb, config_server_buffer_cb, + matrix_config_reload_cb) +from matrix.globals import SCRIPT_NAME, SERVERS, W +from matrix.server import (MatrixServer, create_default_server, + matrix_config_server_change_cb, + matrix_config_server_read_cb, + matrix_config_server_write_cb, matrix_timer_cb, + send_cb) +from matrix.utf import utf8_decode +from matrix.utils import server_buffer_prnt, server_buffer_set_title # yapf: disable WEECHAT_SCRIPT_NAME = SCRIPT_NAME diff --git a/matrix/_weechat.py b/matrix/_weechat.py index 6914e37..a4ab139 100644 --- a/matrix/_weechat.py +++ b/matrix/_weechat.py @@ -1,9 +1,8 @@ +import datetime import random import string -import datetime - -weechat_base_colors = { +WEECHAT_BASE_COLORS = { "black": "0", "red": "1", "green": "2", @@ -29,11 +28,11 @@ def color(color_name): escape_codes = [] reset_code = "0" - def make_fg_color(color): - return "38;5;{}".format(color) + def make_fg_color(color_code): + return "38;5;{}".format(color_code) - def make_bg_color(color): - return "48;5;{}".format(color) + def make_bg_color(color_code): + return "48;5;{}".format(color_code) attributes = { "bold": "1", @@ -76,21 +75,21 @@ def color(color_name): stripped_color = fg_color.lstrip("*_|/!") - if stripped_color in weechat_base_colors: + if stripped_color in WEECHAT_BASE_COLORS: escape_codes.append( - make_fg_color(weechat_base_colors[stripped_color])) + make_fg_color(WEECHAT_BASE_COLORS[stripped_color])) elif stripped_color.isdigit(): num_color = int(stripped_color) - if num_color >= 0 and num_color < 256: + if 0 <= num_color < 256: escape_codes.append(make_fg_color(stripped_color)) - if bg_color in weechat_base_colors: - escape_codes.append(make_bg_color(weechat_base_colors[bg_color])) + if bg_color in WEECHAT_BASE_COLORS: + escape_codes.append(make_bg_color(WEECHAT_BASE_COLORS[bg_color])) else: if bg_color.isdigit(): num_color = int(bg_color) - if num_color >= 0 and num_color < 256: + if 0 <= num_color < 256: escape_codes.append(make_bg_color(bg_color)) escape_string = "\033[{}{}m".format(reset_code, ";".join(escape_codes)) @@ -98,7 +97,7 @@ def color(color_name): return escape_string -def prefix(prefix): +def prefix(prefix_string): prefix_to_symbol = { "error": "=!=", "network": "--", @@ -107,14 +106,14 @@ def prefix(prefix): "quit": "<--" } - if prefix in prefix_to_symbol: + if prefix_string in prefix_to_symbol: return prefix_to_symbol[prefix] return "" -def prnt(_, string): - print(string) +def prnt(_, message): + print(message) def prnt_date_tags(_, date, tags_string, data): @@ -126,44 +125,44 @@ def prnt_date_tags(_, date, tags_string, data): print(message) -def config_search_section(*args, **kwargs): +def config_search_section(*_, **__): pass -def config_new_option(*args, **kwargs): +def config_new_option(*_, **__): pass -def mkdir_home(*args, **kwargs): +def mkdir_home(*_, **__): return True -def info_get(info, *args): +def info_get(info, *_): if info == "nick_color_name": - return random.choice(list(weechat_base_colors.keys())) + return random.choice(list(WEECHAT_BASE_COLORS.keys())) return "" -def buffer_new(*args, **kwargs): +def buffer_new(*_, **__): return "".join( random.choice(string.ascii_uppercase + string.digits) for _ in range(8) ) -def buffer_set(*args, **kwargs): +def buffer_set(*_, **__): return -def nicklist_add_group(*args, **kwargs): +def nicklist_add_group(*_, **__): return -def nicklist_add_nick(*args, **kwargs): +def nicklist_add_nick(*_, **__): return -def nicklist_remove_nick(*args, **kwargs): +def nicklist_remove_nick(*_, **__): return diff --git a/matrix/bar_items.py b/matrix/bar_items.py index 5a45547..56d1965 100644 --- a/matrix/bar_items.py +++ b/matrix/bar_items.py @@ -16,21 +16,20 @@ from __future__ import unicode_literals -from matrix.utf import utf8_decode - -from matrix.globals import W, SERVERS +from .globals import SERVERS, W +from .utf import utf8_decode @utf8_decode def matrix_bar_item_plugin(data, item, window, buffer, extra_info): # pylint: disable=unused-argument for server in SERVERS.values(): - if (buffer in server.buffers.values() or - buffer == server.server_buffer): + if buffer in server.buffers.values() or buffer == server.server_buffer: return "matrix{color}/{color_fg}{name}".format( color=W.color("bar_delim"), color_fg=W.color("bar_fg"), - name=server.name) + name=server.name, + ) return "" @@ -40,24 +39,31 @@ def matrix_bar_item_name(data, item, window, buffer, extra_info): # pylint: disable=unused-argument for server in SERVERS.values(): if buffer in server.buffers.values(): - color = ("status_name_ssl" - if server.ssl_context.check_hostname else "status_name") + color = ( + "status_name_ssl" + if server.ssl_context.check_hostname + else "status_name" + ) room_buffer = server.find_room_from_ptr(buffer) room = room_buffer.room return "{color}{name}".format( - color=W.color(color), - name=room.display_name()) + color=W.color(color), name=room.display_name() + ) - elif buffer == server.server_buffer: - color = ("status_name_ssl" - if server.ssl_context.check_hostname else "status_name") + if buffer == server.server_buffer: + color = ( + "status_name_ssl" + if server.ssl_context.check_hostname + else "status_name" + ) return "{color}server{del_color}[{color}{name}{del_color}]".format( color=W.color(color), del_color=W.color("bar_delim"), - name=server.name) + name=server.name, + ) return "" @@ -66,8 +72,7 @@ def matrix_bar_item_name(data, item, window, buffer, extra_info): def matrix_bar_item_lag(data, item, window, buffer, extra_info): # pylint: disable=unused-argument for server in SERVERS.values(): - if (buffer in server.buffers.values() or - buffer == server.server_buffer): + if buffer in server.buffers.values() or buffer == server.server_buffer: if server.lag >= 500: color = W.color("irc.color.item_lag_counting") if server.lag_done: @@ -77,7 +82,8 @@ def matrix_bar_item_lag(data, item, window, buffer, extra_info): lag_string = "Lag: {color}{lag}{ncolor}".format( lag=lag.format((server.lag / 1000)), color=color, - ncolor=W.color("reset")) + ncolor=W.color("reset"), + ) return lag_string return "" diff --git a/matrix/buffer.py b/matrix/buffer.py index e8928e1..c9fffe7 100644 --- a/matrix/buffer.py +++ b/matrix/buffer.py @@ -22,42 +22,40 @@ from builtins import super from functools import partial from typing import NamedTuple -from . import globals as G -from .globals import W, SERVERS, SCRIPT_NAME -from .utf import utf8_decode -from .colors import Formatted -from .utils import ( - shorten_sender, - server_ts_to_weechat, - string_strikethrough, -) -from .config import RedactType - from nio import ( Api, - RoomMessageText, - RoomMemberEvent, PowerLevelsEvent, - RoomEncryptionEvent, RedactedEvent, + RedactionEvent, RoomAliasEvent, - RoomTopicEvent, + RoomEncryptionEvent, + RoomMemberEvent, RoomMessageEmote, - RoomNameEvent, RoomMessageMedia, RoomMessageNotice, + RoomMessageText, RoomMessageUnknown, - RedactionEvent + RoomNameEvent, + RoomTopicEvent, ) +from . import globals as G +from .colors import Formatted +from .config import RedactType +from .globals import SCRIPT_NAME, SERVERS, W +from .utf import utf8_decode +from .utils import server_ts_to_weechat, shorten_sender, string_strikethrough -OwnMessage = NamedTuple("OwnMessage", [ - ("sender", str), - ("age", int), - ("event_id", str), - ("room_id", str), - ("formatted_message", Formatted) -]) +OwnMessage = NamedTuple( + "OwnMessage", + [ + ("sender", str), + ("age", int), + ("event_id", str), + ("room_id", str), + ("formatted_message", Formatted), + ], +) class OwnAction(OwnMessage): @@ -71,7 +69,7 @@ def room_buffer_input_cb(server_name, buffer, input_data): if not room_buffer: # TODO log error - return + return W.WEECHAT_RC_ERROR if not server.connected: room_buffer.error("You are not connected to the server") @@ -96,7 +94,7 @@ def room_buffer_close_cb(data, buffer): class WeechatUser(object): def __init__(self, nick, host=None, prefix="", join_time=None): - # type: (str, str, str) -> None + # type: (str, str, str, int) -> None self.nick = nick self.host = host self.prefix = prefix @@ -127,7 +125,7 @@ class WeechatUser(object): class RoomUser(WeechatUser): def __init__(self, nick, user_id=None, power_level=0, join_time=None): - # type: (str, str, int) -> None + # type: (str, str, int, int) -> None prefix = self._get_prefix(power_level) super().__init__(nick, user_id, prefix, join_time) @@ -152,26 +150,22 @@ class RoomUser(WeechatUser): # type: (int) -> str if power_level >= 100: return "&" - elif power_level >= 50: + if power_level >= 50: return "@" - elif power_level > 0: + if power_level > 0: return "+" return "" class WeechatChannelBuffer(object): tags = { - "message": [ - SCRIPT_NAME + "_message", - "notify_message", - "log1" - ], + "message": [SCRIPT_NAME + "_message", "notify_message", "log1"], "self_message": [ SCRIPT_NAME + "_message", "notify_none", "no_highlight", "self_msg", - "log1" + "log1", ], "action": [ SCRIPT_NAME + "_message", @@ -179,44 +173,25 @@ class WeechatChannelBuffer(object): "notify_message", "log1", ], - "notice": [ - SCRIPT_NAME + "_notice", - "notify_message", - "log1", - ], + "notice": [SCRIPT_NAME + "_notice", "notify_message", "log1"], "old_message": [ SCRIPT_NAME + "_message", "notify_message", "no_log", - "no_highlight" + "no_highlight", ], - "join": [ - SCRIPT_NAME + "_join", - "log4" - ], - "part": [ - SCRIPT_NAME + "_leave", - "log4" - ], - "kick": [ - SCRIPT_NAME + "_kick", - "log4" - ], - "invite": [ - SCRIPT_NAME + "_invite", - "log4" - ], - "topic": [ - SCRIPT_NAME + "_topic", - "log3", - ] + "join": [SCRIPT_NAME + "_join", "log4"], + "part": [SCRIPT_NAME + "_leave", "log4"], + "kick": [SCRIPT_NAME + "_kick", "log4"], + "invite": [SCRIPT_NAME + "_invite", "log4"], + "topic": [SCRIPT_NAME + "_topic", "log3"], } membership_messages = { "join": "has joined", "part": "has left", "kick": "has been kicked from", - "invite": "has been invited to" + "invite": "has been invited to", } class Line(object): @@ -249,9 +224,7 @@ class WeechatChannelBuffer(object): @property def tags(self): tags_count = W.hdata_get_var_array_size( - self._hdata, - self._ptr, - "tags_array" + self._hdata, self._ptr, "tags_array" ) tags = [ @@ -300,7 +273,7 @@ class WeechatChannelBuffer(object): tags=None, prefix=None, message=None, - highlight=None + highlight=None, ): new_data = {} @@ -309,7 +282,7 @@ class WeechatChannelBuffer(object): if date_printed: new_data["date_printed"] = str(date_printed) if tags: - new_data["tags_array"] = ','.join(tags) + new_data["tags_array"] = ",".join(tags) if prefix: new_data["prefix"] = prefix if message: @@ -337,8 +310,8 @@ class WeechatChannelBuffer(object): self.topic_author = "" self.topic_date = None - W.buffer_set(self._ptr, "localvar_set_type", 'channel') - W.buffer_set(self._ptr, "type", 'formatted') + W.buffer_set(self._ptr, "localvar_set_type", "channel") + W.buffer_set(self._ptr, "type", "formatted") W.buffer_set(self._ptr, "localvar_set_channel", name) @@ -350,32 +323,16 @@ class WeechatChannelBuffer(object): # W.buffer_set(self._ptr, "short_name", short_name) W.nicklist_add_group( - self._ptr, - '', - "000|o", - "weechat.color.nicklist_group", - 1 + self._ptr, "", "000|o", "weechat.color.nicklist_group", 1 ) W.nicklist_add_group( - self._ptr, - '', - "001|h", - "weechat.color.nicklist_group", - 1 + self._ptr, "", "001|h", "weechat.color.nicklist_group", 1 ) W.nicklist_add_group( - self._ptr, - '', - "002|v", - "weechat.color.nicklist_group", - 1 + self._ptr, "", "002|v", "weechat.color.nicklist_group", 1 ) W.nicklist_add_group( - self._ptr, - '', - "999|...", - "weechat.color.nicklist_group", - 1 + self._ptr, "", "999|...", "weechat.color.nicklist_group", 1 ) W.buffer_set(self._ptr, "nicklist", "1") @@ -385,9 +342,7 @@ class WeechatChannelBuffer(object): # TODO make this configurable W.buffer_set( - self._ptr, - "highlight_tags_restrict", - SCRIPT_NAME + "_message" + self._ptr, "highlight_tags_restrict", SCRIPT_NAME + "_message" ) @property @@ -428,23 +383,18 @@ class WeechatChannelBuffer(object): @property def lines(self): - own_lines = W.hdata_pointer( - self._hdata, - self._ptr, - "own_lines" - ) + own_lines = W.hdata_pointer(self._hdata, self._ptr, "own_lines") if own_lines: hdata_line = W.hdata_get("line") line_pointer = W.hdata_pointer( - W.hdata_get("lines"), own_lines, "last_line") + W.hdata_get("lines"), own_lines, "last_line" + ) while line_pointer: data_pointer = W.hdata_pointer( - hdata_line, - line_pointer, - "data" + hdata_line, line_pointer, "data" ) if data_pointer: @@ -469,9 +419,7 @@ class WeechatChannelBuffer(object): # type: (str) -> None """ Print an error to the room buffer """ message = "{prefix}{script}: {message}".format( - prefix=W.prefix("error"), - script=SCRIPT_NAME, - message=string + prefix=W.prefix("error"), script=SCRIPT_NAME, message=string ) self._print(message) @@ -493,7 +441,7 @@ class WeechatChannelBuffer(object): color = self._color_for_tags(user.color) - if message_type != "action" and message_type != "notice": + if message_type not in ("action", "notice"): tags.append("prefix_nick_{color}".format(color=color)) return tags @@ -507,18 +455,23 @@ class WeechatChannelBuffer(object): return WeechatUser(nick) def _print_message(self, user, message, date, tags): - prefix_string = ("" if not user.prefix else "{}{}{}".format( - W.color(self._get_prefix_color(user.prefix)), - user.prefix, - W.color("reset") - )) + prefix_string = ( + "" + if not user.prefix + else "{}{}{}".format( + W.color(self._get_prefix_color(user.prefix)), + user.prefix, + W.color("reset"), + ) + ) data = "{prefix}{color}{author}{ncolor}\t{msg}".format( prefix=prefix_string, color=W.color(user.color), author=user.nick, ncolor=W.color("reset"), - msg=message) + msg=message, + ) self.print_date_tags(data, date, tags) @@ -534,27 +487,32 @@ class WeechatChannelBuffer(object): def notice(self, nick, message, date, extra_tags=None): # type: (str, str, int, Optional[List[str]]) -> None user = self._get_user(nick) - user_prefix = ("" if not user.prefix else "{}{}{}".format( - W.color(self._get_prefix_color(user.prefix)), - user.prefix, - W.color("reset") - )) - - user_string = "{}{}{}{}".format( - user_prefix, - user.color, - user.nick, - W.color("reset") + user_prefix = ( + "" + if not user.prefix + else "{}{}{}".format( + W.color(self._get_prefix_color(user.prefix)), + user.prefix, + W.color("reset"), + ) ) - data = ("{prefix}\t{color}Notice" - "{del_color}({ncolor}{user}{del_color}){ncolor}" - ": {message}").format(prefix=W.prefix("network"), - color=W.color("irc.color.notice"), - del_color=W.color("chat_delimiters"), - ncolor=W.color("reset"), - user=user_string, - message=message) + user_string = "{}{}{}{}".format( + user_prefix, user.color, user.nick, W.color("reset") + ) + + data = ( + "{prefix}\t{color}Notice" + "{del_color}({ncolor}{user}{del_color}){ncolor}" + ": {message}" + ).format( + prefix=W.prefix("network"), + color=W.color("irc.color.notice"), + del_color=W.color("chat_delimiters"), + ncolor=W.color("reset"), + user=user_string, + message=message, + ) tags = self._message_tags(user, "notice") + (extra_tags or []) self.print_date_tags(data, date, tags) @@ -563,27 +521,33 @@ class WeechatChannelBuffer(object): self.unmask_smart_filtered_nick(nick) def _print_action(self, user, message, date, tags): - nick_prefix = ("" if not user.prefix else "{}{}{}".format( - W.color(self._get_prefix_color(user.prefix)), - user.prefix, - W.color("reset") - )) + nick_prefix = ( + "" + if not user.prefix + else "{}{}{}".format( + W.color(self._get_prefix_color(user.prefix)), + user.prefix, + W.color("reset"), + ) + ) - data = ("{prefix}{nick_prefix}{nick_color}{author}" - "{ncolor} {msg}").format( + data = ( + "{prefix}{nick_prefix}{nick_color}{author}" "{ncolor} {msg}" + ).format( prefix=W.prefix("action"), nick_prefix=nick_prefix, nick_color=W.color(user.color), author=user.nick, ncolor=W.color("reset"), - msg=message) + msg=message, + ) self.print_date_tags(data, date, tags) - def action(self, nick, message, date, extra_tags=[]): + def action(self, nick, message, date, extra_tags=None): # type: (str, str, int, Optional[List[str]]) -> None user = self._get_user(nick) - tags = self._message_tags(user, "action") + extra_tags + tags = self._message_tags(user, "action") + (extra_tags or []) self._print_action(user, message, date, tags) user.update_speaking_time(date) @@ -624,9 +588,7 @@ class WeechatChannelBuffer(object): if not nick_pointer: group = W.nicklist_search_group( - self._ptr, - "", - self._get_nicklist_group(user) + self._ptr, "", self._get_nicklist_group(user) ) prefix = user.prefix if user.prefix else " " W.nicklist_add_nick( @@ -636,22 +598,22 @@ class WeechatChannelBuffer(object): user.color, prefix, self._get_prefix_color(user.prefix), - 1 + 1, ) def _membership_message(self, user, message_type): # type: (WeechatUser, str) -> str - action_color = ("green" if message_type == "join" - or message_type == "invite" else "red") - prefix = ("join" if message_type == "join" or message_type == "invite" - else "quit") + action_color = "green" if message_type in ("join", "invite") else "red" + prefix = "join" if message_type in ("join", "invite") else "quit" membership_message = self.membership_messages[message_type] - message = ("{prefix}{color}{author}{ncolor} " - "{del_color}({host_color}{host}{del_color})" - "{action_color} {message} " - "{channel_color}{room}{ncolor}").format( + message = ( + "{prefix}{color}{author}{ncolor} " + "{del_color}({host_color}{host}{del_color})" + "{action_color} {message} " + "{channel_color}{room}{ncolor}" + ).format( prefix=W.prefix(prefix), color=W.color(user.color), author=user.nick, @@ -662,11 +624,12 @@ class WeechatChannelBuffer(object): action_color=W.color(action_color), message=membership_message, channel_color=W.color("chat_channel"), - room=self.short_name) + room=self.short_name, + ) return message - def join(self, user, date, message=True, extra_tags=[]): + def join(self, user, date, message=True, extra_tags=None): # type: (WeechatUser, int, Optional[bool], Optional[List[str]]) -> None self._add_user_to_nicklist(user) self.users[user.nick] = user @@ -681,12 +644,12 @@ class WeechatChannelBuffer(object): self.print_date_tags(message, date, tags) self.add_smart_filtered_nick(user.nick) - def invite(self, nick, date, extra_tags=[]): + def invite(self, nick, date, extra_tags=None): # type: (str, int, Optional[bool], Optional[List[str]]) -> None user = self._get_user(nick) tags = self._message_tags(user, "invite") message = self._membership_message(user, "invite") - self.print_date_tags(message, date, tags + extra_tags) + self.print_date_tags(message, date, tags + (extra_tags or [])) def _remove_user_from_nicklist(self, user): # type: (WeechatUser) -> None @@ -695,7 +658,7 @@ class WeechatChannelBuffer(object): if nick_pointer: W.nicklist_remove_nick(self._ptr, nick_pointer) - def _leave(self, nick, date, message, leave_type, extra_tags): + def _leave(self, nick, date, message, leave_type, extra_tags=None): # type: (str, int, bool, str, List[str]) -> None user = self._get_user(nick) self._remove_user_from_nicklist(user) @@ -708,34 +671,36 @@ class WeechatChannelBuffer(object): tags.append(SCRIPT_NAME + "_smart_filter") message = self._membership_message(user, leave_type) - self.print_date_tags(message, date, tags + extra_tags) + self.print_date_tags(message, date, tags + (extra_tags or [])) self.remove_smart_filtered_nick(user.nick) if user.nick in self.users: del self.users[user.nick] - def part(self, nick, date, message=True, extra_tags=[]): + def part(self, nick, date, message=True, extra_tags=None): # type: (str, int, Optional[bool], Optional[List[str]]) -> None self._leave(nick, date, message, "part", extra_tags) - def kick(self, nick, date, message=True, extra_tags=[]): + def kick(self, nick, date, message=True, extra_tags=None): # type: (str, int, Optional[bool], Optional[List[str]]) -> None - self._leave(nick, date, message, "kick", extra_tags=[]) + self._leave(nick, date, message, "kick", extra_tags) def _print_topic(self, nick, topic, date): user = self._get_user(nick) tags = self._message_tags(user, "topic") - data = ("{prefix}{nick} has changed " - "the topic for {chan_color}{room}{ncolor} " - "to \"{topic}\"").format( - prefix=W.prefix("network"), - nick=user.nick, - chan_color=W.color("chat_channel"), - ncolor=W.color("reset"), - room=self.short_name, - topic=topic - ) + data = ( + "{prefix}{nick} has changed " + "the topic for {chan_color}{room}{ncolor} " + 'to "{topic}"' + ).format( + prefix=W.prefix("network"), + nick=user.nick, + chan_color=W.color("chat_channel"), + ncolor=W.color("reset"), + room=self.short_name, + topic=topic, + ) self.print_date_tags(data, date, tags) user.update_speaking_time(date) @@ -799,9 +764,7 @@ class RoomBuffer(object): self.displayed_nicks = {} user = shorten_sender(self.room.own_user_id) self.weechat_buffer = WeechatChannelBuffer( - buffer_name, - server_name, - user + buffer_name, server_name, user ) def find_nick(self, user_id): @@ -837,11 +800,7 @@ class RoomBuffer(object): buffer_user.color = "weechat.color.chat_nick_self" user.nick_color = "weechat.color.chat_nick_self" - self.weechat_buffer.join( - buffer_user, - date, - not is_state - ) + self.weechat_buffer.join(buffer_user, date, not is_state) date = server_ts_to_weechat(event.server_timestamp) @@ -909,22 +868,28 @@ class RoomBuffer(object): message = line.message tags = line.tags - reason = ("" if not event.reason else - ", reason: \"{reason}\"".format(reason=event.reason)) + reason = ( + "" + if not event.reason + else ', reason: "{reason}"'.format(reason=event.reason) + ) - redaction_msg = ("{del_color}<{log_color}Message redacted by: " - "{censor}{log_color}{reason}{del_color}>" - "{ncolor}").format( - del_color=W.color("chat_delimiters"), - ncolor=W.color("reset"), - log_color=W.color("logger.color.backlog_line"), - censor=censor, - reason=reason) + redaction_msg = ( + "{del_color}<{log_color}Message redacted by: " + "{censor}{log_color}{reason}{del_color}>" + "{ncolor}" + ).format( + del_color=W.color("chat_delimiters"), + ncolor=W.color("reset"), + log_color=W.color("logger.color.backlog_line"), + censor=censor, + reason=reason, + ) new_message = "" if G.CONFIG.look.redaction_type == RedactType.STRIKETHROUGH: - plaintext_msg = W.string_remove_color(message, '') + plaintext_msg = W.string_remove_color(message, "") new_message = string_strikethrough(plaintext_msg) elif G.CONFIG.look.redaction_type == RedactType.NOTICE: new_message = message @@ -944,18 +909,24 @@ class RoomBuffer(object): tags = self.get_event_tags(event) tags.append(SCRIPT_NAME + "_redacted") - reason = (", reason: \"{reason}\"".format(reason=event.reason) - if event.reason else "") + reason = ( + ', reason: "{reason}"'.format(reason=event.reason) + if event.reason + else "" + ) censor = self.find_nick(event.redacter) - data = ("{del_color}<{log_color}Message redacted by: " - "{censor}{log_color}{reason}{del_color}>{ncolor}").format( - del_color=W.color("chat_delimiters"), - ncolor=W.color("reset"), - log_color=W.color("logger.color.backlog_line"), - censor=censor, - reason=reason) + data = ( + "{del_color}<{log_color}Message redacted by: " + "{censor}{log_color}{reason}{del_color}>{ncolor}" + ).format( + del_color=W.color("chat_delimiters"), + ncolor=W.color("reset"), + log_color=W.color("logger.color.backlog_line"), + censor=censor, + reason=reason, + ) self.weechat_buffer.message(nick, data, date, tags) @@ -966,20 +937,22 @@ class RoomBuffer(object): nick, event.topic, server_ts_to_weechat(event.server_timestamp), - not is_state) + not is_state, + ) @staticmethod def get_event_tags(event): return ["matrix_id_{}".format(event.event_id)] - def _handle_power_level(self, event): + def _handle_power_level(self, _): for user_id in self.room.power_levels.users: if user_id in self.displayed_nicks: nick = self.find_nick(user_id) user = self.weechat_buffer.users[nick] user.power_level = self.room.power_levels.get_user_level( - user_id) + user_id + ) # There is no way to change the group of a user without # removing him from the nicklist @@ -994,9 +967,11 @@ class RoomBuffer(object): elif isinstance(event, PowerLevelsEvent): self._handle_power_level(event) elif isinstance(event, RoomEncryptionEvent): - message = ("This room is encrypted, encryption is " - "currently unsuported. Message sending is disabled for " - "this room.") + message = ( + "This room is encrypted, encryption is " + "currently unsuported. Message sending is disabled for " + "this room." + ) self.weechat_buffer.error(message) def handle_timeline_event(self, event): @@ -1016,10 +991,7 @@ class RoomBuffer(object): nick = self.find_nick(event.sender) date = server_ts_to_weechat(event.server_timestamp) self.weechat_buffer.action( - nick, - event.body, - date, - self.get_event_tags(event) + nick, event.body, date, self.get_event_tags(event) ) elif isinstance(event, RoomMessageText): @@ -1029,25 +1001,18 @@ class RoomBuffer(object): if event.formatted_body: formatted = Formatted.from_html(event.formatted_body) - data = (formatted.to_weechat() - if formatted else event.body) + data = formatted.to_weechat() if formatted else event.body date = server_ts_to_weechat(event.server_timestamp) self.weechat_buffer.message( - nick, - data, - date, - self.get_event_tags(event) + nick, data, date, self.get_event_tags(event) ) elif isinstance(event, RoomMessageNotice): nick = self.find_nick(event.sender) date = server_ts_to_weechat(event.server_timestamp) self.weechat_buffer.notice( - nick, - event.body, - date, - self.get_event_tags(event) + nick, event.body, date, self.get_event_tags(event) ) elif isinstance(event, RoomMessageMedia): @@ -1056,15 +1021,11 @@ class RoomBuffer(object): http_url = Api.mxc_to_http(event.url) url = http_url if http_url else event.url - description = ("/{}".format(event.body) - if event.body else "") + description = "/{}".format(event.body) if event.body else "" data = "{url}{desc}".format(url=url, desc=description) self.weechat_buffer.message( - nick, - data, - date, - self.get_event_tags(event) + nick, data, date, self.get_event_tags(event) ) elif isinstance(event, RoomMessageUnknown): @@ -1072,10 +1033,7 @@ class RoomBuffer(object): date = server_ts_to_weechat(event.server_timestamp) data = ("Unknown message of type {t}").format(t=event.type) self.weechat_buffer.message( - nick, - data, - date, - self.get_event_tags(event) + nick, data, date, self.get_event_tags(event) ) elif isinstance(event, RedactionEvent): @@ -1085,9 +1043,11 @@ class RoomBuffer(object): self._handle_redacted_message(event) elif isinstance(event, RoomEncryptionEvent): - message = ("This room is encrypted, encryption is " - "currently unsuported. Message sending is disabled for " - "this room.") + message = ( + "This room is encrypted, encryption is " + "currently unsuported. Message sending is disabled for " + "this room." + ) self.weechat_buffer.error(message) elif isinstance(event, PowerLevelsEvent): @@ -1106,8 +1066,9 @@ class RoomBuffer(object): # ) else: - W.prnt("", "Unhandled event of type {}.".format( - type(event).__name__)) + W.prnt( + "", "Unhandled event of type {}.".format(type(event).__name__) + ) def self_message(self, message): # type: (OwnMessage) -> None @@ -1125,10 +1086,7 @@ class RoomBuffer(object): tags = self.get_event_tags(message) self.weechat_buffer.self_action( - nick, - message.formatted_message.to_weechat(), - date, - tags + nick, message.formatted_message.to_weechat(), date, tags ) def old_redacted(self, event): @@ -1136,20 +1094,26 @@ class RoomBuffer(object): SCRIPT_NAME + "_message", "notify_message", "no_log", - "no_highlight" + "no_highlight", ] - reason = (", reason: \"{reason}\"".format(reason=event.reason) - if event.reason else "") + reason = ( + ', reason: "{reason}"'.format(reason=event.reason) + if event.reason + else "" + ) censor = self.find_nick(event.redacter) - data = ("{del_color}<{log_color}Message redacted by: " - "{censor}{log_color}{reason}{del_color}>{ncolor}").format( - del_color=W.color("chat_delimiters"), - ncolor=W.color("reset"), - log_color=W.color("logger.color.backlog_line"), - censor=censor, - reason=reason) + data = ( + "{del_color}<{log_color}Message redacted by: " + "{censor}{log_color}{reason}{del_color}>{ncolor}" + ).format( + del_color=W.color("chat_delimiters"), + ncolor=W.color("reset"), + log_color=W.color("logger.color.backlog_line"), + censor=censor, + reason=reason, + ) tags += self.get_event_tags(event) nick = self.find_nick(event.sender) @@ -1162,12 +1126,15 @@ class RoomBuffer(object): SCRIPT_NAME + "_message", "notify_message", "no_log", - "no_highlight" + "no_highlight", ] tags += self.get_event_tags(event) nick = self.find_nick(event.sender) - data = (event.formatted_message.to_weechat() - if event.formatted_message else event.message) + data = ( + event.formatted_message.to_weechat() + if event.formatted_message + else event.message + ) user = self.weechat_buffer._get_user(nick) date = server_ts_to_weechat(event.server_timestamp) self.weechat_buffer._print_message(user, data, date, tags) @@ -1175,13 +1142,7 @@ class RoomBuffer(object): def sort_messages(self): class LineCopy(object): def __init__( - self, - date, - date_printed, - tags, - prefix, - message, - highlight + self, date, date_printed, tags, prefix, message, highlight ): self.date = date self.date_printed = date_printed @@ -1192,18 +1153,25 @@ class RoomBuffer(object): @classmethod def from_line(cls, line): - return cls(line.date, line.date_printed, line.tags, - line.prefix, line.message, line.highlight) + return cls( + line.date, + line.date_printed, + line.tags, + line.prefix, + line.message, + line.highlight, + ) lines = [ LineCopy.from_line(line) for line in self.weechat_buffer.lines ] sorted_lines = sorted(lines, key=lambda line: line.date, reverse=True) - for n, line in enumerate(self.weechat_buffer.lines): - new = sorted_lines[n] - line.update(new.date, new.date_printed, new.tags, new.prefix, - new.message) + for line_number, line in enumerate(self.weechat_buffer.lines): + new = sorted_lines[line_number] + line.update( + new.date, new.date_printed, new.tags, new.prefix, new.message + ) def handle_backlog(self, events): for event in events: @@ -1230,7 +1198,7 @@ class RoomBuffer(object): break if leave_index: - timeline_events = info.timeline.events[leave_index+1:] + timeline_events = info.timeline.events[leave_index + 1 :] # Handle our leave as a state event since we're not in the # nicklist anymore but we're already printed out our leave self.handle_state_event(info.timeline.events[leave_index]) diff --git a/matrix/colors.py b/matrix/colors.py index 6ba9bff..bc4f214 100644 --- a/matrix/colors.py +++ b/matrix/colors.py @@ -18,34 +18,34 @@ from __future__ import unicode_literals +import html +import re +import textwrap + # pylint: disable=redefined-builtin from builtins import str from collections import namedtuple -from matrix import globals as G -from matrix.globals import W -from matrix.utils import string_strikethrough -import re -import textwrap import webcolors - from pygments import highlight -from pygments.lexers import guess_lexer, get_lexer_by_name from pygments.formatter import Formatter +from pygments.lexers import get_lexer_by_name, guess_lexer from pygments.util import ClassNotFound +from . import globals as G +from .globals import W +from .utils import string_strikethrough + try: from HTMLParser import HTMLParser except ImportError: from html.parser import HTMLParser -import html -FormattedString = namedtuple('FormattedString', ['text', 'attributes']) +FormattedString = namedtuple("FormattedString", ["text", "attributes"]) -class Formatted(): - +class Formatted: def __init__(self, substrings): # type: (List[FormattedString]) -> None self.substrings = substrings @@ -55,8 +55,8 @@ class Formatted(): return textwrap.TextWrapper( width=67, initial_indent="{}> ".format(W.color(G.CONFIG.color.quote)), - subsequent_indent="{}> ".format(W.color(G.CONFIG.color.quote)) - ) + subsequent_indent="{}> ".format(W.color(G.CONFIG.color.quote)), + ) def is_formatted(self): # type: (Formatted) -> bool @@ -89,21 +89,22 @@ class Formatted(): # Markdown bold elif line[i] == "*": - if attributes["italic"] and not line[i-1].isspace(): + if attributes["italic"] and not line[i - 1].isspace(): if text: - substrings.append(FormattedString( - text, attributes.copy())) + substrings.append( + FormattedString(text, attributes.copy()) + ) text = "" attributes["italic"] = not attributes["italic"] i = i + 1 continue - elif attributes["italic"] and line[i-1].isspace(): + elif attributes["italic"] and line[i - 1].isspace(): text = text + line[i] i = i + 1 continue - elif i+1 < len(line) and line[i+1].isspace(): + elif i + 1 < len(line) and line[i + 1].isspace(): text = text + line[i] i = i + 1 continue @@ -201,27 +202,34 @@ class Formatted(): 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: + bold_on="", text=string, bold_off="" + ) + if name == "italic" and value: return "{italic_on}{text}{italic_off}".format( - italic_on="", text=string, italic_off="") - elif name == "underline" and value: + italic_on="", text=string, italic_off="" + ) + if name == "underline" and value: return "{underline_on}{text}{underline_off}".format( - underline_on="", text=string, underline_off="") - elif name == "strikethrough" and value: + underline_on="", text=string, underline_off="" + ) + if name == "strikethrough" and value: return "{strike_on}{text}{strike_off}".format( - strike_on="", text=string, strike_off="") - elif name == "quote" and value: + strike_on="", text=string, strike_off="" + ) + if name == "quote" and value: return "{quote_on}{text}{quote_off}".format( quote_on="
", text=string, - quote_off="
") - elif name == "fgcolor" and value: + quote_off="", + ) + if name == "fgcolor" and value: return "{color_on}{text}{color_off}".format( color_on="".format( - color=color_weechat_to_html(value)), + color=color_weechat_to_html(value) + ), text=string, - color_off="") + color_off="", + ) return string @@ -261,28 +269,32 @@ class Formatted(): return "{bold_on}{text}{bold_off}".format( bold_on=W.color("bold"), text=string, - bold_off=W.color("-bold")) + bold_off=W.color("-bold"), + ) - elif name == "italic" and value: + if name == "italic" and value: return "{italic_on}{text}{italic_off}".format( italic_on=W.color("italic"), text=string, - italic_off=W.color("-italic")) + italic_off=W.color("-italic"), + ) - elif name == "underline" and value: + if name == "underline" and value: return "{underline_on}{text}{underline_off}".format( underline_on=W.color("underline"), text=string, - underline_off=W.color("-underline")) + underline_off=W.color("-underline"), + ) - elif name == "strikethrough" and value: + if name == "strikethrough" and value: return string_strikethrough(string) - elif name == "quote" and value: + if name == "quote" and value: return self.textwrapper.fill( - W.string_remove_color(string.replace("\n", ""), "")) + W.string_remove_color(string.replace("\n", ""), "") + ) - elif name == "code" and value: + if name == "code" and value: try: lexer = get_lexer_by_name(value) except ClassNotFound: @@ -292,17 +304,19 @@ class Formatted(): # from the output return highlight(string, lexer, WeechatFormatter())[:-1] - elif name == "fgcolor" and value: + if name == "fgcolor" and value: return "{color_on}{text}{color_off}".format( color_on=W.color(value), text=string, - color_off=W.color("resetcolor")) + color_off=W.color("resetcolor"), + ) - elif name == "bgcolor" and value: + if name == "bgcolor" and value: return "{color_on}{text}{color_off}".format( color_on=W.color("," + value), text=string, - color_off=W.color("resetcolor")) + color_off=W.color("resetcolor"), + ) return string @@ -313,17 +327,18 @@ class Formatted(): # We need to handle strikethrough first, since doing # a strikethrough followed by other attributes succeeds in the # terminal, but doing it the other way around results in garbage. - if 'strikethrough' in attributes: - text = add_attribute(text, 'strikethrough', - attributes['strikethrough']) - attributes.pop('strikethrough') + if "strikethrough" in attributes: + text = add_attribute( + text, "strikethrough", attributes["strikethrough"] + ) + attributes.pop("strikethrough") for key, value in attributes.items(): text = add_attribute(text, key, value) return text weechat_strings = map(format_string, self.substrings) - return re.sub(r'\n+', '\n', "".join(weechat_strings)).strip() + return re.sub(r"\n+", "\n", "".join(weechat_strings)).strip() # TODO this should be a typed dict. @@ -335,7 +350,7 @@ DEFAULT_ATRIBUTES = { "quote": False, "code": None, "fgcolor": None, - "bgcolor": None + "bgcolor": None, } @@ -566,7 +581,7 @@ def color_line_to_weechat(color_string): "96": "250", "97": "254", "98": "231", - "99": "default" + "99": "default", } assert color_string in line_colors @@ -623,7 +638,7 @@ def colour_find_rgb(r, g, b): cb = q2c[qb] # If we have hit the colour exactly, return early. - if (cr == r and cg == g and cb == b): + if cr == r and cg == g and cb == b: return 16 + (36 * qr) + (6 * qg) + qb # Work out the closest grey (average of RGB). @@ -964,8 +979,7 @@ def color_weechat_to_html(color): # yapf: enable if color in weechat_basic_colors: return hex_colors[weechat_basic_colors[color]] - else: - return hex_colors[color] + return hex_colors[color] class WeechatFormatter(Formatter): @@ -977,7 +991,8 @@ class WeechatFormatter(Formatter): start = end = "" if style["color"]: start += "{}".format( - W.color(color_html_to_weechat(str(style["color"])))) + W.color(color_html_to_weechat(str(style["color"]))) + ) end = "{}".format(W.color("resetcolor")) + end if style["bold"]: start += W.color("bold") @@ -985,13 +1000,13 @@ class WeechatFormatter(Formatter): if style["italic"]: start += W.color("italic") end = W.color("-italic") + end - if style['underline']: + if style["underline"]: start += W.color("underline") end = W.color("-underline") + end self.styles[token] = (start, end) def format(self, tokensource, outfile): - lastval = '' + lastval = "" lasttype = None for ttype, value in tokensource: diff --git a/matrix/commands.py b/matrix/commands.py index 280149e..beaed12 100644 --- a/matrix/commands.py +++ b/matrix/commands.py @@ -15,18 +15,17 @@ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. from __future__ import unicode_literals + +import argparse +import re from builtins import str -import re -import argparse - -import matrix.globals -from matrix.globals import W, SERVERS - -from matrix.utf import utf8_decode -from matrix.utils import key_from_value, tags_from_line_data -from matrix.server import MatrixServer -from matrix.colors import Formatted +from . import globals as G +from .colors import Formatted +from .globals import SERVERS, W +from .server import MatrixServer +from .utf import utf8_decode +from .utils import key_from_value, tags_from_line_data class ParseError(Exception): @@ -34,15 +33,15 @@ class ParseError(Exception): class WeechatArgParse(argparse.ArgumentParser): - def print_usage(self, file): + def print_usage(self, file=None): pass def error(self, message): - m = ("{prefix}Error: {message} for command {command} " - "(see /help {command})").format(prefix=W.prefix("error"), - message=message, - command=self.prog) - W.prnt("", m) + message = ( + "{prefix}Error: {message} for command {command} " + "(see /help {command})" + ).format(prefix=W.prefix("error"), message=message, command=self.prog) + W.prnt("", message) raise ParseError @@ -95,49 +94,59 @@ class WeechatCommandParser(object): def hook_commands(): W.hook_command( # Command name and short description - 'matrix', - 'Matrix chat protocol command', + "matrix", + "Matrix chat protocol command", # Synopsis - ('server add [:] ||' - 'server delete|list|listfull ||' - 'connect ||' - 'disconnect ||' - 'reconnect ||' - 'help '), + ( + "server add [:] ||" + "server delete|list|listfull ||" + "connect ||" + "disconnect ||" + "reconnect ||" + "help " + ), # Description - (' server: list, add, or remove Matrix servers\n' - ' connect: connect to Matrix servers\n' - 'disconnect: disconnect from one or all Matrix servers\n' - ' reconnect: reconnect to server(s)\n\n' - ' help: show detailed command help\n\n' - 'Use /matrix help [command] to find out more.\n'), + ( + " server: list, add, or remove Matrix servers\n" + " connect: connect to Matrix servers\n" + "disconnect: disconnect from one or all Matrix servers\n" + " reconnect: reconnect to server(s)\n\n" + " help: show detailed command help\n\n" + "Use /matrix help [command] to find out more.\n" + ), # Completions - ('server %(matrix_server_commands)|%* ||' - 'connect %(matrix_servers) ||' - 'disconnect %(matrix_servers) ||' - 'reconnect %(matrix_servers) ||' - 'help %(matrix_commands)'), + ( + "server %(matrix_server_commands)|%* ||" + "connect %(matrix_servers) ||" + "disconnect %(matrix_servers) ||" + "reconnect %(matrix_servers) ||" + "help %(matrix_commands)" + ), # Function name - 'matrix_command_cb', - '') + "matrix_command_cb", + "", + ) W.hook_command( # Command name and short description - 'redact', - 'redact messages', + "redact", + "redact messages", # Synopsis ('[:""] []'), # Description - ("message-number: number of message to redact (starting from 1 for\n" - " the last message received, counting up)\n" - " message-part: an initial part of the message (ignored, only used\n" - " as visual feedback when using completion)\n" - " reason: the redaction reason\n"), + ( + "message-number: number of message to redact (starting from 1 for\n" + " the last message received, counting up)\n" + " message-part: an initial part of the message (ignored, only used\n" + " as visual feedback when using completion)\n" + " reason: the redaction reason\n" + ), # Completions - ('%(matrix_messages)'), + ("%(matrix_messages)"), # Function name - 'matrix_redact_command_cb', - '') + "matrix_redact_command_cb", + "", + ) W.hook_command( # Command name and short description @@ -146,13 +155,13 @@ def hook_commands(): # Synopsis ("[|-delete]"), # Description - (" topic: topic to set\n" - "-delete: delete room topic"), + (" topic: topic to set\n" "-delete: delete room topic"), # Completions "", # Callback "matrix_topic_command_cb", - "") + "", + ) W.hook_command( # Command name and short description @@ -166,7 +175,8 @@ def hook_commands(): "", # Callback "matrix_me_command_cb", - "") + "", + ) W.hook_command( # Command name and short description @@ -175,13 +185,16 @@ def hook_commands(): # Synopsis (" []"), # Description - ("user-id: user-id to kick\n" - " reason: reason why the user was kicked"), + ( + "user-id: user-id to kick\n" + " reason: reason why the user was kicked" + ), # Completions ("%(matrix_users)"), # Callback "matrix_kick_command_cb", - "") + "", + ) W.hook_command( # Command name and short description @@ -195,7 +208,8 @@ def hook_commands(): ("%(matrix_users)"), # Callback "matrix_invite_command_cb", - "") + "", + ) W.hook_command( # Command name and short description @@ -204,13 +218,16 @@ def hook_commands(): # Synopsis ("|"), # Description - (" room-id: room-id of the room to join\n" - "room-alias: room alias of the room to join"), + ( + " room-id: room-id of the room to join\n" + "room-alias: room alias of the room to join" + ), # Completions "", # Callback "matrix_join_command_cb", - "") + "", + ) W.hook_command( # Command name and short description @@ -224,12 +241,13 @@ def hook_commands(): "", # Callback "matrix_part_command_cb", - "") + "", + ) - W.hook_command_run('/buffer clear', 'matrix_command_buf_clear_cb', '') + W.hook_command_run("/buffer clear", "matrix_command_buf_clear_cb", "") # if OPTIONS.enable_backlog: - # hook_page_up() + # hook_page_up() @utf8_decode @@ -238,8 +256,9 @@ def matrix_me_command_cb(data, buffer, args): if buffer in server.buffers.values(): if not server.connected: - message = ("{prefix}matrix: you are not connected to " - "the server").format(prefix=W.prefix("error")) + message = ( + "{prefix}matrix: you are not connected to " "the server" + ).format(prefix=W.prefix("error")) W.prnt(server.server_buffer, message) return W.WEECHAT_RC_ERROR @@ -253,13 +272,16 @@ def matrix_me_command_cb(data, buffer, args): server.room_send_message(room_buffer, formatted_data, "m.emote") return W.WEECHAT_RC_OK - elif buffer == server.server_buffer: - message = ("{prefix}matrix: command \"me\" must be " - "executed on a Matrix channel buffer" - ).format(prefix=W.prefix("error")) + if buffer == server.server_buffer: + message = ( + '{prefix}matrix: command "me" must be ' + "executed on a Matrix channel buffer" + ).format(prefix=W.prefix("error")) W.prnt("", message) return W.WEECHAT_RC_OK + return W.WEECHAT_RC_OK + @utf8_decode def matrix_topic_command_cb(data, buffer, args): @@ -269,8 +291,9 @@ def matrix_topic_command_cb(data, buffer, args): for server in SERVERS.values(): if buffer == server.server_buffer: - server.error("command \"topic\" must be " - "executed on a Matrix room buffer") + server.error( + 'command "topic" must be ' "executed on a Matrix room buffer" + ) return W.WEECHAT_RC_OK room = server.find_room_from_ptr(buffer) @@ -310,15 +333,17 @@ def matrix_fetch_old_messages(server, room_id): def check_server_existence(server_name, servers): if server_name not in servers: message = "{prefix}matrix: No such server: {server}".format( - prefix=W.prefix("error"), server=server_name) + prefix=W.prefix("error"), server=server_name + ) W.prnt("", message) return False return True def hook_page_up(): - OPTIONS.page_up_hook = W.hook_command_run('/window page_up', - 'matrix_command_pgup_cb', '') + G.CONFIG.page_up_hook = W.hook_command_run( + "/window page_up", "matrix_command_pgup_cb", "" + ) @utf8_decode @@ -345,7 +370,8 @@ def matrix_command_pgup_cb(data, buffer, command): window = W.window_search_with_buffer(buffer) first_line_displayed = bool( - W.window_get_integer(window, "first_line_displayed")) + W.window_get_integer(window, "first_line_displayed") + ) if first_line_displayed: room_id = key_from_value(server.buffers, buffer) @@ -382,9 +408,11 @@ def matrix_part_command_cb(data, buffer, args): if not room_id: if buffer == server.server_buffer: - server.error("command \"part\" must be " - "executed on a Matrix room buffer or a room " - "name needs to be given") + server.error( + 'command "part" must be ' + "executed on a Matrix room buffer or a room " + "name needs to be given" + ) return W.WEECHAT_RC_OK room_buffer = server.find_room_from_ptr(buffer) @@ -404,8 +432,9 @@ def matrix_invite_command_cb(data, buffer, args): for server in SERVERS.values(): if buffer == server.server_buffer: - server.error("command \"invite\" must be " - "executed on a Matrix room buffer") + server.error( + 'command "invite" must be ' "executed on a Matrix room buffer" + ) return W.WEECHAT_RC_OK room = server.find_room_from_ptr(buffer) @@ -429,8 +458,9 @@ def matrix_kick_command_cb(data, buffer, args): for server in SERVERS.values(): if buffer == server.server_buffer: - server.error("command \"kick\" must be " - "executed on a Matrix room buffer") + server.error( + 'command "kick" must be ' "executed on a Matrix room buffer" + ) return W.WEECHAT_RC_OK room = server.find_room_from_ptr(buffer) @@ -449,22 +479,24 @@ def matrix_kick_command_cb(data, buffer, args): def event_id_from_line(buf, target_number): # type: (weechat.buffer, int) -> str - own_lines = W.hdata_pointer(W.hdata_get('buffer'), buf, 'own_lines') + own_lines = W.hdata_pointer(W.hdata_get("buffer"), buf, "own_lines") if own_lines: - line = W.hdata_pointer(W.hdata_get('lines'), own_lines, 'last_line') + line = W.hdata_pointer(W.hdata_get("lines"), own_lines, "last_line") line_number = 1 while line: - line_data = W.hdata_pointer(W.hdata_get('line'), line, 'data') + line_data = W.hdata_pointer(W.hdata_get("line"), line, "data") if line_data: tags = tags_from_line_data(line_data) # Only count non redacted user messages - if ("matrix_message" in tags and - 'matrix_redacted' not in tags and - "matrix_new_redacted" not in tags): + if ( + "matrix_message" in tags + and "matrix_redacted" not in tags + and "matrix_new_redacted" not in tags + ): if line_number == target_number: for tag in tags: @@ -474,7 +506,7 @@ def event_id_from_line(buf, target_number): line_number += 1 - line = W.hdata_move(W.hdata_get('line'), line, -1) + line = W.hdata_move(W.hdata_get("line"), line, -1) return "" @@ -488,9 +520,10 @@ def matrix_redact_command_cb(data, buffer, args): matches = re.match(r"(\d+)(:\".*\")? ?(.*)?", args) if not matches: - message = ("{prefix}matrix: Invalid command " - "arguments (see /help redact)" - ).format(prefix=W.prefix("error")) + message = ( + "{prefix}matrix: Invalid command " + "arguments (see /help redact)" + ).format(prefix=W.prefix("error")) W.prnt("", message) return W.WEECHAT_RC_ERROR @@ -500,9 +533,10 @@ def matrix_redact_command_cb(data, buffer, args): event_id = event_id_from_line(buffer, line) if not event_id: - message = ("{prefix}matrix: No such message with number " - "{number} found").format( - prefix=W.prefix("error"), number=line) + message = ( + "{prefix}matrix: No such message with number " + "{number} found" + ).format(prefix=W.prefix("error"), number=line) W.prnt("", message) return W.WEECHAT_RC_OK @@ -510,10 +544,11 @@ def matrix_redact_command_cb(data, buffer, args): return W.WEECHAT_RC_OK - elif buffer == server.server_buffer: - message = ("{prefix}matrix: command \"redact\" must be " - "executed on a Matrix channel buffer" - ).format(prefix=W.prefix("error")) + if buffer == server.server_buffer: + message = ( + '{prefix}matrix: command "redact" must be ' + "executed on a Matrix channel buffer" + ).format(prefix=W.prefix("error")) W.prnt("", message) return W.WEECHAT_RC_OK @@ -522,9 +557,10 @@ def matrix_redact_command_cb(data, buffer, args): def matrix_command_help(args): if not args: - message = ("{prefix}matrix: Too few arguments for command " - "\"/matrix help\" (see /matrix help help)" - ).format(prefix=W.prefix("error")) + message = ( + "{prefix}matrix: Too few arguments for command " + '"/matrix help" (see /matrix help help)' + ).format(prefix=W.prefix("error")) W.prnt("", message) return @@ -532,88 +568,104 @@ def matrix_command_help(args): message = "" if command == "connect": - message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] " - "{ncolor}{cmd_color}/connect{ncolor} " - " [...]" - "\n\n" - "connect to Matrix server(s)" - "\n\n" - "server-name: server to connect to" - "(internal name)").format( - delimiter_color=W.color("chat_delimiters"), - cmd_color=W.color("chat_buffer"), - ncolor=W.color("reset")) + message = ( + "{delimiter_color}[{ncolor}matrix{delimiter_color}] " + "{ncolor}{cmd_color}/connect{ncolor} " + " [...]" + "\n\n" + "connect to Matrix server(s)" + "\n\n" + "server-name: server to connect to" + "(internal name)" + ).format( + delimiter_color=W.color("chat_delimiters"), + cmd_color=W.color("chat_buffer"), + ncolor=W.color("reset"), + ) elif command == "disconnect": - message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] " - "{ncolor}{cmd_color}/disconnect{ncolor} " - " [...]" - "\n\n" - "disconnect from Matrix server(s)" - "\n\n" - "server-name: server to disconnect" - "(internal name)").format( - delimiter_color=W.color("chat_delimiters"), - cmd_color=W.color("chat_buffer"), - ncolor=W.color("reset")) + message = ( + "{delimiter_color}[{ncolor}matrix{delimiter_color}] " + "{ncolor}{cmd_color}/disconnect{ncolor} " + " [...]" + "\n\n" + "disconnect from Matrix server(s)" + "\n\n" + "server-name: server to disconnect" + "(internal name)" + ).format( + delimiter_color=W.color("chat_delimiters"), + cmd_color=W.color("chat_buffer"), + ncolor=W.color("reset"), + ) elif command == "reconnect": - message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] " - "{ncolor}{cmd_color}/reconnect{ncolor} " - " [...]" - "\n\n" - "reconnect to Matrix server(s)" - "\n\n" - "server-name: server to reconnect" - "(internal name)").format( - delimiter_color=W.color("chat_delimiters"), - cmd_color=W.color("chat_buffer"), - ncolor=W.color("reset")) + message = ( + "{delimiter_color}[{ncolor}matrix{delimiter_color}] " + "{ncolor}{cmd_color}/reconnect{ncolor} " + " [...]" + "\n\n" + "reconnect to Matrix server(s)" + "\n\n" + "server-name: server to reconnect" + "(internal name)" + ).format( + delimiter_color=W.color("chat_delimiters"), + cmd_color=W.color("chat_buffer"), + ncolor=W.color("reset"), + ) elif command == "server": - message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] " - "{ncolor}{cmd_color}/server{ncolor} " - "add [:]" - "\n " - "delete|list|listfull " - "\n\n" - "list, add, or remove Matrix servers" - "\n\n" - " list: list servers (without argument, this " - "list is displayed)\n" - " listfull: list servers with detailed info for each " - "server\n" - " add: add a new server\n" - " delete: delete a server\n" - "server-name: server to reconnect (internal name)\n" - " hostname: name or IP address of server\n" - " port: port of server (default: 8448)\n" - "\n" - "Examples:" - "\n /matrix server listfull" - "\n /matrix server add matrix matrix.org:80" - "\n /matrix server del matrix").format( - delimiter_color=W.color("chat_delimiters"), - cmd_color=W.color("chat_buffer"), - ncolor=W.color("reset")) + message = ( + "{delimiter_color}[{ncolor}matrix{delimiter_color}] " + "{ncolor}{cmd_color}/server{ncolor} " + "add [:]" + "\n " + "delete|list|listfull " + "\n\n" + "list, add, or remove Matrix servers" + "\n\n" + " list: list servers (without argument, this " + "list is displayed)\n" + " listfull: list servers with detailed info for each " + "server\n" + " add: add a new server\n" + " delete: delete a server\n" + "server-name: server to reconnect (internal name)\n" + " hostname: name or IP address of server\n" + " port: port of server (default: 8448)\n" + "\n" + "Examples:" + "\n /matrix server listfull" + "\n /matrix server add matrix matrix.org:80" + "\n /matrix server del matrix" + ).format( + delimiter_color=W.color("chat_delimiters"), + cmd_color=W.color("chat_buffer"), + ncolor=W.color("reset"), + ) elif command == "help": - message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] " - "{ncolor}{cmd_color}/help{ncolor} " - " [...]" - "\n\n" - "display help about Matrix commands" - "\n\n" - "matrix-command: a Matrix command name" - "(internal name)").format( - delimiter_color=W.color("chat_delimiters"), - cmd_color=W.color("chat_buffer"), - ncolor=W.color("reset")) + message = ( + "{delimiter_color}[{ncolor}matrix{delimiter_color}] " + "{ncolor}{cmd_color}/help{ncolor} " + " [...]" + "\n\n" + "display help about Matrix commands" + "\n\n" + "matrix-command: a Matrix command name" + "(internal name)" + ).format( + delimiter_color=W.color("chat_delimiters"), + cmd_color=W.color("chat_buffer"), + ncolor=W.color("reset"), + ) else: - message = ("{prefix}matrix: No help available, \"{command}\" " - "is not a matrix command").format( - prefix=W.prefix("error"), command=command) + message = ( + '{prefix}matrix: No help available, "{command}" ' + "is not a matrix command" + ).format(prefix=W.prefix("error"), command=command) W.prnt("", "") W.prnt("", message) @@ -622,7 +674,6 @@ def matrix_command_help(args): def matrix_server_command_listfull(args): - def get_value_string(value, default_value): if value == default_value: if not value: @@ -632,7 +683,8 @@ def matrix_server_command_listfull(args): value_string = "{color}{value}{ncolor}".format( color=W.color("chat_value"), value=value, - ncolor=W.color("reset")) + ncolor=W.color("reset"), + ) return value_string @@ -650,14 +702,17 @@ def matrix_server_command_listfull(args): else: connected = "not connected" - message = ("Server: {server_color}{server}{delimiter_color}" - " [{ncolor}{connected}{delimiter_color}]" - "{ncolor}").format( - server_color=W.color("chat_server"), - server=server.name, - delimiter_color=W.color("chat_delimiters"), - connected=connected, - ncolor=W.color("reset")) + message = ( + "Server: {server_color}{server}{delimiter_color}" + " [{ncolor}{connected}{delimiter_color}]" + "{ncolor}" + ).format( + server_color=W.color("chat_server"), + server=server.name, + delimiter_color=W.color("chat_delimiters"), + connected=connected, + ncolor=W.color("reset"), + ) W.prnt("", message) @@ -703,7 +758,7 @@ def matrix_server_command_listfull(args): if value: value = "(hidden)" - value_string = get_value_string(value, '') + value_string = get_value_string(value, "") message = " password . . : {value}".format(value=value_string) W.prnt("", message) @@ -715,14 +770,17 @@ def matrix_server_command_delete(args): server = SERVERS[server_name] if server.connected: - message = ("{prefix}matrix: you can not delete server " - "{color}{server}{ncolor} because you are " - "connected to it. Try \"/matrix disconnect " - "{color}{server}{ncolor}\" before.").format( - prefix=W.prefix("error"), - color=W.color("chat_server"), - ncolor=W.color("reset"), - server=server.name) + message = ( + "{prefix}matrix: you can not delete server " + "{color}{server}{ncolor} because you are " + 'connected to it. Try "/matrix disconnect ' + '{color}{server}{ncolor}" before.' + ).format( + prefix=W.prefix("error"), + color=W.color("chat_server"), + ncolor=W.color("reset"), + server=server.name, + ) W.prnt("", message) return @@ -735,11 +793,13 @@ def matrix_server_command_delete(args): for option in server.config._option_ptrs.values(): W.config_option_free(option) - message = ("matrix: server {color}{server}{ncolor} has been " - "deleted").format( - server=server.name, - color=W.color("chat_server"), - ncolor=W.color("reset")) + message = ( + "matrix: server {color}{server}{ncolor} has been " "deleted" + ).format( + server=server.name, + color=W.color("chat_server"), + ncolor=W.color("reset"), + ) del SERVERS[server.name] server = None @@ -749,15 +809,17 @@ def matrix_server_command_delete(args): def matrix_server_command_add(args): if len(args) < 2: - message = ("{prefix}matrix: Too few arguments for command " - "\"/matrix server add\" (see /matrix help server)").format( - prefix=W.prefix("error")) + message = ( + "{prefix}matrix: Too few arguments for command " + '"/matrix server add" (see /matrix help server)' + ).format(prefix=W.prefix("error")) W.prnt("", message) return - elif len(args) > 4: - message = ("{prefix}matrix: Too many arguments for command " - "\"/matrix server add\" (see /matrix help server)" - ).format(prefix=W.prefix("error")) + if len(args) > 4: + message = ( + "{prefix}matrix: Too many arguments for command " + '"/matrix server add" (see /matrix help server)' + ).format(prefix=W.prefix("error")) W.prnt("", message) return @@ -769,16 +831,19 @@ def matrix_server_command_add(args): server_name = args[0] if server_name in SERVERS: - message = ("{prefix}matrix: server {color}{server}{ncolor} " - "already exists, can't add it").format( - prefix=W.prefix("error"), - color=W.color("chat_server"), - server=server_name, - ncolor=W.color("reset")) + message = ( + "{prefix}matrix: server {color}{server}{ncolor} " + "already exists, can't add it" + ).format( + prefix=W.prefix("error"), + color=W.color("chat_server"), + server=server_name, + ncolor=W.color("reset"), + ) W.prnt("", message) return - server = MatrixServer(server_name, matrix.globals.CONFIG) + server = MatrixServer(server_name, G.CONFIG._ptr) SERVERS[server.name] = server if len(args) >= 2: @@ -788,20 +853,21 @@ def matrix_server_command_add(args): host, port = args[1], None return_code = W.config_option_set( - server.config._option_ptrs["address"], - host, - 1 + server.config._option_ptrs["address"], host, 1 ) if return_code == W.WEECHAT_CONFIG_OPTION_SET_ERROR: remove_server(server) - message = ("{prefix}Failed to set address for server " - "{color}{server}{ncolor}, failed to add " - "server.").format( - prefix=W.prefix("error"), - color=W.color("chat_server"), - server=server.name, - ncolor=W.color("reset")) + message = ( + "{prefix}Failed to set address for server " + "{color}{server}{ncolor}, failed to add " + "server." + ).format( + prefix=W.prefix("error"), + color=W.color("chat_server"), + server=server.name, + ncolor=W.color("reset"), + ) W.prnt("", message) server = None @@ -809,19 +875,20 @@ def matrix_server_command_add(args): if port: return_code = W.config_option_set( - server.config._option_ptrs["port"], - port, - 1 + server.config._option_ptrs["port"], port, 1 ) if return_code == W.WEECHAT_CONFIG_OPTION_SET_ERROR: remove_server(server) - message = ("{prefix}Failed to set port for server " - "{color}{server}{ncolor}, failed to add " - "server.").format( - prefix=W.prefix("error"), - color=W.color("chat_server"), - server=server.name, - ncolor=W.color("reset")) + message = ( + "{prefix}Failed to set port for server " + "{color}{server}{ncolor}, failed to add " + "server." + ).format( + prefix=W.prefix("error"), + color=W.color("chat_server"), + server=server.name, + ncolor=W.color("reset"), + ) W.prnt("", message) server = None @@ -830,20 +897,21 @@ def matrix_server_command_add(args): if len(args) >= 3: user = args[2] return_code = W.config_option_set( - server.config._option_ptrs["username"], - user, - 1 + server.config._option_ptrs["username"], user, 1 ) if return_code == W.WEECHAT_CONFIG_OPTION_SET_ERROR: remove_server(server) - message = ("{prefix}Failed to set user for server " - "{color}{server}{ncolor}, failed to add " - "server.").format( - prefix=W.prefix("error"), - color=W.color("chat_server"), - server=server.name, - ncolor=W.color("reset")) + message = ( + "{prefix}Failed to set user for server " + "{color}{server}{ncolor}, failed to add " + "server." + ).format( + prefix=W.prefix("error"), + color=W.color("chat_server"), + server=server.name, + ncolor=W.color("reset"), + ) W.prnt("", message) server = None @@ -853,28 +921,31 @@ def matrix_server_command_add(args): password = args[3] return_code = W.config_option_set( - server.config._option_ptrs["password"], - password, - 1 + server.config._option_ptrs["password"], password, 1 ) if return_code == W.WEECHAT_CONFIG_OPTION_SET_ERROR: remove_server(server) - message = ("{prefix}Failed to set password for server " - "{color}{server}{ncolor}, failed to add " - "server.").format( - prefix=W.prefix("error"), - color=W.color("chat_server"), - server=server.name, - ncolor=W.color("reset")) + message = ( + "{prefix}Failed to set password for server " + "{color}{server}{ncolor}, failed to add " + "server." + ).format( + prefix=W.prefix("error"), + color=W.color("chat_server"), + server=server.name, + ncolor=W.color("reset"), + ) W.prnt("", message) server = None return - message = ("matrix: server {color}{server}{ncolor} " - "has been added").format( - server=server.name, - color=W.color("chat_server"), - ncolor=W.color("reset")) + message = ( + "matrix: server {color}{server}{ncolor} " "has been added" + ).format( + server=server.name, + color=W.color("chat_server"), + ncolor=W.color("reset"), + ) W.prnt("", message) @@ -883,23 +954,28 @@ def matrix_server_command(command, args): if SERVERS: W.prnt("", "\nAll matrix servers:") for server in SERVERS: - W.prnt("", " {color}{server}".format( - color=W.color("chat_server"), server=server)) + W.prnt( + "", + " {color}{server}".format( + color=W.color("chat_server"), server=server + ), + ) # TODO the argument for list and listfull is used as a match word to # find/filter servers, we're currently match exactly to the whole name - if command == 'list': + if command == "list": list_servers(args) - elif command == 'listfull': + elif command == "listfull": matrix_server_command_listfull(args) - elif command == 'add': + elif command == "add": matrix_server_command_add(args) - elif command == 'delete': + elif command == "delete": matrix_server_command_delete(args) else: - message = ("{prefix}matrix: Error: unknown matrix server command, " - "\"{command}\" (type /matrix help server for help)").format( - prefix=W.prefix("error"), command=command) + message = ( + "{prefix}matrix: Error: unknown matrix server command, " + '"{command}" (type /matrix help server for help)' + ).format(prefix=W.prefix("error"), command=command) W.prnt("", message) @@ -921,41 +997,44 @@ def matrix_command_cb(data, buffer, args): server.access_token = "" server.disconnect(reconnect=False) - split_args = list(filter(bool, args.split(' '))) + split_args = list(filter(bool, args.split(" "))) if len(split_args) < 1: - message = ("{prefix}matrix: Too few arguments for command " - "\"/matrix\" " - "(see /help matrix)").format(prefix=W.prefix("error")) + message = ( + "{prefix}matrix: Too few arguments for command " + '"/matrix" ' + "(see /help matrix)" + ).format(prefix=W.prefix("error")) W.prnt("", message) return W.WEECHAT_RC_ERROR command, args = split_args[0], split_args[1:] - if command == 'connect': + if command == "connect": connect_server(args) - elif command == 'disconnect': + elif command == "disconnect": disconnect_server(args) - elif command == 'reconnect': + elif command == "reconnect": disconnect_server(args) connect_server(args) - elif command == 'server': + elif command == "server": if len(args) >= 1: subcommand, args = args[0], args[1:] matrix_server_command(subcommand, args) else: matrix_server_command("list", "") - elif command == 'help': + elif command == "help": matrix_command_help(args) else: - message = ("{prefix}matrix: Error: unknown matrix command, " - "\"{command}\" (type /help matrix for help)").format( - prefix=W.prefix("error"), command=command) + message = ( + "{prefix}matrix: Error: unknown matrix command, " + '"{command}" (type /help matrix for help)' + ).format(prefix=W.prefix("error"), command=command) W.prnt("", message) return W.WEECHAT_RC_OK diff --git a/matrix/completion.py b/matrix/completion.py index ce5c471..bf00682 100644 --- a/matrix/completion.py +++ b/matrix/completion.py @@ -16,29 +16,32 @@ from __future__ import unicode_literals +from matrix.globals import SERVERS, W from matrix.utf import utf8_decode -from matrix.globals import W, SERVERS from matrix.utils import tags_from_line_data def add_servers_to_completion(completion): for server_name in SERVERS: - W.hook_completion_list_add(completion, server_name, 0, - W.WEECHAT_LIST_POS_SORT) + W.hook_completion_list_add( + completion, server_name, 0, W.WEECHAT_LIST_POS_SORT + ) @utf8_decode -def matrix_server_command_completion_cb(data, completion_item, buffer, - completion): +def matrix_server_command_completion_cb( + data, completion_item, buffer, completion +): buffer_input = W.buffer_get_string(buffer, "input").split() args = buffer_input[1:] - commands = ['add', 'delete', 'list', 'listfull'] + commands = ["add", "delete", "list", "listfull"] def complete_commands(): for command in commands: - W.hook_completion_list_add(completion, command, 0, - W.WEECHAT_LIST_POS_SORT) + W.hook_completion_list_add( + completion, command, 0, W.WEECHAT_LIST_POS_SORT + ) if len(args) == 1: complete_commands() @@ -47,11 +50,11 @@ def matrix_server_command_completion_cb(data, completion_item, buffer, if args[1] not in commands: complete_commands() else: - if args[1] == 'delete' or args[1] == 'listfull': + if args[1] == "delete" or args[1] == "listfull": add_servers_to_completion(completion) elif len(args) == 3: - if args[1] == 'delete' or args[1] == 'listfull': + if args[1] == "delete" or args[1] == "listfull": if args[2] not in SERVERS: add_servers_to_completion(completion) @@ -67,18 +70,25 @@ def matrix_server_completion_cb(data, completion_item, buffer, completion): @utf8_decode def matrix_command_completion_cb(data, completion_item, buffer, completion): for command in [ - "connect", "disconnect", "reconnect", "server", "help", "debug" + "connect", + "disconnect", + "reconnect", + "server", + "help", + "debug", ]: - W.hook_completion_list_add(completion, command, 0, - W.WEECHAT_LIST_POS_SORT) + W.hook_completion_list_add( + completion, command, 0, W.WEECHAT_LIST_POS_SORT + ) return W.WEECHAT_RC_OK @utf8_decode def matrix_debug_completion_cb(data, completion_item, buffer, completion): for debug_type in ["messaging", "network", "timing"]: - W.hook_completion_list_add(completion, debug_type, 0, - W.WEECHAT_LIST_POS_SORT) + W.hook_completion_list_add( + completion, debug_type, 0, W.WEECHAT_LIST_POS_SORT + ) return W.WEECHAT_RC_OK @@ -88,46 +98,52 @@ REDACTION_COMP_LEN = 50 @utf8_decode def matrix_message_completion_cb(data, completion_item, buffer, completion): - own_lines = W.hdata_pointer(W.hdata_get('buffer'), buffer, 'own_lines') + own_lines = W.hdata_pointer(W.hdata_get("buffer"), buffer, "own_lines") if own_lines: - line = W.hdata_pointer(W.hdata_get('lines'), own_lines, 'last_line') + line = W.hdata_pointer(W.hdata_get("lines"), own_lines, "last_line") line_number = 1 while line: - line_data = W.hdata_pointer(W.hdata_get('line'), line, 'data') + line_data = W.hdata_pointer(W.hdata_get("line"), line, "data") if line_data: message = W.hdata_string( - W.hdata_get('line_data'), line_data, 'message') + W.hdata_get("line_data"), line_data, "message" + ) tags = tags_from_line_data(line_data) # Only add non redacted user messages to the completion - if (message and 'matrix_message' in tags and - 'matrix_redacted' not in tags): + if ( + message + and "matrix_message" in tags + and "matrix_redacted" not in tags + ): if len(message) > REDACTION_COMP_LEN + 2: - message = (message[:REDACTION_COMP_LEN] + '..') + message = message[:REDACTION_COMP_LEN] + ".." - item = ("{number}:\"{message}\"").format( - number=line_number, message=message) + item = ('{number}:"{message}"').format( + number=line_number, message=message + ) - W.hook_completion_list_add(completion, item, 0, - W.WEECHAT_LIST_POS_END) + W.hook_completion_list_add( + completion, item, 0, W.WEECHAT_LIST_POS_END + ) line_number += 1 - line = W.hdata_move(W.hdata_get('line'), line, -1) + line = W.hdata_move(W.hdata_get("line"), line, -1) return W.WEECHAT_RC_OK def server_from_buffer(buffer): for server in SERVERS.values(): - if buffer in server.buffers.values(): - return server - elif buffer == server.server_buffer: - return server + if buffer in server.buffers.values(): + return server + if buffer == server.server_buffer: + return server return None @@ -141,8 +157,9 @@ def matrix_olm_user_completion_cb(data, completion_item, buffer, completion): olm = server.olm for user in olm.device_keys: - W.hook_completion_list_add(completion, user, 0, - W.WEECHAT_LIST_POS_SORT) + W.hook_completion_list_add( + completion, user, 0, W.WEECHAT_LIST_POS_SORT + ) return W.WEECHAT_RC_OK @@ -169,8 +186,9 @@ def matrix_olm_device_completion_cb(data, completion_item, buffer, completion): return W.WEECHAT_RC_OK for device in olm.device_keys[user]: - W.hook_completion_list_add(completion, device.device_id, 0, - W.WEECHAT_LIST_POS_SORT) + W.hook_completion_list_add( + completion, device.device_id, 0, W.WEECHAT_LIST_POS_SORT + ) return W.WEECHAT_RC_OK @@ -178,8 +196,9 @@ def matrix_olm_device_completion_cb(data, completion_item, buffer, completion): @utf8_decode def matrix_user_completion_cb(data, completion_item, buffer, completion): def add_user(completion, user): - W.hook_completion_list_add(completion, user, 0, - W.WEECHAT_LIST_POS_SORT) + W.hook_completion_list_add( + completion, user, 0, W.WEECHAT_LIST_POS_SORT + ) for server in SERVERS.values(): if buffer == server.server_buffer: @@ -201,26 +220,58 @@ def matrix_user_completion_cb(data, completion_item, buffer, completion): def init_completion(): - W.hook_completion("matrix_server_commands", "Matrix server completion", - "matrix_server_command_completion_cb", "") + W.hook_completion( + "matrix_server_commands", + "Matrix server completion", + "matrix_server_command_completion_cb", + "", + ) - W.hook_completion("matrix_servers", "Matrix server completion", - "matrix_server_completion_cb", "") + W.hook_completion( + "matrix_servers", + "Matrix server completion", + "matrix_server_completion_cb", + "", + ) - W.hook_completion("matrix_commands", "Matrix command completion", - "matrix_command_completion_cb", "") + W.hook_completion( + "matrix_commands", + "Matrix command completion", + "matrix_command_completion_cb", + "", + ) - W.hook_completion("matrix_messages", "Matrix message completion", - "matrix_message_completion_cb", "") + W.hook_completion( + "matrix_messages", + "Matrix message completion", + "matrix_message_completion_cb", + "", + ) - W.hook_completion("matrix_debug_types", "Matrix debugging type completion", - "matrix_debug_completion_cb", "") + W.hook_completion( + "matrix_debug_types", + "Matrix debugging type completion", + "matrix_debug_completion_cb", + "", + ) - W.hook_completion("olm_user_ids", "Matrix olm user id completion", - "matrix_olm_user_completion_cb", "") + W.hook_completion( + "olm_user_ids", + "Matrix olm user id completion", + "matrix_olm_user_completion_cb", + "", + ) - W.hook_completion("olm_devices", "Matrix olm device id completion", - "matrix_olm_device_completion_cb", "") + W.hook_completion( + "olm_devices", + "Matrix olm device id completion", + "matrix_olm_device_completion_cb", + "", + ) - W.hook_completion("matrix_users", "Matrix user id completion", - "matrix_user_completion_cb", "") + W.hook_completion( + "matrix_users", + "Matrix user id completion", + "matrix_user_completion_cb", + "", + ) diff --git a/matrix/config.py b/matrix/config.py index 06b9c4a..7a82c14 100644 --- a/matrix/config.py +++ b/matrix/config.py @@ -16,16 +16,16 @@ # from __future__ import unicode_literals from builtins import super +from collections import namedtuple +from enum import Enum, unique -import nio import logbook +import nio -from . import globals as G -from matrix.globals import W, SERVERS, SCRIPT_NAME +from matrix.globals import SCRIPT_NAME, SERVERS, W from matrix.utf import utf8_decode -from enum import Enum, unique -from collections import namedtuple +from . import globals as G @unique @@ -49,20 +49,22 @@ class DebugType(Enum): TIMING = 2 -class Option(namedtuple( - 'Option', - [ - 'name', - 'type', - 'string_values', - 'min', - 'max', - 'value', - 'description', - 'cast_func', - 'change_callback' - ] -)): +class Option( + namedtuple( + "Option", + [ + "name", + "type", + "string_values", + "min", + "max", + "value", + "description", + "cast_func", + "change_callback", + ], + ) +): __slots__ = () def __new__( @@ -75,7 +77,7 @@ class Option(namedtuple( value, description, cast=None, - change_callback=None + change_callback=None, ): return super().__new__( cls, @@ -87,12 +89,10 @@ class Option(namedtuple( value, description, cast, - change_callback + change_callback, ) - - @utf8_decode def matrix_config_reload_cb(data, config_file): return W.WEECHAT_RC_OK @@ -121,8 +121,7 @@ def config_server_buffer_cb(data, option): @utf8_decode def config_log_level_cb(data, option): change_log_level( - G.CONFIG.network.debug_category, - G.CONFIG.network.debug_level + G.CONFIG.network.debug_category, G.CONFIG.network.debug_level ) return 1 @@ -132,8 +131,7 @@ def config_log_category_cb(data, option): change_log_level(G.CONFIG.debug_category, logbook.ERROR) G.CONFIG.debug_category = G.CONFIG.network.debug_category change_log_level( - G.CONFIG.network.debug_category, - G.CONFIG.network.debug_level + G.CONFIG.network.debug_category, G.CONFIG.network.debug_level ) return 1 @@ -141,11 +139,11 @@ def config_log_category_cb(data, option): def level_to_logbook(value): if value == 0: return logbook.ERROR - elif value == 1: + if value == 1: return logbook.WARNING - elif value == 2: + if value == 2: return logbook.INFO - elif value == 3: + if value == 3: return logbook.DEBUG return logbook.ERROR @@ -154,13 +152,13 @@ def level_to_logbook(value): def logbook_category(value): if value == 0: return "all" - elif value == 1: + if value == 1: return "http" - elif value == 2: + if value == 2: return "client" - elif value == 3: + if value == 3: return "events" - elif value == 4: + if value == 4: return "responses" return "all" @@ -169,9 +167,7 @@ def logbook_category(value): class WeechatConfig(object): def __init__(self, sections): self._ptr = W.config_new( - SCRIPT_NAME, - SCRIPT_NAME + "_config_reload_cb", - "" + SCRIPT_NAME, SCRIPT_NAME + "_config_reload_cb", "" ) for section in sections: @@ -180,8 +176,11 @@ class WeechatConfig(object): setattr(self, name, section_class(name, self._ptr, options)) def free(self): - for section in [getattr(self, a) for a in dir(self) if - isinstance(getattr(self, a), ConfigSection)]: + for section in [ + getattr(self, a) + for a in dir(self) + if isinstance(getattr(self, a), ConfigSection) + ]: section.free() W.config_free(self._ptr) @@ -190,9 +189,9 @@ class WeechatConfig(object): return_code = W.config_read(self._ptr) if return_code == W.WEECHAT_CONFIG_READ_OK: return True - elif return_code == W.WEECHAT_CONFIG_READ_MEMORY_ERROR: + if return_code == W.WEECHAT_CONFIG_READ_MEMORY_ERROR: return False - elif return_code == W.WEECHAT_CONFIG_READ_FILE_NOT_FOUND: + if return_code == W.WEECHAT_CONFIG_READ_FILE_NOT_FOUND: return True return False @@ -201,8 +200,9 @@ class ConfigSection(object): @classmethod def build(cls, name, options): def constructor(self, name, config_ptr, options): - self._ptr = W.config_new_section(config_ptr, name, 0, 0, "", "", - "", "", "", "", "", "", "", "") + self._ptr = W.config_new_section( + config_ptr, name, 0, 0, "", "", "", "", "", "", "", "", "", "" + ) self._config_ptr = config_ptr self._option_ptrs = {} @@ -211,18 +211,13 @@ class ConfigSection(object): attributes = { option.name: cls.option_property( - option.name, - option.type, - cast_func=option.cast_func - ) for option in options + option.name, option.type, cast_func=option.cast_func + ) + for option in options } attributes["__init__"] = constructor - section_class = type( - name.title() + "Section", - (cls,), - attributes - ) + section_class = type(name.title() + "Section", (cls,), attributes) return section_class def free(self): @@ -232,10 +227,24 @@ class ConfigSection(object): def _add_option(self, option): cb = option.change_callback.__name__ if option.change_callback else "" option_ptr = W.config_new_option( - self._config_ptr, self._ptr, option.name, option.type, - option.description, option.string_values, option.min, - option.max, option.value, option.value, 0, "", "", - cb, "", "", "") + self._config_ptr, + self._ptr, + option.name, + option.type, + option.description, + option.string_values, + option.min, + option.max, + option.value, + option.value, + 0, + "", + "", + cb, + "", + "", + "", + ) self._option_ptrs[option.name] = option_ptr @@ -249,25 +258,21 @@ class ConfigSection(object): def str_evaluate_getter(self): return W.string_eval_expression( - W.config_string(self._option_ptrs[name]), - {}, - {}, - {} + W.config_string(self._option_ptrs[name]), {}, {}, {} ) def int_getter(self): if cast_func: return cast_func(W.config_integer(self._option_ptrs[name])) - else: - return W.config_integer(self._option_ptrs[name]) + return W.config_integer(self._option_ptrs[name]) - if option_type == "string" or option_type == "color": + if option_type in ("string", "color"): if evaluate: return property(str_evaluate_getter) return property(str_getter) - elif option_type == "boolean": + if option_type == "boolean": return property(bool_getter) - elif option_type == "integer": + if option_type == "integer": return property(int_getter) @@ -276,45 +281,111 @@ class MatrixConfig(WeechatConfig): self.debug_buffer = "" self.debug_category = "all" + self.page_up_hook = None look_options = [ - Option("redactions", "integer", "strikethrough|notice|delete", 0, - 0, "strikethrough", - ("Only notice redactions, strike through or delete " - "redacted messages"), RedactType), - Option("server_buffer", "integer", - "merge_with_core|merge_without_core|independent", 0, 0, - "merge_with_core", "Merge server buffers", ServerBufferType, - config_server_buffer_cb) + Option( + "redactions", + "integer", + "strikethrough|notice|delete", + 0, + 0, + "strikethrough", + ( + "Only notice redactions, strike through or delete " + "redacted messages" + ), + RedactType, + ), + Option( + "server_buffer", + "integer", + "merge_with_core|merge_without_core|independent", + 0, + 0, + "merge_with_core", + "Merge server buffers", + ServerBufferType, + config_server_buffer_cb, + ), ] network_options = [ - Option("max_initial_sync_events", "integer", "", 1, 10000, "30", - ("How many events to fetch during the initial sync")), - Option("max_backlog_sync_events", "integer", "", 1, 100, "10", - ("How many events to fetch during backlog fetching")), - Option("fetch_backlog_on_pgup", "boolean", "", 0, 0, "on", - ("Fetch messages in the backlog on a window page up event") - ), - Option("debug_level", "integer", "error|warn|info|debug", 0, 0, - "error", "Enable network protocol debugging.", - level_to_logbook, config_log_level_cb), - Option("debug_category", "integer", - "all|http|client|events|responses", - 0, 0, "all", "Debugging category", logbook_category), - Option("debug_buffer", "boolean", "", 0, 0, "off", - ("Use a separate buffer for debug logs.")), + Option( + "max_initial_sync_events", + "integer", + "", + 1, + 10000, + "30", + ("How many events to fetch during the initial sync"), + ), + Option( + "max_backlog_sync_events", + "integer", + "", + 1, + 100, + "10", + ("How many events to fetch during backlog fetching"), + ), + Option( + "fetch_backlog_on_pgup", + "boolean", + "", + 0, + 0, + "on", + ("Fetch messages in the backlog on a window page up event"), + ), + Option( + "debug_level", + "integer", + "error|warn|info|debug", + 0, + 0, + "error", + "Enable network protocol debugging.", + level_to_logbook, + config_log_level_cb, + ), + Option( + "debug_category", + "integer", + "all|http|client|events|responses", + 0, + 0, + "all", + "Debugging category", + logbook_category, + ), + Option( + "debug_buffer", + "boolean", + "", + 0, + 0, + "off", + ("Use a separate buffer for debug logs."), + ), ] color_options = [ - Option("quote", "color", "", 0, 0, "lightgreen", - ("Color for matrix style blockquotes")) + Option( + "quote", + "color", + "", + 0, + 0, + "lightgreen", + ("Color for matrix style blockquotes"), + ) ] sections = [ ("network", network_options), ("look", look_options), - ("color", color_options) + ("color", color_options), ] super().__init__(sections) @@ -322,10 +393,23 @@ class MatrixConfig(WeechatConfig): # The server section is essentially a section with subsections and no # options, handle that case independently. W.config_new_section( - self._ptr, "server", 0, 0, "matrix_config_server_read_cb", "", - "matrix_config_server_write_cb", "", "", "", "", "", "", "") + self._ptr, + "server", + 0, + 0, + "matrix_config_server_read_cb", + "", + "matrix_config_server_write_cb", + "", + "", + "", + "", + "", + "", + "", + ) def free(self): - section_ptr = W.config_search_section(self._ptr, 'server') + section_ptr = W.config_search_section(self._ptr, "server") W.config_section_free(section_ptr) super().free() diff --git a/matrix/globals.py b/matrix/globals.py index db3f7d4..87440ba 100644 --- a/matrix/globals.py +++ b/matrix/globals.py @@ -18,13 +18,19 @@ from __future__ import unicode_literals import sys -from matrix.utf import WeechatWrapper +from .utf import WeechatWrapper + +if False: + from typing import Dict + try: import weechat + W = weechat if sys.hexversion >= 0x3000000 else WeechatWrapper(weechat) except ImportError: import matrix._weechat as weechat + W = weechat SERVERS = dict() # type: Dict[str, MatrixServer] diff --git a/matrix/server.py b/matrix/server.py index ba7a215..1f49375 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -17,30 +17,28 @@ from __future__ import unicode_literals import os -import ssl -import socket -import time import pprint - -from collections import deque, defaultdict +import socket +import ssl +import time +from collections import defaultdict, deque from nio import ( HttpClient, + LocalProtocolError, LoginResponse, - SyncRepsponse, RoomSendResponse, + SyncRepsponse, TransportResponse, TransportType, - LocalProtocolError ) -from matrix.utils import (key_from_value, server_buffer_prnt, - create_server_buffer) -from matrix.utf import utf8_decode from . import globals as G -from matrix.globals import W, SERVERS, SCRIPT_NAME -from .buffer import RoomBuffer, OwnMessage, OwnAction -from .config import Option, ServerBufferType, ConfigSection +from .buffer import OwnAction, OwnMessage, RoomBuffer +from .config import ConfigSection, Option, ServerBufferType +from .globals import SCRIPT_NAME, SERVERS, W +from .utf import utf8_decode +from .utils import create_server_buffer, key_from_value, server_buffer_prnt try: FileNotFoundError @@ -56,39 +54,101 @@ class ServerConfig(ConfigSection): self._option_ptrs = {} options = [ - Option('autoconnect', 'boolean', '', 0, 0, 'off', - ("automatically connect to the matrix server when weechat " - "is starting")), - Option('address', 'string', '', 0, 0, '', - "Hostname or IP address for the server"), - Option('port', 'integer', '', 0, 65535, '443', - "Port for the server"), - Option('proxy', 'string', '', 0, 0, '', - ("Name of weechat proxy to use (see /help proxy)")), - Option('ssl_verify', 'boolean', '', 0, 0, 'on', - ("Check that the SSL connection is fully trusted")), - Option('username', 'string', '', 0, 0, '', - "Username to use on server"), Option( - 'password', 'string', '', 0, 0, '', - ("Password for server (note: content is evaluated, see /help " - "eval)")), - Option('device_name', 'string', '', 0, 0, 'Weechat Matrix', - "Device name to use while logging in to the matrix server"), + "autoconnect", + "boolean", + "", + 0, + 0, + "off", + ( + "automatically connect to the matrix server when weechat " + "is starting" + ), + ), + Option( + "address", + "string", + "", + 0, + 0, + "", + "Hostname or IP address for the server", + ), + Option( + "port", "integer", "", 0, 65535, "443", "Port for the server" + ), + Option( + "proxy", + "string", + "", + 0, + 0, + "", + ("Name of weechat proxy to use (see /help proxy)"), + ), + Option( + "ssl_verify", + "boolean", + "", + 0, + 0, + "on", + ("Check that the SSL connection is fully trusted"), + ), + Option( + "username", "string", "", 0, 0, "", "Username to use on server" + ), + Option( + "password", + "string", + "", + 0, + 0, + "", + ( + "Password for server (note: content is evaluated, see " + "/help eval)" + ), + ), + Option( + "device_name", + "string", + "", + 0, + 0, + "Weechat Matrix", + "Device name to use while logging in to the matrix server", + ), ] - section = W.config_search_section(config_ptr, 'server') + section = W.config_search_section(config_ptr, "server") self._ptr = section for option in options: option_name = "{server}.{option}".format( - server=self._server_name, option=option.name) + server=self._server_name, option=option.name + ) self._option_ptrs[option.name] = W.config_new_option( - config_ptr, section, option_name, option.type, - option.description, option.string_values, option.min, - option.max, option.value, option.value, 0, "", "", - "matrix_config_server_change_cb", self._server_name, "", "") + config_ptr, + section, + option_name, + option.type, + option.description, + option.string_values, + option.min, + option.max, + option.value, + option.value, + 0, + "", + "", + "matrix_config_server_change_cb", + self._server_name, + "", + "", + ) autoconnect = ConfigSection.option_property("autoconnect", "boolean") address = ConfigSection.option_property("address", "string") @@ -98,9 +158,7 @@ class ServerConfig(ConfigSection): username = ConfigSection.option_property("username", "string") device_name = ConfigSection.option_property("device_name", "string") password = ConfigSection.option_property( - "password", - "string", - evaluate=True + "password", "string", evaluate=True ) def free(self): @@ -169,12 +227,13 @@ class MatrixServer(object): def _create_session_dir(self): path = os.path.join("matrix", self.name) if not W.mkdir_home(path, 0o700): - message = ("{prefix}matrix: Error creating server session " - "directory").format(prefix=W.prefix("error")) + message = ( + "{prefix}matrix: Error creating server session " "directory" + ).format(prefix=W.prefix("error")) W.prnt("", message) def get_session_path(self): - home_dir = W.info_get('weechat_dir', '') + home_dir = W.info_get("weechat_dir", "") return os.path.join(home_dir, "matrix", self.name) def _load_device_id(self): @@ -184,8 +243,8 @@ class MatrixServer(object): if not os.path.isfile(path): return - with open(path, 'r') as f: - device_id = f.readline().rstrip() + with open(path, "r") as device_file: + device_id = device_file.readline().rstrip() if device_id: self.device_id = device_id @@ -193,11 +252,11 @@ class MatrixServer(object): file_name = "{}{}".format(self.config.username, ".device_id") path = os.path.join(self.get_session_path(), file_name) - with open(path, 'w') as f: - f.write(self.device_id) + with open(path, "w") as device_file: + device_file.write(self.device_id) def _change_client(self): - host = ':'.join([self.config.address, str(self.config.port)]) + host = ":".join([self.config.address, str(self.config.port)]) self.client = HttpClient(host, self.config.username, self.device_id) def update_option(self, option, option_name): @@ -255,14 +314,17 @@ class MatrixServer(object): strerr = error.strerror if error.strerror else "Unknown reason" strerr = errno + strerr - error_message = ("{prefix}Error while writing to " - "socket: {error}").format( - prefix=W.prefix("network"), error=strerr) + error_message = ( + "{prefix}Error while writing to " "socket: {error}" + ).format(prefix=W.prefix("network"), error=strerr) server_buffer_prnt(self, error_message) server_buffer_prnt( - self, ("{prefix}matrix: disconnecting from server..." - ).format(prefix=W.prefix("network"))) + self, + ("{prefix}matrix: disconnecting from server...").format( + prefix=W.prefix("network") + ), + ) self.disconnect() return False @@ -273,10 +335,15 @@ class MatrixServer(object): server_buffer_prnt( self, "{prefix}matrix: Error while writing to socket".format( - prefix=W.prefix("network"))) + prefix=W.prefix("network") + ), + ) server_buffer_prnt( - self, ("{prefix}matrix: disconnecting from server..." - ).format(prefix=W.prefix("network"))) + self, + ("{prefix}matrix: disconnecting from server...").format( + prefix=W.prefix("network") + ), + ) self.disconnect() return False @@ -286,7 +353,6 @@ class MatrixServer(object): return True def _abort_send(self): - self.current_message = None self.send_buffer = "" def _finalize_send(self): @@ -316,8 +382,9 @@ class MatrixServer(object): return True def reconnect(self): - message = ("{prefix}matrix: reconnecting to server..." - ).format(prefix=W.prefix("network")) + message = ("{prefix}matrix: reconnecting to server...").format( + prefix=W.prefix("network") + ) server_buffer_prnt(self, message) @@ -336,9 +403,9 @@ class MatrixServer(object): else: self.reconnect_delay = 10 - message = ("{prefix}matrix: reconnecting to server in {t} " - "seconds").format( - prefix=W.prefix("network"), t=self.reconnect_delay) + message = ( + "{prefix}matrix: reconnecting to server in {t} " "seconds" + ).format(prefix=W.prefix("network"), t=self.reconnect_delay) server_buffer_prnt(self, message) @@ -364,7 +431,6 @@ class MatrixServer(object): self.access_token = "" self.send_buffer = b"" - self.current_message = None self.transport_type = None try: @@ -378,8 +444,9 @@ class MatrixServer(object): self.reconnect_time = None if self.server_buffer: - message = ("{prefix}matrix: disconnected from server" - ).format(prefix=W.prefix("network")) + message = ("{prefix}matrix: disconnected from server").format( + prefix=W.prefix("network") + ) server_buffer_prnt(self, message) if reconnect: @@ -390,13 +457,15 @@ class MatrixServer(object): if not self.config.address or not self.config.port: W.prnt("", self.config.address) message = "{prefix}Server address or port not set".format( - prefix=W.prefix("error")) + prefix=W.prefix("error") + ) W.prnt("", message) return False if not self.config.username or not self.config.password: message = "{prefix}User or password not set".format( - prefix=W.prefix("error")) + prefix=W.prefix("error") + ) W.prnt("", message) return False @@ -407,54 +476,59 @@ class MatrixServer(object): create_server_buffer(self) if not self.timer_hook: - self.timer_hook = W.hook_timer(1 * 1000, 0, 0, "matrix_timer_cb", - self.name) + self.timer_hook = W.hook_timer( + 1 * 1000, 0, 0, "matrix_timer_cb", self.name + ) ssl_message = " (SSL)" if self.ssl_context.check_hostname else "" - message = ("{prefix}matrix: Connecting to " - "{server}:{port}{ssl}...").format( - prefix=W.prefix("network"), - server=self.config.address, - port=self.config.port, - ssl=ssl_message) + message = ( + "{prefix}matrix: Connecting to " "{server}:{port}{ssl}..." + ).format( + prefix=W.prefix("network"), + server=self.config.address, + port=self.config.port, + ssl=ssl_message, + ) W.prnt(self.server_buffer, message) - W.hook_connect(self.config.proxy, - self.config.address, self.config.port, - 1, 0, "", "connect_cb", - self.name) + W.hook_connect( + self.config.proxy, + self.config.address, + self.config.port, + 1, + 0, + "", + "connect_cb", + self.name, + ) return True def schedule_sync(self): self.sync_time = time.time() - def sync(self, timeout=None, filter=None): + def sync(self, timeout=None, sync_filter=None): # type: (Optional[int], Optional[Dict[Any, Any]]) -> None self.sync_time = None - _, request = self.client.sync(timeout, filter) + _, request = self.client.sync(timeout, sync_filter) self.send_or_queue(request) def login(self): # type: () -> None if self.client.logged_in: - msg = ("{prefix}{script_name}: Already logged in, " - "syncing...").format( - prefix=W.prefix("network"), - script_name=SCRIPT_NAME - ) + msg = ( + "{prefix}{script_name}: Already logged in, " "syncing..." + ).format(prefix=W.prefix("network"), script_name=SCRIPT_NAME) W.prnt(self.server_buffer, msg) - timeout = (0 if self.transport_type == TransportType.HTTP - else 30000) + timeout = 0 if self.transport_type == TransportType.HTTP else 30000 sync_filter = {"room": {"timeline": {"limit": 5000}}} self.sync(timeout, sync_filter) return _, request = self.client.login( - self.config.password, - self.config.device_name + self.config.password, self.config.device_name ) self.send_or_queue(request) @@ -469,30 +543,24 @@ class MatrixServer(object): return _, request = self.client.room_put_state( - room_buffer.room.room_id, - event_type, - body + room_buffer.room.room_id, event_type, body ) self.send_or_queue(request) def room_send_redaction(self, room_buffer, event_id, reason=None): _, request = self.client.room_redact( - room_buffer.room.room_id, - event_id, - reason) + room_buffer.room.room_id, event_id, reason + ) self.send_or_queue(request) def room_kick(self, room_buffer, user_id, reason=None): _, request = self.client.room_kick( - room_buffer.room.room_id, - user_id, - reason) + room_buffer.room.room_id, user_id, reason + ) self.send_or_queue(request) def room_invite(self, room_buffer, user_id): - _, request = self.client.room_invite( - room_buffer.room.room_id, - user_id) + _, request = self.client.room_invite(room_buffer.room.room_id, user_id) self.send_or_queue(request) def room_join(self, room_id): @@ -514,11 +582,7 @@ class MatrixServer(object): message_class = OwnMessage own_message = message_class( - self.user_id, - 0, - "", - room_buffer.room.room_id, - formatted + self.user_id, 0, "", room_buffer.room.room_id, formatted ) body = {"msgtype": msgtype, "body": formatted.to_plain()} @@ -528,20 +592,22 @@ class MatrixServer(object): body["formatted_body"] = formatted.to_html() uuid, request = self.client.room_send( - room_buffer.room.room_id, - "m.room.message", - body + room_buffer.room.room_id, "m.room.message", body ) self.own_message_queue[uuid] = own_message self.send_or_queue(request) def _print_message_error(self, message): - server_buffer_prnt(self, - ("{prefix}Unhandled {status_code} error, please " - "inform the developers about this.").format( - prefix=W.prefix("error"), - status_code=message.response.status)) + server_buffer_prnt( + self, + ( + "{prefix}Unhandled {status_code} error, please " + "inform the developers about this." + ).format( + prefix=W.prefix("error"), status_code=message.response.status + ), + ) server_buffer_prnt(self, pprint.pformat(message.__class__.__name__)) server_buffer_prnt(self, pprint.pformat(message.request.payload)) @@ -555,21 +621,13 @@ class MatrixServer(object): if isinstance(message, OwnAction): room_buffer.self_action(message) return - elif isinstance(message, OwnMessage): + if isinstance(message, OwnMessage): room_buffer.self_message(message) return - raise NotImplementedError("Unsupported message of type {}".format( - type(message))) - - def _handle_erorr_response(self, response): - message = ("{prefix}matrix: {error}").format( - prefix=W.prefix("error"), error=self.error_message) - - W.prnt(self.server.server_buffer, message) - - if self.fatal: - self.server.disconnect(reconnect=False) + raise NotImplementedError( + "Unsupported message of type {}".format(type(message)) + ) def _handle_login(self, response): self.access_token = response.access_token @@ -579,7 +637,8 @@ class MatrixServer(object): self.save_device_id() message = "{prefix}matrix: Logged in as {user}".format( - prefix=W.prefix("network"), user=self.user_id) + prefix=W.prefix("network"), user=self.user_id + ) W.prnt(self.server_buffer, message) @@ -590,12 +649,10 @@ class MatrixServer(object): sync_filter = { "room": { - "timeline": { - "limit": G.CONFIG.network.max_initial_sync_events - } + "timeline": {"limit": G.CONFIG.network.max_initial_sync_events} } } - self.sync(timeout=0, filter=sync_filter) + self.sync(timeout=0, sync_filter=sync_filter) def _handle_room_info(self, response): for room_id, info in response.rooms.invite.items(): @@ -604,21 +661,23 @@ class MatrixServer(object): if room: if room.inviter: inviter_msg = " by {}{}".format( - W.color("chat_nick_other"), - room.inviter) + W.color("chat_nick_other"), room.inviter + ) else: inviter_msg = "" - self.info("You have been invited to {} {}({}{}{}){}" - "{}".format( - room.display_name(), - W.color("chat_delimiters"), - W.color("chat_channel"), - room_id, - W.color("chat_delimiters"), - W.color("reset"), - inviter_msg - )) + self.info( + "You have been invited to {} {}({}{}{}){}" + "{}".format( + room.display_name(), + W.color("chat_delimiters"), + W.color("chat_channel"), + room_id, + W.color("chat_delimiters"), + W.color("reset"), + inviter_msg, + ) + ) else: self.info("You have been invited to {}.".format(room_id)) @@ -647,13 +706,17 @@ class MatrixServer(object): self.schedule_sync() def handle_transport_response(self, response): - self.error(("Error with response of type type: {}, " - "error code {}").format( - response.request_info.type, response.status_code)) + self.error( + ("Error with response of type type: {}, " "error code {}").format( + response.request_info.type, response.status_code + ) + ) # TODO better error handling. - if (response.request_info.type == "sync" or - response.request_info.type == "login"): + if ( + response.request_info.type == "sync" + or response.request_info.type == "login" + ): self.disconnect() def handle_response(self, response): @@ -681,8 +744,6 @@ class MatrixServer(object): elif isinstance(response, RoomSendResponse): self.handle_own_messages(response) - return - def create_room_buffer(self, room_id): room = self.client.rooms[room_id] buf = RoomBuffer(room, self.name) @@ -722,8 +783,7 @@ class MatrixServer(object): break if first: num = W.buffer_get_integer( - W.buffer_search_main(), - "number" + W.buffer_search_main(), "number" ) W.buffer_unmerge(buf, num + 1) if buf is not first: @@ -734,13 +794,14 @@ class MatrixServer(object): @utf8_decode -def matrix_config_server_read_cb(data, config_file, section, option_name, - value): +def matrix_config_server_read_cb( + data, config_file, section, option_name, value +): return_code = W.WEECHAT_CONFIG_OPTION_SET_ERROR if option_name: - server_name, option = option_name.rsplit('.', 1) + server_name, option = option_name.rsplit(".", 1) server = None if server_name in SERVERS: @@ -752,9 +813,7 @@ def matrix_config_server_read_cb(data, config_file, section, option_name, # Ignore invalid options if option in server.config._option_ptrs: return_code = W.config_option_set( - server.config._option_ptrs[option], - value, - 1 + server.config._option_ptrs[option], value, 1 ) # TODO print out error message in case of erroneous return_code @@ -796,8 +855,11 @@ def matrix_timer_cb(server_name, remaining_calls): current_time = time.time() - if ((not server.connected) and server.reconnect_time and - current_time >= (server.reconnect_time + server.reconnect_delay)): + if ( + (not server.connected) + and server.reconnect_time + and current_time >= (server.reconnect_time + server.reconnect_delay) + ): server.reconnect() return W.WEECHAT_RC_OK @@ -844,7 +906,7 @@ def matrix_timer_cb(server_name, remaining_calls): def create_default_server(config_file): - server = MatrixServer('matrix_org', config_file._ptr) + server = MatrixServer("matrix_org", config_file._ptr) SERVERS[server.name] = server option = W.config_get(SCRIPT_NAME + ".server." + server.name + ".address") diff --git a/matrix/utf.py b/matrix/utf.py index 6250763..320cb58 100644 --- a/matrix/utf.py +++ b/matrix/utf.py @@ -28,7 +28,7 @@ import sys # pylint: disable=redefined-builtin from builtins import bytes, str -from collections import Mapping, Iterable +from collections import Iterable, Mapping from functools import wraps # These functions were written by Trygve Aaberge for wee-slack and are under a @@ -39,13 +39,11 @@ from functools import wraps class WeechatWrapper(object): - def __init__(self, wrapped_class): self.wrapped_class = wrapped_class # Helper method used to encode/decode method calls. def wrap_for_utf8(self, method): - def hooked(*args, **kwargs): result = method(*encode_to_utf8(args), **encode_to_utf8(kwargs)) # Prevent wrapped_class from becoming unwrapped @@ -69,7 +67,8 @@ class WeechatWrapper(object): def prnt_date_tags(self, buffer, date, tags, message): message = message.replace("\n", "\n \t") return self.wrap_for_utf8(self.wrapped_class.prnt_date_tags)( - buffer, date, tags, message) + buffer, date, tags, message + ) def utf8_decode(function): @@ -92,7 +91,7 @@ def utf8_decode(function): def decode_from_utf8(data): if isinstance(data, bytes): - return data.decode('utf-8') + return data.decode("utf-8") if isinstance(data, str): return data elif isinstance(data, Mapping): @@ -104,7 +103,7 @@ def decode_from_utf8(data): def encode_to_utf8(data): if isinstance(data, str): - return data.encode('utf-8') + return data.encode("utf-8") if isinstance(data, bytes): return data elif isinstance(data, Mapping): diff --git a/matrix/utils.py b/matrix/utils.py index 7172b4e..b59e472 100644 --- a/matrix/utils.py +++ b/matrix/utils.py @@ -15,18 +15,10 @@ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. from __future__ import unicode_literals -from builtins import str import time -import math -from matrix import globals as G -from matrix.globals import W, SERVERS - -try: - from urlparse import urlparse -except ImportError: - from urllib.parse import urlparse +from .globals import W def key_from_value(dictionary, value): @@ -45,11 +37,13 @@ def server_buffer_prnt(server, string): def tags_from_line_data(line_data): # type: (weechat.hdata) -> List[str] tags_count = W.hdata_get_var_array_size( - W.hdata_get('line_data'), line_data, 'tags_array') + W.hdata_get("line_data"), line_data, "tags_array" + ) tags = [ W.hdata_string( - W.hdata_get('line_data'), line_data, '%d|tags_array' % i) + W.hdata_get("line_data"), line_data, "%d|tags_array" % i + ) for i in range(tags_count) ] @@ -59,16 +53,15 @@ def tags_from_line_data(line_data): def create_server_buffer(server): # type: (MatrixServer) -> None buffer_name = "server.{}".format(server.name) - server.server_buffer = W.buffer_new(buffer_name, "server_buffer_cb", - server.name, "", "") + server.server_buffer = W.buffer_new( + buffer_name, "server_buffer_cb", server.name, "", "" + ) server_buffer_set_title(server) W.buffer_set(server.server_buffer, "short_name", server.name) - W.buffer_set(server.server_buffer, "localvar_set_type", 'server') + W.buffer_set(server.server_buffer, "localvar_set_type", "server") W.buffer_set( - server.server_buffer, - "localvar_set_nick", - server.config.username + server.server_buffer, "localvar_set_nick", server.config.username ) W.buffer_set(server.server_buffer, "localvar_set_server", server.name) W.buffer_set(server.server_buffer, "localvar_set_channel", server.name) @@ -84,18 +77,12 @@ def server_buffer_set_title(server): ip_string = "" title = ("Matrix: {address}:{port}{ip}").format( - address=server.config.address, port=server.config.port, ip=ip_string) + address=server.config.address, port=server.config.port, ip=ip_string + ) W.buffer_set(server.server_buffer, "title", title) -def color_for_tags(color): - if color == "weechat.color.chat_nick_self": - option = W.config_get(color) - return W.config_string(option) - return color - - def server_ts_to_weechat(timestamp): # type: (float) -> int date = int(timestamp / 1000) @@ -112,241 +99,5 @@ def shorten_sender(sender): return strip_matrix_server(sender)[1:] -def sender_to_prefix_and_color(room, sender): - if sender in room.users: - user = room.users[sender] - prefix = user.prefix - prefix_color = get_prefix_color(prefix) - return prefix, prefix_color - - return None, None - - -def sender_to_nick_and_color(room, sender): - nick = sender - nick_color_name = "default" - - if sender in room.users: - user = room.users[sender] - nick = (user.display_name if user.display_name else user.name) - nick_color_name = user.nick_color - else: - nick = sender - nick_color_name = W.info_get("nick_color_name", nick) - - return (nick, nick_color_name) - - -def tags_for_message(message_type): - default_tags = { - "message": ["matrix_message", "notify_message", "log1"], - "backlog": - ["matrix_message", "notify_message", "no_log", "no_highlight"] - } - - return default_tags[message_type] - - -def add_event_tags(event_id, nick, color=None, tags=[]): - tags.append("nick_{nick}".format(nick=nick)) - - if color: - tags.append("prefix_nick_{color}".format(color=color_for_tags(color))) - - tags.append("matrix_id_{event_id}".format(event_id=event_id)) - - return tags - - -def sanitize_token(string): - # type: (str) -> str - string = sanitize_string(string) - - if len(string) > 512: - raise ValueError - - if string == "": - raise ValueError - - return string - - -def sanitize_string(string): - # type: (str) -> str - if not isinstance(string, str): - raise TypeError - - # string keys can have empty string values sometimes (e.g. room names that - # got deleted) - if string == "": - return None - - remap = { - ord('\b'): None, - ord('\f'): None, - ord('\n'): None, - ord('\r'): None, - ord('\t'): None, - ord('\0'): None - } - - return string.translate(remap) - - -def sanitize_id(string): - # type: (str) -> str - string = sanitize_string(string) - - if len(string) > 128: - raise ValueError - - if string == "": - raise ValueError - - return string - - -def sanitize_int(number, minimum=None, maximum=None): - # type: (int, int, int) -> int - if not isinstance(number, int): - raise TypeError - - if math.isnan(number): - raise ValueError - - if math.isinf(number): - raise ValueError - - if minimum: - if number < minimum: - raise ValueError - - if maximum: - if number > maximum: - raise ValueError - - return number - - -def sanitize_ts(timestamp): - # type: (int) -> int - return sanitize_int(timestamp, 0) - - -def sanitize_power_level(level): - # type: (int) -> int - return sanitize_int(level, 0, 100) - - -def sanitize_text(string): - # type: (str) -> str - if not isinstance(string, str): - raise TypeError - - # yapf: disable - remap = { - ord('\b'): None, - ord('\f'): None, - ord('\r'): None, - ord('\0'): None - } - # yapf: enable - - return string.translate(remap) - - -def add_user_to_nicklist(buf, user_id, user): - group_name = "999|..." - - if user.power_level >= 100: - group_name = "000|o" - elif user.power_level >= 50: - group_name = "001|h" - elif user.power_level > 0: - group_name = "002|v" - - group = W.nicklist_search_group(buf, "", group_name) - prefix = user.prefix if user.prefix else " " - - # TODO make it configurable so we can use a display name or user_id here - W.nicklist_add_nick(buf, group, user_id, user.nick_color, prefix, - get_prefix_color(user.prefix), 1) - - -def get_prefix_for_level(level): - # type: (int) -> str - if level >= 100: - return "&" - elif level >= 50: - return "@" - elif level > 0: - return "+" - return "" - - -# TODO make this configurable -def get_prefix_color(prefix): - # type: (str) -> str - if prefix == "&": - return "lightgreen" - elif prefix == "@": - return "lightgreen" - elif prefix == "+": - return "yellow" - return "" - - def string_strikethrough(string): return "".join(["{}\u0336".format(c) for c in string]) - - -def line_pointer_and_tags_from_event(buff, event_id): - # type: (str, str) -> str - own_lines = W.hdata_pointer(W.hdata_get('buffer'), buff, 'own_lines') - - if own_lines: - hdata_line = W.hdata_get('line') - - line_pointer = W.hdata_pointer( - W.hdata_get('lines'), own_lines, 'last_line') - - while line_pointer: - data_pointer = W.hdata_pointer(hdata_line, line_pointer, 'data') - - if data_pointer: - tags = tags_from_line_data(data_pointer) - - message_id = event_id_from_tags(tags) - - if event_id == message_id: - return data_pointer, tags - - line_pointer = W.hdata_move(hdata_line, line_pointer, -1) - - return None, [] - - -def event_id_from_tags(tags): - # type: (List[str]) -> str - for tag in tags: - if tag.startswith("matrix_id"): - return tag[10:] - - return "" - - -def mxc_to_http(mxc): - # type: (str) -> str - url = urlparse(mxc) - - if url.scheme != "mxc": - return None - - if not url.netloc or not url.path: - return None - - return "https://{}/_matrix/media/r0/download/{}{}".format( - url.netloc, - url.netloc, - url.path - )