implemented EventSource instead of regular update requests and minor clean up

This commit is contained in:
Baipyrus 2023-04-22 20:23:38 +02:00
parent 127903e423
commit b005e22025

104
index.js
View File

@ -34,10 +34,22 @@ function generatePartialID() {
return Math.floor(Math.random()*10000).toString().padStart(4, '0'); 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 // Check for user inactivity and delete accordingly
function userInactivity(name, id) { function userInactivity(name, id) {
for (let i = 0; i < users.length; i++) 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. // User with ID 'name#id' was inactive for longer than a day.
if (consoleLogging) if (consoleLogging)
@ -68,6 +80,7 @@ app.post('/connect', (req, res) => {
()=>userInactivity(name, id), ()=>userInactivity(name, id),
3600000), 3600000),
seen: new Date(), seen: new Date(),
event: null,
chats: {}, chats: {},
name, name,
id id
@ -89,7 +102,7 @@ app.post('/disconnect', (req, res) => {
// Search for user in data // Search for user in data
for (let i = 0; i < users.length; i++) for (let i = 0; i < users.length; i++)
// If user was found, delete all of their data // 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 // Log disconnect
if (consoleLogging) if (consoleLogging)
console.log(`User with ID '${name}#${id}' disconnected.`); console.log(`User with ID '${name}#${id}' disconnected.`);
@ -121,7 +134,7 @@ app.post('/nickname', (req, res) => {
// Find specified user // Find specified user
for (const u of users) for (const u of users)
if (u.name === oldName && u.id === id) { if (isUser(u, {name: oldName, id})) {
// Log renaming // Log renaming
if (consoleLogging) if (consoleLogging)
console.log(`(Re-)named user with ID '${oldName}#${id}'.`); console.log(`(Re-)named user with ID '${oldName}#${id}'.`);
@ -138,53 +151,36 @@ app.post('/nickname', (req, res) => {
}); });
// User is pulling messages // User is pulling messages
app.post('/getChat', (req, res) => { app.get('/getChat', (req, res) => {
// Retrieve user data and where to retrieve data from res.setHeader('Content-Type', 'text/event-stream');
const { name, from, id } = req.body; res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
// Save user activity // Save user activity
let full = req.query.full, found = false;
for (const u of users) 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(); u.seen = new Date();
break; break;
} }
if (!found) {
// Go through users' chats, retrieve messages, save by username res.write('data: {"message":"Invalid user provided."}');
let received = {}; res.end();
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();
return; return;
} }
// Log if messages were delivered // Log if messages were delivered
if (consoleLogging) 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 // Handle close-event for when client is no longer listening
res.status(200).json(received); res.on('close', () => {
for (const u of users)
if (isUser(u, {full}))
u.event = null;
});
}); });
// User sent new message // User sent new message
@ -194,13 +190,13 @@ app.post('/message', (req, res) => {
// Search for sender // Search for sender
for (const u of users) for (const u of users)
if (u.name === name && u.id === id) { if (isUser(u, {name, id})) {
// Go through every recipient // Go through every recipient
for (const recipient of to) { for (const recipient of to) {
// Save message for recipient // Save message for recipient
if (!u.chats[recipient]) for (const o of users)
u.chats[recipient] = []; if (isUser(o, {full: recipient}) && o.event !== null)
u.chats[recipient].push(message); o.event.write(`data: ${JSON.stringify({from: `${name}#${id}`, message})}\n\n`);
} }
// Save user activity // Save user activity
u.seen = new Date(); u.seen = new Date();
@ -237,7 +233,7 @@ app.post('/activity', (req, res) => {
// Save activity // Save activity
for (const u of users) for (const u of users)
if (u.name === name && u.id === id) { if (isUser(u, {name, id})) {
// Log activity // Log activity
if (consoleLogging) if (consoleLogging)
console.log(`User with ID '${name}#${id}' is online.`); 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 // Go through users, success if user exists
let success = false; let success = false;
for (const u of users) for (const u of users)
if (u.name === name && u.id === id) { if (isUser(u, {name, id})) {
success = true; success = true;
// Save activity // Save activity
u.seen = new Date(); u.seen = new Date();
@ -280,7 +276,7 @@ app.post('/chatInit', (req, res) => {
// Save user activity // Save user activity
for (const u of users) for (const u of users)
if (u.name === name && u.id === id) { if (isUser(u, {name, id})) {
u.seen = new Date(); u.seen = new Date();
break; break;
} }
@ -296,8 +292,8 @@ app.post('/chatInit', (req, res) => {
if (n[0] === c.name) { if (n[0] === c.name) {
// Chat exists, add user to it // Chat exists, add user to it
n[1] = true; n[1] = true;
if (!c.users[fullName]) if (!c.users.includes(fullName))
c.users[fullName] = {}; c.users.push(fullName);
break; break;
} }
} }
@ -308,7 +304,7 @@ app.post('/chatInit', (req, res) => {
if (!n[1]) if (!n[1])
// Create it and save user in it // Create it and save user in it
chats.push({ chats.push({
users: {[fullName]: {}}, users: [fullName],
name: n[0] name: n[0]
}); });
} }
@ -328,7 +324,7 @@ app.post('/sendGroup', (req, res) => {
// Save user activity // Save user activity
for (const u of users) for (const u of users)
if (u.name === name && u.id === id) { if (isUser(u, {name, id})) {
u.seen = new Date(); u.seen = new Date();
break; break;
} }
@ -338,12 +334,12 @@ app.post('/sendGroup', (req, res) => {
for (const c of chats) for (const c of chats)
if (chat.includes(c.name)) { if (chat.includes(c.name)) {
// Go through users in chat // Go through users in chat
for (const u in c.users) for (const u of c.users)
if (u !== fullName) { if (u !== fullName) {
// Save message for recipient // Send message to recipient
if (!c.users[u][fullName]) for (const o of users)
c.users[u][fullName] = []; if (isUser(o, {full: u}) && o.event !== null)
c.users[u][fullName].push(message); o.event.write(`data: ${JSON.stringify({from: fullName, message})}\n\n`);
} }
} }