diff --git a/commands.js b/commands.js index 6db568f..94f0ef8 100644 --- a/commands.js +++ b/commands.js @@ -4,25 +4,51 @@ 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)), + { + name: "lookup", + description: "Look up a ban", + options: [ + { + type: Discord.ApplicationCommandOptionType.Subcommand, + name: "ban-id", + description: "Look up a ban by ban ID", + options: [ + { + type: Discord.ApplicationCommandOptionType.String, + name: "ban-id", + description: "The ban ID", + required: true + } + ] + }, + { + type: Discord.ApplicationCommandOptionType.Subcommand, + name: "roblox-id", + description: "Look up bans by Roblox ID", + options: [ + { + type: Discord.ApplicationCommandOptionType.String, + name: "roblox-id", + description: "The Roblox ID", + required: true + } + ] + }, + { + type: Discord.ApplicationCommandOptionType.Subcommand, + name: "discord-id", + description: "Look up bans by Discord ID", + options: [ + { + type: Discord.ApplicationCommandOptionType.String, + name: "discord-id", + description: "The Discord ID", + required: true + } + ] + } + ] + } ], - admin: [ - new Discord.SlashCommandBuilder() - .setName("ban") - .setDescription("Ban a user.") - .setDefaultMemberPermissions(0) - .addStringOption(option => option.setName("reason").setDescription("The reason for the ban.").setRequired(true)) - .addStringOption(option => option.setName("roblox_id").setDescription("The Roblox ID of the user you're banning.").setRequired(false)) - .addStringOption(option => option.setName("discord_id").setDescription("The Discord ID of the user you're banning.").setRequired(false)), - 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(false)) - .addStringOption(option => option.setName("discord_id").setDescription("The Discord ID of the user you're unbanning.").setRequired(false)) - .setDefaultMemberPermissions(0), - ] + admin: [] } \ No newline at end of file diff --git a/commands/lookup.js b/commands/lookup.js new file mode 100644 index 0000000..6ec1166 --- /dev/null +++ b/commands/lookup.js @@ -0,0 +1,95 @@ +const flags = require("../flags") +const log = require("../log") + +const reasonFlags = global.reasonFlags +const pool = global.db_pool + +const lookupBanByID = async (client, interaction, options) => { + const banID = options.find(option => option.name === "ban-id").value + const connection = await pool.getConnection() + try { + const row = await connection.query('SELECT * FROM bans WHERE id = ?', [banID]) + if (!row) { + await interaction.reply({ content: `Ban with ID ${banID} not found`, ephemeral: true }) + return + } + const ban = row[0]; + const embed = { + title: `Ban ID: ${ban.id}`, + description: `**Roblox ID:** ${ban.robloxId}\n**Discord ID:** ${ban.discordId}\n**Roblox Username:** ${ban.robloxUsername}\n**Discord Username:** ${ban.discordUsername}\n**Reason Short:** ${ban.reasonShort}\n**Reason Long:** ${ban.reasonLong}\n**Reasons Flag:** ${flags.getSetFlags(ban.reasonsFlag, reasonFlags).join(", ")}\n**Moderator:** ${ban.moderator}\n**Ban Timestamp:** \n**Expires Timestamp:** ${ban.expiresTimestamp ? `` : "Never"}` + } + await interaction.reply({ embeds: [embed] }) + } catch (err) { + log.error('Error fetching bans:', err) + await interaction.reply({ content: 'An error occurred while fetching the ban.', ephemeral: true }) + } finally { + connection.release() + } +} + +const lookupBanByRobloxID = async (client, interaction, options) => { // There can be multiple bans with the same Roblox ID + const robloxID = options.find(option => option.name === "roblox-id").value + const connection = await pool.getConnection() + try { + const rows = await connection.query('SELECT * FROM bans WHERE robloxId = ?', [robloxID]) + if (rows.length === 0) { + await interaction.reply({ content: `No bans found for Roblox ID ${robloxID}`, ephemeral: true }) + return + } + const embeds = rows.map(ban => { + return { + title: `Ban ID: ${ban.id}`, + description: `**Roblox ID:** ${ban.robloxId}\n**Discord ID:** ${ban.discordId}\n**Roblox Username:** ${ban.robloxUsername}\n**Discord Username:** ${ban.discordUsername}\n**Reason Short:** ${ban.reasonShort}\n**Reason Long:** ${ban.reasonLong}\n**Reasons Flag:** ${flags.getSetFlags(ban.reasonsFlag, reasonFlags).join(", ")}\n**Moderator:** ${ban.moderator}\n**Ban Timestamp:** \n**Expires Timestamp:** ${ban.expiresTimestamp ? `` : "Never"}` + } + }) + await interaction.reply({ embeds: embeds }) + } catch (err) { + log.error('Error fetching bans:', err) + await interaction.reply({ content: 'An error occurred while fetching the ban.', ephemeral: true }) + } finally { + connection.release() + } +} + +const lookupBanByDiscordID = async (client, interaction, options) => { + const discordID = options.find(option => option.name === "discord-id").value + const connection = await pool.getConnection() + try { + const rows = await connection.query('SELECT * FROM bans WHERE discordId = ?', [discordID]) + if (rows.length === 0) { + await interaction.reply({ content: `No bans found for Discord ID ${discordID}`, ephemeral: true }) + return + } + const embeds = rows.map(ban => { + return { + title: `Ban ID: ${ban.id}`, + description: `**Roblox ID:** ${ban.robloxId}\n**Discord ID:** ${ban.discordId}\n**Roblox Username:** ${ban.robloxUsername}\n**Discord Username:** ${ban.discordUsername}\n**Reason Short:** ${ban.reasonShort}\n**Reason Long:** ${ban.reasonLong}\n**Reasons Flag:** ${flags.getSetFlags(ban.reasonsFlag, reasonFlags).join(", ")}\n**Moderator:** ${ban.moderator}\n**Ban Timestamp:** \n**Expires Timestamp:** ${ban.expiresTimestamp ? `` : "Never"}` + } + }) + interaction.reply({ embeds: embeds }) + } catch (err) { + log.error('Error fetching bans:', err) + await interaction.reply({ content: 'An error occurred while fetching the ban.', ephemeral: true }) + } finally { + connection.release() + } +} + + +const execute = (client, interaction) => { + const subcommand = interaction.options.getSubcommand() + const subcommandOptions = interaction.options.data[0].options + switch (subcommand) { + case "ban-id": + lookupBanByID(client, interaction, subcommandOptions) + break + case "roblox-id": + lookupBanByRobloxID(client, interaction, subcommandOptions) + break + case "discord-id": + lookupBanByDiscordID(client, interaction, subcommandOptions) + break + } +} + +module.exports = {execute} \ No newline at end of file diff --git a/index.js b/index.js index 54c754b..cbbb258 100644 --- a/index.js +++ b/index.js @@ -32,6 +32,8 @@ const pool = mariadb.createPool({ connectionLimit: 5 // Adjust connection limit as needed }); +global.db_pool = pool; // For global access + // Express const express = require("express"); const app = new express(); @@ -100,6 +102,7 @@ const reasonFlagTypes = [ const reasonFlags = flags.defineFlags(reasonFlagTypes) process.env.REASON_FLAGS = JSON.stringify(reasonFlags) +global.reasonFlags = reasonFlags console.log(process.env.REASON_FLAGS) // Discord stuff @@ -136,6 +139,20 @@ client.on("ready", async () => { })(); }); +client.on("interactionCreate", async (interaction) => { + if (!interaction.isCommand()) return; + const command = require(`./commands/${interaction.commandName}`); + + if (!command) return; + + try { + await command.execute(client, interaction); + } catch (error) { + log.error(error); + await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); + } +}); + // Startup log.info("Starting up...") const bcrypt = require("bcrypt") diff --git a/routes/admin.js b/routes/admin.js index d6315c2..acd5969 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -1,7 +1,7 @@ const express = require('express'); const router = express.Router(); const mariadb = require('mariadb'); -const reasonFlags = JSON.parse(process.env.REASON_FLAGS) +const reasonFlags = global.reasonFlags const expressSession = require('express-session'); const bcrypt = require("bcrypt") const crypto = require("crypto") @@ -16,14 +16,7 @@ const csv = require('csv-parser'); const fs = require('fs'); // Create a MariaDB connection pool -const pool = mariadb.createPool({ - host: process.env.DB_HOST, // Replace with your database host - port: process.env.DB_PORT || 3306, - user: process.env.DB_USER, // Replace with your database username - password: process.env.DB_PASS, // Replace with your database password - database: process.env.DB_DATABASE, // Replace with your database name - connectionLimit: 100 // 0 means no limit -}); +const pool = global.db_pool router.use(express.json()); router.use(express.urlencoded({ extended: true })); diff --git a/routes/api.js b/routes/api.js index 9519d1b..cab2541 100644 --- a/routes/api.js +++ b/routes/api.js @@ -1,19 +1,11 @@ const express = require('express'); const router = express.Router(); -const mariadb = require('mariadb'); -const reasonFlags = JSON.parse(process.env.REASON_FLAGS) +const reasonFlags = global.reasonFlags const { execSync } = require('child_process'); // Create a MariaDB connection pool -const pool = mariadb.createPool({ - host: process.env.DB_HOST, // Replace with your database host - port: process.env.DB_PORT || 3306, - user: process.env.DB_USER, // Replace with your database username - password: process.env.DB_PASS, // Replace with your database password - database: process.env.DB_DATABASE, // Replace with your database name - connectionLimit: 100 // Adjust connection limit as needed -}); +const pool = global.db_pool router.get("/health", async (req,res) => { try {