cactus-coin/index.js
Mmadrid509 0b51b8dc09
Possibly fix the cooldowns of coinflip and snakeeyes cmd
The cooldowns were being applied before checks, added it after so that it applies when the command goes fully through.
2023-11-10 18:32:25 -08:00

1127 lines
37 KiB
JavaScript

const config = require("./config.json");
if (!config.debug) config.debug = false;
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",
"GuildMessages",
"MessageContent"
]
});
// 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)");
db.run("CREATE TABLE IF NOT EXISTS cooldowns (id TEXT, type TEXT, cooldown TEXT)");
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...`)
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;
});
}
checkPoints = (user) => {
// Needs to be awaited
return new Promise((resolve, reject) => {
db.get(`SELECT * FROM points WHERE id = '${user.id}'`, async (err, row) => {
if (err) {
console.error(err);
reject(err);
}
if (!row) {
await db.run(`INSERT INTO points (id, points) VALUES ('${user.id}', 0)`);
resolve(0);
}
if (row) {
resolve(row.points);
}
});
});
}
checkCooldown = (user, type) => {
// Needs to be awaited
return new Promise((resolve, reject) => {
// If they are still within the cooldown period return true, if not return false
db.get(`SELECT * FROM cooldowns WHERE id = '${user.id}' AND type = '${type}'`, async (err, row) => {
if (err) {
console.error(err);
reject(err);
}
if (!row) {
resolve(false);
}
if (row) {
if (row.cooldown > Date.now()) {
resolve(row.cooldown);
} else {
resolve(false);
}
}
});
});
}
setCooldown = (user, type, cooldown) => {
// Needs to be awaited
return new Promise((resolve, reject) => {
// If any error occurs reject, otherwise return true
// check if the user and type combo exists, if it does update it, if it doesnt create it
db.get(`SELECT * FROM cooldowns WHERE id = '${user.id}' AND type = '${type}'`, async (err, row) => {
if (err) {
console.error(err);
reject(err);
}
if (!row) {
await db.run(`INSERT INTO cooldowns (id, type, cooldown) VALUES ('${user.id}', '${type}', '${Date.now() + cooldown}')`, (err) => {
if (err) {
console.error(err);
reject(err);
}
resolve(true);
});
}
if (row) {
await db.run(`UPDATE cooldowns SET cooldown = '${Date.now() + cooldown}' WHERE id = '${user.id}' AND type = '${type}'`, (err) => {
if (err) {
console.error(err);
reject(err);
}
resolve(true);
});
}
});
});
}
var slotResults = {};
client.on("interactionCreate", async interaction => {
if (!interaction.isCommand()) return;
switch (interaction.commandName) {
case "coins":
// Get user data
user = interaction.options.getUser("user") || interaction.user;
balance = await checkPoints(interaction.options.getUser("user") || interaction.user);
interaction.reply({
embeds: [{
title: `${user.username}'s Coins`,
description: `${config.discord.coin}${balance}`,
}]
});
break;
case "leaderboard":
// Get the type option, if its "inverted" then order by points ASC, if its not set then order by points DESC
type = interaction.options.getString("type") || "DESC";
// Switch type for the header of the embed
switch (type) {
case "DESC":
header = "Leaderboard";
break;
case "ASC":
header = "Inverted Leaderboard";
break;
}
await db.all(`SELECT * FROM points ORDER BY points ${type}`, async (err, rows) => {
if (err) {
console.error(err);
}
if (!rows) return interaction.reply({
content: "It's quiet here...",
ephemeral: true
});
if (rows) {
leaderboard = [];
// Top 10
for (let i = 0; i < 10; i++) {
if (rows[i]) {
user = await client.users.fetch(rows[i].id);
lvl = rows[i].lvl;
leaderboard.push(`${i + 1}. <@${user.id}> • ${config.discord.coin} ${rows[i].points}`);
}
}
interaction.reply({
embeds: [{
title: header,
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
});
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
amount = interaction.options.getNumber("amount");
if (amount > 0) {
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
}]
}).catch(err => { });
} else {
interaction.reply({
content: `An error occurred.\n`,
ephemeral: true
});
}
break;
case "modifyrandom": // Allows a user to modify a random user's coins
// 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
});
switch (interaction.options.getString("type")) {
case "database":
// Get a random user from the database
await db.all(`SELECT * FROM points`, async (err, rows) => {
if (err) {
console.error(err);
}
if (!rows) return interaction.reply({
content: "It's quiet here...",
ephemeral: true
});
if (rows) {
randomUser = await rows[Math.floor(Math.random() * rows.length)];
randomUser = await client.users.fetch(randomUser.id);
outputStatus = await checkAndModifyPoints(await client.users.fetch(randomUser.id), interaction.options.getNumber("amount"));
if (outputStatus !== false) {
interaction.reply({
content: `Gave ${await client.users.fetch(randomUser.id)} ${interaction.options.getNumber("amount")} coins.`,
ephemeral: true
});
// add + or - to the amount
amount = interaction.options.getNumber("amount");
if (amount > 0) {
amount = `+${amount}`;
}
// Send the log to the log channel
// Tell the user their coins were modified
randomUser.send({
embeds: [{
title: "Coins Modified",
description: `${config.discord.coin}${amount}`,
color: 0xFFff00
}]
}).catch(err => { });
} else {
interaction.reply({
content: `An error occurred.\n`,
ephemeral: true
});
}
}
});
break;
case "guild":
// Get a random user from the guild
await interaction.guild.members.fetch();
userList = await interaction.guild.members.cache.filter(member => !member.user.bot);
randomUser = await userList[Math.floor(Math.random() * userList.length)];
outputStatus = await checkAndModifyPoints(randomUser.user, interaction.options.getNumber("amount"));
if (outputStatus !== false) {
interaction.reply({
content: `Gave ${randomUser.user.username} ${interaction.options.getNumber("amount")} coins.`,
ephemeral: true
});
// add + or - to the amount
amount = interaction.options.getNumber("amount");
if (amount > 0) {
amount = `+${amount}`;
}
// Send the log to the log channel
// Tell the user their coins were modified
randomUser.user.send({
embeds: [{
title: "Coins Modified",
description: `${config.discord.coin}${amount}`,
color: 0xFFff00
}]
}).catch(err => { });
} else {
interaction.reply({
content: `An error occurred.\n`,
ephemeral: true
});
}
break;
}
break;
case "modifyeveryone": // Modify the coins of everyone in the database
// 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
});
// Run a lil db query to update every user's coins, dont bother sending a message to the user, it would take too long
await db.all(`SELECT * FROM points`, async (err, rows) => {
if (err) {
console.error(err);
}
if (!rows) return interaction.reply({
content: "It's quiet here...",
ephemeral: true
});
if (rows) {
for (let i = 0; i < rows.length; i++) {
checkAndModifyPoints(await client.users.fetch(rows[i].id), interaction.options.getNumber("amount"));
}
interaction.reply({
content: `Gave everyone ${interaction.options.getNumber("amount")} coins.`,
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 aren't 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 they're trying to be funny and send money to themselves.
if (interaction.user.id == interaction.options.getMember("user").user.id) return interaction.reply({
content: "You can't send coins to yourself silly.",
ephemeral: true
});
// Round the input up (these fuckers found a dupe one fucking day into the bot, fuck you krill issue)
amount = interaction.options.getNumber("amount");
balance = await checkPoints(interaction.user);
if (balance < amount) return interaction.reply({
content: "You do not have enough coins.",
ephemeral: true
});
// If the user doesnt have any coins tell them.
if (balance == 0) return interaction.reply({
content: "You do not have any coins.",
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 (balance < amount) return interaction.reply({
content: "You do not have enough coins.",
ephemeral: true
});
// If the user doesnt have any coins tell them.
if (balance == 0) return interaction.reply({
content: "You do not have any coins.",
ephemeral: true
});
// Now check if they have enough for the tax
if (balance < amount * 1.25) return interaction.reply({
content: `You do not have enough coins to pay the tax of ${config.discord.coin}${amount * 0.25}. You only have ${config.discord.coin}${balance}.`,
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, -amount * 1.25);
// Now we can give the other user the coins
checkAndModifyPoints(interaction.options.getMember("user").user, amount);
// Now we can tell the user that it worked
// get the amount sent with 2 decimal places if it has a decimal
if (amount % 1 != 0) {
amount = amount.toFixed(2);
}
interaction.reply({
embeds: [{
title: "Transfer Successful",
color: 0x00ff00,
description: `You sent ${config.discord.coin}${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}${amount} from ${interaction.user}.`
}]
}).catch(err => { });
interaction.user.send({
embeds: [{
title: "Transfer Receipt",
color: 0xffff00,
description: `You sent ${config.discord.coin}${amount} to ${interaction.options.getMember("user").user}.\nYou paid a tax of ${config.discord.coin}${amount * 0.25}.`
}]
}).catch(err => { });
}
});
break;
case "ledger": // Allows a user to see the balance of every user in the database
db.all(`SELECT * FROM points`, async (err, rows) => {
if (err) {
console.error(err);
return interaction.reply({
content: "An error occurred.",
ephemeral: true
});
}
if (!rows) return interaction.reply({
content: "It's quiet here...",
ephemeral: true
});
if (rows) {
ledger = [];
for (let i = 0; i < rows.length; i++) {
user = await client.users.fetch(rows[i].id);
if (rows[i].points == 0) continue;
ledger.push(`${user.username} - ${rows[i].points}`);
}
interaction.reply({
embeds: [{
title: "Ledger",
description: ledger.join("\n"),
color: 0x00ff00
}]
});
}
});
break;
case "play": // Allows a user to play a game to earn coins (or lose them)
curCooldown = await checkCooldown(interaction.user, interaction.options.getString("game"))
if (curCooldown) {
return interaction.reply({
content: `You can play again <t:${Math.floor(await checkCooldown(interaction.user, interaction.options.getString("game")) / 1000)}:R>.`,
ephemeral: true
});
}
setCooldown(interaction.user, interaction.options.getString("game"), config.games.waitPeriod * 60 * 1000);
// Check if they're in debt, if they are dont let them play
balance = await checkPoints(interaction.user);
if (balance < 0) return interaction.reply({
content: "You are in debt, you cannot play games until you are out of debt.",
ephemeral: true
});
result = await playGame(interaction.options.getString("game"));
await checkAndModifyPoints(interaction.user, result.difference);
interaction.reply(result.string);
break;
case "slots": // Play some slots, 1 minute cooldown
curCooldown = await checkCooldown(interaction.user, "slots")
if (curCooldown) {
return interaction.reply({
content: `You can play again <t:${Math.floor(await checkCooldown(interaction.user, "slots") / 1000)}:R>.`,
ephemeral: true
});
}
// Check if they have enough money to play, 3 coins, if they do take it and continue
balance = await checkPoints(interaction.user);
if (balance < 3) return interaction.reply({
content: "You do not have enough coins to play slots.",
ephemeral: true
});
// Get the slot results, yes it's pre-defined, but it's not like it matters
slotResults[interaction.user.id] = playSlotMachine();
// If there is a slotResults[interaction.user.id].cooldownOverride use that instead
if (slotResults[interaction.user.id].cooldownOverride) {
setCooldown(interaction.user, "slots", slotResults[interaction.user.id].cooldownOverride * 60 * 1000)
} else {
setCooldown(interaction.user, "slots", config.games.slots.cooldown * 60 * 1000)
}
await interaction.reply({
embeds: [{
title: "Slots",
description: `[${config.games.slots.spinning}][${config.games.slots.spinning}][${config.games.slots.spinning}]`,
color: 0xffff00
}]
});
// Check if they won or lost, if they won, give them the prize
difference = await new Number(slotResults[interaction.user.id].coinDifference);
// If they lost subtract 3 coins from the difference
if (difference <= 0) difference -= 3;
// Wait 4 seconds, then one at a time change the slots, 1 second apart
setTimeout(async () => {
await interaction.editReply({
embeds: [{
title: "Slots",
description: `[${slotResults[interaction.user.id].spinResult[0]}][${config.games.slots.spinning}][${config.games.slots.spinning}]`,
color: 0xffff00
}]
}, 1000);
setTimeout(async () => {
await interaction.editReply({
embeds: [{
title: "Slots",
description: `[${slotResults[interaction.user.id].spinResult[0]}][${slotResults[interaction.user.id].spinResult[1]}][${config.games.slots.spinning}]`,
color: 0xffff00
}]
}, 1000);
setTimeout(async () => {
await interaction.editReply({
embeds: [{
title: "Slots",
description: `[${slotResults[interaction.user.id].spinResult[0]}][${slotResults[interaction.user.id].spinResult[1]}][${slotResults[interaction.user.id].spinResult[2]}]`,
color: 0xffff00
}]
});
if (difference > 0) {
if (slotResults[interaction.user.id].jackpot) {
return await interaction.editReply({
embeds: [{
title: "Jackpot!",
description: `:rotating_light: [${slotResults[interaction.user.id].spinResult[0]}][${slotResults[interaction.user.id].spinResult[1]}][${slotResults[interaction.user.id].spinResult[2]}] :rotating_light:\nYou won the jackpot! (${difference} coins)`,
color: 0xffffff
}]
});
} else if (slotResults[interaction.user.id].triple) {
return await interaction.editReply({
embeds: [{
title: "Triple!",
description: `[${slotResults[interaction.user.id].spinResult[0]}][${slotResults[interaction.user.id].spinResult[1]}][${slotResults[interaction.user.id].spinResult[2]}]\nYou won ${difference} coins!`,
color: 0x00ffff
}]
});
} else {
await interaction.editReply({
embeds: [{
title: "Slots",
description: `[${slotResults[interaction.user.id].spinResult[0]}][${slotResults[interaction.user.id].spinResult[1]}][${slotResults[interaction.user.id].spinResult[2]}]\nYou won ${difference} coins! (You get your play fee back)`,
color: 0x00ff00
}]
});
}
} else {
// They lost, sad
if (slotResults[interaction.user.id].bombs) {
// Triple bombs, very sad
await interaction.editReply({
embeds: [{
title: "Bombs!",
description: `[${slotResults[interaction.user.id].spinResult[0]}][${slotResults[interaction.user.id].spinResult[1]}][${slotResults[interaction.user.id].spinResult[2]}]\nYou lost ${Math.abs(difference)} coins!`,
color: 0xff0000
}]
});
} else {
await interaction.editReply({
embeds: [{
title: "Slots",
description: `[${slotResults[interaction.user.id].spinResult[0]}][${slotResults[interaction.user.id].spinResult[1]}][${slotResults[interaction.user.id].spinResult[2]}]\nYou lost ${Math.abs(difference)} coins!`,
color: 0xff0000
}]
});
}
}
await checkAndModifyPoints(interaction.user, difference);
}, 1000);
}, 1000);
}, 4000);
break;
case "coinflip": // Coinflip game
/*
Minimum Bet: 1
Maximum Bet: 10
*/
// Check cooldown
curCooldown = await checkCooldown(interaction.user, "coinflip")
if (curCooldown) {
return interaction.reply({
content: `You can play again <t:${Math.floor(await checkCooldown(interaction.user, "coinflip") / 1000)}:R>.`,
ephemeral: true
});
}
bet = parseInt(interaction.options.get("amount").value);
if (bet < 1 || bet > 10) return interaction.reply({
content: "You can only bet between 1 and 10 coins.",
ephemeral: true
});
// Check if they have enough coins
points = await checkPoints(interaction.user);
if (points < bet) return interaction.reply({
content: "You do not have enough coins to play coinflip.",
ephemeral: true
});
// Flip the coin
coin = Math.random() < 0.6 ? "heads" : "tails";
before = await checkPoints(interaction.user);
side = interaction.options.getString("side");
outcome = coin == side ? true : false;
// If they win, give them the prize, if they lose, take the prize
// if they lose inverse the bet
if (!outcome) bet = -bet;
await checkAndModifyPoints(interaction.user, bet);
setCooldown(interaction.user, "coinflip", config.games.coinflip.cooldown * 60 * 1000)
if (coin == "heads") return interaction.reply({
embeds: [{
title: "Coinflip",
description: `You flipped ${config.games.coinflip.heads} and **${outcome ? "won" : "lost"}** ${Math.abs(bet)} coins!`,
color: outcome ? 0x00ff00 : 0xff0000
}]
});
else if (coin == "tails") return interaction.reply({
embeds: [{
title: "Coinflip",
description: `You flipped ${config.games.coinflip.tails} and **${outcome ? "won" : "lost"}** ${Math.abs(bet)} coins!`,
color: outcome ? 0x00ff00 : 0xff0000
}]
});
else return interaction.reply({
embeds: [{
title: "Something Went Wrong",
description: `The coin is neither heads nor tails, this shouldn't be possible!`,
color: 0xff0000
}]
});
break;
case "snakeeyes": // Snakeeyes game
/*
Minimum Bet: 1
Maximum Bet: 10
roll a 6 sided dice, if the number lands on 1, you win.
If you win your bet will be tripled, if you lose you lose your entire bet.
*/
// Check cooldown
curCooldown = await checkCooldown(interaction.user, "snakeeyes")
if (curCooldown) {
return interaction.reply({
content: `You can play again <t:${Math.floor(await checkCooldown(interaction.user, "snakeeyes") / 1000)}:R>.`,
ephemeral: true
});
}
bet = parseInt(interaction.options.get("amount").value);
if (bet < 1 || bet > 10) return interaction.reply({
content: "You can only bet between 1 and 10 coins.",
ephemeral: true
});
// Check if they have enough coins
points = await checkPoints(interaction.user);
if (points < bet) return interaction.reply({
content: "You do not have enough coins to play snakeeyes.",
ephemeral: true
});
setCooldown(interaction.user, "snakeeyes", config.games.snakeeyes.cooldown * 60 * 1000)
// Roll the dice
dice = Math.floor(Math.random() * 6) + 1;
before = points;
// If they win, give them the prize, if they lose, take the prize
// if they lose inverse the bet
bet = new Number(bet);
if (dice == 1) {
await checkAndModifyPoints(interaction.user, bet * 3);
interaction.reply({
embeds: [{
title: "Snakeeyes",
description: `You rolled a ${config.games.snakeeyes.sides[dice - 1]} and **won** ${bet * 3} coins!\nYou now have ${before + (bet * 3)} coins.`,
color: 0x00ff00
}]
});
} else {
bet = -bet;
await checkAndModifyPoints(interaction.user, bet);
interaction.reply({
embeds: [{
title: "Snakeeyes",
description: `You rolled a ${config.games.snakeeyes.sides[dice - 1]} and **lost** ${Math.abs(bet)} coins!\nYou now have ${before + bet} coins.`,
color: 0xff0000
}]
});
}
break;
case "daily": // Daily 2 coins
curCooldown = await checkCooldown(interaction.user, "daily")
if (curCooldown) {
return interaction.reply({
content: `Check back <t:${Math.floor(await checkCooldown(interaction.user, "daily") / 1000)}:R>.`,
ephemeral: true
});
}
// 24 hours
setCooldown(interaction.user, "daily", 24 * 60 * 60 * 1000)
await checkAndModifyPoints(interaction.user, 2);
interaction.reply({
embeds: [{
title: "Daily",
description: `You got 2 coins!`,
color: 0x00ff00
}]
});
break;
case "weekly": // Weekly 14 coins
curCooldown = await checkCooldown(interaction.user, "weekly")
if (curCooldown) {
return interaction.reply({
content: `Check back <t:${Math.floor(await checkCooldown(interaction.user, "weekly") / 1000)}:R>.`,
ephemeral: true
});
}
// 7 days
setCooldown(interaction.user, "weekly", 7 * 24 * 60 * 60 * 1000)
await checkAndModifyPoints(interaction.user, 14);
interaction.reply({
embeds: [{
title: "Weekly",
description: `You got 14 coins!`,
color: 0x00ff00
}]
});
break;
case "wordscramble": // Word Scramble game (admin only)
// 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
});
// Check if the channel already has a word scramble going
if (wordScrambles[interaction.channel.id]) {
return interaction.reply({
content: "There is already a word scramble going in this channel.",
ephemeral: true
});
}
// Start a word scramble and check if we specified a word
if (interaction.options.get("override")) {
override = interaction.options.get("override").value;
}
else {
override = false;
}
if (interaction.options.get("amount")) {
coinamount = interaction.options.getNumber("amount");
}
else {
coinamount = 2;
}
gameData = wordScramble(override);
wordScrambles[interaction.channel.id] = {
word: gameData.word,
amount: coinamount,
scrambledWord: gameData.scrambledWord,
badGuesses: []
}
interaction.channel.send({
embeds: [{
title: "Word Scramble",
description: `Unscramble the word **${gameData.scrambledWord}**!`,
color: 0xffff00
}]
});
interaction.reply({
content: "Word scramble started.",
ephemeral: true
})
// Set a timer for 30 seconds, if the word isn't guessed by then, delete the wordScrambles object
wordScrambles[interaction.channel.id].timer = setTimeout(() => {
interaction.channel.send({
embeds: [{
title: "Word Scramble",
description: `The word was **${wordScrambles[interaction.channel.id].word}**!`,
color: 0xff0000
}]
});
delete wordScrambles[interaction.channel.id];
}, 30 * 1000);
break;
};
});
var wordScrambles = {}
client.on('messageCreate', async message => {
if (message.author.bot) return;
if (!message.guild) return;
if (message.channel.type == "dm") return;
// Check if the channel already has a word scramble going
if (wordScrambles[message.channel.id]) {
if (wordScrambles[message.channel.id].badGuesses.includes(message.author.id)) return;
// Check if the message is the correct answer
if (message.content.toLowerCase() == wordScrambles[message.channel.id].word.toLowerCase()) {
// Give the user a point
await checkAndModifyPoints(message.author, wordScrambles[message.channel.id].amount);
// Send the message
message.channel.send({
embeds: [{
title: "Word Scramble",
description: `**${message.author}** got the word **${wordScrambles[message.channel.id].word}**!\nYou got ${wordScrambles[message.channel.id].amount} coins!`,
color: 0x00ff00
}]
});
clearTimeout(wordScrambles[message.channel.id].timer)
// Delete the wordScrambles object
delete wordScrambles[message.channel.id];
} else {
wordScrambles[message.channel.id].badGuesses.push(message.author.id);
}
} else {
if (!config.games.wordscramble.whitelist.includes(message.channel.id) && !config.games.wordscramble.whitelist.includes(message.channel.parentId)) return;
curCooldown = await checkCooldown({ id: 0 }, "wordscramble")
if (curCooldown) {
return;
}
// 1 in 50 chance to start a word scramble
if (Math.floor(Math.random() * 25) == 0) {
// Start a word scramble
setCooldown({ id: 0 }, "wordscramble", 5 * 60 * 1000)
override = false
coinamount = 2
gameData = wordScramble(override);
wordScrambles[message.channel.id] = {
word: gameData.word,
scrambledWord: gameData.scrambledWord,
amount: 2,
badGuesses: []
}
message.channel.send({
embeds: [{
title: "Word Scramble",
description: `Unscramble the word **${gameData.scrambledWord}**!`,
color: 0xffff00
}]
});
// Set a timer for 30 seconds, if the word isn't guessed by then, delete the wordScrambles object
return wordScrambles[message.channel.id].timer = setTimeout(() => {
message.channel.send({
embeds: [{
title: "Word Scramble",
description: `The word was **${wordScrambles[message.channel.id].word}**!`,
color: 0xff0000
}]
});
delete wordScrambles[message.channel.id];
}, 30 * 1000);
}
}
setCooldown({ id: 0 }, "wordscramble", 1 * 60 * 1000)
});
function wordScramble() {
// Get a random word from config.games.wordscramble.words then scramble it
if (!override) {
word = config.games.wordscramble.words[Math.floor(Math.random() * config.games.wordscramble.words.length)];
}
else {
word = override;
}
scrambledWord = word.split('').sort(function () {
// Fully scramble the word 3 times to be safe
return 0.5 - Math.random();
}).sort(function () {
return 0.5 - Math.random();
}).join('');
// if the scrambled word is the same as the word, scramble it again
if (scrambledWord == word) {
scrambledWord = word.split('').sort(function () {
return 0.5 - Math.random();
}).sort(function () {
return 0.5 - Math.random();
}).join('');
}
return {
word: word,
scrambledWord: scrambledWord
};
}
// Game function
function playGame(gameName) {
const randomNumber = Math.random() * 100;
result = {
string: "",
difference: 0
};
switch (gameName) {
case 'FISHING':
if (randomNumber < 40) {
result.string = "You caught water! Now how did you do that? No wonder your Dad left you.";
} else if (randomNumber < 70) {
result.string = "You caught a fish! That's pretty cool I guess. (+1 coin)";
result.difference = 1;
} else if (randomNumber < 90) {
result.string = "You caught a fish but BIGGER! Neat! (+2 coins)";
result.difference = 2;
} else if (randomNumber < 95) {
result.string = "You caught a WORM with your worm! Cactus likes worms! (+3 coins)";
result.difference = 3;
} else {
result.string = "You caught a piranha. It didn't appreciate that and mugged you at gunpoint. (-3 coins)";
result.difference = -3;
}
break;
case 'DIGGING':
if (randomNumber < 40) {
result.string = "You dug up dirt! Real accomplishment there. Dummy.";
} else if (randomNumber < 70) {
result.string = "You dug up a shiny pebble! That's pretty rad. (+1 coin)";
result.difference = 1;
} else if (randomNumber < 90) {
result.string = "You dug up a stick. Sticks are sticky! Nice! (+2 coins)";
result.difference = 2;
} else if (randomNumber < 95) {
result.string = "You dug up a sick ass earthworm! Cactus likes worms, let me tell you. (+3 coins)";
result.difference = 3;
} else {
result.string = "You dug up a pipe bomb. How could you be so dumb? Nice job idiot. (-3 coins)";
result.difference = -3;
}
break;
case 'HUNTING':
if (randomNumber < 40) {
result.string = "You came back empty handed like a loser. Nice job.";
} else if (randomNumber < 70) {
result.string = "You killed a rabbit. That's pretty cool I guess, you can make a jump boost from it. (+1 coin)";
result.difference = 1;
} else if (randomNumber < 90) {
result.string = "You killed a deer! Nice shooting! Maybe you aren't a failure like your father said! (+2 coins)";
result.difference = 2;
} else if (randomNumber < 95) {
result.string = "You killed a Bigfoot. Wait.... What? You killed a bigfo- The government pays to keep you quiet. (+3 coins.)";
result.difference = 3;
} else {
result.string = "You were trying to shoot a deer, missed, and hit Carl. They fined you for the hospital bills. (-3 coins)";
result.difference = -3;
}
break;
default:
result.string = "Unknown game";
break;
}
return result;
}
// Slots
function playSlotMachine() {
const icons = ['🍒', '🍎', '🍋', '🍓', '⭐', '🌵', '💣'];
const getRandomIcon = () => icons[Math.floor(Math.random() * icons.length)];
const spinResult = [getRandomIcon(), getRandomIcon(), getRandomIcon()];
const iconCounts = spinResult.reduce((counts, icon) => {
counts[icon] = (counts[icon] || 0) + 1;
return counts;
}, {});
coinDifference = 0; // Default coin difference for no match, they just lose the play cost
triple = false;
jackpot = false;
bombs = false;
if (iconCounts['🍎'] === 2) {
coinDifference = 1;
} else if (iconCounts['🍎'] === 3) {
triple = true;
coinDifference = 2;
} else if (iconCounts['🍋'] === 2) {
coinDifference = 3;
} else if (iconCounts['🍋'] === 3) {
triple = true;
coinDifference = 5;
} else if (iconCounts['🍒'] === 2) {
coinDifference = 5;
} else if (iconCounts['🍒'] === 3) {
triple = true;
coinDifference = 7;
} else if (iconCounts['🍓'] === 2) {
coinDifference = 7;
} else if (iconCounts['🍓'] === 3) {
triple = true;
coinDifference = 9;
} else if (iconCounts['⭐'] === 2) {
coinDifference = 9;
} else if (iconCounts['⭐'] === 3) {
triple = true;
coinDifference = 12;
} else if (iconCounts['🌵'] === 2) {
coinDifference = 9;
} else if (iconCounts['🌵'] === 3) {
jackpot = true;
coinDifference = 12;
} else if (iconCounts['💣'] === 2) {
bombs = true;
coinDifference = -5;
} else if (iconCounts['💣'] === 3) {
bombs = true;
coinDifference = -8;
}
if (iconCounts['💣'] === 1) {
bombs = true;
jackpot = false;
triple = false;
coinDifference = -1;
}
var cooldownOverride = 6 * iconCounts['💣']; // Change the cooldown to 6 minutes per bomb
const result = {
jackpot,
triple,
bombs,
spinResult,
cooldownOverride,
coinDifference
};
return result;
}
const rockPaperScissors = (userChoice) => {
const choices = ['🪨', '📄', '✂️'];
const botChoice = choices[Math.floor(Math.random() * choices.length)];
if (userChoice === botChoice) return 'It\'s a tie!';
else if (
(userChoice === '🪨' && botChoice === '✂️') ||
(userChoice === '📄' && botChoice === '🪨') ||
(userChoice === '✂️' && botChoice === '📄')
) {
return 'You won!';
}
else return 'You lost!';
};
//return console.log(playSlotMachine())
// 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);