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 = []
|
||||
Loading…
Add table
Add a link
Reference in a new issue