config: Big config refactor.
This commit is contained in:
parent
b05c016fbd
commit
19eeec4f3b
10 changed files with 401 additions and 349 deletions
41
main.py
41
main.py
|
@ -71,18 +71,20 @@ from matrix.completion import (
|
|||
matrix_olm_user_completion_cb, matrix_olm_device_completion_cb,
|
||||
matrix_user_completion_cb)
|
||||
|
||||
from matrix.utils import (key_from_value, server_buffer_prnt, prnt_debug,
|
||||
from matrix.utils import (key_from_value, server_buffer_prnt,
|
||||
server_buffer_set_title)
|
||||
|
||||
from matrix.plugin_options import (DebugType, RedactType)
|
||||
from matrix.config import (
|
||||
matrix_config_reload_cb,
|
||||
MatrixConfig,
|
||||
config_log_level_cb,
|
||||
config_log_category_cb,
|
||||
config_server_buffer_cb
|
||||
)
|
||||
|
||||
from matrix.config import (matrix_config_init, matrix_config_read,
|
||||
matrix_config_free, matrix_config_change_cb,
|
||||
matrix_config_reload_cb)
|
||||
from matrix import globals as G
|
||||
|
||||
import matrix.globals
|
||||
|
||||
from matrix.globals import W, SERVERS, SCRIPT_NAME, OPTIONS
|
||||
from matrix.globals import W, SERVERS, SCRIPT_NAME
|
||||
|
||||
# yapf: disable
|
||||
WEECHAT_SCRIPT_NAME = SCRIPT_NAME
|
||||
|
@ -415,7 +417,10 @@ def room_close_cb(data, buffer):
|
|||
|
||||
@utf8_decode
|
||||
def matrix_unload_cb():
|
||||
matrix_config_free(matrix.globals.CONFIG)
|
||||
for server in SERVERS.values():
|
||||
server.config.free()
|
||||
|
||||
G.CONFIG.free()
|
||||
|
||||
# for server in SERVERS.values():
|
||||
# server.store_olm()
|
||||
|
@ -430,7 +435,7 @@ def autoconnect(servers):
|
|||
|
||||
|
||||
def debug_buffer_close_cb(data, buffer):
|
||||
OPTIONS.debug_buffer_ptr = ""
|
||||
G.CONFIG.debug_buffer = ""
|
||||
return W.WEECHAT_RC_OK
|
||||
|
||||
|
||||
|
@ -450,12 +455,12 @@ class WeechatHandler(StreamHandler):
|
|||
def write(self, item):
|
||||
buf = ""
|
||||
|
||||
if OPTIONS.debug_buffer:
|
||||
if not OPTIONS.debug_buffer_ptr:
|
||||
OPTIONS.debug_buffer_ptr = W.buffer_new(
|
||||
if G.CONFIG.network.debug_buffer:
|
||||
if not G.CONFIG.debug_buffer:
|
||||
G.CONFIG.debug_buffer = W.buffer_new(
|
||||
"Matrix Debug", "", "", "debug_buffer_close_cb", "")
|
||||
|
||||
buf = OPTIONS.debug_buffer_ptr
|
||||
buf = G.CONFIG.debug_buffer
|
||||
|
||||
W.prnt(buf, item)
|
||||
|
||||
|
@ -475,16 +480,14 @@ if __name__ == "__main__":
|
|||
handler.push_application()
|
||||
|
||||
# TODO if this fails we should abort and unload the script.
|
||||
matrix.globals.CONFIG = W.config_new("matrix",
|
||||
"matrix_config_reload_cb", "")
|
||||
matrix_config_init(matrix.globals.CONFIG)
|
||||
matrix_config_read(matrix.globals.CONFIG)
|
||||
G.CONFIG = MatrixConfig()
|
||||
G.CONFIG.read()
|
||||
|
||||
hook_commands()
|
||||
init_bar_items()
|
||||
init_completion()
|
||||
|
||||
if not SERVERS:
|
||||
create_default_server(matrix.globals.CONFIG)
|
||||
create_default_server(G.CONFIG)
|
||||
|
||||
autoconnect(SERVERS)
|
||||
|
|
|
@ -22,7 +22,8 @@ from builtins import super
|
|||
from functools import partial
|
||||
from typing import NamedTuple
|
||||
|
||||
from .globals import W, SERVERS, OPTIONS, SCRIPT_NAME
|
||||
from . import globals as G
|
||||
from .globals import W, SERVERS, SCRIPT_NAME
|
||||
from .utf import utf8_decode
|
||||
from .colors import Formatted
|
||||
from .utils import (
|
||||
|
@ -30,7 +31,7 @@ from .utils import (
|
|||
server_ts_to_weechat,
|
||||
string_strikethrough,
|
||||
)
|
||||
from .plugin_options import RedactType
|
||||
from .config import RedactType
|
||||
|
||||
from nio import (
|
||||
Api,
|
||||
|
@ -128,7 +129,7 @@ class RoomUser(WeechatUser):
|
|||
def __init__(self, nick, user_id=None, power_level=0, join_time=None):
|
||||
# type: (str, str, int) -> None
|
||||
prefix = self._get_prefix(power_level)
|
||||
return super().__init__(nick, user_id, prefix, join_time)
|
||||
super().__init__(nick, user_id, prefix, join_time)
|
||||
|
||||
@property
|
||||
def power_level(self):
|
||||
|
@ -922,12 +923,12 @@ class RoomBuffer(object):
|
|||
|
||||
new_message = ""
|
||||
|
||||
if OPTIONS.redaction_type == RedactType.STRIKETHROUGH:
|
||||
if G.CONFIG.look.redaction_type == RedactType.STRIKETHROUGH:
|
||||
plaintext_msg = W.string_remove_color(message, '')
|
||||
new_message = string_strikethrough(plaintext_msg)
|
||||
elif OPTIONS.redaction_type == RedactType.NOTICE:
|
||||
elif G.CONFIG.look.redaction_type == RedactType.NOTICE:
|
||||
new_message = message
|
||||
elif OPTIONS.redaction_type == RedactType.DELETE:
|
||||
elif G.CONFIG.look.redaction_type == RedactType.DELETE:
|
||||
pass
|
||||
|
||||
message = " ".join(s for s in [new_message, redaction_msg] if s)
|
||||
|
|
|
@ -21,7 +21,8 @@ from __future__ import unicode_literals
|
|||
# pylint: disable=redefined-builtin
|
||||
from builtins import str
|
||||
from collections import namedtuple
|
||||
from matrix.globals import W, OPTIONS
|
||||
from matrix import globals as G
|
||||
from matrix.globals import W
|
||||
from matrix.utils import string_strikethrough
|
||||
|
||||
import re
|
||||
|
@ -53,12 +54,9 @@ class Formatted():
|
|||
def textwrapper(self):
|
||||
return textwrap.TextWrapper(
|
||||
width=67,
|
||||
initial_indent="{}> ".format(
|
||||
W.color(W.config_string(OPTIONS.options["quote"]))
|
||||
),
|
||||
subsequent_indent="{}> ".format(
|
||||
W.color(W.config_string(OPTIONS.options["quote"]))
|
||||
))
|
||||
initial_indent="{}> ".format(G.CONFIG.color.quote),
|
||||
subsequent_indent="{}> ".format(G.CONFIG.color.quote)
|
||||
)
|
||||
|
||||
def is_formatted(self):
|
||||
# type: (Formatted) -> bool
|
||||
|
|
|
@ -21,7 +21,7 @@ import re
|
|||
import argparse
|
||||
|
||||
import matrix.globals
|
||||
from matrix.globals import W, OPTIONS, SERVERS
|
||||
from matrix.globals import W, SERVERS
|
||||
|
||||
from matrix.utf import utf8_decode
|
||||
from matrix.utils import key_from_value, tags_from_line_data
|
||||
|
@ -661,7 +661,7 @@ def matrix_server_command_listfull(args):
|
|||
|
||||
W.prnt("", message)
|
||||
|
||||
option = server.config.options["autoconnect"]
|
||||
option = server.config._option_ptrs["autoconnect"]
|
||||
default_value = W.config_string_default(option)
|
||||
value = W.config_string(option)
|
||||
|
||||
|
@ -670,7 +670,7 @@ def matrix_server_command_listfull(args):
|
|||
|
||||
W.prnt("", message)
|
||||
|
||||
option = server.config.options["address"]
|
||||
option = server.config._option_ptrs["address"]
|
||||
default_value = W.config_string_default(option)
|
||||
value = W.config_string(option)
|
||||
|
||||
|
@ -679,7 +679,7 @@ def matrix_server_command_listfull(args):
|
|||
|
||||
W.prnt("", message)
|
||||
|
||||
option = server.config.options["port"]
|
||||
option = server.config._option_ptrs["port"]
|
||||
default_value = str(W.config_integer_default(option))
|
||||
value = str(W.config_integer(option))
|
||||
|
||||
|
@ -688,7 +688,7 @@ def matrix_server_command_listfull(args):
|
|||
|
||||
W.prnt("", message)
|
||||
|
||||
option = server.config.options["username"]
|
||||
option = server.config._option_ptrs["username"]
|
||||
default_value = W.config_string_default(option)
|
||||
value = W.config_string(option)
|
||||
|
||||
|
@ -697,7 +697,7 @@ def matrix_server_command_listfull(args):
|
|||
|
||||
W.prnt("", message)
|
||||
|
||||
option = server.config.options["password"]
|
||||
option = server.config._option_ptrs["password"]
|
||||
value = W.config_string(option)
|
||||
|
||||
if value:
|
||||
|
@ -732,7 +732,7 @@ def matrix_server_command_delete(args):
|
|||
if server.server_buffer:
|
||||
W.buffer_close(server.server_buffer)
|
||||
|
||||
for option in server.config.options.values():
|
||||
for option in server.config._option_ptrs.values():
|
||||
W.config_option_free(option)
|
||||
|
||||
message = ("matrix: server {color}{server}{ncolor} has been "
|
||||
|
@ -762,7 +762,7 @@ def matrix_server_command_add(args):
|
|||
return
|
||||
|
||||
def remove_server(server):
|
||||
for option in server.config.options.values():
|
||||
for option in server.config._option_ptrs.values():
|
||||
W.config_option_free(option)
|
||||
del SERVERS[server.name]
|
||||
|
||||
|
@ -788,7 +788,7 @@ def matrix_server_command_add(args):
|
|||
host, port = args[1], None
|
||||
|
||||
return_code = W.config_option_set(
|
||||
server.config.options["address"],
|
||||
server.config._option_ptrs["address"],
|
||||
host,
|
||||
1
|
||||
)
|
||||
|
@ -809,7 +809,7 @@ def matrix_server_command_add(args):
|
|||
|
||||
if port:
|
||||
return_code = W.config_option_set(
|
||||
server.config.options["port"],
|
||||
server.config._option_ptrs["port"],
|
||||
port,
|
||||
1
|
||||
)
|
||||
|
@ -830,7 +830,7 @@ def matrix_server_command_add(args):
|
|||
if len(args) >= 3:
|
||||
user = args[2]
|
||||
return_code = W.config_option_set(
|
||||
server.config.options["username"],
|
||||
server.config._option_ptrs["username"],
|
||||
user,
|
||||
1
|
||||
)
|
||||
|
@ -853,7 +853,7 @@ def matrix_server_command_add(args):
|
|||
password = args[3]
|
||||
|
||||
return_code = W.config_option_set(
|
||||
server.config.options["password"],
|
||||
server.config._option_ptrs["password"],
|
||||
password,
|
||||
1
|
||||
)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from matrix.utf import utf8_decode
|
||||
from matrix.globals import W, SERVERS, OPTIONS
|
||||
from matrix.globals import W, SERVERS
|
||||
from matrix.utils import tags_from_line_data
|
||||
|
||||
|
||||
|
@ -82,6 +82,10 @@ def matrix_debug_completion_cb(data, completion_item, buffer, completion):
|
|||
return W.WEECHAT_RC_OK
|
||||
|
||||
|
||||
# TODO this should be configurable
|
||||
REDACTION_COMP_LEN = 50
|
||||
|
||||
|
||||
@utf8_decode
|
||||
def matrix_message_completion_cb(data, completion_item, buffer, completion):
|
||||
own_lines = W.hdata_pointer(W.hdata_get('buffer'), buffer, 'own_lines')
|
||||
|
@ -103,8 +107,8 @@ def matrix_message_completion_cb(data, completion_item, buffer, completion):
|
|||
if (message and 'matrix_message' in tags and
|
||||
'matrix_redacted' not in tags):
|
||||
|
||||
if len(message) > OPTIONS.redaction_comp_len + 2:
|
||||
message = (message[:OPTIONS.redaction_comp_len] + '..')
|
||||
if len(message) > REDACTION_COMP_LEN + 2:
|
||||
message = (message[:REDACTION_COMP_LEN] + '..')
|
||||
|
||||
item = ("{number}:\"{message}\"").format(
|
||||
number=line_number, message=message)
|
||||
|
|
423
matrix/config.py
423
matrix/config.py
|
@ -14,18 +14,83 @@
|
|||
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
# from __future__ import unicode_literals
|
||||
from builtins import super
|
||||
|
||||
import nio
|
||||
import logbook
|
||||
|
||||
from matrix.plugin_options import (Option, RedactType, ServerBufferType)
|
||||
|
||||
import matrix.globals
|
||||
from matrix.globals import W, OPTIONS, SERVERS
|
||||
from . import globals as G
|
||||
from matrix.globals import W, SERVERS, SCRIPT_NAME
|
||||
from matrix.utf import utf8_decode
|
||||
from matrix.utils import key_from_value, server_buffer_merge
|
||||
from matrix.commands import hook_page_up
|
||||
|
||||
from enum import Enum, unique
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
@unique
|
||||
class RedactType(Enum):
|
||||
STRIKETHROUGH = 0
|
||||
NOTICE = 1
|
||||
DELETE = 2
|
||||
|
||||
|
||||
@unique
|
||||
class ServerBufferType(Enum):
|
||||
MERGE_CORE = 0
|
||||
MERGE = 1
|
||||
INDEPENDENT = 2
|
||||
|
||||
|
||||
@unique
|
||||
class DebugType(Enum):
|
||||
MESSAGING = 0
|
||||
NETWORK = 1
|
||||
TIMING = 2
|
||||
|
||||
|
||||
class Option(namedtuple(
|
||||
'Option',
|
||||
[
|
||||
'name',
|
||||
'type',
|
||||
'string_values',
|
||||
'min',
|
||||
'max',
|
||||
'value',
|
||||
'description',
|
||||
'cast_func',
|
||||
'change_callback'
|
||||
]
|
||||
)):
|
||||
__slots__ = ()
|
||||
|
||||
def __new__(
|
||||
cls,
|
||||
name,
|
||||
type,
|
||||
string_values,
|
||||
min,
|
||||
max,
|
||||
value,
|
||||
description,
|
||||
cast=None,
|
||||
change_callback=None
|
||||
):
|
||||
return super().__new__(
|
||||
cls,
|
||||
name,
|
||||
type,
|
||||
string_values,
|
||||
min,
|
||||
max,
|
||||
value,
|
||||
description,
|
||||
cast,
|
||||
change_callback
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
@utf8_decode
|
||||
|
@ -47,148 +112,220 @@ def change_log_level(category, level):
|
|||
|
||||
|
||||
@utf8_decode
|
||||
def matrix_config_change_cb(data, option):
|
||||
option_name = key_from_value(OPTIONS.options, option)
|
||||
|
||||
if option_name == "redactions":
|
||||
OPTIONS.redaction_type = RedactType(W.config_integer(option))
|
||||
|
||||
elif option_name == "server_buffer":
|
||||
OPTIONS.look_server_buf = ServerBufferType(W.config_integer(option))
|
||||
for server in SERVERS.values():
|
||||
if server.server_buffer:
|
||||
server_buffer_merge(server.server_buffer)
|
||||
|
||||
elif option_name == "max_initial_sync_events":
|
||||
OPTIONS.sync_limit = W.config_integer(option)
|
||||
|
||||
elif option_name == "max_backlog_sync_events":
|
||||
OPTIONS.backlog_limit = W.config_integer(option)
|
||||
|
||||
elif option_name == "debug_level":
|
||||
value = W.config_integer(option)
|
||||
if value == 0:
|
||||
OPTIONS.debug_level = logbook.ERROR
|
||||
elif value == 1:
|
||||
OPTIONS.debug_level = logbook.WARNING
|
||||
elif value == 2:
|
||||
OPTIONS.debug_level = logbook.INFO
|
||||
elif value == 3:
|
||||
OPTIONS.debug_level = logbook.DEBUG
|
||||
|
||||
change_log_level(OPTIONS.debug_category, OPTIONS.debug_level)
|
||||
|
||||
elif option_name == "debug_category":
|
||||
value = W.config_integer(option)
|
||||
change_log_level(OPTIONS.debug_category, logbook.ERROR)
|
||||
|
||||
if value == 0:
|
||||
OPTIONS.debug_category = "all"
|
||||
elif value == 1:
|
||||
OPTIONS.debug_category = "http"
|
||||
elif value == 2:
|
||||
OPTIONS.debug_category = "client"
|
||||
elif value == 3:
|
||||
OPTIONS.debug_category = "events"
|
||||
elif value == 4:
|
||||
OPTIONS.debug_category = "responses"
|
||||
|
||||
change_log_level(OPTIONS.debug_category, OPTIONS.debug_level)
|
||||
|
||||
elif option_name == "debug_buffer":
|
||||
OPTIONS.debug_buffer = W.config_boolean(option)
|
||||
|
||||
elif option_name == "fetch_backlog_on_pgup":
|
||||
OPTIONS.enable_backlog = W.config_boolean(option)
|
||||
|
||||
if OPTIONS.enable_backlog:
|
||||
if not OPTIONS.page_up_hook:
|
||||
hook_page_up(matrix.globals.CONFIG)
|
||||
else:
|
||||
if OPTIONS.page_up_hook:
|
||||
W.unhook(OPTIONS.page_up_hook)
|
||||
OPTIONS.page_up_hook = None
|
||||
|
||||
def config_server_buffer_cb(data, option):
|
||||
for server in SERVERS.values():
|
||||
server.buffer_merge()
|
||||
return 1
|
||||
|
||||
|
||||
def matrix_config_init(config_file):
|
||||
look_options = [
|
||||
Option("redactions", "integer", "strikethrough|notice|delete", 0, 0,
|
||||
"strikethrough",
|
||||
("Only notice redactions, strike through or delete "
|
||||
"redacted messages")),
|
||||
Option("server_buffer", "integer",
|
||||
"merge_with_core|merge_without_core|independent", 0, 0,
|
||||
"merge_with_core", "Merge server buffers")
|
||||
]
|
||||
|
||||
network_options = [
|
||||
Option("max_initial_sync_events", "integer", "", 1, 10000, "30",
|
||||
("How many events to fetch during the initial sync")),
|
||||
Option("max_backlog_sync_events", "integer", "", 1, 100, "10",
|
||||
("How many events to fetch during backlog fetching")),
|
||||
Option("fetch_backlog_on_pgup", "boolean", "", 0, 0, "on",
|
||||
("Fetch messages in the backlog on a window page up event")),
|
||||
Option("debug_level", "integer", "error|warn|info|debug", 0, 0,
|
||||
"off", "Enable network protocol debugging."),
|
||||
Option("debug_category", "integer", "all|http|client|events|responses",
|
||||
0, 0, "all", "Debugging category"),
|
||||
Option("debug_buffer", "boolean", "", 0, 0, "off",
|
||||
("Use a separate buffer for debug logs.")),
|
||||
]
|
||||
|
||||
color_options = [
|
||||
Option("quote", "color", "", 0, 0, "lightgreen",
|
||||
("Color for matrix style blockquotes"))
|
||||
]
|
||||
|
||||
def add_global_options(section, options):
|
||||
for option in options:
|
||||
OPTIONS.options[option.name] = W.config_new_option(
|
||||
config_file, section, option.name, option.type,
|
||||
option.description, option.string_values, option.min,
|
||||
option.max, option.value, option.value, 0, "", "",
|
||||
"matrix_config_change_cb", "", "", "")
|
||||
|
||||
section = W.config_new_section(config_file, "color", 0, 0, "", "", "", "",
|
||||
"", "", "", "", "", "")
|
||||
|
||||
add_global_options(section, color_options)
|
||||
|
||||
section = W.config_new_section(config_file, "look", 0, 0, "", "", "", "",
|
||||
"", "", "", "", "", "")
|
||||
|
||||
add_global_options(section, look_options)
|
||||
|
||||
section = W.config_new_section(config_file, "network", 0, 0, "", "", "",
|
||||
"", "", "", "", "", "", "")
|
||||
|
||||
add_global_options(section, network_options)
|
||||
|
||||
W.config_new_section(
|
||||
config_file, "server", 0, 0, "matrix_config_server_read_cb", "",
|
||||
"matrix_config_server_write_cb", "", "", "", "", "", "", "")
|
||||
|
||||
return config_file
|
||||
@utf8_decode
|
||||
def config_log_level_cb(data, option):
|
||||
change_log_level(
|
||||
G.CONFIG.network.debug_category,
|
||||
G.CONFIG.network.debug_level
|
||||
)
|
||||
return 1
|
||||
|
||||
|
||||
def matrix_config_read(config):
|
||||
# type: (str) -> bool
|
||||
return_code = W.config_read(config)
|
||||
if return_code == W.WEECHAT_CONFIG_READ_OK:
|
||||
return True
|
||||
elif return_code == W.WEECHAT_CONFIG_READ_MEMORY_ERROR:
|
||||
@utf8_decode
|
||||
def config_log_category_cb(data, option):
|
||||
change_log_level(G.CONFIG.debug_category, logbook.ERROR)
|
||||
G.CONFIG.debug_category = G.CONFIG.network.debug_category
|
||||
change_log_level(
|
||||
G.CONFIG.network.debug_category,
|
||||
G.CONFIG.network.debug_level
|
||||
)
|
||||
return 1
|
||||
|
||||
|
||||
def level_to_logbook(value):
|
||||
if value == 0:
|
||||
return logbook.ERROR
|
||||
elif value == 1:
|
||||
return logbook.WARNING
|
||||
elif value == 2:
|
||||
return logbook.INFO
|
||||
elif value == 3:
|
||||
return logbook.DEBUG
|
||||
|
||||
return logbook.ERROR
|
||||
|
||||
|
||||
def logbook_category(value):
|
||||
if value == 0:
|
||||
return "all"
|
||||
elif value == 1:
|
||||
return "http"
|
||||
elif value == 2:
|
||||
return "client"
|
||||
elif value == 3:
|
||||
return "events"
|
||||
elif value == 4:
|
||||
return "responses"
|
||||
|
||||
return "all"
|
||||
|
||||
|
||||
class WeechatConfig(object):
|
||||
def __init__(self, sections):
|
||||
self._ptr = W.config_new(
|
||||
SCRIPT_NAME,
|
||||
SCRIPT_NAME + "_config_reload_cb",
|
||||
""
|
||||
)
|
||||
|
||||
for section in sections:
|
||||
name, options = section
|
||||
section_class = ConfigSection.build(name, options)
|
||||
setattr(self, name, section_class(name, self._ptr, options))
|
||||
|
||||
def free(self):
|
||||
for section in [getattr(self, a) for a in dir(self) if
|
||||
isinstance(getattr(self, a), ConfigSection)]:
|
||||
section.free()
|
||||
|
||||
W.config_free(self._ptr)
|
||||
|
||||
def read(self):
|
||||
return_code = W.config_read(self._ptr)
|
||||
if return_code == W.WEECHAT_CONFIG_READ_OK:
|
||||
return True
|
||||
elif return_code == W.WEECHAT_CONFIG_READ_MEMORY_ERROR:
|
||||
return False
|
||||
elif return_code == W.WEECHAT_CONFIG_READ_FILE_NOT_FOUND:
|
||||
return True
|
||||
return False
|
||||
elif return_code == W.WEECHAT_CONFIG_READ_FILE_NOT_FOUND:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def matrix_config_free(config):
|
||||
for section in ["network", "look", "color", "server"]:
|
||||
section_pointer = W.config_search_section(config, section)
|
||||
W.config_section_free_options(section_pointer)
|
||||
W.config_section_free(section_pointer)
|
||||
class ConfigSection(object):
|
||||
@classmethod
|
||||
def build(cls, name, options):
|
||||
def constructor(self, name, config_ptr, options):
|
||||
self._ptr = W.config_new_section(config_ptr, name, 0, 0, "", "",
|
||||
"", "", "", "", "", "", "", "")
|
||||
self._config_ptr = config_ptr
|
||||
self._option_ptrs = {}
|
||||
|
||||
W.config_free(config)
|
||||
for option in options:
|
||||
self._add_option(option)
|
||||
|
||||
attributes = {
|
||||
option.name: cls.option_property(
|
||||
option.name,
|
||||
option.type,
|
||||
cast_func=option.cast_func
|
||||
) for option in options
|
||||
}
|
||||
attributes["__init__"] = constructor
|
||||
|
||||
section_class = type(
|
||||
name.title() + "Section",
|
||||
(cls,),
|
||||
attributes
|
||||
)
|
||||
return section_class
|
||||
|
||||
def free(self):
|
||||
W.config_section_free_options(self._ptr)
|
||||
W.config_section_free(self._ptr)
|
||||
|
||||
def _add_option(self, option):
|
||||
cb = option.change_callback.__name__ if option.change_callback else ""
|
||||
option_ptr = W.config_new_option(
|
||||
self._config_ptr, self._ptr, option.name, option.type,
|
||||
option.description, option.string_values, option.min,
|
||||
option.max, option.value, option.value, 0, "", "",
|
||||
cb, "", "", "")
|
||||
|
||||
self._option_ptrs[option.name] = option_ptr
|
||||
|
||||
@staticmethod
|
||||
def option_property(name, option_type, evaluate=False, cast_func=None):
|
||||
def bool_getter(self):
|
||||
return bool(W.config_boolean(self._option_ptrs[name]))
|
||||
|
||||
def str_getter(self):
|
||||
return W.config_string(self._option_ptrs[name])
|
||||
|
||||
def str_evaluate_getter(self):
|
||||
return W.string_eval_expression(
|
||||
W.config_string(self._option_ptrs[name]),
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
)
|
||||
|
||||
def int_getter(self):
|
||||
if cast_func:
|
||||
return cast_func(W.config_integer(self._option_ptrs[name]))
|
||||
else:
|
||||
return W.config_integer(self._option_ptrs[name])
|
||||
|
||||
if option_type == "string" or option_type == "color":
|
||||
if evaluate:
|
||||
return property(str_evaluate_getter)
|
||||
return property(str_getter)
|
||||
elif option_type == "boolean":
|
||||
return property(bool_getter)
|
||||
elif option_type == "integer":
|
||||
return property(int_getter)
|
||||
|
||||
|
||||
class MatrixConfig(WeechatConfig):
|
||||
def __init__(self):
|
||||
|
||||
self.debug_buffer = ""
|
||||
self.debug_category = "all"
|
||||
|
||||
look_options = [
|
||||
Option("redactions", "integer", "strikethrough|notice|delete", 0,
|
||||
0, "strikethrough",
|
||||
("Only notice redactions, strike through or delete "
|
||||
"redacted messages"), RedactType),
|
||||
Option("server_buffer", "integer",
|
||||
"merge_with_core|merge_without_core|independent", 0, 0,
|
||||
"merge_with_core", "Merge server buffers", ServerBufferType,
|
||||
config_server_buffer_cb)
|
||||
]
|
||||
|
||||
network_options = [
|
||||
Option("max_initial_sync_events", "integer", "", 1, 10000, "30",
|
||||
("How many events to fetch during the initial sync")),
|
||||
Option("max_backlog_sync_events", "integer", "", 1, 100, "10",
|
||||
("How many events to fetch during backlog fetching")),
|
||||
Option("fetch_backlog_on_pgup", "boolean", "", 0, 0, "on",
|
||||
("Fetch messages in the backlog on a window page up event")
|
||||
),
|
||||
Option("debug_level", "integer", "error|warn|info|debug", 0, 0,
|
||||
"error", "Enable network protocol debugging.",
|
||||
level_to_logbook, config_log_level_cb),
|
||||
Option("debug_category", "integer",
|
||||
"all|http|client|events|responses",
|
||||
0, 0, "all", "Debugging category", logbook_category),
|
||||
Option("debug_buffer", "boolean", "", 0, 0, "off",
|
||||
("Use a separate buffer for debug logs.")),
|
||||
]
|
||||
|
||||
color_options = [
|
||||
Option("quote", "color", "", 0, 0, "lightgreen",
|
||||
("Color for matrix style blockquotes"))
|
||||
]
|
||||
|
||||
sections = [
|
||||
("network", network_options),
|
||||
("look", look_options),
|
||||
("color", color_options)
|
||||
]
|
||||
|
||||
super().__init__(sections)
|
||||
|
||||
# The server section is essentially a section with subsections and no
|
||||
# options, handle that case independently.
|
||||
W.config_new_section(
|
||||
self._ptr, "server", 0, 0, "matrix_config_server_read_cb", "",
|
||||
"matrix_config_server_write_cb", "", "", "", "", "", "", "")
|
||||
|
||||
def free(self):
|
||||
section_ptr = W.config_search_section(self._ptr, 'server')
|
||||
W.config_section_free(section_ptr)
|
||||
super().free()
|
||||
|
|
|
@ -19,7 +19,6 @@ from __future__ import unicode_literals
|
|||
import sys
|
||||
|
||||
from matrix.utf import WeechatWrapper
|
||||
from matrix.plugin_options import PluginOptions
|
||||
|
||||
try:
|
||||
import weechat
|
||||
|
@ -28,8 +27,7 @@ except ImportError:
|
|||
import matrix._weechat as weechat
|
||||
W = weechat
|
||||
|
||||
OPTIONS = PluginOptions() # type: PluginOptions
|
||||
SERVERS = dict() # type: Dict[str, MatrixServer]
|
||||
CONFIG = None # type: weechat.config
|
||||
CONFIG = None # type: MatrixConfig
|
||||
ENCRYPTION = True # type: bool
|
||||
SCRIPT_NAME = "matrix" # type: str
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright © 2018 Damir Jelić <poljar@termina.org.uk>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logbook
|
||||
|
||||
from collections import namedtuple
|
||||
from enum import Enum, unique
|
||||
|
||||
|
||||
@unique
|
||||
class RedactType(Enum):
|
||||
STRIKETHROUGH = 0
|
||||
NOTICE = 1
|
||||
DELETE = 2
|
||||
|
||||
|
||||
@unique
|
||||
class ServerBufferType(Enum):
|
||||
MERGE_CORE = 0
|
||||
MERGE = 1
|
||||
INDEPENDENT = 2
|
||||
|
||||
|
||||
@unique
|
||||
class DebugType(Enum):
|
||||
MESSAGING = 0
|
||||
NETWORK = 1
|
||||
TIMING = 2
|
||||
|
||||
|
||||
Option = namedtuple(
|
||||
'Option',
|
||||
['name', 'type', 'string_values', 'min', 'max', 'value', 'description'])
|
||||
|
||||
|
||||
class PluginOptions:
|
||||
|
||||
def __init__(self):
|
||||
self.redaction_type = RedactType.STRIKETHROUGH # type: RedactType
|
||||
self.look_server_buf = ServerBufferType.MERGE_CORE \
|
||||
# type: ServerBufferType
|
||||
|
||||
self.sync_limit = 30 # type: int
|
||||
self.backlog_limit = 10 # type: int
|
||||
self.enable_backlog = True # type: bool
|
||||
self.page_up_hook = None # type: weechat.hook
|
||||
|
||||
self.redaction_comp_len = 50 # type: int
|
||||
|
||||
self.options = dict() # type: Dict[str, weechat.config_option]
|
||||
self.debug = []
|
||||
self.debug_level = logbook.ERROR
|
||||
self.debug_category = "all"
|
||||
self.debug_buffer = False
|
||||
self.debug_buffer_ptr = ""
|
119
matrix/server.py
119
matrix/server.py
|
@ -29,18 +29,18 @@ from nio import (
|
|||
LoginResponse,
|
||||
SyncRepsponse,
|
||||
RoomSendResponse,
|
||||
RoomPutStateResponse,
|
||||
TransportResponse,
|
||||
TransportType,
|
||||
LocalProtocolError
|
||||
)
|
||||
|
||||
from matrix.plugin_options import Option, DebugType
|
||||
from matrix.utils import (key_from_value, prnt_debug, server_buffer_prnt,
|
||||
from matrix.utils import (key_from_value, server_buffer_prnt,
|
||||
create_server_buffer)
|
||||
from matrix.utf import utf8_decode
|
||||
from matrix.globals import W, SERVERS, SCRIPT_NAME, OPTIONS
|
||||
from . import globals as G
|
||||
from matrix.globals import W, SERVERS, SCRIPT_NAME
|
||||
from .buffer import RoomBuffer, OwnMessage, OwnAction
|
||||
from .config import Option, ServerBufferType, ConfigSection
|
||||
|
||||
try:
|
||||
FileNotFoundError
|
||||
|
@ -48,29 +48,12 @@ except NameError:
|
|||
FileNotFoundError = IOError
|
||||
|
||||
|
||||
class ServerConfig(object):
|
||||
def option_property(name, option_type):
|
||||
def bool_getter(self):
|
||||
return bool(W.config_boolean(self.options[name]))
|
||||
|
||||
def str_getter(self):
|
||||
return W.config_string(self.options[name])
|
||||
|
||||
def int_getter(self):
|
||||
return W.config_integer(self.options[name])
|
||||
|
||||
if option_type == str:
|
||||
return property(str_getter)
|
||||
elif option_type == bool:
|
||||
return property(bool_getter)
|
||||
elif option_type == int:
|
||||
return property(int_getter)
|
||||
|
||||
class ServerConfig(ConfigSection):
|
||||
def __init__(self, server_name, config_ptr):
|
||||
# type: (str, str) -> None
|
||||
self._server_name = server_name
|
||||
self._ptr = config_ptr
|
||||
self.options = {}
|
||||
self._config_ptr = config_ptr
|
||||
self._option_ptrs = {}
|
||||
|
||||
options = [
|
||||
Option('autoconnect', 'boolean', '', 0, 0, 'off',
|
||||
|
@ -95,37 +78,33 @@ class ServerConfig(object):
|
|||
]
|
||||
|
||||
section = W.config_search_section(config_ptr, 'server')
|
||||
self._ptr = section
|
||||
|
||||
for option in options:
|
||||
option_name = "{server}.{option}".format(
|
||||
server=self._server_name, option=option.name)
|
||||
|
||||
self.options[option.name] = W.config_new_option(
|
||||
self._option_ptrs[option.name] = W.config_new_option(
|
||||
config_ptr, section, option_name, option.type,
|
||||
option.description, option.string_values, option.min,
|
||||
option.max, option.value, option.value, 0, "", "",
|
||||
"matrix_config_server_change_cb", self._server_name, "", "")
|
||||
|
||||
def _get_str_option(self, option_name):
|
||||
return W.config_string(self.options[option_name])
|
||||
autoconnect = ConfigSection.option_property("autoconnect", "boolean")
|
||||
address = ConfigSection.option_property("address", "string")
|
||||
port = ConfigSection.option_property("port", "integer")
|
||||
proxy = ConfigSection.option_property("proxy", "string")
|
||||
ssl_verify = ConfigSection.option_property("ssl_verify", "boolean")
|
||||
username = ConfigSection.option_property("username", "string")
|
||||
device_name = ConfigSection.option_property("device_name", "string")
|
||||
password = ConfigSection.option_property(
|
||||
"password",
|
||||
"string",
|
||||
evaluate=True
|
||||
)
|
||||
|
||||
autoconnect = option_property("autoconnect", bool)
|
||||
address = option_property("address", str)
|
||||
port = option_property("port", int)
|
||||
proxy = option_property("proxy", str)
|
||||
ssl_verify = option_property("ssl_verify", bool)
|
||||
username = option_property("username", str)
|
||||
device_name = option_property("device_name", str)
|
||||
|
||||
@property
|
||||
def password(self):
|
||||
# type: () -> str
|
||||
return W.string_eval_expression(
|
||||
self._get_str_option("password"),
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
)
|
||||
def free(self):
|
||||
W.config_section_free_options(self._ptr)
|
||||
|
||||
|
||||
class MatrixServer(object):
|
||||
|
@ -609,7 +588,13 @@ class MatrixServer(object):
|
|||
# self.store_olm()
|
||||
# self.upload_keys(device_keys=True, one_time_keys=False)
|
||||
|
||||
sync_filter = {"room": {"timeline": {"limit": OPTIONS.sync_limit}}}
|
||||
sync_filter = {
|
||||
"room": {
|
||||
"timeline": {
|
||||
"limit": G.CONFIG.network.max_initial_sync_events
|
||||
}
|
||||
}
|
||||
}
|
||||
self.sync(timeout=0, filter=sync_filter)
|
||||
|
||||
def _handle_room_info(self, response):
|
||||
|
@ -718,6 +703,35 @@ class MatrixServer(object):
|
|||
room_buffer = self.room_buffers[room_id]
|
||||
return room_buffer
|
||||
|
||||
def buffer_merge(self):
|
||||
if not self.server_buffer:
|
||||
return
|
||||
|
||||
buf = self.server_buffer
|
||||
|
||||
if G.CONFIG.look.server_buffer == ServerBufferType.MERGE_CORE:
|
||||
num = W.buffer_get_integer(W.buffer_search_main(), "number")
|
||||
W.buffer_unmerge(buf, num + 1)
|
||||
W.buffer_merge(buf, W.buffer_search_main())
|
||||
elif G.CONFIG.look.server_buffer == ServerBufferType.MERGE:
|
||||
if SERVERS:
|
||||
first = None
|
||||
for server in SERVERS.values():
|
||||
if server.server_buffer:
|
||||
first = server.server_buffer
|
||||
break
|
||||
if first:
|
||||
num = W.buffer_get_integer(
|
||||
W.buffer_search_main(),
|
||||
"number"
|
||||
)
|
||||
W.buffer_unmerge(buf, num + 1)
|
||||
if buf is not first:
|
||||
W.buffer_merge(buf, first)
|
||||
else:
|
||||
num = W.buffer_get_integer(W.buffer_search_main(), "number")
|
||||
W.buffer_unmerge(buf, num + 1)
|
||||
|
||||
|
||||
@utf8_decode
|
||||
def matrix_config_server_read_cb(data, config_file, section, option_name,
|
||||
|
@ -736,9 +750,9 @@ def matrix_config_server_read_cb(data, config_file, section, option_name,
|
|||
SERVERS[server.name] = server
|
||||
|
||||
# Ignore invalid options
|
||||
if option in server.config.options:
|
||||
if option in server.config._option_ptrs:
|
||||
return_code = W.config_option_set(
|
||||
server.config.options[option],
|
||||
server.config._option_ptrs[option],
|
||||
value,
|
||||
1
|
||||
)
|
||||
|
@ -754,7 +768,7 @@ def matrix_config_server_write_cb(data, config_file, section_name):
|
|||
return W.WECHAT_CONFIG_WRITE_ERROR
|
||||
|
||||
for server in SERVERS.values():
|
||||
for option in server.config.options.values():
|
||||
for option in server.config._option_ptrs.values():
|
||||
if not W.config_write_option(config_file, option):
|
||||
return W.WECHAT_CONFIG_WRITE_ERROR
|
||||
|
||||
|
@ -770,7 +784,7 @@ def matrix_config_server_change_cb(server_name, option):
|
|||
# The function config_option_get_string() is used to get differing
|
||||
# properties from a config option, sadly it's only available in the plugin
|
||||
# API of weechat.
|
||||
option_name = key_from_value(server.config.options, option)
|
||||
option_name = key_from_value(server.config._option_ptrs, option)
|
||||
server.update_option(option, option_name)
|
||||
|
||||
return 1
|
||||
|
@ -807,11 +821,6 @@ def matrix_timer_cb(server_name, remaining_calls):
|
|||
|
||||
while server.send_queue:
|
||||
message = server.send_queue.popleft()
|
||||
prnt_debug(
|
||||
DebugType.MESSAGING,
|
||||
server, ("Timer hook found message of type {t} in queue. Sending "
|
||||
"out.".format(t=message.__class__.__name__)))
|
||||
|
||||
if not server.send(message):
|
||||
# We got an error while sending the last message return the message
|
||||
# to the queue and exit the loop
|
||||
|
@ -835,7 +844,7 @@ def matrix_timer_cb(server_name, remaining_calls):
|
|||
|
||||
|
||||
def create_default_server(config_file):
|
||||
server = MatrixServer('matrix_org', config_file)
|
||||
server = MatrixServer('matrix_org', config_file._ptr)
|
||||
SERVERS[server.name] = server
|
||||
|
||||
option = W.config_get(SCRIPT_NAME + ".server." + server.name + ".address")
|
||||
|
|
|
@ -20,9 +20,8 @@ from builtins import str
|
|||
import time
|
||||
import math
|
||||
|
||||
from matrix.globals import W, SERVERS, OPTIONS
|
||||
|
||||
from matrix.plugin_options import ServerBufferType
|
||||
from matrix import globals as G
|
||||
from matrix.globals import W, SERVERS
|
||||
|
||||
try:
|
||||
from urlparse import urlparse
|
||||
|
@ -35,11 +34,6 @@ def key_from_value(dictionary, value):
|
|||
return list(dictionary.keys())[list(dictionary.values()).index(value)]
|
||||
|
||||
|
||||
def prnt_debug(debug_type, server, message):
|
||||
if debug_type in OPTIONS.debug:
|
||||
W.prnt(server.server_buffer, message)
|
||||
|
||||
|
||||
def server_buffer_prnt(server, string):
|
||||
# type: (MatrixServer, str) -> None
|
||||
assert server.server_buffer
|
||||
|
@ -79,29 +73,7 @@ def create_server_buffer(server):
|
|||
W.buffer_set(server.server_buffer, "localvar_set_server", server.name)
|
||||
W.buffer_set(server.server_buffer, "localvar_set_channel", server.name)
|
||||
|
||||
server_buffer_merge(server.server_buffer)
|
||||
|
||||
|
||||
def server_buffer_merge(buffer):
|
||||
if OPTIONS.look_server_buf == ServerBufferType.MERGE_CORE:
|
||||
num = W.buffer_get_integer(W.buffer_search_main(), "number")
|
||||
W.buffer_unmerge(buffer, num + 1)
|
||||
W.buffer_merge(buffer, W.buffer_search_main())
|
||||
elif OPTIONS.look_server_buf == ServerBufferType.MERGE:
|
||||
if SERVERS:
|
||||
first = None
|
||||
for server in SERVERS.values():
|
||||
if server.server_buffer:
|
||||
first = server.server_buffer
|
||||
break
|
||||
if first:
|
||||
num = W.buffer_get_integer(W.buffer_search_main(), "number")
|
||||
W.buffer_unmerge(buffer, num + 1)
|
||||
if buffer is not first:
|
||||
W.buffer_merge(buffer, first)
|
||||
else:
|
||||
num = W.buffer_get_integer(W.buffer_search_main(), "number")
|
||||
W.buffer_unmerge(buffer, num + 1)
|
||||
server.buffer_merge()
|
||||
|
||||
|
||||
def server_buffer_set_title(server):
|
||||
|
|
Loading…
Reference in a new issue