const config = require("./config.json"); const Discord = require("discord.js"); const colors = require("colors"); const sqlite3 = require("sqlite3").verbose(); const db = new sqlite3.Database("./database.db", (err) => { if (err) { console.error(`${colors.red("[ERROR]")} ${err.message}`); } console.log(`${colors.cyan("[INFO]")} DB Ready`); db.run("CREATE TABLE IF NOT EXISTS actions (id INTEGER PRIMARY KEY AUTOINCREMENT, action TEXT, userid TEXT, username TEXT, reason TEXT, moderator TEXT, timestamp TEXT, expires TEXT, notes TEXT)"); }); const client = new Discord.Client({ intents: ["Guilds"] }); const { REST, Routes } = require('discord.js'); const rest = new REST({ version: '10' }).setToken(config.token); client.on("ready", async () => { console.log(`${colors.cyan("[INFO]")} Logged in as ${client.user.tag}`); const commands = require("./commands.json"); await(async () => { try { //Global await rest.put(Routes.applicationCommands(client.user.id), { body: commands }).then(() => { console.log(`${colors.green("[SUCCESS]")} Global Commands registered`); }).catch((error) => { console.error(`${colors.red("[ERROR]")} ${error}`); }); } catch (error) { console.error(error); } })(); }); client.on("interactionCreate", async interaction => { switch (interaction.type) { case Discord.InteractionType.ApplicationCommand: switch (interaction.commandName) { case "log": action = interaction.options.getString("action"); userid = interaction.options.getString("userid"); username = interaction.options.getString("username"); reason = interaction.options.getString("reason"); moderator = interaction.user.id; timestamp = new Date(); expires = interaction.options.getString("duration"); notes = interaction.options.getString("notes"); // Start sanity checks // Check if action is valid if (!["warn", "mute", "kick", "ban"].includes(action)) { await interaction.reply({ content: "Invalid action", ephemeral: true }); return; } // Check if userid is valid (SCPSL id, steam64@steam) \b[0-9]{17}@steam\b if (!userid.match(/\b[0-9]{17}@steam\b/)) { await interaction.reply({ content: "Invalid userid", ephemeral: true }); return; } // Check expires (format is Xm) X being a number m being m (minutes) h (hours) d (days) w (weeks) M (months) y (years) if (!expires.match(/\b[0-9]{1,3}[mhdwMy]\b/)) { await interaction.reply({ content: "Invalid expiry", ephemeral: true }); return; } // Convert expires to valid timestamp (like format above, that much time after current time) expiry = new Date(); time = Number(expires.match(/\d+/)[0]); unit = expires.match(/[mhdwMy]/)[0]; console.log(time) console.log(unit) switch (unit) { case "m": expiry.setMinutes(expiry.getMinutes() + time); break; case "h": expiry.setHours(expiry.getHours() + time); break; case "d": expiry.setDate(expiry.getDate() + time); break; case "w": expiry.setDate(expiry.getDate() + time * 7); break; case "M": expiry.setMonth(expiry.getMonth() + time); break; case "y": expiry.setFullYear(expiry.getFullYear() + time); break; } // Debug console log expiry console.log(expiry.toTimeString()); console.log(new Date().toTimeString()) // Insert into database db.run("INSERT INTO actions (action, userid, username, reason, moderator, timestamp, expires, notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", [action, userid, reason, moderator, timestamp, expiry, notes], async (err) => { if (err) { await interaction.reply({ content: "An error occured", ephemeral: true }); return; } // Send log to log channel // Get log channel logChannel = await client.channels.fetch(config.log_channel); // Send log logChannel.send({ embeds: [{ title: `New ${action}`, fields: [ { name: "Action", value: action, inline: true }, { name: "User ID", value: userid, inline: true }, { "name": "Username", value: username || "No username provided", inline: true }, { name: "Reason", value: reason || "No reason provided", inline: true }, { name: "Moderator", value: `<@${moderator}>` }, { name: "Expires", value: ` ` }, { name: "Notes", value: notes || "No notes provided" } ] }] }) await interaction.reply({ content: "Logged", ephemeral: true }); }); break; case "get": // Get logs for specific IP or user ID // Figure out if it's an IP or a user ID, then switch case it target = interaction.options.getString("target"); if (target.match(/\b[0-9]{17}@steam\b/)) { // sql limit 10 is () db.all("SELECT * FROM actions WHERE userid = ? LIMIT 10", [target], async (err, rows) => { if (err) { await interaction.reply({ content: "An error occured", ephemeral: true }); return; } if (rows.length == 0) { await interaction.reply({ content: "No logs found", ephemeral: true }); return; } // Map rows to fields for embed await interaction.reply({ content: `Last 10 entries for ID ${target}`, embeds: [{ title: `Logs for ${target}`, fields: rows.map(row => { return { name: `${row.action} - ${row.id}`, value: `Reason: ${row.reason}\nModerator: <@${row.moderator}>\nTimestamp: \nExpires: ${row.expires}\nNotes: ${row.notes}` } }) }], ephemeral: true }); }); } else { // Get logs for IP db.all("SELECT * FROM actions WHERE ip LIKE ? LIMIT 10", [target + "%"], async (err, rows) => { if (err) { await interaction.reply({ content: "An error occured", ephemeral: true }); return; } if (rows.length == 0) { await interaction.reply({ content: "No logs found", ephemeral: true }); return; } // Map rows to fields for embed await interaction.reply({ content: `Last 10 entries for ${target}`, embeds: [{ title: `Logs for ${target}`, fields: rows.map(row => { return { name: `${row.action} - ${row.id}`, value: `Reason: ${row.reason}\nModerator: <@${row.moderator}>\nTimestamp: ${row.timestamp}\nExpires: ${row.expires}\nNotes: ${row.notes}` } }) }], ephemeral: true }); }); } break; } break; } }); client.login(config.token);