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
# file, import the callbacks here so weechat can find them.
from matrix.commands import (hook_commands, hook_page_up, matrix_command_cb,
matrix_topic_command_cb, matrix_command_join_cb,
matrix_command_part_cb, matrix_invite_command_cb,
matrix_topic_command_cb, matrix_join_command_cb,
matrix_part_command_cb, matrix_invite_command_cb,
matrix_command_pgup_cb, matrix_redact_command_cb,
matrix_command_buf_clear_cb, matrix_me_command_cb,
matrix_kick_command_cb)

View file

@ -783,6 +783,8 @@ class RoomBuffer(object):
def __init__(self, room, server_name):
self.room = room
self.backlog_pending = False
self.joined = True
self.leave_event_id = None # type: Optional[str]
buffer_name = "{}.{}".format(room.room_id, server_name)
@ -854,6 +856,12 @@ class RoomBuffer(object):
if event.state_key in self.displayed_nicks:
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":
if is_state:
return
@ -1200,6 +1208,44 @@ class RoomBuffer(object):
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):
# type: (str) -> None
self.weechat_buffer.error(string)

View file

@ -79,6 +79,18 @@ class WeechatCommandParser(object):
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():
W.hook_command(
@ -185,9 +197,34 @@ def hook_commands():
"matrix_invite_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(
# Command name and short description
"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', '')
@ -320,64 +357,41 @@ def matrix_command_pgup_cb(data, buffer, command):
@utf8_decode
def matrix_command_join_cb(data, buffer, command):
def join(server, args):
split_args = args.split(" ", 1)
# 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
def matrix_join_command_cb(data, buffer, args):
parsed_args = WeechatCommandParser.join(args)
if not parsed_args:
return W.WEECHAT_RC_OK
for server in SERVERS.values():
if buffer in server.buffers.values():
join(server, command)
return W.WEECHAT_RC_OK_EAT
elif buffer == server.server_buffer:
join(server, command)
return W.WEECHAT_RC_OK_EAT
if buffer in server.buffers.values() or buffer == server.server_buffer:
server.room_join(parsed_args.room_id)
break
return W.WEECHAT_RC_OK
@utf8_decode
def matrix_command_part_cb(data, buffer, command):
def part(server, buffer, args):
rooms = []
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
def matrix_part_command_cb(data, buffer, args):
parsed_args = WeechatCommandParser.part(args)
if not parsed_args:
return W.WEECHAT_RC_OK
for server in SERVERS.values():
if buffer in server.buffers.values():
part(server, buffer, command)
return W.WEECHAT_RC_OK_EAT
elif buffer == server.server_buffer:
part(server, buffer, command)
return W.WEECHAT_RC_OK_EAT
if buffer in server.buffers.values() or buffer == server.server_buffer:
room_id = parsed_args.room_id
if not room_id:
if buffer == server.server_buffer:
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
@ -736,14 +750,14 @@ def matrix_server_command_delete(args):
def matrix_server_command_add(args):
if len(args) < 2:
message = ("{prefix}matrix: Too few arguments for command "
"\"/matrix server add\" (see /matrix help server)"
).format(prefix=W.prefix("error"))
"\"/matrix server add\" (see /matrix help server)").format(
prefix=W.prefix("error"))
W.prnt("", message)
return
elif len(args) > 4:
message = ("{prefix}matrix: Too many arguments for command "
"\"/matrix server add\" (see /matrix help server)"
).format(prefix=W.prefix("error"))
).format(prefix=W.prefix("error"))
W.prnt("", message)
return
@ -865,7 +879,6 @@ def matrix_server_command_add(args):
def matrix_server_command(command, args):
def list_servers(_):
if SERVERS:
W.prnt("", "\nAll matrix servers:")
@ -892,7 +905,6 @@ def matrix_server_command(command, args):
@utf8_decode
def matrix_command_cb(data, buffer, args):
def connect_server(args):
for server_name in args:
if check_server_existence(server_name, SERVERS):
@ -913,7 +925,8 @@ def matrix_command_cb(data, buffer, args):
if len(split_args) < 1:
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)
return W.WEECHAT_RC_ERROR

View file

@ -528,6 +528,14 @@ class MatrixServer(object):
user_id)
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"):
# type: (RoomBuffer, Formatted, str) -> None
if room_buffer.room.encrypted:
@ -617,17 +625,19 @@ class MatrixServer(object):
self.sync(timeout=0, filter=sync_filter)
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:
self.create_room_buffer(room_id)
room_buffer = self.find_room_from_id(room_id)
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)
room_buffer.handle_joined_room(info)
def _handle_sync(self, response):
# we got the same batch again, nothing to do