From 56b921e65a3fdb30b1960ede0e76ceb21bb903fd Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Mon, 22 Nov 2021 22:42:47 +0100 Subject: [PATCH 01/11] improve type checking for push This adds explicit types, via TypedDicts for most of the data structures used inside the push module. Signed-off-by: Marcus Hoffmann --- synapse/push/emailpusher.py | 10 ++- synapse/push/httppusher.py | 3 +- synapse/push/mailer.py | 64 ++++++++++-------- synapse/push/push_types.py | 66 +++++++++++++++++++ .../databases/main/event_push_actions.py | 20 +++++- 5 files changed, 129 insertions(+), 34 deletions(-) create mode 100644 synapse/push/push_types.py diff --git a/synapse/push/emailpusher.py b/synapse/push/emailpusher.py index cf5abdfbda49..4f13c0418ab9 100644 --- a/synapse/push/emailpusher.py +++ b/synapse/push/emailpusher.py @@ -21,6 +21,8 @@ from synapse.metrics.background_process_metrics import run_as_background_process from synapse.push import Pusher, PusherConfig, PusherConfigException, ThrottleParams from synapse.push.mailer import Mailer +from synapse.push.push_types import EmailReason +from synapse.storage.databases.main.event_push_actions import EmailPushAction from synapse.util.threepids import validate_email if TYPE_CHECKING: @@ -190,7 +192,7 @@ async def _unsafe_process(self) -> None: # we then consider all previously outstanding notifications # to be delivered. - reason = { + reason: EmailReason = { "room_id": push_action["room_id"], "now": self.clock.time_msec(), "received_at": received_at, @@ -275,7 +277,7 @@ def room_ready_to_notify_at(self, room_id: str) -> int: return may_send_at async def sent_notif_update_throttle( - self, room_id: str, notified_push_action: dict + self, room_id: str, notified_push_action: EmailPushAction ) -> None: # We have sent a notification, so update the throttle accordingly. # If the event that triggered the notif happened more than @@ -315,7 +317,9 @@ async def sent_notif_update_throttle( self.pusher_id, room_id, self.throttle_params[room_id] ) - async def send_notification(self, push_actions: List[dict], reason: dict) -> None: + async def send_notification( + self, push_actions: List[EmailPushAction], reason: EmailReason + ) -> None: logger.info("Sending notif email for user %r", self.user_id) await self.mailer.send_notification_mail( diff --git a/synapse/push/httppusher.py b/synapse/push/httppusher.py index dbf4ad7f97ee..bd68937f8824 100644 --- a/synapse/push/httppusher.py +++ b/synapse/push/httppusher.py @@ -28,6 +28,7 @@ from synapse.push import Pusher, PusherConfig, PusherConfigException from . import push_rule_evaluator, push_tools +from ..storage.databases.main.event_push_actions import HttpPushAction if TYPE_CHECKING: from synapse.server import HomeServer @@ -273,7 +274,7 @@ async def _unsafe_process(self) -> None: ) break - async def _process_one(self, push_action: dict) -> bool: + async def _process_one(self, push_action: HttpPushAction) -> bool: if "notify" not in push_action["actions"]: return True diff --git a/synapse/push/mailer.py b/synapse/push/mailer.py index ce299ba3da16..cacc0853d987 100644 --- a/synapse/push/mailer.py +++ b/synapse/push/mailer.py @@ -28,6 +28,14 @@ descriptor_from_member_events, name_from_member_event, ) +from synapse.push.push_types import ( + EmailReason, + MessageVars, + NotifVars, + RoomVars, + TemplateVars, +) +from synapse.storage.databases.main.event_push_actions import EmailPushAction from synapse.storage.state import StateFilter from synapse.types import StateMap, UserID from synapse.util.async_helpers import concurrently_execute @@ -135,7 +143,7 @@ async def send_password_reset_mail( % urllib.parse.urlencode(params) ) - template_vars = {"link": link} + template_vars: TemplateVars = {"link": link} await self.send_email( email_address, @@ -165,7 +173,7 @@ async def send_registration_mail( % urllib.parse.urlencode(params) ) - template_vars = {"link": link} + template_vars: TemplateVars = {"link": link} await self.send_email( email_address, @@ -196,7 +204,7 @@ async def send_add_threepid_mail( % urllib.parse.urlencode(params) ) - template_vars = {"link": link} + template_vars: TemplateVars = {"link": link} await self.send_email( email_address, @@ -210,8 +218,8 @@ async def send_notification_mail( app_id: str, user_id: str, email_address: str, - push_actions: Iterable[Dict[str, Any]], - reason: Dict[str, Any], + push_actions: Iterable[EmailPushAction], + reason: EmailReason, ) -> None: """ Send email regarding a user's room notifications @@ -230,7 +238,7 @@ async def send_notification_mail( [pa["event_id"] for pa in push_actions] ) - notifs_by_room: Dict[str, List[Dict[str, Any]]] = {} + notifs_by_room: Dict[str, List[EmailPushAction]] = {} for pa in push_actions: notifs_by_room.setdefault(pa["room_id"], []).append(pa) @@ -258,7 +266,7 @@ async def _fetch_room_state(room_id: str) -> None: # actually sort our so-called rooms_in_order list, most recent room first rooms_in_order.sort(key=lambda r: -(notifs_by_room[r][-1]["received_ts"] or 0)) - rooms: List[Dict[str, Any]] = [] + rooms: List[RoomVars] = [] for r in rooms_in_order: roomvars = await self._get_room_vars( @@ -289,7 +297,7 @@ async def _fetch_room_state(room_id: str) -> None: notifs_by_room, state_by_room, notif_events, reason ) - template_vars = { + template_vars: TemplateVars = { "user_display_name": user_display_name, "unsubscribe_link": self._make_unsubscribe_link( user_id, app_id, email_address @@ -302,10 +310,10 @@ async def _fetch_room_state(room_id: str) -> None: await self.send_email(email_address, summary_text, template_vars) async def send_email( - self, email_address: str, subject: str, extra_template_vars: Dict[str, Any] + self, email_address: str, subject: str, extra_template_vars: TemplateVars ) -> None: """Send an email with the given information and template text""" - template_vars = { + template_vars: TemplateVars = { "app_name": self.app_name, "server_name": self.hs.config.server.server_name, } @@ -327,10 +335,10 @@ async def _get_room_vars( self, room_id: str, user_id: str, - notifs: Iterable[Dict[str, Any]], + notifs: Iterable[EmailPushAction], notif_events: Dict[str, EventBase], room_state_ids: StateMap[str], - ) -> Dict[str, Any]: + ) -> RoomVars: """ Generate the variables for notifications on a per-room basis. @@ -356,7 +364,7 @@ async def _get_room_vars( room_name = await calculate_room_name(self.store, room_state_ids, user_id) - room_vars: Dict[str, Any] = { + room_vars: RoomVars = { "title": room_name, "hash": string_ordinal_total(room_id), # See sender avatar hash "notifs": [], @@ -417,11 +425,11 @@ async def _get_room_avatar( async def _get_notif_vars( self, - notif: Dict[str, Any], + notif: EmailPushAction, user_id: str, notif_event: EventBase, room_state_ids: StateMap[str], - ) -> Dict[str, Any]: + ) -> NotifVars: """ Generate the variables for a single notification. @@ -442,7 +450,7 @@ async def _get_notif_vars( after_limit=CONTEXT_AFTER, ) - ret = { + ret: NotifVars = { "link": self._make_notif_link(notif), "ts": notif["received_ts"], "messages": [], @@ -461,8 +469,8 @@ async def _get_notif_vars( return ret async def _get_message_vars( - self, notif: Dict[str, Any], event: EventBase, room_state_ids: StateMap[str] - ) -> Optional[Dict[str, Any]]: + self, notif: EmailPushAction, event: EventBase, room_state_ids: StateMap[str] + ) -> Optional[MessageVars]: """ Generate the variables for a single event, if possible. @@ -494,7 +502,9 @@ async def _get_message_vars( if sender_state_event: sender_name = name_from_member_event(sender_state_event) - sender_avatar_url = sender_state_event.content.get("avatar_url") + sender_avatar_url: Optional[str] = sender_state_event.content.get( + "avatar_url" + ) else: # No state could be found, fallback to the MXID. sender_name = event.sender @@ -504,7 +514,7 @@ async def _get_message_vars( # sender_hash % the number of default images to choose from sender_hash = string_ordinal_total(event.sender) - ret = { + ret: MessageVars = { "event_type": event.type, "is_historical": event.event_id != notif["event_id"], "id": event.event_id, @@ -533,7 +543,7 @@ async def _get_message_vars( return ret def _add_text_message_vars( - self, messagevars: Dict[str, Any], event: EventBase + self, messagevars: MessageVars, event: EventBase ) -> None: """ Potentially add a sanitised message body to the message variables. @@ -555,7 +565,7 @@ def _add_text_message_vars( messagevars["body_text_html"] = safe_text(body) def _add_image_message_vars( - self, messagevars: Dict[str, Any], event: EventBase + self, messagevars: MessageVars, event: EventBase ) -> None: """ Potentially add an image URL to the message variables. @@ -570,7 +580,7 @@ def _add_image_message_vars( async def _make_summary_text_single_room( self, room_id: str, - notifs: List[Dict[str, Any]], + notifs: List[EmailPushAction], room_state_ids: StateMap[str], notif_events: Dict[str, EventBase], user_id: str, @@ -685,10 +695,10 @@ async def _make_summary_text_single_room( async def _make_summary_text( self, - notifs_by_room: Dict[str, List[Dict[str, Any]]], + notifs_by_room: Dict[str, List[EmailPushAction]], room_state_ids: Dict[str, StateMap[str]], notif_events: Dict[str, EventBase], - reason: Dict[str, Any], + reason: EmailReason, ) -> str: """ Make a summary text for the email when multiple rooms have notifications. @@ -718,7 +728,7 @@ async def _make_summary_text( async def _make_summary_text_from_member_events( self, room_id: str, - notifs: List[Dict[str, Any]], + notifs: List[EmailPushAction], room_state_ids: StateMap[str], notif_events: Dict[str, EventBase], ) -> str: @@ -805,7 +815,7 @@ def _make_room_link(self, room_id: str) -> str: base_url = "https://matrix.to/#" return "%s/%s" % (base_url, room_id) - def _make_notif_link(self, notif: Dict[str, str]) -> str: + def _make_notif_link(self, notif: EmailPushAction) -> str: """ Generate a link to open an event in the web client. diff --git a/synapse/push/push_types.py b/synapse/push/push_types.py new file mode 100644 index 000000000000..4471ad14669d --- /dev/null +++ b/synapse/push/push_types.py @@ -0,0 +1,66 @@ +# Copyright 2021 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import List, Optional, Any +from typing_extensions import TypedDict + + +class EmailReason(TypedDict, total=False): + room_id: str + room_name: Optional[str] + now: int + received_at: int + delay_before_mail_ms: int + last_sent_ts: int + throttle_ms: int + + +class NotifVars(TypedDict): + link: str + ts: Optional[int] + messages: List + + +class RoomVars(TypedDict): + title: Optional[str] + hash: int + notifs: List + invite: bool + link: str + avatar_url: Optional[str] + + +class MessageVars(TypedDict, total=False): + event_type: str + is_historical: bool + id: str + ts: int + sender_name: str + sender_avatar_url: Optional[str] + sender_hash: int + msgtype: Optional[Any] + body_text_html: str + body_text_plain: str + image_url: str + format: Optional[Any] + + +class TemplateVars(TypedDict, total=False): + app_name: str + server_name: str + link: str + user_display_name: str + unsubscribe_link: str + summary_text: str + rooms: List + reason: EmailReason diff --git a/synapse/storage/databases/main/event_push_actions.py b/synapse/storage/databases/main/event_push_actions.py index d957e770dcd8..944dece59386 100644 --- a/synapse/storage/databases/main/event_push_actions.py +++ b/synapse/storage/databases/main/event_push_actions.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import logging -from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union +from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, TypedDict, Union import attr @@ -37,6 +37,20 @@ ] +class BasePushAction(TypedDict): + event_id: str + actions: List[Union[dict, str]] + + +class HttpPushAction(BasePushAction): + room_id: str + stream_ordering: int + + +class EmailPushAction(HttpPushAction): + received_ts: Optional[int] + + def _serialize_action(actions, is_highlight): """Custom serializer for actions. This allows us to "compress" common actions. @@ -221,7 +235,7 @@ async def get_unread_push_actions_for_user_in_range_for_http( min_stream_ordering: int, max_stream_ordering: int, limit: int = 20, - ) -> List[dict]: + ) -> List[HttpPushAction]: """Get a list of the most recent unread push actions for a given user, within the given stream ordering range. Called by the httppusher. @@ -326,7 +340,7 @@ async def get_unread_push_actions_for_user_in_range_for_email( min_stream_ordering: int, max_stream_ordering: int, limit: int = 20, - ) -> List[dict]: + ) -> List[EmailPushAction]: """Get a list of the most recent unread push actions for a given user, within the given stream ordering range. Called by the emailpusher From e9991bf3c920ab0adf9c905cfddda663592530ca Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Mon, 22 Nov 2021 23:03:28 +0100 Subject: [PATCH 02/11] add changelog --- changelog.d/11409.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/11409.misc diff --git a/changelog.d/11409.misc b/changelog.d/11409.misc new file mode 100644 index 000000000000..f9e8ae9e3a5f --- /dev/null +++ b/changelog.d/11409.misc @@ -0,0 +1 @@ +Improve internal types in push code. From fb1fbc13716d2878144a334e8fce009bc844f88a Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Mon, 22 Nov 2021 23:04:57 +0100 Subject: [PATCH 03/11] isort --- synapse/push/httppusher.py | 2 +- synapse/push/push_types.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/synapse/push/httppusher.py b/synapse/push/httppusher.py index bd68937f8824..a7bfeb010406 100644 --- a/synapse/push/httppusher.py +++ b/synapse/push/httppusher.py @@ -27,8 +27,8 @@ from synapse.metrics.background_process_metrics import run_as_background_process from synapse.push import Pusher, PusherConfig, PusherConfigException -from . import push_rule_evaluator, push_tools from ..storage.databases.main.event_push_actions import HttpPushAction +from . import push_rule_evaluator, push_tools if TYPE_CHECKING: from synapse.server import HomeServer diff --git a/synapse/push/push_types.py b/synapse/push/push_types.py index 4471ad14669d..459a08511185 100644 --- a/synapse/push/push_types.py +++ b/synapse/push/push_types.py @@ -11,7 +11,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import List, Optional, Any +from typing import Any, List, Optional + from typing_extensions import TypedDict From 08f12e412176bfa34df781ad1f5c6e70e1ea5ea7 Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Mon, 22 Nov 2021 23:05:34 +0100 Subject: [PATCH 04/11] lint --- synapse/push/mailer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/push/mailer.py b/synapse/push/mailer.py index cacc0853d987..6c7648436142 100644 --- a/synapse/push/mailer.py +++ b/synapse/push/mailer.py @@ -14,7 +14,7 @@ import logging import urllib.parse -from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, TypeVar +from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, TypeVar import bleach import jinja2 From d404a4cea8747fdfedb99f17f508d0890326036c Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Mon, 22 Nov 2021 23:18:31 +0100 Subject: [PATCH 05/11] use TypedDict from typing_extensions --- synapse/storage/databases/main/event_push_actions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/synapse/storage/databases/main/event_push_actions.py b/synapse/storage/databases/main/event_push_actions.py index 944dece59386..3ea2c7de8ada 100644 --- a/synapse/storage/databases/main/event_push_actions.py +++ b/synapse/storage/databases/main/event_push_actions.py @@ -13,7 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. import logging -from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, TypedDict, Union +from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union +from typing_extensions import TypedDict import attr From 073bdb8b4dd526d2885572fc1078fc1e6dcf2dfc Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Mon, 22 Nov 2021 23:27:06 +0100 Subject: [PATCH 06/11] isort again --- synapse/storage/databases/main/event_push_actions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/storage/databases/main/event_push_actions.py b/synapse/storage/databases/main/event_push_actions.py index 3ea2c7de8ada..3efdd0c920f6 100644 --- a/synapse/storage/databases/main/event_push_actions.py +++ b/synapse/storage/databases/main/event_push_actions.py @@ -14,9 +14,9 @@ # limitations under the License. import logging from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union -from typing_extensions import TypedDict import attr +from typing_extensions import TypedDict from synapse.metrics.background_process_metrics import wrap_as_background_process from synapse.storage._base import SQLBaseStore, db_to_json From ec270560835f4ecb99fc2793dc6351363688621b Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Tue, 23 Nov 2021 12:41:10 +0100 Subject: [PATCH 07/11] properly type fields pulled from event json --- synapse/push/mailer.py | 4 ++++ synapse/push/push_types.py | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/synapse/push/mailer.py b/synapse/push/mailer.py index 6c7648436142..5a3963dc1628 100644 --- a/synapse/push/mailer.py +++ b/synapse/push/mailer.py @@ -529,6 +529,8 @@ async def _get_message_vars( return ret msgtype = event.content.get("msgtype") + if not isinstance(msgtype, str): + msgtype = None ret["msgtype"] = msgtype @@ -553,6 +555,8 @@ def _add_text_message_vars( event: The event under consideration. """ msgformat = event.content.get("format") + if not isinstance(msgformat, str): + msgformat = None messagevars["format"] = msgformat diff --git a/synapse/push/push_types.py b/synapse/push/push_types.py index 459a08511185..dbf5a0972729 100644 --- a/synapse/push/push_types.py +++ b/synapse/push/push_types.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, List, Optional +from typing import List, Optional from typing_extensions import TypedDict @@ -49,11 +49,11 @@ class MessageVars(TypedDict, total=False): sender_name: str sender_avatar_url: Optional[str] sender_hash: int - msgtype: Optional[Any] + msgtype: Optional[str] body_text_html: str body_text_plain: str image_url: str - format: Optional[Any] + format: Optional[str] class TemplateVars(TypedDict, total=False): From 6f8c5d5b775e150c08df36eb5c67c4a6715a8153 Mon Sep 17 00:00:00 2001 From: Marcus Date: Tue, 23 Nov 2021 12:42:14 +0100 Subject: [PATCH 08/11] Update synapse/push/httppusher.py Co-authored-by: Sean Quah <8349537+squahtx@users.noreply.github.com> --- synapse/push/httppusher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/push/httppusher.py b/synapse/push/httppusher.py index a7bfeb010406..52005799a6d5 100644 --- a/synapse/push/httppusher.py +++ b/synapse/push/httppusher.py @@ -27,7 +27,7 @@ from synapse.metrics.background_process_metrics import run_as_background_process from synapse.push import Pusher, PusherConfig, PusherConfigException -from ..storage.databases.main.event_push_actions import HttpPushAction +from synapse.storage.databases.main.event_push_actions import HttpPushAction from . import push_rule_evaluator, push_tools if TYPE_CHECKING: From c8387bdb0968c929a5ae99287a5c96b3ceec2be4 Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Tue, 23 Nov 2021 14:24:56 +0100 Subject: [PATCH 09/11] add docstrings for EmailReason The parameter "now" was never used, so it can be removed. --- synapse/push/emailpusher.py | 1 - synapse/push/push_types.py | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/synapse/push/emailpusher.py b/synapse/push/emailpusher.py index 4f13c0418ab9..860584f4cfa7 100644 --- a/synapse/push/emailpusher.py +++ b/synapse/push/emailpusher.py @@ -194,7 +194,6 @@ async def _unsafe_process(self) -> None: reason: EmailReason = { "room_id": push_action["room_id"], - "now": self.clock.time_msec(), "received_at": received_at, "delay_before_mail_ms": DELAY_BEFORE_MAIL_MS, "last_sent_ts": self.get_room_last_sent_ts(push_action["room_id"]), diff --git a/synapse/push/push_types.py b/synapse/push/push_types.py index dbf5a0972729..c0d6dca02d87 100644 --- a/synapse/push/push_types.py +++ b/synapse/push/push_types.py @@ -17,9 +17,23 @@ class EmailReason(TypedDict, total=False): + """ + Information on the event that triggered the email to be sent + + Params: + room_id: the ID of the room the event was sent in + room_name: a human-readable name for the room the event was sent in + received_at: the time in milliseconds at which the event was received + delay_before_mail_ms: the amount of time in milliseconds Synapse always waits + before ever emailing about a notification (to give the user a chance to respond + to other push or notice the window) + last_sent_ts: the time in milliseconds at which a notification was last sent + for an event in this room + throttle_ms: the minimum amount of time in milliseconds between two + notifications can be sent for this room + """ room_id: str room_name: Optional[str] - now: int received_at: int delay_before_mail_ms: int last_sent_ts: int From 388803d29e128e7956d2f3a580d4761eedcfdd14 Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Tue, 23 Nov 2021 16:07:54 +0100 Subject: [PATCH 10/11] document all the push types Synchronize with docs/templates.md --- docs/templates.md | 5 ++ synapse/push/emailpusher.py | 1 + synapse/push/mailer.py | 2 - synapse/push/push_types.py | 106 ++++++++++++++++++++++++++---------- 4 files changed, 84 insertions(+), 30 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index a240f58b54fd..2b66e9d86294 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -71,7 +71,12 @@ Below are the templates Synapse will look for when generating the content of an * `sender_avatar_url`: the avatar URL (as a `mxc://` URL) for the event's sender * `sender_hash`: a hash of the user ID of the sender + * `msgtype`: the type of the message + * `body_text_html`: html representation of the message + * `body_text_plain`: plaintext representation of the message + * `image_url`: mxc url of an image, when "msgtype" is "m.image" * `link`: a `matrix.to` link to the room + * `avator_url`: url to the room's avator * `reason`: information on the event that triggered the email to be sent. It's an object with the following attributes: * `room_id`: the ID of the room the event was sent in diff --git a/synapse/push/emailpusher.py b/synapse/push/emailpusher.py index 860584f4cfa7..4f13c0418ab9 100644 --- a/synapse/push/emailpusher.py +++ b/synapse/push/emailpusher.py @@ -194,6 +194,7 @@ async def _unsafe_process(self) -> None: reason: EmailReason = { "room_id": push_action["room_id"], + "now": self.clock.time_msec(), "received_at": received_at, "delay_before_mail_ms": DELAY_BEFORE_MAIL_MS, "last_sent_ts": self.get_room_last_sent_ts(push_action["room_id"]), diff --git a/synapse/push/mailer.py b/synapse/push/mailer.py index 5a3963dc1628..ba4f866487ec 100644 --- a/synapse/push/mailer.py +++ b/synapse/push/mailer.py @@ -558,8 +558,6 @@ def _add_text_message_vars( if not isinstance(msgformat, str): msgformat = None - messagevars["format"] = msgformat - formatted_body = event.content.get("formatted_body") body = event.content.get("body") diff --git a/synapse/push/push_types.py b/synapse/push/push_types.py index c0d6dca02d87..e86ab235b0c4 100644 --- a/synapse/push/push_types.py +++ b/synapse/push/push_types.py @@ -20,19 +20,20 @@ class EmailReason(TypedDict, total=False): """ Information on the event that triggered the email to be sent - Params: - room_id: the ID of the room the event was sent in - room_name: a human-readable name for the room the event was sent in - received_at: the time in milliseconds at which the event was received - delay_before_mail_ms: the amount of time in milliseconds Synapse always waits - before ever emailing about a notification (to give the user a chance to respond - to other push or notice the window) - last_sent_ts: the time in milliseconds at which a notification was last sent - for an event in this room - throttle_ms: the minimum amount of time in milliseconds between two - notifications can be sent for this room + room_id: the ID of the room the event was sent in + now: timestamp in ms when the email is being sent out + room_name: a human-readable name for the room the event was sent in + received_at: the time in milliseconds at which the event was received + delay_before_mail_ms: the amount of time in milliseconds Synapse always waits + before ever emailing about a notification (to give the user a chance to respond + to other push or notice the window) + last_sent_ts: the time in milliseconds at which a notification was last sent + for an event in this room + throttle_ms: the minimum amount of time in milliseconds between two + notifications can be sent for this room """ room_id: str + now: int room_name: Optional[str] received_at: int delay_before_mail_ms: int @@ -40,22 +41,24 @@ class EmailReason(TypedDict, total=False): throttle_ms: int -class NotifVars(TypedDict): - link: str - ts: Optional[int] - messages: List - - -class RoomVars(TypedDict): - title: Optional[str] - hash: int - notifs: List - invite: bool - link: str - avatar_url: Optional[str] - - class MessageVars(TypedDict, total=False): + """ + Details about a specific message to include in a notification + + event_type: the type of the event + is_historical: a boolean, which is `False` if the message is the one + that triggered the notification, `True` otherwise + id: the ID of the event + ts: the time in milliseconds at which the event was sent + sender_name: the display name for the event's sender + sender_avatar_url: the avatar URL (as a `mxc://` URL) for the event's + sender + sender_hash: a hash of the user ID of the sender + msgtype: the type of the message + body_text_html: html representation of the message + body_text_plain: plaintext representation of the message + image_url: mxc url of an image, when "msgtype" is "m.image" + """ event_type: str is_historical: bool id: str @@ -67,15 +70,62 @@ class MessageVars(TypedDict, total=False): body_text_html: str body_text_plain: str image_url: str - format: Optional[str] + + +class NotifVars(TypedDict): + """ + Details about an event we are about to include in a notification + + link: a `matrix.to` link to the event + ts: the time in milliseconds at which the event was received + messages: a list of messages containing one message before the event, the + message in the event, and one message after the event. + """ + link: str + ts: Optional[int] + messages: List[MessageVars] + + +class RoomVars(TypedDict): + """ + Represents a room containing events to include in the email. + + title: a human-readable name for the room + hash: a hash of the ID of the room + invite: a boolean, which is `True` if the room is an invite the user hasn't + accepted yet, `False` otherwise + notifs: a list of events, or an empty list if `invite` is `True`. + link: a `matrix.to` link to the room + avator_url: url to the room's avator + """ + title: Optional[str] + hash: int + invite: bool + notifs: List[NotifVars] + link: str + avatar_url: Optional[str] class TemplateVars(TypedDict, total=False): + """ + Generic structure for passing to the email sender, can hold all the fields used in email templates. + + app_name: name of the app/service this homeserver is associated with + server_name: name of our own homeserver + link: a link to include into the email to be sent + user_display_name: the display name for the user receiving the notification + unsubscribe_link: the link users can click to unsubscribe from email notifications + summary_text: a summary of the notification(s). The text used can be customised + by configuring the various settings in the `email.subjects` section of the + configuration file. + rooms: a list of rooms containing events to include in the email + reason: information on the event that triggered the email to be sent + """ app_name: str server_name: str link: str user_display_name: str unsubscribe_link: str summary_text: str - rooms: List + rooms: List[RoomVars] reason: EmailReason From 2904f49c7406ee8af130a024e9bebb3fbf32205c Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Tue, 23 Nov 2021 16:08:53 +0100 Subject: [PATCH 11/11] lint --- synapse/push/httppusher.py | 2 +- synapse/push/push_types.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/synapse/push/httppusher.py b/synapse/push/httppusher.py index 52005799a6d5..3fa603ccb7f7 100644 --- a/synapse/push/httppusher.py +++ b/synapse/push/httppusher.py @@ -26,8 +26,8 @@ from synapse.logging import opentracing from synapse.metrics.background_process_metrics import run_as_background_process from synapse.push import Pusher, PusherConfig, PusherConfigException - from synapse.storage.databases.main.event_push_actions import HttpPushAction + from . import push_rule_evaluator, push_tools if TYPE_CHECKING: diff --git a/synapse/push/push_types.py b/synapse/push/push_types.py index e86ab235b0c4..8d16ab62cef6 100644 --- a/synapse/push/push_types.py +++ b/synapse/push/push_types.py @@ -32,6 +32,7 @@ class EmailReason(TypedDict, total=False): throttle_ms: the minimum amount of time in milliseconds between two notifications can be sent for this room """ + room_id: str now: int room_name: Optional[str] @@ -59,6 +60,7 @@ class MessageVars(TypedDict, total=False): body_text_plain: plaintext representation of the message image_url: mxc url of an image, when "msgtype" is "m.image" """ + event_type: str is_historical: bool id: str @@ -81,6 +83,7 @@ class NotifVars(TypedDict): messages: a list of messages containing one message before the event, the message in the event, and one message after the event. """ + link: str ts: Optional[int] messages: List[MessageVars] @@ -98,6 +101,7 @@ class RoomVars(TypedDict): link: a `matrix.to` link to the room avator_url: url to the room's avator """ + title: Optional[str] hash: int invite: bool @@ -121,6 +125,7 @@ class TemplateVars(TypedDict, total=False): rooms: a list of rooms containing events to include in the email reason: information on the event that triggered the email to be sent """ + app_name: str server_name: str link: str