diff --git a/commands/currency/app.js b/commands/currency/app.js new file mode 100644 index 0000000..5d8fbce --- /dev/null +++ b/commands/currency/app.js @@ -0,0 +1,192 @@ +module.exports = { + name: 'ECON', + description: 'ALL ECON STUFF', + async execute(clientTemp, prefix, message, args, com2, Users, currency) { + const { Op } = require('sequelize'); + const { Collection, Client, Formatters, Intents } = require('discord.js'); + const { CurrencyShop } = require('./dbObjects.js'); + const { token } = require('./config.json'); + const command = com2; + + const client = clientTemp; //new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] }); + + + /* + * THIS REPO HEAVILY BORROWS FROM https://github.com/discordjs/guide/tree/main/code-samples/sequelize/currency + + * Make sure you are on at least version 5 of Sequelize! Version 4 as used in this guide will pose a security threat. + * You can read more about this issue On the [Sequelize issue tracker](https://github.com/sequelize/sequelize/issues/7310). + */ + + //If the table hasn't been created, use "node dbInit.js" + + function isNum(arg) { + return (!isNaN(arg) && Number.isSafeInteger(Number(arg))); + }; + + + + Reflect.defineProperty(currency, 'add', { + value: async (id, amount) => { + const user = currency.get(id); + + if (user) { + user.balance += Number(amount); + return user.save(); + } + + const newUser = await Users.create({ user_id: id, balance: amount }); + currency.set(id, newUser); + + return newUser; + }, + }); + + Reflect.defineProperty(currency, 'getBalance', { + value: id => { + const user = currency.get(id); + return user ? user.balance : 0; + }, + }); + + client.once('ready', async () => { + const storedBalances = await Users.findAll(); + storedBalances.forEach(b => currency.set(b.user_id, b)); + + console.log(`Logged in as ${client.user.tag}!`); + }); + + // client.on('messageCreate', async message => { + //debounce(); + + // if (message.author.bot) return; + // currency.add(message.author.id, 1); + // }); + + // client.on('interactionCreate', async interaction => { + + //if (!interaction.isCommand()) return; + //To replace this with an interaction, replace every instance of "message" with interaction + + //Custom section + + //const { commandName } = command; + //Replace all instances of "command" with "commandName" + //Replace "message.author;" with "interaction.options.getUser('user') || interaction.user;" + const user = await Users.findOne({ where: { user_id: message.author.id } }); + if (!user) { currency.add(message.author.id, 0); } + + + if (command == 'reset') { + if(message.guild.fetchOwner()) { + const target = message.author; + const oldBal = Number(currency.getBalance(target.id)); + currency.add(target.id, -oldBal); + } + } else if (command == 'add') { + //Check if the person is a mod + if (!isNum(args[0])) { message.reply("No..."); } + else if (args[0] > 100) { + message.reply("That's over $100 you greedy pig!"); + } else if (args[0] < 0) { + currency.add(message.author.id, args[0]); + } + else if (args.length < 2) { + const oldBal = Number(currency.getBalance(message.author.id)); + if (oldBal > 0) { + currency.add(message.author.id, -oldBal); + } + + currency.add(message.author.id, Number(args[0]) + oldBal); + } else { + for (let i = 1; i < args.size(); i ++) { + currency.add(args[i].id, oldBal + args[0]); + } + } + } else if (command === 'balance') { + const target = message.author; + return message.reply(`${target.tag} has \$${currency.getBalance(target.id)}`); + } else if (command === 'inventory') { + const target = message.author; + const user = await Users.findOne({ where: { user_id: target.id } }); + const items = await user.getItems(); + + if (!items.length) return message.reply(`${target.tag} has nothing!`); + + return message.reply(Formatters.codeBlock(items.map(i => `\$${i.item.cost * i.amount} worth of ${i.amount} ${i.item.icon}`).join('\n'))); + + //return message.reply(`${target.tag} currently has ${items.map(t => `${t.amount} ${t.item.name}`).join(', ')}`); + + } else if (command === 'transfer') { + const currentAmount = currency.getBalance(message.author.id); //interaction.user.id + const transferAmount = args[0]; //interaction.options.getInteger('amount'); + const transferTarget = args[1]; //interaction.options.getUser('user'); + + if (transferAmount > currentAmount) return message.reply(`Sorry ${message.author} you don't have that much.`); + if (transferAmount <= 0) return message.reply(`Please enter an amount greater than zero, ${message.author}`); + + currency.add(message.author.id, -transferAmount); + currency.add(transferTarget.id, transferAmount); + + return message.reply(`Successfully transferred ${transferAmount}💰 to ${transferTarget.tag}. Your current balance is ${currency.getBalance(message.author.id)}💰`); + + } else if (command === 'buy') { + if (!isNum(args[0]) || Number(args[0]) < 0) { + message.reply("Please enter a valid argument!"); + return; + } + + const numItems = Number(args[0]); + const itemName = args[1]; + + const item = await CurrencyShop.findOne({ where: { name: { [Op.like]: itemName } } }); + + if (!item) return message.reply('That item doesn\'t exist.'); + if (item.cost > currency.getBalance(message.author.id)) { + return message.reply(`You don't have enough currency, ${message.author}`); + } + + const user = await Users.findOne({ where: { user_id: message.author.id } }); + await user.addItem(item, message, currency, args[0]); + + return; + + //return message.reply(`You've bought a ${item.name}`); + + } else if (command == 'sell') { + const itemName = args[1]; + const item = await CurrencyShop.findOne({ where: { name: { [Op.like]: itemName } } }); + + if (!item) return message.reply('That item doesn\'t exist.'); + + const user = await Users.findOne({ where: { user_id: message.author.id } }); + + let ll; + if (args.length > 1) { + ll = Number(args[0]); + } else { + ll = 1; + } + + user.removeItem(item, message, currency, ll, CurrencyShop); + + + }else if (command === 'shop') { + const items = await CurrencyShop.findAll(); + return message.reply(Formatters.codeBlock(items.map(i => `${i.icon} (${i.name}): \$${i.cost}`).join('\n'))); + } else if (command === 'leaderboard') { + return message.reply( + Formatters.codeBlock( + currency.sort((a, b) => b.balance - a.balance) + .filter(user => client.users.cache.has(user.user_id)) + .first(10) + .map((user, position) => `(${position + 1}) ${(client.users.cache.get(user.user_id).tag)}: ${user.balance}💰`) + .join('\n'), + ), + ); + } else { + message.channel.send("'" + message.content + "' is not a command!"); + } + // }); + } +} \ No newline at end of file diff --git a/commands/currency/database.sqlite b/commands/currency/database.sqlite new file mode 100644 index 0000000..b41e07e Binary files /dev/null and b/commands/currency/database.sqlite differ diff --git a/currency/dbInit.js b/commands/currency/dbInit.js similarity index 80% rename from currency/dbInit.js rename to commands/currency/dbInit.js index 89e0b3c..8b30088 100644 --- a/currency/dbInit.js +++ b/commands/currency/dbInit.js @@ -10,6 +10,8 @@ const sequelize = new Sequelize('database', 'username', 'password', { dialect: 'sqlite', logging: false, storage: 'database.sqlite', + idle: 200000, + aquire: 1000000, }); const CurrencyShop = require('./models/CurrencyShop.js')(sequelize, Sequelize.DataTypes); @@ -20,9 +22,9 @@ const force = process.argv.includes('--force') || process.argv.includes('-f'); sequelize.sync({ force }).then(async () => { const shop = [ - CurrencyShop.upsert({ name: 'Tea', cost: 1 }), - CurrencyShop.upsert({ name: 'Coffee', cost: 2 }), - CurrencyShop.upsert({ name: 'Cake', cost: 5 }), + CurrencyShop.upsert({ name: 'Tea', cost: 1, icon: '🍵' }), + CurrencyShop.upsert({ name: 'Coffee', cost: 2, icon: '☕' }), + CurrencyShop.upsert({ name: 'Cake', cost: 5, icon: '🍰' }), ]; await Promise.all(shop); diff --git a/commands/currency/dbObjects.js b/commands/currency/dbObjects.js new file mode 100644 index 0000000..038492d --- /dev/null +++ b/commands/currency/dbObjects.js @@ -0,0 +1,94 @@ +const Sequelize = require('sequelize'); + +/* + * Make sure you are on at least version 5 of Sequelize! Version 4 as used in this guide will pose a security threat. + * You can read more about this issue on the [Sequelize issue tracker](https://github.com/sequelize/sequelize/issues/7310). + */ + +const sequelize = new Sequelize('database', 'username', 'password', { + host: 'localhost', + dialect: 'sqlite', + logging: false, + storage: 'database.sqlite', +}); + +const Users = require('./models/Users.js')(sequelize, Sequelize.DataTypes); +const CurrencyShop = require('./models/CurrencyShop.js')(sequelize, Sequelize.DataTypes); +const UserItems = require('./models/UserItems.js')(sequelize, Sequelize.DataTypes); + +UserItems.belongsTo(CurrencyShop, { foreignKey: 'item_id', as: 'item' }); + +Reflect.defineProperty(Users.prototype, 'addItem', { + /* eslint-disable-next-line func-name-matching */ + value: async function addItem(item, message, currency, numItems) { + const userItem = await UserItems.findOne({ + where: { user_id: this.user_id, item_id: item.id }, + }); + + //Makes it so you can only buy as many items as you can afford + let numItemsFinal; + let n = Math.floor(currency.getBalance(message.author.id)/item.cost); + + if (n > numItems) { numItemsFinal = numItems; } + else { numItemsFinal = n; } + + currency.add(message.author.id, -(item.cost * numItemsFinal)); + + if (userItem) { + userItem.amount += numItemsFinal; + userItem.save(); + } else { + UserItems.create({ user_id: this.user_id, item_id: item.id, amount: numItemsFinal, icon: item.icon }); + } + //console.log(numItemsFinal); + return message.reply(`You bought ${numItemsFinal} ${item.icon} for \$${numItemsFinal * item.cost}. You have \$${currency.getBalance(message.author.id)} left.`); + }, +}); + +Reflect.defineProperty(Users.prototype, 'removeItem', { + /* eslint-disable-next-line func-name-matching */ + value: async function removeItem(item, message, currency, ll, CurrencyShop) { + const userItem = await UserItems.findOne({ + where: { user_id: this.user_id, item_id: item.id }, + }); + + let val; + if (userItem) { + if (userItem.amount > 0 && ll > 0) { + val = userItem.amount; + let i = 0; + + val = userItem.amount; + if (ll > val) { i = val; } + else { i = ll; } + + userItem.amount -= i; + userItem.save(); + currency.add(message.author.id, i * item.cost); + + if (userItem.amount <= 0) { + //START + const tagID = item.id; + // equivalent to: DELETE from tags WHERE name = ?; + const rowCount = await UserItems.destroy({ where: { item_id: tagID } }); + + if (!rowCount) return message.reply('That tag doesn\'t exist.'); + } + + return message.reply(`You've sold ${i} ${item.icon} for \$${i * item.cost}!`); + } else { return message.reply("You don't have this item!"); } + } else { return message.reply("You don't have this item!");} + }, +}); + +Reflect.defineProperty(Users.prototype, 'getItems', { + /* eslint-disable-next-line func-name-matching */ + value: function getItems() { + return UserItems.findAll({ + where: { user_id: this.user_id }, + include: ['item'], + }); + }, +}); + +module.exports = { Users, CurrencyShop, UserItems }; diff --git a/currency/models/CurrencyShop.js b/commands/currency/models/CurrencyShop.js similarity index 80% rename from currency/models/CurrencyShop.js rename to commands/currency/models/CurrencyShop.js index 6ba721a..5fecc4e 100644 --- a/currency/models/CurrencyShop.js +++ b/commands/currency/models/CurrencyShop.js @@ -8,6 +8,10 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.INTEGER, allowNull: false, }, + icon: { + type: DataTypes.STRING, + unique: true, + }, }, { timestamps: false, }); diff --git a/currency/models/UserItems.js b/commands/currency/models/UserItems.js similarity index 80% rename from currency/models/UserItems.js rename to commands/currency/models/UserItems.js index 8ba57e3..a65923c 100644 --- a/currency/models/UserItems.js +++ b/commands/currency/models/UserItems.js @@ -7,6 +7,10 @@ module.exports = (sequelize, DataTypes) => { allowNull: false, 'default': 0, }, + icon: { + type: DataTypes.STRING, + 'default': '🤖', + } }, { timestamps: false, }); diff --git a/currency/models/Users.js b/commands/currency/models/Users.js similarity index 100% rename from currency/models/Users.js rename to commands/currency/models/Users.js diff --git a/currency/app.js b/currency/app.js deleted file mode 100644 index c967b27..0000000 --- a/currency/app.js +++ /dev/null @@ -1,107 +0,0 @@ -const { Op } = require('sequelize'); -const { Collection, Client, Formatters, Intents } = require('discord.js'); -const { Users, CurrencyShop } = require('./dbObjects.js'); - -const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] }); -const currency = new Collection(); - -/* - * Make sure you are on at least version 5 of Sequelize! Version 4 as used in this guide will pose a security threat. - * You can read more about this issue On the [Sequelize issue tracker](https://github.com/sequelize/sequelize/issues/7310). - */ - -Reflect.defineProperty(currency, 'add', { - value: async (id, amount) => { - const user = currency.get(id); - - if (user) { - user.balance += Number(amount); - return user.save(); - } - - const newUser = await Users.create({ user_id: id, balance: amount }); - currency.set(id, newUser); - - return newUser; - }, -}); - -Reflect.defineProperty(currency, 'getBalance', { - value: id => { - const user = currency.get(id); - return user ? user.balance : 0; - }, -}); - -client.once('ready', async () => { - const storedBalances = await Users.findAll(); - storedBalances.forEach(b => currency.set(b.user_id, b)); - - console.log(`Logged in as ${client.user.tag}!`); -}); - -client.on('messageCreate', async message => { - if (message.author.bot) return; - currency.add(message.author.id, 1); -}); - -client.on('interactionCreate', async interaction => { - if (!interaction.isCommand()) return; - - const { commandName } = interaction; - - if (commandName === 'balance') { - const target = interaction.options.getUser('user') || interaction.user; - - return interaction.reply(`${target.tag} has ${currency.getBalance(target.id)}💰`); - } else if (commandName === 'inventory') { - const target = interaction.options.getUser('user') || interaction.user; - const user = await Users.findOne({ where: { user_id: target.id } }); - const items = await user.getItems(); - - if (!items.length) return interaction.reply(`${target.tag} has nothing!`); - - return interaction.reply(`${target.tag} currently has ${items.map(t => `${t.amount} ${t.item.name}`).join(', ')}`); - } else if (commandName === 'transfer') { - const currentAmount = currency.getBalance(interaction.user.id); - const transferAmount = interaction.options.getInteger('amount'); - const transferTarget = interaction.options.getUser('user'); - - if (transferAmount > currentAmount) return interaction.reply(`Sorry ${interaction.user} you don't have that much.`); - if (transferAmount <= 0) return interaction.reply(`Please enter an amount greater than zero, ${interaction.user}`); - - currency.add(interaction.user.id, -transferAmount); - currency.add(transferTarget.id, transferAmount); - - return interaction.reply(`Successfully transferred ${transferAmount}💰 to ${transferTarget.tag}. Your current balance is ${currency.getBalance(interaction.user.id)}💰`); - } else if (commandName === 'buy') { - const itemName = interaction.options.getString('item'); - const item = await CurrencyShop.findOne({ where: { name: { [Op.like]: itemName } } }); - - if (!item) return interaction.reply('That item doesn\'t exist.'); - if (item.cost > currency.getBalance(interaction.user.id)) { - return interaction.reply(`You don't have enough currency, ${interaction.user}`); - } - - const user = await Users.findOne({ where: { user_id: interaction.user.id } }); - currency.add(interaction.user.id, -item.cost); - await user.addItem(item); - - return interaction.reply(`You've bought a ${item.name}`); - } else if (commandName === 'shop') { - const items = await CurrencyShop.findAll(); - return interaction.reply(Formatters.codeBlock(items.map(i => `${i.name}: ${i.cost}💰`).join('\n'))); - } else if (commandName === 'leaderboard') { - return interaction.reply( - Formatters.codeBlock( - currency.sort((a, b) => b.balance - a.balance) - .filter(user => client.users.cache.has(user.user_id)) - .first(10) - .map((user, position) => `(${position + 1}) ${(client.users.cache.get(user.user_id).tag)}: ${user.balance}💰`) - .join('\n'), - ), - ); - } -}); - -client.login('your-token-goes-here'); diff --git a/currency/dbObjects.js b/currency/dbObjects.js deleted file mode 100644 index ac0d201..0000000 --- a/currency/dbObjects.js +++ /dev/null @@ -1,47 +0,0 @@ -const Sequelize = require('sequelize'); - -/* - * Make sure you are on at least version 5 of Sequelize! Version 4 as used in this guide will pose a security threat. - * You can read more about this issue on the [Sequelize issue tracker](https://github.com/sequelize/sequelize/issues/7310). - */ - -const sequelize = new Sequelize('database', 'username', 'password', { - host: 'localhost', - dialect: 'sqlite', - logging: false, - storage: 'database.sqlite', -}); - -const Users = require('./models/Users.js')(sequelize, Sequelize.DataTypes); -const CurrencyShop = require('./models/CurrencyShop.js')(sequelize, Sequelize.DataTypes); -const UserItems = require('./models/UserItems.js')(sequelize, Sequelize.DataTypes); - -UserItems.belongsTo(CurrencyShop, { foreignKey: 'item_id', as: 'item' }); - -Reflect.defineProperty(Users.prototype, 'addItem', { - /* eslint-disable-next-line func-name-matching */ - value: async function addItem(item) { - const userItem = await UserItems.findOne({ - where: { user_id: this.user_id, item_id: item.id }, - }); - - if (userItem) { - userItem.amount += 1; - return userItem.save(); - } - - return UserItems.create({ user_id: this.user_id, item_id: item.id, amount: 1 }); - }, -}); - -Reflect.defineProperty(Users.prototype, 'getItems', { - /* eslint-disable-next-line func-name-matching */ - value: function getItems() { - return UserItems.findAll({ - where: { user_id: this.user_id }, - include: ['item'], - }); - }, -}); - -module.exports = { Users, CurrencyShop, UserItems }; diff --git a/database.sqlite b/database.sqlite new file mode 100644 index 0000000..cb35599 Binary files /dev/null and b/database.sqlite differ diff --git a/main.js b/main.js index 24fb03c..e5427b2 100644 --- a/main.js +++ b/main.js @@ -1,6 +1,7 @@ const { Client, Intents } = require('discord.js'); const Discord = require('discord.js'); -const { token } = require('./config.json'); +const { token } = require('./commands/currency/config.json'); + const client = new Client({ intents: [ @@ -19,8 +20,12 @@ client.commands = new Discord.Collection(); client.commNames = new Discord.Collection(); +client.econ = new Discord.Collection(); + const commandFiles = fs.readdirSync('./commands/').filter(file => file.endsWith('.js')); +const econFiles = fs.readdirSync('./commands/currency').filter(file => file.endsWith('.js'));; + let i = 0; for (const file of commandFiles) { const command = require(`./commands/${file}`); @@ -30,28 +35,26 @@ for (const file of commandFiles) { i ++; } +//ECON SECTION +client.commands.set('ECON', require(`./commands/currency/app.js`)); +const currency = new Discord.Collection(); +const { Users } = require('./commands/currency/dbObjects.js'); +i++; client.commNames.set('length', i); -client.on('ready', () => { +client.on('ready', async () => { + // client.once('ready', async () => { + const storedBalances = await Users.findAll(); + storedBalances.forEach(b => currency.set(b.user_id, b)); + + // console.log(`Logged in as ${client.user.tag}!`); console.log('SLEEMER BOT ONLINE!!!!! OH MY GOD OH MY GOD!!!'); }); client.on('messageCreate', (message) => { - - /*//PREVIEW COMMANDS START - const lib = require('lib')({token: process.env.STDLIB_SECRET_TOKEN}); - - lib.discord.commands['@0.0.0'].create({ - "name": "test", - "description": "it's a test command!", - "options": [] - }); - - //PREVIEW COMMANDS END*/ - //COMMAND AREA //Check if the prefix exists if (!message.content.startsWith(prefix) || message.author.bot) return; @@ -90,7 +93,7 @@ client.on('messageCreate', (message) => { case 'kareoke': client.commands.get('kareoke').execute(message, args); break; - default: message.channel.send("'" + message.content + "' is not a command!"); + default: client.commands.get('ECON').execute(client, prefix, message, args, command, Users, currency); } })