group chat bugfixes

This commit is contained in:
Baipyrus 2023-02-06 09:25:14 +01:00
parent d672692854
commit f408548ab0

180
index.js
View File

@ -38,6 +38,8 @@ function generatePartialID() {
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 (users[i].name === name && users[i].id === id && new Date() - users[i].seen > 86400000) {
// User with ID 'name#id' was inactive for longer than a day.
if (consoleLogging) if (consoleLogging)
console.log(`Deleting user with ID '${name}#${id}' because of inactivity.`); console.log(`Deleting user with ID '${name}#${id}' because of inactivity.`);
@ -51,12 +53,16 @@ function userInactivity(name, id) {
const users = [], chats = []; const users = [], chats = [];
// Incoming user connection // Incoming user connection
app.post('/connect', (req, res) => { app.post('/connect', (req, res) => {
// Generate id, save user // Retrieve username
const { name } = req.body; const { name } = req.body;
// Generate id in unique pattern 'name#id'
let id = generatePartialID(); let id = generatePartialID();
const name_id = users.map(u => `${u.name}#${u.id}`); const name_id = users.map(u => `${u.name}#${u.id}`);
while (!isStringUnique(name_id, `${name}#${id}`)) while (!isStringUnique(name_id, `${name}#${id}`))
id = generatePartialID(); id = generatePartialID();
// Save user data
users.push({ users.push({
deletion: setInterval( deletion: setInterval(
()=>userInactivity(name, id), ()=>userInactivity(name, id),
@ -66,24 +72,34 @@ app.post('/connect', (req, res) => {
name, name,
id id
}); });
// Log connection, send back id
// Log connection
if (consoleLogging) if (consoleLogging)
console.log(`User with ID '${name}#${id}' connected.`); console.log(`User with ID '${name}#${id}' connected.`);
// Respond with id
res.status(200).json({ id }); res.status(200).json({ id });
}); });
// User has disconnected // User has disconnected
app.post('/disconnect', (req, res) => { app.post('/disconnect', (req, res) => {
// Retrieve user data
const { name, id } = req.body; const { name, id } = req.body;
// 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 (users[i].name === name && users[i].id === id) { if (users[i].name === name && users[i].id === id) {
// If id is valid, delete all user data // Log disconnect
if (consoleLogging) if (consoleLogging)
console.log(`User with ID '${name}#${id}' disconnected.`); console.log(`User with ID '${name}#${id}' disconnected.`);
// Delete user
users.splice(i, 1); users.splice(i, 1);
break; break;
} }
// Confirm disconnect
// Respond with id as confirmation
res.status(200).send(); res.status(200).send();
}); });
@ -94,33 +110,39 @@ app.get('/ping', (req, res) => {
// User wants to change name // User wants to change name
app.post('/nickname', (req, res) => { app.post('/nickname', (req, res) => {
// Retrieve user data and old name
const { oldName, name, id } = req.body; const { oldName, name, id } = req.body;
// Check if name is taken, if not, append id until unique // Check if unique pattern 'name#id' is valid, generate new one
const name_id = users.map(u => `${u.name}#${u.id}`); const name_id = users.map(u => `${u.name}#${u.id}`);
let currentID = id; let currentID = id;
while (!isStringUnique(name_id, `${name}#${currentID}`)) while (!isStringUnique(name_id, `${name}#${currentID}`))
currentID = generatePartialID(); currentID = generatePartialID();
// Change username // Find specified user
for (const u of users) for (const u of users)
if (u.name === oldName && u.id === id) { if (u.name === oldName && u.id === id) {
// Log renaming
if (consoleLogging) if (consoleLogging)
console.log(`(Re-)named user with ID '${oldName}#${id}'.`); console.log(`(Re-)named user with ID '${oldName}#${id}'.`);
// Save new name
u.name = name; u.name = name;
u.id = currentID; u.id = currentID;
u.seen = new Date(); u.seen = new Date();
break; break;
} }
// Confirm renaming // Respond with confirmation
res.status(200).json({ id: currentID }); res.status(200).json({ id: currentID });
}); });
// User is pulling messages // User is pulling messages
app.post('/getChat', (req, res) => { app.post('/getChat', (req, res) => {
// Retrieve user data and where to retrieve data from
const { name, from, id } = req.body; const { name, from, id } = req.body;
// Save user activity
for (const u of users) for (const u of users)
if (u.name === name && u.id === id) { if (u.name === name && u.id === id) {
u.seen = new Date(); u.seen = new Date();
@ -128,17 +150,31 @@ app.post('/getChat', (req, res) => {
} }
// Go through users' chats, retrieve messages, save by username // Go through users' chats, retrieve messages, save by username
let chats = {}; let received = {};
const fullName = `${name}#${id}`; const fullName = `${name}#${id}`;
for (const u of users) for (const u of users)
if (fullName in u.chats) { if (fullName in u.chats) {
// User might have new message from another user
const len = u.chats[fullName].length; const len = u.chats[fullName].length;
if (len > 0 && from.includes(`${u.name}#${u.id}`)) if (len > 0 && from.includes(`${u.name}#${u.id}`))
chats[`${u.name}#${u.id}`] = u.chats[fullName].splice(0, len); 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 // No chat messages were found
if (Object.keys(chats).length === 0) { if (Object.keys(received).length === 0) {
// Respond with no content
res.status(204).send(); res.status(204).send();
return; return;
} }
@ -147,27 +183,31 @@ app.post('/getChat', (req, res) => {
if (consoleLogging) if (consoleLogging)
console.log(`Delivered messages to user with ID '${fullName}' from '${from}'.`); console.log(`Delivered messages to user with ID '${fullName}' from '${from}'.`);
// Send back data // Respond with data
res.status(200).json(chats); res.status(200).json(received);
}); });
// User sent new message // User sent new message
app.post('/message', (req, res) => { app.post('/message', (req, res) => {
// Retrieve user data, their message and where to deliver it to
const { name, id, to, message } = req.body; const { name, id, to, message } = req.body;
// Search for senders' name, save message // Search for sender
for (const u of users) for (const u of users)
if (u.name === name && u.id === id) { if (u.name === name && u.id === id) {
// Go through every recipient
for (const recipient of to) { for (const recipient of to) {
// Save message for recipient
if (!u.chats[recipient]) if (!u.chats[recipient])
u.chats[recipient] = []; u.chats[recipient] = [];
u.chats[recipient].push(message); u.chats[recipient].push(message);
} }
// Save user activity
u.seen = new Date(); u.seen = new Date();
break; break;
} }
// Log message for debugging // Log users' message
if (consoleLogging) if (consoleLogging)
console.log(`User with ID '${name}#${id}' sent message '${message}' to '${to}'.`); console.log(`User with ID '${name}#${id}' sent message '${message}' to '${to}'.`);
@ -177,9 +217,11 @@ app.post('/message', (req, res) => {
// User requesting all names // User requesting all names
app.get('/getNames', (req, res) => { app.get('/getNames', (req, res) => {
// Log request
if (consoleLogging) if (consoleLogging)
console.log('Some user requested all usernames + IDs.'); console.log('Some user requested all usernames + IDs.');
// Respond with unique patterns 'name#id'
res.status(200).json(users.map(u => { res.status(200).json(users.map(u => {
return { return {
name: u.name, name: u.name,
@ -190,82 +232,126 @@ app.get('/getNames', (req, res) => {
// User sends activity notification // User sends activity notification
app.post('/activity', (req, res) => { app.post('/activity', (req, res) => {
// Retrieve user data
const { name, id } = req.body; const { name, id } = req.body;
// Log activity
if (consoleLogging) if (consoleLogging)
console.log(`User with ID '${name}#${id}' is online.`); console.log(`User with ID '${name}#${id}' is online.`);
// Save activity
for (const u of users) for (const u of users)
if (u.name === name && u.id === id) { if (u.name === name && u.id === id) {
u.seen = new Date(); u.seen = new Date();
break; break;
} }
// Confirm process
res.status(200).send(); res.status(200).send();
}); });
// User asks if their data exists
app.post('/login', (req, res) => { app.post('/login', (req, res) => {
// Retrieve user data
const { name, id } = req.body; const { name, id } = req.body;
// Log login
if (consoleLogging) if (consoleLogging)
console.log(`Some user requested existence of '${name}#${id}'.`); console.log(`Some user requested existence of '${name}#${id}'.`);
// 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 (u.name === name && u.id === id) {
success = true; success = true;
// Save activity
u.seen = new Date(); u.seen = new Date();
break; break;
} }
// Respond with status
res.status(200).json({success}); res.status(200).json({success});
}); });
// User wants to join chat
app.post('/chatInit', (req, res) => { app.post('/chatInit', (req, res) => {
// Retrieve user data and chat name
const { name, id, chat } = req.body; const { name, id, chat } = req.body;
const fullName = `${name}#${id}`;
let chatExists = false;
for (const c of chats)
if (c.name === chat) {
chatExists = true;
if (!c.users[fullName])
c.users[fullName] = [];
break;
}
if (!chatExists)
chats.push({
users: {},
name: chat
});
// Log message for debugging
if (consoleLogging)
console.log(`User with ID '${name}#${id}' joined chat '${chat}'.`);
res.status(200).send();
});
app.post('/sendGroup', (req, res) => {
const { name, id, message, chat } = req.body;
for (const c of chats)
if (c.name === chat) {
c.users[`${name}#${id}`].push(message);
break;
}
// Save user activity
for (const u of users) for (const u of users)
if (u.name === name && u.id === id) { if (u.name === name && u.id === id) {
u.seen = new Date(); u.seen = new Date();
break; break;
} }
// Log message for debugging // Check if chats already exist
const fullName = `${name}#${id}`;
let existance = chat.map(e => [e, false]);
// Go through chats
for (const c of chats)
// Go through provided names
for (const n of existance) {
// If name is this chat
if (n[0] === c.name) {
// Chat exists, add user to it
n[1] = true;
if (!c.users[fullName])
c.users[fullName] = {};
break;
}
}
// Go through provided names
for (const n of existance) {
// Chat didn't exist
if (!n[1])
// Create it and save user in it
chats.push({
users: {[fullName]: {}},
name: n[0]
});
}
// Log chat initialization
if (consoleLogging)
console.log(`User with ID '${name}#${id}' joined chat '${chat}'.`);
// Confirm process
res.status(200).send();
});
// User sends a message in chat
app.post('/sendGroup', (req, res) => {
// Retrieve user data and chat name and message
const { name, id, message, chat } = req.body;
// Save user activity
for (const u of users)
if (u.name === name && u.id === id) {
u.seen = new Date();
break;
}
// Find provided chat
const fullName = `${name}#${id}`;
for (const c of chats)
if (chat.includes(c.name)) {
// Go through users in chat
for (const u in c.users)
if (u !== fullName) {
// Save message for recipient
if (!c.users[u][fullName])
c.users[u][fullName] = [];
c.users[u][fullName].push(message);
}
}
// Log users' message
if (consoleLogging) if (consoleLogging)
console.log(`User with ID '${name}#${id}' sent message '${message}' in '${chat}'.`); console.log(`User with ID '${name}#${id}' sent message '${message}' in '${chat}'.`);
// Confirm process
res.status(200).send(); res.status(200).send();
}); });