Files
backend-v1/core/apps/chat/consumers/chat.py
2026-04-21 14:45:01 +05:00

123 lines
4.1 KiB
Python

import json
from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncWebsocketConsumer
from django.contrib.auth.models import AnonymousUser
def get_base_url(scope):
headers = dict(scope["headers"])
host = headers.get(b"host", b"").decode()
scheme = "https" if scope.get("scheme") == "https" else "http"
return f"{scheme}://{host}"
class ChatConsumer(AsyncWebsocketConsumer):
"""
Xona asosidagi chat consumer.
Ulanish: ws://host/ws/chat/room/{room_id}/?token=<jwt>
Matn xabari yuborish:
{ "message_type": "text", "text": "Salom" }
Fayl xabari (oldin REST orqali yuklab, keyin URL yuborish):
{ "message_type": "image", "file_url": "https://...", "text": "caption (ixtiyoriy)" }
"""
async def connect(self):
user = self.scope.get("user")
if not user or isinstance(user, AnonymousUser):
await self.close(code=4001)
return
self.room_id = self.scope["url_route"]["kwargs"]["room_id"]
self.room_group = f"chat_room_{self.room_id}"
await self.channel_layer.group_add(self.room_group, self.channel_name)
await self.accept()
async def disconnect(self, close_code):
if hasattr(self, "room_group"):
await self.channel_layer.group_discard(self.room_group, self.channel_name)
async def receive(self, text_data):
user = self.scope.get("user")
if not user or isinstance(user, AnonymousUser):
await self.close(code=401)
return
try:
data = json.loads(text_data)
except (json.JSONDecodeError, ValueError):
await self.send(text_data=json.dumps({"error": "Noto'g'ri format."}))
return
message_type = data.get("message_type", "text")
text = (data.get("text") or "").strip()
if message_type == "text" and not text:
await self.send(text_data=json.dumps({"error": "Matn bo'sh bo'lishi mumkin emas."}))
return
if message_type != "text":
await self.send(
text_data=json.dumps(
{"error": "Fayl xabarlarni yuklash uchun REST API dan foydalaning."}
)
)
return
await self._save_message(user, text)
# Uz
# Bu funksiya ishlatilmayapti, shuning uchun commentga olib qoydim, bu funksiya orniga /core/apps/chat/tasks/message.py ichida rest api yordamida message
# yuborilsa ishlatiladigan task bor.
# En
# This function is not used, so I commented it out. Instead, a task is used in /core/apps/chat/tasks/message.py
# to send message when message is added from REST API.
# async def chat_message(self, event):
# await self.send(
# text_data=json.dumps(
# {
# "id": event["id"],
# "message_type": event["message_type"],
# "text": event["text"],
# "file_url": event["file_url"],
# "sender": event["sender"],
# "created_at": event["created_at"],
# }
# )
# )
@database_sync_to_async
def _save_message(self, user, text):
from core.apps.chat.models import ChatmessageModel
msg = ChatmessageModel.objects.create(
room_id=self.room_id,
sender=user,
message_type="text",
text=text,
)
full_name = user.get_full_name().strip() or str(user.phone)
base_url = get_base_url(self.scope)
avatar_url = (
base_url + user.avatar.url
if user.avatar else None
)
return {
"id": msg.id,
"message_type": msg.message_type,
"text": msg.text,
"file_url": None,
"sender": {
"id": user.id,
"full_name": full_name,
"role": user.role,
"phone": user.phone,
"avatar": avatar_url,
},
"created_at": msg.created_at.isoformat(),
}