293 lines
8.2 KiB
JavaScript
293 lines
8.2 KiB
JavaScript
const express = require("express")
|
|
const router = express.Router()
|
|
const rcctalk = require("./../../thumbnailrcctalk")
|
|
const rcctalk2018 = require("./../../rcctalk2018")
|
|
const fs = require("fs")
|
|
const assetrenderscript = fs.readFileSync("assetthumbnailrenderer.lua", "utf-8")
|
|
var path = require("path")
|
|
const User = require("./../../model/user.js")
|
|
const item = require("./../../model/item.js")
|
|
var rgx = /^[0-9]*\.?[0-9]*$/
|
|
router.use(express.json({ limit: "200mb" }))
|
|
const { requireAuth } = require("./../../middleware/authmiddleware.js")
|
|
const { grabAuth } = require("./../../middleware/grabauth.js")
|
|
const fetch = (...args) =>
|
|
import("node-fetch").then(({ default: fetch }) => fetch(...args))
|
|
require("dotenv").config()
|
|
const RCC_HOST = process.env.RCC_HOST
|
|
const rateLimit = require("express-rate-limit")
|
|
const limiter = rateLimit({
|
|
windowMs: 2 * 1000, // 5 seconds
|
|
max: 1, // Limit each IP to 1 requests per `window`
|
|
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
|
|
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
|
|
handler: (request, response, next, options) => {
|
|
return response.sendFile(path.resolve("./assets/default.png"))
|
|
},
|
|
})
|
|
|
|
router.get("/", grabAuth, async (req, res) => {
|
|
if (!req.query.id && !req.query.userId) {
|
|
return res.status(400)
|
|
}
|
|
let headshot = false
|
|
if (req.query.type === "headshot") {
|
|
headshot = true
|
|
}
|
|
let id = req.query.id ?? req.query.userId
|
|
|
|
var sanitizedid = id.match(rgx)
|
|
|
|
const user = await User.findOne({ userid: sanitizedid }).lean()
|
|
if (!user) {
|
|
return res.json({ status: "error", error: "User does not exist" })
|
|
}
|
|
|
|
// lets get our file path with sanitized id
|
|
let path2 = path.resolve(
|
|
__dirname,
|
|
"../../assets/userthumbnails/" + sanitizedid + ".png",
|
|
)
|
|
if (headshot === true) {
|
|
path2 = path.resolve(
|
|
__dirname,
|
|
"../../assets/userthumbnailsheadshots/" + sanitizedid + ".png",
|
|
)
|
|
}
|
|
|
|
fs.access(path2, fs.F_OK, async err => {
|
|
if (err) {
|
|
let newrender = await rcctalk2018.OpenRender(sanitizedid, headshot)
|
|
if (newrender.error) {
|
|
return res.sendFile(path.resolve("./assets/default.png"))
|
|
}
|
|
newrender =
|
|
newrender["SOAP-ENV:Envelope"]["SOAP-ENV:Body"][
|
|
"ns1:OpenJobResponse"
|
|
]["ns1:OpenJobResult"][0]["ns1:value"]._text
|
|
|
|
res.writeHead(200, { "Content-Type": "image/png" })
|
|
|
|
fs.writeFile(path2, newrender, "base64", function (err) {
|
|
if (err) {
|
|
console.log("error")
|
|
}
|
|
})
|
|
return res.end(Buffer.from(newrender, "base64"))
|
|
|
|
// if this timeouts and rcc doesn't return the image feor some reason then send the default fallback
|
|
//return res.sendFile(path.resolve("./assets/default.png"))
|
|
}
|
|
|
|
//file exists
|
|
if (
|
|
req.query.method &&
|
|
req.userdocument &&
|
|
req.userdocument.userid == sanitizedid
|
|
) {
|
|
// don't allow unauthenticated users to regenerate avatars and don't allow authenticated users to regenerate other peoples avatars
|
|
if (req.query.method === "regenerate") {
|
|
fs.unlink(path2, async function (err) {
|
|
if (err) {
|
|
console.log(err)
|
|
}
|
|
|
|
let newrender = await rcctalk2018.OpenRender(
|
|
sanitizedid,
|
|
headshot,
|
|
)
|
|
if (newrender.error) {
|
|
return res.sendFile(
|
|
path.resolve("./assets/default.png"),
|
|
)
|
|
}
|
|
newrender =
|
|
newrender["SOAP-ENV:Envelope"]["SOAP-ENV:Body"][
|
|
"ns1:OpenJobResponse"
|
|
]["ns1:OpenJobResult"][0]["ns1:value"]._text
|
|
|
|
res.writeHead(200, { "Content-Type": "image/png" })
|
|
|
|
fs.writeFile(path2, newrender, "base64", function (err) {
|
|
if (err) {
|
|
console.log("error")
|
|
}
|
|
})
|
|
return res.end(Buffer.from(newrender, "base64"))
|
|
})
|
|
}
|
|
} else {
|
|
res.sendFile(path.resolve(path2))
|
|
return
|
|
}
|
|
})
|
|
})
|
|
|
|
router.post("/rcc", (req, res) => {
|
|
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
|
|
if (ip == RCC_HOST || ip == "::ffff:" + RCC_HOST) {
|
|
const { player, thumbnail } = req.body
|
|
let path2 = path.resolve(
|
|
__dirname,
|
|
"../../assets/userthumbnails/" + player + ".png",
|
|
)
|
|
fs.writeFile(path2, thumbnail, "base64", function (err) {
|
|
if (err) {
|
|
console.log("error")
|
|
// if writing fails we can still fallback
|
|
return res.sendFile(path.resolve("./../../assets/default.png"))
|
|
}
|
|
// if it succeeds then we can send the userthumbnail
|
|
// close the job after
|
|
rcctalk.CloseJob("Thumbnailfor" + player)
|
|
})
|
|
}
|
|
})
|
|
|
|
router.get(["/asset", "/asset.ashx"], grabAuth, async (req, res) => {
|
|
if (!req.query.id && !req.query.assetid) {
|
|
return res.status(400)
|
|
}
|
|
let id = req.query.id ?? req.query.assetid
|
|
|
|
var sanitizedid = id.match(rgx)
|
|
|
|
const user = await item.findOne({ ItemId: sanitizedid }).lean()
|
|
if (!user) {
|
|
return res.json({ status: "error", error: "Item does not exist" })
|
|
}
|
|
if (user.Type === "Audio") {
|
|
return res.sendFile(path.resolve("./assets/images/audio.png"))
|
|
}
|
|
if (user.Hidden === true) {
|
|
// if item isn't supposed to have a thumbnail
|
|
return res.sendFile(path.resolve("./assets/moderated.png"))
|
|
}
|
|
if (user.approved === false && !req.query.nonapproved) {
|
|
return res.sendFile(path.resolve("./assets/approval.png"))
|
|
}
|
|
if (req.query.nonapproved && req?.userdocument?.admin === false) {
|
|
// we only want admins to be able to see non approved assets anyways
|
|
return res.sendFile(path.resolve("./assets/approval.png"))
|
|
}
|
|
if (
|
|
req.query.nonapproved &&
|
|
(user.Type === "Pants" || user.Type === "Shirts")
|
|
) {
|
|
sanitizedid -= 1
|
|
return res.sendFile(
|
|
path.resolve(
|
|
__dirname,
|
|
"../../assets/ugc/itemfile-" + sanitizedid + ".rbxm",
|
|
),
|
|
)
|
|
}
|
|
if (req.query.nonapproved && user.Type === "Video") {
|
|
return res.sendFile(
|
|
path.resolve(
|
|
__dirname,
|
|
"../../assets/ugc/itemfile-" + sanitizedid + ".rbxm",
|
|
),
|
|
)
|
|
}
|
|
if (user.Type === "Video") {
|
|
return res.sendFile(path.resolve("./assets/video.png"))
|
|
}
|
|
if (user.Type === "User Ad" || user.Type === "Gamepass") {
|
|
try {
|
|
await fs.promises.access(
|
|
path.resolve(
|
|
__dirname,
|
|
"../../assets/ugc/itemfile-" + sanitizedid + ".rbxm",
|
|
),
|
|
fs.constants.W_OK,
|
|
)
|
|
return res.sendFile(
|
|
path.resolve(
|
|
__dirname,
|
|
"../../assets/ugc/itemfile-" + sanitizedid + ".rbxm",
|
|
),
|
|
)
|
|
} catch {
|
|
return res.sendFile(
|
|
path.resolve("./assets/images/defaultadsky.png"),
|
|
)
|
|
}
|
|
}
|
|
|
|
// lets get our file path with sanitized id
|
|
let path2 = path.resolve(
|
|
__dirname,
|
|
"../../assets/ugc/asset-" + sanitizedid + ".png",
|
|
)
|
|
|
|
fs.access(path2, fs.F_OK, async err => {
|
|
if (err) {
|
|
// get our renderscript with the new character app
|
|
var newrenderscript = assetrenderscript.replace(
|
|
"local asset = 0",
|
|
'local asset = "' + sanitizedid + '"',
|
|
)
|
|
//open a new job for our thumbnail render request
|
|
var response = await rcctalk.OpenJob(
|
|
"Thumbnailfor" + sanitizedid,
|
|
newrenderscript,
|
|
"120",
|
|
)
|
|
if (
|
|
response["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["SOAP-ENV:Fault"]
|
|
) {
|
|
// if failed then print out error close job then send a fallback image
|
|
//console.dir(response,{ depth: null })
|
|
rcctalk.CloseJob("Thumbnailfor" + sanitizedid)
|
|
return res.sendFile(path.resolve("./assets/default.png"))
|
|
} else {
|
|
// send image to user
|
|
// wait for image to be uploaded by rcc
|
|
function check() {
|
|
setTimeout(() => {
|
|
fs.access(path2, fs.constants.F_OK, error => {
|
|
if (error) {
|
|
check()
|
|
} else {
|
|
return res.sendFile(path2)
|
|
}
|
|
})
|
|
}, 3000)
|
|
}
|
|
}
|
|
check()
|
|
|
|
// if this timeouts and rcc doesn't return the image feor some reason then send the default fallback
|
|
return res.sendFile(path.resolve("./assets/default.png"))
|
|
}
|
|
|
|
res.sendFile(path.resolve(path2))
|
|
return
|
|
})
|
|
})
|
|
|
|
router.post("/rccasset", (req, res) => {
|
|
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
|
|
if (ip == RCC_HOST || ip == "::ffff:" + RCC_HOST) {
|
|
const { asset, thumbnail } = req.body
|
|
console.log(asset)
|
|
let path2 = path.resolve(
|
|
__dirname,
|
|
"../../assets/ugc/asset-" + asset + ".png",
|
|
)
|
|
fs.writeFile(path2, thumbnail, "base64", function (err) {
|
|
if (err) {
|
|
console.log("error")
|
|
// if writing fails we can still fallback
|
|
return res.sendFile(path.resolve("./../../assets/default.png"))
|
|
}
|
|
// if it succeeds then we can send the userthumbnail
|
|
// close the job after
|
|
rcctalk.CloseJob("Thumbnailforasset" + asset)
|
|
})
|
|
}
|
|
})
|
|
|
|
module.exports = router
|