Progress is being made

This commit is contained in:
Christopher Cookman 2024-12-06 09:13:01 -07:00
parent 65c6991a6a
commit 8d6aa4cbe7
11 changed files with 1177 additions and 20 deletions

24
commands.js Normal file
View file

@ -0,0 +1,24 @@
// Command definitions
const Discord = require("discord.js")
module.exports = {
global: [
// Use SlashCommandBuilder for command creation
new Discord.SlashCommandBuilder()
.setName("report")
.setDescription("Report a user.")
.addNumberOption(option => option.setName("roblox_id").setDescription("The Roblox ID of the user you're reporting.").setRequired(true))
.addStringOption(option => option.setName("reason").setDescription("The reason for the report. (Please be as descriptive as possible)").setRequired(true)),
],
admin: [
new Discord.SlashCommandBuilder()
.setName("ban")
.setDescription("Ban a user.")
.setDefaultMemberPermissions(0),
new Discord.SlashCommandBuilder()
.setName("unban")
.setDescription("Unban a user.")
.addNumberOption(option => option.setName("roblox_id").setDescription("The Roblox ID of the user you're unbanning.").setRequired(true))
.setDefaultMemberPermissions(0),
]
}

View file

@ -70,6 +70,18 @@ function defineFlags(flagNames) {
}, {}); }, {});
} }
/**
* Retrieves the names of the flags that are set.
* @param {number} flags - The current set of flags.
* @param {Object} flagDefinitions - An object where keys are flag names and values are powers of 2.
* @returns {string[]} - An array of flag names that are set.
*/
function getSetFlags(flags, flagDefinitions) {
return Object.keys(flagDefinitions).filter(flagName =>
(flags & flagDefinitions[flagName]) !== 0
);
}
module.exports = { module.exports = {
addFlag, addFlag,
@ -78,5 +90,6 @@ module.exports = {
toggleFlag, toggleFlag,
hasAllFlags, hasAllFlags,
hasAnyFlag, hasAnyFlag,
defineFlags defineFlags,
getSetFlags
} }

View file

@ -1,18 +1,25 @@
// Other stuff // Other requires
const colors = require("colors");
const fs = require("fs"); const fs = require("fs");
const path = require('path'); const path = require('path');
const { execSync } = require('child_process');
const flags = require("./flags.js") const flags = require("./flags.js")
const log = require("./log");
// Legal stuff
log.info(`UBS Server (${execSync("git rev-parse --short HEAD").toString().trim()}) on ${execSync("git rev-parse --abbrev-ref HEAD").toString().trim()}`)
log.info(`\u00A9 ${new Date().getFullYear()} RTECH Consortium.`)
log.info("This software is licensed under the GNU General Public License v3.0")
log.info("This software is provided as-is with no warranty or guarantee of support.")
log.info("This software is not affiliated with Roblox Corporation.")
// Color logs
const log = {
info(msg) {
console.log(`${colors.cyan.bold("[INFO]")} ${msg}`);
}
}
// dotenv // dotenv
require("dotenv").config(); require("dotenv").config();
const noblox = require("noblox.js")
noblox.setCookie(process.env.ROBLOSECURITY)
// Express // Express
const express = require("express"); const express = require("express");
const app = new express(); const app = new express();
@ -27,11 +34,76 @@ app.use((req, res, next) => {
requestIp = req.headers["x-forwarded-for"]; requestIp = req.headers["x-forwarded-for"];
} }
fs.appendFileSync(process.env.LOGFILE, `${requestIp} - ${req.method} ${req.protocol}://${req.get('host')}${req.originalUrl} - ${req.headers["user-agent"]}\n`) fs.appendFileSync(process.env.LOGFILE, `${requestIp} - ${req.method} ${req.protocol}://${req.get('host')}${req.originalUrl} - ${req.headers["user-agent"]}\n`)
console.log(req.headers)
next() next()
}); });
// Run migrations // Flags
const reasonFlagTypes = [
"OTHER",
"LEAKER",
"TOXIC",
"SCAM",
"CHILD_SAFETY"
]
const reasonFlags = flags.defineFlags(reasonFlagTypes)
process.env.REASON_FLAGS = JSON.stringify(reasonFlags)
// Discord stuff
const Discord = require("discord.js");
const client = new Discord.Client({intents: ["Guilds", "GuildBans", "GuildMembers"]})
client.on("ready", async () => {
log.info(`Logged into Discord as ${client.user.displayName}`);
const commands = require("./commands")
// Command registration
await (async () => {
try {
const rest = new Discord.REST().setToken(client.token);
//Global
await rest.put(Discord.Routes.applicationGuildCommands(client.user.id, process.env.ADMIN_GUILD), { body: [] })
log.info(`Registering global commands`);
await rest.put(Discord.Routes.applicationCommands(client.user.id), { body: commands.global })
//Admin
log.info(`Registering admin commands`);
await rest.put(Discord.Routes.applicationGuildCommands(client.user.id, process.env.ADMIN_GUILD), { body: commands.admin })
} catch (error) {
console.error(error);
}
})();
});
client.on("interactionCreate", async (interaction) => {
// Switch by type (either slash command or modal)
switch(interaction.type) {
// Slash Command Handler
case Discord.InteractionType.ApplicationCommand:
if (!interaction.isCommand()) return;
const command = interaction.commandName;
const args = interaction.options;
switch(command) {
// Report Command
case "report":
const robloxId = args.getNumber("roblox_id");
const reason = args.getString("reason");
// TODO: Report Command
break;
};
break;
// Modal Handler
case Discord.InteractionType.ModalSubmit:
break;
}
});
// Startup
log.info("Starting up...")
require("./migrations")().then(() => { require("./migrations")().then(() => {
// Load all route modules from the 'routes' folder // Load all route modules from the 'routes' folder
const routesPath = path.join(__dirname, 'routes'); const routesPath = path.join(__dirname, 'routes');
@ -45,4 +117,5 @@ require("./migrations")().then(() => {
app.listen(port, () => { app.listen(port, () => {
log.info(`Listening on ${port}`) log.info(`Listening on ${port}`)
}) })
client.login(process.env.DISCORD_TOKEN);
}); });

9
log.js Normal file
View file

@ -0,0 +1,9 @@
const colors = require("colors");
module.exports = {
info(msg) {
console.log(`${colors.cyan.bold("[INFO]")} ${msg}`);
},
error(msg) {
console.log(`${colors.red.bold("[ERROR]")} ${msg}`);
}
}

View file

@ -3,6 +3,8 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const util = require("util") const util = require("util")
require("dotenv").config() require("dotenv").config()
const log = require("./log");
// Create a MariaDB connection pool // Create a MariaDB connection pool
const pool = mariadb.createPool({ const pool = mariadb.createPool({
@ -45,7 +47,7 @@ function runMigrations() {
[migrationName] [migrationName]
).then(([rows]) => { ).then(([rows]) => {
if (Object.keys(rows || {}).length > 0) { if (Object.keys(rows || {}).length > 0) {
console.log(`Skipping already applied migration: ${migrationName}`); //log.info(`Skipping already applied migration: ${migrationName}`);
return; // Skip this migration return; // Skip this migration
} }
@ -58,7 +60,7 @@ function runMigrations() {
'INSERT INTO migrations (name) VALUES (?)', 'INSERT INTO migrations (name) VALUES (?)',
[migrationName] [migrationName]
).then(() => { ).then(() => {
console.log(`Applied migration: ${migrationName}`); log.info(`Applied migration: ${migrationName}`);
}); });
}); });
}); });
@ -66,11 +68,11 @@ function runMigrations() {
}, Promise.resolve()); }, Promise.resolve());
}) })
.then(() => { .then(() => {
console.log('All migrations applied successfully!'); log.info('All migrations applied successfully!');
resolve(); resolve();
}) })
.catch(err => { .catch(err => {
console.error('Error running migrations:', err); log.error('Error running migrations:', err);
reject(err); reject(err);
}) })
.finally(() => { .finally(() => {

View file

@ -1,7 +1,7 @@
CREATE TABLE bans ( CREATE TABLE bans (
id INT AUTO_INCREMENT PRIMARY KEY, id CHAR(36) DEFAULT (UUID()) PRIMARY KEY,
robloxId INT, robloxId VARCHAR(16),
discordId INT, discordId VARCHAR(24),
robloxUsername VARCHAR(255), robloxUsername VARCHAR(255),
discordUsername VARCHAR(255), discordUsername VARCHAR(255),
reasonShort VARCHAR(255), reasonShort VARCHAR(255),

View file

@ -0,0 +1,12 @@
CREATE TABLE guilds (
id VARCHAR(24) NOT NULL PRIMARY KEY,
robloxId VARCHAR(16),
discordId VARCHAR(24),
robloxUsername VARCHAR(255),
discordUsername VARCHAR(255),
reasonShort VARCHAR(255),
reasonLong VARCHAR(2048),
reasonsFlag INT,
banTimestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
expiresTimestamp TIMESTAMP DEFAULT NULL
);

View file

@ -0,0 +1 @@
INSERT INTO ubs.bans (robloxId,discordId,robloxUsername,discordUsername,reasonShort,reasonLong,reasonsFlag) VALUES (999999999,123456789,'testuser','testuser', "Example Short", "Example Long", 20);

990
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,7 @@
"discord.js": "^14.16.3", "discord.js": "^14.16.3",
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"express": "^4.21.1", "express": "^4.21.1",
"mariadb": "^3.4.0" "mariadb": "^3.4.0",
"noblox.js": "^6.0.2"
} }
} }

View file

@ -1,6 +1,9 @@
const express = require('express'); const express = require('express');
const router = express.Router(); const router = express.Router();
const mariadb = require('mariadb'); const mariadb = require('mariadb');
const reasonFlags = JSON.parse(process.env.REASON_FLAGS)
const { execSync } = require('child_process');
// Create a MariaDB connection pool // Create a MariaDB connection pool
const pool = mariadb.createPool({ const pool = mariadb.createPool({
@ -60,4 +63,35 @@ router.get("/v1/ban/roblox/:uid", async (req, res) => {
} }
}) })
router.get("/v1/ban/discord/:uid", async (req, res) => {
if (!req.params.uid) return res.status(400).json({error: "Specify user ID!"});
try {
// Get a connection from the pool
const connection = await pool.getConnection();
try {
// Execute the query to fetch all rows from the `bans` table
const rows = await connection.query('SELECT * FROM bans WHERE discordId = ?', [req.params.uid]);
// Send the results as a JSON response
res.json(rows);
} finally {
// Release the connection back to the pool
connection.release();
}
} catch (err) {
console.error('Error fetching bans:', err);
// Respond with a 500 Internal Server Error status if something goes wrong
res.status(500).json({ error: 'An error occurred while fetching the bans.' });
}
})
router.get("/v1/info", (req,res) => {
res.json({
commit_hash: execSync('git rev-parse HEAD').toString().trim(),
reasonFlags
})
})
module.exports = router; module.exports = router;