diff --git a/main.py b/main.py index a1f7f20..4ffa08d 100644 --- a/main.py +++ b/main.py @@ -39,7 +39,7 @@ from matrix.commands import (hook_commands, hook_page_up, matrix_command_cb, matrix_command_join_cb, matrix_command_part_cb, matrix_command_invite_cb, matrix_command_topic_cb, matrix_command_pgup_cb, matrix_redact_command_cb, - matrix_command_buf_clear_cb) + matrix_command_buf_clear_cb, matrix_me_command_cb) from matrix.server import ( MatrixServer, diff --git a/matrix/api.py b/matrix/api.py index b7af846..9c364b9 100644 --- a/matrix/api.py +++ b/matrix/api.py @@ -91,11 +91,15 @@ class MatrixClient: return HttpRequest(RequestType.GET, self.host, path) - def room_send_message(self, room_id, content, formatted_content=None): + def room_send_message(self, + room_id, + message_type, + content, + formatted_content=None): # type: (str, str, str) -> HttpRequest query_parameters = {"access_token": self.access_token} - body = {"msgtype": "m.text", "body": content} + body = {"msgtype": message_type, "body": content} if formatted_content: body["format"] = "org.matrix.custom.html" @@ -301,15 +305,17 @@ class MatrixSyncMessage(MatrixMessage): class MatrixSendMessage(MatrixMessage): - def __init__(self, client, room_id, formatted_message): + def __init__(self, + client, + room_id, + formatted_message, + message_type="m.text"): self.room_id = room_id self.formatted_message = formatted_message - assert self.room_id - assert self.formatted_message - data = { "room_id": self.room_id, + "message_type": message_type, "content": self.formatted_message.to_plain() } @@ -329,6 +335,23 @@ class MatrixSendMessage(MatrixMessage): return self._decode(server, object_hook) +class MatrixEmoteMessage(MatrixSendMessage): + + def __init__(self, client, room_id, formatted_message): + MatrixSendMessage.__init__(self, client, room_id, formatted_message, + "m.emote") + + def decode_body(self, server): + object_hook = partial( + MatrixEvents.MatrixEmoteEvent.from_dict, + server, + self.room_id, + self.formatted_message, + ) + + return self._decode(server, object_hook) + + class MatrixTopicMessage(MatrixMessage): def __init__(self, client, room_id, topic): diff --git a/matrix/commands.py b/matrix/commands.py index 53fed48..7c270fb 100644 --- a/matrix/commands.py +++ b/matrix/commands.py @@ -26,10 +26,12 @@ from matrix.globals import W, OPTIONS, SERVERS from matrix.utf import utf8_decode from matrix.api import (MatrixTopicMessage, MatrixRedactMessage, MatrixBacklogMessage, MatrixJoinMessage, - MatrixPartMessage, MatrixInviteMessage) + MatrixPartMessage, MatrixInviteMessage, + MatrixEmoteMessage) from matrix.utils import key_from_value, tags_from_line_data from matrix.plugin_options import DebugType from matrix.server import MatrixServer +from matrix.colors import Formatted def hook_commands(): @@ -82,6 +84,20 @@ def hook_commands(): 'matrix_redact_command_cb', '') + W.hook_command( + # Command name and short description + "me", + "send an emote message to the current room", + # Synopsis + (""), + # Description + ("message: message to send"), + # Completions + "", + # Function name + "matrix_me_command_cb", + "") + W.hook_command_run('/topic', 'matrix_command_topic_cb', '') W.hook_command_run('/buffer clear', 'matrix_command_buf_clear_cb', '') W.hook_command_run('/join', 'matrix_command_join_cb', '') @@ -92,6 +108,40 @@ def hook_commands(): hook_page_up() +@utf8_decode +def matrix_me_command_cb(data, buffer, args): + for server in SERVERS.values(): + if buffer in server.buffers.values(): + + if not server.connected: + message = ("{prefix}matrix: you are not connected to " + "the server").format(prefix=W.prefix("error")) + W.prnt(server.server_buffer, message) + return W.WEECHAT_RC_ERROR + + room_id = key_from_value(server.buffers, buffer) + + if not args: + return W.WEECHAT_RC_OK + + formatted_data = Formatted.from_input_line(args) + message = MatrixEmoteMessage( + server.client, + room_id=room_id, + formatted_message=formatted_data) + + server.send_or_queue(message) + + return W.WEECHAT_RC_OK + + elif buffer == server.server_buffer: + message = ("{prefix}matrix: command \"me\" must be " + "executed on a Matrix channel buffer" + ).format(prefix=W.prefix("error")) + W.prnt("", message) + return W.WEECHAT_RC_OK + + def matrix_fetch_old_messages(server, room_id): room = server.rooms[room_id] diff --git a/matrix/events.py b/matrix/events.py index 70e6032..ee10fec 100644 --- a/matrix/events.py +++ b/matrix/events.py @@ -25,7 +25,8 @@ from matrix.globals import W from matrix.utils import (color_for_tags, tags_for_message, sanitize_id, sanitize_token, sanitize_text, tags_from_line_data) from matrix.rooms import (matrix_create_room_buffer, RoomInfo, RoomMessageText, - RoomMessageEvent, RoomRedactedMessageEvent) + RoomMessageEvent, RoomRedactedMessageEvent, + RoomMessageEmote) class MatrixEvent(): @@ -125,6 +126,26 @@ class MatrixSendEvent(MatrixEvent): False, parsed_dict) +class MatrixEmoteEvent(MatrixSendEvent): + + @classmethod + def from_dict(cls, server, room_id, message, parsed_dict): + try: + event_id = sanitize_id(parsed_dict["event_id"]) + sender = server.user_id + age = 0 + plain_message = message.to_plain() + formatted_message = message + + message = RoomMessageEmote(event_id, sender, age, plain_message, + formatted_message) + + return cls(server, room_id, message) + except (KeyError, TypeError, ValueError): + return MatrixErrorEvent.from_dict(server, "Error sending message", + False, parsed_dict) + + class MatrixTopicEvent(MatrixEvent): def __init__(self, server, room_id, event_id, topic):