Corp/backend/communications/services/chat_quick_reply.py
2026-09-07 19:43:48 +03:00

54 lines
1.7 KiB
Python

import rules
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from communications.models import Message
from communications.serialization import serialize_message
from communications.utils import user_can_access_chat
class ChatQuickReplyError(Exception):
"""A native push reply cannot be sent to the requested chat."""
class ChatQuickReplyService:
"""Create and broadcast a plain-text reply received from native push UI."""
MAX_CONTENT_LENGTH = 4000
def send(self, *, chat, user, reply_to, content: str) -> Message:
normalized_content = content.strip()
if not normalized_content:
raise ChatQuickReplyError("empty reply")
if len(normalized_content) > self.MAX_CONTENT_LENGTH:
raise ChatQuickReplyError("reply too long")
if not chat.can_reply:
raise ChatQuickReplyError("replies are disabled")
if not user_can_access_chat(chat, user) or not rules.test_rule(
"communications.send_message",
user,
chat,
):
raise ChatQuickReplyError("sending is not allowed")
message = Message.objects.create(
chat=chat,
author=user,
content=normalized_content,
reply_to=reply_to,
)
self._broadcast(message)
return message
@staticmethod
def _broadcast(message: Message) -> None:
payload = serialize_message(message)
async_to_sync(get_channel_layer().group_send)(
f"chat_{message.chat_id}",
{
"type": "chat.message",
"chat_id": message.chat_id,
"payload": payload,
},
)