Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions models/ChatMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ module.exports = (sequelize, DataTypes) => {
type: DataTypes.STRING,
allowNull: false
},
from: {
sender: {
type: DataTypes.STRING,
allowNull: false
},
datetime: {
type: DataTypes.STRING,
allowNull: false
}
},
}, { tableName: 'chatMessages' })

// Associations
Expand Down
248 changes: 155 additions & 93 deletions routes/chat/WebSocketServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,109 +3,171 @@ const http = require("http");
const WebSocket = require("ws");
const { ChatHistory, ChatMessage } = require("../../models");
const Universal = require("../../services/Universal");
const Cache = require("../../services/Cache");

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 cachedMessages = Cache.cache["chat"];
for (const messageId in cachedMessages) {
const message = {
id: messageId,
...cachedMessages[messageId],
};
ws.send(JSON.stringify(message));
}

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);
}
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: {
Comment thread
nicholascheww marked this conversation as resolved.
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
// 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);
} catch (error) {
console.error("Error creating message:", error);
}
}
});

ws.on("close", () => {
const index = clients.indexOf(ws);
if (index > -1) {
clients.splice(index, 1);
}
});
});
} catch (error) {
console.error("Error checking ChatHistory:", error);
}

wss.on("error", (error) => {
console.error("WebSocket server error:", error);
ws.on("close", () => {
const index = clients.indexOf(ws);
if (index > -1) {
clients.splice(index, 1);
}
});

function broadcastMessage(message, sender) {
clients.forEach((client) => {
if (client !== sender && client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});

wss.on("error", (error) => {
console.error("WebSocket server error:", error);
});

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);

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);
if (!findMessage) {
console.log("Message not found");
Comment thread
Prakhar896 marked this conversation as resolved.
const jsonMessage = {
action: "error",
message: "Error occured on the server",
};
broadcastMessage(JSON.stringify(jsonMessage));
return;
}

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.`);
}
const editMessage = ChatMessage.update({
message: editedMessage.message,
datetime: editedMessage.datetime,
}, {
where: {
messageID: messageId,
},
});
const jsonMessage = {
action: "reload",
}

server.listen(PORT, () => {
console.log(`WebSocket Server running on port ${PORT}`);
broadcastMessage(JSON.stringify(jsonMessage));
Comment thread
nicholascheww marked this conversation as resolved.
}

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) {
const jsonMessage = {
action: "reload",
}
broadcastMessage(JSON.stringify(jsonMessage));
return;
}
const deleteMessage = ChatMessage.destroy({
where: {
messageID: messageId,
},
});
const jsonMessage = {
action: "reload",
}
broadcastMessage(JSON.stringify(jsonMessage));
}
function broadcastMessage(message, sender) {
clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
}


server.listen(PORT, () => {
console.log(`WebSocket Server running on port ${PORT}`);
});
}

module.exports = startWebSocketServer;