285 lines
9 KiB
JavaScript
285 lines
9 KiB
JavaScript
const config = require("./config.json");
|
|
const Discord = require("discord.js");
|
|
const rest = new Discord.REST({
|
|
version: '10'
|
|
}).setToken(config.discord.token);
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const colors = require("colors");
|
|
const client = new Discord.Client({
|
|
intents: [
|
|
"GuildMembers",
|
|
"Guilds"
|
|
]
|
|
});
|
|
|
|
|
|
// Use sqlite3 for object storage, and create a database if it doesn't exist
|
|
const sqlite3 = require("sqlite3").verbose();
|
|
const db = new sqlite3.Database("./database.db");
|
|
|
|
// Create table if it doesn't exist
|
|
db.run("CREATE TABLE IF NOT EXISTS points (id TEXT, points INTEGER)");
|
|
// update table if it does exist
|
|
|
|
client.on("ready", async () => {
|
|
console.log(`${colors.cyan("[INFO]")} Logged in as ${colors.green(client.user.tag)}`)
|
|
// Load Commands
|
|
console.log(`${colors.cyan("[INFO]")} Loading Commands...`)
|
|
const commands = require('./commands.json');
|
|
await (async () => {
|
|
try {
|
|
console.log(`${colors.cyan("[INFO]")} Registering Commands...`)
|
|
let start = Date.now()
|
|
// Global commands
|
|
await rest.put(Discord.Routes.applicationCommands(client.user.id), {
|
|
body: commands
|
|
});
|
|
|
|
console.log(`${colors.cyan("[INFO]")} Successfully registered commands. Took ${colors.green((Date.now() - start) / 1000)} seconds.`);
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
})();
|
|
|
|
// Log startup time in seconds
|
|
console.log(`${colors.cyan("[INFO]")} Startup took ${colors.green((Date.now() - initTime) / 1000)} seconds.`)
|
|
});
|
|
|
|
// Functions
|
|
|
|
checkAndModifyPoints = async (user, amount, override) => {
|
|
// Check if the user exists, if not, add them to the database
|
|
await db.get(`SELECT * FROM points WHERE id = '${user.id}'`, async (err, row) => {
|
|
|
|
if (err) {
|
|
console.error(`Smthn went wrong: ${err}`);
|
|
return false;
|
|
}
|
|
if (!row) {
|
|
await db.run(`INSERT INTO points (id, points) VALUES ('${user.id}', ${amount})`);
|
|
return amount;
|
|
}
|
|
if (row) {
|
|
if (override) {
|
|
await db.run(`UPDATE points SET points = ${amount} WHERE id = '${user.id}'`);
|
|
return amount;
|
|
}
|
|
await db.run(`UPDATE points SET points = ${row.points + amount} WHERE id = '${user.id}'`);
|
|
return row.points + amount;
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
|
|
client.on("interactionCreate", async interaction => {
|
|
if (!interaction.isCommand()) return;
|
|
switch (interaction.commandName) {
|
|
case "points":
|
|
var user;
|
|
if (interaction.options.getMember("user")) {
|
|
user = interaction.options.getMember("user").user;
|
|
} else {
|
|
user = interaction.user;
|
|
}
|
|
// Get user data
|
|
await db.get(`SELECT * FROM points WHERE id = '${user.id}'`, async (err, row) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
if (!row) return interaction.reply({
|
|
content: "This user does not have any coins.",
|
|
ephemeral: true
|
|
});
|
|
if (row) {
|
|
var data = row;
|
|
interaction.reply({
|
|
embeds: [{
|
|
title: `${user.username}'s Coins`,
|
|
description: `${config.discord.coin} ${data.points}`,
|
|
}]
|
|
});
|
|
}
|
|
});
|
|
break;
|
|
case "leaderboard":
|
|
await db.all(`SELECT * FROM points ORDER BY points DESC`, async (err, rows) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
if (!rows) return interaction.reply({
|
|
content: "It's quiet here...",
|
|
ephemeral: true
|
|
});
|
|
if (rows) {
|
|
let leaderboard = [];
|
|
// Top 10
|
|
for (let i = 0; i < 10; i++) {
|
|
if (rows[i]) {
|
|
let user = await client.users.fetch(rows[i].id);
|
|
let lvl = rows[i].lvl;
|
|
leaderboard.push(`${i + 1}. <@${user.id}> - ${config.discord.coin}${rows[i].points}`);
|
|
}
|
|
}
|
|
interaction.reply({
|
|
embeds: [{
|
|
title: "Leaderboard",
|
|
description: leaderboard.join("\n"),
|
|
color: 0x00ff00
|
|
}]
|
|
});
|
|
}
|
|
});
|
|
break;
|
|
|
|
case "modify":
|
|
// check if the user is in the config.discord.givers array
|
|
if (!config.discord.givers.includes(interaction.user.id)) return interaction.reply({
|
|
content: "You do not have permission to use this command.",
|
|
ephemeral: true
|
|
});
|
|
let outputStatus = await checkAndModifyPoints(interaction.options.getMember("user").user, interaction.options.getNumber("amount"), interaction.options.getBoolean("override") || false);
|
|
if (outputStatus !== false) {
|
|
interaction.reply({
|
|
content: `Gave ${interaction.options.getMember("user").user.username} ${interaction.options.getNumber("amount")} coins.`,
|
|
ephemeral: true
|
|
});
|
|
// add + or - to the amount
|
|
let amount = interaction.options.getNumber("amount");
|
|
if (amount > 0) {
|
|
amount = `+${amount}`;
|
|
} else {
|
|
amount = `-${amount}`;
|
|
}
|
|
// Send the log to the log channel
|
|
// Tell the user their coins were modified
|
|
interaction.options.getMember("user").user.send({
|
|
embeds: [{
|
|
title: "Coins Modified",
|
|
description: `${config.discord.coin}${amount}`,
|
|
color: 0xFFff00
|
|
}]
|
|
});
|
|
|
|
|
|
} else {
|
|
interaction.reply({
|
|
content: `An error occurred.\n`,
|
|
ephemeral: true
|
|
});
|
|
}
|
|
break;
|
|
case "transfer": // Allows a user to transfer a positive amount of coins to another user at a 50% tax, rounded down, if the user sends 2 coins, the other user will receive 1, the other gets sent to the abyss.
|
|
// check if the arguments are there
|
|
if (!interaction.options.getMember("user")) return interaction.reply({
|
|
content: "You must specify a user.",
|
|
ephemeral: true
|
|
});
|
|
if (!interaction.options.getNumber("amount")) return interaction.reply({
|
|
content: "You must specify an amount.",
|
|
ephemeral: true
|
|
});
|
|
// Sanity check to make sure they arent trying to send negative coins and break the economy
|
|
if (interaction.options.getNumber("amount") < 0) return interaction.reply({
|
|
content: "You cannot send negative coins you lil goober.",
|
|
ephemeral: true
|
|
});
|
|
// check if the user has enough coins
|
|
await db.get(`SELECT * FROM points WHERE id = '${interaction.user.id}'`, async (err, row) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return interaction.reply({
|
|
content: "An error occurred.",
|
|
ephemeral: true
|
|
});
|
|
}
|
|
if (!row) return interaction.reply({
|
|
content: "You do not have any coins.",
|
|
ephemeral: true
|
|
});
|
|
if (row) {
|
|
if (row.points < interaction.options.getNumber("amount")) return interaction.reply({
|
|
content: "You do not have enough coins.",
|
|
ephemeral: true
|
|
});
|
|
// If the user doesnt have any coins tell them.
|
|
if (row.points == 0) return interaction.reply({
|
|
content: "You do not have any coins.",
|
|
ephemeral: true
|
|
});
|
|
// Now check if they have enough for the tax
|
|
if (row.points < Math.floor(interaction.options.getNumber("amount") * 2)) return interaction.reply({
|
|
content: "You do not have enough coins to pay the tax.",
|
|
ephemeral: true
|
|
});
|
|
// At this point we know they have enough coins, so we can take them away, make sure to take the tax away too
|
|
checkAndModifyPoints(interaction.user, -Math.floor(interaction.options.getNumber("amount") * 2));
|
|
// Now we can give the other user the coins
|
|
checkAndModifyPoints(interaction.options.getMember("user").user, Math.floor(interaction.options.getNumber("amount")));
|
|
// Now we can tell the user that it worked
|
|
interaction.reply({
|
|
embeds: [{
|
|
title: "Transfer Successful",
|
|
color: 0x00ff00,
|
|
description: `You sent ${config.discord.coin}${interaction.options.getNumber("amount")} to ${interaction.options.getMember("user").user.username}.`
|
|
}]
|
|
});
|
|
// Tell the user being transferred from about the change as a sort of receipt
|
|
interaction.options.getMember("user").user.send({
|
|
embeds: [{
|
|
title: "Transfer Receipt",
|
|
color: 0xffff00,
|
|
description: `You received ${config.discord.coin}${Math.floor(interaction.options.getNumber("amount"))} from ${interaction.user}.`
|
|
}]
|
|
});
|
|
interaction.user.send({
|
|
embeds: [{
|
|
title: "Transfer Receipt",
|
|
color: 0xffff00,
|
|
description: `You sent ${config.discord.coin}${interaction.options.getNumber("amount")} to ${interaction.options.getMember("user").user}.\nYou paid a tax of ${config.discord.coin}${Math.floor(interaction.options.getNumber("amount"))}.`
|
|
}]
|
|
})
|
|
|
|
}
|
|
});
|
|
break;
|
|
};
|
|
});
|
|
|
|
|
|
|
|
// Handle SIGINT gracefully
|
|
process.on('SIGINT', async () => {
|
|
await console.log(`${colors.cyan("[INFO]")} Stop received, exiting...`);
|
|
await client.user.setPresence({
|
|
status: "invisible",
|
|
activities: []
|
|
});
|
|
await client.destroy();
|
|
await console.log(`${colors.cyan("[INFO]")} Goodbye!`);
|
|
process.exit(0);
|
|
});
|
|
|
|
// Global error handler
|
|
/*process.on('uncaughtException', async (error) => {
|
|
await console.error(`${colors.red("[ERROR]")} Uncaught Exception: ${error}`);
|
|
if (client.user.tag) {
|
|
client.channels.fetch(config.discord.errorChannel).then(async channel => {
|
|
await channel.send({
|
|
embeds: [{
|
|
title: "Uncaught Exception",
|
|
description: `\`\`\`${error}\`\`\``,
|
|
color: 0xff0000
|
|
}]
|
|
});
|
|
});
|
|
}
|
|
});*/
|
|
|
|
|
|
|
|
console.log(`${colors.cyan("[INFO]")} Starting...`)
|
|
// Start timer to see how long startup takes
|
|
const initTime = Date.now()
|
|
// Login to Discord
|
|
client.login(config.discord.token); |