More splitting.
This commit is contained in:
parent
6e7ed8333f
commit
7328dcf7ab
4 changed files with 400 additions and 349 deletions
200
matrix/api.py
Normal file
200
matrix/api.py
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
from enum import Enum, unique
|
||||||
|
|
||||||
|
from matrix.http import RequestType, HttpRequest
|
||||||
|
|
||||||
|
|
||||||
|
MATRIX_API_PATH = "/_matrix/client/r0" # type: str
|
||||||
|
|
||||||
|
|
||||||
|
@unique
|
||||||
|
class MessageType(Enum):
|
||||||
|
LOGIN = 0
|
||||||
|
SYNC = 1
|
||||||
|
SEND = 2
|
||||||
|
STATE = 3
|
||||||
|
REDACT = 4
|
||||||
|
ROOM_MSG = 5
|
||||||
|
JOIN = 6
|
||||||
|
PART = 7
|
||||||
|
INVITE = 8
|
||||||
|
|
||||||
|
|
||||||
|
class MatrixMessage:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
server, # type: MatrixServer
|
||||||
|
options, # type: PluginOptions
|
||||||
|
message_type, # type: MessageType
|
||||||
|
room_id=None, # type: str
|
||||||
|
extra_id=None, # type: str
|
||||||
|
data={}, # type: Dict[str, Any]
|
||||||
|
extra_data=None # type: Dict[str, Any]
|
||||||
|
):
|
||||||
|
# type: (...) -> None
|
||||||
|
# pylint: disable=dangerous-default-value
|
||||||
|
self.type = message_type # type: MessageType
|
||||||
|
self.request = None # type: HttpRequest
|
||||||
|
self.response = None # type: HttpResponse
|
||||||
|
self.extra_data = extra_data # type: Dict[str, Any]
|
||||||
|
|
||||||
|
self.creation_time = time.time() # type: float
|
||||||
|
self.send_time = None # type: float
|
||||||
|
self.receive_time = None # type: float
|
||||||
|
|
||||||
|
if message_type == MessageType.LOGIN:
|
||||||
|
path = ("{api}/login").format(api=MATRIX_API_PATH)
|
||||||
|
self.request = HttpRequest(
|
||||||
|
RequestType.POST,
|
||||||
|
server.address,
|
||||||
|
server.port,
|
||||||
|
path,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
|
||||||
|
elif message_type == MessageType.SYNC:
|
||||||
|
sync_filter = {
|
||||||
|
"room": {
|
||||||
|
"timeline": {"limit": options.sync_limit}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
path = ("{api}/sync?access_token={access_token}&"
|
||||||
|
"filter={sync_filter}").format(
|
||||||
|
api=MATRIX_API_PATH,
|
||||||
|
access_token=server.access_token,
|
||||||
|
sync_filter=json.dumps(sync_filter,
|
||||||
|
separators=(',', ':')))
|
||||||
|
|
||||||
|
if server.next_batch:
|
||||||
|
path = path + '&since={next_batch}'.format(
|
||||||
|
next_batch=server.next_batch)
|
||||||
|
|
||||||
|
self.request = HttpRequest(
|
||||||
|
RequestType.GET,
|
||||||
|
server.address,
|
||||||
|
server.port,
|
||||||
|
path
|
||||||
|
)
|
||||||
|
|
||||||
|
elif message_type == MessageType.SEND:
|
||||||
|
path = ("{api}/rooms/{room}/send/m.room.message/{tx_id}?"
|
||||||
|
"access_token={access_token}").format(
|
||||||
|
api=MATRIX_API_PATH,
|
||||||
|
room=room_id,
|
||||||
|
tx_id=get_transaction_id(server),
|
||||||
|
access_token=server.access_token)
|
||||||
|
|
||||||
|
self.request = HttpRequest(
|
||||||
|
RequestType.PUT,
|
||||||
|
server.address,
|
||||||
|
server.port,
|
||||||
|
path,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
|
||||||
|
elif message_type == MessageType.STATE:
|
||||||
|
path = ("{api}/rooms/{room}/state/{event_type}?"
|
||||||
|
"access_token={access_token}").format(
|
||||||
|
api=MATRIX_API_PATH,
|
||||||
|
room=room_id,
|
||||||
|
event_type=extra_id,
|
||||||
|
access_token=server.access_token)
|
||||||
|
|
||||||
|
self.request = HttpRequest(
|
||||||
|
RequestType.PUT,
|
||||||
|
server.address,
|
||||||
|
server.port,
|
||||||
|
path,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
|
||||||
|
elif message_type == MessageType.REDACT:
|
||||||
|
path = ("{api}/rooms/{room}/redact/{event_id}/{tx_id}?"
|
||||||
|
"access_token={access_token}").format(
|
||||||
|
api=MATRIX_API_PATH,
|
||||||
|
room=room_id,
|
||||||
|
event_id=extra_id,
|
||||||
|
tx_id=get_transaction_id(server),
|
||||||
|
access_token=server.access_token)
|
||||||
|
|
||||||
|
self.request = HttpRequest(
|
||||||
|
RequestType.PUT,
|
||||||
|
server.address,
|
||||||
|
server.port,
|
||||||
|
path,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
|
||||||
|
elif message_type == MessageType.ROOM_MSG:
|
||||||
|
path = ("{api}/rooms/{room}/messages?from={prev_batch}&"
|
||||||
|
"dir=b&limit={message_limit}&"
|
||||||
|
"access_token={access_token}").format(
|
||||||
|
api=MATRIX_API_PATH,
|
||||||
|
room=room_id,
|
||||||
|
prev_batch=extra_id,
|
||||||
|
message_limit=options.backlog_limit,
|
||||||
|
access_token=server.access_token)
|
||||||
|
self.request = HttpRequest(
|
||||||
|
RequestType.GET,
|
||||||
|
server.address,
|
||||||
|
server.port,
|
||||||
|
path,
|
||||||
|
)
|
||||||
|
|
||||||
|
elif message_type == MessageType.JOIN:
|
||||||
|
path = ("{api}/rooms/{room_id}/join?"
|
||||||
|
"access_token={access_token}").format(
|
||||||
|
api=MATRIX_API_PATH,
|
||||||
|
room_id=room_id,
|
||||||
|
access_token=server.access_token)
|
||||||
|
|
||||||
|
self.request = HttpRequest(
|
||||||
|
RequestType.POST,
|
||||||
|
server.address,
|
||||||
|
server.port,
|
||||||
|
path,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
|
||||||
|
elif message_type == MessageType.PART:
|
||||||
|
path = ("{api}/rooms/{room_id}/leave?"
|
||||||
|
"access_token={access_token}").format(
|
||||||
|
api=MATRIX_API_PATH,
|
||||||
|
room_id=room_id,
|
||||||
|
access_token=server.access_token)
|
||||||
|
|
||||||
|
self.request = HttpRequest(
|
||||||
|
RequestType.POST,
|
||||||
|
server.address,
|
||||||
|
server.port,
|
||||||
|
path,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
|
||||||
|
elif message_type == MessageType.INVITE:
|
||||||
|
path = ("{api}/rooms/{room}/invite?"
|
||||||
|
"access_token={access_token}").format(
|
||||||
|
api=MATRIX_API_PATH,
|
||||||
|
room=room_id,
|
||||||
|
access_token=server.access_token)
|
||||||
|
|
||||||
|
self.request = HttpRequest(
|
||||||
|
RequestType.POST,
|
||||||
|
server.address,
|
||||||
|
server.port,
|
||||||
|
path,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_transaction_id(server):
|
||||||
|
# type: (MatrixServer) -> int
|
||||||
|
transaction_id = server.transaction_id
|
||||||
|
server.transaction_id += 1
|
||||||
|
return transaction_id
|
55
matrix/config.py
Normal file
55
matrix/config.py
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
|
from enum import Enum, unique
|
||||||
|
|
||||||
|
|
||||||
|
@unique
|
||||||
|
class RedactType(Enum):
|
||||||
|
STRIKETHROUGH = 0
|
||||||
|
NOTICE = 1
|
||||||
|
DELETE = 2
|
||||||
|
|
||||||
|
|
||||||
|
@unique
|
||||||
|
class ServerBufferType(Enum):
|
||||||
|
MERGE_CORE = 0
|
||||||
|
MERGE = 1
|
||||||
|
INDEPENDENT = 2
|
||||||
|
|
||||||
|
|
||||||
|
@unique
|
||||||
|
class DebugType(Enum):
|
||||||
|
MESSAGING = 0
|
||||||
|
NETWORK = 1
|
||||||
|
TIMING = 2
|
||||||
|
|
||||||
|
|
||||||
|
Option = namedtuple(
|
||||||
|
'Option', [
|
||||||
|
'name',
|
||||||
|
'type',
|
||||||
|
'string_values',
|
||||||
|
'min',
|
||||||
|
'max',
|
||||||
|
'value',
|
||||||
|
'description'
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
class PluginOptions:
|
||||||
|
def __init__(self):
|
||||||
|
self.redaction_type = RedactType.STRIKETHROUGH # type: RedactType
|
||||||
|
self.look_server_buf = ServerBufferType.MERGE_CORE # type: ServerBufferType
|
||||||
|
|
||||||
|
self.sync_limit = 30 # type: int
|
||||||
|
self.backlog_limit = 10 # type: int
|
||||||
|
self.enable_backlog = True # type: bool
|
||||||
|
self.page_up_hook = None # type: weechat.hook
|
||||||
|
|
||||||
|
self.redaction_comp_len = 50 # type: int
|
||||||
|
|
||||||
|
self.options = dict() # type: Dict[str, weechat.config_option]
|
||||||
|
self.debug = [] # type: List[DebugType]
|
111
matrix/server.py
Normal file
111
matrix/server.py
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import ssl
|
||||||
|
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
|
from http_parser.pyparser import HttpParser
|
||||||
|
|
||||||
|
|
||||||
|
from matrix.config import Option
|
||||||
|
|
||||||
|
|
||||||
|
class MatrixServer:
|
||||||
|
# pylint: disable=too-many-instance-attributes
|
||||||
|
def __init__(self, name, w, config_file):
|
||||||
|
# type: (str, weechat, weechat.config) -> None
|
||||||
|
self.name = name # type: str
|
||||||
|
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.user = "" # type: str
|
||||||
|
self.password = "" # type: str
|
||||||
|
|
||||||
|
self.rooms = dict() # type: Dict[str, MatrixRoom]
|
||||||
|
self.buffers = dict() # type: Dict[str, weechat.buffer]
|
||||||
|
self.server_buffer = None # type: weechat.buffer
|
||||||
|
self.fd_hook = None # type: weechat.hook
|
||||||
|
self.timer_hook = None # type: weechat.hook
|
||||||
|
self.numeric_address = "" # type: str
|
||||||
|
|
||||||
|
self.autoconnect = False # type: bool
|
||||||
|
self.connected = False # type: bool
|
||||||
|
self.connecting = False # type: bool
|
||||||
|
self.reconnect_count = 0 # type: int
|
||||||
|
self.socket = None # type: ssl.SSLSocket
|
||||||
|
self.ssl_context = ssl.create_default_context() # type: ssl.SSLContext
|
||||||
|
|
||||||
|
self.access_token = None # type: str
|
||||||
|
self.next_batch = None # type: str
|
||||||
|
self.transaction_id = 0 # type: int
|
||||||
|
|
||||||
|
self.http_parser = HttpParser() # type: HttpParser
|
||||||
|
self.http_buffer = [] # type: List[bytes]
|
||||||
|
|
||||||
|
# Queue of messages we need to send off.
|
||||||
|
self.send_queue = deque() # type: Deque[MatrixMessage]
|
||||||
|
# Queue of messages we send off and are waiting a response for
|
||||||
|
self.receive_queue = deque() # type: Deque[MatrixMessage]
|
||||||
|
self.message_queue = deque() # type: Deque[MatrixMessage]
|
||||||
|
self.ignore_event_list = [] # type: List[str]
|
||||||
|
|
||||||
|
self._create_options(w, config_file)
|
||||||
|
|
||||||
|
def _create_options(self, w, 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(
|
||||||
|
'ssl_verify', 'boolean', '', 0, 0, 'on',
|
||||||
|
(
|
||||||
|
"Check that the SSL connection is fully trusted"
|
||||||
|
"is starting"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Option(
|
||||||
|
'username', 'string', '', 0, 0, '',
|
||||||
|
"Username to use on server"
|
||||||
|
),
|
||||||
|
Option(
|
||||||
|
'password', 'string', '', 0, 0, '',
|
||||||
|
"Password for server"
|
||||||
|
),
|
||||||
|
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, "",
|
||||||
|
"", "server_config_change_cb", self.name, "", "")
|
||||||
|
|
||||||
|
def reset_parser(self):
|
||||||
|
self.http_parser = HttpParser()
|
||||||
|
self.http_buffer = []
|
|
@ -14,18 +14,23 @@ import sys
|
||||||
# pylint: disable=redefined-builtin
|
# pylint: disable=redefined-builtin
|
||||||
from builtins import bytes, str
|
from builtins import bytes, str
|
||||||
|
|
||||||
from collections import deque, namedtuple
|
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from enum import Enum, unique
|
|
||||||
|
|
||||||
# pylint: disable=unused-import
|
# pylint: disable=unused-import
|
||||||
from typing import (List, Set, Dict, Tuple, Text, Optional, AnyStr, Deque, Any)
|
from typing import (List, Set, Dict, Tuple, Text, Optional, AnyStr, Deque, Any)
|
||||||
|
|
||||||
from http_parser.pyparser import HttpParser
|
|
||||||
|
|
||||||
from matrix import colors
|
from matrix import colors
|
||||||
from matrix.utf import WeechatWrapper, utf8_decode
|
from matrix.utf import WeechatWrapper, utf8_decode
|
||||||
from matrix.http import HttpRequest, HttpResponse, RequestType
|
from matrix.http import HttpResponse
|
||||||
|
from matrix.api import MatrixMessage, MessageType
|
||||||
|
from matrix.server import MatrixServer
|
||||||
|
from matrix.config import (
|
||||||
|
PluginOptions,
|
||||||
|
Option,
|
||||||
|
DebugType,
|
||||||
|
RedactType,
|
||||||
|
ServerBufferType
|
||||||
|
)
|
||||||
|
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
import weechat
|
import weechat
|
||||||
|
@ -36,254 +41,16 @@ WEECHAT_SCRIPT_AUTHOR = "Damir Jelić <poljar@termina.org.uk>" # type: str
|
||||||
WEECHAT_SCRIPT_VERSION = "0.1" # type: str
|
WEECHAT_SCRIPT_VERSION = "0.1" # type: str
|
||||||
WEECHAT_SCRIPT_LICENSE = "MIT" # type: str
|
WEECHAT_SCRIPT_LICENSE = "MIT" # type: str
|
||||||
|
|
||||||
MATRIX_API_PATH = "/_matrix/client/r0" # type: str
|
|
||||||
|
|
||||||
SERVERS = dict() # type: Dict[str, MatrixServer]
|
SERVERS = dict() # type: Dict[str, MatrixServer]
|
||||||
CONFIG = None # type: weechat.config
|
CONFIG = None # type: weechat.config
|
||||||
GLOBAL_OPTIONS = None # type: PluginOptions
|
GLOBAL_OPTIONS = None # type: PluginOptions
|
||||||
|
|
||||||
|
|
||||||
@unique
|
|
||||||
class MessageType(Enum):
|
|
||||||
LOGIN = 0
|
|
||||||
SYNC = 1
|
|
||||||
SEND = 2
|
|
||||||
STATE = 3
|
|
||||||
REDACT = 4
|
|
||||||
ROOM_MSG = 5
|
|
||||||
JOIN = 6
|
|
||||||
PART = 7
|
|
||||||
INVITE = 8
|
|
||||||
|
|
||||||
|
|
||||||
@unique
|
|
||||||
class RedactType(Enum):
|
|
||||||
STRIKETHROUGH = 0
|
|
||||||
NOTICE = 1
|
|
||||||
DELETE = 2
|
|
||||||
|
|
||||||
|
|
||||||
@unique
|
|
||||||
class ServerBufferType(Enum):
|
|
||||||
MERGE_CORE = 0
|
|
||||||
MERGE = 1
|
|
||||||
INDEPENDENT = 2
|
|
||||||
|
|
||||||
|
|
||||||
@unique
|
|
||||||
class DebugType(Enum):
|
|
||||||
MESSAGING = 0
|
|
||||||
NETWORK = 1
|
|
||||||
TIMING = 2
|
|
||||||
|
|
||||||
|
|
||||||
def prnt_debug(debug_type, server, message):
|
def prnt_debug(debug_type, server, message):
|
||||||
if debug_type in GLOBAL_OPTIONS.debug:
|
if debug_type in GLOBAL_OPTIONS.debug:
|
||||||
W.prnt(server.server_buffer, message)
|
W.prnt(server.server_buffer, message)
|
||||||
|
|
||||||
|
|
||||||
Option = namedtuple(
|
|
||||||
'Option', [
|
|
||||||
'name',
|
|
||||||
'type',
|
|
||||||
'string_values',
|
|
||||||
'min',
|
|
||||||
'max',
|
|
||||||
'value',
|
|
||||||
'description'
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
class PluginOptions:
|
|
||||||
def __init__(self):
|
|
||||||
self.redaction_type = RedactType.STRIKETHROUGH # type: RedactType
|
|
||||||
self.look_server_buf = ServerBufferType.MERGE_CORE # type: ServerBufferType
|
|
||||||
|
|
||||||
self.sync_limit = 30 # type: int
|
|
||||||
self.backlog_limit = 10 # type: int
|
|
||||||
self.enable_backlog = True # type: bool
|
|
||||||
self.page_up_hook = None # type: weechat.hook
|
|
||||||
|
|
||||||
self.redaction_comp_len = 50 # type: int
|
|
||||||
|
|
||||||
self.options = dict() # type: Dict[str, weechat.config_option]
|
|
||||||
self.debug = [] # type: DebugType
|
|
||||||
|
|
||||||
|
|
||||||
def get_transaction_id(server):
|
|
||||||
# type: (MatrixServer) -> int
|
|
||||||
transaction_id = server.transaction_id
|
|
||||||
server.transaction_id += 1
|
|
||||||
return transaction_id
|
|
||||||
|
|
||||||
|
|
||||||
class MatrixMessage:
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
server, # type: MatrixServer
|
|
||||||
message_type, # type: MessageType
|
|
||||||
room_id=None, # type: str
|
|
||||||
extra_id=None, # type: str
|
|
||||||
data={}, # type: Dict[str, Any]
|
|
||||||
extra_data=None # type: Dict[str, Any]
|
|
||||||
):
|
|
||||||
# type: (...) -> None
|
|
||||||
# pylint: disable=dangerous-default-value
|
|
||||||
self.type = message_type # type: MessageType
|
|
||||||
self.request = None # type: HttpRequest
|
|
||||||
self.response = None # type: HttpResponse
|
|
||||||
self.extra_data = extra_data # type: Dict[str, Any]
|
|
||||||
|
|
||||||
self.creation_time = time.time() # type: float
|
|
||||||
self.send_time = None # type: float
|
|
||||||
self.receive_time = None # type: float
|
|
||||||
|
|
||||||
if message_type == MessageType.LOGIN:
|
|
||||||
path = ("{api}/login").format(api=MATRIX_API_PATH)
|
|
||||||
self.request = HttpRequest(
|
|
||||||
RequestType.POST,
|
|
||||||
server.address,
|
|
||||||
server.port,
|
|
||||||
path,
|
|
||||||
data
|
|
||||||
)
|
|
||||||
|
|
||||||
elif message_type == MessageType.SYNC:
|
|
||||||
sync_filter = {
|
|
||||||
"room": {
|
|
||||||
"timeline": {"limit": GLOBAL_OPTIONS.sync_limit}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
path = ("{api}/sync?access_token={access_token}&"
|
|
||||||
"filter={sync_filter}").format(
|
|
||||||
api=MATRIX_API_PATH,
|
|
||||||
access_token=server.access_token,
|
|
||||||
sync_filter=json.dumps(sync_filter,
|
|
||||||
separators=(',', ':')))
|
|
||||||
|
|
||||||
if server.next_batch:
|
|
||||||
path = path + '&since={next_batch}'.format(
|
|
||||||
next_batch=server.next_batch)
|
|
||||||
|
|
||||||
self.request = HttpRequest(
|
|
||||||
RequestType.GET,
|
|
||||||
server.address,
|
|
||||||
server.port,
|
|
||||||
path
|
|
||||||
)
|
|
||||||
|
|
||||||
elif message_type == MessageType.SEND:
|
|
||||||
path = ("{api}/rooms/{room}/send/m.room.message/{tx_id}?"
|
|
||||||
"access_token={access_token}").format(
|
|
||||||
api=MATRIX_API_PATH,
|
|
||||||
room=room_id,
|
|
||||||
tx_id=get_transaction_id(server),
|
|
||||||
access_token=server.access_token)
|
|
||||||
|
|
||||||
self.request = HttpRequest(
|
|
||||||
RequestType.PUT,
|
|
||||||
server.address,
|
|
||||||
server.port,
|
|
||||||
path,
|
|
||||||
data
|
|
||||||
)
|
|
||||||
|
|
||||||
elif message_type == MessageType.STATE:
|
|
||||||
path = ("{api}/rooms/{room}/state/{event_type}?"
|
|
||||||
"access_token={access_token}").format(
|
|
||||||
api=MATRIX_API_PATH,
|
|
||||||
room=room_id,
|
|
||||||
event_type=extra_id,
|
|
||||||
access_token=server.access_token)
|
|
||||||
|
|
||||||
self.request = HttpRequest(
|
|
||||||
RequestType.PUT,
|
|
||||||
server.address,
|
|
||||||
server.port,
|
|
||||||
path,
|
|
||||||
data
|
|
||||||
)
|
|
||||||
|
|
||||||
elif message_type == MessageType.REDACT:
|
|
||||||
path = ("{api}/rooms/{room}/redact/{event_id}/{tx_id}?"
|
|
||||||
"access_token={access_token}").format(
|
|
||||||
api=MATRIX_API_PATH,
|
|
||||||
room=room_id,
|
|
||||||
event_id=extra_id,
|
|
||||||
tx_id=get_transaction_id(server),
|
|
||||||
access_token=server.access_token)
|
|
||||||
|
|
||||||
self.request = HttpRequest(
|
|
||||||
RequestType.PUT,
|
|
||||||
server.address,
|
|
||||||
server.port,
|
|
||||||
path,
|
|
||||||
data
|
|
||||||
)
|
|
||||||
|
|
||||||
elif message_type == MessageType.ROOM_MSG:
|
|
||||||
path = ("{api}/rooms/{room}/messages?from={prev_batch}&"
|
|
||||||
"dir=b&limit={message_limit}&"
|
|
||||||
"access_token={access_token}").format(
|
|
||||||
api=MATRIX_API_PATH,
|
|
||||||
room=room_id,
|
|
||||||
prev_batch=extra_id,
|
|
||||||
message_limit=GLOBAL_OPTIONS.backlog_limit,
|
|
||||||
access_token=server.access_token)
|
|
||||||
self.request = HttpRequest(
|
|
||||||
RequestType.GET,
|
|
||||||
server.address,
|
|
||||||
server.port,
|
|
||||||
path,
|
|
||||||
)
|
|
||||||
|
|
||||||
elif message_type == MessageType.JOIN:
|
|
||||||
path = ("{api}/rooms/{room_id}/join?"
|
|
||||||
"access_token={access_token}").format(
|
|
||||||
api=MATRIX_API_PATH,
|
|
||||||
room_id=room_id,
|
|
||||||
access_token=server.access_token)
|
|
||||||
|
|
||||||
self.request = HttpRequest(
|
|
||||||
RequestType.POST,
|
|
||||||
server.address,
|
|
||||||
server.port,
|
|
||||||
path,
|
|
||||||
data
|
|
||||||
)
|
|
||||||
|
|
||||||
elif message_type == MessageType.PART:
|
|
||||||
path = ("{api}/rooms/{room_id}/leave?"
|
|
||||||
"access_token={access_token}").format(
|
|
||||||
api=MATRIX_API_PATH,
|
|
||||||
room_id=room_id,
|
|
||||||
access_token=server.access_token)
|
|
||||||
|
|
||||||
self.request = HttpRequest(
|
|
||||||
RequestType.POST,
|
|
||||||
server.address,
|
|
||||||
server.port,
|
|
||||||
path,
|
|
||||||
data
|
|
||||||
)
|
|
||||||
|
|
||||||
elif message_type == MessageType.INVITE:
|
|
||||||
path = ("{api}/rooms/{room}/invite?"
|
|
||||||
"access_token={access_token}").format(
|
|
||||||
api=MATRIX_API_PATH,
|
|
||||||
room=room_id,
|
|
||||||
access_token=server.access_token)
|
|
||||||
|
|
||||||
self.request = HttpRequest(
|
|
||||||
RequestType.POST,
|
|
||||||
server.address,
|
|
||||||
server.port,
|
|
||||||
path,
|
|
||||||
data
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class MatrixUser:
|
class MatrixUser:
|
||||||
def __init__(self, name, display_name):
|
def __init__(self, name, display_name):
|
||||||
self.name = name # type: str
|
self.name = name # type: str
|
||||||
|
@ -355,101 +122,6 @@ def server_config_change_cb(server_name, option):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
class MatrixServer:
|
|
||||||
# pylint: disable=too-many-instance-attributes
|
|
||||||
def __init__(self, name, config_file):
|
|
||||||
# type: (str, weechat.config) -> None
|
|
||||||
self.name = name # type: str
|
|
||||||
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.user = "" # type: str
|
|
||||||
self.password = "" # type: str
|
|
||||||
|
|
||||||
self.rooms = dict() # type: Dict[str, MatrixRoom]
|
|
||||||
self.buffers = dict() # type: Dict[str, weechat.buffer]
|
|
||||||
self.server_buffer = None # type: weechat.buffer
|
|
||||||
self.fd_hook = None # type: weechat.hook
|
|
||||||
self.timer_hook = None # type: weechat.hook
|
|
||||||
self.numeric_address = "" # type: str
|
|
||||||
|
|
||||||
self.autoconnect = False # type: bool
|
|
||||||
self.connected = False # type: bool
|
|
||||||
self.connecting = False # type: bool
|
|
||||||
self.reconnect_count = 0 # type: int
|
|
||||||
self.socket = None # type: ssl.SSLSocket
|
|
||||||
self.ssl_context = ssl.create_default_context() # type: ssl.SSLContext
|
|
||||||
|
|
||||||
self.access_token = None # type: str
|
|
||||||
self.next_batch = None # type: str
|
|
||||||
self.transaction_id = 0 # type: int
|
|
||||||
|
|
||||||
self.http_parser = HttpParser() # type: HttpParser
|
|
||||||
self.http_buffer = [] # type: List[bytes]
|
|
||||||
|
|
||||||
# Queue of messages we need to send off.
|
|
||||||
self.send_queue = deque() # type: Deque[MatrixMessage]
|
|
||||||
# Queue of messages we send off and are waiting a response for
|
|
||||||
self.receive_queue = deque() # type: Deque[MatrixMessage]
|
|
||||||
self.message_queue = deque() # type: Deque[MatrixMessage]
|
|
||||||
self.ignore_event_list = [] # type: List[str]
|
|
||||||
|
|
||||||
self._create_options(config_file)
|
|
||||||
|
|
||||||
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(
|
|
||||||
'ssl_verify', 'boolean', '', 0, 0, 'on',
|
|
||||||
(
|
|
||||||
"Check that the SSL connection is fully trusted"
|
|
||||||
"is starting"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'username', 'string', '', 0, 0, '',
|
|
||||||
"Username to use on server"
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'password', 'string', '', 0, 0, '',
|
|
||||||
"Password for server"
|
|
||||||
),
|
|
||||||
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, "",
|
|
||||||
"", "server_config_change_cb", self.name, "", "")
|
|
||||||
|
|
||||||
|
|
||||||
def wrap_socket(server, file_descriptor):
|
def wrap_socket(server, file_descriptor):
|
||||||
# type: (MatrixServer, int) -> socket.socket
|
# type: (MatrixServer, int) -> socket.socket
|
||||||
sock = None # type: socket.socket
|
sock = None # type: socket.socket
|
||||||
|
@ -1231,7 +903,7 @@ def matrix_handle_message(
|
||||||
if message_type is MessageType.LOGIN:
|
if message_type is MessageType.LOGIN:
|
||||||
server.access_token = response["access_token"]
|
server.access_token = response["access_token"]
|
||||||
server.user_id = response["user_id"]
|
server.user_id = response["user_id"]
|
||||||
message = MatrixMessage(server, MessageType.SYNC)
|
message = MatrixMessage(server, GLOBAL_OPTIONS, MessageType.SYNC)
|
||||||
send_or_queue(server, message)
|
send_or_queue(server, message)
|
||||||
|
|
||||||
elif message_type is MessageType.SYNC:
|
elif message_type is MessageType.SYNC:
|
||||||
|
@ -1301,7 +973,7 @@ def matrix_handle_message(
|
||||||
|
|
||||||
|
|
||||||
def matrix_sync(server):
|
def matrix_sync(server):
|
||||||
message = MatrixMessage(server, MessageType.SYNC)
|
message = MatrixMessage(server, GLOBAL_OPTIONS, MessageType.SYNC)
|
||||||
server.send_queue.append(message)
|
server.send_queue.append(message)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1314,6 +986,7 @@ def matrix_login(server):
|
||||||
|
|
||||||
message = MatrixMessage(
|
message = MatrixMessage(
|
||||||
server,
|
server,
|
||||||
|
GLOBAL_OPTIONS,
|
||||||
MessageType.LOGIN,
|
MessageType.LOGIN,
|
||||||
data=post_data
|
data=post_data
|
||||||
)
|
)
|
||||||
|
@ -1423,8 +1096,7 @@ def receive_cb(server_name, file_descriptor):
|
||||||
s=status))
|
s=status))
|
||||||
|
|
||||||
# Message done, reset the parser state.
|
# Message done, reset the parser state.
|
||||||
server.http_parser = HttpParser()
|
server.reset_parser()
|
||||||
server.http_buffer = []
|
|
||||||
|
|
||||||
handle_http_response(server, message)
|
handle_http_response(server, message)
|
||||||
break
|
break
|
||||||
|
@ -1670,7 +1342,7 @@ def room_input_cb(server_name, buffer, input_data):
|
||||||
"room_id": room_id
|
"room_id": room_id
|
||||||
}
|
}
|
||||||
|
|
||||||
message = MatrixMessage(server, MessageType.SEND,
|
message = MatrixMessage(server, GLOBAL_OPTIONS, MessageType.SEND,
|
||||||
data=body, room_id=room_id,
|
data=body, room_id=room_id,
|
||||||
extra_data=extra_data)
|
extra_data=extra_data)
|
||||||
|
|
||||||
|
@ -1735,7 +1407,7 @@ def matrix_config_server_read_cb(
|
||||||
if server_name in SERVERS:
|
if server_name in SERVERS:
|
||||||
server = SERVERS[server_name]
|
server = SERVERS[server_name]
|
||||||
else:
|
else:
|
||||||
server = MatrixServer(server_name, config_file)
|
server = MatrixServer(server_name, W, config_file)
|
||||||
SERVERS[server.name] = server
|
SERVERS[server.name] = server
|
||||||
|
|
||||||
# Ignore invalid options
|
# Ignore invalid options
|
||||||
|
@ -2212,7 +1884,7 @@ def matrix_server_command_add(args):
|
||||||
W.prnt("", message)
|
W.prnt("", message)
|
||||||
return
|
return
|
||||||
|
|
||||||
server = MatrixServer(args[0], CONFIG)
|
server = MatrixServer(args[0], W, CONFIG)
|
||||||
SERVERS[server.name] = server
|
SERVERS[server.name] = server
|
||||||
|
|
||||||
if len(args) >= 2:
|
if len(args) >= 2:
|
||||||
|
@ -2471,7 +2143,7 @@ def matrix_command_completion_cb(data, completion_item, buffer, completion):
|
||||||
|
|
||||||
|
|
||||||
def create_default_server(config_file):
|
def create_default_server(config_file):
|
||||||
server = MatrixServer('matrix.org', config_file)
|
server = MatrixServer('matrix.org', W, config_file)
|
||||||
SERVERS[server.name] = server
|
SERVERS[server.name] = server
|
||||||
|
|
||||||
W.config_option_set(server.options["address"], "matrix.org", 1)
|
W.config_option_set(server.options["address"], "matrix.org", 1)
|
||||||
|
@ -2527,6 +2199,7 @@ def matrix_command_topic_cb(data, buffer, command):
|
||||||
|
|
||||||
message = MatrixMessage(
|
message = MatrixMessage(
|
||||||
server,
|
server,
|
||||||
|
GLOBAL_OPTIONS,
|
||||||
MessageType.STATE,
|
MessageType.STATE,
|
||||||
data=body,
|
data=body,
|
||||||
room_id=room_id,
|
room_id=room_id,
|
||||||
|
@ -2553,7 +2226,7 @@ def matrix_fetch_old_messages(server, room_id):
|
||||||
if not prev_batch:
|
if not prev_batch:
|
||||||
return
|
return
|
||||||
|
|
||||||
message = MatrixMessage(server, MessageType.ROOM_MSG,
|
message = MatrixMessage(server, GLOBAL_OPTIONS, MessageType.ROOM_MSG,
|
||||||
room_id=room_id, extra_id=prev_batch)
|
room_id=room_id, extra_id=prev_batch)
|
||||||
|
|
||||||
send_or_queue(server, message)
|
send_or_queue(server, message)
|
||||||
|
@ -2611,7 +2284,12 @@ def matrix_command_join_cb(data, buffer, command):
|
||||||
return
|
return
|
||||||
|
|
||||||
_, room_id = split_args
|
_, room_id = split_args
|
||||||
message = MatrixMessage(server, MessageType.JOIN, room_id=room_id)
|
message = MatrixMessage(
|
||||||
|
server,
|
||||||
|
GLOBAL_OPTIONS,
|
||||||
|
MessageType.JOIN,
|
||||||
|
room_id=room_id
|
||||||
|
)
|
||||||
send_or_queue(server, message)
|
send_or_queue(server, message)
|
||||||
|
|
||||||
for server in SERVERS.values():
|
for server in SERVERS.values():
|
||||||
|
@ -2647,7 +2325,12 @@ def matrix_command_part_cb(data, buffer, command):
|
||||||
rooms = rooms.split(" ")
|
rooms = rooms.split(" ")
|
||||||
|
|
||||||
for room_id in rooms:
|
for room_id in rooms:
|
||||||
message = MatrixMessage(server, MessageType.PART, room_id=room_id)
|
message = MatrixMessage(
|
||||||
|
server,
|
||||||
|
GLOBAL_OPTIONS,
|
||||||
|
MessageType.PART,
|
||||||
|
room_id=room_id
|
||||||
|
)
|
||||||
send_or_queue(server, message)
|
send_or_queue(server, message)
|
||||||
|
|
||||||
for server in SERVERS.values():
|
for server in SERVERS.values():
|
||||||
|
@ -2681,6 +2364,7 @@ def matrix_command_invite_cb(data, buffer, command):
|
||||||
|
|
||||||
message = MatrixMessage(
|
message = MatrixMessage(
|
||||||
server,
|
server,
|
||||||
|
GLOBAL_OPTIONS,
|
||||||
MessageType.INVITE,
|
MessageType.INVITE,
|
||||||
room_id=room_id,
|
room_id=room_id,
|
||||||
data=body
|
data=body
|
||||||
|
@ -2787,6 +2471,7 @@ def matrix_redact_command_cb(data, buffer, args):
|
||||||
|
|
||||||
message = MatrixMessage(
|
message = MatrixMessage(
|
||||||
server,
|
server,
|
||||||
|
GLOBAL_OPTIONS,
|
||||||
MessageType.REDACT,
|
MessageType.REDACT,
|
||||||
data=body,
|
data=body,
|
||||||
room_id=room_id,
|
room_id=room_id,
|
||||||
|
|
Loading…
Add table
Reference in a new issue