2017-12-30 14:03:03 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2018-01-26 18:22:06 +01:00
|
|
|
# Weechat Matrix Protocol Script
|
|
|
|
# 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.
|
|
|
|
|
2017-12-30 14:03:03 +01:00
|
|
|
from __future__ import unicode_literals
|
|
|
|
|
|
|
|
import json
|
|
|
|
import socket
|
|
|
|
import ssl
|
|
|
|
import time
|
2018-01-11 16:21:14 +01:00
|
|
|
import datetime
|
2018-01-19 12:43:12 +01:00
|
|
|
import pprint
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
# pylint: disable=redefined-builtin
|
2018-01-26 17:43:07 +01:00
|
|
|
from builtins import str
|
2018-01-06 17:12:54 +01:00
|
|
|
|
2018-01-16 13:23:45 +01:00
|
|
|
from operator import itemgetter
|
2018-01-06 17:12:54 +01:00
|
|
|
|
|
|
|
# pylint: disable=unused-import
|
2018-01-05 19:39:11 +01:00
|
|
|
from typing import (List, Set, Dict, Tuple, Text, Optional, AnyStr, Deque, Any)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-26 13:12:57 +01:00
|
|
|
from matrix import colors
|
2018-01-26 17:43:07 +01:00
|
|
|
from matrix.utf import utf8_decode
|
2018-01-26 14:38:46 +01:00
|
|
|
from matrix.http import HttpResponse
|
|
|
|
from matrix.api import MatrixMessage, MessageType
|
|
|
|
from matrix.server import MatrixServer
|
2018-01-26 17:43:07 +01:00
|
|
|
from matrix.socket import disconnect, send_or_queue, send
|
|
|
|
|
|
|
|
|
|
|
|
# Weechat searches for the registered callbacks in the global scope, import the
|
|
|
|
# callbacks here so weechat can find them.
|
|
|
|
from matrix.commands import (
|
|
|
|
hook_commands,
|
|
|
|
hook_page_up,
|
|
|
|
matrix_command_join_cb,
|
|
|
|
matrix_command_part_cb,
|
|
|
|
matrix_command_invite_cb,
|
|
|
|
matrix_command_pgup_cb,
|
|
|
|
matrix_redact_command_cb,
|
|
|
|
matrix_command_buf_clear_cb,
|
|
|
|
matrix_debug_completion_cb,
|
|
|
|
matrix_message_completion_cb
|
|
|
|
)
|
|
|
|
|
|
|
|
from matrix.utils import (
|
|
|
|
key_from_value,
|
|
|
|
server_buffer_prnt,
|
|
|
|
prnt_debug,
|
|
|
|
tags_from_line_data
|
|
|
|
)
|
|
|
|
|
2018-01-26 14:38:46 +01:00
|
|
|
from matrix.config import (
|
|
|
|
DebugType,
|
|
|
|
RedactType,
|
|
|
|
ServerBufferType
|
|
|
|
)
|
2018-01-24 17:34:07 +01:00
|
|
|
|
2018-01-26 17:43:07 +01:00
|
|
|
import matrix.globals
|
|
|
|
|
|
|
|
W = matrix.globals.W
|
|
|
|
GLOBAL_OPTIONS = matrix.globals.OPTIONS
|
|
|
|
CONFIG = matrix.globals.CONFIG
|
|
|
|
SERVERS = matrix.globals.SERVERS
|
|
|
|
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-23 13:30:42 +01:00
|
|
|
WEECHAT_SCRIPT_NAME = "matrix" # type: str
|
|
|
|
WEECHAT_SCRIPT_DESCRIPTION = "matrix chat plugin" # type: str
|
|
|
|
WEECHAT_SCRIPT_AUTHOR = "Damir Jelić <poljar@termina.org.uk>" # type: str
|
|
|
|
WEECHAT_SCRIPT_VERSION = "0.1" # type: str
|
2018-01-26 18:22:06 +01:00
|
|
|
WEECHAT_SCRIPT_LICENSE = "ISC" # type: str
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-24 12:41:01 +01:00
|
|
|
|
2018-01-18 12:31:00 +01:00
|
|
|
class MatrixUser:
|
|
|
|
def __init__(self, name, display_name):
|
2018-01-23 13:30:42 +01:00
|
|
|
self.name = name # type: str
|
|
|
|
self.display_name = display_name # type: str
|
2018-01-18 12:31:00 +01:00
|
|
|
self.power_level = 0 # type: int
|
2018-01-23 13:30:42 +01:00
|
|
|
self.nick_color = "" # type: str
|
|
|
|
self.prefix = "" # type: str
|
2018-01-18 12:31:00 +01:00
|
|
|
|
|
|
|
|
2017-12-30 14:03:03 +01:00
|
|
|
class MatrixRoom:
|
2018-01-11 16:21:14 +01:00
|
|
|
def __init__(self, room_id):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (str) -> None
|
|
|
|
self.room_id = room_id # type: str
|
|
|
|
self.alias = room_id # type: str
|
|
|
|
self.topic = "" # type: str
|
|
|
|
self.topic_author = "" # type: str
|
2018-01-11 16:21:14 +01:00
|
|
|
self.topic_date = None # type: datetime.datetime
|
2018-01-23 13:30:42 +01:00
|
|
|
self.prev_batch = "" # type: str
|
|
|
|
self.users = dict() # type: Dict[str, MatrixUser]
|
2018-01-19 11:36:16 +01:00
|
|
|
self.encrypted = False # type: bool
|
2018-01-05 19:39:11 +01:00
|
|
|
|
|
|
|
|
|
|
|
@utf8_decode
|
|
|
|
def server_config_change_cb(server_name, option):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (str, weechat.config_option) -> int
|
2018-01-05 19:39:11 +01:00
|
|
|
server = SERVERS[server_name]
|
|
|
|
option_name = None
|
|
|
|
|
|
|
|
# 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.
|
2018-01-10 17:09:02 +01:00
|
|
|
option_name = key_from_value(server.options, option)
|
2018-01-26 14:48:34 +01:00
|
|
|
server.update_option(option, option_name, W)
|
2018-01-05 19:39:11 +01:00
|
|
|
|
|
|
|
return 1
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
def wrap_socket(server, file_descriptor):
|
2018-01-05 19:39:11 +01:00
|
|
|
# type: (MatrixServer, int) -> socket.socket
|
2018-01-06 17:12:54 +01:00
|
|
|
sock = None # type: socket.socket
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
temp_socket = socket.fromfd(
|
|
|
|
file_descriptor,
|
|
|
|
socket.AF_INET,
|
|
|
|
socket.SOCK_STREAM
|
|
|
|
)
|
2018-01-03 12:14:24 +01:00
|
|
|
|
2018-01-19 11:36:16 +01:00
|
|
|
# For python 2.7 wrap_socket() doesn't work with sockets created from an
|
|
|
|
# file descriptor because fromfd() doesn't return a wrapped socket, the bug
|
2018-01-24 17:34:07 +01:00
|
|
|
# was fixed for python 3, more info: https://bugs.python.org/issue13942
|
2018-01-23 13:30:42 +01:00
|
|
|
# pylint: disable=protected-access,unidiomatic-typecheck
|
|
|
|
if type(temp_socket) == socket._socket.socket:
|
2018-01-07 15:46:18 +01:00
|
|
|
# pylint: disable=no-member
|
2018-01-06 17:12:54 +01:00
|
|
|
sock = socket._socketobject(_sock=temp_socket)
|
2017-12-30 14:03:03 +01:00
|
|
|
else:
|
2018-01-06 17:12:54 +01:00
|
|
|
sock = temp_socket
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
try:
|
2018-01-06 17:12:54 +01:00
|
|
|
ssl_socket = server.ssl_context.wrap_socket(
|
|
|
|
sock,
|
2018-01-03 12:14:24 +01:00
|
|
|
server_hostname=server.address) # type: ssl.SSLSocket
|
2018-01-06 17:12:54 +01:00
|
|
|
|
2018-01-03 12:14:24 +01:00
|
|
|
return ssl_socket
|
2018-01-19 11:36:16 +01:00
|
|
|
# TODO add finer grained error messages with the subclass exceptions
|
2018-01-06 17:12:54 +01:00
|
|
|
except ssl.SSLError as error:
|
|
|
|
server_buffer_prnt(server, str(error))
|
2018-01-03 12:14:24 +01:00
|
|
|
return None
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
def handle_http_response(server, message):
|
2018-01-05 19:39:11 +01:00
|
|
|
# type: (MatrixServer, MatrixMessage) -> None
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-11 16:21:14 +01:00
|
|
|
assert message.response
|
|
|
|
|
2017-12-30 14:03:03 +01:00
|
|
|
status_code = message.response.status
|
|
|
|
|
2018-01-19 12:43:12 +01:00
|
|
|
def decode_json(server, json_string):
|
2018-01-19 11:36:16 +01:00
|
|
|
try:
|
2018-01-19 12:43:12 +01:00
|
|
|
return json.loads(json_string, encoding='utf-8')
|
2018-01-23 13:30:42 +01:00
|
|
|
except Exception as error:
|
2018-01-19 11:36:16 +01:00
|
|
|
message = ("{prefix}matrix: Error decoding json response from "
|
2018-01-19 12:43:12 +01:00
|
|
|
"server: {error}").format(
|
2018-01-23 13:30:42 +01:00
|
|
|
prefix=W.prefix("error"),
|
|
|
|
error=error)
|
2018-01-19 12:43:12 +01:00
|
|
|
|
2018-01-19 11:36:16 +01:00
|
|
|
W.prnt(server.server_buffer, message)
|
2018-01-19 12:43:12 +01:00
|
|
|
return None
|
|
|
|
|
|
|
|
if status_code == 200:
|
|
|
|
response = decode_json(server, message.response.body)
|
2018-01-19 11:36:16 +01:00
|
|
|
|
2018-01-23 17:21:27 +01:00
|
|
|
# if not response:
|
|
|
|
# # Resend the message
|
|
|
|
# message.response = None
|
|
|
|
# send_or_queue(server, message)
|
|
|
|
# return
|
2018-01-19 11:36:16 +01:00
|
|
|
|
2018-01-12 10:51:37 +01:00
|
|
|
matrix_handle_message(
|
|
|
|
server,
|
|
|
|
message.type,
|
|
|
|
response,
|
|
|
|
message.extra_data
|
|
|
|
)
|
2018-01-19 11:36:16 +01:00
|
|
|
|
|
|
|
# TODO handle try again response
|
|
|
|
elif status_code == 504:
|
2018-01-24 12:41:01 +01:00
|
|
|
if message.type == MessageType.SYNC:
|
|
|
|
matrix_sync(server)
|
|
|
|
|
2018-01-19 12:43:12 +01:00
|
|
|
elif status_code == 403:
|
|
|
|
if message.type == MessageType.LOGIN:
|
|
|
|
response = decode_json(server, message.response.body)
|
|
|
|
reason = ("." if not response or not response["error"] else
|
|
|
|
": {r}.".format(r=response["error"]))
|
|
|
|
|
2018-01-26 12:18:52 +01:00
|
|
|
error_message = ("{prefix}Login error{reason}").format(
|
2018-01-19 12:43:12 +01:00
|
|
|
prefix=W.prefix("error"),
|
|
|
|
reason=reason)
|
2018-01-26 12:18:52 +01:00
|
|
|
server_buffer_prnt(server, error_message)
|
2018-01-19 12:43:12 +01:00
|
|
|
|
|
|
|
W.unhook(server.timer_hook)
|
|
|
|
server.timer_hook = None
|
|
|
|
|
|
|
|
close_socket(server)
|
|
|
|
disconnect(server)
|
2018-01-19 13:24:32 +01:00
|
|
|
elif message.type == MessageType.STATE:
|
|
|
|
response = decode_json(server, message.response.body)
|
|
|
|
reason = ("." if not response or not response["error"] else
|
|
|
|
": {r}.".format(r=response["error"]))
|
|
|
|
|
2018-01-26 12:18:52 +01:00
|
|
|
error_message = ("{prefix}Can't set state{reason}").format(
|
2018-01-19 13:24:32 +01:00
|
|
|
prefix=W.prefix("network"),
|
|
|
|
reason=reason)
|
2018-01-26 12:18:52 +01:00
|
|
|
server_buffer_prnt(server, error_message)
|
2018-01-19 13:24:32 +01:00
|
|
|
else:
|
2018-01-26 12:18:52 +01:00
|
|
|
error_message = ("{prefix}Unhandled 403 error, please inform the "
|
|
|
|
"developers about this: {error}").format(
|
|
|
|
prefix=W.prefix("error"),
|
|
|
|
error=message.response.body)
|
|
|
|
server_buffer_prnt(server, error_message)
|
2018-01-19 13:24:32 +01:00
|
|
|
|
2017-12-30 14:03:03 +01:00
|
|
|
else:
|
2018-01-06 17:12:54 +01:00
|
|
|
server_buffer_prnt(
|
|
|
|
server,
|
2018-01-19 13:24:32 +01:00
|
|
|
("{prefix}Unhandled {status_code} error, please inform "
|
|
|
|
"the developers about this.").format(
|
2018-01-23 13:30:42 +01:00
|
|
|
prefix=W.prefix("error"),
|
|
|
|
status_code=status_code))
|
2018-01-06 17:12:54 +01:00
|
|
|
|
2018-01-19 13:24:32 +01:00
|
|
|
server_buffer_prnt(server, pprint.pformat(message.type))
|
2018-01-19 12:43:12 +01:00
|
|
|
server_buffer_prnt(server, pprint.pformat(message.request.payload))
|
|
|
|
server_buffer_prnt(server, pprint.pformat(message.response.body))
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-24 12:41:01 +01:00
|
|
|
creation_date = datetime.datetime.fromtimestamp(message.creation_time)
|
|
|
|
done_time = time.time()
|
2018-01-26 12:18:52 +01:00
|
|
|
info_message = ("Message of type {t} created at {c}."
|
|
|
|
"\nMessage lifetime information:"
|
|
|
|
"\n Send delay: {s} ms"
|
|
|
|
"\n Receive delay: {r} ms"
|
|
|
|
"\n Handling time: {h} ms"
|
|
|
|
"\n Total time: {total} ms").format(
|
|
|
|
t=message.type,
|
|
|
|
c=creation_date,
|
|
|
|
s=(message.send_time - message.creation_time) * 1000,
|
|
|
|
r=(message.receive_time - message.send_time) * 1000,
|
|
|
|
h=(done_time - message.receive_time) * 1000,
|
|
|
|
total=(done_time - message.creation_time) * 1000,)
|
|
|
|
prnt_debug(DebugType.TIMING, server, info_message)
|
2018-01-24 12:41:01 +01:00
|
|
|
|
2017-12-30 14:03:03 +01:00
|
|
|
return
|
|
|
|
|
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
def strip_matrix_server(string):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (str) -> str
|
2018-01-10 17:09:02 +01:00
|
|
|
return string.rsplit(":", 1)[0]
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
|
2018-01-18 13:35:46 +01:00
|
|
|
def add_user_to_nicklist(buf, 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)
|
|
|
|
# TODO make it configurable so we can use a display name or user_id here
|
|
|
|
W.nicklist_add_nick(
|
|
|
|
buf,
|
|
|
|
group,
|
|
|
|
user.display_name,
|
|
|
|
user.nick_color,
|
|
|
|
user.prefix,
|
|
|
|
get_prefix_color(user.prefix),
|
|
|
|
1
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
def matrix_create_room_buffer(server, room_id):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (MatrixServer, str) -> None
|
2018-01-10 17:09:02 +01:00
|
|
|
buf = W.buffer_new(
|
|
|
|
room_id,
|
|
|
|
"room_input_cb",
|
|
|
|
server.name,
|
|
|
|
"room_close_cb",
|
|
|
|
server.name
|
|
|
|
)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
W.buffer_set(buf, "localvar_set_type", 'channel')
|
2018-01-24 17:34:07 +01:00
|
|
|
W.buffer_set(buf, "type", 'formatted')
|
2018-01-19 08:46:23 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
W.buffer_set(buf, "localvar_set_channel", room_id)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
W.buffer_set(buf, "localvar_set_nick", server.user)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
W.buffer_set(buf, "localvar_set_server", server.name)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
short_name = strip_matrix_server(room_id)
|
|
|
|
W.buffer_set(buf, "short_name", short_name)
|
|
|
|
|
2018-01-18 13:35:46 +01:00
|
|
|
W.nicklist_add_group(buf, '', "000|o", "weechat.color.nicklist_group", 1)
|
|
|
|
W.nicklist_add_group(buf, '', "001|h", "weechat.color.nicklist_group", 1)
|
|
|
|
W.nicklist_add_group(buf, '', "002|v", "weechat.color.nicklist_group", 1)
|
|
|
|
W.nicklist_add_group(buf, '', "999|...", "weechat.color.nicklist_group", 1)
|
2018-01-10 17:09:02 +01:00
|
|
|
|
|
|
|
W.buffer_set(buf, "nicklist", "1")
|
|
|
|
W.buffer_set(buf, "nicklist_display_groups", "0")
|
|
|
|
|
|
|
|
server.buffers[room_id] = buf
|
2018-01-11 16:21:14 +01:00
|
|
|
server.rooms[room_id] = MatrixRoom(room_id)
|
2018-01-10 17:09:02 +01:00
|
|
|
|
|
|
|
|
|
|
|
def matrix_handle_room_aliases(server, room_id, event):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (MatrixServer, str, Dict[str, Any]) -> None
|
2018-01-10 17:09:02 +01:00
|
|
|
buf = server.buffers[room_id]
|
2018-01-11 16:21:14 +01:00
|
|
|
room = server.rooms[room_id]
|
2018-01-10 17:09:02 +01:00
|
|
|
|
|
|
|
alias = event['content']['aliases'][-1]
|
|
|
|
|
|
|
|
if not alias:
|
|
|
|
return
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
short_name = strip_matrix_server(alias)
|
|
|
|
|
2018-01-11 16:21:14 +01:00
|
|
|
room.alias = alias
|
2018-01-10 17:09:02 +01:00
|
|
|
W.buffer_set(buf, "name", alias)
|
|
|
|
W.buffer_set(buf, "short_name", short_name)
|
|
|
|
W.buffer_set(buf, "localvar_set_channel", alias)
|
|
|
|
|
|
|
|
|
|
|
|
def matrix_handle_room_members(server, room_id, event):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (MatrixServer, str, Dict[str, Any]) -> None
|
2018-01-10 17:09:02 +01:00
|
|
|
buf = server.buffers[room_id]
|
2018-01-18 12:31:00 +01:00
|
|
|
room = server.rooms[room_id]
|
2018-01-10 17:09:02 +01:00
|
|
|
|
2018-01-12 10:51:37 +01:00
|
|
|
# TODO print out a informational message
|
2018-01-10 17:09:02 +01:00
|
|
|
if event['membership'] == 'join':
|
2018-01-12 10:51:37 +01:00
|
|
|
# TODO set the buffer type to a channel if we have more than 2 users
|
2018-01-18 12:31:00 +01:00
|
|
|
display_name = event['content']['displayname']
|
|
|
|
full_name = event['sender']
|
|
|
|
short_name = strip_matrix_server(full_name)[1:]
|
|
|
|
|
2018-01-19 11:36:16 +01:00
|
|
|
if not display_name:
|
|
|
|
display_name = short_name
|
|
|
|
|
2018-01-18 12:31:00 +01:00
|
|
|
user = MatrixUser(short_name, display_name)
|
|
|
|
|
|
|
|
if full_name == server.user_id:
|
|
|
|
user.nick_color = "weechat.color.chat_nick_self"
|
|
|
|
W.buffer_set(
|
|
|
|
buf,
|
|
|
|
"highlight_words",
|
|
|
|
",".join([full_name, user.name, user.display_name]))
|
|
|
|
else:
|
|
|
|
user.nick_color = W.info_get("nick_color_name", user.name)
|
|
|
|
|
|
|
|
room.users[full_name] = user
|
|
|
|
|
2018-01-18 13:35:46 +01:00
|
|
|
nick_pointer = W.nicklist_search_nick(buf, "", user.display_name)
|
2018-01-10 17:09:02 +01:00
|
|
|
if not nick_pointer:
|
2018-01-18 13:35:46 +01:00
|
|
|
add_user_to_nicklist(buf, user)
|
|
|
|
else:
|
|
|
|
# TODO we can get duplicate display names
|
|
|
|
pass
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
elif event['membership'] == 'leave':
|
2018-01-18 12:31:00 +01:00
|
|
|
full_name = event['sender']
|
2018-01-19 11:36:16 +01:00
|
|
|
if full_name in room.users:
|
|
|
|
user = room.users[full_name]
|
|
|
|
nick_pointer = W.nicklist_search_nick(buf, "", user.display_name)
|
|
|
|
if nick_pointer:
|
|
|
|
W.nicklist_remove_nick(buf, nick_pointer)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-19 11:36:16 +01:00
|
|
|
del room.users[full_name]
|
2018-01-18 12:31:00 +01:00
|
|
|
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
def date_from_age(age):
|
|
|
|
# type: (float) -> int
|
|
|
|
now = time.time()
|
|
|
|
date = int(now - (age / 1000))
|
|
|
|
return date
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
|
2018-01-18 12:31:00 +01:00
|
|
|
def color_for_tags(color):
|
|
|
|
if color == "weechat.color.chat_nick_self":
|
2018-01-26 17:43:07 +01:00
|
|
|
option = W.config_get(color)
|
|
|
|
return W.config_string(option)
|
2018-01-18 12:31:00 +01:00
|
|
|
return color
|
|
|
|
|
|
|
|
|
2018-01-16 13:23:45 +01:00
|
|
|
def matrix_handle_room_text_message(server, room_id, event, old=False):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (MatrixServer, str, Dict[str, Any], bool) -> None
|
2018-01-16 13:23:45 +01:00
|
|
|
tag = ""
|
2018-01-18 12:31:00 +01:00
|
|
|
msg_author = ""
|
|
|
|
nick_color_name = ""
|
|
|
|
|
|
|
|
room = server.rooms[room_id]
|
2018-01-10 17:09:02 +01:00
|
|
|
msg = event['content']['body']
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-24 17:34:07 +01:00
|
|
|
if 'format' in event['content'] and 'formatted_body' in event['content']:
|
|
|
|
if event['content']['format'] == "org.matrix.custom.html":
|
2018-01-26 12:18:52 +01:00
|
|
|
formatted_data = colors.html_to_formatted(
|
2018-01-24 17:34:07 +01:00
|
|
|
event['content']['formatted_body'])
|
2018-01-26 12:18:52 +01:00
|
|
|
msg = colors.formatted_to_weechat(W, formatted_data)
|
2018-01-24 17:34:07 +01:00
|
|
|
|
2018-01-18 13:35:46 +01:00
|
|
|
if event['sender'] in room.users:
|
2018-01-18 12:31:00 +01:00
|
|
|
user = room.users[event['sender']]
|
|
|
|
msg_author = user.display_name
|
|
|
|
nick_color_name = user.nick_color
|
|
|
|
else:
|
|
|
|
msg_author = strip_matrix_server(event['sender'])[1:]
|
|
|
|
nick_color_name = W.info_get("nick_color_name", msg_author)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
data = "{author}\t{msg}".format(author=msg_author, msg=msg)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
event_id = event['event_id']
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
msg_date = date_from_age(event['unsigned']['age'])
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
# TODO if this is an initial sync tag the messages as backlog
|
2018-01-18 12:31:00 +01:00
|
|
|
# TODO handle self messages from other devices
|
2018-01-16 13:23:45 +01:00
|
|
|
if old:
|
2018-01-18 12:31:00 +01:00
|
|
|
tag = ("nick_{a},prefix_nick_{color},matrix_id_{event_id},"
|
2018-01-16 13:23:45 +01:00
|
|
|
"matrix_message,notify_message,no_log,no_highlight").format(
|
|
|
|
a=msg_author,
|
2018-01-18 12:31:00 +01:00
|
|
|
color=color_for_tags(nick_color_name),
|
2018-01-16 13:23:45 +01:00
|
|
|
event_id=event_id)
|
|
|
|
else:
|
2018-01-18 12:31:00 +01:00
|
|
|
tag = ("nick_{a},prefix_nick_{color},matrix_id_{event_id},"
|
2018-01-16 13:23:45 +01:00
|
|
|
"matrix_message,notify_message,log1").format(
|
|
|
|
a=msg_author,
|
2018-01-18 12:31:00 +01:00
|
|
|
color=color_for_tags(nick_color_name),
|
2018-01-16 13:23:45 +01:00
|
|
|
event_id=event_id)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
buf = server.buffers[room_id]
|
|
|
|
W.prnt_date_tags(buf, msg_date, tag, data)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
def matrix_handle_redacted_message(server, room_id, event):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (MatrixServer, str, Dict[Any, Any]) -> None
|
2018-01-15 11:11:38 +01:00
|
|
|
reason = ""
|
2018-01-18 12:31:00 +01:00
|
|
|
room = server.rooms[room_id]
|
2018-01-17 10:03:14 +01:00
|
|
|
|
|
|
|
# TODO check if the message is already printed out, in that case we got the
|
|
|
|
# message a second time and a redaction event will take care of it.
|
2018-01-18 12:31:00 +01:00
|
|
|
censor = event['unsigned']['redacted_because']['sender']
|
|
|
|
nick_color_name = ""
|
|
|
|
|
|
|
|
if censor in room.users:
|
|
|
|
user = room.users[censor]
|
|
|
|
nick_color_name = user.nick_color
|
|
|
|
censor = ("{nick_color}{nick}{ncolor} {del_color}"
|
|
|
|
"({host_color}{full_name}{ncolor}{del_color})").format(
|
|
|
|
nick_color=W.color(nick_color_name),
|
|
|
|
nick=user.display_name,
|
|
|
|
ncolor=W.color("reset"),
|
|
|
|
del_color=W.color("chat_delimiters"),
|
|
|
|
host_color=W.color("chat_host"),
|
|
|
|
full_name=censor)
|
|
|
|
else:
|
|
|
|
censor = strip_matrix_server(censor)[1:]
|
|
|
|
nick_color_name = W.info_get("nick_color_name", censor)
|
|
|
|
censor = "{color}{censor}{ncolor}".format(
|
|
|
|
color=W.color(nick_color_name),
|
|
|
|
censor=censor,
|
|
|
|
ncolor=W.color("reset"))
|
2018-01-12 16:15:11 +01:00
|
|
|
|
|
|
|
if 'reason' in event['unsigned']['redacted_because']['content']:
|
2018-01-15 11:11:38 +01:00
|
|
|
reason = ", reason: \"{reason}\"".format(
|
2018-01-12 16:15:11 +01:00
|
|
|
reason=event['unsigned']['redacted_because']['content']['reason'])
|
|
|
|
|
2018-01-15 11:11:38 +01:00
|
|
|
msg = ("{del_color}<{log_color}Message redacted by: "
|
|
|
|
"{censor}{log_color}{reason}{del_color}>{ncolor}").format(
|
2018-01-16 13:23:45 +01:00
|
|
|
del_color=W.color("chat_delimiters"),
|
|
|
|
ncolor=W.color("reset"),
|
|
|
|
log_color=W.color("logger.color.backlog_line"),
|
|
|
|
censor=censor,
|
|
|
|
reason=reason)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
msg_author = strip_matrix_server(event['sender'])[1:]
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
data = "{author}\t{msg}".format(author=msg_author, msg=msg)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
event_id = event['event_id']
|
2018-01-05 19:39:11 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
msg_date = date_from_age(event['unsigned']['age'])
|
2018-01-07 16:04:17 +01:00
|
|
|
|
2018-01-18 12:31:00 +01:00
|
|
|
tag = ("nick_{a},prefix_nick_{color},matrix_id_{event_id},"
|
|
|
|
"matrix_message,matrix_redacted,"
|
|
|
|
"notify_message,no_highlight").format(
|
|
|
|
a=msg_author,
|
|
|
|
color=color_for_tags(nick_color_name),
|
|
|
|
event_id=event_id)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
buf = server.buffers[room_id]
|
|
|
|
W.prnt_date_tags(buf, msg_date, tag, data)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
|
2018-01-16 13:23:45 +01:00
|
|
|
def matrix_handle_room_messages(server, room_id, event, old=False):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (MatrixServer, str, Dict[str, Any], bool) -> None
|
2018-01-10 17:09:02 +01:00
|
|
|
if event['type'] == 'm.room.message':
|
|
|
|
if 'redacted_by' in event['unsigned']:
|
|
|
|
matrix_handle_redacted_message(server, room_id, event)
|
|
|
|
return
|
|
|
|
|
|
|
|
if event['content']['msgtype'] == 'm.text':
|
2018-01-16 13:23:45 +01:00
|
|
|
matrix_handle_room_text_message(server, room_id, event, old)
|
2018-01-10 17:09:02 +01:00
|
|
|
|
|
|
|
# TODO handle different content types here
|
|
|
|
else:
|
|
|
|
message = ("{prefix}Handling of content type "
|
|
|
|
"{type} not implemented").format(
|
2018-01-11 16:21:14 +01:00
|
|
|
type=event['content']['msgtype'],
|
2018-01-10 17:09:02 +01:00
|
|
|
prefix=W.prefix("error"))
|
|
|
|
W.prnt(server.server_buffer, message)
|
|
|
|
|
2018-01-11 16:21:14 +01:00
|
|
|
|
2018-01-17 10:03:14 +01:00
|
|
|
def event_id_from_tags(tags):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (List[str]) -> str
|
2018-01-17 10:03:14 +01:00
|
|
|
for tag in tags:
|
|
|
|
if tag.startswith("matrix_id"):
|
|
|
|
return tag[10:]
|
|
|
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
2018-01-24 17:34:07 +01:00
|
|
|
def string_strikethrough(string):
|
|
|
|
return "".join(["{}\u0336".format(c) for c in string])
|
|
|
|
|
|
|
|
|
2018-01-17 10:03:14 +01:00
|
|
|
def matrix_redact_line(data, tags, event):
|
|
|
|
reason = ""
|
|
|
|
|
|
|
|
hdata_line_data = W.hdata_get('line_data')
|
|
|
|
|
|
|
|
message = W.hdata_string(hdata_line_data, data, 'message')
|
|
|
|
censor = strip_matrix_server(event['sender'])[1:]
|
|
|
|
|
|
|
|
if 'reason' in event['content']:
|
|
|
|
reason = ", reason: \"{reason}\"".format(
|
|
|
|
reason=event['content']['reason'])
|
|
|
|
|
|
|
|
redaction_msg = ("{del_color}<{log_color}Message redacted by: "
|
|
|
|
"{censor}{log_color}{reason}{del_color}>{ncolor}").format(
|
|
|
|
del_color=W.color("chat_delimiters"),
|
|
|
|
ncolor=W.color("reset"),
|
|
|
|
log_color=W.color("logger.color.backlog_line"),
|
|
|
|
censor=censor,
|
|
|
|
reason=reason)
|
|
|
|
|
|
|
|
if GLOBAL_OPTIONS.redaction_type == RedactType.STRIKETHROUGH:
|
2018-01-24 17:34:07 +01:00
|
|
|
message = string_strikethrough(message)
|
2018-01-17 10:03:14 +01:00
|
|
|
message = message + " " + redaction_msg
|
|
|
|
elif GLOBAL_OPTIONS.redaction_type == RedactType.DELETE:
|
|
|
|
message = redaction_msg
|
|
|
|
elif GLOBAL_OPTIONS.redaction_type == RedactType.NOTICE:
|
|
|
|
message = message + " " + redaction_msg
|
|
|
|
|
|
|
|
tags.append("matrix_new_redacted")
|
|
|
|
|
|
|
|
new_data = {'tags_array': tags,
|
|
|
|
'message': message}
|
|
|
|
|
|
|
|
W.hdata_update(hdata_line_data, data, new_data)
|
|
|
|
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
|
|
|
def matrix_handle_room_redaction(server, room_id, event):
|
|
|
|
buf = server.buffers[room_id]
|
|
|
|
event_id = event['redacts']
|
|
|
|
|
|
|
|
own_lines = W.hdata_pointer(W.hdata_get('buffer'), buf, 'own_lines')
|
|
|
|
|
|
|
|
if own_lines:
|
|
|
|
hdata_line = W.hdata_get('line')
|
|
|
|
|
|
|
|
line = W.hdata_pointer(
|
|
|
|
W.hdata_get('lines'),
|
|
|
|
own_lines,
|
|
|
|
'last_line'
|
|
|
|
)
|
|
|
|
|
|
|
|
while line:
|
|
|
|
data = W.hdata_pointer(hdata_line, line, 'data')
|
|
|
|
|
|
|
|
if data:
|
|
|
|
tags = tags_from_line_data(data)
|
|
|
|
|
|
|
|
message_id = event_id_from_tags(tags)
|
|
|
|
|
|
|
|
if event_id == message_id:
|
|
|
|
# If the message is already redacted there is nothing to do
|
|
|
|
if ("matrix_redacted" not in tags and
|
|
|
|
"matrix_new_redacted" not in tags):
|
|
|
|
matrix_redact_line(data, tags, event)
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
line = W.hdata_move(hdata_line, line, -1)
|
|
|
|
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
2018-01-18 12:31:00 +01:00
|
|
|
def get_prefix_for_level(level):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (int) -> str
|
2018-01-18 12:31:00 +01:00
|
|
|
if level >= 100:
|
|
|
|
return "&"
|
|
|
|
elif level >= 50:
|
|
|
|
return "@"
|
|
|
|
elif level > 0:
|
|
|
|
return "+"
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
2018-01-18 13:35:46 +01:00
|
|
|
# TODO make this configurable
|
2018-01-18 12:31:00 +01:00
|
|
|
def get_prefix_color(prefix):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (str) -> str
|
2018-01-18 12:31:00 +01:00
|
|
|
if prefix == "&":
|
|
|
|
return "lightgreen"
|
|
|
|
elif prefix == "@":
|
|
|
|
return "lightgreen"
|
|
|
|
elif prefix == "+":
|
|
|
|
return "yellow"
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
def matrix_handle_room_power_levels(server, room_id, event):
|
|
|
|
if not event['content']['users']:
|
|
|
|
return
|
|
|
|
|
|
|
|
buf = server.buffers[room_id]
|
|
|
|
room = server.rooms[room_id]
|
|
|
|
|
|
|
|
for full_name, level in event['content']['users'].items():
|
|
|
|
if full_name not in room.users:
|
|
|
|
continue
|
|
|
|
|
|
|
|
user = room.users[full_name]
|
|
|
|
user.power_level = level
|
|
|
|
user.prefix = get_prefix_for_level(level)
|
|
|
|
|
2018-01-18 13:35:46 +01:00
|
|
|
nick_pointer = W.nicklist_search_nick(buf, "", user.display_name)
|
|
|
|
W.nicklist_remove_nick(buf, nick_pointer)
|
|
|
|
add_user_to_nicklist(buf, user)
|
2018-01-18 12:31:00 +01:00
|
|
|
|
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
def matrix_handle_room_events(server, room_id, room_events):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (MatrixServer, str, Dict[Any, Any]) -> None
|
2018-01-10 17:09:02 +01:00
|
|
|
for event in room_events:
|
2018-01-11 11:30:41 +01:00
|
|
|
if event['event_id'] in server.ignore_event_list:
|
|
|
|
server.ignore_event_list.remove(event['event_id'])
|
|
|
|
continue
|
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
if event['type'] == 'm.room.aliases':
|
|
|
|
matrix_handle_room_aliases(server, room_id, event)
|
|
|
|
|
|
|
|
elif event['type'] == 'm.room.member':
|
|
|
|
matrix_handle_room_members(server, room_id, event)
|
|
|
|
|
|
|
|
elif event['type'] == 'm.room.message':
|
|
|
|
matrix_handle_room_messages(server, room_id, event)
|
|
|
|
|
2018-01-11 16:21:14 +01:00
|
|
|
elif event['type'] == 'm.room.topic':
|
|
|
|
buf = server.buffers[room_id]
|
|
|
|
room = server.rooms[room_id]
|
|
|
|
topic = event['content']['topic']
|
|
|
|
|
|
|
|
room.topic = topic
|
|
|
|
room.topic_author = event['sender']
|
|
|
|
|
|
|
|
topic_age = event['unsigned']['age']
|
|
|
|
room.topic_date = datetime.datetime.fromtimestamp(
|
|
|
|
time.time() - (topic_age / 1000))
|
|
|
|
|
|
|
|
W.buffer_set(buf, "title", topic)
|
|
|
|
|
2018-01-18 12:31:00 +01:00
|
|
|
nick_color = W.info_get("nick_color_name", room.topic_author)
|
|
|
|
author = room.topic_author
|
|
|
|
|
|
|
|
if author in room.users:
|
|
|
|
user = room.users[author]
|
|
|
|
nick_color = user.nick_color
|
|
|
|
author = user.display_name
|
|
|
|
|
|
|
|
author = ("{nick_color}{user}{ncolor}").format(
|
|
|
|
nick_color=W.color(nick_color),
|
|
|
|
user=author,
|
|
|
|
ncolor=W.color("reset"))
|
|
|
|
|
2018-01-11 16:21:14 +01:00
|
|
|
# TODO print old topic if configured so
|
|
|
|
# TODO nick display name if configured so and found
|
2018-01-18 12:31:00 +01:00
|
|
|
message = ("{prefix}{nick} has changed "
|
|
|
|
"the topic for {chan_color}{room}{ncolor} "
|
|
|
|
"to \"{topic}\"").format(
|
2018-01-11 16:21:14 +01:00
|
|
|
prefix=W.prefix("network"),
|
2018-01-18 12:31:00 +01:00
|
|
|
nick=author,
|
|
|
|
chan_color=W.color("chat_channel"),
|
|
|
|
ncolor=W.color("reset"),
|
|
|
|
room=strip_matrix_server(room.alias),
|
2018-01-11 16:21:14 +01:00
|
|
|
topic=topic)
|
|
|
|
|
2018-01-18 12:31:00 +01:00
|
|
|
tags = "matrix_topic,no_highlight,log3,matrix_id_{event_id}".format(
|
2018-01-17 10:04:26 +01:00
|
|
|
event_id=event['event_id'])
|
|
|
|
|
2018-01-16 13:23:45 +01:00
|
|
|
date = date_from_age(topic_age)
|
2018-01-11 16:21:14 +01:00
|
|
|
|
|
|
|
W.prnt_date_tags(buf, date, tags, message)
|
|
|
|
|
2018-01-12 16:15:11 +01:00
|
|
|
elif event['type'] == "m.room.redaction":
|
2018-01-17 10:03:14 +01:00
|
|
|
matrix_handle_room_redaction(server, room_id, event)
|
2018-01-12 16:15:11 +01:00
|
|
|
|
2018-01-18 12:31:00 +01:00
|
|
|
elif event["type"] == "m.room.power_levels":
|
|
|
|
matrix_handle_room_power_levels(server, room_id, event)
|
|
|
|
|
2018-01-19 11:36:16 +01:00
|
|
|
# These events are unimportant for us.
|
2018-01-18 13:35:46 +01:00
|
|
|
elif event["type"] in ["m.room.create", "m.room.join_rules",
|
|
|
|
"m.room.history_visibility",
|
2018-01-19 11:36:16 +01:00
|
|
|
"m.room.canonical_alias",
|
|
|
|
"m.room.guest_access",
|
|
|
|
"m.room.third_party_invite"]:
|
|
|
|
pass
|
|
|
|
|
|
|
|
elif event["type"] == "m.room.name":
|
|
|
|
buf = server.buffers[room_id]
|
|
|
|
room = server.rooms[room_id]
|
|
|
|
|
|
|
|
name = event['content']['name']
|
|
|
|
|
|
|
|
if not name:
|
|
|
|
return
|
|
|
|
|
|
|
|
room.alias = name
|
|
|
|
W.buffer_set(buf, "name", name)
|
|
|
|
W.buffer_set(buf, "short_name", name)
|
|
|
|
W.buffer_set(buf, "localvar_set_channel", name)
|
|
|
|
|
|
|
|
elif event["type"] == "m.room.encryption":
|
|
|
|
buf = server.buffers[room_id]
|
|
|
|
room = server.rooms[room_id]
|
|
|
|
room.encrypted = True
|
|
|
|
message = ("{prefix}This room is encrypted, encryption is "
|
|
|
|
"currently unsuported. Message sending is disabled for "
|
|
|
|
"this room.").format(prefix=W.prefix("error"))
|
|
|
|
W.prnt(buf, message)
|
|
|
|
|
|
|
|
# TODO implement message decryption
|
|
|
|
elif event["type"] == "m.room.encrypted":
|
2018-01-18 13:35:46 +01:00
|
|
|
pass
|
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
else:
|
2018-01-16 13:23:45 +01:00
|
|
|
message = ("{prefix}Handling of room event type "
|
2018-01-10 17:09:02 +01:00
|
|
|
"{type} not implemented").format(
|
|
|
|
type=event['type'],
|
|
|
|
prefix=W.prefix("error"))
|
|
|
|
W.prnt(server.server_buffer, message)
|
|
|
|
|
|
|
|
|
2018-01-23 16:11:42 +01:00
|
|
|
def matrix_handle_invite_events(server, room_id, events):
|
|
|
|
# type: (MatrixServer, str, List[Dict[str, Any]]) -> None
|
|
|
|
for event in events:
|
|
|
|
if event["type"] != "m.room.member":
|
|
|
|
continue
|
|
|
|
|
|
|
|
if 'membership' not in event:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if event["membership"] == "invite":
|
|
|
|
sender = event["sender"]
|
|
|
|
# TODO does this go to the server buffer or to the channel buffer?
|
|
|
|
message = ("{prefix}You have been invited to {chan_color}{channel}"
|
|
|
|
"{ncolor} by {nick_color}{nick}{ncolor}").format(
|
2018-01-25 13:39:48 +01:00
|
|
|
prefix=W.prefix("network"),
|
|
|
|
chan_color=W.color("chat_channel"),
|
|
|
|
channel=room_id,
|
|
|
|
ncolor=W.color("reset"),
|
|
|
|
nick_color=W.color("chat_nick"),
|
|
|
|
nick=sender)
|
2018-01-23 16:11:42 +01:00
|
|
|
W.prnt(server.server_buffer, message)
|
|
|
|
|
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
def matrix_handle_room_info(server, room_info):
|
|
|
|
# type: (MatrixServer, Dict) -> None
|
2018-01-23 13:30:42 +01:00
|
|
|
for room_id, room in room_info['join'].items():
|
2018-01-10 17:09:02 +01:00
|
|
|
if not room_id:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if room_id not in server.buffers:
|
|
|
|
matrix_create_room_buffer(server, room_id)
|
|
|
|
|
2018-01-16 13:23:45 +01:00
|
|
|
if not server.rooms[room_id].prev_batch:
|
|
|
|
server.rooms[room_id].prev_batch = room['timeline']['prev_batch']
|
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
matrix_handle_room_events(server, room_id, room['state']['events'])
|
|
|
|
matrix_handle_room_events(server, room_id, room['timeline']['events'])
|
|
|
|
|
2018-01-23 16:11:42 +01:00
|
|
|
for room_id, room in room_info['invite'].items():
|
|
|
|
matrix_handle_invite_events(
|
|
|
|
server,
|
|
|
|
room_id,
|
|
|
|
room['invite_state']['events']
|
|
|
|
)
|
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
|
2018-01-16 13:23:45 +01:00
|
|
|
def matrix_sort_old_messages(server, room_id):
|
|
|
|
lines = []
|
|
|
|
buf = server.buffers[room_id]
|
|
|
|
|
|
|
|
own_lines = W.hdata_pointer(W.hdata_get('buffer'), buf, 'own_lines')
|
|
|
|
|
|
|
|
if own_lines:
|
|
|
|
hdata_line = W.hdata_get('line')
|
|
|
|
hdata_line_data = W.hdata_get('line_data')
|
|
|
|
line = W.hdata_pointer(
|
|
|
|
W.hdata_get('lines'),
|
|
|
|
own_lines,
|
|
|
|
'first_line'
|
|
|
|
)
|
|
|
|
|
|
|
|
while line:
|
|
|
|
data = W.hdata_pointer(hdata_line, line, 'data')
|
|
|
|
|
|
|
|
line_data = {}
|
|
|
|
|
|
|
|
if data:
|
|
|
|
date = W.hdata_time(hdata_line_data, data, 'date')
|
|
|
|
print_date = W.hdata_time(hdata_line_data, data,
|
|
|
|
'date_printed')
|
|
|
|
tags = tags_from_line_data(data)
|
|
|
|
prefix = W.hdata_string(hdata_line_data, data, 'prefix')
|
|
|
|
message = W.hdata_string(hdata_line_data, data,
|
|
|
|
'message')
|
|
|
|
|
|
|
|
line_data = {'date': date,
|
|
|
|
'date_printed': print_date,
|
|
|
|
'tags_array': ','.join(tags),
|
|
|
|
'prefix': prefix,
|
|
|
|
'message': message}
|
|
|
|
|
|
|
|
lines.append(line_data)
|
|
|
|
|
|
|
|
line = W.hdata_move(hdata_line, line, 1)
|
|
|
|
|
|
|
|
sorted_lines = sorted(lines, key=itemgetter('date'))
|
|
|
|
lines = []
|
|
|
|
|
|
|
|
# We need to convert the dates to a string for hdata_update(), this
|
|
|
|
# will reverse the list at the same time
|
|
|
|
while sorted_lines:
|
|
|
|
line = sorted_lines.pop()
|
2018-01-23 13:30:42 +01:00
|
|
|
new_line = {k: str(v) for k, v in line.items()}
|
2018-01-16 13:23:45 +01:00
|
|
|
lines.append(new_line)
|
|
|
|
|
|
|
|
matrix_update_buffer_lines(lines, own_lines)
|
|
|
|
|
|
|
|
|
|
|
|
def matrix_update_buffer_lines(new_lines, own_lines):
|
|
|
|
hdata_line = W.hdata_get('line')
|
|
|
|
hdata_line_data = W.hdata_get('line_data')
|
|
|
|
|
|
|
|
line = W.hdata_pointer(
|
|
|
|
W.hdata_get('lines'),
|
|
|
|
own_lines,
|
|
|
|
'first_line'
|
|
|
|
)
|
|
|
|
|
|
|
|
while line:
|
|
|
|
data = W.hdata_pointer(hdata_line, line, 'data')
|
|
|
|
|
|
|
|
if data:
|
|
|
|
W.hdata_update(hdata_line_data, data, new_lines.pop())
|
|
|
|
|
|
|
|
line = W.hdata_move(hdata_line, line, 1)
|
|
|
|
|
|
|
|
|
|
|
|
def matrix_handle_old_messages(server, room_id, events):
|
|
|
|
for event in events:
|
|
|
|
if event['type'] == 'm.room.message':
|
|
|
|
matrix_handle_room_messages(server, room_id, event, old=True)
|
|
|
|
# TODO do we wan't to handle topics joins/quits here?
|
|
|
|
else:
|
|
|
|
pass
|
|
|
|
|
|
|
|
matrix_sort_old_messages(server, room_id)
|
|
|
|
|
|
|
|
|
2018-01-12 10:51:37 +01:00
|
|
|
def matrix_handle_message(
|
|
|
|
server, # type: MatrixServer
|
|
|
|
message_type, # type: MessageType
|
2018-01-23 13:30:42 +01:00
|
|
|
response, # type: Dict[str, Any]
|
|
|
|
extra_data # type: Dict[str, Any]
|
2018-01-12 10:51:37 +01:00
|
|
|
):
|
|
|
|
# type: (...) -> None
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
if message_type is MessageType.LOGIN:
|
|
|
|
server.access_token = response["access_token"]
|
2018-01-18 12:31:00 +01:00
|
|
|
server.user_id = response["user_id"]
|
2018-01-26 14:38:46 +01:00
|
|
|
message = MatrixMessage(server, GLOBAL_OPTIONS, MessageType.SYNC)
|
2018-01-05 19:39:11 +01:00
|
|
|
send_or_queue(server, message)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
elif message_type is MessageType.SYNC:
|
|
|
|
next_batch = response['next_batch']
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
# we got the same batch again, nothing to do
|
2018-01-05 19:39:11 +01:00
|
|
|
if next_batch == server.next_batch:
|
2018-01-24 12:41:01 +01:00
|
|
|
matrix_sync(server)
|
2017-12-30 14:03:03 +01:00
|
|
|
return
|
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
room_info = response['rooms']
|
2018-01-10 17:09:02 +01:00
|
|
|
matrix_handle_room_info(server, room_info)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-05 19:39:11 +01:00
|
|
|
server.next_batch = next_batch
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-24 12:41:01 +01:00
|
|
|
# TODO add a delay to this
|
|
|
|
matrix_sync(server)
|
|
|
|
|
2018-01-11 16:21:14 +01:00
|
|
|
elif message_type is MessageType.SEND:
|
2018-01-11 11:30:41 +01:00
|
|
|
author = extra_data["author"]
|
|
|
|
message = extra_data["message"]
|
|
|
|
room_id = extra_data["room_id"]
|
|
|
|
date = int(time.time())
|
2018-01-25 12:33:50 +01:00
|
|
|
# TODO the event_id can be missing if sending has failed for
|
|
|
|
# some reason
|
2018-01-11 11:30:41 +01:00
|
|
|
event_id = response["event_id"]
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-11 11:30:41 +01:00
|
|
|
# This message will be part of the next sync, we already printed it out
|
|
|
|
# so ignore it in the sync.
|
|
|
|
server.ignore_event_list.append(event_id)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-18 12:31:00 +01:00
|
|
|
tag = ("notify_none,no_highlight,self_msg,log1,nick_{a},"
|
|
|
|
"prefix_nick_{color},matrix_id_{event_id},"
|
|
|
|
"matrix_message").format(
|
|
|
|
a=author,
|
2018-01-19 12:43:12 +01:00
|
|
|
color=color_for_tags("weechat.color.chat_nick_self"),
|
2018-01-18 12:31:00 +01:00
|
|
|
event_id=event_id)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-11 11:30:41 +01:00
|
|
|
data = "{author}\t{msg}".format(author=author, msg=message)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-11 11:30:41 +01:00
|
|
|
buf = server.buffers[room_id]
|
|
|
|
W.prnt_date_tags(buf, date, tag, data)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-16 13:23:45 +01:00
|
|
|
elif message_type == MessageType.ROOM_MSG:
|
|
|
|
# Response has no messages, that is we already got the oldest message
|
|
|
|
# in a previous request, nothing to do
|
|
|
|
if not response['chunk']:
|
|
|
|
return
|
|
|
|
|
|
|
|
room_id = response['chunk'][0]['room_id']
|
|
|
|
room = server.rooms[room_id]
|
|
|
|
|
|
|
|
matrix_handle_old_messages(server, room_id, response['chunk'])
|
|
|
|
|
|
|
|
room.prev_batch = response['end']
|
|
|
|
|
2018-01-12 16:15:11 +01:00
|
|
|
# Nothing to do here, we'll handle state changes and redactions in the sync
|
|
|
|
elif (message_type == MessageType.STATE or
|
|
|
|
message_type == MessageType.REDACT):
|
2018-01-11 16:21:14 +01:00
|
|
|
pass
|
|
|
|
|
2017-12-30 14:03:03 +01:00
|
|
|
else:
|
2018-01-11 11:30:41 +01:00
|
|
|
server_buffer_prnt(
|
|
|
|
server,
|
|
|
|
"Handling of message type {type} not implemented".format(
|
|
|
|
type=message_type))
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
|
2018-01-24 12:41:01 +01:00
|
|
|
def matrix_sync(server):
|
2018-01-26 14:38:46 +01:00
|
|
|
message = MatrixMessage(server, GLOBAL_OPTIONS, MessageType.SYNC)
|
2018-01-24 12:41:01 +01:00
|
|
|
server.send_queue.append(message)
|
|
|
|
|
|
|
|
|
2018-01-03 12:14:24 +01:00
|
|
|
def matrix_login(server):
|
2018-01-05 19:39:11 +01:00
|
|
|
# type: (MatrixServer) -> None
|
2018-01-10 17:09:02 +01:00
|
|
|
post_data = {"type": "m.login.password",
|
|
|
|
"user": server.user,
|
2018-01-25 13:15:21 +01:00
|
|
|
"password": server.password,
|
|
|
|
"initial_device_display_name": server.device_name}
|
2018-01-10 17:09:02 +01:00
|
|
|
|
2018-01-11 11:30:41 +01:00
|
|
|
message = MatrixMessage(
|
2018-01-10 17:09:02 +01:00
|
|
|
server,
|
2018-01-26 14:38:46 +01:00
|
|
|
GLOBAL_OPTIONS,
|
2018-01-10 17:09:02 +01:00
|
|
|
MessageType.LOGIN,
|
|
|
|
data=post_data
|
|
|
|
)
|
2018-01-05 19:39:11 +01:00
|
|
|
send_or_queue(server, message)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
@utf8_decode
|
2018-01-06 17:12:54 +01:00
|
|
|
def receive_cb(server_name, file_descriptor):
|
2018-01-05 19:39:11 +01:00
|
|
|
server = SERVERS[server_name]
|
|
|
|
|
2017-12-30 14:03:03 +01:00
|
|
|
while True:
|
|
|
|
try:
|
2018-01-05 19:39:11 +01:00
|
|
|
data = server.socket.recv(4096)
|
2017-12-30 14:03:03 +01:00
|
|
|
except ssl.SSLWantReadError:
|
|
|
|
break
|
2018-01-06 17:12:54 +01:00
|
|
|
except socket.error as error:
|
2018-01-05 19:39:11 +01:00
|
|
|
disconnect(server)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
# Queue the failed message for resending
|
2018-01-24 12:41:01 +01:00
|
|
|
if server.receive_queue:
|
|
|
|
message = server.receive_queue.popleft()
|
|
|
|
server.send_queue.appendleft(message)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-25 12:33:50 +01:00
|
|
|
server_buffer_prnt(server, pprint.pformat(error))
|
2018-01-06 17:12:54 +01:00
|
|
|
return W.WEECHAT_RC_OK
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
if not data:
|
2018-01-05 19:39:11 +01:00
|
|
|
server_buffer_prnt(server, "No data while reading")
|
2018-01-24 12:41:01 +01:00
|
|
|
|
|
|
|
# Queue the failed message for resending
|
|
|
|
if server.receive_queue:
|
|
|
|
message = server.receive_queue.popleft()
|
|
|
|
server.send_queue.appendleft(message)
|
|
|
|
|
2018-01-05 19:39:11 +01:00
|
|
|
disconnect(server)
|
2017-12-30 14:03:03 +01:00
|
|
|
break
|
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
received = len(data) # type: int
|
|
|
|
parsed_bytes = server.http_parser.execute(data, received)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
assert parsed_bytes == received
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
if server.http_parser.is_partial_body():
|
|
|
|
server.http_buffer.append(server.http_parser.recv_body())
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
if server.http_parser.is_message_complete():
|
|
|
|
status = server.http_parser.get_status_code()
|
|
|
|
headers = server.http_parser.get_headers()
|
|
|
|
body = b"".join(server.http_buffer)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
message = server.receive_queue.popleft()
|
2017-12-30 14:03:03 +01:00
|
|
|
message.response = HttpResponse(status, headers, body)
|
2018-01-24 12:41:01 +01:00
|
|
|
receive_time = time.time()
|
|
|
|
message.receive_time = receive_time
|
|
|
|
|
|
|
|
prnt_debug(DebugType.MESSAGING, server,
|
|
|
|
("{prefix}Received message of type {t} and "
|
|
|
|
"status {s}").format(
|
|
|
|
prefix=W.prefix("error"),
|
|
|
|
t=message.type,
|
|
|
|
s=status))
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
# Message done, reset the parser state.
|
2018-01-26 14:38:46 +01:00
|
|
|
server.reset_parser()
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
handle_http_response(server, message)
|
2017-12-30 14:03:03 +01:00
|
|
|
break
|
|
|
|
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
2018-01-19 12:43:12 +01:00
|
|
|
def close_socket(server):
|
|
|
|
# type: (MatrixServer) -> None
|
|
|
|
server.socket.shutdown(socket.SHUT_RDWR)
|
|
|
|
server.socket.close()
|
|
|
|
|
|
|
|
|
2018-01-11 16:21:14 +01:00
|
|
|
def server_buffer_set_title(server):
|
|
|
|
# type: (MatrixServer) -> None
|
|
|
|
if server.numeric_address:
|
|
|
|
ip_string = " ({address})".format(address=server.numeric_address)
|
|
|
|
else:
|
|
|
|
ip_string = ""
|
|
|
|
|
|
|
|
title = ("Matrix: {address}/{port}{ip}").format(
|
|
|
|
address=server.address,
|
|
|
|
port=server.port,
|
|
|
|
ip=ip_string)
|
|
|
|
|
|
|
|
W.buffer_set(server.server_buffer, "title", title)
|
|
|
|
|
|
|
|
|
2018-01-03 12:14:24 +01:00
|
|
|
def create_server_buffer(server):
|
|
|
|
# type: (MatrixServer) -> None
|
|
|
|
server.server_buffer = W.buffer_new(
|
|
|
|
server.name,
|
|
|
|
"server_buffer_cb",
|
2018-01-05 19:39:11 +01:00
|
|
|
server.name,
|
2018-01-03 12:14:24 +01:00
|
|
|
"",
|
|
|
|
""
|
|
|
|
)
|
|
|
|
|
2018-01-11 16:21:14 +01:00
|
|
|
server_buffer_set_title(server)
|
2018-01-05 19:39:11 +01:00
|
|
|
W.buffer_set(server.server_buffer, "localvar_set_type", 'server')
|
2018-01-10 17:09:02 +01:00
|
|
|
W.buffer_set(server.server_buffer, "localvar_set_nick", server.user)
|
2018-01-05 19:39:11 +01:00
|
|
|
W.buffer_set(server.server_buffer, "localvar_set_server", server.name)
|
|
|
|
W.buffer_set(server.server_buffer, "localvar_set_channel", server.name)
|
2018-01-03 12:14:24 +01:00
|
|
|
|
2018-01-12 10:51:37 +01:00
|
|
|
# TODO merge without core
|
|
|
|
if GLOBAL_OPTIONS.look_server_buf == ServerBufferType.MERGE_CORE:
|
2018-01-05 19:39:11 +01:00
|
|
|
W.buffer_merge(server.server_buffer, W.buffer_search_main())
|
2018-01-12 10:51:37 +01:00
|
|
|
elif GLOBAL_OPTIONS.look_server_buf == ServerBufferType.MERGE:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
pass
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
@utf8_decode
|
|
|
|
def connect_cb(data, status, gnutls_rc, sock, error, ip_address):
|
2018-01-07 16:04:17 +01:00
|
|
|
# pylint: disable=too-many-arguments,too-many-branches
|
2018-01-09 12:42:06 +01:00
|
|
|
status_value = int(status) # type: int
|
2018-01-03 12:14:24 +01:00
|
|
|
server = SERVERS[data]
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
if status_value == W.WEECHAT_HOOK_CONNECT_OK:
|
2018-01-06 17:12:54 +01:00
|
|
|
file_descriptor = int(sock) # type: int
|
|
|
|
sock = wrap_socket(server, file_descriptor)
|
|
|
|
|
|
|
|
if sock:
|
|
|
|
server.socket = sock
|
|
|
|
hook = W.hook_fd(
|
|
|
|
server.socket.fileno(),
|
|
|
|
1, 0, 0,
|
|
|
|
"receive_cb",
|
|
|
|
server.name
|
|
|
|
)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-07 15:46:18 +01:00
|
|
|
server.fd_hook = hook
|
|
|
|
server.connected = True
|
|
|
|
server.connecting = False
|
|
|
|
server.reconnect_count = 0
|
2018-01-11 16:21:14 +01:00
|
|
|
server.numeric_address = ip_address
|
2018-01-03 12:14:24 +01:00
|
|
|
|
2018-01-11 16:21:14 +01:00
|
|
|
server_buffer_set_title(server)
|
2018-01-05 19:39:11 +01:00
|
|
|
server_buffer_prnt(server, "Connected")
|
2018-01-03 12:14:24 +01:00
|
|
|
|
|
|
|
if not server.access_token:
|
|
|
|
matrix_login(server)
|
2017-12-30 14:03:03 +01:00
|
|
|
else:
|
2018-01-05 19:39:11 +01:00
|
|
|
reconnect(server)
|
2018-01-19 11:36:16 +01:00
|
|
|
return W.WEECHAT_RC_OK
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
elif status_value == W.WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND:
|
2018-01-19 11:36:16 +01:00
|
|
|
W.prnt(
|
|
|
|
server.server_buffer,
|
|
|
|
'{address} not found'.format(address=ip_address)
|
|
|
|
)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
elif status_value == W.WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND:
|
2018-01-19 11:36:16 +01:00
|
|
|
W.prnt(server.server_buffer, 'IP address not found')
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
elif status_value == W.WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED:
|
2018-01-19 11:36:16 +01:00
|
|
|
W.prnt(server.server_buffer, 'Connection refused')
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
elif status_value == W.WEECHAT_HOOK_CONNECT_PROXY_ERROR:
|
2018-01-19 11:36:16 +01:00
|
|
|
W.prnt(
|
|
|
|
server.server_buffer,
|
|
|
|
'Proxy fails to establish connection to server'
|
|
|
|
)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
elif status_value == W.WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR:
|
2018-01-19 11:36:16 +01:00
|
|
|
W.prnt(server.server_buffer, 'Unable to set local hostname')
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
elif status_value == W.WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR:
|
2018-01-19 11:36:16 +01:00
|
|
|
W.prnt(server.server_buffer, 'TLS init error')
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
elif status_value == W.WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR:
|
2018-01-19 11:36:16 +01:00
|
|
|
W.prnt(server.server_buffer, 'TLS Handshake failed')
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
elif status_value == W.WEECHAT_HOOK_CONNECT_MEMORY_ERROR:
|
2018-01-19 11:36:16 +01:00
|
|
|
W.prnt(server.server_buffer, 'Not enough memory')
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
elif status_value == W.WEECHAT_HOOK_CONNECT_TIMEOUT:
|
2018-01-19 11:36:16 +01:00
|
|
|
W.prnt(server.server_buffer, 'Timeout')
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
elif status_value == W.WEECHAT_HOOK_CONNECT_SOCKET_ERROR:
|
2018-01-19 11:36:16 +01:00
|
|
|
W.prnt(server.server_buffer, 'Unable to create socket')
|
2017-12-30 14:03:03 +01:00
|
|
|
else:
|
2018-01-19 11:36:16 +01:00
|
|
|
W.prnt(
|
|
|
|
server.server_buffer,
|
|
|
|
'Unexpected error: {status}'.format(status=status_value)
|
|
|
|
)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-19 11:36:16 +01:00
|
|
|
reconnect(server)
|
2017-12-30 14:03:03 +01:00
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
2018-01-05 19:39:11 +01:00
|
|
|
def reconnect(server):
|
|
|
|
# type: (MatrixServer) -> None
|
2018-01-07 15:46:18 +01:00
|
|
|
server.connecting = True
|
2018-01-06 17:12:54 +01:00
|
|
|
timeout = server.reconnect_count * 5 * 1000
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
if timeout > 0:
|
2018-01-06 17:12:54 +01:00
|
|
|
server_buffer_prnt(
|
|
|
|
server,
|
|
|
|
"Reconnecting in {timeout} seconds.".format(
|
|
|
|
timeout=timeout / 1000))
|
2018-01-05 19:39:11 +01:00
|
|
|
W.hook_timer(timeout, 0, 1, "reconnect_cb", server.name)
|
2017-12-30 14:03:03 +01:00
|
|
|
else:
|
2018-01-05 19:39:11 +01:00
|
|
|
connect(server)
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
server.reconnect_count += 1
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
@utf8_decode
|
2018-01-05 19:39:11 +01:00
|
|
|
def reconnect_cb(server_name, remaining):
|
|
|
|
server = SERVERS[server_name]
|
|
|
|
connect(server)
|
|
|
|
|
2017-12-30 14:03:03 +01:00
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
2018-01-05 19:39:11 +01:00
|
|
|
def connect(server):
|
2018-01-23 13:30:42 +01:00
|
|
|
# type: (MatrixServer) -> int
|
2018-01-05 19:39:11 +01:00
|
|
|
if not server.address or not server.port:
|
|
|
|
message = "{prefix}Server address or port not set".format(
|
|
|
|
prefix=W.prefix("error"))
|
|
|
|
W.prnt("", message)
|
|
|
|
return False
|
|
|
|
|
|
|
|
if not server.user or not server.password:
|
|
|
|
message = "{prefix}User or password not set".format(
|
|
|
|
prefix=W.prefix("error"))
|
|
|
|
W.prnt("", message)
|
|
|
|
return False
|
|
|
|
|
|
|
|
if server.connected:
|
|
|
|
return True
|
|
|
|
|
2018-01-03 12:14:24 +01:00
|
|
|
if not server.server_buffer:
|
|
|
|
create_server_buffer(server)
|
|
|
|
|
2018-01-07 15:46:18 +01:00
|
|
|
if not server.timer_hook:
|
|
|
|
server.timer_hook = W.hook_timer(
|
|
|
|
1 * 1000,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
"matrix_timer_cb",
|
|
|
|
server.name
|
|
|
|
)
|
2018-01-03 12:14:24 +01:00
|
|
|
|
|
|
|
W.hook_connect("", server.address, server.port, 1, 0, "",
|
|
|
|
"connect_cb", server.name)
|
|
|
|
|
2017-12-30 14:03:03 +01:00
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
|
|
|
@utf8_decode
|
2018-01-05 19:39:11 +01:00
|
|
|
def room_input_cb(server_name, buffer, input_data):
|
|
|
|
server = SERVERS[server_name]
|
|
|
|
|
2018-01-07 15:46:18 +01:00
|
|
|
if not server.connected:
|
|
|
|
message = "{prefix}you are not connected to the server".format(
|
|
|
|
prefix=W.prefix("error"))
|
|
|
|
W.prnt(buffer, message)
|
|
|
|
return W.WEECHAT_RC_ERROR
|
|
|
|
|
2018-01-10 17:09:02 +01:00
|
|
|
room_id = key_from_value(server.buffers, buffer)
|
2018-01-19 11:36:16 +01:00
|
|
|
room = server.rooms[room_id]
|
|
|
|
|
|
|
|
if room.encrypted:
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
2018-01-26 12:18:52 +01:00
|
|
|
formatted_data = colors.parse_input_line(input_data)
|
2018-01-24 17:34:07 +01:00
|
|
|
|
2018-01-26 12:18:52 +01:00
|
|
|
body = {
|
|
|
|
"msgtype": "m.text",
|
|
|
|
"body": colors.formatted_to_plain(formatted_data)
|
|
|
|
}
|
2018-01-24 17:34:07 +01:00
|
|
|
|
2018-01-26 12:18:52 +01:00
|
|
|
if colors.formatted(formatted_data):
|
2018-01-24 17:34:07 +01:00
|
|
|
body["format"] = "org.matrix.custom.html"
|
2018-01-26 12:18:52 +01:00
|
|
|
body["formatted_body"] = colors.formatted_to_html(formatted_data)
|
2018-01-23 13:44:20 +01:00
|
|
|
|
2018-01-11 11:30:41 +01:00
|
|
|
extra_data = {
|
|
|
|
"author": server.user,
|
2018-01-26 12:18:52 +01:00
|
|
|
"message": colors.formatted_to_weechat(W, formatted_data),
|
2018-01-11 11:30:41 +01:00
|
|
|
"room_id": room_id
|
|
|
|
}
|
|
|
|
|
2018-01-26 14:38:46 +01:00
|
|
|
message = MatrixMessage(server, GLOBAL_OPTIONS, MessageType.SEND,
|
2018-01-11 11:30:41 +01:00
|
|
|
data=body, room_id=room_id,
|
|
|
|
extra_data=extra_data)
|
2018-01-10 17:09:02 +01:00
|
|
|
|
2018-01-05 19:39:11 +01:00
|
|
|
send_or_queue(server, message)
|
2017-12-30 14:03:03 +01:00
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
|
|
|
@utf8_decode
|
2018-01-03 12:14:24 +01:00
|
|
|
def room_close_cb(data, buffer):
|
2017-12-30 14:03:03 +01:00
|
|
|
W.prnt("", "Buffer '%s' will be closed!" %
|
|
|
|
W.buffer_get_string(buffer, "name"))
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
|
|
|
@utf8_decode
|
2018-01-05 19:39:11 +01:00
|
|
|
def matrix_timer_cb(server_name, remaining_calls):
|
|
|
|
server = SERVERS[server_name]
|
|
|
|
|
|
|
|
if not server.connected:
|
|
|
|
if not server.connecting:
|
|
|
|
server_buffer_prnt(server, "Reconnecting timeout blaaaa")
|
|
|
|
reconnect(server)
|
2017-12-30 14:03:03 +01:00
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
while server.send_queue:
|
|
|
|
message = server.send_queue.popleft()
|
2018-01-24 12:41:01 +01:00
|
|
|
prnt_debug(DebugType.MESSAGING, server,
|
|
|
|
("Timer hook found message of type {t} in queue. Sending "
|
|
|
|
"out.".format(t=message.type)))
|
2017-12-30 14:03:03 +01:00
|
|
|
|
2018-01-05 19:39:11 +01:00
|
|
|
if not send(server, message):
|
2017-12-30 14:03:03 +01:00
|
|
|
# We got an error while sending the last message return the message
|
|
|
|
# to the queue and exit the loop
|
2018-01-06 17:12:54 +01:00
|
|
|
server.send_queue.appendleft(message)
|
2017-12-30 14:03:03 +01:00
|
|
|
break
|
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
for message in server.message_queue:
|
|
|
|
server_buffer_prnt(
|
|
|
|
server,
|
|
|
|
"Handling message: {message}".format(message=message))
|
2017-12-30 14:03:03 +01:00
|
|
|
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
2018-01-03 12:14:24 +01:00
|
|
|
@utf8_decode
|
|
|
|
def matrix_config_reload_cb(data, config_file):
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
|
2018-01-05 19:39:11 +01:00
|
|
|
@utf8_decode
|
|
|
|
def matrix_config_server_read_cb(
|
2018-01-06 17:12:54 +01:00
|
|
|
data, config_file, section,
|
|
|
|
option_name, value
|
2018-01-05 19:39:11 +01:00
|
|
|
):
|
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
return_code = W.WEECHAT_CONFIG_OPTION_SET_ERROR
|
2018-01-05 19:39:11 +01:00
|
|
|
|
|
|
|
if option_name:
|
|
|
|
server_name, option = option_name.rsplit('.', 1)
|
|
|
|
server = None
|
|
|
|
|
|
|
|
if server_name in SERVERS:
|
|
|
|
server = SERVERS[server_name]
|
|
|
|
else:
|
2018-01-26 14:38:46 +01:00
|
|
|
server = MatrixServer(server_name, W, config_file)
|
2018-01-05 19:39:11 +01:00
|
|
|
SERVERS[server.name] = server
|
|
|
|
|
|
|
|
# Ignore invalid options
|
|
|
|
if option in server.options:
|
2018-01-06 17:12:54 +01:00
|
|
|
return_code = W.config_option_set(server.options[option], value, 1)
|
2018-01-05 19:39:11 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
# TODO print out error message in case of erroneous return_code
|
2018-01-05 19:39:11 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
return return_code
|
2018-01-05 19:39:11 +01:00
|
|
|
|
|
|
|
|
|
|
|
@utf8_decode
|
|
|
|
def matrix_config_server_write_cb(data, config_file, section_name):
|
|
|
|
if not W.config_write_line(config_file, section_name, ""):
|
|
|
|
return W.WECHAT_CONFIG_WRITE_ERROR
|
|
|
|
|
|
|
|
for server in SERVERS.values():
|
|
|
|
for option in server.options.values():
|
|
|
|
if not W.config_write_option(config_file, option):
|
|
|
|
return W.WECHAT_CONFIG_WRITE_ERROR
|
|
|
|
|
|
|
|
return W.WEECHAT_CONFIG_WRITE_OK
|
|
|
|
|
2018-01-03 12:14:24 +01:00
|
|
|
|
2018-01-12 10:51:37 +01:00
|
|
|
@utf8_decode
|
|
|
|
def matrix_config_change_cb(data, option):
|
|
|
|
option_name = key_from_value(GLOBAL_OPTIONS.options, option)
|
|
|
|
|
|
|
|
if option_name == "redactions":
|
2018-01-17 10:03:14 +01:00
|
|
|
GLOBAL_OPTIONS.redaction_type = RedactType(W.config_integer(option))
|
2018-01-12 10:51:37 +01:00
|
|
|
elif option_name == "server_buffer":
|
2018-01-17 10:10:57 +01:00
|
|
|
GLOBAL_OPTIONS.look_server_buf = ServerBufferType(
|
|
|
|
W.config_integer(option))
|
2018-01-17 11:32:00 +01:00
|
|
|
elif option_name == "max_initial_sync_events":
|
|
|
|
GLOBAL_OPTIONS.sync_limit = W.config_integer(option)
|
|
|
|
elif option_name == "max_backlog_sync_events":
|
|
|
|
GLOBAL_OPTIONS.backlog_limit = W.config_integer(option)
|
|
|
|
elif option_name == "fetch_backlog_on_pgup":
|
|
|
|
GLOBAL_OPTIONS.enable_backlog = W.config_boolean(option)
|
|
|
|
|
|
|
|
if GLOBAL_OPTIONS.enable_backlog:
|
|
|
|
if not GLOBAL_OPTIONS.page_up_hook:
|
2018-01-26 17:43:07 +01:00
|
|
|
hook_page_up(CONFIG)
|
2018-01-17 11:32:00 +01:00
|
|
|
else:
|
|
|
|
if GLOBAL_OPTIONS.page_up_hook:
|
|
|
|
W.unhook(GLOBAL_OPTIONS.page_up_hook)
|
|
|
|
GLOBAL_OPTIONS.page_up_hook = None
|
2018-01-12 10:51:37 +01:00
|
|
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
2018-01-03 12:14:24 +01:00
|
|
|
def read_matrix_config():
|
2018-01-05 19:39:11 +01:00
|
|
|
# type: () -> bool
|
2018-01-06 17:12:54 +01:00
|
|
|
return_code = W.config_read(CONFIG)
|
2018-01-26 17:43:07 +01:00
|
|
|
if return_code == W.WEECHAT_CONFIG_READ_OK:
|
2018-01-03 12:14:24 +01:00
|
|
|
return True
|
2018-01-26 17:43:07 +01:00
|
|
|
elif return_code == W.WEECHAT_CONFIG_READ_MEMORY_ERROR:
|
2018-01-03 12:14:24 +01:00
|
|
|
return False
|
2018-01-26 17:43:07 +01:00
|
|
|
elif return_code == W.WEECHAT_CONFIG_READ_FILE_NOT_FOUND:
|
2018-01-03 12:14:24 +01:00
|
|
|
return True
|
2018-01-07 16:04:17 +01:00
|
|
|
return False
|
2018-01-03 12:14:24 +01:00
|
|
|
|
|
|
|
|
|
|
|
@utf8_decode
|
2018-01-05 19:39:11 +01:00
|
|
|
def matrix_unload_cb():
|
|
|
|
for section in ["network", "look", "color", "server"]:
|
2018-01-06 17:12:54 +01:00
|
|
|
section_pointer = W.config_search_section(CONFIG, section)
|
|
|
|
W.config_section_free_options(section_pointer)
|
|
|
|
W.config_section_free(section_pointer)
|
2018-01-03 12:14:24 +01:00
|
|
|
|
|
|
|
W.config_free(CONFIG)
|
|
|
|
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
2018-01-07 15:46:18 +01:00
|
|
|
def check_server_existence(server_name, servers):
|
2018-01-07 16:04:17 +01:00
|
|
|
if server_name not in servers:
|
|
|
|
message = "{prefix}matrix: No such server: {server} found".format(
|
|
|
|
prefix=W.prefix("error"), server=server_name)
|
|
|
|
W.prnt("", message)
|
|
|
|
return False
|
|
|
|
return True
|
2018-01-07 15:46:18 +01:00
|
|
|
|
|
|
|
|
2018-01-24 12:41:01 +01:00
|
|
|
def matrix_command_debug(args):
|
|
|
|
if not args:
|
|
|
|
message = ("{prefix}matrix: Too few arguments for command "
|
|
|
|
"\"/matrix debug\" (see the help for the command: "
|
|
|
|
"/matrix help debug").format(prefix=W.prefix("error"))
|
|
|
|
W.prnt("", message)
|
|
|
|
return
|
|
|
|
|
|
|
|
def toggle_debug(debug_type):
|
|
|
|
if debug_type in GLOBAL_OPTIONS.debug:
|
|
|
|
message = ("{prefix}matrix: Disabling matrix {t} "
|
|
|
|
"debugging.").format(
|
2018-01-25 13:39:48 +01:00
|
|
|
prefix=W.prefix("error"),
|
|
|
|
t=debug_type)
|
2018-01-24 12:41:01 +01:00
|
|
|
W.prnt("", message)
|
|
|
|
GLOBAL_OPTIONS.debug.remove(debug_type)
|
|
|
|
else:
|
|
|
|
message = ("{prefix}matrix: Enabling matrix {t} "
|
|
|
|
"debugging.").format(
|
2018-01-25 13:39:48 +01:00
|
|
|
prefix=W.prefix("error"),
|
|
|
|
t=debug_type)
|
2018-01-24 12:41:01 +01:00
|
|
|
W.prnt("", message)
|
|
|
|
GLOBAL_OPTIONS.debug.append(debug_type)
|
|
|
|
|
|
|
|
for command in args:
|
|
|
|
if command == "network":
|
|
|
|
toggle_debug(DebugType.NETWORK)
|
|
|
|
elif command == "messaging":
|
|
|
|
toggle_debug(DebugType.MESSAGING)
|
|
|
|
elif command == "timing":
|
|
|
|
toggle_debug(DebugType.TIMING)
|
|
|
|
else:
|
|
|
|
message = ("{prefix}matrix: Unknown matrix debug "
|
|
|
|
"type \"{t}\".").format(
|
2018-01-25 13:39:48 +01:00
|
|
|
prefix=W.prefix("error"),
|
|
|
|
t=command)
|
2018-01-24 12:41:01 +01:00
|
|
|
W.prnt("", message)
|
|
|
|
|
|
|
|
|
2018-01-09 12:42:06 +01:00
|
|
|
def matrix_command_help(args):
|
2018-01-12 16:49:29 +01:00
|
|
|
if not args:
|
|
|
|
message = ("{prefix}matrix: Too few arguments for command "
|
|
|
|
"\"/matrix help\" (see the help for the command: "
|
|
|
|
"/matrix help help").format(prefix=W.prefix("error"))
|
|
|
|
W.prnt("", message)
|
|
|
|
return
|
|
|
|
|
2018-01-09 12:42:06 +01:00
|
|
|
for command in args:
|
|
|
|
message = ""
|
|
|
|
|
|
|
|
if command == "connect":
|
|
|
|
message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
|
|
|
"{ncolor}{cmd_color}/connect{ncolor} "
|
|
|
|
"<server-name> [<server-name>...]"
|
|
|
|
"\n\n"
|
|
|
|
"connect to Matrix server(s)"
|
|
|
|
"\n\n"
|
|
|
|
"server-name: server to connect to"
|
|
|
|
"(internal name)").format(
|
|
|
|
delimiter_color=W.color("chat_delimiters"),
|
|
|
|
cmd_color=W.color("chat_buffer"),
|
|
|
|
ncolor=W.color("reset"))
|
|
|
|
|
|
|
|
elif command == "disconnect":
|
|
|
|
message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
|
|
|
"{ncolor}{cmd_color}/disconnect{ncolor} "
|
|
|
|
"<server-name> [<server-name>...]"
|
|
|
|
"\n\n"
|
|
|
|
"disconnect from Matrix server(s)"
|
|
|
|
"\n\n"
|
|
|
|
"server-name: server to disconnect"
|
|
|
|
"(internal name)").format(
|
|
|
|
delimiter_color=W.color("chat_delimiters"),
|
|
|
|
cmd_color=W.color("chat_buffer"),
|
|
|
|
ncolor=W.color("reset"))
|
|
|
|
|
|
|
|
elif command == "reconnect":
|
|
|
|
message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
|
|
|
"{ncolor}{cmd_color}/reconnect{ncolor} "
|
|
|
|
"<server-name> [<server-name>...]"
|
|
|
|
"\n\n"
|
|
|
|
"reconnect to Matrix server(s)"
|
|
|
|
"\n\n"
|
|
|
|
"server-name: server to reconnect"
|
|
|
|
"(internal name)").format(
|
|
|
|
delimiter_color=W.color("chat_delimiters"),
|
|
|
|
cmd_color=W.color("chat_buffer"),
|
|
|
|
ncolor=W.color("reset"))
|
|
|
|
|
|
|
|
elif command == "server":
|
|
|
|
message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
|
|
|
"{ncolor}{cmd_color}/server{ncolor} "
|
|
|
|
"add <server-name> <hostname>[:<port>]"
|
|
|
|
"\n "
|
|
|
|
"delete|list|listfull <server-name>"
|
|
|
|
"\n\n"
|
|
|
|
"list, add, or remove Matrix servers"
|
|
|
|
"\n\n"
|
|
|
|
" list: list servers (without argument, this "
|
|
|
|
"list is displayed)\n"
|
|
|
|
" listfull: list servers with detailed info for each "
|
|
|
|
"server\n"
|
|
|
|
" add: add a new server\n"
|
|
|
|
" delete: delete a server\n"
|
|
|
|
"server-name: server to reconnect (internal name)\n"
|
|
|
|
" hostname: name or IP address of server\n"
|
|
|
|
" port: port of server (default: 8448)\n"
|
|
|
|
"\n"
|
|
|
|
"Examples:"
|
|
|
|
"\n /server listfull"
|
|
|
|
"\n /server add matrix matrix.org:80"
|
|
|
|
"\n /server del matrix").format(
|
|
|
|
delimiter_color=W.color("chat_delimiters"),
|
|
|
|
cmd_color=W.color("chat_buffer"),
|
|
|
|
ncolor=W.color("reset"))
|
|
|
|
|
|
|
|
elif command == "help":
|
|
|
|
message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
|
|
|
"{ncolor}{cmd_color}/help{ncolor} "
|
|
|
|
"<matrix-command> [<matrix-command>...]"
|
|
|
|
"\n\n"
|
|
|
|
"display help about Matrix commands"
|
|
|
|
"\n\n"
|
|
|
|
"matrix-command: a Matrix command name"
|
|
|
|
"(internal name)").format(
|
|
|
|
delimiter_color=W.color("chat_delimiters"),
|
|
|
|
cmd_color=W.color("chat_buffer"),
|
|
|
|
ncolor=W.color("reset"))
|
|
|
|
|
2018-01-24 12:41:01 +01:00
|
|
|
elif command == "debug":
|
|
|
|
message = ("{delimiter_color}[{ncolor}matrix{delimiter_color}] "
|
|
|
|
"{ncolor}{cmd_color}/debug{ncolor} "
|
|
|
|
"<debug-type> [<debug-type>...]"
|
|
|
|
"\n\n"
|
|
|
|
"enable/disable degugging for a Matrix subsystem"
|
|
|
|
"\n\n"
|
|
|
|
"debug-type: a Matrix debug type, one of messaging, "
|
|
|
|
"timing, network").format(
|
|
|
|
delimiter_color=W.color("chat_delimiters"),
|
|
|
|
cmd_color=W.color("chat_buffer"),
|
|
|
|
ncolor=W.color("reset"))
|
|
|
|
|
2018-01-09 12:42:06 +01:00
|
|
|
else:
|
|
|
|
message = ("{prefix}matrix: No help available, \"{command}\" "
|
|
|
|
"is not a matrix command").format(
|
|
|
|
prefix=W.prefix("error"),
|
|
|
|
command=command)
|
|
|
|
|
|
|
|
W.prnt("", "")
|
|
|
|
W.prnt("", message)
|
2018-01-07 15:46:18 +01:00
|
|
|
|
2018-01-12 16:49:29 +01:00
|
|
|
return
|
|
|
|
|
2018-01-09 12:42:06 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
def matrix_server_command_listfull(args):
|
2018-01-08 19:54:32 +01:00
|
|
|
def get_value_string(value, default_value):
|
|
|
|
if value == default_value:
|
|
|
|
if not value:
|
|
|
|
value = "''"
|
|
|
|
value_string = " ({value})".format(value=value)
|
|
|
|
else:
|
|
|
|
value_string = "{color}{value}{ncolor}".format(
|
|
|
|
color=W.color("chat_value"),
|
|
|
|
value=value,
|
|
|
|
ncolor=W.color("reset"))
|
|
|
|
|
|
|
|
return value_string
|
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
for server_name in args:
|
|
|
|
if server_name not in SERVERS:
|
|
|
|
continue
|
2018-01-05 19:39:11 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
server = SERVERS[server_name]
|
|
|
|
connected = ""
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
W.prnt("", "")
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
if server.connected:
|
|
|
|
connected = "connected"
|
|
|
|
else:
|
|
|
|
connected = "not connected"
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
message = ("Server: {server_color}{server}{delimiter_color}"
|
|
|
|
" [{ncolor}{connected}{delimiter_color}]"
|
|
|
|
"{ncolor}").format(
|
|
|
|
server_color=W.color("chat_server"),
|
|
|
|
server=server.name,
|
|
|
|
delimiter_color=W.color("chat_delimiters"),
|
|
|
|
connected=connected,
|
|
|
|
ncolor=W.color("reset"))
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
W.prnt("", message)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
option = server.options["autoconnect"]
|
|
|
|
default_value = W.config_string_default(option)
|
|
|
|
value = W.config_string(option)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
value_string = get_value_string(value, default_value)
|
|
|
|
message = " autoconnect. : {value}".format(value=value_string)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
W.prnt("", message)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
option = server.options["address"]
|
|
|
|
default_value = W.config_string_default(option)
|
|
|
|
value = W.config_string(option)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
value_string = get_value_string(value, default_value)
|
|
|
|
message = " address. . . : {value}".format(value=value_string)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
W.prnt("", message)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
option = server.options["port"]
|
|
|
|
default_value = str(W.config_integer_default(option))
|
|
|
|
value = str(W.config_integer(option))
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
value_string = get_value_string(value, default_value)
|
|
|
|
message = " port . . . . : {value}".format(value=value_string)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
W.prnt("", message)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
option = server.options["username"]
|
|
|
|
default_value = W.config_string_default(option)
|
|
|
|
value = W.config_string(option)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
value_string = get_value_string(value, default_value)
|
|
|
|
message = " username . . : {value}".format(value=value_string)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
W.prnt("", message)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
option = server.options["password"]
|
|
|
|
value = W.config_string(option)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
if value:
|
|
|
|
value = "(hidden)"
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
value_string = get_value_string(value, '')
|
|
|
|
message = " password . . : {value}".format(value=value_string)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
W.prnt("", message)
|
2018-01-08 19:54:32 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
def matrix_server_command_delete(args):
|
|
|
|
for server_name in args:
|
|
|
|
if check_server_existence(server_name, SERVERS):
|
|
|
|
server = SERVERS[server_name]
|
2018-01-07 15:46:18 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
if server.connected:
|
|
|
|
message = ("{prefix}matrix: you can not delete server "
|
|
|
|
"{color}{server}{ncolor} because you are "
|
|
|
|
"connected to it. Try \"/matrix disconnect "
|
|
|
|
"{color}{server}{ncolor}\" before.").format(
|
|
|
|
prefix=W.prefix("error"),
|
2018-01-09 12:42:06 +01:00
|
|
|
color=W.color("chat_server"),
|
2018-01-09 18:41:04 +01:00
|
|
|
ncolor=W.color("reset"),
|
|
|
|
server=server.name)
|
2018-01-07 15:46:18 +01:00
|
|
|
W.prnt("", message)
|
2018-01-09 18:41:04 +01:00
|
|
|
return
|
2018-01-07 15:46:18 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
for buf in server.buffers.values():
|
|
|
|
W.buffer_close(buf)
|
|
|
|
|
|
|
|
if server.server_buffer:
|
|
|
|
W.buffer_close(server.server_buffer)
|
2018-01-08 15:57:29 +01:00
|
|
|
|
|
|
|
for option in server.options.values():
|
|
|
|
W.config_option_free(option)
|
2018-01-09 18:41:04 +01:00
|
|
|
|
|
|
|
message = ("matrix: server {color}{server}{ncolor} has been "
|
|
|
|
"deleted").format(
|
|
|
|
server=server.name,
|
|
|
|
color=W.color("chat_server"),
|
|
|
|
ncolor=W.color("reset"))
|
|
|
|
|
2018-01-08 15:57:29 +01:00
|
|
|
del SERVERS[server.name]
|
2018-01-09 18:41:04 +01:00
|
|
|
server = None
|
2018-01-08 15:57:29 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
W.prnt("", message)
|
2018-01-08 15:57:29 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
|
|
|
|
def matrix_server_command_add(args):
|
|
|
|
if len(args) < 2:
|
|
|
|
message = ("{prefix}matrix: Too few arguments for command "
|
|
|
|
"\"/matrix server add\" (see the help for the command: "
|
|
|
|
"/matrix help server").format(prefix=W.prefix("error"))
|
|
|
|
W.prnt("", message)
|
|
|
|
return
|
|
|
|
elif len(args) > 4:
|
|
|
|
message = ("{prefix}matrix: Too many arguments for command "
|
|
|
|
"\"/matrix server add\" (see the help for the command: "
|
|
|
|
"/matrix help server").format(prefix=W.prefix("error"))
|
|
|
|
W.prnt("", message)
|
|
|
|
return
|
|
|
|
|
|
|
|
def remove_server(server):
|
|
|
|
for option in server.options.values():
|
|
|
|
W.config_option_free(option)
|
|
|
|
del SERVERS[server.name]
|
|
|
|
|
|
|
|
server_name = args[0]
|
|
|
|
|
|
|
|
if server_name in SERVERS:
|
|
|
|
message = ("{prefix}matrix: server {color}{server}{ncolor} "
|
|
|
|
"already exists, can't add it").format(
|
|
|
|
prefix=W.prefix("error"),
|
|
|
|
color=W.color("chat_server"),
|
|
|
|
server=server_name,
|
|
|
|
ncolor=W.color("reset"))
|
|
|
|
W.prnt("", message)
|
|
|
|
return
|
|
|
|
|
2018-01-26 14:38:46 +01:00
|
|
|
server = MatrixServer(args[0], W, CONFIG)
|
2018-01-09 18:41:04 +01:00
|
|
|
SERVERS[server.name] = server
|
|
|
|
|
|
|
|
if len(args) >= 2:
|
|
|
|
try:
|
|
|
|
host, port = args[1].split(":", 1)
|
|
|
|
except ValueError:
|
|
|
|
host, port = args[1], None
|
|
|
|
|
|
|
|
return_code = W.config_option_set(
|
|
|
|
server.options["address"],
|
|
|
|
host,
|
|
|
|
1
|
|
|
|
)
|
|
|
|
|
|
|
|
if return_code == W.WEECHAT_CONFIG_OPTION_SET_ERROR:
|
|
|
|
remove_server(server)
|
|
|
|
message = ("{prefix}Failed to set address for server "
|
|
|
|
"{color}{server}{ncolor}, failed to add "
|
|
|
|
"server.").format(
|
2018-01-08 15:57:29 +01:00
|
|
|
prefix=W.prefix("error"),
|
2018-01-09 12:42:06 +01:00
|
|
|
color=W.color("chat_server"),
|
2018-01-09 18:41:04 +01:00
|
|
|
server=server.name,
|
2018-01-09 12:42:06 +01:00
|
|
|
ncolor=W.color("reset"))
|
2018-01-09 18:41:04 +01:00
|
|
|
|
2018-01-08 15:57:29 +01:00
|
|
|
W.prnt("", message)
|
2018-01-09 18:41:04 +01:00
|
|
|
server = None
|
2018-01-08 15:57:29 +01:00
|
|
|
return
|
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
if port:
|
2018-01-08 15:57:29 +01:00
|
|
|
return_code = W.config_option_set(
|
2018-01-09 18:41:04 +01:00
|
|
|
server.options["port"],
|
|
|
|
port,
|
2018-01-08 15:57:29 +01:00
|
|
|
1
|
|
|
|
)
|
|
|
|
if return_code == W.WEECHAT_CONFIG_OPTION_SET_ERROR:
|
|
|
|
remove_server(server)
|
2018-01-09 18:41:04 +01:00
|
|
|
message = ("{prefix}Failed to set port for server "
|
2018-01-08 15:57:29 +01:00
|
|
|
"{color}{server}{ncolor}, failed to add "
|
|
|
|
"server.").format(
|
|
|
|
prefix=W.prefix("error"),
|
2018-01-09 12:42:06 +01:00
|
|
|
color=W.color("chat_server"),
|
2018-01-08 15:57:29 +01:00
|
|
|
server=server.name,
|
2018-01-09 12:42:06 +01:00
|
|
|
ncolor=W.color("reset"))
|
2018-01-08 15:57:29 +01:00
|
|
|
|
|
|
|
W.prnt("", message)
|
|
|
|
server = None
|
|
|
|
return
|
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
if len(args) >= 3:
|
|
|
|
user = args[2]
|
|
|
|
return_code = W.config_option_set(
|
|
|
|
server.options["username"],
|
|
|
|
user,
|
|
|
|
1
|
|
|
|
)
|
2018-01-08 15:57:29 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
if return_code == W.WEECHAT_CONFIG_OPTION_SET_ERROR:
|
|
|
|
remove_server(server)
|
|
|
|
message = ("{prefix}Failed to set user for server "
|
|
|
|
"{color}{server}{ncolor}, failed to add "
|
|
|
|
"server.").format(
|
|
|
|
prefix=W.prefix("error"),
|
|
|
|
color=W.color("chat_server"),
|
|
|
|
server=server.name,
|
|
|
|
ncolor=W.color("reset"))
|
2018-01-06 17:12:54 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
W.prnt("", message)
|
|
|
|
server = None
|
|
|
|
return
|
2018-01-08 15:57:29 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
if len(args) == 4:
|
|
|
|
password = args[3]
|
2018-01-08 15:57:29 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
return_code = W.config_option_set(
|
|
|
|
server.options["password"],
|
|
|
|
password,
|
|
|
|
1
|
|
|
|
)
|
|
|
|
if return_code == W.WEECHAT_CONFIG_OPTION_SET_ERROR:
|
|
|
|
remove_server(server)
|
|
|
|
message = ("{prefix}Failed to set password for server "
|
|
|
|
"{color}{server}{ncolor}, failed to add "
|
|
|
|
"server.").format(
|
|
|
|
prefix=W.prefix("error"),
|
|
|
|
color=W.color("chat_server"),
|
|
|
|
server=server.name,
|
|
|
|
ncolor=W.color("reset"))
|
|
|
|
W.prnt("", message)
|
|
|
|
server = None
|
|
|
|
return
|
2018-01-08 15:57:29 +01:00
|
|
|
|
2018-01-09 18:41:04 +01:00
|
|
|
message = ("matrix: server {color}{server}{ncolor} "
|
|
|
|
"has been added").format(
|
|
|
|
server=server.name,
|
|
|
|
color=W.color("chat_server"),
|
|
|
|
ncolor=W.color("reset"))
|
|
|
|
W.prnt("", message)
|
|
|
|
|
|
|
|
|
|
|
|
def matrix_server_command(command, args):
|
2018-01-11 16:21:14 +01:00
|
|
|
def list_servers(_):
|
2018-01-09 18:41:04 +01:00
|
|
|
if SERVERS:
|
|
|
|
W.prnt("", "\nAll matrix servers:")
|
|
|
|
for server in SERVERS:
|
|
|
|
W.prnt("", " {color}{server}".format(
|
|
|
|
color=W.color("chat_server"),
|
|
|
|
server=server
|
|
|
|
))
|
2018-01-08 15:57:29 +01:00
|
|
|
|
|
|
|
# TODO the argument for list and listfull is used as a match word to
|
|
|
|
# find/filter servers, we're currently match exactly to the whole name
|
|
|
|
if command == 'list':
|
|
|
|
list_servers(args)
|
|
|
|
elif command == 'listfull':
|
2018-01-09 18:41:04 +01:00
|
|
|
matrix_server_command_listfull(args)
|
2018-01-08 15:57:29 +01:00
|
|
|
elif command == 'add':
|
2018-01-09 18:41:04 +01:00
|
|
|
matrix_server_command_add(args)
|
2018-01-08 15:57:29 +01:00
|
|
|
elif command == 'delete':
|
2018-01-09 18:41:04 +01:00
|
|
|
matrix_server_command_delete(args)
|
2018-01-08 15:57:29 +01:00
|
|
|
else:
|
2018-01-09 18:41:04 +01:00
|
|
|
message = ("{prefix}matrix: Error: unknown matrix server command, "
|
|
|
|
"\"{command}\" (type /matrix help server for help)").format(
|
|
|
|
prefix=W.prefix("error"),
|
|
|
|
command=command)
|
|
|
|
W.prnt("", message)
|
2018-01-08 15:57:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
@utf8_decode
|
|
|
|
def matrix_command_cb(data, buffer, args):
|
|
|
|
def connect_server(args):
|
|
|
|
for server_name in args:
|
|
|
|
if check_server_existence(server_name, SERVERS):
|
|
|
|
server = SERVERS[server_name]
|
|
|
|
connect(server)
|
|
|
|
|
|
|
|
def disconnect_server(args):
|
|
|
|
for server_name in args:
|
|
|
|
if check_server_existence(server_name, SERVERS):
|
|
|
|
server = SERVERS[server_name]
|
2018-01-24 12:41:01 +01:00
|
|
|
if server.connected:
|
|
|
|
W.unhook(server.timer_hook)
|
|
|
|
server.timer_hook = None
|
|
|
|
server.access_token = ""
|
|
|
|
disconnect(server)
|
2018-01-08 15:57:29 +01:00
|
|
|
|
2018-01-08 19:54:32 +01:00
|
|
|
split_args = list(filter(bool, args.split(' ')))
|
2018-01-06 17:12:54 +01:00
|
|
|
|
2018-01-12 16:49:29 +01:00
|
|
|
if len(split_args) < 1:
|
|
|
|
message = ("{prefix}matrix: Too few arguments for command "
|
|
|
|
"\"/matrix\" (see the help for the command: "
|
|
|
|
"/help matrix").format(prefix=W.prefix("error"))
|
|
|
|
W.prnt("", message)
|
2018-01-08 15:57:29 +01:00
|
|
|
return W.WEECHAT_RC_ERROR
|
|
|
|
|
2018-01-12 16:49:29 +01:00
|
|
|
command, args = split_args[0], split_args[1:]
|
|
|
|
|
|
|
|
if command == 'connect':
|
2018-01-06 17:12:54 +01:00
|
|
|
connect_server(args)
|
|
|
|
|
|
|
|
elif command == 'disconnect':
|
|
|
|
disconnect_server(args)
|
|
|
|
|
|
|
|
elif command == 'reconnect':
|
|
|
|
disconnect_server(args)
|
|
|
|
connect_server(args)
|
2018-01-05 19:39:11 +01:00
|
|
|
|
|
|
|
elif command == 'server':
|
2018-01-08 15:57:29 +01:00
|
|
|
if len(args) >= 1:
|
|
|
|
subcommand, args = args[0], args[1:]
|
|
|
|
matrix_server_command(subcommand, args)
|
2018-01-08 19:54:32 +01:00
|
|
|
else:
|
|
|
|
matrix_server_command("list", "")
|
2018-01-05 19:39:11 +01:00
|
|
|
|
2018-01-09 12:42:06 +01:00
|
|
|
elif command == 'help':
|
|
|
|
matrix_command_help(args)
|
|
|
|
|
2018-01-24 12:41:01 +01:00
|
|
|
elif command == 'debug':
|
|
|
|
matrix_command_debug(args)
|
|
|
|
|
2018-01-03 12:14:24 +01:00
|
|
|
else:
|
2018-01-09 18:41:04 +01:00
|
|
|
message = ("{prefix}matrix: Error: unknown matrix command, "
|
|
|
|
"\"{command}\" (type /help matrix for help)").format(
|
|
|
|
prefix=W.prefix("error"),
|
|
|
|
command=command)
|
|
|
|
W.prnt("", message)
|
2018-01-03 12:14:24 +01:00
|
|
|
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
2018-01-05 19:39:11 +01:00
|
|
|
def add_servers_to_completion(completion):
|
2018-01-07 16:04:17 +01:00
|
|
|
for server_name in SERVERS:
|
2018-01-05 19:39:11 +01:00
|
|
|
W.hook_completion_list_add(
|
|
|
|
completion,
|
|
|
|
server_name,
|
|
|
|
0,
|
2018-01-26 17:43:07 +01:00
|
|
|
W.WEECHAT_LIST_POS_SORT
|
2018-01-05 19:39:11 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@utf8_decode
|
2018-01-06 17:12:54 +01:00
|
|
|
def server_command_completion_cb(data, completion_item, buffer, completion):
|
2018-01-26 17:43:07 +01:00
|
|
|
buffer_input = W.buffer_get_string(buffer, "input").split()
|
2018-01-05 19:39:11 +01:00
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
args = buffer_input[1:]
|
2018-01-08 15:57:29 +01:00
|
|
|
commands = ['add', 'delete', 'list', 'listfull']
|
2018-01-05 19:39:11 +01:00
|
|
|
|
|
|
|
def complete_commands():
|
|
|
|
for command in commands:
|
|
|
|
W.hook_completion_list_add(
|
|
|
|
completion,
|
|
|
|
command,
|
|
|
|
0,
|
2018-01-26 17:43:07 +01:00
|
|
|
W.WEECHAT_LIST_POS_SORT
|
2018-01-05 19:39:11 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
if len(args) == 1:
|
|
|
|
complete_commands()
|
|
|
|
|
|
|
|
elif len(args) == 2:
|
|
|
|
if args[1] not in commands:
|
|
|
|
complete_commands()
|
|
|
|
else:
|
2018-01-06 17:12:54 +01:00
|
|
|
if args[1] == 'delete' or args[1] == 'listfull':
|
2018-01-05 19:39:11 +01:00
|
|
|
add_servers_to_completion(completion)
|
|
|
|
|
|
|
|
elif len(args) == 3:
|
2018-01-06 17:12:54 +01:00
|
|
|
if args[1] == 'delete' or args[1] == 'listfull':
|
2018-01-07 16:04:17 +01:00
|
|
|
if args[2] not in SERVERS:
|
2018-01-05 19:39:11 +01:00
|
|
|
add_servers_to_completion(completion)
|
|
|
|
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
2018-01-09 12:42:06 +01:00
|
|
|
@utf8_decode
|
2018-01-05 19:39:11 +01:00
|
|
|
def matrix_server_completion_cb(data, completion_item, buffer, completion):
|
|
|
|
add_servers_to_completion(completion)
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
2018-01-09 12:42:06 +01:00
|
|
|
@utf8_decode
|
|
|
|
def matrix_command_completion_cb(data, completion_item, buffer, completion):
|
2018-01-24 12:41:01 +01:00
|
|
|
for command in [
|
2018-01-25 13:39:48 +01:00
|
|
|
"connect",
|
|
|
|
"disconnect",
|
|
|
|
"reconnect",
|
|
|
|
"server",
|
|
|
|
"help",
|
|
|
|
"debug"
|
2018-01-24 12:41:01 +01:00
|
|
|
]:
|
2018-01-09 12:42:06 +01:00
|
|
|
W.hook_completion_list_add(
|
|
|
|
completion,
|
|
|
|
command,
|
|
|
|
0,
|
2018-01-26 17:43:07 +01:00
|
|
|
W.WEECHAT_LIST_POS_SORT)
|
2018-01-09 12:42:06 +01:00
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
2018-01-05 19:39:11 +01:00
|
|
|
def create_default_server(config_file):
|
2018-01-26 14:38:46 +01:00
|
|
|
server = MatrixServer('matrix.org', W, config_file)
|
2018-01-05 19:39:11 +01:00
|
|
|
SERVERS[server.name] = server
|
|
|
|
|
2018-01-19 08:46:23 +01:00
|
|
|
W.config_option_set(server.options["address"], "matrix.org", 1)
|
2018-01-05 19:39:11 +01:00
|
|
|
|
|
|
|
return True
|
2018-01-03 12:14:24 +01:00
|
|
|
|
|
|
|
|
2018-01-11 16:21:14 +01:00
|
|
|
@utf8_decode
|
|
|
|
def matrix_command_topic_cb(data, buffer, command):
|
|
|
|
for server in SERVERS.values():
|
|
|
|
if buffer in server.buffers.values():
|
|
|
|
topic = None
|
|
|
|
room_id = key_from_value(server.buffers, buffer)
|
|
|
|
split_command = command.split(' ', 1)
|
|
|
|
|
|
|
|
if len(split_command) == 2:
|
|
|
|
topic = split_command[1]
|
|
|
|
|
|
|
|
if not topic:
|
|
|
|
room = server.rooms[room_id]
|
2018-01-12 16:49:29 +01:00
|
|
|
if not room.topic:
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
message = ("{prefix}Topic for {color}{room}{ncolor} is "
|
|
|
|
"\"{topic}\"").format(
|
|
|
|
prefix=W.prefix("network"),
|
|
|
|
color=W.color("chat_buffer"),
|
|
|
|
ncolor=W.color("reset"),
|
|
|
|
room=room.alias,
|
|
|
|
topic=room.topic)
|
|
|
|
|
|
|
|
date = int(time.time())
|
|
|
|
topic_date = room.topic_date.strftime("%a, %d %b %Y "
|
|
|
|
"%H:%M:%S")
|
|
|
|
|
|
|
|
tags = "matrix_topic,log1"
|
|
|
|
W.prnt_date_tags(buffer, date, tags, message)
|
|
|
|
|
|
|
|
# TODO the nick should be colored
|
2018-01-17 11:32:00 +01:00
|
|
|
|
2018-01-12 16:49:29 +01:00
|
|
|
# TODO we should use the display name as well as
|
|
|
|
# the user name here
|
|
|
|
message = ("{prefix}Topic set by {author} on "
|
|
|
|
"{date}").format(
|
|
|
|
prefix=W.prefix("network"),
|
|
|
|
author=room.topic_author,
|
|
|
|
date=topic_date)
|
|
|
|
W.prnt_date_tags(buffer, date, tags, message)
|
2018-01-11 16:21:14 +01:00
|
|
|
|
|
|
|
return W.WEECHAT_RC_OK_EAT
|
|
|
|
|
|
|
|
body = {"topic": topic}
|
|
|
|
|
|
|
|
message = MatrixMessage(
|
|
|
|
server,
|
2018-01-26 14:38:46 +01:00
|
|
|
GLOBAL_OPTIONS,
|
2018-01-11 16:21:14 +01:00
|
|
|
MessageType.STATE,
|
|
|
|
data=body,
|
|
|
|
room_id=room_id,
|
2018-01-12 16:15:11 +01:00
|
|
|
extra_id="m.room.topic"
|
2018-01-11 16:21:14 +01:00
|
|
|
)
|
|
|
|
send_or_queue(server, message)
|
|
|
|
|
|
|
|
return W.WEECHAT_RC_OK_EAT
|
|
|
|
|
|
|
|
elif buffer == server.server_buffer:
|
|
|
|
message = ("{prefix}matrix: command \"topic\" must be "
|
|
|
|
"executed on a Matrix channel buffer").format(
|
|
|
|
prefix=W.prefix("error"))
|
|
|
|
W.prnt(buffer, message)
|
|
|
|
return W.WEECHAT_RC_OK_EAT
|
|
|
|
|
|
|
|
return W.WEECHAT_RC_OK
|
|
|
|
|
|
|
|
|
2018-01-19 10:15:03 +01:00
|
|
|
@utf8_decode
|
|
|
|
def matrix_bar_item_plugin(data, item, window, buffer, extra_info):
|
2018-01-23 13:30:42 +01:00
|
|
|
# pylint: disable=unused-argument
|
2018-01-19 10:15:03 +01:00
|
|
|
for server in SERVERS.values():
|
|
|
|
if (buffer in server.buffers.values() or
|
|
|
|
buffer == server.server_buffer):
|
|
|
|
return "matrix{color}/{color_fg}{name}".format(
|
|
|
|
color=W.color("bar_delim"),
|
|
|
|
color_fg=W.color("bar_fg"),
|
|
|
|
name=server.name)
|
|
|
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
@utf8_decode
|
|
|
|
def matrix_bar_item_name(data, item, window, buffer, extra_info):
|
2018-01-23 13:30:42 +01:00
|
|
|
# pylint: disable=unused-argument
|
2018-01-19 10:15:03 +01:00
|
|
|
for server in SERVERS.values():
|
|
|
|
if buffer in server.buffers.values():
|
|
|
|
color = ("status_name_ssl"
|
|
|
|
if server.ssl_context.check_hostname else
|
|
|
|
"status_name")
|
|
|
|
|
|
|
|
room_id = key_from_value(server.buffers, buffer)
|
|
|
|
|
|
|
|
room = server.rooms[room_id]
|
|
|
|
|
|
|
|
return "{color}{name}".format(
|
|
|
|
color=W.color(color),
|
|
|
|
name=room.alias)
|
|
|
|
|
|
|
|
elif buffer in server.server_buffer:
|
|
|
|
color = ("status_name_ssl"
|
|
|
|
if server.ssl_context.check_hostname else
|
|
|
|
"status_name")
|
|
|
|
|
|
|
|
return "{color}server{del_color}[{color}{name}{del_color}]".format(
|
|
|
|
color=W.color(color),
|
|
|
|
del_color=W.color("bar_delim"),
|
|
|
|
name=server.name)
|
|
|
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
def autoconnect(servers):
|
|
|
|
for server in servers.values():
|
|
|
|
if server.autoconnect:
|
|
|
|
connect(server)
|
|
|
|
|
|
|
|
|
2017-12-30 14:03:03 +01:00
|
|
|
if __name__ == "__main__":
|
|
|
|
if W.register(WEECHAT_SCRIPT_NAME,
|
|
|
|
WEECHAT_SCRIPT_AUTHOR,
|
|
|
|
WEECHAT_SCRIPT_VERSION,
|
|
|
|
WEECHAT_SCRIPT_LICENSE,
|
|
|
|
WEECHAT_SCRIPT_DESCRIPTION,
|
2018-01-05 19:39:11 +01:00
|
|
|
'matrix_unload_cb',
|
2017-12-30 14:03:03 +01:00
|
|
|
''):
|
|
|
|
|
2018-01-03 12:14:24 +01:00
|
|
|
# TODO if this fails we should abort and unload the script.
|
2018-01-26 17:43:07 +01:00
|
|
|
CONFIG = matrix.globals.init_matrix_config()
|
2018-01-03 12:14:24 +01:00
|
|
|
read_matrix_config()
|
|
|
|
|
2018-01-26 17:43:07 +01:00
|
|
|
hook_commands()
|
2018-01-06 17:12:54 +01:00
|
|
|
|
2018-01-19 10:15:03 +01:00
|
|
|
W.bar_item_new("(extra)buffer_plugin", "matrix_bar_item_plugin", "")
|
|
|
|
W.bar_item_new("(extra)buffer_name", "matrix_bar_item_name", "")
|
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
if not SERVERS:
|
2018-01-05 19:39:11 +01:00
|
|
|
create_default_server(CONFIG)
|
|
|
|
|
2018-01-06 17:12:54 +01:00
|
|
|
autoconnect(SERVERS)
|