diff --git a/main.py b/main.py index af8cf80..d1a6236 100644 --- a/main.py +++ b/main.py @@ -47,7 +47,7 @@ from matrix.commands import (hook_commands, hook_page_up, matrix_command_cb, matrix_command_part_cb, matrix_command_invite_cb, matrix_command_pgup_cb, matrix_redact_command_cb, matrix_command_buf_clear_cb, matrix_me_command_cb, - matrix_command_kick_cb) + matrix_kick_command_cb) from matrix.buffer import room_buffer_input_cb, room_buffer_close_cb from matrix.server import ( @@ -68,7 +68,8 @@ from matrix.completion import ( init_completion, matrix_command_completion_cb, matrix_server_command_completion_cb, matrix_debug_completion_cb, matrix_message_completion_cb, matrix_server_completion_cb, - matrix_olm_user_completion_cb, matrix_olm_device_completion_cb) + matrix_olm_user_completion_cb, matrix_olm_device_completion_cb, + matrix_user_completion_cb) from matrix.utils import (key_from_value, server_buffer_prnt, prnt_debug, server_buffer_set_title) diff --git a/matrix/commands.py b/matrix/commands.py index c7ae56f..edf2a00 100644 --- a/matrix/commands.py +++ b/matrix/commands.py @@ -18,7 +18,6 @@ from __future__ import unicode_literals from builtins import str import re -import time import argparse import matrix.globals @@ -48,6 +47,14 @@ class WeechatArgParse(argparse.ArgumentParser): class WeechatCommandParser(object): + @staticmethod + def _run_parser(parser, args): + try: + parsed_args = parser.parse_args(args.split()) + return parsed_args + except ParseError: + return None + @staticmethod def topic(args): parser = WeechatArgParse(prog="topic") @@ -55,11 +62,15 @@ class WeechatCommandParser(object): parser.add_argument("-delete", action="store_true") parser.add_argument("topic", nargs="*") - try: - parsed_args = parser.parse_args(args.split()) - return parsed_args - except ParseError: - return None + return WeechatCommandParser._run_parser(parser, args) + + @staticmethod + def kick(args): + parser = WeechatArgParse(prog="kick") + parser.add_argument("user_id") + parser.add_argument("reason", nargs="*") + + return WeechatCommandParser._run_parser(parser, args) def hook_commands(): @@ -138,11 +149,25 @@ def hook_commands(): "matrix_me_command_cb", "") + W.hook_command( + # Command name and short description + "kick", + "kick a user from the current room", + # Synopsis + (" []"), + # Description + ("user-id: user-id to kick\n" + " reason: reason why the user was kicked"), + # Completions + ("%(matrix_users)"), + # Callback + "matrix_kick_command_cb", + "") + # TODO those should be hook_command() calls - W.hook_command_run('/join', 'matrix_command_join_cb', '') - W.hook_command_run('/part', 'matrix_command_part_cb', '') - W.hook_command_run('/invite', 'matrix_command_invite_cb', '') - W.hook_command_run('/kick', 'matrix_command_kick_cb', '') + # W.hook_command_run('/join', 'matrix_command_join_cb', '') + # W.hook_command_run('/part', 'matrix_command_part_cb', '') + # W.hook_command_run('/invite', 'matrix_command_invite_cb', '') W.hook_command_run('/buffer clear', 'matrix_command_buf_clear_cb', '') @@ -365,35 +390,27 @@ def matrix_command_invite_cb(data, buffer, command): @utf8_decode -def matrix_command_kick_cb(data, buffer, command): - - def kick(server, buf, args): - split_args = args.split(" ", 1)[1:] - - if (len(split_args) < 1 or - split_args[0].startswith("#") and len(split_args) < 2): - error_msg = ( - '{prefix}Error with command "/kick" (help on ' - 'command: /help kick)').format(prefix=W.prefix("error")) - W.prnt("", error_msg) - return - - if split_args[0].startswith("#"): - assert len(split_args) >= 2 - room_id = split_args[0] - kicked_user = split_args[1] - reason = split_args[2:] or None - else: - room_id = key_from_value(server.buffers, buf) - kicked_user = split_args[0] - reason = split_args[1:] or None - - raise NotImplementedError +def matrix_kick_command_cb(data, buffer, args): + parsed_args = WeechatCommandParser.kick(args) + if not parsed_args: + return W.WEECHAT_RC_OK for server in SERVERS.values(): - if buffer in server.buffers.values(): - kick(server, buffer, command) - return W.WEECHAT_RC_OK_EAT + if buffer == server.server_buffer: + server.error("command \"kick\" must be " + "executed on a Matrix room buffer") + return W.WEECHAT_RC_OK + + room = server.find_room_from_ptr(buffer) + if not room: + continue + + user_id = parsed_args.user_id + user_id = user_id if user_id.startswith("@") else "@" + user_id + reason = " ".join(parsed_args.reason) if parsed_args.reason else None + + server.room_kick(room, user_id, reason) + break return W.WEECHAT_RC_OK diff --git a/matrix/completion.py b/matrix/completion.py index 454664b..a15d9d2 100644 --- a/matrix/completion.py +++ b/matrix/completion.py @@ -171,6 +171,31 @@ def matrix_olm_device_completion_cb(data, completion_item, buffer, completion): return W.WEECHAT_RC_OK +@utf8_decode +def matrix_user_completion_cb(data, completion_item, buffer, completion): + def add_user(completion, user): + W.hook_completion_list_add(completion, user, 0, + W.WEECHAT_LIST_POS_SORT) + + for server in SERVERS.values(): + if buffer == server.server_buffer: + return W.WEECHAT_RC_OK + + room_buffer = server.find_room_from_ptr(buffer) + + if not room_buffer: + continue + + users = room_buffer.room.users + + users = [user[1:] for user in users] + + for user in users: + add_user(completion, user) + + return W.WEECHAT_RC_OK + + def init_completion(): W.hook_completion("matrix_server_commands", "Matrix server completion", "matrix_server_command_completion_cb", "") @@ -192,3 +217,6 @@ def init_completion(): W.hook_completion("olm_devices", "Matrix olm device id completion", "matrix_olm_device_completion_cb", "") + + W.hook_completion("matrix_users", "Matrix user id completion", + "matrix_user_completion_cb", "") diff --git a/matrix/server.py b/matrix/server.py index 3db149b..1a1ea7b 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -515,6 +515,13 @@ class MatrixServer(object): reason) self.send_or_queue(request) + def room_kick(self, room_buffer, user_id, reason=None): + _, request = self.client.room_kick( + room_buffer.room.room_id, + user_id, + reason) + self.send_or_queue(request) + def room_send_message(self, room_buffer, formatted, msgtype="m.text"): # type: (RoomBuffer, Formatted, str) -> None if room_buffer.room.encrypted: