require("dotenv").config(); const Crypto = require('crypto'); const express = require('express'); const PORT = process.env.SERVER_PORT || 3000; var { WebSocket } = require('ws'); const ws_ = []; const app = express(); app.set('trust proxy', true); app.set('view engine', 'ejs'); app.get('/', (req, res) => { res.render('index'); }); app.get('/api/connect/:jobid/:url', (req, res) => { var id = btoa(Crypto.randomBytes(10).toString('base64').slice(0, 10)).replaceAll("=", ""); ws_[id] = {}; ws_[id].jobid = req.params.jobid; // Roblox server ID, checked on all requests as a sort of username alongside the ID ws_[id].message = ""; ws_[id].connection = new WebSocket(atob(req.params.url)); ws_[id].connection.on('message', function(data) { ws_[id].message = data; }) ws_[id].connection.on('close', function() { ws_[id].connection.terminate(); }) ws_[id].open = false; setInterval(() => { ws_[id].connection.on('open', () => { ws_[id].open = true; }); }) ws_[id].connection.on("error", () => { res.status(500); }) res.send(id); }); app.get("/api/send/:jobid/:id/:data", (req, res) => { if (ws_[req.params.id].jobid !== req.params.jobid) { res.status(401).send({ success: false, message: "Invalid job ID" }); return; } var id = req.params.id; var stats = ws_[id]; var socket = ws_[id].connection; req.params.data = atob(req.params.data); console.log("sent data: " + req.params.data) if (stats.open == true) { socket.send(req.params.data); } else { socket.on('open', () => { socket.send(req.params.data); }); } res.send({ success: true }); }) app.get("/api/poll/:jobid/:id", (req, res) => { if (ws_[req.params.id].jobid !== req.params.jobid) { res.status(401).send({ success: false, message: "Invalid job ID" }); return; } var socket = ws_[req.params.id]; if (!/^\s*$/.test(socket.message.toString())) { res.send(socket.message); } }) app.listen(PORT, () => { console.log('server started'); });