const express = require("express") const router = express.Router() const signatures = require("./signatures.js") const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); const User = require('../model/user.js') const { requireAuth } = require('../middleware/authmiddlewaregame') const rcctalk = require('../rcctalk') const games = require('../model/games.js') const catalog = require('../model/item.js') const rcc = require('../model/rcc.js') var sanitize = require('mongo-sanitize'); const { getPort, checkPort, getRandomPort, waitForPort } = require('get-port-please') const fs = require('fs') const gamescript = fs.readFileSync('actualgameserver.lua','utf-8') require('dotenv').config() const RCC_HOST = process.env.RCC_HOST const logshook = process.env.logshook const crypto = require('crypto'); const key = fs.readFileSync('DefaultPrivateKey.pem') const key2 = fs.readFileSync('DefaultPrivateKey.pem') const key2020 = fs.readFileSync('PrivateKey2020.txt') const { _2020placelauncher } = require('../routes/2020/game') const { _2018placelauncher } = require('../routes/2018/game') //join and placelauncher function sleep(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } router.get("/visit",async (req, res) => { // studio const string = `local RS = game:GetService("RunService") local P = game:GetService("Players") local LP = P:CreateLocalPlayer(0) LP.CharacterAppearance = "" LP.CharacterAdded:connect( function(c) repeat wait() until c:FindFirstChild("Humanoid") local h = c:FindFirstChild("Humanoid") h.Died:connect( function() wait(5) LP:LoadCharacter() end ) end ) game:GetService("InsertService"):SetBaseSetsUrl("http://mete0r.xyz/Game/Tools/InsertAsset.ashx?nsets=10&type=base") game:GetService("InsertService"):SetUserSetsUrl("http://mete0r.xyz/Game/Tools/InsertAsset.ashx?nsets=20&type=user&userid=%d") game:GetService("InsertService"):SetCollectionUrl("http://mete0r.xyz/Game/Tools/InsertAsset.ashx?sid=%d") pcall(function() game:GetService("InsertService"):SetFreeModelUrl("http://mete0r.xyz/Game/Tools/InsertAsset.ashx?type=fm&q=%s&pg=%d&rs=%d") end) pcall(function() game:GetService("InsertService"):SetFreeDecalUrl("http://mete0r.xyz/Game/Tools/InsertAsset.ashx?type=fd&q=%s&pg=%d&rs=%d") end) RS:Run() LP:LoadCharacter() pcall( function() game:GetService("ContentProvider"):SetBaseUrl("http://mete0r.xyz" .. "/") end ) ` const sign = crypto.createSign('SHA1'); sign.update("\r\n" + string) var signature = sign.sign(key, "base64") res.send("--rbxsig%"+signature+"%\r\n" +string) }) router.get(["/GetCurrentUser","/GetCurrentUser.ashx"],async (req, res) => { res.send("1") // 1 means logged in and null means logged out }) // don't send 404 error but i don't think we will have studio publishing router.post("/validate-machine",async (req, res) => { res.json({"success":true,"message":""}) }) router.get(["/join","/join.ashx"],requireAuth,async (req, res) => { if (!req.userdocument.discordid){ return res.json({status:"error",error:"Link your discord account stinky"}) } if (req.query.ver === "2018"){ if (!req.userdocument.gamejoin2018 || req.userdocument.gamejoin2018 === "{}"){ return res.json({status:"error",error:"no placelauncher"}) } var joinJson = JSON.parse(req.userdocument.gamejoin2018) req.userdocument.gamejoin2018 = undefined req.userdocument.markModified('gamejoin2018') await req.userdocument.save() //sign with our sign module var signature = signatures.signer(joinJson) //console.log(signature) return res.send("--rbxsig%"+signature+"%\r\n"+JSON.stringify(joinJson)) } if (req.query.ver === "2020"){ if (!req.userdocument.gamejoin2020 || req.userdocument.gamejoin2020 === "{}"){ return res.json({status:"error",error:"no placelauncher"}) } var joinJson = JSON.parse(req.userdocument.gamejoin2020) req.userdocument.gamejoin2020 = undefined req.userdocument.markModified('gamejoin2020') await req.userdocument.save() //sign with our sign module const sign = crypto.createSign('SHA1'); sign.update("\r\n" + JSON.stringify(joinJson)) var signature = sign.sign(key2020, "base64") //console.log(signature) return res.send("--rbxsig2%"+signature+"%\r\n"+JSON.stringify(joinJson)) } if (!req.userdocument.gamejoin || req.userdocument.gamejoin === "{}"){ return res.json({status:"error",error:"no placelauncher"}) } var joinJson = JSON.parse(req.userdocument.gamejoin) req.userdocument.gamejoin = undefined req.userdocument.markModified('gamejoin') await req.userdocument.save() //sign with our sign module var signature = signatures.signer(joinJson) //console.log(signature) res.send("--rbxsig%"+signature+"%\r\n"+JSON.stringify(joinJson)) }) router.all(["/placelauncher","/placelauncher.ashx"],requireAuth,_2020placelauncher,_2018placelauncher,async (req, res, next) => { var enabled = req.config if (enabled.GamesEnabled === false){ return res.json({status:"error",error:"Games are disabled bad boy"}) } var joinJson = {"ClientPort":0,"MachineAddress":"localhost","ServerPort":25564,"PingUrl":"","PingInterval":120,"UserName":"default","SeleniumTestMode":false,"UserId":0,"SuperSafeChat":false,"CharacterAppearance":"http://shitncumblox.gq/game/charapp?name=default","ClientTicket":"","GameId":1,"PlaceId":1818,"MeasurementUrl":"","WaitingForCharacterGuid":"cad99b30-7983-434b-b24c-eac12595e5fd","BaseUrl":"http://www.mete0r.xyz/","ChatStyle":"ClassicAndBubble","VendorId":0,"ScreenShotInfo":"","VideoInfo":"GamesROBLOX, video, free game, online virtual world","CreatorId":0,"CreatorTypeEnum":"User","MembershipType":"None","AccountAge":365,"CookieStoreFirstTimePlayKey":"rbx_evt_ftp","CookieStoreFiveMinutePlayKey":"rbx_evt_fmp","CookieStoreEnabled":true,"IsRobloxPlace":false,"GenerateTeleportJoin":false,"IsUnknownOrUnder13":false,"SessionId":"c25fd620-bbaa-4fb2-b022-3f053cdd1abd|00000000-0000-0000-0000-000000000000|0|204.236.226.210|8|2016-08-17T01:05:05.7115837Z|0|null|null|null|null","DataCenterId":0,"UniverseId":0,"BrowserTrackerId":0,"UsePortraitMode":false,"FollowUserId":0,"CharacterAppearanceId":1} if (!req.query.name && !req.query.placeId){ return res.json({status:"error",error:"no placeid bad"}) } if (req.userdocument.gamejoin){ return res.json({"jobId":"Test","status":2,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?auth="+req.query.auth??req.cookies.jwt,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""}) } var sanitizedplaceid = sanitize(req.query.name??req.query.placeId) const game = await games.findOne({idofgame: sanitizedplaceid}).lean() if (!game){ return res.json({status:"error",error:"that game doesn't exist!"}) } if (game.version != "2016"){ return res.json({status: "error",error:"game version is different than client requested"}) } const instance = await rcc.findOne({PlaceId: sanitizedplaceid}).lean() if (instance && instance.Status === 2){ // if an rcc instance already exists we don't need to create a new one so we will just drag them into the existing game joinJson.UserName = req.userdocument.username joinJson.UserId = req.userdocument.userid joinJson.CharacterAppearance = "http://mete0r.xyz/game/charapp?name=" + req.userdocument.userid joinJson.MachineAddress = RCC_HOST // need to put rcc host here lol joinJson.ServerPort = instance.Port joinJson.PlaceId = instance.PlaceId joinJson.GameId = sanitizedplaceid joinJson.CharacterAppearanceId = req.userdocument.userid joinJson.MembershipType = req.userdocument.membership joinJson.CreatorId = game.useridofowner joinJson.SessionId = req.query.auth??req.cookies.jwt const timestamp = Date.now() joinJson.ClientTicket = timestamp+";" // timestamp //create signature 1 const sign1 = crypto.createSign('SHA1'); sign1.update(`${req.userdocument.userid}\n`/*userid*/+`${req.userdocument.username}\n`/*username*/+`http://mete0r.xyz/game/charapp?name=${req.userdocument.userid}\n`/*charapp*/+`game${sanitizedplaceid}\n`/*jobid*/+ timestamp/*timestamp*/) var signature1 = sign1.sign(key, "base64") joinJson.ClientTicket += signature1 + ";" //create signature 2 const sign2 = crypto.createSign('SHA1'); sign2.update(`${req.userdocument.userid}\n`/*userid*/+`game${sanitizedplaceid}\n`/*jobid*/+ timestamp/*timestamp*/) var signature2 = sign2.sign(key, "base64") joinJson.ClientTicket += signature2 req.userdocument.gamejoin = JSON.stringify(joinJson) req.userdocument.markModified('gamejoin') await req.userdocument.save() var joinScriptJson = {"jobId":"Test","status":2,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?auth="+joinJson.SessionId,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""} return res.send(JSON.stringify(joinScriptJson)) } if (instance && instance.Status === 1){ var joinScriptJson = {"jobId":"Test","status":1,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?auth="+joinJson.SessionId,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""} return res.send(JSON.stringify(joinScriptJson)) } var port = await getPort({random: true}) var newgamescript = "local placeId = "+sanitizedplaceid+"\n"+ gamescript newgamescript = "local port = "+port+"\n"+ newgamescript // launch job var response = await rcctalk.OpenJob("game"+sanitizedplaceid,newgamescript,"99999") await rcc.create({ PlaceId: sanitizedplaceid, Port: port, Status: 1 // 1 means loading }) //console.log(newrenderscript) var joinScriptJson = {"jobId":"Test","status":1,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?auth="+joinJson.SessionId,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""} res.send(JSON.stringify(joinScriptJson)) } ) //charapp and colors stealing from roblox router.get("/charapp", async (req, res) => { if (Object.keys(req.query).length === 0) { res.status(404).send('No variables :('); } else{ const user = await User.findOne({userid: req.query.name}).lean() const placeid = req.headers?.['roblox-place-id']??0 const placedoc = await games.findOne({idofgame: placeid}) if (!placedoc){ return res.json({status:"error",error:"Place not found."}) } if (!user) { return res.json({status: 'error', error: 'User not found!'}) } if (!user.inventory){ if (req.query.rcc){ return res.json([]) } return res.send('http://mete0r.xyz/game/colors?name='+req.query.name+';') } if (req.query.rcc){ var empty = [] for (var key of user.inventory) { if (key.Equipped === true){ empty.push({"item": {itemid: key.ItemId, type: key.Type}}) } } return res.json(empty) } var charapp = 'http://mete0r.xyz/asset?name='+req.query.name+';' // add to charapp string by adding json to it for (var key of user.inventory) { if (key.Equipped === true){ if (placedoc.gearallowed??false === true){ charapp += "http://mete0r.xyz/asset?id=" + key.ItemId + ";" }else{ if (key.Type != "Gears"){ charapp += "http://mete0r.xyz/asset?id=" + key.ItemId + ";" } } } } res.write(charapp) res.end() } }) router.get("/colors", async (req, res) => { if (Object.keys(req.query).length === 0) { res.status(404).send('No variables :('); } else{ const user = await User.findOne({userid: req.query.name}).lean() if (!user) { return res.json({status: 'error', error: 'User not found!'}) } if (req.query.rcc){ var empty = [] for (var key of user.colors) { empty.push(key.value) } return res.json(empty) } res.type('application/xml'); var colorsxml = ` null nil `+user.colors.find(x => x.name === 'Head').value+` `+user.colors.find(x => x.name === 'Left Arm').value+` `+user.colors.find(x => x.name === 'Left Leg').value+` Body Colors `+user.colors.find(x => x.name === 'Right Arm').value+` `+user.colors.find(x => x.name === 'Right Leg').value+` `+user.colors.find(x => x.name === 'Torso').value+` true ` res.send(colorsxml) } }) router.get("/", (req, res) => { res.status(404).send('hmmm? kinda sus'); }) router.get("/players/:id", (req, res) => { res.json({"ChatFilter":"whitelist"}) }) router.post("/load-place-info", (req, res) => { res.json({"CreatorId": 0, "CreatorType": "User", "PlaceVersion": 1}) }) router.post("/badge/awardbadge",async (req, res) => { const userid = req.query.UserID const badgeid = req.query.BadgeID const placeid = req.query.PlaceID const badge = await catalog.findOne({ItemId: badgeid}).lean() const user = await User.findOne({userid: userid}).lean() if(!badge){ //Badge doesn't exist! return res.send("0") } if(!user){ return res.send("0") } const badgecreator = await User.findOne({userid: badge.Creator}).lean() if (typeof user.badges !== "undefined"){ // check if user already owns item for (var v of user.badges){ if (v.badgeid === badgeid){ // they already own it return res.send("0") } } } User.updateOne({userid: req.query.UserID}, { $push: { badges: {badgeid: badgeid, badgename: badge.Name, creator: badge.Creator, placeid: placeid} } }, function(err, doc) { if (err){ return res.send("0") } }) return res.send(user.username+" won "+badgecreator.username+"'s "+badge.Name+" award!") }) router.get(["/LuaWebService/HandleSocialRequest","/LuaWebService/HandleSocialRequest.ashx"],async (req, res) => { res.type('application/xml'); if (req.query.method === "IsInGroup"){ if (req.query.groupid === '0' || req.query.groupid === '1200769'){ // 1200769 admin group const user = await User.findOne({userid: req.query.playerid}).lean() if (user){ return res.send(`${user.admin}`) } } return res.send('false') } if (req.query.method === "GetGroupRank"){ if (req.query.groupid === '0'|| req.query.groupid === '1200769'){ const user = await User.findOne({userid: req.query.playerid}).lean() if (user){ if (user.admin === true){ return res.send(`255`) } } } return res.send('0') } if (req.query.method === "IsBestFriendsWith"){ return res.send('false') } if (req.query.method === "IsFriendsWith"){ return res.send('false') } res.type('html'); return res.status(404).end() }) router.get("/Tools/InsertAsset.ashx",async (req, res) => { const lol = await fetch('http://sets.pizzaboxer.xyz/Game'+req.url); if (lol.status === 400){ return res.send(``) } return res.send(await lol.text()) }) router.post("/MachineConfiguration.ashx", (req,res) => { res.json({"success": true}) }) module.exports = router