matrix: Change the way responses and events are executed.
This commit is contained in:
parent
e7208ded62
commit
38d6a14a33
6 changed files with 218 additions and 132 deletions
1
main.py
1
main.py
|
@ -46,6 +46,7 @@ from matrix.commands import (hook_commands, hook_page_up, matrix_command_cb,
|
||||||
matrix_command_pgup_cb, matrix_redact_command_cb,
|
matrix_command_pgup_cb, matrix_redact_command_cb,
|
||||||
matrix_command_buf_clear_cb, matrix_me_command_cb,
|
matrix_command_buf_clear_cb, matrix_me_command_cb,
|
||||||
matrix_command_kick_cb)
|
matrix_command_kick_cb)
|
||||||
|
from matrix.buffer import room_buffer_input_cb, room_buffer_close_cb
|
||||||
|
|
||||||
from matrix.server import (
|
from matrix.server import (
|
||||||
MatrixServer,
|
MatrixServer,
|
||||||
|
|
|
@ -28,7 +28,7 @@ from builtins import super
|
||||||
@utf8_decode
|
@utf8_decode
|
||||||
def room_buffer_input_cb(server_name, buffer, input_data):
|
def room_buffer_input_cb(server_name, buffer, input_data):
|
||||||
server = SERVERS[server_name]
|
server = SERVERS[server_name]
|
||||||
room, room_buffer = server.find_room(buffer)
|
room, room_buffer = server.find_room_from_ptr(buffer)
|
||||||
|
|
||||||
if not room_buffer:
|
if not room_buffer:
|
||||||
# TODO log error
|
# TODO log error
|
||||||
|
@ -40,9 +40,7 @@ def room_buffer_input_cb(server_name, buffer, input_data):
|
||||||
|
|
||||||
formatted_data = Formatted.from_input_line(input_data)
|
formatted_data = Formatted.from_input_line(input_data)
|
||||||
|
|
||||||
if room.encrypted:
|
server.send_room_message(room, formatted_data)
|
||||||
server.send_room_message(room.id, formatted_data)
|
|
||||||
return W.WEECHAT_RC_OK
|
|
||||||
|
|
||||||
return W.WEECHAT_RC_OK
|
return W.WEECHAT_RC_OK
|
||||||
|
|
||||||
|
@ -86,6 +84,13 @@ class WeechatChannelBuffer(object):
|
||||||
"notify_message",
|
"notify_message",
|
||||||
"log1"
|
"log1"
|
||||||
],
|
],
|
||||||
|
"self_message": [
|
||||||
|
SCRIPT_NAME + "_message",
|
||||||
|
"notify_none",
|
||||||
|
"no_highlight",
|
||||||
|
"self_msg",
|
||||||
|
"log1"
|
||||||
|
],
|
||||||
"old_message": [
|
"old_message": [
|
||||||
SCRIPT_NAME + "_message",
|
SCRIPT_NAME + "_message",
|
||||||
"notify_message",
|
"notify_message",
|
||||||
|
@ -107,6 +112,10 @@ class WeechatChannelBuffer(object):
|
||||||
"invite": [
|
"invite": [
|
||||||
SCRIPT_NAME + "_invite",
|
SCRIPT_NAME + "_invite",
|
||||||
"log4"
|
"log4"
|
||||||
|
],
|
||||||
|
"topic": [
|
||||||
|
SCRIPT_NAME + "_topic",
|
||||||
|
"log3",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,13 +132,17 @@ class WeechatChannelBuffer(object):
|
||||||
name,
|
name,
|
||||||
"room_buffer_input_cb",
|
"room_buffer_input_cb",
|
||||||
server_name,
|
server_name,
|
||||||
"room_buffer_input_cb",
|
"room_buffer_close_cb",
|
||||||
server_name,
|
server_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.name = ""
|
self.name = ""
|
||||||
self.users = {} # type: Dict[str, RoomUser]
|
self.users = {} # type: Dict[str, RoomUser]
|
||||||
|
|
||||||
|
self.topic = ""
|
||||||
|
self.topic_author = ""
|
||||||
|
self.topic_date = None
|
||||||
|
|
||||||
W.buffer_set(self._ptr, "localvar_set_type", 'channel')
|
W.buffer_set(self._ptr, "localvar_set_type", 'channel')
|
||||||
W.buffer_set(self._ptr, "type", 'formatted')
|
W.buffer_set(self._ptr, "type", 'formatted')
|
||||||
|
|
||||||
|
@ -216,7 +229,7 @@ class WeechatChannelBuffer(object):
|
||||||
|
|
||||||
def _message_tags(self, user, message_type):
|
def _message_tags(self, user, message_type):
|
||||||
# type: (str, RoomUser, str) -> List[str]
|
# type: (str, RoomUser, str) -> List[str]
|
||||||
tags = self.tags[message_type].copy()
|
tags = list(self.tags[message_type])
|
||||||
|
|
||||||
tags.append("nick_{nick}".format(nick=user.nick))
|
tags.append("nick_{nick}".format(nick=user.nick))
|
||||||
|
|
||||||
|
@ -235,10 +248,10 @@ class WeechatChannelBuffer(object):
|
||||||
# A message from a non joined user
|
# A message from a non joined user
|
||||||
return RoomUser(nick)
|
return RoomUser(nick)
|
||||||
|
|
||||||
def message(self, nick, message, date):
|
def message(self, nick, message, date, tags=[]):
|
||||||
# type: (str, str, int, str) -> None
|
# type: (str, str, int, str) -> None
|
||||||
user = self._get_user(nick)
|
user = self._get_user(nick)
|
||||||
tags = self._message_tags(user, "message")
|
tags = tags or self._message_tags(user, "message")
|
||||||
|
|
||||||
prefix_string = ("" if not user.prefix else "{}{}{}".format(
|
prefix_string = ("" if not user.prefix else "{}{}{}".format(
|
||||||
W.color(self._get_prefix_color(user.prefix)),
|
W.color(self._get_prefix_color(user.prefix)),
|
||||||
|
@ -264,10 +277,10 @@ class WeechatChannelBuffer(object):
|
||||||
|
|
||||||
self.message(nick, data, date)
|
self.message(nick, data, date)
|
||||||
|
|
||||||
def action(self, nick, message, date):
|
def action(self, nick, message, date, tags=[]):
|
||||||
# type: (str, str, int) -> None
|
# type: (str, str, int) -> None
|
||||||
user = self._get_user(nick)
|
user = self._get_user(nick)
|
||||||
tags = self._message_tags(user, "action")
|
tags = tags or self._message_tags(user, "action")
|
||||||
|
|
||||||
nick_prefix = ("" if not user.prefix else "{}{}{}".format(
|
nick_prefix = ("" if not user.prefix else "{}{}{}".format(
|
||||||
W.color(self._get_prefix_color(user.prefix)),
|
W.color(self._get_prefix_color(user.prefix)),
|
||||||
|
@ -282,7 +295,7 @@ class WeechatChannelBuffer(object):
|
||||||
nick_color=W.color(user.color),
|
nick_color=W.color(user.color),
|
||||||
author=nick,
|
author=nick,
|
||||||
ncolor=W.color("reset"),
|
ncolor=W.color("reset"),
|
||||||
msg=self.message)
|
msg=message)
|
||||||
|
|
||||||
self.print_date_tags(data, date, tags)
|
self.print_date_tags(data, date, tags)
|
||||||
|
|
||||||
|
@ -293,9 +306,9 @@ class WeechatChannelBuffer(object):
|
||||||
|
|
||||||
if user.prefix == "&":
|
if user.prefix == "&":
|
||||||
group_name = "000|o"
|
group_name = "000|o"
|
||||||
elif user.power_level == "@":
|
elif user.prefix == "@":
|
||||||
group_name = "001|h"
|
group_name = "001|h"
|
||||||
elif user.power_level > "+":
|
elif user.prefix > "+":
|
||||||
group_name = "002|v"
|
group_name = "002|v"
|
||||||
|
|
||||||
return group_name
|
return group_name
|
||||||
|
@ -400,3 +413,41 @@ class WeechatChannelBuffer(object):
|
||||||
def kick(self, user, date, message=True, extra_tags=[]):
|
def kick(self, user, date, message=True, extra_tags=[]):
|
||||||
# type: (WeechatUser, int, Optional[bool], Optional[List[str]]) -> None
|
# type: (WeechatUser, int, Optional[bool], Optional[List[str]]) -> None
|
||||||
self._leave(user, date, message, "kick", extra_tags=[])
|
self._leave(user, date, message, "kick", extra_tags=[])
|
||||||
|
|
||||||
|
def _print_topic(self, nick, topic, date):
|
||||||
|
user = self._get_user(nick)
|
||||||
|
tags = self._message_tags(user, "topic")
|
||||||
|
|
||||||
|
data = ("{prefix}{nick} has changed "
|
||||||
|
"the topic for {chan_color}{room}{ncolor} "
|
||||||
|
"to \"{topic}\"").format(
|
||||||
|
prefix=W.prefix("network"),
|
||||||
|
nick=user.nick,
|
||||||
|
chan_color=W.color("chat_channel"),
|
||||||
|
ncolor=W.color("reset"),
|
||||||
|
room=self.name,
|
||||||
|
topic=topic
|
||||||
|
)
|
||||||
|
|
||||||
|
self.print_date_tags(data, date, tags)
|
||||||
|
|
||||||
|
def topic(self, nick, topic, date, message=True):
|
||||||
|
W.buffer_set(self._ptr, "title", topic)
|
||||||
|
|
||||||
|
if message:
|
||||||
|
self._print_topic(nick, topic, date)
|
||||||
|
|
||||||
|
self.topic = topic
|
||||||
|
self.topic_author = nick
|
||||||
|
self.topic_date = date
|
||||||
|
|
||||||
|
def self_message(self, nick, message, date):
|
||||||
|
user = self._get_user(nick)
|
||||||
|
tags = self._message_tags(user, "self_message")
|
||||||
|
self.message(nick, message, date, tags)
|
||||||
|
|
||||||
|
def self_action(self, nick, message, date):
|
||||||
|
user = self._get_user(nick)
|
||||||
|
tags = self._message_tags(user, "self_message")
|
||||||
|
tags.append(SCRIPT_NAME + "_action")
|
||||||
|
self.action(nick, message, date, tags)
|
||||||
|
|
|
@ -73,8 +73,9 @@ class WeechatArgParse(argparse.ArgumentParser):
|
||||||
|
|
||||||
def error(self, message):
|
def error(self, message):
|
||||||
m = ("{prefix}Error: {message} for command {command} "
|
m = ("{prefix}Error: {message} for command {command} "
|
||||||
"(see /help {command})").format(prefix=W.prefix("error"),
|
"(see /help {command})").format(prefix=W.prefix("error"),
|
||||||
message=message, command=self.prog)
|
message=message,
|
||||||
|
command=self.prog)
|
||||||
W.prnt("", m)
|
W.prnt("", m)
|
||||||
raise ParseError
|
raise ParseError
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,12 @@ from operator import itemgetter
|
||||||
from matrix.globals import W
|
from matrix.globals import W
|
||||||
from matrix.utils import (tags_for_message, sanitize_id, sanitize_token,
|
from matrix.utils import (tags_for_message, sanitize_id, sanitize_token,
|
||||||
sanitize_text, tags_from_line_data)
|
sanitize_text, tags_from_line_data)
|
||||||
from matrix.rooms import (matrix_create_room_buffer, RoomInfo, RoomMessageText,
|
from matrix.rooms import (RoomInfo, RoomMessageText,
|
||||||
RoomMessageEvent, RoomRedactedMessageEvent,
|
RoomMessageEvent, RoomRedactedMessageEvent,
|
||||||
RoomMessageEmote)
|
RoomMessageEmote)
|
||||||
|
|
||||||
from matrix.encryption import OlmDeviceKey, OneTimeKey
|
from matrix.encryption import OlmDeviceKey, OneTimeKey
|
||||||
|
from .buffer import RoomUser
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from olm.session import OlmMessage, OlmPreKeyMessage
|
from olm.session import OlmMessage, OlmPreKeyMessage
|
||||||
|
@ -657,7 +658,7 @@ class MatrixSyncEvent(MatrixEvent):
|
||||||
info = self.joined_room_infos.pop()
|
info = self.joined_room_infos.pop()
|
||||||
|
|
||||||
if info.room_id not in server.buffers:
|
if info.room_id not in server.buffers:
|
||||||
matrix_create_room_buffer(server, info.room_id)
|
server.create_room_buffer(info.room_id)
|
||||||
|
|
||||||
room = server.rooms[info.room_id]
|
room = server.rooms[info.room_id]
|
||||||
|
|
||||||
|
|
138
matrix/rooms.py
138
matrix/rooms.py
|
@ -156,45 +156,15 @@ class MatrixUser:
|
||||||
# yapf: enable
|
# yapf: enable
|
||||||
|
|
||||||
|
|
||||||
def matrix_create_room_buffer(server, room_id):
|
|
||||||
# type: (MatrixServer, str) -> None
|
|
||||||
buf = W.buffer_new(room_id, "room_input_cb", server.name, "room_close_cb",
|
|
||||||
server.name)
|
|
||||||
|
|
||||||
W.buffer_set(buf, "localvar_set_type", 'channel')
|
|
||||||
W.buffer_set(buf, "type", 'formatted')
|
|
||||||
|
|
||||||
W.buffer_set(buf, "localvar_set_channel", room_id)
|
|
||||||
|
|
||||||
W.buffer_set(buf, "localvar_set_nick", server.user)
|
|
||||||
|
|
||||||
W.buffer_set(buf, "localvar_set_server", server.name)
|
|
||||||
|
|
||||||
short_name = strip_matrix_server(room_id)
|
|
||||||
W.buffer_set(buf, "short_name", short_name)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
W.buffer_set(buf, "nicklist", "1")
|
|
||||||
W.buffer_set(buf, "nicklist_display_groups", "0")
|
|
||||||
|
|
||||||
# TODO make this configurable
|
|
||||||
W.buffer_set(buf, "highlight_tags_restrict", "matrix_message")
|
|
||||||
|
|
||||||
server.buffers[room_id] = buf
|
|
||||||
server.rooms[room_id] = MatrixRoom(room_id)
|
|
||||||
|
|
||||||
|
|
||||||
class RoomInfo():
|
class RoomInfo():
|
||||||
|
|
||||||
def __init__(self, room_id, prev_batch, events):
|
def __init__(self, room_id, prev_batch, state, timeline):
|
||||||
# type: (str, str, List[Any], List[Any]) -> None
|
# type: (str, str, List[Any], List[Any]) -> None
|
||||||
self.room_id = room_id
|
self.room_id = room_id
|
||||||
self.prev_batch = prev_batch
|
self.prev_batch = prev_batch
|
||||||
self.events = deque(events)
|
|
||||||
|
self.state = deque(state)
|
||||||
|
self.timeline = deque(timeline)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _message_from_event(event):
|
def _message_from_event(event):
|
||||||
|
@ -219,66 +189,40 @@ class RoomInfo():
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
if event_dict["content"]["membership"] == "join":
|
if event_dict["content"]["membership"] == "join":
|
||||||
event = RoomMemberJoin.from_dict(event_dict)
|
return RoomMemberJoin.from_dict(event_dict)
|
||||||
|
|
||||||
try:
|
|
||||||
message = RoomMembershipMessage(
|
|
||||||
event.event_id, event.sender, event.timestamp,
|
|
||||||
"has joined", "join")
|
|
||||||
|
|
||||||
return event, message
|
|
||||||
except AttributeError:
|
|
||||||
return event, None
|
|
||||||
|
|
||||||
elif event_dict["content"]["membership"] == "leave":
|
elif event_dict["content"]["membership"] == "leave":
|
||||||
event = RoomMemberLeave.from_dict(event_dict)
|
return RoomMemberLeave.from_dict(event_dict)
|
||||||
|
|
||||||
try:
|
return None
|
||||||
msg = ("has left" if event.sender == event.leaving_user else
|
|
||||||
"has been kicked")
|
|
||||||
message = RoomMembershipMessage(
|
|
||||||
event.event_id, event.leaving_user, event.timestamp, msg, "quit")
|
|
||||||
return event, message
|
|
||||||
except AttributeError:
|
|
||||||
return event, None
|
|
||||||
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_event(olm, room_id, event_dict):
|
def parse_event(olm, room_id, event_dict):
|
||||||
# type: (Dict[Any, Any]) -> (RoomEvent, RoomEvent)
|
# type: (Dict[Any, Any]) -> (RoomEvent, RoomEvent)
|
||||||
state_event = None
|
event = None
|
||||||
message_event = None
|
|
||||||
|
|
||||||
if "redacted_by" in event_dict["unsigned"]:
|
if "redacted_by" in event_dict["unsigned"]:
|
||||||
message_event = RoomRedactedMessageEvent.from_dict(event_dict)
|
event = RoomRedactedMessageEvent.from_dict(event_dict)
|
||||||
elif event_dict["type"] == "m.room.message":
|
elif event_dict["type"] == "m.room.message":
|
||||||
message_event = RoomInfo._message_from_event(event_dict)
|
event = RoomInfo._message_from_event(event_dict)
|
||||||
elif event_dict["type"] == "m.room.member":
|
elif event_dict["type"] == "m.room.member":
|
||||||
state_event, message_event = (
|
event = RoomInfo._membership_from_dict(event_dict)
|
||||||
RoomInfo._membership_from_dict(event_dict))
|
|
||||||
elif event_dict["type"] == "m.room.power_levels":
|
elif event_dict["type"] == "m.room.power_levels":
|
||||||
state_event = RoomPowerLevels.from_dict(event_dict)
|
event = RoomPowerLevels.from_dict(event_dict)
|
||||||
elif event_dict["type"] == "m.room.topic":
|
elif event_dict["type"] == "m.room.topic":
|
||||||
state_event = RoomTopicEvent.from_dict(event_dict)
|
event = RoomTopicEvent.from_dict(event_dict)
|
||||||
message_event = RoomTopiceMessage(
|
|
||||||
state_event.event_id,
|
|
||||||
state_event.sender,
|
|
||||||
state_event.timestamp,
|
|
||||||
state_event.topic)
|
|
||||||
elif event_dict["type"] == "m.room.redaction":
|
elif event_dict["type"] == "m.room.redaction":
|
||||||
message_event = RoomRedactionEvent.from_dict(event_dict)
|
event = RoomRedactionEvent.from_dict(event_dict)
|
||||||
elif event_dict["type"] == "m.room.name":
|
elif event_dict["type"] == "m.room.name":
|
||||||
state_event = RoomNameEvent.from_dict(event_dict)
|
event = RoomNameEvent.from_dict(event_dict)
|
||||||
elif event_dict["type"] == "m.room.canonical_alias":
|
elif event_dict["type"] == "m.room.canonical_alias":
|
||||||
state_event = RoomAliasEvent.from_dict(event_dict)
|
event = RoomAliasEvent.from_dict(event_dict)
|
||||||
elif event_dict["type"] == "m.room.encryption":
|
elif event_dict["type"] == "m.room.encryption":
|
||||||
state_event = RoomEncryptionEvent.from_dict(event_dict)
|
event = RoomEncryptionEvent.from_dict(event_dict)
|
||||||
elif event_dict["type"] == "m.room.encrypted":
|
elif event_dict["type"] == "m.room.encrypted":
|
||||||
state_event, message_event = RoomInfo._decrypt_event(olm, room_id,
|
event = RoomInfo._decrypt_event(olm, room_id, event_dict)
|
||||||
event_dict)
|
|
||||||
|
|
||||||
return state_event, message_event
|
return event
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _decrypt_event(olm, room_id, event_dict):
|
def _decrypt_event(olm, room_id, event_dict):
|
||||||
|
@ -287,7 +231,7 @@ class RoomInfo():
|
||||||
plaintext = olm.group_decrypt(room_id, session_id, ciphertext)
|
plaintext = olm.group_decrypt(room_id, session_id, ciphertext)
|
||||||
|
|
||||||
if not plaintext:
|
if not plaintext:
|
||||||
return None, None
|
return None
|
||||||
|
|
||||||
parsed_plaintext = json.loads(plaintext, encoding="utf-8")
|
parsed_plaintext = json.loads(plaintext, encoding="utf-8")
|
||||||
|
|
||||||
|
@ -297,18 +241,13 @@ class RoomInfo():
|
||||||
return RoomInfo.parse_event(olm, room_id, event_dict)
|
return RoomInfo.parse_event(olm, room_id, event_dict)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_events(olm, room_id, parsed_dict, messages=True, state=True):
|
def _parse_events(olm, room_id, parsed_dict):
|
||||||
state_events = []
|
events = []
|
||||||
message_events = []
|
|
||||||
|
|
||||||
if not messages and not state:
|
|
||||||
return []
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for event in parsed_dict:
|
for event in parsed_dict:
|
||||||
m_event, s_event = RoomInfo.parse_event(olm, room_id, event)
|
e = RoomInfo.parse_event(olm, room_id, event)
|
||||||
state_events.append(m_event)
|
events.append(e)
|
||||||
message_events.append(s_event)
|
|
||||||
except (ValueError, TypeError, KeyError) as error:
|
except (ValueError, TypeError, KeyError) as error:
|
||||||
message = ("{prefix}matrix: Error parsing "
|
message = ("{prefix}matrix: Error parsing "
|
||||||
"room event of type {type}: {error}\n{event}").format(
|
"room event of type {type}: {error}\n{event}").format(
|
||||||
|
@ -319,14 +258,6 @@ class RoomInfo():
|
||||||
W.prnt("", message)
|
W.prnt("", message)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
events = []
|
|
||||||
|
|
||||||
if state:
|
|
||||||
events = events + state_events
|
|
||||||
|
|
||||||
if messages:
|
|
||||||
events = events + message_events
|
|
||||||
|
|
||||||
return events
|
return events
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -336,12 +267,23 @@ class RoomInfo():
|
||||||
state_dict = parsed_dict['state']['events']
|
state_dict = parsed_dict['state']['events']
|
||||||
timeline_dict = parsed_dict['timeline']['events']
|
timeline_dict = parsed_dict['timeline']['events']
|
||||||
|
|
||||||
state_events = RoomInfo._parse_events(olm, room_id, state_dict, messages=False)
|
state_events = RoomInfo._parse_events(
|
||||||
timeline_events = RoomInfo._parse_events(olm, room_id, timeline_dict)
|
olm,
|
||||||
|
room_id,
|
||||||
|
state_dict
|
||||||
|
)
|
||||||
|
timeline_events = RoomInfo._parse_events(
|
||||||
|
olm,
|
||||||
|
room_id,
|
||||||
|
timeline_dict
|
||||||
|
)
|
||||||
|
|
||||||
events = state_events + timeline_events
|
return cls(
|
||||||
|
room_id,
|
||||||
return cls(room_id, prev_batch, list(filter(None, events)))
|
prev_batch,
|
||||||
|
list(filter(None, state_events)),
|
||||||
|
list(filter(None, timeline_events))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class RoomEvent():
|
class RoomEvent():
|
||||||
|
|
124
matrix/server.py
124
matrix/server.py
|
@ -29,10 +29,19 @@ from http_parser.pyparser import HttpParser
|
||||||
|
|
||||||
from matrix.plugin_options import Option, DebugType
|
from matrix.plugin_options import Option, DebugType
|
||||||
from matrix.utils import (key_from_value, prnt_debug, server_buffer_prnt,
|
from matrix.utils import (key_from_value, prnt_debug, server_buffer_prnt,
|
||||||
create_server_buffer, tags_for_message)
|
create_server_buffer, tags_for_message,
|
||||||
|
server_ts_to_weechat, shorten_sender)
|
||||||
from matrix.utf import utf8_decode
|
from matrix.utf import utf8_decode
|
||||||
from matrix.globals import W, SERVERS, OPTIONS
|
from matrix.globals import W, SERVERS, OPTIONS
|
||||||
import matrix.api as API
|
import matrix.api as API
|
||||||
|
from .buffer import WeechatChannelBuffer, RoomUser
|
||||||
|
from .rooms import (
|
||||||
|
MatrixRoom,
|
||||||
|
RoomMessageText,
|
||||||
|
RoomMessageEmote,
|
||||||
|
MatrixUser,
|
||||||
|
RoomMemberJoin
|
||||||
|
)
|
||||||
from matrix.api import (
|
from matrix.api import (
|
||||||
MatrixClient,
|
MatrixClient,
|
||||||
MatrixSyncMessage,
|
MatrixSyncMessage,
|
||||||
|
@ -40,10 +49,13 @@ from matrix.api import (
|
||||||
MatrixKeyUploadMessage,
|
MatrixKeyUploadMessage,
|
||||||
MatrixKeyQueryMessage,
|
MatrixKeyQueryMessage,
|
||||||
MatrixToDeviceMessage,
|
MatrixToDeviceMessage,
|
||||||
|
MatrixSendMessage,
|
||||||
MatrixEncryptedMessage,
|
MatrixEncryptedMessage,
|
||||||
MatrixKeyClaimMessage
|
MatrixKeyClaimMessage
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .events import MatrixSendEvent
|
||||||
|
|
||||||
from matrix.encryption import (
|
from matrix.encryption import (
|
||||||
Olm,
|
Olm,
|
||||||
EncryptionError,
|
EncryptionError,
|
||||||
|
@ -77,6 +89,7 @@ class MatrixServer:
|
||||||
self.password = "" # type: str
|
self.password = "" # type: str
|
||||||
|
|
||||||
self.rooms = dict() # type: Dict[str, MatrixRoom]
|
self.rooms = dict() # type: Dict[str, MatrixRoom]
|
||||||
|
self.room_buffers = dict() # type: Dict[str, WeechatChannelBuffer]
|
||||||
self.buffers = dict() # type: Dict[str, weechat.buffer]
|
self.buffers = dict() # type: Dict[str, weechat.buffer]
|
||||||
self.server_buffer = None # type: weechat.buffer
|
self.server_buffer = None # type: weechat.buffer
|
||||||
self.fd_hook = None # type: weechat.hook
|
self.fd_hook = None # type: weechat.hook
|
||||||
|
@ -433,7 +446,7 @@ class MatrixServer:
|
||||||
|
|
||||||
if self.server_buffer:
|
if self.server_buffer:
|
||||||
message = ("{prefix}matrix: disconnected from server"
|
message = ("{prefix}matrix: disconnected from server"
|
||||||
).format(prefix=W.prefix("network"))
|
).format(prefix=W.prefix("network"))
|
||||||
server_buffer_prnt(self, message)
|
server_buffer_prnt(self, message)
|
||||||
|
|
||||||
if reconnect:
|
if reconnect:
|
||||||
|
@ -486,16 +499,20 @@ class MatrixServer:
|
||||||
message = MatrixSyncMessage(self.client, self.next_batch, limit)
|
message = MatrixSyncMessage(self.client, self.next_batch, limit)
|
||||||
self.send_queue.append(message)
|
self.send_queue.append(message)
|
||||||
|
|
||||||
|
def _send_unencrypted_message(self, room_id, formatted_data):
|
||||||
|
message = MatrixSendMessage(
|
||||||
|
self.client, room_id=room_id, formatted_message=formatted_data)
|
||||||
|
self.send_or_queue(message)
|
||||||
|
|
||||||
def send_room_message(
|
def send_room_message(
|
||||||
self,
|
self,
|
||||||
room_id,
|
room,
|
||||||
formatted_data,
|
formatted_data,
|
||||||
already_claimed=False
|
already_claimed=False
|
||||||
):
|
):
|
||||||
# type: (str, Formatted) -> None
|
# type: (str, Formatted) -> None
|
||||||
room = self.rooms[room_id]
|
|
||||||
|
|
||||||
if not room.encrypted:
|
if not room.encrypted:
|
||||||
|
self._send_unencrypted_message(room.room_id, formatted_data)
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO don't send messages unless all the devices are verified
|
# TODO don't send messages unless all the devices are verified
|
||||||
|
@ -505,8 +522,8 @@ class MatrixServer:
|
||||||
W.prnt("", "{prefix}matrix: Olm session missing for room, can't"
|
W.prnt("", "{prefix}matrix: Olm session missing for room, can't"
|
||||||
" encrypt message.")
|
" encrypt message.")
|
||||||
W.prnt("", pprint.pformat(missing))
|
W.prnt("", pprint.pformat(missing))
|
||||||
self.encryption_queue[room_id].append(formatted_data)
|
self.encryption_queue[room.room_id].append(formatted_data)
|
||||||
message = MatrixKeyClaimMessage(self.client, room_id, missing)
|
message = MatrixKeyClaimMessage(self.client, room.room_id, missing)
|
||||||
self.send_or_queue(message)
|
self.send_or_queue(message)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -525,7 +542,7 @@ class MatrixServer:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
payload_dict, to_device_dict = self.olm.group_encrypt(
|
payload_dict, to_device_dict = self.olm.group_encrypt(
|
||||||
room_id,
|
room.room_id,
|
||||||
plaintext_dict,
|
plaintext_dict,
|
||||||
self.user_id,
|
self.user_id,
|
||||||
room.users.keys()
|
room.users.keys()
|
||||||
|
@ -538,7 +555,7 @@ class MatrixServer:
|
||||||
|
|
||||||
message = MatrixEncryptedMessage(
|
message = MatrixEncryptedMessage(
|
||||||
self.client,
|
self.client,
|
||||||
room_id,
|
room.room_id,
|
||||||
formatted_data,
|
formatted_data,
|
||||||
payload_dict
|
payload_dict
|
||||||
)
|
)
|
||||||
|
@ -612,19 +629,46 @@ class MatrixServer:
|
||||||
server_buffer_prnt(self, pprint.pformat(message.request.payload))
|
server_buffer_prnt(self, pprint.pformat(message.request.payload))
|
||||||
server_buffer_prnt(self, pprint.pformat(message.response.body))
|
server_buffer_prnt(self, pprint.pformat(message.response.body))
|
||||||
|
|
||||||
|
def handle_room_event(self, room, room_buffer, event, is_state_event):
|
||||||
|
if isinstance(event, RoomMemberJoin):
|
||||||
|
if event.sender in room.users:
|
||||||
|
user = room.users[event.sender]
|
||||||
|
if event.display_name:
|
||||||
|
user.display_name = event.display_name
|
||||||
|
else:
|
||||||
|
short_name = shorten_sender(event.sender)
|
||||||
|
user = MatrixUser(short_name, event.display_name)
|
||||||
|
buffer_user = RoomUser(user.name, event.sender)
|
||||||
|
room.users[event.sender] = user
|
||||||
|
|
||||||
|
if self.user_id == event.sender:
|
||||||
|
buffer_user.color = "weechat.color.chat_nick_self"
|
||||||
|
user.nick_color = "weechat.color.chat_nick_self"
|
||||||
|
|
||||||
|
room_buffer.join(
|
||||||
|
buffer_user,
|
||||||
|
server_ts_to_weechat(event.timestamp),
|
||||||
|
not is_state_event
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
tags = tags_for_message("message")
|
||||||
|
event.execute(self, room, room_buffer._ptr, tags)
|
||||||
|
|
||||||
def _loop_events(self, info, n):
|
def _loop_events(self, info, n):
|
||||||
|
|
||||||
for i in range(n+1):
|
for i in range(n+1):
|
||||||
|
is_state = False
|
||||||
try:
|
try:
|
||||||
event = info.events.popleft()
|
event = info.state.popleft()
|
||||||
|
is_state = True
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return i
|
try:
|
||||||
|
event = info.timeline.popleft()
|
||||||
|
except IndexError:
|
||||||
|
return i
|
||||||
|
|
||||||
room = self.rooms[info.room_id]
|
room, room_buffer = self.find_room_from_id(info.room_id)
|
||||||
buf = self.buffers[info.room_id]
|
self.handle_room_event(room, room_buffer, event, is_state)
|
||||||
|
|
||||||
tags = tags_for_message("message")
|
|
||||||
event.execute(self, room, buf, tags)
|
|
||||||
|
|
||||||
self.event_queue.appendleft(info)
|
self.event_queue.appendleft(info)
|
||||||
return i
|
return i
|
||||||
|
@ -657,6 +701,32 @@ class MatrixServer:
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def handle_own_messages(self, room_buffer, message):
|
||||||
|
if isinstance(message, RoomMessageText):
|
||||||
|
msg = (message.formatted_message.to_weechat()
|
||||||
|
if message.formatted_message
|
||||||
|
else message.message)
|
||||||
|
|
||||||
|
date = server_ts_to_weechat(message.timestamp)
|
||||||
|
room_buffer.self_message(self.user, msg, date)
|
||||||
|
|
||||||
|
return
|
||||||
|
elif isinstance(message, RoomMessageEmote):
|
||||||
|
date = server_ts_to_weechat(message.timestamp)
|
||||||
|
room_buffer.self_action(self.user, message.message, date)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
raise NotImplementedError("Unsupported message of type {}".format(
|
||||||
|
type(message)))
|
||||||
|
|
||||||
|
def handle_matrix_response(self, response):
|
||||||
|
if isinstance(response, MatrixSendEvent):
|
||||||
|
_, room_buffer = self.find_room_from_id(response.room_id)
|
||||||
|
self.handle_own_messages(room_buffer, response.message)
|
||||||
|
else:
|
||||||
|
response.execute()
|
||||||
|
|
||||||
def handle_response(self, message):
|
def handle_response(self, message):
|
||||||
# type: (MatrixMessage) -> None
|
# type: (MatrixMessage) -> None
|
||||||
|
|
||||||
|
@ -674,7 +744,7 @@ class MatrixServer:
|
||||||
return
|
return
|
||||||
|
|
||||||
event = message.event
|
event = message.event
|
||||||
event.execute()
|
self.handle_matrix_response(event)
|
||||||
else:
|
else:
|
||||||
status_code = message.response.status
|
status_code = message.response.status
|
||||||
if status_code == 504:
|
if status_code == 504:
|
||||||
|
@ -705,6 +775,26 @@ class MatrixServer:
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def create_room_buffer(self, room_id):
|
||||||
|
buf = WeechatChannelBuffer(room_id, self.name, self.user)
|
||||||
|
# TODO this should turned into a propper class
|
||||||
|
self.room_buffers[room_id] = buf
|
||||||
|
self.buffers[room_id] = buf._ptr
|
||||||
|
self.rooms[room_id] = MatrixRoom(room_id)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def find_room_from_ptr(self, pointer):
|
||||||
|
room_id = key_from_value(self.buffers, pointer)
|
||||||
|
room = self.rooms[room_id]
|
||||||
|
room_buffer = self.room_buffers[room_id]
|
||||||
|
|
||||||
|
return room, room_buffer
|
||||||
|
|
||||||
|
def find_room_from_id(self, room_id):
|
||||||
|
room = self.rooms[room_id]
|
||||||
|
room_buffer = self.room_buffers[room_id]
|
||||||
|
return room, room_buffer
|
||||||
|
|
||||||
|
|
||||||
@utf8_decode
|
@utf8_decode
|
||||||
def matrix_config_server_read_cb(data, config_file, section, option_name,
|
def matrix_config_server_read_cb(data, config_file, section, option_name,
|
||||||
|
|
Loading…
Add table
Reference in a new issue