diff --git a/assets/js/chat/Base.js b/assets/js/chat/Base.js index ddc4630..9ec3cd8 100644 --- a/assets/js/chat/Base.js +++ b/assets/js/chat/Base.js @@ -188,20 +188,22 @@ function delete_friend(friend){ }, success: function(response){ if(response.status == true){ - Swal.fire( - 'Deleted!', - 'User has been deleted.', - 'success' - ).then(function(){ - location.reload(); + Swal.fire({ + title: 'Deleted!', + text: 'User has been deleted.', + confirmButtonColor: '#3085d6', + icon: 'success', + }).then(function(){ + parent.location.href = '/'; }); } else{ - Swal.fire( - 'Error!', - 'An error occured. Please try again later.', - 'error' - ); + Swal.fire({ + title: 'Error!', + text: 'An error occured. Please try again later.', + confirmButtonColor: '#3085d6', + icon: 'error', + }); } }, error: function(response){ diff --git a/assets/js/chat/chats.js b/assets/js/chat/chats.js index b8b40db..732d0d8 100644 --- a/assets/js/chat/chats.js +++ b/assets/js/chat/chats.js @@ -1,8 +1,8 @@ -const socketProtocol3 = (window.location.protocol === 'https:') ? 'wss' : 'ws'; +const socketProtocol_3 = (window.location.protocol === 'https:') ? 'wss' : 'ws'; -const socket3 = new WebSocket(socketProtocol3 + "://" + window.location.host + '/ws/chat'); -socket3.onopen = function (e) { - socket3.send(JSON.stringify({ +const socket_3 = new WebSocket(socketProtocol_3 + "://" + window.location.host + '/ws/chat/status/'); +socket_3.onopen = function (e) { + socket_3.send(JSON.stringify({ 'check': 'livestatus', 'for': getUserName(), })); @@ -10,14 +10,14 @@ socket3.onopen = function (e) { //keep checking if user is online setInterval(function () { - socket3.send(JSON.stringify({ + socket_3.send(JSON.stringify({ 'check': 'livestatus', 'for': getUserName(), })); }, 3000); var count = 0; -socket3.addEventListener('message', function (e) { +socket_3.addEventListener('message', function (e) { const data = JSON.parse(e.data); if (data.status == 'offline') { if (count >= 3) { @@ -28,7 +28,7 @@ socket3.addEventListener('message', function (e) { text: "User disconnected, Navigating you to home page!", }).then(function(){ parent.location.href = "/"; - + }); } else { diff --git a/chat/consumers.py b/chat/consumers.py index 1687074..7823e07 100644 --- a/chat/consumers.py +++ b/chat/consumers.py @@ -1,145 +1,104 @@ import json -from json.decoder import JSONDecodeError -from channels.generic.websocket import AsyncJsonWebsocketConsumer from channels.generic.websocket import WebsocketConsumer from asgiref.sync import async_to_sync -from chat.models import Keys, UserProfile -from channels.db import database_sync_to_async -import time +from chat.models import UserProfile class ChatConsumer(WebsocketConsumer): - - + """ + Description: This consumer is used to send and receive messages between two users. + A user will send a message ('message') along with the username ('to') of friend to send the message to the friend, also the user will send a message ('destroy') to destroy the message. + 'destroy' contains seconds after which the message will be destroyed. + If the friend is online, the message will be sent to the friend and the user will receive a message with status 'received'. + """ http_user_and_session = True def connect(self): user = self.scope["user"] - UpdateStatus = UserProfile.objects.get(username=user) UpdateStatus.online = 1 - UpdateStatus.save() - self.room_name = "box_"+str(user) - async_to_sync(self.channel_layer.group_add)( self.room_name, self.channel_name ) self.accept() + def receive(self, text_data=None, bytes_data=None): + text_data_json = json.loads(text_data) + message = text_data_json['message'] + to = text_data_json['to'] + destroy = text_data_json['destroy'] + if message == "ping": + self.send(text_data=json.dumps({ + 'message': "pong", + 'status': "received", + 'destroy': destroy + })) + return + async_to_sync(self.channel_layer.group_send)( + "box_"+str(to), + { + 'type': 'chat_message', + 'message': message, + 'destroy': destroy + } + ) - def receive(self, text_data=None, bytes_data=None): - text_data_json = json.dumps(text_data) - text_data_json = json.loads(text_data) + def chat_message(self, event): + self.send(text_data=json.dumps({ + 'message': event['message'], + 'status': "received", + 'destroy': event['destroy'] + })) - try: - #Check User's online status - if text_data_json['check']=="livestatus": - ForUser = text_data_json['for'] - user = self.scope["user"] - #requested user's userprofile - if UserProfile.objects.get(username=ForUser).online==1 and UserProfile.objects.get(username=ForUser).online_for==UserProfile.objects.get(username=user): - async_to_sync(self.channel_layer.group_send)( - "box_"+str(ForUser), - { - 'type': 'UserLiveStatus', - 'status': 'online', - 'user': ForUser - } - ) - else: - self.send(text_data=json.dumps({ - 'status': "offline", - 'user': ForUser - })) - - except Exception as e: - pass - - - try: - if text_data_json['status'] == "online" and text_data_json['for']!="NULL": - ForUser = text_data_json['for'] - user = self.scope["user"] - UserUpdate = UserProfile.objects.get(username=user) - UserUpdate.online_for = UserProfile.objects.get(username=ForUser) - UserUpdate.save() - #end here - except Exception as e: - pass - - try: - if text_data_json['status'] == "typing" and text_data_json['for']!="NULL": - ForUser = text_data_json['for'] - user = self.scope["user"] - - async_to_sync(self.channel_layer.group_send)( - "box_"+str(ForUser), - { - 'type': 'In_chat_message', - 'status': 'typing', - 'user': ForUser - } - ) - except Exception as e: - pass - try: - message = text_data_json['message'] - to = text_data_json['to'] - destroy = text_data_json['destroy'] - + def disconnect(self, code): + user = self.scope["user"] + UpdateStatus = UserProfile.objects.get(username=user) + UpdateStatus.online = 0 + UpdateStatus.online_for = None + UpdateStatus.save() + self.close() - async_to_sync(self.channel_layer.group_send)( - "box_"+str(to), - { - 'type': 'chat_message', - 'message': message, - 'destroy': destroy - } - ) - except Exception as e: - pass +class ChatConsumerStatus(WebsocketConsumer): + """ + Description: This consumer is used to check the online status of the user. + A user will send a message ('check') along with the username ('for') of friend to check the online status of the friend. + If the friend is online, the user will receive a message with status 'online' and vice versa. + """ + http_user_and_session = True + def connect(self): + user = self.scope["user"] + self.room_name = "box2_"+str(user) + async_to_sync(self.channel_layer.group_add)( + self.room_name, + self.channel_name + ) + self.accept() + + def receive(self, text_data=None, bytes_data=None): + text_data_json = json.loads(text_data) - try: - if text_data_json['status'] == "online" and text_data_json['for']!="NULL": - ForUser = text_data_json['for'] - user = self.scope["user"] - + if text_data_json['check']=="livestatus": + ForUser = text_data_json['for'] + user = self.scope["user"] + if UserProfile.objects.get(username=ForUser).online==1 and UserProfile.objects.get(username=ForUser).online_for==UserProfile.objects.get(username=user): async_to_sync(self.channel_layer.group_send)( - "box_"+str(ForUser), + "box2_"+str(ForUser), { - 'type': 'In_chat_message', + 'type': 'UserLiveStatus', 'status': 'online', 'user': ForUser } ) - except Exception as e: - pass - - def chat_message(self, event): - print(event['destroy']) - try: - self.send(text_data=json.dumps({ - 'message': event['message'], - 'status': "received", - 'destroy': event['destroy'] - })) - except: - pass - - def In_chat_message(self, event): - - type = event['type'] - status = event['status'] - user = event['user'] - self.send(text_data=json.dumps({ - 'status': status, - 'user': user - })) + else: + self.send(text_data=json.dumps({ + 'status': 'offline', + 'user': ForUser + })) def UserLiveStatus(self, event): status = event['status'] @@ -150,17 +109,52 @@ def UserLiveStatus(self, event): })) def disconnect(self, code): + self.close() + +class ChatConsumerCurrentStatus(WebsocketConsumer): + """ + Description: This consumer is used to check the current status of the user (typing/not typing). + A user will send a message ('status') along with the username ('for') of friend to check the current status of the friend. + If the friend is typing, the user will receive a message with status 'typing' otherwise 'online'. + """ + http_user_and_session = True + def connect(self): user = self.scope["user"] - try: + self.room_name = "box3_"+str(user) + async_to_sync(self.channel_layer.group_add)( + self.room_name, + self.channel_name + ) + self.accept() - UpdateStatus = UserProfile.objects.get(username=user) - UpdateStatus.online = 0 - UpdateStatus.online_for = None + def receive(self, text_data=None, bytes_data=None): + text_data_json = json.loads(text_data) + + if text_data_json['for'] != "NULL": + status = text_data_json['status'] + ForUser = text_data_json['for'] + user = self.scope["user"] + UserUpdate = UserProfile.objects.get(username=user) + UserUpdate.online_for = UserProfile.objects.get(username=ForUser) + UserUpdate.save() - UpdateStatus.save() + async_to_sync(self.channel_layer.group_send)( + "box3_"+str(ForUser), + { + 'type': 'In_chat_message', + 'status': status, + 'user': ForUser + } + ) - except: - pass + def In_chat_message(self, event): + status = event['status'] + user = event['user'] + self.send(text_data=json.dumps({ + 'status': status, + 'user': user + })) - pass \ No newline at end of file + def disconnect(self, code): + self.close() \ No newline at end of file diff --git a/chat/routing.py b/chat/routing.py index ba9d213..b9f65f8 100644 --- a/chat/routing.py +++ b/chat/routing.py @@ -1,6 +1,8 @@ from django.urls import re_path as url -from chat.consumers import ChatConsumer +from chat.consumers import ChatConsumer, ChatConsumerStatus, ChatConsumerCurrentStatus websocket_urlpatterns = [ - url('ws/chat', ChatConsumer.as_asgi()) + url('ws/chat/currentstatus/', ChatConsumerCurrentStatus.as_asgi()), + url('ws/chat/status/', ChatConsumerStatus.as_asgi()), + url('ws/chat/', ChatConsumer.as_asgi()), ] \ No newline at end of file diff --git a/chat/templates/chat/Base.html b/chat/templates/chat/Base.html index 8263885..cbbd7a8 100644 --- a/chat/templates/chat/Base.html +++ b/chat/templates/chat/Base.html @@ -247,26 +247,35 @@

Privacy is a Fundamental Right!

//WebSockets Script start flowOpen = false; - const socketProtocol = + const socketProtocol_1 = window.location.protocol === "https:" ? "wss" : "ws"; - const socket = new WebSocket( - socketProtocol + "://" + window.location.host + "/ws/chat" + const socket_1 = new WebSocket( + socketProtocol_1 + "://" + window.location.host + "/ws/chat/" ); // Connection opened - socket.addEventListener("open", (event) => { - send_status = { - status: "online", - for: getUserName(), + socket_1.addEventListener("open", (event) => { + send_status_1 = { + message: "ping", + to: getUserName(), + destroy: 0, }; - send_status = JSON.stringify(send_status); - socket.send(send_status); + send_status_1 = JSON.stringify(send_status_1); + //send ping 3 times for 3 seconds + var PingCounter = 0; + var PingInterval = setInterval(function () { + socket_1.send(send_status_1); + PingCounter++; + if (PingCounter == 3) { + clearInterval(PingInterval); + } + }, 1000); }); // Listen for messages var loaderstatus = 0; - socket.addEventListener("message", (event) => { + socket_1.addEventListener("message", (event) => { if(window.location.href.includes("/chat")){ if(flowOpen == false){ @@ -284,30 +293,13 @@

Privacy is a Fundamental Right!

} } - - //get only message from event.data - const obj = JSON.parse(event.data); - //check if already there is a loader, then don't append - if (obj.status == "typing") { - if (loaderstatus == 0) { - if (document.getElementById("fromloader") == null) { - var loader = - '
'; - $("#board").append(loader); - scrolltoend(); - loaderstatus = 1; - } - } - } - if (obj.status == "online") { - //somehow, calling one time is removing the loader. - - document.getElementById("fromloader").remove(); + const obj_1 = JSON.parse(event.data); - loaderstatus = 0; + var message_1 = obj_1.message; + if (message_1 == "pong") { + return; } - var message = obj.message; //base64 to array buffer function base64ToArrayBuffer(base64) { @@ -320,7 +312,7 @@

Privacy is a Fundamental Right!

return bytes.buffer; } //convert to array buffer - const arrayBuffer = base64ToArrayBuffer(message); + const arrayBuffer = base64ToArrayBuffer(message_1); //get the private key from local storage const privateKey = JSON.parse(localStorage.getItem("privateKey")); @@ -331,12 +323,11 @@

Privacy is a Fundamental Right!

const decrypted = decoder.decode(decrypted_message); message = decrypted; - destroy = obj.destroy; + destroy = obj_1.destroy; const outputDiv = document.getElementById("output"); var lenth = message.length; var width = 0; - console.log(lenth) if (lenth < 10) { width = 10; } else if (lenth >= 10 && lenth <= 20) { @@ -383,12 +374,12 @@

Privacy is a Fundamental Right!

}); }); // Connection closed - socket.addEventListener("close", (event) => { + socket_1.addEventListener("close", (event) => { }); // Connection error - socket.addEventListener("error", (event) => { + socket_1.addEventListener("error", (event) => { }); // Function to send a message @@ -406,7 +397,6 @@

Privacy is a Fundamental Right!

//get the public key from cookie var public_key = getCookie("public_key"); - console.log(public_key); //base64 utf-8 decode public_key = decodeURIComponent(escape(window.atob(public_key))); @@ -430,7 +420,7 @@

Privacy is a Fundamental Right!

encryptData(message, public_key).then((encrypted_message) => { //convert to base64 const base64 = arrayBufferToBase64(encrypted_message); - socket.send( + socket_1.send( JSON.stringify({ message: base64, to: getUserName(), @@ -493,78 +483,173 @@

Privacy is a Fundamental Right!

'' ); }); - - var TypingStatusSend = false; - $("#msg_field").on("keypress", function () { - var send_status2 = { - status: "typing", - for: getUserName(), - }; - if(TypingStatusSend == false){ - send_status2 = JSON.stringify(send_status2); - TypingStatusSend = true; - socket.send(send_status2); - OnlineStatusSend = false; - } - }); - //check if message field looses focus, then send status not typing - var OnlineStatusSend = false; - $("#msg_field").on("focusout", function () { - var send_status2 = { - status: "online", - for: getUserName(), - }; - if(OnlineStatusSend == false){ - send_status2 = JSON.stringify(send_status2); - socket.send(send_status2); - OnlineStatusSend = true; - loaderstatus = 0; - TypingStatusSend = false; - } - }); - - + // Websocket script end + - //check if message field is empty, then send status not typing - var OnlineStatusSend = false; - $("#msg_field").on("input", function () { - if ($("#msg_field").val() == "") { - var send_status2 = { - status: "online", - for: getUserName(), - }; - if(OnlineStatusSend == false){ - send_status2 = JSON.stringify(send_status2); - socket.send(send_status2); - loaderstatus = 0; - TypingStatusSend = false; - OnlineStatusSend = true; - } - } - }); - //on press enter and press send button send the not typing status - var OnlineStatusSend = false; - $("#msg_field").on("keypress", function (e) { - if (e.which == 13) { - var send_status2 = { - status: "online", - for: getUserName(), - }; - if(OnlineStatusSend == false){ - send_status2 = JSON.stringify(send_status2); - socket.send(send_status2); - loaderstatus = 0; - TypingStatusSend = false; - OnlineStatusSend = true; - } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file