AudioDownloadAPI/index.js

183 lines
4.4 KiB
JavaScript

require("dotenv").config()
const express = require("express")
const codes = require("./codes.json");
const app = express()
const fs = require("fs");
const port = process.env.SERVER_PORT || 3000;
app.use(express.json());
app.set("trust proxy", 1);
// if blacklist doesnt exist, make the file
if (!fs.existsSync("./blacklist.json")) {
fs.writeFileSync("./blacklist.json", "[]");
}
app.use((req, res, next) => { // Blacklist handler
const blacklist = JSON.parse(fs.readFileSync("./blacklist.json", "utf-8"));
if (blacklist.includes(req.ip)) {
console.log(`[${new Date().toLocaleString()}] ${req.ip} ${req.method} ${req.url} - Blacklisted`);
return res.status(403).json({
code: 403,
message: codes[403].message,
additional: codes[403].description
});
}
console.log(`[${new Date().toLocaleString()}] ${req.ip} ${req.method} ${req.url}`);
next();
})
var rateLimits = {};
app.get("/", (req, res) => {
// load index
res.sendFile(__dirname + "/static/index.html")
});
app.post("/", async (req, res) => {
// Impliment a rate limit of 25 requests per minute
const ip = req.ip;
console.log(rateLimits[ip])
if (!rateLimits[ip]) {
rateLimits[ip] = {
count: 0,
lastRequest: Date.now()
};
}
const limit = rateLimits[ip];
const now = Date.now();
if (now - limit.lastRequest > 60000) {
limit.count = 0;
limit.lastRequest = now;
}
if (limit.count >= 25) {
return res.status(429).json({
code: 429,
error: "Rate limit exceeded",
status: "error"
});
}
limit.count++;
// Validate request body
if (!req.body.type || req.body.type !== "batching") {
return res.status(400).json({
error: "Invalid request type",
status: "error"
});
}
// Check that the body is valid json, if not throw an error
if (!req.body.data || !Array.isArray(req.body.data)) {
return res.status(400).json({
error: "Invalid data format",
status: "error"
});
}
// Build the batch request body
const batchRequests = req.body.data.map(item => {
const assetId = item;
if (!assetId) {
return {
assetId,
requestId: assetId,
status: "failure",
additional: "Missing assetId."
};
}
return {
assetId,
requestId: assetId
};
});
// If body.cookie is provided, use it, else use process.env.COOKIE
const cookie = req.body.cookie || process.env.COOKIE;
const options = {
method: 'POST',
headers: {
authority: 'assetdelivery.roblox.com',
accept: '',
'accept-language': 'en-US,en;q=0.9',
'cache-control': 'no-cache',
'content-type': 'application/json',
origin: 'https://create.roblox.com',
pragma: 'no-cache',
referer: 'https://create.roblox.com/',
'roblox-browser-asset-request': 'true',
'roblox-place-id': '0', // Use a default or placeholder value if needed
'sec-ch-ua': '"Opera GX";v="105", "Chromium";v="119", "Not?A_Brand";v="24"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0',
Cookie: `.ROBLOSECURITY=${cookie};`
},
body: JSON.stringify(batchRequests)
};
try {
let response = await fetch("https://assetdelivery.roblox.com/v1/assets/batch", options);
let json = await response.json();
//console.log(JSON.stringify(json, null, 2));
// Build the response object
const responses = req.body.data.reduce((acc, item, index) => {
const assetId = item;
if (json[index].errors) {
const errorCode = json[index].errors[0].code;
acc[assetId] = {
status: "failure",
code: errorCode,
message: codes[errorCode].message,
additional: codes[errorCode].description
};
} else if (json[index].assetTypeId !== 3) {
// Return 415, the asset isnt audio
acc[assetId] = {
status: "failure",
code: 415,
message: codes[415].message,
additional: codes[415].description
};
} else {
acc[assetId] = {
status: "success",
url: json[index].location
};
}
return acc;
}, {});
res.json({
type: "batching-response",
data: responses
});
} catch (error) {
res.status(500).json({
type: "batching-response",
data: req.body.data.reduce((acc, item) => {
acc[item] = {
status: "failure",
url: "",
additional: "Request failed"
};
return acc;
}, {})
});
}
});
app.listen(port, () => {
console.log(`Listening on ${port}`);
});