From e4fd1128cc5fd1353b32c40fbe78009777281258 Mon Sep 17 00:00:00 2001 From: Mathieu Velten Date: Thu, 23 Nov 2023 14:51:00 +0100 Subject: [PATCH] Add avatar and topic settings for server notice room --- changelog.d/16679.feature | 1 + docs/server_notices.md | 4 +- .../configuration/config_documentation.md | 4 + synapse/config/server_notices.py | 12 +++ .../server_notices/server_notices_manager.py | 98 ++++++++++++++++++- 5 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 changelog.d/16679.feature diff --git a/changelog.d/16679.feature b/changelog.d/16679.feature new file mode 100644 index 000000000000..2398e4386759 --- /dev/null +++ b/changelog.d/16679.feature @@ -0,0 +1 @@ +Add a way to set the avatar and the topic of the server notices room. diff --git a/docs/server_notices.md b/docs/server_notices.md index 339d10a0ab3f..0585665e2ecb 100644 --- a/docs/server_notices.md +++ b/docs/server_notices.md @@ -46,11 +46,13 @@ server_notices: system_mxid_display_name: "Server Notices" system_mxid_avatar_url: "mxc://server.com/oumMVlgDnLYFaPVkExemNVVZ" room_name: "Server Notices" + room_avatar_url: "mxc://server.com/oumMVlgDnLYFaPVkExemNVVZ" + room_topic: "Room used by your server admin to notice you of important information" ``` The only compulsory setting is `system_mxid_localpart`, which defines the user id of the Server Notices user, as above. `room_name` defines the name of the -room which will be created. +room which will be created, `room_avatar_url` its avatar and `room_topic` its topic. `system_mxid_display_name` and `system_mxid_avatar_url` can be used to set the displayname and avatar of the Server Notices user. diff --git a/docs/usage/configuration/config_documentation.md b/docs/usage/configuration/config_documentation.md index 7c4e742cd5d5..e4182282f307 100644 --- a/docs/usage/configuration/config_documentation.md +++ b/docs/usage/configuration/config_documentation.md @@ -3815,6 +3815,8 @@ Sub-options for this setting include: * `system_mxid_display_name`: set the display name of the "notices" user * `system_mxid_avatar_url`: set the avatar for the "notices" user * `room_name`: set the room name of the server notices room +* `room_avatar_url`: set the room avatar URL of the server notices room +* `room_topic`: set the room topic of the server notices room Example configuration: ```yaml @@ -3823,6 +3825,8 @@ server_notices: system_mxid_display_name: "Server Notices" system_mxid_avatar_url: "mxc://server.com/oumMVlgDnLYFaPVkExemNVVZ" room_name: "Server Notices" + room_avatar_url: "mxc://server.com/oumMVlgDnLYFaPVkExemNVVZ" + room_topic: "Room used by your server admin to notice you of important information" ``` --- ### `enable_room_list_search` diff --git a/synapse/config/server_notices.py b/synapse/config/server_notices.py index ce041abe9bb3..cdb3416ba781 100644 --- a/synapse/config/server_notices.py +++ b/synapse/config/server_notices.py @@ -38,6 +38,14 @@ class ServerNoticesConfig(Config): server_notices_room_name (str|None): The name to use for the server notices room. None if server notices are not enabled. + + server_notices_room_avatar_url (str|None): + The avatar URL to use for the server notices room. + None if server notices are not enabled. + + server_notices_room_topic (str|None): + The topic to use for the server notices room. + None if server notices are not enabled. """ section = "servernotices" @@ -48,6 +56,8 @@ def __init__(self, *args: Any): self.server_notices_mxid_display_name: Optional[str] = None self.server_notices_mxid_avatar_url: Optional[str] = None self.server_notices_room_name: Optional[str] = None + self.server_notices_room_avatar_url: Optional[str] = None + self.server_notices_room_topic: Optional[str] = None def read_config(self, config: JsonDict, **kwargs: Any) -> None: c = config.get("server_notices") @@ -62,3 +72,5 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None: self.server_notices_mxid_avatar_url = c.get("system_mxid_avatar_url", None) # todo: i18n self.server_notices_room_name = c.get("room_name", "Server Notices") + self.server_notices_room_avatar_url = c.get("room_avatar_url", None) + self.server_notices_room_avatar_url = c.get("room_topic", None) diff --git a/synapse/server_notices/server_notices_manager.py b/synapse/server_notices/server_notices_manager.py index c3552d6c73f8..57afa11d3ee1 100644 --- a/synapse/server_notices/server_notices_manager.py +++ b/synapse/server_notices/server_notices_manager.py @@ -160,6 +160,30 @@ async def get_or_create_notice_room_for_user(self, user_id: str) -> str: self._config.servernotices.server_notices_mxid_display_name, self._config.servernotices.server_notices_mxid_avatar_url, ) + await self._update_room_info( + requester, + room_id, + EventTypes.Name, + "name", + self._config.servernotices.server_notices_room_name, + if_changed_only=True, + ) + await self._update_room_info( + requester, + room_id, + EventTypes.RoomAvatar, + "url", + self._config.servernotices.server_notices_room_avatar_url, + if_changed_only=True, + ) + await self._update_room_info( + requester, + room_id, + EventTypes.Topic, + "topic", + self._config.servernotices.server_notices_room_topic, + if_changed_only=True, + ) return room_id # apparently no existing notice room: create a new one @@ -178,17 +202,33 @@ async def get_or_create_notice_room_for_user(self, user_id: str) -> str: "avatar_url": self._config.servernotices.server_notices_mxid_avatar_url, } + room_config = { + "preset": RoomCreationPreset.PRIVATE_CHAT, + "power_level_content_override": {"users_default": -10}, + } + + if self._config.servernotices.server_notices_room_name: + room_config["name"] = self._config.servernotices.server_notices_room_name + if self._config.servernotices.server_notices_room_topic: + room_config["topic"] = self._config.servernotices.server_notices_room_topic + room_id, _, _ = await self._room_creation_handler.create_room( requester, - config={ - "preset": RoomCreationPreset.PRIVATE_CHAT, - "name": self._config.servernotices.server_notices_room_name, - "power_level_content_override": {"users_default": -10}, - }, + config=room_config, ratelimit=False, creator_join_profile=join_profile, ) + # Room avatar can't be set at creation time so let's just send an event for that + if self._config.servernotices.server_notices_room_avatar_url: + await self._update_room_info( + requester, + room_id, + EventTypes.RoomAvatar, + "url", + self._config.servernotices.server_notices_room_avatar_url, + ) + self.maybe_get_notice_room_for_user.invalidate((user_id,)) max_id = await self._account_data_handler.add_tag_to_room( @@ -272,3 +312,51 @@ async def _update_notice_user_profile_if_changed( ratelimit=False, content={"displayname": display_name, "avatar_url": avatar_url}, ) + + async def _update_room_info( + self, + requester: Requester, + room_id: str, + info_event_type: str, + info_content_key: str, + info_value: Optional[str], + if_changed_only: Optional[bool] = False, + ) -> None: + """ + Updates a specific notice room's info if it's different from what is set. + + Args: + requester: The user who is performing the update. + room_id: The ID of the server notice room + info_event_type: The event type holding the specific info + info_content_key: The key containing the specific info in the event's content + info_value: The expected value for the specific info + if_changed_only: Try to read the info first and does not send the event if it's already the same + """ + if if_changed_only: + room_info_event = await self._message_handler.get_room_data( + requester, + room_id, + info_event_type, + "", + ) + + if room_info_event and room_info_event.get(info_content_key) == info_value: + return + + if info_value is None: + info_value = "" + + room_info_event_dict = { + "type": info_event_type, + "room_id": room_id, + "sender": requester.user.to_string(), + "state_key": "", + "content": { + info_content_key: info_value, + }, + } + + event, _ = await self._event_creation_handler.create_and_send_nonmember_event( + requester, room_info_event_dict, ratelimit=False + )