commands: Add join/part.

This commit is contained in:
Damir Jelić 2018-08-26 20:44:06 +02:00
parent 53d2152a21
commit ebcbf454d9
4 changed files with 136 additions and 67 deletions

View file

@ -43,8 +43,8 @@ from matrix.utf import utf8_decode
# Weechat searches for the registered callbacks in the scope of the main script # Weechat searches for the registered callbacks in the scope of the main script
# file, import the callbacks here so weechat can find them. # file, import the callbacks here so weechat can find them.
from matrix.commands import (hook_commands, hook_page_up, matrix_command_cb, from matrix.commands import (hook_commands, hook_page_up, matrix_command_cb,
matrix_topic_command_cb, matrix_command_join_cb, matrix_topic_command_cb, matrix_join_command_cb,
matrix_command_part_cb, matrix_invite_command_cb, matrix_part_command_cb, matrix_invite_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_kick_command_cb) matrix_kick_command_cb)

View file

@ -783,6 +783,8 @@ class RoomBuffer(object):
def __init__(self, room, server_name): def __init__(self, room, server_name):
self.room = room self.room = room
self.backlog_pending = False self.backlog_pending = False
self.joined = True
self.leave_event_id = None # type: Optional[str]
buffer_name = "{}.{}".format(room.room_id, server_name) buffer_name = "{}.{}".format(room.room_id, server_name)
@ -854,6 +856,12 @@ class RoomBuffer(object):
if event.state_key in self.displayed_nicks: if event.state_key in self.displayed_nicks:
del self.displayed_nicks[event.state_key] del self.displayed_nicks[event.state_key]
# We left the room, remember the event id of our leave, if we
# rejoin we get events that came before this event as well as
# after our leave, this way we know where to continue
if event.state_key == self.room.own_user_id:
self.leave_event_id = event.event_id
elif event.content["membership"] == "invite": elif event.content["membership"] == "invite":
if is_state: if is_state:
return return
@ -1200,6 +1208,44 @@ class RoomBuffer(object):
self.sort_messages() self.sort_messages()
def handle_joined_room(self, info):
for event in info.state:
self.handle_state_event(event)
timeline_events = None
# This is a rejoin, skip already handled events
if not self.joined:
leave_index = None
for i, event in enumerate(info.timeline.events):
if event.event_id == self.leave_event_id:
leave_index = i
break
if leave_index:
timeline_events = info.timeline.events[leave_index:]
else:
timeline_events = info.timeline.events
# mark that we are now joined
self.joined = True
else:
timeline_events = info.timeline.events
for event in timeline_events:
self.handle_timeline_event(event)
def handle_left_room(self, info):
self.joined = False
for event in info.state:
self.handle_state_event(event)
for event in info.timeline.events:
self.handle_timeline_event(event)
def error(self, string): def error(self, string):
# type: (str) -> None # type: (str) -> None
self.weechat_buffer.error(string) self.weechat_buffer.error(string)

View file

