server: Introduce a server config class.

This commit is contained in:
Damir Jelić 2018-08-03 17:43:34 +02:00
parent 5e676f168f
commit a513b82418
4 changed files with 162 additions and 98 deletions

View file

@ -181,7 +181,7 @@ def wrap_socket(server, file_descriptor):
ssl_socket = server.ssl_context.wrap_socket( ssl_socket = server.ssl_context.wrap_socket(
sock, do_handshake_on_connect=False, sock, do_handshake_on_connect=False,
server_hostname=server.address) # type: ssl.SSLSocket server_hostname=server.config.address) # type: ssl.SSLSocket
server.socket = ssl_socket server.socket = ssl_socket
@ -428,7 +428,7 @@ def matrix_unload_cb():
def autoconnect(servers): def autoconnect(servers):
for server in servers.values(): for server in servers.values():
if server.autoconnect: if server.config.autoconnect:
server.connect() server.connect()

View file

@ -620,7 +620,7 @@ def matrix_server_command_listfull(args):
W.prnt("", message) W.prnt("", message)
option = server.options["autoconnect"] option = server.config.options["autoconnect"]
default_value = W.config_string_default(option) default_value = W.config_string_default(option)
value = W.config_string(option) value = W.config_string(option)
@ -629,7 +629,7 @@ def matrix_server_command_listfull(args):
W.prnt("", message) W.prnt("", message)
option = server.options["address"] option = server.config.options["address"]
default_value = W.config_string_default(option) default_value = W.config_string_default(option)
value = W.config_string(option) value = W.config_string(option)
@ -638,7 +638,7 @@ def matrix_server_command_listfull(args):
W.prnt("", message) W.prnt("", message)
option = server.options["port"] option = server.config.options["port"]
default_value = str(W.config_integer_default(option)) default_value = str(W.config_integer_default(option))
value = str(W.config_integer(option)) value = str(W.config_integer(option))
@ -647,7 +647,7 @@ def matrix_server_command_listfull(args):
W.prnt("", message) W.prnt("", message)
option = server.options["username"] option = server.config.options["username"]
default_value = W.config_string_default(option) default_value = W.config_string_default(option)
value = W.config_string(option) value = W.config_string(option)
@ -656,7 +656,7 @@ def matrix_server_command_listfull(args):
W.prnt("", message) W.prnt("", message)
option = server.options["password"] option = server.config.options["password"]
value = W.config_string(option) value = W.config_string(option)
if value: if value:
@ -691,7 +691,7 @@ def matrix_server_command_delete(args):
if server.server_buffer: if server.server_buffer:
W.buffer_close(server.server_buffer) W.buffer_close(server.server_buffer)
for option in server.options.values(): for option in server.config.options.values():
W.config_option_free(option) W.config_option_free(option)
message = ("matrix: server {color}{server}{ncolor} has been " message = ("matrix: server {color}{server}{ncolor} has been "
@ -721,7 +721,7 @@ def matrix_server_command_add(args):
return return
def remove_server(server): def remove_server(server):
for option in server.options.values(): for option in server.config.options.values():
W.config_option_free(option) W.config_option_free(option)
del SERVERS[server.name] del SERVERS[server.name]
@ -746,7 +746,11 @@ def matrix_server_command_add(args):
except ValueError: except ValueError:
host, port = args[1], None host, port = args[1], None
return_code = W.config_option_set(server.options["address"], host, 1) return_code = W.config_option_set(
server.config.options["address"],
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)
@ -763,7 +767,11 @@ def matrix_server_command_add(args):
return return
if port: if port:
return_code = W.config_option_set(server.options["port"], port, 1) return_code = W.config_option_set(
server.config.options["port"],
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 "
@ -780,7 +788,11 @@ 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(server.options["username"], user, 1) return_code = W.config_option_set(
server.config.options["username"],
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)
@ -799,8 +811,11 @@ def matrix_server_command_add(args):
if len(args) == 4: if len(args) == 4:
password = args[3] password = args[3]
return_code = W.config_option_set(server.options["password"], password, return_code = W.config_option_set(
1) server.config.options["password"],
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 "

View file

@ -46,25 +46,118 @@ except NameError:
FileNotFoundError = IOError FileNotFoundError = IOError
class MatrixServer: class ServerConfig(object):
_section_name = "{}.{}".format(SCRIPT_NAME, "server")
def __init__(self, server_name, config_ptr):
# type: (str, str) -> None
self._server_name = server_name
self._ptr = config_ptr
self.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(
'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')
for option in options:
option_name = "{server}.{option}".format(
server=self._server_name, option=option.name)
self.options[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])
def _get_bool_option(self, option_name):
return bool(W.config_boolean(self.options[option_name]))
@property
def config_section(self):
# type: () -> str
return "{}.{}".format(self._server_name, self._server_name)
@property
def autoconnect(self):
# type: () -> bool
return self._get_bool_option("autoconnect")
@property
def address(self):
# type: () -> str
return self._get_str_option("address")
@property
def port(self):
# type: () -> int
return W.config_integer(self.options["port"])
@property
def proxy(self):
# type: () -> str
return self._get_str_option("proxy")
@property
def ssl_verify(self):
# type: () -> bool
return self._get_bool_option("ssl_verify")
@property
def username(self):
# type: () -> str
return self._get_str_option("username")
@property
def password(self):
# type: () -> str
return W.string_eval_expression(
self._get_str_option("password"),
{},
{},
{}
)
@property
def device_name(self):
# type: () -> str
return self._get_str_option("device_name")
class MatrixServer(object):
# pylint: disable=too-many-instance-attributes # pylint: disable=too-many-instance-attributes
def __init__(self, name, config_file): def __init__(self, name, config_file):
# type: (str, weechat.config) -> None # type: (str, weechat.config) -> None
# yapf: disable # yapf: disable
self.name = name # type: str self.name = name # type: str
self.user_id = "" self.user_id = ""
self.address = "" # type: str
self.port = 8448 # type: int
self.options = dict() # type: Dict[str, weechat.config]
self.device_name = "Weechat Matrix" # type: str
self.device_id = "" # type: str self.device_id = "" # type: str
self.olm = None # type: Olm self.olm = None # type: Olm
self.encryption_queue = defaultdict(deque) self.encryption_queue = defaultdict(deque)
self.user = "" # type: str
self.password = "" # type: str
self.room_buffers = dict() # type: Dict[str, WeechatChannelBuffer] self.room_buffers = dict() # type: Dict[str, WeechatChannelBuffer]
self.buffers = dict() # type: Dict[str, weechat.buffer] self.buffers = dict() # type: Dict[str, weechat.buffer]
self.server_buffer = None # type: weechat.buffer self.server_buffer = None # type: weechat.buffer
@ -73,10 +166,8 @@ class MatrixServer:
self.timer_hook = None # type: weechat.hook self.timer_hook = None # type: weechat.hook
self.numeric_address = "" # type: str self.numeric_address = "" # type: str
self.autoconnect = False # type: bool
self.connected = False # type: bool self.connected = False # type: bool
self.connecting = False # type: bool self.connecting = False # type: bool
self.proxy = None # type: str
self.reconnect_delay = 0 # type: int self.reconnect_delay = 0 # type: int
self.reconnect_time = None # type: float self.reconnect_time = None # type: float
self.sync_time = None # type: Optional[float] self.sync_time = None # type: Optional[float]
@ -108,7 +199,8 @@ class MatrixServer:
self.event_queue_timer = None self.event_queue_timer = None
self.event_queue = deque() # type: Deque[RoomInfo] self.event_queue = deque() # type: Deque[RoomInfo]
self._create_options(config_file) # self._create_options(config_file)
self.config = ServerConfig(self.name, config_file)
self._create_session_dir() self._create_session_dir()
# yapf: enable # yapf: enable
@ -124,7 +216,7 @@ class MatrixServer:
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):
file_name = "{}{}".format(self.user, ".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)
if not os.path.isfile(path): if not os.path.isfile(path):
@ -136,66 +228,21 @@ class MatrixServer:
self.device_id = device_id self.device_id = device_id
def save_device_id(self): def save_device_id(self):
file_name = "{}{}".format(self.user, ".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 f:
f.write(self.device_id) f.write(self.device_id)
def _create_options(self, config_file):
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, '8448',
"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_file, 'server')
for option in options:
option_name = "{server}.{option}".format(
server=self.name, option=option.name)
self.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_server_change_cb", self.name, "", "")
def _change_client(self): def _change_client(self):
host = ':'.join([self.address, str(self.port)]) host = ':'.join([self.config.address, str(self.config.port)])
self.client = HttpClient(host, self.user) self.client = HttpClient(host, self.config.username)
def update_option(self, option, option_name): def update_option(self, option, option_name):
if option_name == "address": if option_name == "address":
value = W.config_string(option)
self.address = value
self._change_client() self._change_client()
elif option_name == "autoconnect":
value = W.config_boolean(option)
self.autoconnect = value
elif option_name == "port": elif option_name == "port":
value = W.config_integer(option)
self.port = value
self._change_client() self._change_client()
elif option_name == "proxy":
value = W.config_string(option)
self.proxy = value
elif option_name == "ssl_verify": elif option_name == "ssl_verify":
value = W.config_boolean(option) value = W.config_boolean(option)
if value: if value:
@ -206,18 +253,10 @@ class MatrixServer:
self.ssl_context.verify_mode = ssl.CERT_NONE self.ssl_context.verify_mode = ssl.CERT_NONE
elif option_name == "username": elif option_name == "username":
value = W.config_string(option) value = W.config_string(option)
self.user = value
self.access_token = "" self.access_token = ""
if self.client: if self.client:
self.client.user = value self.client.user = value
elif option_name == "password":
value = W.config_string(option)
self.password = W.string_eval_expression(value, {}, {}, {})
elif option_name == "device_name":
value = W.config_string(option)
self.device_name = value
else: else:
pass pass
@ -271,7 +310,7 @@ class MatrixServer:
prefix=W.prefix("network"))) prefix=W.prefix("network")))
server_buffer_prnt( server_buffer_prnt(
self, ("{prefix}matrix: disconnecting from server..." self, ("{prefix}matrix: disconnecting from server..."
).format(prefix=W.prefix("network"))) ).format(prefix=W.prefix("network")))
self.disconnect() self.disconnect()
return False return False
@ -373,13 +412,14 @@ class MatrixServer:
def connect(self): def connect(self):
# type: (MatrixServer) -> int # type: (MatrixServer) -> int
if not self.address or not self.port: if not self.config.address or not self.config.port:
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.user or not self.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)
@ -400,14 +440,14 @@ class MatrixServer:
message = ("{prefix}matrix: Connecting to " message = ("{prefix}matrix: Connecting to "
"{server}:{port}{ssl}...").format( "{server}:{port}{ssl}...").format(
prefix=W.prefix("network"), prefix=W.prefix("network"),
server=self.address, server=self.config.address,
port=self.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.proxy if self.proxy else "", W.hook_connect(self.config.proxy,
self.address, self.port, self.config.address, self.config.port,
1, 0, "", "connect_cb", 1, 0, "", "connect_cb",
self.name) self.name)
@ -424,7 +464,7 @@ class MatrixServer:
def login(self): def login(self):
# type: () -> None # type: () -> None
_, request = self.client.login(self.password) _, request = self.client.login(self.config.password)
self.send_or_queue(request) self.send_or_queue(request)
msg = "{prefix}matrix: Logging in...".format( msg = "{prefix}matrix: Logging in...".format(
@ -597,8 +637,12 @@ def matrix_config_server_read_cb(data, config_file, section, option_name,
SERVERS[server.name] = server SERVERS[server.name] = server
# Ignore invalid options # Ignore invalid options
if option in server.options: if option in server.config.options:
return_code = W.config_option_set(server.options[option], value, 1) return_code = W.config_option_set(
server.config.options[option],
value,
1
)
# TODO print out error message in case of erroneous return_code # TODO print out error message in case of erroneous return_code
@ -611,7 +655,7 @@ def matrix_config_server_write_cb(data, config_file, section_name):
return W.WECHAT_CONFIG_WRITE_ERROR return W.WECHAT_CONFIG_WRITE_ERROR
for server in SERVERS.values(): for server in SERVERS.values():
for option in server.options.values(): for option in server.config.options.values():
if not W.config_write_option(config_file, option): if not W.config_write_option(config_file, option):
return W.WECHAT_CONFIG_WRITE_ERROR return W.WECHAT_CONFIG_WRITE_ERROR
@ -627,7 +671,7 @@ def matrix_config_server_change_cb(server_name, option):
# The function config_option_get_string() is used to get differing # The function config_option_get_string() is used to get differing
# properties from a config option, sadly it's only available in the plugin # properties from a config option, sadly it's only available in the plugin
# API of weechat. # API of weechat.
option_name = key_from_value(server.options, option) option_name = key_from_value(server.config.options, option)
server.update_option(option, option_name) server.update_option(option, option_name)
return 1 return 1
@ -690,10 +734,11 @@ 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) server = MatrixServer('matrix_org', config_file)
SERVERS[server.name] = server SERVERS[server.name] = server
W.config_option_set(server.options["address"], "matrix.org", 1) option = W.config_get(SCRIPT_NAME + ".server." + server.name + ".address")
W.config_option_set(option, "matrix.org", 1)
return True return True

View file

@ -69,7 +69,11 @@ def create_server_buffer(server):
server_buffer_set_title(server) server_buffer_set_title(server)
W.buffer_set(server.server_buffer, "localvar_set_type", 'server') W.buffer_set(server.server_buffer, "localvar_set_type", 'server')
W.buffer_set(server.server_buffer, "localvar_set_nick", server.user) W.buffer_set(
server.server_buffer,
"localvar_set_nick",
server.config.username
)
W.buffer_set(server.server_buffer, "localvar_set_server", server.name) W.buffer_set(server.server_buffer, "localvar_set_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)
@ -106,7 +110,7 @@ def server_buffer_set_title(server):
ip_string = "" ip_string = ""
title = ("Matrix: {address}:{port}{ip}").format( title = ("Matrix: {address}:{port}{ip}").format(
address=server.address, port=server.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)