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