128 lines
3.8 KiB
Python
128 lines
3.8 KiB
Python
"""Synchronize stored and native browser notifications with chat events."""
|
|
|
|
from collections import defaultdict
|
|
|
|
from django.db import transaction
|
|
from django.utils import timezone
|
|
|
|
from notifications.cache import invalidate_unread_summary
|
|
from notifications.models import Notification
|
|
from notifications.realtime import send_notifications_deleted_event
|
|
|
|
PUSH_CONTROL_ID_BATCH_SIZE = 150
|
|
|
|
|
|
def queue_push_control(
|
|
*,
|
|
user_id: int,
|
|
action: str,
|
|
scope: dict,
|
|
replacement_notification_id: int | None = None,
|
|
) -> None:
|
|
def enqueue():
|
|
from notifications.tasks import send_push_control
|
|
|
|
send_push_control.delay(
|
|
user_id,
|
|
action,
|
|
scope,
|
|
replacement_notification_id,
|
|
)
|
|
|
|
transaction.on_commit(enqueue)
|
|
|
|
|
|
def dismiss_chat_push(
|
|
*,
|
|
user_id: int,
|
|
chat_id: int,
|
|
notification_ids=None,
|
|
) -> None:
|
|
scope = {"chat_id": chat_id}
|
|
if notification_ids:
|
|
scope["notification_ids"] = [
|
|
int(item) for item in list(notification_ids)[:PUSH_CONTROL_ID_BATCH_SIZE]
|
|
]
|
|
queue_push_control(
|
|
user_id=user_id,
|
|
action="dismiss_chat",
|
|
scope=scope,
|
|
)
|
|
|
|
|
|
def dismiss_notifications_push(*, user_id: int, notification_ids) -> None:
|
|
normalized_ids = [int(notification_id) for notification_id in notification_ids]
|
|
for start in range(0, len(normalized_ids), PUSH_CONTROL_ID_BATCH_SIZE):
|
|
queue_push_control(
|
|
user_id=user_id,
|
|
action="dismiss_notifications",
|
|
scope={
|
|
"notification_ids": normalized_ids[
|
|
start : start + PUSH_CONTROL_ID_BATCH_SIZE
|
|
]
|
|
},
|
|
)
|
|
|
|
|
|
def delete_message_notifications(*, chat_id: int, message_id: int) -> None:
|
|
notifications = list(
|
|
Notification.objects.filter(
|
|
deleted=False,
|
|
data__chat_id=chat_id,
|
|
data__message_id=message_id,
|
|
).values("id", "recipient_id")
|
|
)
|
|
if not notifications:
|
|
return
|
|
|
|
notification_ids = [item["id"] for item in notifications]
|
|
Notification.objects.filter(id__in=notification_ids).update(
|
|
deleted=True,
|
|
unread=False,
|
|
timestamp_read=timezone.now(),
|
|
)
|
|
notifications_by_recipient = defaultdict(list)
|
|
for item in notifications:
|
|
notifications_by_recipient[item["recipient_id"]].append(item["id"])
|
|
for recipient_id, recipient_notification_ids in notifications_by_recipient.items():
|
|
invalidate_unread_summary(recipient_id)
|
|
send_notifications_deleted_event(
|
|
recipient_id,
|
|
recipient_notification_ids,
|
|
)
|
|
queue_push_control(
|
|
user_id=recipient_id,
|
|
action="dismiss_message",
|
|
scope={"chat_id": chat_id, "message_id": message_id},
|
|
)
|
|
|
|
|
|
def replace_message_notifications(message) -> None:
|
|
notifications = list(
|
|
Notification.objects.filter(
|
|
deleted=False,
|
|
data__chat_id=message.chat_id,
|
|
data__message_id=message.id,
|
|
)
|
|
)
|
|
if not notifications:
|
|
return
|
|
|
|
description = (message.content or "").strip()
|
|
if len(description) > 150:
|
|
description = description[:147] + "..."
|
|
grouped = defaultdict(list)
|
|
for notification in notifications:
|
|
notification.description = description
|
|
grouped[notification.recipient_id].append(notification)
|
|
Notification.objects.bulk_update(notifications, ["description"])
|
|
|
|
for recipient_id, recipient_notifications in grouped.items():
|
|
latest = max(recipient_notifications, key=lambda item: item.id)
|
|
queue_push_control(
|
|
user_id=recipient_id,
|
|
action="replace_message",
|
|
scope={"chat_id": message.chat_id, "message_id": message.id},
|
|
replacement_notification_id=latest.id,
|
|
)
|