180 lines
4.6 KiB
JavaScript
180 lines
4.6 KiB
JavaScript
// Global logging toggles
|
|
// const fileLogging = false;
|
|
const consoleLogging = true;
|
|
|
|
|
|
// Imports
|
|
// const fs = require('fs');
|
|
const http = require('http');
|
|
const express = require('express');
|
|
|
|
|
|
// Global server setup
|
|
const app = express();
|
|
const clientPath = __dirname+'/../html';
|
|
console.log('Serving static from ' + clientPath);
|
|
app.use(express.json());
|
|
app.use(express.static(clientPath));
|
|
const server = http.createServer(app);
|
|
|
|
|
|
// Check if string is already in array
|
|
function isStringUnique(arr, str) {
|
|
let match = true;
|
|
for (const s of arr)
|
|
if (s === str) {
|
|
match = false;
|
|
break;
|
|
}
|
|
return match;
|
|
}
|
|
|
|
// Generate the partial ID after username
|
|
function generatePartialID() {
|
|
return Math.floor(Math.random()*10000).toString().padStart(4, '0');
|
|
}
|
|
|
|
|
|
// User data
|
|
const users = [];
|
|
// Incoming user connection
|
|
app.post('/connect', (req, res) => {
|
|
// Generate id, save user
|
|
const { name } = req.body;
|
|
let id = generatePartialID();
|
|
const name_id = users.map(u => `${u.name}#${u.id}`);
|
|
while (!isStringUnique(name_id, `${name}#${id}`))
|
|
id = generatePartialID();
|
|
users.push({
|
|
socket: req.socket,
|
|
date: new Date(),
|
|
chats: {},
|
|
name,
|
|
id
|
|
});
|
|
// Log connection, send back id
|
|
if (consoleLogging)
|
|
console.log(`User with ID '${name}#${id}' connected.`);
|
|
res.status(200).json({ id });
|
|
});
|
|
|
|
// User has disconnected
|
|
app.post('/disconnect', (req, res) => {
|
|
const { name, id } = req.body;
|
|
for (let i = 0; i < users.length; i++)
|
|
if (users[i].name === name && users[i].id === id) {
|
|
// If id is valid, delete all user data
|
|
if (consoleLogging)
|
|
console.log(`User with ID '${name}#${id}' disconnected.`);
|
|
users.splice(i, 1);
|
|
break;
|
|
}
|
|
// Confirm disconnect
|
|
res.status(200).send();
|
|
});
|
|
|
|
// User wants to measure ping
|
|
app.get('/ping', (req, res) => {
|
|
res.status(200).send();
|
|
});
|
|
|
|
// User wants to change name
|
|
app.post('/nickname', (req, res) => {
|
|
const { oldName, name, id } = req.body;
|
|
|
|
// Check if name is taken, if not, append id until unique
|
|
const name_id = users.map(u => `${u.name}#${u.id}`);
|
|
let currentID = id;
|
|
while (!isStringUnique(name_id, `${name}#${currentID}`))
|
|
currentID = generatePartialID();
|
|
|
|
// Change username
|
|
for (const u of users)
|
|
if (u.name === oldName && u.id === id) {
|
|
if (consoleLogging)
|
|
console.log(`(Re-)named user with ID '${oldName}#${id}'.`);
|
|
u.name = name;
|
|
u.id = currentID;
|
|
break;
|
|
}
|
|
|
|
// Confirm renaming
|
|
res.status(200).json({ id: currentID });
|
|
});
|
|
|
|
// User is pulling messages
|
|
app.post('/getChat', (req, res) => {
|
|
const { name, id } = req.body;
|
|
|
|
// Go through users' chats, retrieve messages, save by username
|
|
let chats = {};
|
|
const fullName = `${name}#${id}`;
|
|
for (const u of users)
|
|
if (fullName in u.chats) {
|
|
const len = u.chats[fullName].length;
|
|
if (len > 0)
|
|
chats[`${u.name}#${u.id}`] = u.chats[fullName].splice(0, len);
|
|
}
|
|
|
|
// No chat messages were found
|
|
if (Object.keys(chats).length === 0) {
|
|
res.status(204).send();
|
|
return;
|
|
}
|
|
|
|
// Log if messages were delivered
|
|
if (consoleLogging)
|
|
console.log(`Delivered messages to user with ID '${fullName}'.`);
|
|
|
|
// Send back data
|
|
res.status(200).json(chats);
|
|
});
|
|
|
|
// User sent new message
|
|
app.post('/message', (req, res) => {
|
|
const { name, id, recipient, message } = req.body;
|
|
|
|
// Search for senders' name, save message
|
|
for (const u of users)
|
|
if (u.name === name && u.id === id) {
|
|
if (!u.chats[recipient])
|
|
u.chats[recipient] = [];
|
|
u.chats[recipient].push(message);
|
|
break;
|
|
}
|
|
|
|
// Log message for debugging
|
|
if (consoleLogging)
|
|
console.log(`User '${name}#${id}' sent message '${message}'.`);
|
|
|
|
// Confirm process
|
|
res.status(200).send();
|
|
});
|
|
|
|
// User requesting all names
|
|
app.get('/getNames', (req, res) => {
|
|
if (consoleLogging)
|
|
console.log('Some user requested all names.');
|
|
|
|
res.status(200).json(users.map(u => {
|
|
return {
|
|
name: u.name,
|
|
id: u.id
|
|
};
|
|
}));
|
|
});
|
|
|
|
// Internal server error
|
|
server.on('error', err => {
|
|
console.error('Internal server error', err);
|
|
});
|
|
|
|
// Server has closed
|
|
server.on('close', () => {
|
|
console.log('Shutting down server ...');
|
|
});
|
|
|
|
// Listen on port 3000 for webserver connection
|
|
server.listen(3000, () => {
|
|
console.log('Server running on port 3000');
|
|
}); |