I have the following issue: I'm building a chat using Node.js, Socket.IO, and MongoDB. Everything is working perfectly, except for the real-time aspect. For instance, when 'Sebas' sends a message to 'Gene', 'Sebas' can see that their message has been sent, but 'Gene' doesn't see it, and vice versa. Could you please help me? I'm struggling to solve this part.
This is my
chat.html, the display for my private rooms.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,
initial-scale=1.0">
<title>Chat Personal</title>
</head>
<body>
<h1>Chat Personal</h1>
<p>Conversación ID: <span id="conversationId"></span></p>
<div id="messages"></div>
<!--
<input type="text" id="messageInput"
placeholder="Escribe un mensaje">
<!--
<button id="sendButton">Enviar</button>
<!--
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();
const messageInput = document.getElementById('messageInput');
const sendButton = document.getElementById('sendButton');
const messagesDiv = document.getElementById('messages');
const conversationIdSpan = document.getElementById('conversationId');
const emisor = getUsernameFromSession();
const receptor = getReceptorFromURL();
const conversacionId = generateConversationId(emisor, receptor);
conversationIdSpan.textContent = conversacionId;
sendButton.addEventListener('click', () => {
const message = messageInput.value;
socket.emit('personal message',
{ emisor, receptor, conversacionId, mensaje: message });
messageInput.value = '';
});
socket.on('personal message sent', (data) => {
if (data.emisor === emisor) {
appendMessage(`Tú: ${data.mensaje}`);
}
});
socket.on('personal message received', (data) => {
if (data.emisor !== emisor) {
if (data.conversacionId === conversacionId) {
appendMessage(`${data.emisor}: ${data.mensaje}`);
}
}
});
socket.emit('get message history', conversacionId);
socket.on('message history', (messageHistory) => {
messageHistory.forEach((message) => {
const messageText = `${message.emisor}: ${message.mensaje}`;
appendMessage(messageText);
});
});
function getUsernameFromSession() {
const username = localStorage.getItem('username');
return username;
}
function getReceptorFromURL() {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get('user');
}
function generateConversationId(user1, user2) {
const sortedUsers = [user1, user2].sort();
const concatenatedUsers = sortedUsers.join('-');
const hash = md5(concatenatedUsers);
return hash;
}
function md5(str) {
let md5hash = '';
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
md5hash += char.toString(16);
}
return md5hash;
}
function appendMessage(message) {
const messageElement = document.createElement('p');
messageElement.textContent = message;
messagesDiv.appendChild(messageElement);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
}
</script>
</body>
</html>
And this is my socket.js.
const Message = require('./models/Message');
const UserModel = require('./models/user');
const ConversacionPersonal = require('./models/ConversacionPersonal');
const setupSocketIO = (io, users) => {
io.on('connection', async (socket) => {
console.log('Nuevo usuario conectado');
try {
const messages = await Message.find().exec();
socket.emit('chat history', messages);
} catch (err) {
console.error('Error al obtener el historial de mensajes:', err);
}
socket.on('set username', (username) => {
socket.username = username;
});
const filteredUsers = users.filter((user) =>
user.username !== socket.username);
socket.emit('users', filteredUsers);
socket.on('chat message', async (msg) => {
try {
const newMessage = new Message
({ usuarios: socket.username, message: msg });
const savedMessage = await newMessage.save();
console.log('Mensaje guardado en MongoDB:', savedMessage._id);
io.emit('chat message', { user: socket.username, message: msg });
} catch (err) {
console.error('Error al guardar el mensaje:', err);
}
});
socket.on('personal message', async (data) => {
try {
const newPersonalMessage = new ConversacionPersonal({
emisor: data.emisor,
receptor: data.receptor,
conversacionId: data.conversacionId,
mensaje: data.mensaje
});
const savedPersonalMessage = await newPersonalMessage.save();
socket.emit('personal message sent', savedPersonalMessage);
io.to(data.conversacionId).emit
('personal message received', savedPersonalMessage);
const existingConversation = await ConversacionPersonal.findOne
({ conversacionId: data.conversacionId });
if (!existingConversation) {
const newConversation = new ConversacionPersonal({
emisor: data.emisor,
receptor: data.receptor,
conversacionId: data.conversacionId,
mensaje: `Conversación iniciada con ID: ${data.conversacionId}`
});
await newConversation.save();
}
} catch (err) {
console.error('Error al guardar el mensaje personal:', err);
}
});
socket.on('get message history', async (conversacionId) => {
try {
const messageHistory = await ConversacionPersonal.find
({ conversacionId });
socket.emit('message history', messageHistory);
} catch (err) {
console.error('Error al cargar el historial de mensajes:', err);
}
});
socket.on('disconnect', () => {
console.log('Usuario desconectado');
});
});
};
module.exports = { setupSocketIO };
My native language is Spanish, but usually the English community has more responses.
I can translate the comments of the code if you need it.
What I have tried:
I've tried a thousand ways to achieve real-time conversation. In short, I need that when a message is sent, the recipient can see it without reloading the page.