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 .`, 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 .`, 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 .`, 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 .`, 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 .`, 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 .`, 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);