import express from 'express'; import http from 'http'; import { Server } from 'socket.io'; import { handler } from './build/handler.js'; 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}`); }); socket.on('request-state', (data) => { socket.to(data.room).emit('request-state', { from: socket.id }); }); socket.on('sync-state', (data) => { socket.to(data.to).emit('sync-state', data); }); socket.on('card-move', (data) => { socket.to(data.room).emit('card-move', data); }); socket.on('card-click', (data) => { socket.to(data.room).emit('card-click', data); }); socket.on('card-drop', (data) => { socket.to(data.room).emit('card-drop', data); }); socket.on('sticky-note-add', (data) => { socket.to(data.room).emit('sticky-note-add', data); }); socket.on('sticky-note-move', (data) => { socket.to(data.room).emit('sticky-note-move', data); }); socket.on('sticky-note-update', (data) => { socket.to(data.room).emit('sticky-note-update', data); }); socket.on('sticky-note-delete', (data) => { socket.to(data.room).emit('sticky-note-delete', data); }); socket.on('deck-change', (data) => { socket.to(data.room).emit('deck-change', data); }); socket.on('shuffle-deck', (data) => { socket.to(data.room).emit('shuffle-deck', data); }); socket.on('collect-to-deck', (data) => { socket.to(data.room).emit('collect-to-deck', data); }); socket.on('deal-cards', (data) => { socket.to(data.room).emit('deal-cards', data); }); socket.on('flip-all-cards', (data) => { socket.to(data.room).emit('flip-all-cards', data); }); socket.on('shuffle-mode-change', (data) => { socket.to(data.room).emit('shuffle-mode-change', data); }); socket.on('import-canvas', (data) => { socket.to(data.room).emit('import-canvas', data); }); socket.on('disconnect', () => { console.log('user disconnected'); }); }); app.use(handler); server.listen(3000, () => { console.log('listening on *:3000'); });