matrix: Style fixes and cleanup.
This commit is contained in:
parent
f8a318fef2
commit
05a413f7cb
13 changed files with 1278 additions and 1278 deletions
|
@ -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
|
||||
|
|
97
main.py
97
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
420
matrix/buffer.py
420
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", [
|
||||
OwnMessage = NamedTuple(
|
||||
"OwnMessage",
|
||||
[
|
||||
("sender", str),
|
||||
("age", int),
|
||||
("event_id", str),
|
||||
("room_id", str),
|
||||
("formatted_message", Formatted)
|
||||
])
|
||||
("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(
|
||||
prefix_string = (
|
||||
""
|
||||
if not user.prefix
|
||||
else "{}{}{}".format(
|
||||
W.color(self._get_prefix_color(user.prefix)),
|
||||
user.prefix,
|
||||
W.color("reset")
|
||||
))
|
||||
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(
|
||||
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")
|
||||
W.color("reset"),
|
||||
)
|
||||
)
|
||||
|
||||
data = ("{prefix}\t{color}Notice"
|
||||
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"),
|
||||
": {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)
|
||||
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(
|
||||
nick_prefix = (
|
||||
""
|
||||
if not user.prefix
|
||||
else "{}{}{}".format(
|
||||
W.color(self._get_prefix_color(user.prefix)),
|
||||
user.prefix,
|
||||
W.color("reset")
|
||||
))
|
||||
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} "
|
||||
message = (
|
||||
"{prefix}{color}{author}{ncolor} "
|
||||
"{del_color}({host_color}{host}{del_color})"
|
||||
"{action_color} {message} "
|
||||
"{channel_color}{room}{ncolor}").format(
|
||||
"{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,33 +671,35 @@ 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 "
|
||||
data = (
|
||||
"{prefix}{nick} has changed "
|
||||
"the topic for {chan_color}{room}{ncolor} "
|
||||
"to \"{topic}\"").format(
|
||||
'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
|
||||
topic=topic,
|
||||
)
|
||||
|
||||
self.print_date_tags(data, date, tags)
|
||||
|
@ -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: "
|
||||
redaction_msg = (
|
||||
"{del_color}<{log_color}Message redacted by: "
|
||||
"{censor}{log_color}{reason}{del_color}>"
|
||||
"{ncolor}").format(
|
||||
"{ncolor}"
|
||||
).format(
|
||||
del_color=W.color("chat_delimiters"),
|
||||
ncolor=W.color("reset"),
|
||||
log_color=W.color("logger.color.backlog_line"),
|
||||
censor=censor,
|
||||
reason=reason)
|
||||
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(
|
||||
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)
|
||||
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 "
|
||||
message = (
|
||||
"This room is encrypted, encryption is "
|
||||
"currently unsuported. Message sending is disabled for "
|
||||
"this room.")
|
||||
"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 "
|
||||
message = (
|
||||
"This room is encrypted, encryption is "
|
||||
"currently unsuported. Message sending is disabled for "
|
||||
"this room.")
|
||||
"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(
|
||||
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)
|
||||
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])
|
||||
|
|
123
matrix/colors.py
123
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,7 +55,7 @@ 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):
|
||||
|
@ -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="<strong>", text=string, bold_off="</strong>")
|
||||
elif name == "italic" and value:
|
||||
bold_on="<strong>", text=string, bold_off="</strong>"
|
||||
)
|
||||
if name == "italic" and value:
|
||||
return "{italic_on}{text}{italic_off}".format(
|
||||
italic_on="<em>", text=string, italic_off="</em>")
|
||||
elif name == "underline" and value:
|
||||
italic_on="<em>", text=string, italic_off="</em>"
|
||||
)
|
||||
if name == "underline" and value:
|
||||
return "{underline_on}{text}{underline_off}".format(
|
||||
underline_on="<u>", text=string, underline_off="</u>")
|
||||
elif name == "strikethrough" and value:
|
||||
underline_on="<u>", text=string, underline_off="</u>"
|
||||
)
|
||||
if name == "strikethrough" and value:
|
||||
return "{strike_on}{text}{strike_off}".format(
|
||||
strike_on="<del>", text=string, strike_off="</del>")
|
||||
elif name == "quote" and value:
|
||||
strike_on="<del>", text=string, strike_off="</del>"
|
||||
)
|
||||
if name == "quote" and value:
|
||||
return "{quote_on}{text}{quote_off}".format(
|
||||
quote_on="<blockquote>",
|
||||
text=string,
|
||||
quote_off="</blockquote>")
|
||||
elif name == "fgcolor" and value:
|
||||
quote_off="</blockquote>",
|
||||
)
|
||||
if name == "fgcolor" and value:
|
||||
return "{color_on}{text}{color_off}".format(
|
||||
color_on="<font color={color}>".format(
|
||||
color=color_weechat_to_html(value)),
|
||||
color=color_weechat_to_html(value)
|
||||
),
|
||||
text=string,
|
||||
color_off="</font>")
|
||||
color_off="</font>",
|
||||
)
|
||||
|
||||
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,7 +979,6 @@ 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]
|
||||
|
||||
|
||||
|
@ -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:
|
||||
|
|
|
@ -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-name> <hostname>[:<port>] ||'
|
||||
'server delete|list|listfull <server-name> ||'
|
||||
'connect <server-name> ||'
|
||||
'disconnect <server-name> ||'
|
||||
'reconnect <server-name> ||'
|
||||
'help <matrix-command>'),
|
||||
(
|
||||
"server add <server-name> <hostname>[:<port>] ||"
|
||||
"server delete|list|listfull <server-name> ||"
|
||||
"connect <server-name> ||"
|
||||
"disconnect <server-name> ||"
|
||||
"reconnect <server-name> ||"
|
||||
"help <matrix-command>"
|
||||
),
|
||||
# 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
|
||||
('<message-number>[:"<message-part>"] [<reason>]'),
|
||||
# Description
|
||||
("message-number: number of message to redact (starting from 1 for\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"),
|
||||
" 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
|
||||
("[<topic>|-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
|
||||
("<user-id> [<reason>]"),
|
||||
# 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
|
||||
("<room-id>|<room-alias>"),
|
||||
# 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,9 +241,10 @@ 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()
|
||||
|
@ -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 "
|
||||
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 "
|
||||
server.error(
|
||||
'command "part" must be '
|
||||
"executed on a Matrix room buffer or a room "
|
||||
"name needs to be given")
|
||||
"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,7 +520,8 @@ def matrix_redact_command_cb(data, buffer, args):
|
|||
matches = re.match(r"(\d+)(:\".*\")? ?(.*)?", args)
|
||||
|
||||
if not matches:
|
||||
message = ("{prefix}matrix: Invalid command "
|
||||
message = (
|
||||
"{prefix}matrix: Invalid command "
|
||||
"arguments (see /help redact)"
|
||||
).format(prefix=W.prefix("error"))
|
||||
W.prnt("", message)
|
||||
|
@ -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,8 +544,9 @@ 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 "
|
||||
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)
|
||||
|
@ -522,8 +557,9 @@ 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)"
|
||||
message = (
|
||||
"{prefix}matrix: Too few arguments for command "
|
||||
'"/matrix help" (see /matrix help help)'
|
||||
).format(prefix=W.prefix("error"))
|
||||
W.prnt("", message)
|
||||
return
|
||||
|
@ -532,46 +568,56 @@ def matrix_command_help(args):
|
|||
message = ""
|
||||
|
||||
if command == "connect":
|
||||
message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
||||
message = (
|
||||
"{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
||||
"{ncolor}{cmd_color}/connect{ncolor} "
|
||||
"<server-name> [<server-name>...]"
|
||||
"\n\n"
|
||||
"connect to Matrix server(s)"
|
||||
"\n\n"
|
||||
"server-name: server to connect to"
|
||||
"(internal name)").format(
|
||||
"(internal name)"
|
||||
).format(
|
||||
delimiter_color=W.color("chat_delimiters"),
|
||||
cmd_color=W.color("chat_buffer"),
|
||||
ncolor=W.color("reset"))
|
||||
ncolor=W.color("reset"),
|
||||
)
|
||||
|
||||
elif command == "disconnect":
|
||||
message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
||||
message = (
|
||||
"{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
||||
"{ncolor}{cmd_color}/disconnect{ncolor} "
|
||||
"<server-name> [<server-name>...]"
|
||||
"\n\n"
|
||||
"disconnect from Matrix server(s)"
|
||||
"\n\n"
|
||||
"server-name: server to disconnect"
|
||||
"(internal name)").format(
|
||||
"(internal name)"
|
||||
).format(
|
||||
delimiter_color=W.color("chat_delimiters"),
|
||||
cmd_color=W.color("chat_buffer"),
|
||||
ncolor=W.color("reset"))
|
||||
ncolor=W.color("reset"),
|
||||
)
|
||||
|
||||
elif command == "reconnect":
|
||||
message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
||||
message = (
|
||||
"{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
||||
"{ncolor}{cmd_color}/reconnect{ncolor} "
|
||||
"<server-name> [<server-name>...]"
|
||||
"\n\n"
|
||||
"reconnect to Matrix server(s)"
|
||||
"\n\n"
|
||||
"server-name: server to reconnect"
|
||||
"(internal name)").format(
|
||||
"(internal name)"
|
||||
).format(
|
||||
delimiter_color=W.color("chat_delimiters"),
|
||||
cmd_color=W.color("chat_buffer"),
|
||||
ncolor=W.color("reset"))
|
||||
ncolor=W.color("reset"),
|
||||
)
|
||||
|
||||
elif command == "server":
|
||||
message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
||||
message = (
|
||||
"{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
||||
"{ncolor}{cmd_color}/server{ncolor} "
|
||||
"add <server-name> <hostname>[:<port>]"
|
||||
"\n "
|
||||
|
@ -592,28 +638,34 @@ def matrix_command_help(args):
|
|||
"Examples:"
|
||||
"\n /matrix server listfull"
|
||||
"\n /matrix server add matrix matrix.org:80"
|
||||
"\n /matrix server del matrix").format(
|
||||
"\n /matrix server del matrix"
|
||||
).format(
|
||||
delimiter_color=W.color("chat_delimiters"),
|
||||
cmd_color=W.color("chat_buffer"),
|
||||
ncolor=W.color("reset"))
|
||||
ncolor=W.color("reset"),
|
||||
)
|
||||
|
||||
elif command == "help":
|
||||
message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
||||
message = (
|
||||
"{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
||||
"{ncolor}{cmd_color}/help{ncolor} "
|
||||
"<matrix-command> [<matrix-command>...]"
|
||||
"\n\n"
|
||||
"display help about Matrix commands"
|
||||
"\n\n"
|
||||
"matrix-command: a Matrix command name"
|
||||
"(internal name)").format(
|
||||
"(internal name)"
|
||||
).format(
|
||||
delimiter_color=W.color("chat_delimiters"),
|
||||
cmd_color=W.color("chat_buffer"),
|
||||
ncolor=W.color("reset"))
|
||||
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}"
|
||||
message = (
|
||||
"Server: {server_color}{server}{delimiter_color}"
|
||||
" [{ncolor}{connected}{delimiter_color}]"
|
||||
"{ncolor}").format(
|
||||
"{ncolor}"
|
||||
).format(
|
||||
server_color=W.color("chat_server"),
|
||||
server=server.name,
|
||||
delimiter_color=W.color("chat_delimiters"),
|
||||
connected=connected,
|
||||
ncolor=W.color("reset"))
|
||||
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 "
|
||||
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(
|
||||
'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)
|
||||
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(
|
||||
message = (
|
||||
"matrix: server {color}{server}{ncolor} has been " "deleted"
|
||||
).format(
|
||||
server=server.name,
|
||||
color=W.color("chat_server"),
|
||||
ncolor=W.color("reset"))
|
||||
ncolor=W.color("reset"),
|
||||
)
|
||||
|
||||
del SERVERS[server.name]
|
||||
server = None
|
||||
|
@ -749,14 +809,16 @@ 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)"
|
||||
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(
|
||||
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"))
|
||||
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 "
|
||||
message = (
|
||||
"{prefix}Failed to set address for server "
|
||||
"{color}{server}{ncolor}, failed to add "
|
||||
"server.").format(
|
||||
"server."
|
||||
).format(
|
||||
prefix=W.prefix("error"),
|
||||
color=W.color("chat_server"),
|
||||
server=server.name,
|
||||
ncolor=W.color("reset"))
|
||||
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 "
|
||||
message = (
|
||||
"{prefix}Failed to set port for server "
|
||||
"{color}{server}{ncolor}, failed to add "
|
||||
"server.").format(
|
||||
"server."
|
||||
).format(
|
||||
prefix=W.prefix("error"),
|
||||
color=W.color("chat_server"),
|
||||
server=server.name,
|
||||
ncolor=W.color("reset"))
|
||||
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 "
|
||||
message = (
|
||||
"{prefix}Failed to set user for server "
|
||||
"{color}{server}{ncolor}, failed to add "
|
||||
"server.").format(
|
||||
"server."
|
||||
).format(
|
||||
prefix=W.prefix("error"),
|
||||
color=W.color("chat_server"),
|
||||
server=server.name,
|
||||
ncolor=W.color("reset"))
|
||||
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 "
|
||||
message = (
|
||||
"{prefix}Failed to set password for server "
|
||||
"{color}{server}{ncolor}, failed to add "
|
||||
"server.").format(
|
||||
"server."
|
||||
).format(
|
||||
prefix=W.prefix("error"),
|
||||
color=W.color("chat_server"),
|
||||
server=server.name,
|
||||
ncolor=W.color("reset"))
|
||||
ncolor=W.color("reset"),
|
||||
)
|
||||
W.prnt("", message)
|
||||
server = None
|
||||
return
|
||||
|
||||
message = ("matrix: server {color}{server}{ncolor} "
|
||||
"has been added").format(
|
||||
message = (
|
||||
"matrix: server {color}{server}{ncolor} " "has been added"
|
||||
).format(
|
||||
server=server.name,
|
||||
color=W.color("chat_server"),
|
||||
ncolor=W.color("reset"))
|
||||
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
|
||||
|
|
|
@ -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,36 +98,42 @@ 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
|
||||
|
||||
|
@ -126,7 +142,7 @@ def server_from_buffer(buffer):
|
|||
for server in SERVERS.values():
|
||||
if buffer in server.buffers.values():
|
||||
return server
|
||||
elif buffer == server.server_buffer:
|
||||
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",
|
||||
"",
|
||||
)
|
||||
|
|
264
matrix/config.py
264
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',
|
||||
class Option(
|
||||
namedtuple(
|
||||
"Option",
|
||||
[
|
||||
'name',
|
||||
'type',
|
||||
'string_values',
|
||||
'min',
|
||||
'max',
|
||||
'value',
|
||||
'description',
|
||||
'cast_func',
|
||||
'change_callback'
|
||||
]
|
||||
)):
|
||||
"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])
|
||||
|
||||
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(
|
||||
"max_initial_sync_events",
|
||||
"integer",
|
||||
"",
|
||||
1,
|
||||
10000,
|
||||
"30",
|
||||
("How many events to fetch during the initial sync"),
|
||||
),
|
||||
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",
|
||||
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.")),
|
||||
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()
|
||||
|
|
|
@ -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]
|
||||
|
|
366
matrix/server.py
366
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(
|
||||
message = (
|
||||
"{prefix}matrix: Connecting to " "{server}:{port}{ssl}..."
|
||||
).format(
|
||||
prefix=W.prefix("network"),
|
||||
server=self.config.address,
|
||||
port=self.config.port,
|
||||
ssl=ssl_message)
|
||||
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,12 +661,13 @@ 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 {} {}({}{}{}){}"
|
||||
self.info(
|
||||
"You have been invited to {} {}({}{}{}){}"
|
||||
"{}".format(
|
||||
room.display_name(),
|
||||
W.color("chat_delimiters"),
|
||||
|
@ -617,8 +675,9 @@ class MatrixServer(object):
|
|||
room_id,
|
||||
W.color("chat_delimiters"),
|
||||
W.color("reset"),
|
||||
inviter_msg
|
||||
))
|
||||
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")
|
||||
|
|
|
@ -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):
|
||||
|
|
273
matrix/utils.py
273
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
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue