54 lines
1.7 KiB
Python
54 lines
1.7 KiB
Python
from asgiref.sync import async_to_sync
|
|
from channels.layers import get_channel_layer
|
|
import rules
|
|
|
|
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,
|
|
},
|
|
)
|