diff --git a/matrix/buffer.py b/matrix/buffer.py index f27d20b..c659718 100644 --- a/matrix/buffer.py +++ b/matrix/buffer.py @@ -385,8 +385,9 @@ class WeechatChannelBuffer(object): message = self._membership_message(user, "join") self.print_date_tags(message, date, tags) - def invite(self, user, date, extra_tags=[]): - # type: (WeechatUser, int, Optional[bool], Optional[List[str]]) -> None + def invite(self, nick, date, extra_tags=[]): + # type: (str, int, Optional[bool], Optional[List[str]]) -> None + user = self._get_user(nick) tags = self._message_tags(user, "invite") message = self._membership_message(user, "invite") self.print_date_tags(message, date, tags + extra_tags) diff --git a/matrix/rooms.py b/matrix/rooms.py index f03251f..0c2c29c 100644 --- a/matrix/rooms.py +++ b/matrix/rooms.py @@ -208,6 +208,9 @@ class RoomInfo(): elif event_dict["content"]["membership"] == "leave": return RoomMemberLeave.from_dict(event_dict) + elif event_dict["content"]["membership"] == "invite": + return RoomMemberInvite.from_dict(event_dict) + return None @staticmethod @@ -308,6 +311,10 @@ class RoomEvent(): self.timestamp = timestamp +class RoomMembershipEvent(RoomEvent): + pass + + class RoomRedactedMessageEvent(RoomEvent): def __init__(self, event_id, sender, timestamp, censor, reason=None): @@ -527,11 +534,22 @@ class RoomMessageMedia(RoomMessageEvent): self._print_message(msg, room, buff, tags) -class RoomMemberJoin(RoomEvent): +class RoomMemberJoin(RoomMembershipEvent): - def __init__(self, event_id, sender, timestamp, display_name, state_key): + def __init__( + self, + event_id, + sender, + timestamp, + display_name, + state_key, + content, + prev_content + ): self.display_name = display_name self.state_key = state_key + self.content = content + self.prev_content = prev_content RoomEvent.__init__(self, event_id, sender, timestamp) @classmethod @@ -541,16 +559,42 @@ class RoomMemberJoin(RoomEvent): timestamp = sanitize_ts(event_dict["origin_server_ts"]) state_key = sanitize_id(event_dict["state_key"]) display_name = None + content = event_dict["content"] + prev_content = (event_dict["unsigned"]["prev_content"] + if "prev_content" in event_dict["unsigned"] else None) if event_dict["content"]: if "display_name" in event_dict["content"]: display_name = sanitize_text( event_dict["content"]["displayname"]) - return cls(event_id, sender, timestamp, display_name, state_key) + return cls( + event_id, + sender, + timestamp, + display_name, + state_key, + content, + prev_content + ) -class RoomMemberLeave(RoomEvent): +class RoomMemberInvite(RoomMembershipEvent): + def __init__(self, event_id, sender, invited_user, timestamp): + self.invited_user = invited_user + RoomEvent.__init__(self, event_id, sender, timestamp) + + @classmethod + def from_dict(cls, event_dict): + event_id = sanitize_id(event_dict["event_id"]) + sender = sanitize_id(event_dict["sender"]) + invited_user = sanitize_id(event_dict["state_key"]) + timestamp = sanitize_ts(event_dict["origin_server_ts"]) + + return cls(event_id, sender, invited_user, timestamp) + + +class RoomMemberLeave(RoomMembershipEvent): def __init__(self, event_id, sender, leaving_user, timestamp): self.leaving_user = leaving_user diff --git a/matrix/server.py b/matrix/server.py index 694e86b..3a2e0b9 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -40,8 +40,10 @@ from .rooms import ( RoomMessageText, RoomMessageEmote, MatrixUser, + RoomMembershipEvent, RoomMemberJoin, RoomMemberLeave, + RoomMemberInvite, RoomTopicEvent ) from matrix.api import ( @@ -638,7 +640,7 @@ class MatrixServer: event, is_state_event ): - if isinstance(event, RoomMemberJoin): + def join(event, date, room, room_buffer, is_state_event): room.handle_event(event) user = room.users[event.sender] buffer_user = RoomUser(user.name, event.sender) @@ -655,14 +657,39 @@ class MatrixServer: not is_state_event ) - elif isinstance(event, RoomMemberLeave): - user = room.users[event.sender] - date = server_ts_to_weechat(event.timestamp) + date = server_ts_to_weechat(event.timestamp) - if event.sender == event.leaving_user: - room_buffer.part(user.name, date, not is_state_event) + joined = False + left = False + + if isinstance(event, RoomMemberJoin): + if event.prev_content and "membership" in event.prev_content: + if (event.prev_content["membership"] == "leave" + or event.prev_content["membership"] == "invite"): + join(event, date, room, room_buffer, is_state_event) + joined = True + else: + # TODO print out profile changes + return else: - room_buffer.kick(user.name, date, not is_state_event) + # No previous content for this user in this room, so he just + # joined. + join(event, date, room, room_buffer, is_state_event) + joined = True + + elif isinstance(event, RoomMemberLeave): + # TODO the nick can be a display name or a full sender name + nick = shorten_sender(event.sender) + if event.sender == event.leaving_user: + room_buffer.part(nick, date, not is_state_event) + else: + room_buffer.kick(nick, date, not is_state_event) + + left = True + + elif isinstance(event, RoomMemberInvite): + room_buffer.invite(event.sender, date) + return # calculate room display name and set it as the buffer list name room_name = room.display_name(self.user_id) @@ -670,11 +697,11 @@ class MatrixServer: # A user has joined or left an encrypted room, we need to check for # new devices and create a new group session - if room.encrypted: + if room.encrypted and (joined or left): self.device_check_timestamp = None def handle_room_event(self, room, room_buffer, event, is_state_event): - if isinstance(event, (RoomMemberJoin, RoomMemberLeave)): + if isinstance(event, RoomMembershipEvent): self.handle_room_membership_events( room, room_buffer,