|
2 | 2 | Defines data models for each email we sent out to users. |
3 | 3 | """ |
4 | 4 |
|
| 5 | +import re |
5 | 6 | from abc import ABC, abstractmethod |
6 | 7 | from dataclasses import dataclass |
7 | 8 | from datetime import UTC, date, datetime |
@@ -274,6 +275,25 @@ def build_body(self, builder: EmailBlocksBuilder, loc_context: LocalizationConte |
274 | 275 | builder.quote(self.text, markdown=False) |
275 | 276 | builder.action(self.view_url, "view_action") |
276 | 277 |
|
| 278 | + @classmethod |
| 279 | + def from_notification(cls, data: notification_data_pb2.ChatMessage, *, user_name: str) -> Self: |
| 280 | + group_chat_title: str | None = data.group_chat_title |
| 281 | + if not group_chat_title: |
| 282 | + # Backcompat (2026-05): The group name previously was formatted in the message string |
| 283 | + # msg = f"{message.author.name} sent a message in {group_chat.title}" |
| 284 | + if match := re.search(" sent a message in (.+)$", data.message or ""): |
| 285 | + group_chat_title = match[1] |
| 286 | + else: |
| 287 | + group_chat_title = None |
| 288 | + |
| 289 | + return cls( |
| 290 | + user_name, |
| 291 | + author=UserInfo.from_protobuf(data.author), |
| 292 | + text=data.text, |
| 293 | + group_chat_title=group_chat_title, |
| 294 | + view_url=urls.chat_link(chat_id=data.group_chat_id), |
| 295 | + ) |
| 296 | + |
277 | 297 | @classmethod |
278 | 298 | def dummy_data(cls) -> ChatMessageReceivedEmail: |
279 | 299 | return ChatMessageReceivedEmail( |
@@ -318,6 +338,38 @@ def build_body(self, builder: EmailBlocksBuilder, loc_context: LocalizationConte |
318 | 338 | builder.quote(entry.latest_message_text, markdown=False) |
319 | 339 | builder.action(entry.view_url, "view_action") |
320 | 340 |
|
| 341 | + @classmethod |
| 342 | + def from_notification(cls, data: notification_data_pb2.ChatMissedMessages, *, user_name: str) -> Self: |
| 343 | + missed_entries = [] |
| 344 | + for message in data.messages: |
| 345 | + group_chat_title: str | None = message.group_chat_title |
| 346 | + missed_count: int = message.unseen_count |
| 347 | + |
| 348 | + # Backcompat (2026-05): The group name and unseen count were previously was formatted in the message string |
| 349 | + # msg = f"You missed {unseen_count} message(s) in {group_chat.title}" |
| 350 | + if not group_chat_title or not missed_count: |
| 351 | + if match := re.search(" message(s) in (.+)$", message.message or ""): |
| 352 | + group_chat_title = match[1] |
| 353 | + else: |
| 354 | + group_chat_title = None |
| 355 | + |
| 356 | + if match := re.search(r"^You missed (\d+) message(s)", message.message or ""): |
| 357 | + missed_count = int(match[1]) |
| 358 | + else: |
| 359 | + missed_count = 1 |
| 360 | + |
| 361 | + missed_entries.append( |
| 362 | + cls.Entry( |
| 363 | + group_chat_title=group_chat_title, |
| 364 | + missed_count=missed_count, |
| 365 | + latest_message_author=UserInfo.from_protobuf(message.author), |
| 366 | + latest_message_text=message.text, |
| 367 | + view_url=urls.chat_link(chat_id=message.group_chat_id), |
| 368 | + ) |
| 369 | + ) |
| 370 | + |
| 371 | + return cls(user_name, entries=missed_entries) |
| 372 | + |
321 | 373 | @classmethod |
322 | 374 | def dummy_data(cls) -> ChatMessagesMissedEmail: |
323 | 375 | return ChatMessagesMissedEmail( |
|
0 commit comments