92 lines
4.1 KiB
Python
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'
|
|
) |