feat: improve rich chat notifications
- show image previews in photo notifications - localize non-text notification bodies by message type - use sender names as notification titles
This commit is contained in:
@@ -4,6 +4,7 @@ import re
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.chats.repository import is_chat_muted_for_user, list_chat_members
|
||||
from app.media.repository import list_attachments_by_message_ids
|
||||
from app.messages.models import Message
|
||||
from app.notifications.repository import (
|
||||
create_notification_log,
|
||||
@@ -29,6 +30,21 @@ def _extract_mentions(text: str | None) -> set[str]:
|
||||
return {match.group(1).lower() for match in _MENTION_RE.finditer(text)}
|
||||
|
||||
|
||||
def _message_preview_label(message: Message, image_preview_url: str | None) -> str:
|
||||
text_preview = (message.text or "").strip()
|
||||
if text_preview:
|
||||
return text_preview[:120]
|
||||
message_type = message.type.value if hasattr(message.type, "value") else str(message.type)
|
||||
return {
|
||||
"image": "Photo" if image_preview_url else "Image",
|
||||
"video": "Video",
|
||||
"audio": "Audio",
|
||||
"voice": "Voice message",
|
||||
"circle_video": "Video note",
|
||||
"file": "File",
|
||||
}.get(message_type, "Message")
|
||||
|
||||
|
||||
async def enqueue_notification(db: AsyncSession, payload: NotificationRequest) -> None:
|
||||
await create_notification_log(
|
||||
db,
|
||||
@@ -51,18 +67,28 @@ async def dispatch_message_notifications(db: AsyncSession, message: Message) ->
|
||||
|
||||
sender_users = await list_users_by_ids(db, [message.sender_id])
|
||||
sender_name = sender_users[0].username if sender_users else "Someone"
|
||||
attachments = await list_attachments_by_message_ids(db, message_ids=[message.id])
|
||||
first_attachment = attachments[0] if attachments else None
|
||||
preview_image_url = None
|
||||
if first_attachment and first_attachment.file_type.lower().startswith("image/"):
|
||||
preview_image_url = first_attachment.file_url
|
||||
preview_body = _message_preview_label(message, preview_image_url=preview_image_url)
|
||||
message_type = message.type.value if hasattr(message.type, "value") else str(message.type)
|
||||
|
||||
for recipient in users:
|
||||
base_payload = {
|
||||
"chat_id": message.chat_id,
|
||||
"message_id": message.id,
|
||||
"sender_id": message.sender_id,
|
||||
"message_type": message_type,
|
||||
"preview_image_url": preview_image_url or "",
|
||||
"sender_name": sender_name,
|
||||
}
|
||||
if recipient.id in mentioned_user_ids:
|
||||
payload = {
|
||||
**base_payload,
|
||||
"type": "mention",
|
||||
"text_preview": (message.text or "")[:120],
|
||||
"text_preview": preview_body,
|
||||
}
|
||||
await create_notification_log(
|
||||
db,
|
||||
@@ -72,8 +98,8 @@ async def dispatch_message_notifications(db: AsyncSession, message: Message) ->
|
||||
)
|
||||
send_mention_notification_task.delay(
|
||||
recipient.id,
|
||||
f"{sender_name} mentioned you",
|
||||
(message.text or "")[:120],
|
||||
sender_name,
|
||||
preview_body,
|
||||
payload,
|
||||
)
|
||||
continue
|
||||
@@ -84,7 +110,7 @@ async def dispatch_message_notifications(db: AsyncSession, message: Message) ->
|
||||
payload = {
|
||||
**base_payload,
|
||||
"type": "message",
|
||||
"text_preview": (message.text or "")[:120],
|
||||
"text_preview": preview_body,
|
||||
}
|
||||
await create_notification_log(
|
||||
db,
|
||||
@@ -94,8 +120,8 @@ async def dispatch_message_notifications(db: AsyncSession, message: Message) ->
|
||||
)
|
||||
send_push_notification_task.delay(
|
||||
recipient.id,
|
||||
f"New message from {sender_name}",
|
||||
(message.text or "")[:120],
|
||||
sender_name,
|
||||
preview_body,
|
||||
payload,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user