244 lines
7.1 KiB
JavaScript
244 lines
7.1 KiB
JavaScript
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: `<t:${Math.floor(expiry.getTime() / 1000)}:R> <t:${Math.floor(expiry.getTime() / 1000)}:f>`
|
|
},
|
|
{
|
|
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: <t:${Math.floor(new Date(row.timestamp) / 1000)}:r>\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); |