More splitting.

This commit is contained in:
poljar (Damir Jelić) 2018-01-26 14:38:46 +01:00
parent 6e7ed8333f
commit 7328dcf7ab
4 changed files with 400 additions and 349 deletions

200
matrix/api.py Normal file
View 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
View 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
View 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 = []