From b005e22025aea7f3e04c54dc698876e5dba1ac57 Mon Sep 17 00:00:00 2001 From: Baipyrus Date: Sat, 22 Apr 2023 20:23:38 +0200 Subject: [PATCH] implemented EventSource instead of regular update requests and minor clean up --- index.js | 104 ++++++++++++++++++++++++++----------------------------- 1 file changed, 50 insertions(+), 54 deletions(-) diff --git a/index.js b/index.js index 7728994..92c562a 100644 --- a/index.js +++ b/index.js @@ -34,10 +34,22 @@ function generatePartialID() { return Math.floor(Math.random()*10000).toString().padStart(4, '0'); } +// Check if input is a user +function isUser(user, other) { + // Check by full name + if ('full' in other) + return `${user.name}#${user.id}` === other.full; + // Check by unique id + else if ('id' in other && 'name' in other) + return other.id === user.id && other.name === user.name; + // Not applicable + else return false; +} + // Check for user inactivity and delete accordingly function userInactivity(name, id) { for (let i = 0; i < users.length; i++) - if (users[i].name === name && users[i].id === id && new Date() - users[i].seen > 86400000) { + if (isUser(users[i], {name, id}) && new Date() - users[i].seen > 86400000) { // User with ID 'name#id' was inactive for longer than a day. if (consoleLogging) @@ -68,6 +80,7 @@ app.post('/connect', (req, res) => { ()=>userInactivity(name, id), 3600000), seen: new Date(), + event: null, chats: {}, name, id @@ -89,7 +102,7 @@ app.post('/disconnect', (req, res) => { // Search for user in data for (let i = 0; i < users.length; i++) // If user was found, delete all of their data - if (users[i].name === name && users[i].id === id) { + if (isUser(users[i], {name, id})) { // Log disconnect if (consoleLogging) console.log(`User with ID '${name}#${id}' disconnected.`); @@ -121,7 +134,7 @@ app.post('/nickname', (req, res) => { // Find specified user for (const u of users) - if (u.name === oldName && u.id === id) { + if (isUser(u, {name: oldName, id})) { // Log renaming if (consoleLogging) console.log(`(Re-)named user with ID '${oldName}#${id}'.`); @@ -138,53 +151,36 @@ app.post('/nickname', (req, res) => { }); // User is pulling messages -app.post('/getChat', (req, res) => { - // Retrieve user data and where to retrieve data from - const { name, from, id } = req.body; +app.get('/getChat', (req, res) => { + res.setHeader('Content-Type', 'text/event-stream'); + res.setHeader('Cache-Control', 'no-cache'); + res.setHeader('Connection', 'keep-alive'); // Save user activity + let full = req.query.full, found = false; for (const u of users) - if (u.name === name && u.id === id) { + if (isUser(u, {full})) { + found = true; + u.event = res; u.seen = new Date(); break; } - - // Go through users' chats, retrieve messages, save by username - let received = {}; - const fullName = `${name}#${id}`; - for (const u of users) - if (fullName in u.chats) { - // User might have new message from another user - const len = u.chats[fullName].length; - if (len > 0 && from.includes(`${u.name}#${u.id}`)) - received[`${u.name}#${u.id}`] = u.chats[fullName].splice(0, len); - } - - // Go through chats (Array of Objects) - for (const c of chats) - if (from.includes(c.name)) { - const cusers = c.users[fullName]; - // Look through user data (Object with usernames as keys) - for (const u in cusers) { - // Retrieve messages from data (Array) - const len = cusers[u].length; - if (len > 0) received[u] = cusers[u].splice(0, len); - } - } - - // No chat messages were found - if (Object.keys(received).length === 0) { - // Respond with no content - res.status(204).send(); + if (!found) { + res.write('data: {"message":"Invalid user provided."}'); + res.end(); return; } // Log if messages were delivered if (consoleLogging) - console.log(`Delivered messages to user with ID '${fullName}' from '${from}'.`); + console.log(`New message event listener opened by user with ID '${full}'.`); - // Respond with data - res.status(200).json(received); + // Handle close-event for when client is no longer listening + res.on('close', () => { + for (const u of users) + if (isUser(u, {full})) + u.event = null; + }); }); // User sent new message @@ -194,13 +190,13 @@ app.post('/message', (req, res) => { // Search for sender for (const u of users) - if (u.name === name && u.id === id) { + if (isUser(u, {name, id})) { // Go through every recipient for (const recipient of to) { // Save message for recipient - if (!u.chats[recipient]) - u.chats[recipient] = []; - u.chats[recipient].push(message); + for (const o of users) + if (isUser(o, {full: recipient}) && o.event !== null) + o.event.write(`data: ${JSON.stringify({from: `${name}#${id}`, message})}\n\n`); } // Save user activity u.seen = new Date(); @@ -237,7 +233,7 @@ app.post('/activity', (req, res) => { // Save activity for (const u of users) - if (u.name === name && u.id === id) { + if (isUser(u, {name, id})) { // Log activity if (consoleLogging) console.log(`User with ID '${name}#${id}' is online.`); @@ -262,7 +258,7 @@ app.post('/login', (req, res) => { // Go through users, success if user exists let success = false; for (const u of users) - if (u.name === name && u.id === id) { + if (isUser(u, {name, id})) { success = true; // Save activity u.seen = new Date(); @@ -280,7 +276,7 @@ app.post('/chatInit', (req, res) => { // Save user activity for (const u of users) - if (u.name === name && u.id === id) { + if (isUser(u, {name, id})) { u.seen = new Date(); break; } @@ -296,8 +292,8 @@ app.post('/chatInit', (req, res) => { if (n[0] === c.name) { // Chat exists, add user to it n[1] = true; - if (!c.users[fullName]) - c.users[fullName] = {}; + if (!c.users.includes(fullName)) + c.users.push(fullName); break; } } @@ -308,7 +304,7 @@ app.post('/chatInit', (req, res) => { if (!n[1]) // Create it and save user in it chats.push({ - users: {[fullName]: {}}, + users: [fullName], name: n[0] }); } @@ -328,7 +324,7 @@ app.post('/sendGroup', (req, res) => { // Save user activity for (const u of users) - if (u.name === name && u.id === id) { + if (isUser(u, {name, id})) { u.seen = new Date(); break; } @@ -338,12 +334,12 @@ app.post('/sendGroup', (req, res) => { for (const c of chats) if (chat.includes(c.name)) { // Go through users in chat - for (const u in c.users) + for (const u of c.users) if (u !== fullName) { - // Save message for recipient - if (!c.users[u][fullName]) - c.users[u][fullName] = []; - c.users[u][fullName].push(message); + // Send message to recipient + for (const o of users) + if (isUser(o, {full: u}) && o.event !== null) + o.event.write(`data: ${JSON.stringify({from: fullName, message})}\n\n`); } }