Files
web-chat/backend/socket.js
2024-08-29 23:31:05 +02:00

125 lines
4.8 KiB
JavaScript

const { Server } = require('socket.io');
const jwt = require('jsonwebtoken');
const jwtSecret = process.env.JWT_SECRET;
const { db } = require('./db.js');
function initializeSocket(server) {
const io = new Server(server, {
cookie: {
httpOnly: true,
sameSite: "strict",
maxAge: 30 * 24 * 60 * 60 * 1000
}
});
io.use((socket, next) => {
const token = socket.handshake.auth.token;
if(token) {
jwt.verify(token, jwtSecret, (err, user) => {
if(err) {
console.log(err);
return next(new Error('Authentication error'));
}
socket.user = user;
next();
});
} else {
next(new Error('Not logged in'));
}
});
io.on('connection', (socket) => {
if (!socket.user) {
console.log('User not authenticated');
socket.disconnect();
return;
}
const username = socket.user.username;
console.log(username + ' connected');
// Join a room with the user's username
socket.join(username);
// chat message event
socket.on('chat message', async (msgData) => {
const { content, recipient } = msgData;
let insertedId;
try {
// Insert the new message into the database
const result = await db.query('INSERT INTO messages (content, username, recipient) VALUES ($1, $2, $3) RETURNING id', [content, username, recipient]);
insertedId = result.rows[0].id;
} catch (err) {
console.error('Error inserting message:', err);
return;
}
// Fetch the newly inserted message from the database
try {
const query = 'SELECT id, content, username, recipient FROM messages WHERE id = $1';
const result = await db.query(query, [insertedId]);
if (result.rows.length > 0) {
const newMessage = result.rows[0];
const formattedMessage = `Username: ${newMessage.username}, recipient: ${newMessage.recipient}, message: ${newMessage.content}`;
//console.log(formattedMessage);
// Emit message to the sender's and recipient's rooms
io.to(username).to(recipient).emit('chat message', { username: newMessage.username, recipient: newMessage.recipient, content: newMessage.content });
}
} catch (err) {
console.error('Error fetching inserted message:', err);
}
// i think this is not needed? (it cause duplicate messages with loading messages history)
// if (!socket.recovered) {
// try {
// const query = 'SELECT id, content, username, recipient FROM messages WHERE id > $1 ORDER BY id ASC';
// const values = [socket.handshake.auth.serverOffset || 0];
// const result = await db.query(query, values);
// //const newMessage = result.rows[0];
// for (const row of result.rows) {
// if (row.username === username || row.recipient === username) {
// io.to(username).to(recipient).emit('chat message', { username: row.username, recipient: row.recipient, content: row.content });
//
// }
// }
// } catch (e) {
// console.error('Error retrieving messages:', e);
// }
// }
});
socket.on('get messages', async (recipient) => {
const username = socket.user.username;
try {
const query = `
SELECT id, content, username, recipient
FROM messages
WHERE (username = $1 AND recipient = $2) OR (username = $2 AND recipient = $1)
ORDER BY id ASC
`;
const result = await db.query(query, [username, recipient]);
if (result.rows.length > 0) {
//const { username: sender, recipient: receiver, content: content, id: id } = result.rows;
console.log('Sending historical messages');
socket.emit('messages history', result.rows);
} else {
io.emit('no messages', );
}
} catch (e) {
console.error('Error retrieving messages:', e);
}
});
// disconnect event
socket.on('disconnect', () => {
console.log(username + ' has disconnected');
});
});
return io;
}
module.exports = { initializeSocket };