diff --git a/osinaweb/db.sqlite3 b/osinaweb/db.sqlite3 index b8f93ba2..6c272bc8 100644 Binary files a/osinaweb/db.sqlite3 and b/osinaweb/db.sqlite3 differ diff --git a/osinaweb/static/js/tickets/tickets-room.js b/osinaweb/static/js/tickets/tickets-room.js index 8736bd93..0a794b5e 100644 --- a/osinaweb/static/js/tickets/tickets-room.js +++ b/osinaweb/static/js/tickets/tickets-room.js @@ -63,7 +63,7 @@ function app(socket) { function initializeWebSocket() { const ticketId = document.getElementById('ticketId').textContent.trim(); - const wsUrl = `wss://${window.location.host}/ws/ticketroom/${ticketId}/`; + const wsUrl = `ws://${window.location.host}/ws/ticketroom/${ticketId}/`; const socket = new WebSocket(wsUrl); socket.onopen = () => { diff --git a/osinaweb/support/__pycache__/consumers.cpython-310.pyc b/osinaweb/support/__pycache__/consumers.cpython-310.pyc index 05c2d41e..c4b4a2e5 100644 Binary files a/osinaweb/support/__pycache__/consumers.cpython-310.pyc and b/osinaweb/support/__pycache__/consumers.cpython-310.pyc differ diff --git a/osinaweb/support/consumers.py b/osinaweb/support/consumers.py index 71ab0ec1..2e233f54 100644 --- a/osinaweb/support/consumers.py +++ b/osinaweb/support/consumers.py @@ -11,65 +11,59 @@ import json from django.template.loader import render_to_string from asgiref.sync import async_to_sync +from channels.generic.websocket import AsyncWebsocketConsumer +from django.shortcuts import get_object_or_404 +from datetime import datetime +from asgiref.sync import sync_to_async +import json -class TicketRoomConsumer(WebsocketConsumer): - def connect(self): +class TicketRoomConsumer(AsyncWebsocketConsumer): + async def connect(self): self.user = self.scope['user'] self.ticket_id = self.scope['url_route']['kwargs']['ticket_id'] - self.ticket = get_object_or_404(Ticket, id=self.ticket_id) + self.ticket = await sync_to_async(get_object_or_404)(Ticket, id=self.ticket_id) self.ticket_number = self.ticket.ticket_number - existing_connection = TicketConnection.objects.filter(ticket=self.ticket, user=self.user, terminated_at__isnull=True).delete() - TicketConnection.objects.create( + await sync_to_async(TicketConnection.objects.filter(ticket=self.ticket, user=self.user, terminated_at__isnull=True).delete)() + await sync_to_async(TicketConnection.objects.create)( ticket=self.ticket, user=self.user, date=datetime.now() ) - staff_profile = StaffProfile.objects.filter(user=self.user).first() + + staff_profile = await sync_to_async(StaffProfile.objects.filter(user=self.user).first)() if staff_profile: - if not TicketStaff.objects.filter(staff=staff_profile, ticket=self.ticket).exists(): - TicketStaff.objects.create( + if not await sync_to_async(TicketStaff.objects.filter(staff=staff_profile, ticket=self.ticket).exists)(): + await sync_to_async(TicketStaff.objects.create)( staff=staff_profile, ticket=self.ticket, date_added=datetime.now() ) - async_to_sync(self.channel_layer.group_add)( - self.ticket_number, self.channel_name - ) - self.accept() - self.modify_online_user() + await self.channel_layer.group_add(self.ticket_number, self.channel_name) + await self.accept() + await self.modify_online_user() + async def disconnect(self, close_code): + await sync_to_async(TicketConnection.objects.filter(ticket=self.ticket, user=self.user).update)(terminated_at=datetime.now()) + await self.channel_layer.group_discard(self.ticket_number, self.channel_name) + await self.modify_online_user() - def disconnect(self, close_code): - TicketConnection.objects.filter( - ticket=self.ticket, - user=self.user, - ).update(terminated_at=datetime.now()) - async_to_sync(self.channel_layer.group_discard)( - self.ticket_number, self.channel_name - ) - self.modify_online_user() - - def receive(self, text_data): + async def receive(self, text_data): text_data_json = json.loads(text_data) event_type = text_data_json.get('event_type') - + if event_type == 'typing': event = { 'type': 'typing_handler', 'user': self.scope['user'] } - async_to_sync(self.channel_layer.group_send)( - self.ticket_number, event - ) + await self.channel_layer.group_send(self.ticket_number, event) elif event_type == 'stop_typing': event = { 'type': 'stop_typing_handler', } - async_to_sync(self.channel_layer.group_send)( - self.ticket_number, event - ) + await self.channel_layer.group_send(self.ticket_number, event) elif event_type == 'update_reaction': reaction = text_data_json['reaction'] update_id = text_data_json['update_id'] @@ -79,13 +73,11 @@ class TicketRoomConsumer(WebsocketConsumer): 'reaction': reaction, 'user': self.scope['user'] } - async_to_sync(self.channel_layer.group_send)( - self.ticket_number, event - ) + await self.channel_layer.group_send(self.ticket_number, event) else: body = text_data_json['description'] file_paths = text_data_json['filePath'] - ticketupdate = TicketUpdate.objects.create( + ticketupdate = await sync_to_async(TicketUpdate.objects.create)( added_by=self.user, description=body, ticket=self.ticket, @@ -96,94 +88,88 @@ class TicketRoomConsumer(WebsocketConsumer): ticket_update=ticketupdate, file_path=file_path ) - ticket_attachment.save() + await sync_to_async(ticket_attachment.save)() event = { 'type': 'update_handler', 'update_id': ticketupdate.id } - async_to_sync(self.channel_layer.group_send)( - self.ticket_number, event - ) + await self.channel_layer.group_send(self.ticket_number, event) - def update_handler(self, event): + async def update_handler(self, event): update_id = event['update_id'] - update = TicketUpdate.objects.get(id=update_id) + update = await sync_to_async(TicketUpdate.objects.get)(id=update_id) context = { 'update': update, 'user': self.user } - - - html = render_to_string("details_templates/partials/new-ticket-message.html", context=context) - self.send(text_data=json.dumps({ + html = await sync_to_async(render_to_string)("details_templates/partials/new-ticket-message.html", context=context) + await self.send(text_data=json.dumps({ 'event_type': 'update', 'html': html })) - def typing_handler(self, event): + async def typing_handler(self, event): context = { 'user': event['user'] } - html = render_to_string("details_templates/partials/typing-message.html", context=context) - self.send(text_data=json.dumps({ + html = await sync_to_async(render_to_string)("details_templates/partials/typing-message.html", context=context) + await self.send(text_data=json.dumps({ 'event_type': 'typing', 'html': html })) - def stop_typing_handler(self, event): - self.send(text_data=json.dumps({ + async def stop_typing_handler(self, event): + await self.send(text_data=json.dumps({ 'event_type': 'stop_typing' })) - def reaction_handler(self, event): + async def reaction_handler(self, event): update_id = event['update_id'] reaction = event['reaction'] user = self.user - update = TicketUpdate.objects.get(id=update_id) - existing_reaction = TicketUpdateReaction.objects.filter(ticket_update=update, customer=user).first() + update = await sync_to_async(TicketUpdate.objects.get)(id=update_id) + existing_reaction = await sync_to_async(TicketUpdateReaction.objects.filter)(ticket_update=update, customer=user).first() new_reaction = None if existing_reaction: - # If the existing reaction type is equal to the new reaction, delete it if existing_reaction.reaction == reaction: - existing_reaction.delete() + await sync_to_async(existing_reaction.delete)() else: - # If not, delete all previous reactions and add a new one - TicketUpdateReaction.objects.filter(ticket_update=update, customer=user).delete() - new_reaction = TicketUpdateReaction.objects.create( + await sync_to_async(TicketUpdateReaction.objects.filter)(ticket_update=update, customer=user).delete() + new_reaction = await sync_to_async(TicketUpdateReaction.objects.create)( ticket_update=update, reaction=reaction, customer=user ) else: - # If there's no existing reaction, simply add the new one - new_reaction = TicketUpdateReaction.objects.create( + new_reaction = await sync_to_async(TicketUpdateReaction.objects.create)( ticket_update=update, reaction=reaction, customer=user ) - self.send(text_data=json.dumps({ + await self.send(text_data=json.dumps({ 'event_type': 'reaction', 'update_id': update_id, 'reaction': new_reaction.reaction if new_reaction else None })) - def modify_online_user(self): + async def modify_online_user(self): + connections = await sync_to_async(TicketConnection.objects.filter)(ticket=self.ticket, terminated_at__isnull=True) event = { 'type': 'user_connection_handler', 'user': self.user, + 'connections': connections, } - async_to_sync(self.channel_layer.group_send)( - self.ticket_number, event - ) + await self.channel_layer.group_send(self.ticket_number, event) - def user_connection_handler(self, event): + async def user_connection_handler(self, event): context = { + 'connections': event['connections'], 'user': event['user'] } - html = render_to_string("details_templates/partials/ticket-online-users.html", context=context) - self.send(text_data=json.dumps({ + html = await sync_to_async(render_to_string)("details_templates/partials/ticket-online-users.html", context=context) + await self.send(text_data=json.dumps({ 'event_type': 'user_status', 'html': html }))