Spaces:
Running
Running
// server.js | |
const express = require('express'); | |
const http = require('http'); | |
const WebSocket = require('ws'); | |
const path = require('path'); | |
const app = express(); | |
const port = 7860; | |
// 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) => { | |
const clientId = generateId(); | |
clients[clientId] = { | |
ws: ws, | |
html: '', | |
css: '', | |
url: '' | |
}; | |
console.log(`Client ${clientId} connected`); | |
ws.on('message', (message) => { | |
try { | |
const data = JSON.parse(message); | |
if (data.type === 'sessionInfo') { | |
if(data.sessionId){ | |
clients[clientId].sessionId = data.sessionId; | |
} | |
} | |
if (data.type === 'pageContent') { | |
clients[clientId].html = data.html; | |
clients[clientId].css = data.css; | |
clients[clientId].url = data.url; | |
} else if (data.type === 'userInteraction') { | |
// Handle user interactions if needed | |
console.log(`Interaction from ${clientId}:`, data); | |
} | |
} catch (e) { | |
console.error('Error parsing message:', e); | |
} | |
}); | |
ws.on('close', () => { | |
console.log(`Client ${clientId} disconnected`); | |
delete clients[clientId]; | |
}); | |
}); | |
// Generate a unique client ID | |
function generateId() { | |
return Math.random().toString(36).substr(2, 9); | |
} | |
// Tailwind Play CDN for including Tailwind CSS | |
const tailwindCDN = `<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">`; | |
// Route to list all active clients | |
app.get('/', (req, res) => { | |
// Get the list of active clients | |
const clientKeys = Object.keys(clients); | |
// If no clients are available | |
if (clientKeys.length === 0) { | |
return res.send(` | |
${tailwindCDN} | |
<div class="min-h-screen flex items-center justify-center bg-gray-100"> | |
<h1 class="text-2xl font-bold text-gray-800">No Active Clients</h1> | |
</div> | |
`); | |
} | |
// Render the list of active clients using Tailwind | |
let clientListHTML = ` | |
${tailwindCDN} | |
<div class="min-h-screen bg-gray-100 py-10 px-4"> | |
<h1 class="text-4xl font-bold text-center mb-10 text-gray-800">Active Clients</h1> | |
<div class="max-w-4xl mx-auto"> | |
<ul class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6"> | |
`; | |
// Loop through each client and create a link for each one | |
clientKeys.forEach(clientId => { | |
clientListHTML += ` | |
<li class="bg-white shadow-md rounded-lg p-6 hover:shadow-lg transition duration-300 ease-in-out"> | |
<a href="/clientCSS/${clientId}" class="block text-lg font-semibold text-blue-600 hover:text-blue-800"> | |
Client ID: ${clientId} | |
Session Name : ${clients[clientId].sessionId ?? "No Session Name"} | |
</a> | |
</li> | |
`; | |
}); | |
clientListHTML += ` | |
</ul> | |
</div> | |
</div> | |
`; | |
// Send the rendered HTML response | |
res.send(clientListHTML); | |
}); | |
// Route to render the client's page | |
app.get('/client/:id', (req, res) => { | |
const client = clients[req.params.id]; | |
if (client) { | |
res.send(client.html); | |
} else { | |
res.status(404).send('Client not found'); | |
} | |
}); | |
app.get('/clientCSS/: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>`); | |
//remove all script tags | |
htmlContent = htmlContent.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ""); | |
//enable copy paste | |
htmlContent = htmlContent.replace(/-webkit-user-select: none;/gi, ""); | |
htmlContent = htmlContent.replace(/user-select: none;/gi, ""); | |
htmlContent = htmlContent.replace(/-moz-user-select: none;/gi, ""); | |
htmlContent = htmlContent.replace(/-ms-user-select: none;/gi, ""); | |
htmlContent = htmlContent.replace(/-o-user-select: none;/gi, ""); | |
//enable right click | |
htmlContent = htmlContent.replace(/oncontextmenu="return false;"/gi, ""); | |
htmlContent = htmlContent.replace(/onselectstart="return false;"/gi, ""); | |
htmlContent = htmlContent.replace(/onselect="return false;"/gi, ""); | |
htmlContent = htmlContent.replace(/ondragstart="return false;"/gi, ""); | |
htmlContent = htmlContent.replace(/onmousedown="return false;"/gi, ""); | |
htmlContent = htmlContent.replace(/onmouseup="return false;"/gi, ""); | |
htmlContent = htmlContent.replace(/onselectstart="return false;"/gi, ""); | |
htmlContent = htmlContent.replace(/onselect="return false;"/gi, ""); | |
htmlContent = htmlContent.replace(/oncopy="return false;"/gi, ""); | |
//add css to allow copy paste | |
//add css to allow right click | |
//add custom js code | |
htmlContent = htmlContent.replace('</body>', `<script> | |
function addGlobalStyle() { | |
const style = document.createElement('style'); | |
style.innerHTML = ` + `"* { user-select: text !important; -webkit-user-select: text !important; -ms-user-select: text !important; cursor: text !important; }"` + `; | |
document.head.appendChild(style); | |
} | |
function enableCopyPaste() { | |
document.oncopy = null; | |
document.onpaste = null; | |
document.oncut = null; | |
document.oncontextmenu = null; | |
document.onselectstart = null; | |
// Also enabling right-click | |
document.addEventListener('contextmenu', function(e) { | |
e.stopPropagation(); // Stop propagation of right-click blocking | |
}, true); | |
} | |
// Wait for the page to load before enabling copy-paste | |
window.addEventListener('DOMContentLoaded', (event) => { | |
enableCopyPaste(); | |
addGlobalStyle(); | |
}); | |
</script></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}`); | |
}); |