198 lines
5.1 KiB
JavaScript
198 lines
5.1 KiB
JavaScript
const { response } = require("express")
|
|
const express = require("express")
|
|
const router = express.Router()
|
|
const fs = require("fs")
|
|
var path = require("path")
|
|
const crypto = require("crypto")
|
|
require("dotenv").config()
|
|
const RCC_HOST = process.env.RCC_HOST
|
|
const ACCESS_KEY = process.env.ACCESS_KEY
|
|
const User = require("../model/user.js")
|
|
const catalog = require("../model/item")
|
|
const games = require("./../model/games.js")
|
|
const fetch = (...args) =>
|
|
import("node-fetch").then(({ default: fetch }) => fetch(...args))
|
|
|
|
//redirect hmmmm
|
|
var rgx = /^[0-9]*\.?[0-9]*$/
|
|
router.get("/", async (req, res) => {
|
|
if (req.query.name) {
|
|
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 =
|
|
`<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
|
|
<External>null</External>
|
|
<External>nil</External>
|
|
<Item class="BodyColors">
|
|
<Properties>
|
|
<int name="HeadColor">` +
|
|
user.colors.find(x => x.name === "Head").value +
|
|
`</int>
|
|
<int name="LeftArmColor">` +
|
|
user.colors.find(x => x.name === "Left Arm").value +
|
|
`</int>
|
|
<int name="LeftLegColor">` +
|
|
user.colors.find(x => x.name === "Left Leg").value +
|
|
`</int>
|
|
<string name="Name">Body Colors</string>
|
|
<int name="RightArmColor">` +
|
|
user.colors.find(x => x.name === "Right Arm").value +
|
|
`</int>
|
|
<int name="RightLegColor">` +
|
|
user.colors.find(x => x.name === "Right Leg").value +
|
|
`</int>
|
|
<int name="TorsoColor">` +
|
|
user.colors.find(x => x.name === "Torso").value +
|
|
`</int>
|
|
<bool name="archivable">true</bool>
|
|
</Properties>
|
|
</Item>
|
|
</roblox>`
|
|
|
|
return res.send(colorsxml)
|
|
}
|
|
if (
|
|
req.query.method ||
|
|
/*req.headers?.["requester"] === "Server" &&*/ req.headers?.[
|
|
"assettype"
|
|
] === "Place"
|
|
) {
|
|
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
|
|
console.log(ip)
|
|
var sanitizedid = req.query.id.match(rgx)
|
|
if (ip === RCC_HOST || ip === "::ffff:" + RCC_HOST) {
|
|
console.log(req.headers["accesskey"])
|
|
if (req.headers?.["accesskey"] === ACCESS_KEY) {
|
|
fs.access(
|
|
"./assets/ugc/gamefile-" + sanitizedid + ".rbxl",
|
|
fs.F_OK,
|
|
err => {
|
|
if (err) {
|
|
res.status(404).send("not found")
|
|
return
|
|
}
|
|
|
|
//file exists
|
|
res.sendFile(
|
|
path.resolve(
|
|
"./assets/ugc/gamefile-" +
|
|
sanitizedid +
|
|
".rbxl",
|
|
),
|
|
)
|
|
return
|
|
},
|
|
)
|
|
}
|
|
}
|
|
return res.status(401).end()
|
|
} else {
|
|
if (!req.query.id) {
|
|
req.query.id = req.query.assetversionid
|
|
}
|
|
if (isNaN(parseFloat(req.query.id)) === true) {
|
|
res.writeHead(302, {
|
|
Location:
|
|
"https://assetdelivery.roblox.com/v1/asset?id=" +
|
|
req.query.id,
|
|
})
|
|
return res.end()
|
|
}
|
|
var sanitizedid = parseFloat(req.query.id)
|
|
const response = await catalog.findOne({ ItemId: sanitizedid }).lean()
|
|
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
|
|
if (
|
|
response?.approved === false &&
|
|
(ip != RCC_HOST || ip === "::ffff:" + RCC_HOST) &&
|
|
!req.query.nonapproved
|
|
) {
|
|
return res.status(401).end()
|
|
}
|
|
//this will only allow numbers in our system so that we don't allow nodejs to expose our whole server filesystem
|
|
fs.access(
|
|
"./assets/ugc/itemfile-" + sanitizedid + ".rbxm",
|
|
fs.F_OK,
|
|
async err => {
|
|
//console.log("./assets/ugc/itemfile-"+sanitizedid+".rbxm")
|
|
if (err) {
|
|
if (
|
|
req.headers?.["user-agent"]?.includes("Android") ===
|
|
true ||
|
|
req.headers?.["user-agent"]?.includes("iPhone") === true
|
|
) {
|
|
const response = await fetch(
|
|
"https://assetdelivery.roblox.com/v1/assetId/" +
|
|
req.query.id,
|
|
{ headers: { "User-Agent": "Roblox/WinInet" } },
|
|
)
|
|
const data = await response.json()
|
|
if (data) {
|
|
if (data.location) {
|
|
res.writeHead(302, { Location: data.location })
|
|
res.end()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
if (req.query.id === "507766666") {
|
|
// 2018 r15 animation use legacy
|
|
res.writeHead(302, {
|
|
Location:
|
|
"https://assetdelivery.roblox.com/v1/asset?id=" +
|
|
req.query.id +
|
|
"&version=3",
|
|
})
|
|
return res.end()
|
|
}
|
|
if (req.query.id === "507766388") {
|
|
res.writeHead(302, {
|
|
Location:
|
|
"https://assetdelivery.roblox.com/v1/asset?id=" +
|
|
req.query.id +
|
|
"&version=2",
|
|
})
|
|
return res.end()
|
|
}
|
|
if (req.query.id === "62633901") {
|
|
return res.sendFile(
|
|
path.resolve(
|
|
"./assets/ugc/common/itemfile-" +
|
|
sanitizedid +
|
|
".rbxm",
|
|
),
|
|
)
|
|
}
|
|
res.writeHead(302, {
|
|
Location:
|
|
"https://assetdelivery.roblox.com/v1/asset?id=" +
|
|
req.query.id,
|
|
})
|
|
res.end()
|
|
return
|
|
}
|
|
|
|
res.sendFile(
|
|
path.resolve(
|
|
"./assets/ugc/itemfile-" + sanitizedid + ".rbxm",
|
|
),
|
|
)
|
|
return
|
|
},
|
|
)
|
|
}
|
|
})
|
|
|
|
module.exports = router
|