diff --git a/lib b/lib index a957a29..a618eda 160000 --- a/lib +++ b/lib @@ -1 +1 @@ -Subproject commit a957a29498d6b9c3b121f8e27e43ad73d9342075 +Subproject commit a618eda73268a675e0c90dace9751ad05d5e0443 diff --git a/server.node.ts b/server.node.ts index c74f53d..8de9cdd 100644 --- a/server.node.ts +++ b/server.node.ts @@ -9,18 +9,22 @@ import type { IdResponseMessage, TextMessage, TypingMessage, + ConnectedUser, + ConnectedUsersMessage, } from "./lib/ServerMessage"; import { isServerMessage, isTextMessage, isTypingMessage, + isDesiredNameMessage, MessageType, } from "./lib/ServerMessage"; const port = 8085; -const timeout = 15000; +const timeout = 5000; const typingTimeout = 2000; +const serverId = "00000000-0000-0000-0000-000000000000"; const httpsServer = https.createServer({ key: fs.readFileSync("./key.pem"), @@ -49,6 +53,10 @@ async function handleTextMessage(message: TextMessage, from: string) { const activeConnections = new Set(); const currentlyTyping = new Set(); const currentlyTypingTimeouts = new Map>(); +const desiredNames = new Map(); + +activeConnections.add(serverId); +desiredNames.set(serverId, "[SYSTEM]"); async function handleTypingMessage(_message: TypingMessage, from: string) { currentlyTyping.add(from); @@ -85,6 +93,50 @@ async function sendCurrentlyTypingMessage(from?: string, stopped = false) { async function handleCloseConnection(id: string) { activeConnections.delete(id); + if (desiredNames.has(id)) { + desiredNames.delete(id); + } + + for (const to of webSocketServer.clients) { + to.send( + JSON.stringify({ + type: MessageType.CONNECTED_USERS, + __ctx: `${id} left`, + date: Date.now(), + connected: + Array.from(activeConnections, + (id) => { + return { + id, + desiredName: desiredNames.get(id), + } as ConnectedUser; + }), + } as ConnectedUsersMessage) + ); + } + +} + +function handleNewConnection(id: string) { + activeConnections.add(id); + + for (const to of webSocketServer.clients) { + to.send( + JSON.stringify({ + type: MessageType.CONNECTED_USERS, + __ctx: `${id} joined`, + date: Date.now(), + connected: + Array.from(activeConnections, + (id) => { + return { + id, + desiredName: desiredNames.get(id), + } as ConnectedUser; + }), + } as ConnectedUsersMessage) + ); + } } webSocketServer.on("connection", function connection(socket) { @@ -107,6 +159,9 @@ webSocketServer.on("connection", function connection(socket) { if (!isServerMessage(message)) { console.error(`Unexpected message received from client "${authorId}": \`${message}\``); return; + } else { + clearTimeout(closeTimeout); + closeTimeout = setTimeout(close, timeout); } if (isTextMessage(message)) { @@ -115,10 +170,9 @@ webSocketServer.on("connection", function connection(socket) { } } else if (isTypingMessage(message)) { handleTypingMessage(message, authorId); + } else if (isDesiredNameMessage(message)) { + desiredNames.set(authorId, message.desiredName); } - - clearTimeout(closeTimeout); - closeTimeout = setTimeout(close, timeout); }); socket.on("close", function close() { console.log("closed a connection"); @@ -133,7 +187,18 @@ webSocketServer.on("connection", function connection(socket) { authorId, } as IdResponseMessage) ); - activeConnections.add(authorId); + + handleNewConnection(authorId); + + socket.send( + JSON.stringify({ + type: MessageType.TEXT, + __ctx: "server welcome message", + date: Date.now(), + author: serverId, + content: "Successfully connected. Welcome!\nSend a message to talk to other connected users.", + } as TextMessage) + ); let closeTimeout = setTimeout(close, timeout); });