help-desk/backend/chat/consumers.py

92 lines
4.1 KiB
Python

import json
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
from helpdesk.services.ticket_service import TicketService # ตรวจสอบ Ticket
class ChatConsumer(AsyncWebsocketConsumer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.ticket_id = None
self.ticket_group_name = None
@database_sync_to_async
def check_ticket_and_auth(self, ticket_id, user):
"""ตรวจสอบสิทธิ์และสถานะของ Ticket ใน DB"""
if not user.is_authenticated:
return False
# Business Logic Authorization:
# ใช้ TicketService เพื่อตรวจสอบว่าผู้ใช้มีสิทธิ์เข้าถึง Ticket นี้หรือไม่
if not TicketService().is_user_authorized(ticket_id, user):
return False
# สำหรับตัวอย่างนี้ให้แค่ตรวจสอบว่า Ticket มีอยู่จริงหรือไม่
from helpdesk.models import Ticket
return Ticket.objects.filter(pk=ticket_id).exists()
async def connect(self):
self.ticket_id = self.scope['url_route']['kwargs']['ticket_id']
self.ticket_group_name = f'ticket_{self.ticket_id}'
user = self.scope['user']
# 1. ตรวจสอบสิทธิ์ก่อนเชื่อมต่อ
is_allowed = await self.check_ticket_and_auth(self.ticket_id, user)
if is_allowed:
# Join room group
await self.channel_layer.group_add(
self.ticket_group_name,
self.channel_name
)
await self.accept()
else:
await self.close()
async def disconnect(self, close_code):
if self.ticket_group_name:
# Leave room group
await self.channel_layer.group_discard(
self.ticket_group_name,
self.channel_name
)
# Receive message from WebSocket (ไคลเอนต์ส่งข้อความมา)
async def receive(self, text_data=None, bytes_data=None):
# Consumer ไม่ควรมี Business Logic
# ข้อมูลขาเข้าควรถูกส่งไปให้ Service Layer ประมวลผล
text_data_json = json.loads(text_data)
content = text_data_json.get('content')
# เรียก Service เพื่อสร้างและส่งข้อความ (ต้องทำแบบ sync)
# เนื่องจาก Consumer เป็น async, เราจะส่งไปให้ Service แบบ sync/async
await self.save_message_and_broadcast(self.ticket_id, self.scope['user'], content)
# เมธอดที่ Service Layer เรียกผ่าน Channel Layer (group_send)
async def chat_message(self, event):
"""ส่งข้อความที่ถูก broadcast กลับไปยัง WebSocket Client"""
message = event['message']
# Send message to WebSocket
await self.send(text_data=json.dumps({
'type': 'new_message',
'message': message
}))
@database_sync_to_async
def save_message_and_broadcast(self, ticket_id, user, content):
"""
เมธอด sync ที่เรียก Service Layer เพื่อทำ Business Logic
และส่ง broadcast กลับมา (ผ่าน _send_realtime_update ใน Service)
"""
from chat.services.message_service import chat_svc # ต้องแน่ใจว่า import ถูกต้อง
if not content:
return
# Service จะสร้างข้อความใน DB, อัปเดต Ticket, และส่ง broadcast
chat_svc.create_and_send_message(
ticket_id=ticket_id,
sender=user,
content=content,
message_type='T'
)