|
| 1 | +const Command = require('../../base/Command.js'); |
| 2 | +const { EmbedBuilder } = require('discord.js'); |
| 3 | +const { QuickDB } = require('quick.db'); |
| 4 | +require('moment-duration-format'); |
| 5 | +const moment = require('moment'); |
| 6 | +const db = new QuickDB(); |
| 7 | + |
| 8 | +class BuyItem extends Command { |
| 9 | + constructor(client) { |
| 10 | + super(client, { |
| 11 | + name: 'buy-item', |
| 12 | + category: 'Items', |
| 13 | + description: 'Buy an item from the store.', |
| 14 | + usage: 'buy-item [quantity] <item>', |
| 15 | + examples: ['buy pizza'], |
| 16 | + aliases: ['buy'], |
| 17 | + requiredArgs: 1, |
| 18 | + guildOnly: true, |
| 19 | + }); |
| 20 | + } |
| 21 | + |
| 22 | + async run(msg, args) { |
| 23 | + let quantity = 1; |
| 24 | + let itemName = args.join(' ').toLowerCase(); |
| 25 | + if (!isNaN(args[0])) { |
| 26 | + quantity = parseInt(args[0]); |
| 27 | + if (quantity <= 0) { |
| 28 | + return msg.reply('Invalid `[quantity]` argument given. Cannot be less than 1'); |
| 29 | + } |
| 30 | + args.shift(); |
| 31 | + itemName = args.join(' ').toLowerCase(); |
| 32 | + if (!itemName) { |
| 33 | + return msg.reply('Invalid `<item name>` argument given'); |
| 34 | + } |
| 35 | + } |
| 36 | + |
| 37 | + if (!itemName) return msg.reply('Please specify an item to buy.'); |
| 38 | + |
| 39 | + const store = (await db.get(`servers.${msg.guild.id}.economy.store`)) || {}; |
| 40 | + |
| 41 | + // Find the item in the store regardless of case |
| 42 | + const itemKey = Object.keys(store).find((key) => key.toLowerCase() === itemName); |
| 43 | + if (!itemKey) return msg.reply('That item does not exist in the store.'); |
| 44 | + |
| 45 | + const item = store[itemKey]; |
| 46 | + const itemCost = BigInt(item.cost); |
| 47 | + let userCash = BigInt(await db.get(`servers.${msg.guild.id}.users.${msg.member.id}.economy.cash`)); |
| 48 | + if (userCash < itemCost * BigInt(quantity)) return msg.reply('You do not have enough money to buy this item.'); |
| 49 | + |
| 50 | + if (item.stock && item.stock < quantity) { |
| 51 | + return msg.reply(`The store only has ${item.stock} stock remaining.`); |
| 52 | + } |
| 53 | + if (item.stock) { |
| 54 | + item.stock -= quantity; |
| 55 | + if (item.stock === 0) { |
| 56 | + await db.delete(`servers.${msg.guild.id}.economy.store.${itemKey}`); |
| 57 | + } else { |
| 58 | + store[itemKey] = item; |
| 59 | + await db.set(`servers.${msg.guild.id}.economy.store`, store); |
| 60 | + } |
| 61 | + } |
| 62 | + |
| 63 | + if (item.roleRequired) { |
| 64 | + const roleRequired = this.client.util.getRole(msg, item.roleRequired); |
| 65 | + if (roleRequired) { |
| 66 | + // Check if the member has the role |
| 67 | + const hasRole = msg.member.roles.cache.has(roleRequired.id); |
| 68 | + if (!hasRole) { |
| 69 | + return msg.reply(`You do not have the required role **${roleRequired.name}** to purchase this item.`); |
| 70 | + } |
| 71 | + } else { |
| 72 | + return msg.reply('The required role specified does not exist.'); |
| 73 | + } |
| 74 | + } |
| 75 | + |
| 76 | + if (item.roleGiven || item.roleRemoved) { |
| 77 | + if (!msg.guild.members.me.permissions.has('ManageRoles')) |
| 78 | + return this.client.util.errorEmbed( |
| 79 | + msg, |
| 80 | + 'Manage Roles permission is required on the bot to buy this item.', |
| 81 | + 'Missing Permission', |
| 82 | + ); |
| 83 | + } |
| 84 | + |
| 85 | + // Deduct the cost from the user's cash |
| 86 | + userCash = userCash - itemCost * BigInt(quantity); |
| 87 | + await db.set(`servers.${msg.guild.id}.users.${msg.member.id}.economy.cash`, userCash.toString()); |
| 88 | + |
| 89 | + if (!item.inventory) { |
| 90 | + if (item.roleGiven) { |
| 91 | + const role = this.client.util.getRole(msg, item.roleGiven); |
| 92 | + await msg.member.roles.add(role).catch((error) => msg.channel.send(error)); |
| 93 | + } |
| 94 | + if (item.roleRemoved) { |
| 95 | + const role = this.client.util.getRole(msg, item.roleRemoved); |
| 96 | + await msg.member.roles.remove(role).catch((error) => msg.channel.send(error)); |
| 97 | + } |
| 98 | + if (!item.replyMessage) { |
| 99 | + return msg.channel.send('👍'); |
| 100 | + } |
| 101 | + |
| 102 | + // Replace Member |
| 103 | + const memberCreatedAt = moment(msg.author.createdAt); |
| 104 | + const memberCreated = memberCreatedAt.format('D MM YY'); |
| 105 | + const memberCreatedDuration = memberCreatedAt.from(moment(), true); |
| 106 | + let replyMessage = item.replyMessage |
| 107 | + .replace('{member.id}', msg.author.id) |
| 108 | + .replace('{member.username}', msg.author.username) |
| 109 | + .replace('{member.tag}', msg.author.tag) |
| 110 | + .replace('{member.mention}', msg.author) |
| 111 | + .replace('{member.created}', memberCreated) |
| 112 | + .replace('{member.created.duration}', memberCreatedDuration); |
| 113 | + |
| 114 | + // Replace Server |
| 115 | + const guildCreatedAt = moment(msg.guild.createdAt); |
| 116 | + const serverCreated = guildCreatedAt.format('D MM YY'); |
| 117 | + const serverCreatedDuration = guildCreatedAt.from(moment(), true); |
| 118 | + |
| 119 | + replyMessage = replyMessage |
| 120 | + .replace('{server.id}', msg.guild.id) |
| 121 | + .replace('{server.name}', msg.guild.name) |
| 122 | + .replace('{server.members}', msg.guild.memberCount.toLocaleString()) |
| 123 | + .replace('{server.created}', serverCreated) |
| 124 | + .replace('{servers.created.duration', serverCreatedDuration); |
| 125 | + |
| 126 | + const role = |
| 127 | + (await this.client.util.getRole(msg, item.roleGiven)) || |
| 128 | + (await this.client.util.getRole(msg, item.roleRemoved)) || |
| 129 | + (await this.client.util.getRole(msg, item.roleRequired)); |
| 130 | + |
| 131 | + if (role) { |
| 132 | + const roleCreatedAt = moment(role.createdAt); |
| 133 | + const roleCreated = roleCreatedAt.format('D MM YY'); |
| 134 | + const roleCreatedDuration = roleCreatedAt.from(moment(), true); |
| 135 | + |
| 136 | + replyMessage = replyMessage |
| 137 | + .replace('{role.id}', role.id) |
| 138 | + .replace('{role.name}', role.name) |
| 139 | + .replace('{role.mention}', role) |
| 140 | + .replace('{role.members}', role.members.size.toLocaleString()) |
| 141 | + .replace('{role.created}', roleCreated) |
| 142 | + .replace('{role.created.duration}', roleCreatedDuration); |
| 143 | + } |
| 144 | + return msg.channel.send(replyMessage); |
| 145 | + } |
| 146 | + |
| 147 | + const userInventory = (await db.get(`servers.${msg.guild.id}.users.${msg.member.id}.economy.inventory`)) || []; |
| 148 | + |
| 149 | + // Find the index of the item in the user's inventory |
| 150 | + const itemIndex = userInventory.findIndex((inventoryItem) => inventoryItem?.name?.toLowerCase() === itemName); |
| 151 | + if (itemIndex !== -1) { |
| 152 | + // If the item is found, increment the quantity |
| 153 | + userInventory[itemIndex].quantity += quantity; |
| 154 | + userInventory[itemIndex] = { |
| 155 | + ...userInventory[itemIndex], |
| 156 | + replyMessage: item.replyMessage, |
| 157 | + roleRequired: item.roleRequired, |
| 158 | + roleGiven: item.roleGiven, |
| 159 | + roleRemoved: item.roleRemoved, |
| 160 | + }; |
| 161 | + await db.set(`servers.${msg.guild.id}.users.${msg.member.id}.economy.inventory`, userInventory); |
| 162 | + } else { |
| 163 | + // Add the item to the user's inventory |
| 164 | + item.quantity = quantity; |
| 165 | + userInventory.push({ name: itemKey, ...item }); |
| 166 | + |
| 167 | + await db.set(`servers.${msg.guild.id}.users.${msg.member.id}.economy.inventory`, userInventory); |
| 168 | + } |
| 169 | + |
| 170 | + const currencySymbol = (await db.get(`servers.${msg.guild.id}.economy.symbol`)) || '$'; |
| 171 | + const itemCostQuantity = (itemCost * BigInt(quantity)).toLocaleString(); |
| 172 | + const csCost = |
| 173 | + itemCostQuantity.length > 700 |
| 174 | + ? currencySymbol + itemCostQuantity.slice(0, 700) + '...' |
| 175 | + : currencySymbol + itemCostQuantity; |
| 176 | + |
| 177 | + const embed = new EmbedBuilder() |
| 178 | + .setTitle('Purchase Successful') |
| 179 | + .setDescription( |
| 180 | + `You have bought ${quantity} ${itemKey}${ |
| 181 | + quantity > 1 ? 's' : '' |
| 182 | + } for ${csCost}! This is now in your inventory. \nUse this item with the \`use-item\` command.`, |
| 183 | + ) |
| 184 | + .setColor(msg.settings.embedColor) |
| 185 | + .setTimestamp(); |
| 186 | + |
| 187 | + return msg.channel.send({ embeds: [embed] }); |
| 188 | + } |
| 189 | +} |
| 190 | + |
| 191 | +module.exports = BuyItem; |
0 commit comments