Spaces:
Runtime error
Runtime error
| const express = require('express'); | |
| const http = require('http'); | |
| const WebSocket = require('ws'); | |
| const path = require('path'); | |
| const app = express(); | |
| const port = 8080; | |
| // Serve static files (if any) | |
| app.use(express.static('public')); | |
| // Data structures to store client data | |
| const clients = {}; | |
| // HTTP server | |
| const server = http.createServer(app); | |
| // WebSocket server | |
| const wss = new WebSocket.Server({ server }); | |
| // Handle new WebSocket connections | |
| wss.on('connection', (ws) => { | |
| let clientId = null; | |
| ws.on('message', (message) => { | |
| try { | |
| const data = JSON.parse(message); | |
| if (!clientId && data.clientId) { | |
| clientId = data.clientId; | |
| clients[clientId] = { | |
| ws: ws, | |
| html: '', | |
| css: '', | |
| url: '' | |
| }; | |
| console.log(`Client ${clientId} connected`); | |
| } | |
| if (data.type === 'pageContent') { | |
| clients[clientId].html = data.html; | |
| clients[clientId].css = data.css; | |
| clients[clientId].url = data.url; | |
| } else if (data.type === 'keyboardEvent') { | |
| // Relay the keyboard event to other clients | |
| relayKeyboardEvent(data, clientId); | |
| } | |
| } catch (e) { | |
| console.error('Error parsing message:', e); | |
| } | |
| }); | |
| ws.on('close', () => { | |
| console.log(`Client ${clientId} disconnected`); | |
| delete clients[clientId]; | |
| }); | |
| }); | |
| // Function to relay keyboard events to other clients | |
| function relayKeyboardEvent(data, senderId) { | |
| // Send the keyboard event to all connected clients except the sender | |
| for (const [id, client] of Object.entries(clients)) { | |
| if (id !== senderId) { | |
| client.ws.send(JSON.stringify(data)); | |
| } | |
| } | |
| } | |
| // Route to list all active clients | |
| app.get('/clients', (req, res) => { | |
| res.json(Object.keys(clients)); | |
| }); | |
| // Route to render the client's page | |
| app.get('/client/:id', (req, res) => { | |
| const client = clients[req.params.id]; | |
| if (client) { | |
| let htmlContent = client.html; | |
| // Inject the CSS into a style tag in the head | |
| const cssTag = `<style>${client.css}</style>`; | |
| htmlContent = htmlContent.replace('</head>', `${cssTag}</head>`); | |
| // Inject the script to establish WebSocket connection | |
| const scriptTag = ` | |
| <script> | |
| (function() { | |
| const socket = new WebSocket('ws://' + location.host); | |
| const clientId = '${req.params.id}-page'; | |
| socket.addEventListener('open', () => { | |
| console.log('WebSocket connection opened from rendered page'); | |
| }); | |
| socket.addEventListener('message', (event) => { | |
| const data = JSON.parse(event.data); | |
| // Ignore messages originating from this client | |
| if (data.clientId === clientId) return; | |
| if (data.type === 'keyboardEvent') { | |
| simulateKeyboardEvent(data.event); | |
| } | |
| }); | |
| // Send keyboard events to the server | |
| function sendKeyboardEvent(event) { | |
| const data = { | |
| type: 'keyboardEvent', | |
| event: serializeKeyboardEvent(event), | |
| clientId: clientId | |
| }; | |
| socket.send(JSON.stringify(data)); | |
| } | |
| // Serialize keyboard event properties | |
| function serializeKeyboardEvent(event) { | |
| return { | |
| type: event.type, | |
| key: event.key, | |
| code: event.code, | |
| keyCode: event.keyCode, | |
| charCode: event.charCode, | |
| which: event.which, | |
| altKey: event.altKey, | |
| ctrlKey: event.ctrlKey, | |
| metaKey: event.metaKey, | |
| shiftKey: event.shiftKey, | |
| repeat: event.repeat, | |
| isComposing: event.isComposing, | |
| }; | |
| } | |
| // Simulate keyboard event | |
| function simulateKeyboardEvent(eventData) { | |
| const event = new KeyboardEvent(eventData.type, eventData); | |
| document.activeElement.dispatchEvent(event); | |
| } | |
| // Listen for keyboard events | |
| ['keydown', 'keypress', 'keyup'].forEach(eventType => { | |
| document.addEventListener(eventType, sendKeyboardEvent, true); | |
| }); | |
| })(); | |
| </script> | |
| `; | |
| htmlContent = htmlContent.replace('</body>', `${scriptTag}</body>`); | |
| res.send(htmlContent); | |
| } else { | |
| res.status(404).send('Client not found'); | |
| } | |
| }); | |
| // Start the server | |
| server.listen(port, () => { | |
| console.log(`Server is listening on http://localhost:${port}`); | |
| }); | |