const express = require('express'); const http = require('http'); const { Server } = require('socket.io'); const { db, init } = require('./database'); const app = express(); const server = http.createServer(app); const io = new Server(server); // Initialize DB init(); app.use(express.static('public')); // Rate limit helper function canClick(name) { const row = db.prepare('SELECT timestamp FROM logs WHERE name = ? ORDER BY timestamp DESC LIMIT 1').get(name); if (!row) return true; const lastClickTime = new Date(row.timestamp).getTime(); const now = Date.now(); // 30 seconds cooldown return (now - lastClickTime) >= 30000; } function getGlobalCount() { return db.prepare('SELECT count FROM global_count WHERE id = 1').get().count; } io.on('connection', (socket) => { // Send current count immediately socket.emit('update', { count: getGlobalCount() }); // Handle increment socket.on('increment', (data) => { const { name, quote } = data; if (!name || name.trim() === "") { socket.emit('error', 'Name is required'); return; } if (!canClick(name)) { socket.emit('error', 'You must wait 30 seconds between clicks.'); return; } // Transaction to ensure consistency const incrementTx = db.transaction(() => { db.prepare('UPDATE global_count SET count = count + 1 WHERE id = 1').run(); db.prepare('INSERT INTO logs (name, quote) VALUES (?, ?)').run(name, quote || ''); return getGlobalCount(); }); const newCount = incrementTx(); // Broadcast new count to EVERYONE io.emit('update', { count: newCount }); // Broadcast new log entry to admins (in a real app, we'd check auth, here we broadcast to "admin" room or just all for simplicity, but let's be nice and use a room if we were distinguishing. For now, I'll just emit a 'new_log' event globally or maybe just to the sender? // The admin panel "gets logs". I should probably emit 'new_log' to everyone on the admin page. // Let's assume admin listeners join a room 'admin'. io.to('admin').emit('new_log', { name, quote, timestamp: new Date().toISOString() }); }); // Admin room join socket.on('join_admin', () => { socket.join('admin'); // Send recent logs const logs = db.prepare('SELECT * FROM logs ORDER BY timestamp DESC LIMIT 50').all(); socket.emit('admin_data', { logs }); }); }); const PORT = process.env.PORT || 3000; server.listen(PORT, () => { console.log(`Server running on http://localhost:${PORT}`); });