From d5a744652daa952af3daab0fc5a5bccb8324eea6 Mon Sep 17 00:00:00 2001 From: Yandrik Date: Tue, 8 Jul 2025 14:57:44 +0200 Subject: [PATCH] feat: better colab --- server.js | 27 +++++++++++++++++++++++++++ src/routes/+page.svelte | 14 ++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/server.js b/server.js index 71050c0..67361eb 100644 --- a/server.js +++ b/server.js @@ -8,9 +8,36 @@ const app = express(); const server = http.createServer(app); const io = new Server(server); +const eventTimestamps = {}; +const EVENT_LIMIT = 100; // Max events per second per user +const TIME_FRAME = 1000; // 1 second in milliseconds + io.on('connection', (socket) => { console.log('a user connected'); + // Middleware to check for event spamming + socket.use((packet, next) => { + const userId = socket.id; + const eventName = packet[0]; + const now = Date.now(); + + if (!eventTimestamps[userId]) { + eventTimestamps[userId] = []; + } + + // Remove timestamps older than the time frame + eventTimestamps[userId] = eventTimestamps[userId].filter(ts => now - ts < TIME_FRAME); + + // Check if the user has exceeded the event limit + if (eventTimestamps[userId].length >= EVENT_LIMIT) { + console.warn(`User ${userId} is sending too many events (${eventName}). Throttling.`); + return next(new Error('Too many events')); + } + + eventTimestamps[userId].push(now); + next(); + }); + socket.on('join', (room) => { socket.join(room); console.log(`User joined room: ${room}`); diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 3964c7e..f3be5f4 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -119,7 +119,7 @@ let socket: Socket; let room: string; let isStateSynced = false; - let lastMoveTime = 0; + let lastEmitTime = 0; onMount(() => { const urlParams = new URLSearchParams(window.location.search); @@ -291,9 +291,9 @@ card.zIndex = ++maxZIndex; const now = Date.now(); - if (now - lastMoveTime > 50) { // Throttle to 20fps + if (now - lastEmitTime > 16) { // Throttle to ~60fps socket.emit('card-move', { room, id, x, y, zIndex: card.zIndex }); - lastMoveTime = now; + lastEmitTime = now; } } } @@ -431,6 +431,7 @@ } function collectToDeck() { + if (!confirm('Are you sure you want to collect all cards to the deck?')) return; cards.forEach((card, index) => { card.x = deckPosition.x + index * 2; card.y = deckPosition.y + index * 2; @@ -442,6 +443,7 @@ } function dealCards() { + if (!confirm('Are you sure you want to deal all cards?')) return; cards.forEach((card, index) => { card.x = 50 + 330 + (index % 6) * 240; card.y = 50 + Math.floor(index / 6) * 320; @@ -607,7 +609,11 @@ note.x = x; note.y = y; note.zIndex = ++maxZIndex; - socket.emit('sticky-note-move', { room, id, x, y, zIndex: note.zIndex }); + const now = Date.now(); + if (now - lastEmitTime > 16) { // Throttle to ~60fps + socket.emit('sticky-note-move', { room, id, x, y, zIndex: note.zIndex }); + lastEmitTime = now; + } } }