mirror of
				https://gitlab.com/animath/si/plateforme.git
				synced 2025-11-01 00:24:29 +01:00 
			
		
		
		
	Initialize chat interface
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
		
							
								
								
									
										46
									
								
								chat/consumers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								chat/consumers.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| # Copyright (C) 2024 by Animath | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from channels.generic.websocket import AsyncJsonWebsocketConsumer | ||||
| from registration.models import Registration | ||||
|  | ||||
|  | ||||
| class ChatConsumer(AsyncJsonWebsocketConsumer): | ||||
|     """ | ||||
|     This consumer manages the websocket of the chat interface. | ||||
|     """ | ||||
|     async def connect(self) -> None: | ||||
|         """ | ||||
|         This function is called when a new websocket is trying to connect to the server. | ||||
|         We accept only if this is a user of a team of the associated tournament, or a volunteer | ||||
|         of the tournament. | ||||
|         """ | ||||
|  | ||||
|         # Fetch the registration of the current user | ||||
|         user = self.scope['user'] | ||||
|         if user.is_anonymous: | ||||
|             # User is not authenticated | ||||
|             await self.close() | ||||
|             return | ||||
|  | ||||
|         reg = await Registration.objects.aget(user_id=user.id) | ||||
|         self.registration = reg | ||||
|  | ||||
|         # Accept the connection | ||||
|         await self.accept() | ||||
|  | ||||
|     async def disconnect(self, close_code) -> None: | ||||
|         """ | ||||
|         Called when the websocket got disconnected, for any reason. | ||||
|         :param close_code: The error code. | ||||
|         """ | ||||
|         if self.scope['user'].is_anonymous: | ||||
|             # User is not authenticated | ||||
|             return | ||||
|  | ||||
|     async def receive_json(self, content, **kwargs): | ||||
|         """ | ||||
|         Called when the client sends us some data, parsed as JSON. | ||||
|         :param content: The sent data, decoded from JSON text. Must content a `type` field. | ||||
|         """ | ||||
|         # TODO Process chat protocol | ||||
							
								
								
									
										52
									
								
								chat/static/chat.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								chat/static/chat.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| (async () => { | ||||
|     // check notification permission | ||||
|     // This is useful to alert people that they should do something | ||||
|     await Notification.requestPermission() | ||||
| })() | ||||
|  | ||||
| /** | ||||
|  * Display a new notification with the given title and the given body. | ||||
|  * @param title The title of the notification | ||||
|  * @param body The body of the notification | ||||
|  * @param timeout The time (in milliseconds) after that the notification automatically closes. 0 to make indefinite. Default to 5000 ms. | ||||
|  * @return Notification | ||||
|  */ | ||||
| function showNotification(title, body, timeout = 5000) { | ||||
|     let notif = new Notification(title, {'body': body, 'icon': "/static/tfjm.svg"}) | ||||
|     if (timeout) | ||||
|         setTimeout(() => notif.close(), timeout) | ||||
|     return notif | ||||
| } | ||||
|  | ||||
| document.addEventListener('DOMContentLoaded', () => { | ||||
|     /** | ||||
|      * Process the received data from the server. | ||||
|      * @param data The received message | ||||
|      */ | ||||
|     function processMessage(data) { | ||||
|         // TODO Implement chat protocol | ||||
|     } | ||||
|  | ||||
|     function setupSocket(nextDelay = 1000) { | ||||
|         // Open a global websocket | ||||
|         socket = new WebSocket( | ||||
|             (document.location.protocol === 'https:' ? 'wss' : 'ws') + '://' + window.location.host + '/ws/chat/' | ||||
|         ) | ||||
|  | ||||
|         // Listen on websockets and process messages from the server | ||||
|         socket.addEventListener('message', e => { | ||||
|             // Parse received data as JSON | ||||
|             const data = JSON.parse(e.data) | ||||
|  | ||||
|             processMessage(data) | ||||
|         }) | ||||
|  | ||||
|         // Manage errors | ||||
|         socket.addEventListener('close', e => { | ||||
|             console.error('Chat socket closed unexpectedly, restarting…') | ||||
|             setTimeout(() => setupSocket(2 * nextDelay), nextDelay) | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     setupSocket() | ||||
| }) | ||||
							
								
								
									
										12
									
								
								chat/templates/chat/chat.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								chat/templates/chat/chat.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| {% extends "base.html" %} | ||||
|  | ||||
| {% load static %} | ||||
| {% load i18n %} | ||||
|  | ||||
| {% block content %} | ||||
| {% endblock %} | ||||
|  | ||||
| {% block extrajavascript %} | ||||
|     {# This script contains all data for the chat management #} | ||||
|     <script src="{% static 'chat.js' %}"></script> | ||||
| {% endblock %} | ||||
							
								
								
									
										11
									
								
								chat/urls.py
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								chat/urls.py
									
									
									
									
									
								
							| @@ -1,2 +1,13 @@ | ||||
| # Copyright (C) 2024 by Animath | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from django.urls import path | ||||
|  | ||||
| from .views import ChatView | ||||
|  | ||||
|  | ||||
| app_name = 'chat' | ||||
|  | ||||
| urlpatterns = [ | ||||
|     path('', ChatView.as_view(), name='chat'), | ||||
| ] | ||||
|   | ||||
| @@ -1,2 +1,13 @@ | ||||
| # Copyright (C) 2024 by Animath | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from django.contrib.auth.mixins import LoginRequiredMixin | ||||
| from django.views.generic import TemplateView | ||||
|  | ||||
|  | ||||
| class ChatView(LoginRequiredMixin, TemplateView): | ||||
|     """ | ||||
|     This view is the main interface of the chat system, which is working | ||||
|     with Javascript and websockets. | ||||
|     """ | ||||
|     template_name = "chat/chat.html" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user