diff --git a/matrix/api.py b/matrix/api.py index 4e8c8d3..071ee22 100644 --- a/matrix/api.py +++ b/matrix/api.py @@ -443,13 +443,3 @@ class MatrixInviteMessage(MatrixMessage): self.room_id, self.user_id) return self._decode(server, object_hook) - - -class MatrixUser: - - def __init__(self, name, display_name): - self.name = name # type: str - self.display_name = display_name # type: str - self.power_level = 0 # type: int - self.nick_color = "" # type: str - self.prefix = "" # type: str diff --git a/matrix/messages.py b/matrix/messages.py index 7ed2df6..f673770 100644 --- a/matrix/messages.py +++ b/matrix/messages.py @@ -28,12 +28,14 @@ from matrix.colors import Formatted from matrix.globals import W, OPTIONS -from matrix.api import (MessageType, MatrixUser) +from matrix.api import MessageType +from matrix.rooms import MatrixUser from matrix.rooms import MatrixRoom from matrix.utils import (server_buffer_prnt, tags_from_line_data, prnt_debug, - color_for_tags) + color_for_tags, add_user_to_nicklist, + get_prefix_for_level) from matrix.plugin_options import RedactType, DebugType @@ -42,22 +44,6 @@ def strip_matrix_server(string): return string.rsplit(":", 1)[0] -def add_user_to_nicklist(buf, user): - group_name = "999|..." - - if user.power_level >= 100: - group_name = "000|o" - elif user.power_level >= 50: - group_name = "001|h" - elif user.power_level > 0: - group_name = "002|v" - - group = W.nicklist_search_group(buf, "", group_name) - # TODO make it configurable so we can use a display name or user_id here - W.nicklist_add_nick(buf, group, user.display_name, user.nick_color, - user.prefix, get_prefix_color(user.prefix), 1) - - def matrix_create_room_buffer(server, room_id): # type: (MatrixServer, str) -> None buf = W.buffer_new(room_id, "room_input_cb", server.name, "room_close_cb", @@ -133,7 +119,7 @@ def matrix_handle_room_members(server, room_id, event): nick_pointer = W.nicklist_search_nick(buf, "", user.display_name) if not nick_pointer: - add_user_to_nicklist(buf, user) + add_user_to_nicklist(buf, full_name, user) else: # TODO we can get duplicate display names pass @@ -364,29 +350,6 @@ def matrix_handle_room_redaction(server, room_id, event): return W.WEECHAT_RC_OK -def get_prefix_for_level(level): - # type: (int) -> str - if level >= 100: - return "&" - elif level >= 50: - return "@" - elif level > 0: - return "+" - return "" - - -# TODO make this configurable -def get_prefix_color(prefix): - # type: (str) -> str - if prefix == "&": - return "lightgreen" - elif prefix == "@": - return "lightgreen" - elif prefix == "+": - return "yellow" - return "" - - def matrix_handle_room_power_levels(server, room_id, event): if not event['content']['users']: return diff --git a/matrix/rooms.py b/matrix/rooms.py index 8c84cb1..54b8524 100644 --- a/matrix/rooms.py +++ b/matrix/rooms.py @@ -23,7 +23,7 @@ from matrix.colors import Formatted from matrix.utils import (strip_matrix_server, color_for_tags, date_from_age, sender_to_nick_and_color, tags_for_message, add_event_tags, sanitize_id, sanitize_age, - sanitize_text) + sanitize_text, shorten_sender, add_user_to_nicklist) class MatrixRoom: @@ -43,6 +43,18 @@ class MatrixRoom: # yapf: enable +class MatrixUser: + + def __init__(self, name, display_name): + # yapf: disable + self.name = name # type: str + self.display_name = display_name # type: str + self.power_level = 0 # type: int + self.nick_color = "" # type: str + self.prefix = "" # type: str + # yapf: enable + + def matrix_create_room_buffer(server, room_id): # type: (MatrixServer, str) -> None buf = W.buffer_new(room_id, "room_input_cb", server.name, "room_close_cb", @@ -95,10 +107,28 @@ class RoomInfo(): return RoomMessageEvent.from_dict(event) + @staticmethod + def _membership_from_dict(event_dict): + if (event_dict["membership"] not in [ + "invite", "join", "knock", "leave", "ban" + ]): + raise ValueError + + if event_dict["membership"] == "join": + return RoomMemberJoin.from_dict(event_dict) + elif event_dict["membership"] == "leave": + return RoomMemberLeave.from_dict(event_dict) + + return None + @staticmethod def _event_from_dict(event): - if event['type'] == 'm.room.message': + if event["type"] == "m.room.message": return RoomInfo._message_from_event(event) + elif event["type"] == "m.room.member": + return RoomInfo._membership_from_dict(event) + else: + return None @classmethod def from_dict(cls, room_id, parsed_dict): @@ -147,7 +177,7 @@ class RoomRedactedMessageEvent(RoomEvent): return cls(event_id, sender, age, censor, reason) - def execute(self, room, buff, tags): + def execute(self, server, room, buff, tags): nick, color_name = sender_to_nick_and_color(room, self.sender) color = color_for_tags(color_name) date = date_from_age(self.age) @@ -203,7 +233,7 @@ class RoomMessageEvent(RoomEvent): return cls(event_id, sender, age, msg, formatted_msg) - def execute(self, room, buff, tags): + def execute(self, server, room, buff, tags): msg = (self.formatted_message.to_weechat() if self.formatted_message else self.message) @@ -218,3 +248,67 @@ class RoomMessageEvent(RoomEvent): date = date_from_age(self.age) W.prnt_date_tags(buff, date, tags_string, data) + + +class RoomMemberJoin(RoomEvent): + + def __init__(self, event_id, sender, age, display_name): + self.display_name = display_name + RoomEvent.__init__(self, event_id, sender, age) + + @classmethod + def from_dict(cls, event_dict): + event_id = sanitize_id(event_dict["event_id"]) + sender = sanitize_id(event_dict["sender"]) + age = sanitize_age(event_dict["unsigned"]["age"]) + display_name = sanitize_text(event_dict["content"]["displayname"]) + + return cls(event_id, sender, age, display_name) + + def execute(self, server, room, buff, tags): + short_name = shorten_sender(self.sender) + + if self.sender in room.users: + user = room.users[self.sender] + if self.display_name: + user.display_name = self.display_name + else: + user = MatrixUser(short_name, self.display_name) + + if not user.nick_color: + if self.sender == server.user_id: + user.nick_color = "weechat.color.chat_nick_self" + W.buffer_set(buff, "highlight_words", ",".join( + [self.sender, user.name, user.display_name])) + else: + user.nick_color = W.info_get("nick_color_name", user.name) + + room.users[self.sender] = user + + nick_pointer = W.nicklist_search_nick(buff, "", self.sender) + + if not nick_pointer: + add_user_to_nicklist(buff, self.sender, user) + + +class RoomMemberLeave(RoomEvent): + + def __init__(self, event_id, sender, age): + RoomEvent.__init__(self, event_id, sender, age) + + @classmethod + def from_dict(cls, event_dict): + event_id = sanitize_id(event_dict["event_id"]) + sender = sanitize_id(event_dict["sender"]) + age = sanitize_age(event_dict["unsigned"]["age"]) + + return cls(event_id, sender, age) + + def execute(self, server, room, buff, tags): + if self.sender in room.users: + nick_pointer = W.nicklist_search_nick(buff, "", self.sender) + + if nick_pointer: + W.nicklist_remove_nick(buff, nick_pointer) + + del room.users[self.sender] diff --git a/matrix/utils.py b/matrix/utils.py index 3faee0a..926f702 100644 --- a/matrix/utils.py +++ b/matrix/utils.py @@ -236,3 +236,42 @@ def sanitize_text(string): # yapf: enable return string.translate(remap) + + +def add_user_to_nicklist(buf, user_id, user): + group_name = "999|..." + + if user.power_level >= 100: + group_name = "000|o" + elif user.power_level >= 50: + group_name = "001|h" + elif user.power_level > 0: + group_name = "002|v" + + group = W.nicklist_search_group(buf, "", group_name) + # TODO make it configurable so we can use a display name or user_id here + W.nicklist_add_nick(buf, group, user_id, user.nick_color, user.prefix, + get_prefix_color(user.prefix), 1) + + +def get_prefix_for_level(level): + # type: (int) -> str + if level >= 100: + return "&" + elif level >= 50: + return "@" + elif level > 0: + return "+" + return "" + + +# TODO make this configurable +def get_prefix_color(prefix): + # type: (str) -> str + if prefix == "&": + return "lightgreen" + elif prefix == "@": + return "lightgreen" + elif prefix == "+": + return "yellow" + return ""