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.use(express.json()); app.set('trust proxy', true); app.use((req, res, next) => { // Request logger for debugging //console.log(`[${new Date().toLocaleString()}] ${req.method} ${req.path} from ${req.ip} with ${JSON.stringify(req.body)}`); next(); }); app.put('/api/connect/:jobid', (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(req.body.url); ws_[id].connection.on('message', function(data) { ws_[id].message = data; }) ws_[id].connection.on('close', function() { if (ws_[id]) { ws_[id].connection.terminate(); delete ws_[id]; } }) ws_[id].open = false; ws_[id].connection.on('open', () => { ws_[id].open = true; }); ws_[id].connection.on("error", () => { res.status(500); }) res.send(id); }); app.post("/api/send/:jobid/:id/", (req, res) => { if (!ws_[req.params.id]) { res.status(404).send({ success: false, message: "Invalid ID" }); return; } 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; // Catch if body is not json data if (!req.body.data) { res.status(400).send({ success: false, message: "No data provided" }); return; } if (stats.open == true) { socket.send(req.body.data); } else { socket.on('open', () => { socket.send(req.body.data); }); } res.send({ success: true }); }) app.get("/api/poll/:jobid/:id", (req, res) => { if (!ws_[req.params.id]) { res.status(404).send({ success: false, message: "Invalid ID" }); return; } 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.delete("/api/close/:jobid/:id", (req, res) => { var id = req.params.id; if (ws_[id]) ws_[id].connection.terminate(); delete ws_[id]; res.send({ success: true }); }) // Catch rejections and exceptions process.on('unhandledRejection', (err) => { console.error(err); }); process.on('uncaughtException', (err) => { console.error(err); }); app.listen(PORT, () => { console.log('server started'); });