From af7049f2cf673f4df4d5613f5dd3a7fccd931cac Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Sat, 9 May 2020 20:03:02 +0100 Subject: [PATCH] feat(replies): enable based on redaction implementation * Close #86 * https://matrix.org/docs/spec/client_server/latest#rich-replies * Modify to `/reply-matrix` to avoid clash with `/reply` used by `wee-slack` --- main.py | 3 +- matrix/commands.py | 79 ++++++++++++++++++++++++++++++++++++++++++++++ matrix/server.py | 7 +++- 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index 73d9524..a3993ad 100644 --- a/main.py +++ b/main.py @@ -73,7 +73,8 @@ from matrix.commands import (hook_commands, hook_page_up, matrix_redact_command_cb, matrix_topic_command_cb, matrix_olm_command_cb, matrix_devices_command_cb, matrix_room_command_cb, matrix_uploads_command_cb, - matrix_upload_command_cb, matrix_send_anyways_cb) + matrix_upload_command_cb, matrix_send_anyways_cb, + matrix_reply_command_cb) from matrix.completion import (init_completion, matrix_command_completion_cb, matrix_debug_completion_cb, matrix_message_completion_cb, diff --git a/matrix/commands.py b/matrix/commands.py index 0e0ed2d..ea53484 100644 --- a/matrix/commands.py +++ b/matrix/commands.py @@ -285,6 +285,27 @@ def hook_commands(): "", ) + W.hook_command( + # Command name and short description + "reply-matrix", + "reply to a message", + # Synopsis + ('[:""] []'), + # Description + ( + " event-id: event id of the message that will be replied to\n" + "message-part: an initial part of the message (ignored, only " + "used\n" + " as visual feedback when using completion)\n" + " reply: the reply\n" + ), + # Completions + ("%(matrix_messages)"), + # Function name + "matrix_reply_command_cb", + "", + ) + W.hook_command( # Command name and short description "topic", @@ -1321,6 +1342,64 @@ def matrix_redact_command_cb(data, buffer, args): return W.WEECHAT_RC_OK +@utf8_decode +def matrix_reply_command_cb(data, buffer, args): + def predicate(event_id, line): + event_tag = SCRIPT_NAME + "_id_{}".format(event_id) + tags = line.tags + + if event_tag in tags: + return True + return False + + for server in SERVERS.values(): + if buffer in server.buffers.values(): + room_buffer = server.find_room_from_ptr(buffer) + + # Intentional use of `parse_redact_args` which serves the + # necessary purpose + event_id, reply = parse_redact_args(args) + + if not event_id: + message = ( + "{prefix}matrix: Invalid command " + "arguments (see /help reply)" + ).format(prefix=W.prefix("error")) + W.prnt("", message) + return W.WEECHAT_RC_ERROR + + lines = room_buffer.weechat_buffer.find_lines( + partial(predicate, event_id), max_lines=1 + ) + + if not lines: + room_buffer.error( + "No such message with event id " + "{event_id} found.".format(event_id=event_id)) + return W.WEECHAT_RC_OK + + formatted_data = Formatted.from_input_line(reply) + server.room_send_message( + room_buffer, + formatted_data, + "m.text", + in_reply_to_event_id=event_id, + ) + room_buffer.last_message = None + + return W.WEECHAT_RC_OK + + if buffer == server.server_buffer: + message = ( + '{prefix}matrix: command "reply" must be ' + "executed on a Matrix channel buffer" + ).format(prefix=W.prefix("error")) + W.prnt("", message) + return W.WEECHAT_RC_OK + + return W.WEECHAT_RC_OK + + def matrix_command_help(args): if not args: message = ( diff --git a/matrix/server.py b/matrix/server.py index 1ef69c4..7d9ee0f 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -1118,6 +1118,7 @@ class MatrixServer(object): formatted, # type: Formatted msgtype="m.text", # type: str ignore_unverified_devices=False, # type: bool + in_reply_to_event_id="", # type: str ): # type: (...) -> bool room = room_buffer.room @@ -1126,9 +1127,13 @@ class MatrixServer(object): content = {"msgtype": msgtype, "body": formatted.to_plain()} - if formatted.is_formatted(): + if formatted.is_formatted() or in_reply_to_event_id: content["format"] = "org.matrix.custom.html" content["formatted_body"] = formatted.to_html() + if in_reply_to_event_id: + content["m.relates_to"] = { + "m.in_reply_to": {"event_id": in_reply_to_event_id} + } try: uuid = self.room_send_event(