From fd9053eacdc8128a8b5b2091a44177c823f0cd29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Sat, 3 Nov 2018 16:44:40 +0100 Subject: [PATCH] server: Support printing out sent messages before finishing the request. --- matrix/buffer.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++-- matrix/config.py | 34 ++++++++++++++++++++++++++++- matrix/server.py | 42 ++++++++++++++++++++++++++++++++++-- 3 files changed, 127 insertions(+), 5 deletions(-) diff --git a/matrix/buffer.py b/matrix/buffer.py index 142cb5f..9fe4506 100644 --- a/matrix/buffer.py +++ b/matrix/buffer.py @@ -57,6 +57,7 @@ OwnMessages = NamedTuple( ("sender", str), ("age", int), ("event_id", str), + ("uuid", str), ("room_id", str), ("formatted_message", Formatted), ], @@ -1242,7 +1243,10 @@ class RoomBuffer(object): # type: (OwnMessage) -> None nick = self.find_nick(self.room.own_user_id) data = message.formatted_message.to_weechat() - tags = [SCRIPT_NAME + "_id_{}".format(message.event_id)] + if message.event_id: + tags = [SCRIPT_NAME + "_id_{}".format(message.event_id)] + else: + tags = [SCRIPT_NAME + "_uuid_{}".format(message.uuid)] date = message.age self.weechat_buffer.self_message(nick, data, date, tags) @@ -1251,12 +1255,60 @@ class RoomBuffer(object): # type: (OwnMessage) -> None nick = self.find_nick(self.room.own_user_id) date = message.age - tags = [SCRIPT_NAME + "_id_{}".format(message.event_id)] + if message.event_id: + tags = [SCRIPT_NAME + "_id_{}".format(message.event_id)] + else: + tags = [SCRIPT_NAME + "_uuid_{}".format(message.uuid)] self.weechat_buffer.self_action( nick, message.formatted_message.to_weechat(), date, tags ) + @staticmethod + def _find_by_uuid_predicate(uuid, line): + uuid_tag = SCRIPT_NAME + "_uuid_{}".format(uuid) + tags = line.tags + + if uuid_tag in tags: + return True + return False + + def mark_message_as_unsent(self, uuid, _): + """Append to already printed lines that are greyed out an error + message""" + lines = self.weechat_buffer.find_lines( + partial(self._find_by_uuid_predicate, uuid) + ) + last_line = lines[-1] + + message = last_line.message + message += (" {del_color}<{ncolor}{error_color}Error sending " + "message{del_color}>{ncolor}").format( + del_color=W.color("chat_delimiters"), + ncolor=W.color("reset"), + error_color=W.color(G.CONFIG.color.error_message)) + + last_line.message = message + + def replace_printed_line_by_uuid(self, uuid, new_message): + """Replace already printed lines that are greyed out with real ones""" + lines = self.weechat_buffer.find_lines( + partial(self._find_by_uuid_predicate, uuid) + ) + + new_lines = new_message.formatted_message.to_weechat().split("\n") + + for i, line in enumerate(lines): + line.message = new_lines[i] + tags = line.tags + + new_tags = [ + tag for tag in tags + if not tag.startswith(SCRIPT_NAME + "_uuid_") + ] + new_tags.append(SCRIPT_NAME + "_id_ " + new_message.event_id) + line.tags = new_tags + def old_redacted(self, event): tags = [ SCRIPT_NAME + "_message", diff --git a/matrix/config.py b/matrix/config.py index c612686..4d69c76 100644 --- a/matrix/config.py +++ b/matrix/config.py @@ -453,6 +453,17 @@ class MatrixConfig(WeechatConfig): ("Reconnect to the server if the lag is greater than this " "value (in seconds)"), ), + Option( + "print_unconfirmed_messages", + "boolean", + "", + 0, + 0, + "on", + ("If off, messages are only printed after the server confirms" + "their receival. If on, messages are immediately printed but " + "colored differently until receival is confirmed."), + ), ] color_options = [ @@ -464,7 +475,28 @@ class MatrixConfig(WeechatConfig): 0, "lightgreen", ("Color for matrix style blockquotes"), - ) + ), + Option( + "error_message", + "color", + "", + 0, + 0, + "darkgray", + ("Color for error messages that appear inside a room buffer (" + "e.g. when a message errors out when sending or when a " + "message is redacted)"), + ), + Option( + "unconfirmed_message", + "color", + "", + 0, + 0, + "darkgray", + ("Color for messages that are printed out but the server " + "hasn't confirmed the that he received them."), + ), ] sections = [ diff --git a/matrix/server.py b/matrix/server.py index 5bed5e5..18b7943 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -61,7 +61,7 @@ from .globals import SCRIPT_NAME, SERVERS, W, MAX_EVENTS from .utf import utf8_decode from .utils import create_server_buffer, key_from_value, server_buffer_prnt -from .colors import Formatted +from .colors import Formatted, FormattedString, DEFAULT_ATRIBUTES try: @@ -248,6 +248,7 @@ class MatrixServer(object): self.device_deletion_queue = dict() self.own_message_queue = dict() # type: Dict[str, OwnMessage] + self.print_before_ack_queue = [] # type: List[UUID] self.encryption_queue = defaultdict(deque) \ # type: DefaultDict[str, Deque[EncrytpionQueueItem]] self.backlog_queue = dict() # type: Dict[str, str] @@ -719,11 +720,32 @@ class MatrixServer(object): message_class = OwnMessage own_message = message_class( - self.user_id, 0, "", room.room_id, formatted + self.user_id, 0, "", uuid, room.room_id, formatted ) self.own_message_queue[uuid] = own_message self.send_or_queue(request) + + if G.CONFIG.network.print_unconfirmed_messages: + self.print_before_ack_queue.append(uuid) + plain_message = formatted.to_weechat() + plain_message = W.string_remove_color(plain_message, "") + attributes = DEFAULT_ATRIBUTES.copy() + attributes["fgcolor"] = G.CONFIG.color.unconfirmed_message + new_formatted = Formatted([FormattedString( + plain_message, + attributes + )]) + + own_message = message_class( + self.user_id, 0, "", uuid, room.room_id, new_formatted + ) + + if isinstance(own_message, OwnAction): + room_buffer.self_action(own_message) + elif isinstance(own_message, OwnMessage): + room_buffer.self_message(own_message) + return True def keys_upload(self): @@ -758,11 +780,25 @@ class MatrixServer(object): server_buffer_prnt(self, pprint.pformat(message.request.payload)) server_buffer_prnt(self, pprint.pformat(message.response.body)) + def handle_own_messages_error(self, response): + message = self.own_message_queue.pop(response.uuid) + if response.uuid not in self.print_before_ack_queue: + return + + room_buffer = self.room_buffers[message.room_id] + room_buffer.mark_message_as_unsent(response.uuid, message) + def handle_own_messages(self, response): message = self.own_message_queue.pop(response.uuid) room_buffer = self.room_buffers[message.room_id] message = message._replace(event_id=response.event_id) + # We already printed the message, just modify it to contain the proper + # colors and formatting. + if response.uuid in self.print_before_ack_queue: + room_buffer.replace_printed_line_by_uuid(response.uuid, message) + return + if isinstance(message, OwnAction): room_buffer.self_action(message) return @@ -990,6 +1026,8 @@ class MatrixServer(object): elif isinstance(response, JoinedMembersError): self.rooms_with_missing_members.append(response.room_id) self.get_joined_members(self.rooms_with_missing_members.pop()) + elif isinstance(response, RoomSendResponse): + self.handle_own_messages_error(response) def handle_response(self, response): # type: (Response) -> None