From 7ab3186545faff1c9228b6066723351ff0f05dbf Mon Sep 17 00:00:00 2001 From: Nic <3xpect1916@gmail.com> Date: Sat, 29 Jun 2024 21:55:47 +0800 Subject: [PATCH 1/5] done rendering from database and editing of message --- models/ChatMessage.js | 8 +- routes/chat/WebSocketServer.js | 204 ++++++++++++++++++--------------- 2 files changed, 120 insertions(+), 92 deletions(-) diff --git a/models/ChatMessage.js b/models/ChatMessage.js index 5e26aca..b947d31 100644 --- a/models/ChatMessage.js +++ b/models/ChatMessage.js @@ -1,3 +1,5 @@ +const { Timestamp } = require('firebase-admin/firestore'); + /** * * @param {import('sequelize').Sequelize} sequelize @@ -15,13 +17,17 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.STRING, allowNull: false }, - from: { + sender: { type: DataTypes.STRING, allowNull: false }, datetime: { type: DataTypes.STRING, allowNull: false + }, + timestamp: { + type: DataTypes.STRING, + allowNull: false } }, { tableName: 'chatMessages' }) diff --git a/routes/chat/WebSocketServer.js b/routes/chat/WebSocketServer.js index 439d824..ae0a04f 100644 --- a/routes/chat/WebSocketServer.js +++ b/routes/chat/WebSocketServer.js @@ -3,109 +3,131 @@ const http = require("http"); const WebSocket = require("ws"); const { ChatHistory, ChatMessage } = require("../../models"); const Universal = require("../../services/Universal"); -const Cache = require("../../services/Cache"); - +const mysql = require('mysql'); function startWebSocketServer(app) { - if (!process.env.WS_PORT) { console.log("WARNING: WS_PORT environment variable not set. Defaulting to 8080.") } - const PORT = process.env.WS_PORT || 8080; - - const server = http.createServer(app); - - const wss = new WebSocket.Server({ server }); - - const clients = []; - - wss.on("connection", (ws) => { - console.log("WS connection arrived"); - clients.push(ws); - - if (!Cache.cache["chat"]) { - Cache.cache["chat"] = {}; + const PORT = 8080; + const server = http.createServer(app); + const wss = new WebSocket.Server({ server }); + const clients = []; + + wss.on("connection", async (ws) => { + console.log("WS connection arrived"); + clients.push(ws); + + // Assuming you have some way to identify users, like user IDs + const user1ID = "Jamie"; // Replace with actual user IDs + const user2ID = "James"; // Replace with actual user IDs + + try { + // Check if a ChatHistory exists between user1 and user2 + let chatHistory = await ChatHistory.findOne({ + where: { + user1ID, + user2ID, + }, + }); + + if (!chatHistory) { + // Create a new ChatHistory if it doesn't exist + chatHistory = await ChatHistory.create({ + chatID: Universal.generateUniqueID(), + user1ID, + user2ID, + datetime: new Date().toISOString(), // Replace with current datetime logic + }); + } + + // Fetch and send previous chat messages + const previousMessages = await ChatMessage.findAll({ + where: { + chatID: chatHistory.chatID, + }, + order: [['datetime', 'ASC']], // Order messages by datetime ascending + }); + + ws.send(JSON.stringify({ + type: 'chat_history', + messages: previousMessages, + })); + + // Now you can handle further WebSocket message events + ws.on("message", async (message) => { + const parsedMessage = JSON.parse(message); + console.log("Received message:", parsedMessage); + if (parsedMessage.action === "edit") { + handleEditMessage(parsedMessage); + } else if (parsedMessage.action === "delete") { + handleDeleteMessage(parsedMessage); } - - const cachedMessages = Cache.cache["chat"]; - for (const messageId in cachedMessages) { - const message = { - id: messageId, - ...cachedMessages[messageId], - }; - ws.send(JSON.stringify(message)); + else{ + try { + // Create ChatMessage in the database + const createdMessage = await ChatMessage.create({ + messageID: parsedMessage.messageid, + message: parsedMessage.message, + sender: parsedMessage.sender, + datetime: parsedMessage.datetime, + timestamp: parsedMessage.timestamp, + chatID: chatHistory.chatID, // Assign the chatID from ChatHistory + }); + + // Broadcast the message to all clients + broadcastMessage(JSON.stringify(createdMessage), ws); + } catch (error) { + console.error("Error creating message:", error); } + } + }); - ws.on("message", (message) => { - const parsedMessage = JSON.parse(message); - - Cache.cache["chat"][parsedMessage.id] = { - sender: parsedMessage.sender, - message: parsedMessage.message, - timestamp: parsedMessage.timestamp, - }; - Cache.save(); - - if (parsedMessage.action === "edit") { - handleEditMessage(parsedMessage); - } else if (parsedMessage.action === "delete") { - handleDeleteMessage(parsedMessage); - } else { - broadcastMessage(message, ws); - } - }); + } catch (error) { + console.error("Error checking ChatHistory:", error); + } - ws.on("close", () => { - const index = clients.indexOf(ws); - if (index > -1) { - clients.splice(index, 1); - } - }); + ws.on("close", () => { + const index = clients.indexOf(ws); + if (index > -1) { + clients.splice(index, 1); + } }); + }); - wss.on("error", (error) => { - console.error("WebSocket server error:", error); - }); + wss.on("error", (error) => { + console.error("WebSocket server error:", error); + }); - function broadcastMessage(message, sender) { - clients.forEach((client) => { - if (client !== sender && client.readyState === WebSocket.OPEN) { - client.send(message); - } - }); - } - - function handleDeleteMessage(deleteMessage) { - const messageId = deleteMessage.id; - delete Cache.cache["chat"][messageId]; - Cache.save(); - - const jsonMessage = JSON.stringify({ - id: messageId, - action: "delete", - action: "reload", - }); - broadcastMessage(jsonMessage); + function handleEditMessage(editedMessage) { + const messageId = editedMessage.id; + const findMessage = ChatMessage.findByPk(messageId); + if (!findMessage) { + console.log("Message not found"); } + const editMessage = ChatMessage.update({ + message: editedMessage.message, + timestamp: `${new Date().getHours()}:${new Date() + .getMinutes() + .toString() + .padStart(2, "0")}` + }, { + where: { + messageID: messageId, + }, + }); + } + - function handleEditMessage(editedMessage) { - const messageId = editedMessage.id; - if (Cache.cache["chat"][messageId]) { - Cache.cache["chat"][messageId].message = editedMessage.message; - Cache.cache["chat"][messageId].edited = true; - Cache.save(); - - const jsonMessage = JSON.stringify({ - ...Cache.cache["chat"][messageId], - id: messageId, - action: "edit", - action: "reload", - }); - broadcastMessage(jsonMessage); - } else { - console.error(`Message with ID ${messageId} not found.`); - } - } - server.listen(PORT, () => { - console.log(`WebSocket Server running on port ${PORT}`); + function broadcastMessage(message, sender) { + clients.forEach((client) => { + if (client !== sender && client.readyState === WebSocket.OPEN) { + client.send(message); + } }); + } + + + server.listen(PORT, () => { + console.log(`WebSocket Server running on port ${PORT}`); + }); } module.exports = startWebSocketServer; From f07a027d688b30fb495d595fa25370597b71ff78 Mon Sep 17 00:00:00 2001 From: Nic <3xpect1916@gmail.com> Date: Sat, 29 Jun 2024 22:27:17 +0800 Subject: [PATCH 2/5] done delete message --- routes/chat/WebSocketServer.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/routes/chat/WebSocketServer.js b/routes/chat/WebSocketServer.js index ae0a04f..4fdd673 100644 --- a/routes/chat/WebSocketServer.js +++ b/routes/chat/WebSocketServer.js @@ -112,6 +112,27 @@ function startWebSocketServer(app) { messageID: messageId, }, }); + const jsonMessage = { + action: "reload", + } + broadcastMessage(JSON.stringify(jsonMessage)); + } + + function handleDeleteMessage(deletedMessage) { + const messageId = deletedMessage.id; + const findMessage = ChatMessage.findByPk(messageId); + if (!findMessage) { + console.log("Message not found"); + } + const deleteMessage = ChatMessage.destroy({ + where: { + messageID: messageId, + }, + }); + const jsonMessage = { + action: "reload", + } + broadcastMessage(JSON.stringify(jsonMessage)); } From 56ab84eee19a74c31a3db574778e4b6e869c8084 Mon Sep 17 00:00:00 2001 From: Nicholas Chew <3xpect1916@gmail.com> Date: Fri, 5 Jul 2024 12:01:26 +0800 Subject: [PATCH 3/5] removed hard coded timestamp --- models/ChatMessage.js | 6 ----- routes/chat/WebSocketServer.js | 40 ++++++++++++++++------------------ 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/models/ChatMessage.js b/models/ChatMessage.js index b947d31..38eb253 100644 --- a/models/ChatMessage.js +++ b/models/ChatMessage.js @@ -1,5 +1,3 @@ -const { Timestamp } = require('firebase-admin/firestore'); - /** * * @param {import('sequelize').Sequelize} sequelize @@ -25,10 +23,6 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.STRING, allowNull: false }, - timestamp: { - type: DataTypes.STRING, - allowNull: false - } }, { tableName: 'chatMessages' }) // Associations diff --git a/routes/chat/WebSocketServer.js b/routes/chat/WebSocketServer.js index 4fdd673..99f2b81 100644 --- a/routes/chat/WebSocketServer.js +++ b/routes/chat/WebSocketServer.js @@ -3,7 +3,6 @@ const http = require("http"); const WebSocket = require("ws"); const { ChatHistory, ChatMessage } = require("../../models"); const Universal = require("../../services/Universal"); -const mysql = require('mysql'); function startWebSocketServer(app) { const PORT = 8080; const server = http.createServer(app); @@ -51,25 +50,24 @@ function startWebSocketServer(app) { })); // Now you can handle further WebSocket message events - ws.on("message", async (message) => { - const parsedMessage = JSON.parse(message); - console.log("Received message:", parsedMessage); - if (parsedMessage.action === "edit") { - handleEditMessage(parsedMessage); - } else if (parsedMessage.action === "delete") { - handleDeleteMessage(parsedMessage); - } - else{ - try { - // Create ChatMessage in the database - const createdMessage = await ChatMessage.create({ - messageID: parsedMessage.messageid, - message: parsedMessage.message, - sender: parsedMessage.sender, - datetime: parsedMessage.datetime, - timestamp: parsedMessage.timestamp, - chatID: chatHistory.chatID, // Assign the chatID from ChatHistory - }); +// Now you can handle further WebSocket message events +ws.on("message", async (message) => { + const parsedMessage = JSON.parse(message); + console.log("Received message:", parsedMessage); + if (parsedMessage.action === "edit") { + handleEditMessage(parsedMessage, chatHistory.chatID, ws); + } else if (parsedMessage.action === "delete") { + handleDeleteMessage(parsedMessage); + } else { + try { + // Create ChatMessage in the database + const createdMessage = await ChatMessage.create({ + messageID: Universal.generateUniqueID(), + message: parsedMessage.message, + sender: parsedMessage.sender, + datetime: parsedMessage.datetime, + chatID: chatHistory.chatID, // Assign the chatID from ChatHistory + }); // Broadcast the message to all clients broadcastMessage(JSON.stringify(createdMessage), ws); @@ -139,7 +137,7 @@ function startWebSocketServer(app) { function broadcastMessage(message, sender) { clients.forEach((client) => { - if (client !== sender && client.readyState === WebSocket.OPEN) { + if (client.readyState === WebSocket.OPEN) { client.send(message); } }); From 790c6d6dc0df13389d576f073d0f144686a8f947 Mon Sep 17 00:00:00 2001 From: Nicholas Chew <3xpect1916@gmail.com> Date: Fri, 5 Jul 2024 12:38:59 +0800 Subject: [PATCH 4/5] changed error to show on frontend also --- routes/chat/WebSocketServer.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/routes/chat/WebSocketServer.js b/routes/chat/WebSocketServer.js index 99f2b81..4d085bf 100644 --- a/routes/chat/WebSocketServer.js +++ b/routes/chat/WebSocketServer.js @@ -93,11 +93,19 @@ ws.on("message", async (message) => { console.error("WebSocket server error:", error); }); - function handleEditMessage(editedMessage) { + async function handleEditMessage(editedMessage) { const messageId = editedMessage.id; - const findMessage = ChatMessage.findByPk(messageId); + // Assuming findByPk is asynchronous + const findMessage = await ChatMessage.findByPk(messageId); + if (!findMessage) { console.log("Message not found"); + const jsonMessage = { + action: "error", + message: "Error occured on the server", + }; + broadcastMessage(JSON.stringify(jsonMessage)); + return; } const editMessage = ChatMessage.update({ message: editedMessage.message, @@ -132,9 +140,6 @@ ws.on("message", async (message) => { } broadcastMessage(JSON.stringify(jsonMessage)); } - - - function broadcastMessage(message, sender) { clients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { From 0cf6431ceabfc627b5a57c59021ccd963235d235 Mon Sep 17 00:00:00 2001 From: Nicholas Chew <3xpect1916@gmail.com> Date: Fri, 5 Jul 2024 14:18:34 +0800 Subject: [PATCH 5/5] removed timestamp and have item potency --- routes/chat/WebSocketServer.js | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/routes/chat/WebSocketServer.js b/routes/chat/WebSocketServer.js index 4d085bf..20041ae 100644 --- a/routes/chat/WebSocketServer.js +++ b/routes/chat/WebSocketServer.js @@ -95,6 +95,14 @@ ws.on("message", async (message) => { async function handleEditMessage(editedMessage) { const messageId = editedMessage.id; + if (!messageId) { + const jsonMessage = { + action: "error", + message: "ID not provided", + }; + broadcastMessage(JSON.stringify(jsonMessage)); + return; + } // Assuming findByPk is asynchronous const findMessage = await ChatMessage.findByPk(messageId); @@ -109,10 +117,7 @@ ws.on("message", async (message) => { } const editMessage = ChatMessage.update({ message: editedMessage.message, - timestamp: `${new Date().getHours()}:${new Date() - .getMinutes() - .toString() - .padStart(2, "0")}` + datetime: editedMessage.datetime, }, { where: { messageID: messageId, @@ -126,9 +131,20 @@ ws.on("message", async (message) => { function handleDeleteMessage(deletedMessage) { const messageId = deletedMessage.id; + if (!messageId) { + const jsonMessage = { + action: "reload", + } + broadcastMessage(JSON.stringify(jsonMessage)); + return; + } const findMessage = ChatMessage.findByPk(messageId); if (!findMessage) { - console.log("Message not found"); + const jsonMessage = { + action: "reload", + } + broadcastMessage(JSON.stringify(jsonMessage)); + return; } const deleteMessage = ChatMessage.destroy({ where: {