199 lines
7.4 KiB
JavaScript
199 lines
7.4 KiB
JavaScript
const { Server } = require('socket.io');
|
|
const jwt = require('jsonwebtoken');
|
|
const jwtSecret = process.env.JWT_SECRET;
|
|
const { db } = require('./db.js');
|
|
const {json} = require("express");
|
|
|
|
function initializeSocket(server) {
|
|
const io = new Server(server, {
|
|
cookie: {
|
|
httpOnly: true,
|
|
sameSite: "strict",
|
|
maxAge: 30 * 24 * 60 * 60 * 1000
|
|
}
|
|
});
|
|
|
|
io.use((socket, next) => {
|
|
// user auth
|
|
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'));
|
|
}
|
|
});
|
|
|
|
// open main socket connection
|
|
io.on('connection', (socket) => {
|
|
if (!socket.user) {
|
|
socket.emit('socket error', 'User not authenticated')
|
|
socket.disconnect();
|
|
return;
|
|
}
|
|
const username = socket.user.username;
|
|
// Join a room with the user's username
|
|
socket.join(username);
|
|
|
|
io.to(username).emit('username', 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);
|
|
socket.emit('socket error', "Error inserting message, try refreshing the page")
|
|
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];
|
|
|
|
// 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);
|
|
socket.emit('socket error', 'Failed to send message')
|
|
}
|
|
});
|
|
|
|
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;
|
|
|
|
io.to(username).emit('messages history', result.rows);
|
|
} else {
|
|
io.to(username).emit('no messages');
|
|
}
|
|
} catch (e) {
|
|
console.error('Error retrieving messages:', e);
|
|
socket.emit('socket error', 'Error retrieving messages, refresh the page (server error)')
|
|
}
|
|
});
|
|
|
|
// Contacts socket
|
|
socket.on('contacts', async (contactUsername) => {
|
|
const username = socket.user.username;
|
|
const status = (contactUsername.status === "read") ? "read" : "unread";
|
|
|
|
// Update contact list in db
|
|
try {
|
|
const query = `
|
|
INSERT INTO contacts (username, contact, status)
|
|
SELECT $1, $2, $3
|
|
WHERE NOT EXISTS (
|
|
SELECT 1 FROM contacts WHERE username = $1 AND contact = $2
|
|
)
|
|
`;
|
|
await db.query(query, [username, contactUsername.contact, status]);
|
|
} catch (err) {
|
|
console.error('Failed to update contacts ', err)
|
|
socket.emit('socket error', 'Failed to update contacts (server error)')
|
|
}
|
|
// Get contact list from db
|
|
try {
|
|
const query = (`
|
|
SELECT contact, username, status
|
|
FROM contacts
|
|
WHERE username = $1
|
|
`);
|
|
const result = await db.query(query, [username]);
|
|
io.to(username).emit('contacts', result.rows);
|
|
|
|
} catch(err) {
|
|
console.error('Failed to get contacts from db');
|
|
io.to(username).emit('socket error', 'Failed to get contacts (server error)');
|
|
}
|
|
})
|
|
|
|
socket.on('get contacts', async () => {
|
|
const username = socket.user.username;
|
|
try {
|
|
const query = (`
|
|
SELECT contact, username, status
|
|
FROM contacts
|
|
WHERE username = $1
|
|
`);
|
|
const result = await db.query(query, [username]);
|
|
io.to(username).emit('contacts', result.rows);
|
|
|
|
} catch(err) {
|
|
console.error('Failed to get contacts from db');
|
|
io.to(username).emit('socket error', 'Failed to get contacts (server error)');
|
|
}
|
|
})
|
|
socket.on('delete contact', async (contactUsername) => {
|
|
const username = socket.user.username;
|
|
try {
|
|
const query = ('DELETE FROM contacts WHERE (username = $1 AND contact = $2)');
|
|
await db.query(query, [username, contactUsername]);
|
|
|
|
} catch(err) {
|
|
console.error('Failed to remove contact from db');
|
|
io.to(username).emit('socket error', 'Failed to remove contact (server error)');
|
|
}
|
|
})
|
|
|
|
socket.on('status', async (username) => {
|
|
const userUsername = socket.user.username;
|
|
const status = 'unread';
|
|
try {
|
|
const query = (
|
|
'UPDATE contacts SET status = $1 WHERE username = $2 AND contact = $3'
|
|
);
|
|
await db.query(query, [status, userUsername, username]);
|
|
io.to(userUsername).emit('status', username);
|
|
} catch(err) {
|
|
console.error('Failed to update unread status:', err);
|
|
}
|
|
})
|
|
|
|
socket.on('read', async(contactUsername) => {
|
|
const userUsername = socket.user.username;
|
|
const status = 'read';
|
|
try {
|
|
const query = ('UPDATE contacts SET status = $1 WHERE username = $2 AND contact = $3');
|
|
await db.query(query, [status, userUsername, contactUsername]);
|
|
io.to(userUsername).emit('status', contactUsername);
|
|
} catch(err) {
|
|
console.error('Failed to update unread status:', err)
|
|
}
|
|
})
|
|
// disconnect event
|
|
socket.on('disconnect', () => {
|
|
return "Disconnected";
|
|
});
|
|
});
|
|
|
|
return io;
|
|
}
|
|
|
|
module.exports = { initializeSocket }; |