@ -79,6 +79,18 @@ class WeechatCommandParser(object):
return WeechatCommandParser._run_parser(parser, args) return WeechatCommandParser._run_parser(parser, args)
@staticmethod
def join(args):
parser = WeechatArgParse(prog="join")
parser.add_argument("room_id")
return WeechatCommandParser._run_parser(parser, args)
@staticmethod
def part(args):
parser = WeechatArgParse(prog="part")
parser.add_argument("room_id", nargs="?")
return WeechatCommandParser._run_parser(parser, args)
def hook_commands(): def hook_commands():
W.hook_command( W.hook_command(
@ -185,9 +197,34 @@ def hook_commands():
"matrix_invite_command_cb", "matrix_invite_command_cb",
"") "")
# TODO those should be hook_command() calls W.hook_command(
# W.hook_command_run('/join', 'matrix_command_join_cb', '') # Command name and short description
# W.hook_command_run('/part', 'matrix_command_part_cb', '') "join",
"join a room",
# Synopsis
("<room-id>|<room-alias>"),
# Description
(" room-id: room-id of the room to join\n"
"room-alias: room alias of the room to join"),
# Completions
"",
# Callback
"matrix_join_command_cb",
"")
W.hook_command(
# Command name and short description
"part",
"leave a room",
# Synopsis
("[<room-name>]"),
# Description
(" room-name: room name of the room to leave"),
# Completions
"",
# Callback
"matrix_part_command_cb",
"")
W.hook_command_run('/buffer clear', 'matrix_command_buf_clear_cb', '') W.hook_command_run('/buffer clear', 'matrix_command_buf_clear_cb', '')
@ -320,64 +357,41 @@ def matrix_command_pgup_cb(data, buffer, command):
@utf8_decode @utf8_decode
def matrix_command_join_cb(data, buffer, command): def matrix_join_command_cb(data, buffer, args):
parsed_args = WeechatCommandParser.join(args)
def join(server, args): if not parsed_args:
split_args = args.split(" ", 1) return W.WEECHAT_RC_OK
# TODO handle join for non public rooms
if len(split_args) != 2:
message = ("{prefix}Error with command \"/join\" (help on "
"command: /help join)").format(prefix=W.prefix("error"))
W.prnt("", message)
return
_, room_id = split_args
raise NotImplementedError
for server in SERVERS.values(): for server in SERVERS.values():
if buffer in server.buffers.values(): if buffer in server.buffers.values() or buffer == server.server_buffer:
join(server, command) server.room_join(parsed_args.room_id)
return W.WEECHAT_RC_OK_EAT break
elif buffer == server.server_buffer:
join(server, command)
return W.WEECHAT_RC_OK_EAT
return W.WEECHAT_RC_OK return W.WEECHAT_RC_OK
@utf8_decode @utf8_decode
def matrix_command_part_cb(data, buffer, command): def matrix_part_command_cb(data, buffer, args):
parsed_args = WeechatCommandParser.part(args)
def part(server, buffer, args): if not parsed_args:
rooms = [] return W.WEECHAT_RC_OK
split_args = args.split(" ", 1)
if len(split_args) == 1:
if buffer == server.server_buffer:
message = (
"{prefix}Error with command \"/part\" (help on "
"command: /help part)").format(prefix=W.prefix("error"))
W.prnt("", message)
return
rooms = [key_from_value(server.buffers, buffer)]
else:
_, rooms = split_args
rooms = rooms.split(" ")
raise NotImplementedError
for server in SERVERS.values(): for server in SERVERS.values():
if buffer in server.buffers.values(): if buffer in server.buffers.values() or buffer == server.server_buffer:
part(server, buffer, command) room_id = parsed_args.room_id
return W.WEECHAT_RC_OK_EAT
elif buffer == server.server_buffer: if not room_id:
part(server, buffer, command) if buffer == server.server_buffer:
return W.WEECHAT_RC_OK_EAT server.error("command \"part\" must be "
"executed on a Matrix room buffer or a room "
"name needs to be given")
return W.WEECHAT_RC_OK
room_buffer = server.find_room_from_ptr(buffer)
room_id = room_buffer.room.room_id
server.room_leave(room_id)
break
return W.WEECHAT_RC_OK return W.WEECHAT_RC_OK
@ -736,8 +750,8 @@ def matrix_server_command_delete(args):
def matrix_server_command_add(args): def matrix_server_command_add(args):
if len(args) < 2: if len(args) < 2:
message = ("{prefix}matrix: Too few arguments for command " message = ("{prefix}matrix: Too few arguments for command "
"\"/matrix server add\" (see /matrix help server)" "\"/matrix server add\" (see /matrix help server)").format(
).format(prefix=W.prefix("error")) prefix=W.prefix("error"))
W.prnt("", message) W.prnt("", message)
return return
elif len(args) > 4: elif len(args) > 4:
@ -865,7 +879,6 @@ def matrix_server_command_add(args):
def matrix_server_command(command, args): def matrix_server_command(command, args):
def list_servers(_): def list_servers(_):
if SERVERS: if SERVERS:
W.prnt("", "\nAll matrix servers:") W.prnt("", "\nAll matrix servers:")
@ -892,7 +905,6 @@ def matrix_server_command(command, args):
@utf8_decode @utf8_decode
def matrix_command_cb(data, buffer, args): def matrix_command_cb(data, buffer, args):
def connect_server(args): def connect_server(args):
for server_name in args: for server_name in args:
if check_server_existence(server_name, SERVERS): if check_server_existence(server_name, SERVERS):
@ -913,7 +925,8 @@ def matrix_command_cb(data, buffer, args):
if len(split_args) < 1: if len(split_args) < 1:
message = ("{prefix}matrix: Too few arguments for command " message = ("{prefix}matrix: Too few arguments for command "
"\"/matrix\" (see /help matrix)").format(prefix=W.prefix("error")) "\"/matrix\" "
"(see /help matrix)").format(prefix=W.prefix("error"))
W.prnt("", message) W.prnt("", message)
return W.WEECHAT_RC_ERROR return W.WEECHAT_RC_ERROR

View file

@ -528,6 +528,14 @@ class MatrixServer(object):
user_id) user_id)
self.send_or_queue(request) self.send_or_queue(request)
def room_join(self, room_id):
_, request = self.client.join(room_id)
self.send_or_queue(request)
def room_leave(self, room_id):
_, request = self.client.room_leave(room_id)
self.send_or_queue(request)
def room_send_message(self, room_buffer, formatted, msgtype="m.text"): def room_send_message(self, room_buffer, formatted, msgtype="m.text"):
# type: (RoomBuffer, Formatted, str) -> None # type: (RoomBuffer, Formatted, str) -> None
if room_buffer.room.encrypted: if room_buffer.room.encrypted:
@ -617,17 +625,19 @@ class MatrixServer(object):
self.sync(timeout=0, filter=sync_filter) self.sync(timeout=0, filter=sync_filter)
def _handle_room_info(self, response): def _handle_room_info(self, response):
for room_id, join_info in response.rooms.join.items(): for room_id, info in response.rooms.leave.items():
if room_id not in self.buffers:
continue
room_buffer = self.find_room_from_id(room_id)
room_buffer.handle_left_room(info)
for room_id, info in response.rooms.join.items():
if room_id not in self.buffers: if room_id not in self.buffers:
self.create_room_buffer(room_id) self.create_room_buffer(room_id)
room_buffer = self.find_room_from_id(room_id) room_buffer = self.find_room_from_id(room_id)
room_buffer.handle_joined_room(info)
for event in join_info.state:
room_buffer.handle_state_event(event)
for event in join_info.timeline.events:
room_buffer.handle_timeline_event(event)
def _handle_sync(self, response): def _handle_sync(self, response):
# we got the same batch again, nothing to do # we got the same batch again, nothing to do