From 99565f78a3d25d7e350b9831a07d0c8789a68133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20Olausson=20Holten=C3=A4s?= Date: Wed, 9 Mar 2022 21:12:57 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=96=20Version=203.0.0=20released?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 +- src/commands/admin/credits/addons/give.js | 90 +++++++++++++ src/commands/admin/credits/addons/index.js | 8 ++ src/commands/admin/credits/addons/set.js | 90 +++++++++++++ src/commands/admin/credits/addons/take.js | 90 +++++++++++++ src/commands/admin/credits/addons/transfer.js | 122 ++++++++++++++++++ src/commands/admin/credits/index.js | 50 +++++++ src/commands/admin/index.js | 55 ++++++++ src/commands/credits/addons/balance.js | 9 +- src/commands/credits/addons/gift.js | 13 +- src/commands/credits/addons/give.js | 62 --------- src/commands/credits/addons/set.js | 51 -------- src/commands/credits/addons/settings.js | 65 ---------- src/commands/credits/addons/take.js | 60 --------- src/commands/credits/addons/transfer.js | 104 --------------- src/commands/credits/index.js | 63 --------- src/commands/profile/addons/view.js | 70 ++++++++++ src/commands/profile/index.js | 17 +++ src/commands/reputation/addons/give.js | 59 +++++++++ src/commands/reputation/index.js | 35 +++++ src/commands/settings/guild/addons/credits.js | 102 +++++++++++++++ src/commands/settings/guild/addons/index.js | 4 + .../settings/guild/addons/pterodactyl.js | 57 ++++++++ src/commands/settings/guild/index.js | 40 ++++++ src/commands/settings/index.js | 53 ++++++++ .../settings/user/addons/appearance.js | 54 ++++++++ src/commands/settings/user/addons/index.js | 3 + src/commands/settings/user/index.js | 36 ++++++ src/commands/utilities/addons/users.js | 30 +++++ src/commands/utilities/index.js | 8 +- src/events/guildCreate.js | 2 +- src/events/interactionCreate.js | 112 ++++++++++------ src/events/memberCreate.js | 20 +++ src/events/messageCreate.js | 55 +++++++- src/handlers/locale.js | 55 ++++++++ src/helpers/database/models/apiSchema.js | 28 ++++ src/helpers/database/models/creditSchema.js | 2 +- .../database/models/experienceSchema.js | 35 +++++ src/helpers/database/models/guildSchema.js | 34 ++++- src/helpers/database/models/index.js | 10 ++ src/helpers/database/models/timeoutSchema.js | 22 ++++ src/helpers/database/models/userSchema.js | 20 +++ src/index.js | 19 +++ 43 files changed, 1451 insertions(+), 466 deletions(-) create mode 100644 src/commands/admin/credits/addons/give.js create mode 100644 src/commands/admin/credits/addons/index.js create mode 100644 src/commands/admin/credits/addons/set.js create mode 100644 src/commands/admin/credits/addons/take.js create mode 100644 src/commands/admin/credits/addons/transfer.js create mode 100644 src/commands/admin/credits/index.js create mode 100644 src/commands/admin/index.js delete mode 100644 src/commands/credits/addons/give.js delete mode 100644 src/commands/credits/addons/set.js delete mode 100644 src/commands/credits/addons/settings.js delete mode 100644 src/commands/credits/addons/take.js delete mode 100644 src/commands/credits/addons/transfer.js create mode 100644 src/commands/profile/addons/view.js create mode 100644 src/commands/profile/index.js create mode 100644 src/commands/reputation/addons/give.js create mode 100644 src/commands/reputation/index.js create mode 100644 src/commands/settings/guild/addons/credits.js create mode 100644 src/commands/settings/guild/addons/index.js create mode 100644 src/commands/settings/guild/addons/pterodactyl.js create mode 100644 src/commands/settings/guild/index.js create mode 100644 src/commands/settings/index.js create mode 100644 src/commands/settings/user/addons/appearance.js create mode 100644 src/commands/settings/user/addons/index.js create mode 100644 src/commands/settings/user/index.js create mode 100644 src/commands/utilities/addons/users.js create mode 100644 src/events/memberCreate.js create mode 100644 src/handlers/locale.js create mode 100644 src/helpers/database/models/apiSchema.js create mode 100644 src/helpers/database/models/experienceSchema.js create mode 100644 src/helpers/database/models/index.js create mode 100644 src/helpers/database/models/timeoutSchema.js create mode 100644 src/helpers/database/models/userSchema.js diff --git a/package.json b/package.json index d04eb94..1c97f54 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xyter", - "version": "2.4.0", + "version": "3.0.0", "description": "Earn credits while chatting! And more", "main": "src/index.js", "scripts": { @@ -31,6 +31,7 @@ "discord-api-types": "^0.27.3", "discord.js": "^13.6.0", "dotenv": "^16.0.0", + "i18next": "^21.6.13", "mongoose": "^6.2.3", "pino": "^7.0.0-rc.9", "quick.db": "^7.1.3", diff --git a/src/commands/admin/credits/addons/give.js b/src/commands/admin/credits/addons/give.js new file mode 100644 index 0000000..10f2fa2 --- /dev/null +++ b/src/commands/admin/credits/addons/give.js @@ -0,0 +1,90 @@ +const { Permissions } = require('discord.js'); +const config = require('../../../../../config.json'); +const logger = require('../../../../handlers/logger'); + +// Database models + +const { credits } = require('../../../../helpers/database/models'); +const creditNoun = require('../../../../helpers/creditNoun'); + +module.exports = async (interaction) => { + // Destructure member + + const { member } = interaction; + + // Check permission + + if (!member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { + const embed = { + title: 'Admin', + color: config.colors.error, + description: 'You do not have permission to manage this!', + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Get options + + const user = await interaction.options.getUser('user'); + const amount = await interaction.options.getInteger('amount'); + + // Stop if given amount is zero or below + + if (amount <= 0) { + const embed = { + title: 'Give', + description: "You can't give zero or below.", + color: 0xbb2124, + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Get toUser object + + const toUser = await credits.findOne({ userId: user.id, guildId: interaction.member.guild.id }); + + // Stop if user has zero or below credits + + if (!toUser) { + const embed = { + title: 'Give', + description: 'That user has no credits, I can not give credits to the user', + color: config.colors.error, + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Increase toUser with amount + + toUser.balance += amount; + + // Save toUser + + await toUser.save().then(async () => { + const embed = { + title: 'Give', + description: `Gave ${creditNoun(amount)} to ${user}.`, + color: 0x22bb33, + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + await logger.debug( + `Administrator: ${interaction.user.username} gave ${ + amount <= 1 ? `${amount} credit` : `${amount} credits` + } to ${user.username}`, + ); + // Send reply + + await interaction.editReply({ embeds: [embed], ephemeral: true }); + + // Send debug message + + await logger.debug(`Guild: ${member.guild.id} User: ${member.id} gave ${user.id} ${creditNoun(amount)}.`); + }); +}; diff --git a/src/commands/admin/credits/addons/index.js b/src/commands/admin/credits/addons/index.js new file mode 100644 index 0000000..ab3352e --- /dev/null +++ b/src/commands/admin/credits/addons/index.js @@ -0,0 +1,8 @@ +const give = require('./give'); +const set = require('./set'); +const take = require('./take'); +const transfer = require('./transfer'); + +module.exports = { + give, set, take, transfer, +}; diff --git a/src/commands/admin/credits/addons/set.js b/src/commands/admin/credits/addons/set.js new file mode 100644 index 0000000..b1ab71e --- /dev/null +++ b/src/commands/admin/credits/addons/set.js @@ -0,0 +1,90 @@ +const { Permissions } = require('discord.js'); +const config = require('../../../../../config.json'); +const logger = require('../../../../handlers/logger'); + +// Database models + +const { credits } = require('../../../../helpers/database/models'); +const creditNoun = require('../../../../helpers/creditNoun'); + +module.exports = async (interaction) => { + // Destructure member + + const { member } = interaction; + + // Check permission + + if (!member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { + const embed = { + title: 'Admin', + color: config.colors.error, + description: 'You do not have permission to manage this!', + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Get options + + const user = await interaction.options.getUser('user'); + const amount = await interaction.options.getInteger('amount'); + + // Stop if given amount is zero or below + + if (amount <= 0) { + const embed = { + title: 'Give', + description: "You can't give zero or below.", + color: 0xbb2124, + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Get toUser object + + const toUser = await credits.findOne({ userId: user.id, guildId: interaction.member.guild.id }); + + // Stop if user has zero or below credits + + if (!toUser) { + const embed = { + title: 'Set', + description: 'That user has no credits, I can not set credits to the user', + color: config.colors.error, + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Set toUser with amount + + toUser.balance = amount; + + // Save toUser + + await toUser.save().then(async () => { + const embed = { + title: 'Set', + description: `You set ${creditNoun(amount)} on ${user}.`, + color: 0x22bb33, + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + await logger.debug( + `Administrator: ${interaction.user.username} set ${ + amount <= 1 ? `${amount} credit` : `${amount} credits` + } on ${user.username}`, + ); + // Send reply + + await interaction.editReply({ embeds: [embed], ephemeral: true }); + + // Send debug message + + await logger.debug(`Guild: ${member.guild.id} User: ${member.id} set ${user.id} to ${creditNoun(amount)}.`); + }); +}; diff --git a/src/commands/admin/credits/addons/take.js b/src/commands/admin/credits/addons/take.js new file mode 100644 index 0000000..5f34da6 --- /dev/null +++ b/src/commands/admin/credits/addons/take.js @@ -0,0 +1,90 @@ +const { Permissions } = require('discord.js'); +const config = require('../../../../../config.json'); +const logger = require('../../../../handlers/logger'); + +// Database models + +const { credits } = require('../../../../helpers/database/models'); +const creditNoun = require('../../../../helpers/creditNoun'); + +module.exports = async (interaction) => { + // Destructure member + + const { member } = interaction; + + // Check permission + + if (!member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { + const embed = { + title: 'Admin', + color: config.colors.error, + description: 'You do not have permission to manage this!', + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Get options + + const user = await interaction.options.getUser('user'); + const amount = await interaction.options.getInteger('amount'); + + // Stop if given amount is zero or below + + if (amount <= 0) { + const embed = { + title: 'Take', + description: "You can't take zero or below.", + color: 0xbb2124, + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Get toUser object + + const toUser = await credits.findOne({ userId: user.id, guildId: interaction.member.guild.id }); + + // Stop if user has zero or below credits + + if (!toUser) { + const embed = { + title: 'Take', + description: 'That user has no credits, I can not take credits from the user', + color: config.colors.error, + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Decrease toUser with amount + + toUser.balance -= amount; + + // Save toUser + + await toUser.save().then(async () => { + const embed = { + title: 'Take', + description: `You took ${creditNoun(amount)} to ${user}.`, + color: 0x22bb33, + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + await logger.debug( + `Administrator: ${interaction.user.username} took ${ + amount <= 1 ? `${amount} credit` : `${amount} credits` + } from ${user.username}`, + ); + // Send reply + + await interaction.editReply({ embeds: [embed], ephemeral: true }); + + // Send debug message + + await logger.debug(`Guild: ${member.guild.id} User: ${member.id} took ${creditNoun(amount)} from ${user.id}.`); + }); +}; diff --git a/src/commands/admin/credits/addons/transfer.js b/src/commands/admin/credits/addons/transfer.js new file mode 100644 index 0000000..a19494c --- /dev/null +++ b/src/commands/admin/credits/addons/transfer.js @@ -0,0 +1,122 @@ +const { Permissions } = require('discord.js'); +const config = require('../../../../../config.json'); +const logger = require('../../../../handlers/logger'); + +// Database models + +const { credits } = require('../../../../helpers/database/models'); +const creditNoun = require('../../../../helpers/creditNoun'); +const saveUser = require('../../../../helpers/saveUser'); + +module.exports = async (interaction) => { + // Destructure member + + const { member } = interaction; + + // Check permission + + if (!member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { + const embed = { + title: 'Admin', + color: config.colors.error, + description: 'You do not have permission to manage this!', + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Get options + + const from = await interaction.options.getUser('from'); + const to = await interaction.options.getUser('to'); + const amount = await interaction.options.getInteger('amount'); + + // Get fromUser object + + const fromUser = await credits.findOne({ + userId: from.id, + guildId: interaction.member.guild.id, + }); + + // Get toUser object + + const toUser = await credits.findOne({ userId: to.id, guildId: interaction.member.guild.id }); + + // Stop if fromUser has zero credits or below + + if (!fromUser) { + const embed = { + title: 'Transfer', + description: 'That user has no credits, I can not transfer credits from the user', + color: config.colors.error, + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Stop if toUser has zero credits or below + + if (!toUser) { + const embed = { + title: 'Transfer', + description: 'That user has no credits, I can not transfer credits to the user', + color: config.colors.error, + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Stop if amount is zero or below + + if (amount <= 0) { + const embed = { + title: 'Transfer failed', + description: "You can't transfer zero or below.", + color: 0xbb2124, + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Decrease fromUser with amount + + fromUser.balance -= amount; + + // Increase toUser with amount + + toUser.balance += amount; + + await saveUser(fromUser, toUser).then(async () => { + const embed = { + title: 'Transfer', + description: `You sent ${creditNoun(amount)} from ${from} to ${to}.`, + color: 0x22bb33, + fields: [ + { + name: `${from.username} Balance`, + value: `${fromUser.balance}`, + inline: true, + }, + { + name: `${to.username} Balance`, + value: `${toUser.balance}`, + inline: true, + }, + ], + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + + // Send reply + + await interaction.editReply({ embeds: [embed], ephemeral: true }); + + // Send debug message + + await logger.debug(`Guild: ${member.guild.id} User: ${member.id} transferred ${creditNoun(amount)} from ${from.id} to ${to.id}.`); + }); +}; diff --git a/src/commands/admin/credits/index.js b/src/commands/admin/credits/index.js new file mode 100644 index 0000000..dce4dee --- /dev/null +++ b/src/commands/admin/credits/index.js @@ -0,0 +1,50 @@ +const { Permissions } = require('discord.js'); +const config = require('../../../../config.json'); +const logger = require('../../../handlers/logger'); + +const { + give, take, set, transfer, +} = require('./addons'); + +module.exports = async (interaction) => { + // Destructure member + + const { member } = interaction; + + // Check permission + + if (!member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { + const embed = { + title: 'Admin', + color: config.colors.error, + description: 'You do not have permission to manage this!', + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + await interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Command handler + + if (interaction.options.getSubcommand() === 'give') { + // Execute give addon + + await give(interaction); + } else if (interaction.options.getSubcommand() === 'take') { + // Execute take addon + + await take(interaction); + } else if (interaction.options.getSubcommand() === 'set') { + // Execute set addon + + await set(interaction); + } else if (interaction.options.getSubcommand() === 'transfer') { + // Execute transfer addon + + await transfer(interaction); + } + + // Send debug message + + await logger.debug(`Guild: ${member.guild.id} User: ${member.id} executed /${interaction.commandName} ${interaction.options.getSubcommandGroup()} ${interaction.options.getSubcommand()}`); +}; diff --git a/src/commands/admin/index.js b/src/commands/admin/index.js new file mode 100644 index 0000000..cebc7a7 --- /dev/null +++ b/src/commands/admin/index.js @@ -0,0 +1,55 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { Permissions } = require('discord.js'); + +const credits = require('./credits'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('admin') + .setDescription('Admin actions.') + .addSubcommandGroup((group) => group + .setName('credits') + .setDescription('Manage credits.') + .addSubcommand((command) => command + .setName('give') + .setDescription('Give credits to a user') + .addUserOption((option) => option.setName('user').setDescription('The user you want to pay.').setRequired(true)) + .addIntegerOption((option) => option.setName('amount').setDescription('The amount you will pay.').setRequired(true))) + .addSubcommand((command) => command + .setName('set') + .setDescription('Set credits to a user') + .addUserOption((option) => option + .setName('user') + .setDescription('The user you want to set credits on.') + .setRequired(true)) + .addIntegerOption((option) => option.setName('amount').setDescription('The amount you will set.').setRequired(true))) + .addSubcommand((command) => command + .setName('take') + .setDescription('Take credits from a user') + .addUserOption((option) => option + .setName('user') + .setDescription('The user you want to take credits from.') + .setRequired(true)) + .addIntegerOption((option) => option.setName('amount').setDescription('The amount you will take.').setRequired(true))) + .addSubcommand((command) => command + .setName('transfer') + .setDescription('Transfer credits from a user to another user.') + .addUserOption((option) => option + .setName('from') + .setDescription('The user you want to take credits from.') + .setRequired(true)) + .addUserOption((option) => option + .setName('to') + .setDescription('The user you want to give credits to.') + .setRequired(true)) + .addIntegerOption((option) => option + .setName('amount') + .setDescription('The amount you will transfer.') + .setRequired(true)))), + async execute(interaction) { + if (interaction.options.getSubcommandGroup() === 'credits') { + await credits(interaction); + } + return true; + }, +}; diff --git a/src/commands/credits/addons/balance.js b/src/commands/credits/addons/balance.js index 5f3907f..d30a4f7 100644 --- a/src/commands/credits/addons/balance.js +++ b/src/commands/credits/addons/balance.js @@ -1,3 +1,4 @@ +const i18next = require('i18next'); const config = require('../../../../config.json'); const logger = require('../../../handlers/logger'); @@ -8,6 +9,8 @@ module.exports = async (interaction) => { try { const user = await interaction.options.getUser('user'); + logger.debug(i18next.t('commands:credits:general:key', { count: 1 })); + await credits // eslint-disable-next-line max-len .findOne({ @@ -17,7 +20,7 @@ module.exports = async (interaction) => { .then(async (data) => { if (!data) { const embed = { - title: 'Balance', + title: `${i18next.t('commands:credits:addons:balance:embed:title')}`, description: `${user} has no credits.`, color: config.colors.success, timestamp: new Date(), @@ -29,8 +32,8 @@ module.exports = async (interaction) => { const { balance } = data; const embed = { - title: 'Balance', - description: `${user ? `${user} has` : 'You have'} ${creditNoun(balance)}.`, + title: `${i18next.t('commands:credits:addons:balance:embed:title')}`, + description: `${user ? `${user} has` : 'You have'} ${i18next.t('commands:credits:general:credits', { count: balance })}.`, color: config.colors.success, timestamp: new Date(), footer: { iconURL: config.footer.icon, text: config.footer.text }, diff --git a/src/commands/credits/addons/gift.js b/src/commands/credits/addons/gift.js index 91ddf15..e030277 100644 --- a/src/commands/credits/addons/gift.js +++ b/src/commands/credits/addons/gift.js @@ -1,3 +1,4 @@ +const i18next = require('i18next'); const config = require('../../../../config.json'); const logger = require('../../../handlers/logger'); @@ -18,7 +19,7 @@ module.exports = async (interaction) => { if (user.id === interaction.user.id) { const embed = { - title: 'Gift failed', + title: `${i18next.t('commands:credits:addons:gift:embed:title')}`, description: "You can't pay yourself.", color: 0xbb2124, timestamp: new Date(), @@ -28,7 +29,7 @@ module.exports = async (interaction) => { } if (amount <= 0) { const embed = { - title: 'Gift failed', + title: `${i18next.t('commands:credits:addons:gift:embed:title')}`, description: "You can't pay zero or below.", color: 0xbb2124, timestamp: new Date(), @@ -38,7 +39,7 @@ module.exports = async (interaction) => { } if (data.balance < amount) { const embed = { - title: 'Gift', + title: `${i18next.t('commands:credits:addons:gift:embed:title')}`, description: `You have insufficient credits. Your balance is ${data.balance}`, color: 0xbb2124, timestamp: new Date(), @@ -55,7 +56,7 @@ module.exports = async (interaction) => { if (!toUser) { const embed = { - title: 'Gift', + title: `${i18next.t('commands:credits:addons:gift:embed:title')}`, description: 'That user has no credits, I can not gift credits to the user', color: config.colors.error, timestamp: new Date(), @@ -69,7 +70,7 @@ module.exports = async (interaction) => { await saveUser(fromUser, toUser); const interactionEmbed = { - title: 'Gift', + title: `${i18next.t('commands:credits:addons:gift:embed:title')}`, description: `You sent ${creditNoun(amount)} to ${user}${ reason ? ` with reason: ${reason}` : '' }. Your new balance is ${creditNoun(fromUser.balance)}.`, @@ -78,7 +79,7 @@ module.exports = async (interaction) => { footer: { iconURL: config.footer.icon, text: config.footer.text }, }; const dmEmbed = { - title: 'Gift', + title: `${i18next.t('commands:credits:addons:gift:embed:title')}`, description: `You received ${creditNoun(amount)} from ${interaction.user}${ reason ? ` with reason: ${reason}` : '' }. Your new balance is ${creditNoun(toUser.balance)}.`, diff --git a/src/commands/credits/addons/give.js b/src/commands/credits/addons/give.js deleted file mode 100644 index c15d3e4..0000000 --- a/src/commands/credits/addons/give.js +++ /dev/null @@ -1,62 +0,0 @@ -const { Permissions } = require('discord.js'); - -const config = require('../../../../config.json'); -const logger = require('../../../handlers/logger'); - -const credits = require('../../../helpers/database/models/creditSchema'); -const creditNoun = require('../../../helpers/creditNoun'); - -module.exports = async (interaction) => { - try { - if (!interaction.member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { - const embed = { - title: 'Give failed', - description: 'You need to have permission to manage this guild (MANAGE_GUILD)', - }; - return await interaction.editReply({ embeds: [embed], ephemeral: true }); - } - const user = await interaction.options.getUser('user'); - const amount = await interaction.options.getInteger('amount'); - - if (amount <= 0) { - const embed = { - title: 'Give', - description: "You can't give zero or below.", - color: 0xbb2124, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - return await interaction.editReply({ embeds: [embed], ephemeral: true }); - } - const toUser = await credits.findOne({ userId: user.id, guildId: interaction.member.guild.id }); - - if (!toUser) { - const embed = { - title: 'Give', - description: 'That user has no credits, I can not give credits to the user', - color: config.colors.error, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - return interaction.editReply({ embeds: [embed], ephemeral: true }); - } - toUser.balance += amount; - await toUser.save(); - const embed = { - title: 'Give', - description: `Gave ${creditNoun(amount)} to ${user}.`, - color: 0x22bb33, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - await logger.debug( - `Administrator: ${interaction.user.username} gave ${ - amount <= 1 ? `${amount} credit` : `${amount} credits` - } to ${user.username}` - ); - return await interaction.editReply({ embeds: [embed], ephemeral: true }); - } catch (e) { - await logger.error(e); - } - return true; -}; diff --git a/src/commands/credits/addons/set.js b/src/commands/credits/addons/set.js deleted file mode 100644 index f4b6e28..0000000 --- a/src/commands/credits/addons/set.js +++ /dev/null @@ -1,51 +0,0 @@ -const { Permissions } = require('discord.js'); - -const config = require('../../../../config.json'); -const logger = require('../../../handlers/logger'); - -const credits = require('../../../helpers/database/models/creditSchema'); -const creditNoun = require('../../../helpers/creditNoun'); - -module.exports = async (interaction) => { - if (!interaction.member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { - const embed = { - title: 'Set', - description: 'You need to have permission to manage this guild (MANAGE_GUILD)', - color: 0xbb2124, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - return interaction.editReply({ embeds: [embed], ephemeral: true }); - } - const user = await interaction.options.getUser('user'); - const amount = await interaction.options.getInteger('amount'); - - const toUser = await credits.findOne({ userId: user.id, guildId: interaction.member.guild.id }); - - if (!toUser) { - const embed = { - title: 'Set', - description: 'That user has no credits, I can not set credits to the user', - color: config.colors.error, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - return interaction.editReply({ embeds: [embed], ephemeral: true }); - } - toUser.balance = amount; - await toUser.save(); - - const embed = { - title: 'Set', - description: `You set ${creditNoun(amount)} on ${user}.`, - color: 0x22bb33, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - await logger.debug( - `Administrator: ${interaction.user.username} set ${ - amount <= 1 ? `${amount} credit` : `${amount} credits` - } on ${user.username}`, - ); - return interaction.editReply({ embeds: [embed], ephemeral: true }); -}; diff --git a/src/commands/credits/addons/settings.js b/src/commands/credits/addons/settings.js deleted file mode 100644 index 561e285..0000000 --- a/src/commands/credits/addons/settings.js +++ /dev/null @@ -1,65 +0,0 @@ -const config = require('../../../../config.json'); -const logger = require('../../../handlers/logger'); - -const guilds = require('../../../helpers/database/models/guildSchema'); - -// eslint-disable-next-line consistent-return -module.exports = async (interaction) => { - try { - const status = await interaction.options.getBoolean('status'); - const url = await interaction.options.getString('url'); - const token = await interaction.options.getString('token'); - const rate = await interaction.options.getNumber('rate'); - const timeout = await interaction.options.getNumber('timeout'); - const minimumLength = await interaction.options.getNumber('minimum-length'); - const workRate = await interaction.options.getNumber('work-rate'); - const workTimeout = await interaction.options.getNumber('work-timeout'); - - const guild = await guilds.findOne({ guildId: interaction.member.guild.id }); - - guild.credits.status = status !== null ? status : guild.credits.status; - guild.credits.url = url !== null ? url : guild.credits.url; - guild.credits.token = token !== null ? token : guild.credits.token; - guild.credits.rate = rate !== null ? rate : guild.credits.rate; - guild.credits.timeout = timeout !== null ? timeout : guild.credits.timeout; - guild.credits.workRate = workRate !== null ? workRate : guild.credits.workRate; - // eslint-disable-next-line max-len - guild.credits.workTimeout = workTimeout !== null ? workTimeout : guild.credits.workTimeout; - // eslint-disable-next-line max-len - guild.credits.minimumLength = minimumLength !== null ? minimumLength : guild.credits.minimumLength; - - await guild.save(); - const embed = { - title: 'Credits', - description: 'Following settings is set', - color: config.colors.success, - fields: [ - { name: 'Status', value: `${guild.credits.status}`, inline: true }, - { name: 'URL', value: `${guild.credits.url}`, inline: true }, - { name: 'Token', value: `${guild.credits.token}` }, - { name: 'Rate', value: `${guild.credits.rate}`, inline: true }, - { - name: 'Minimum Length', - value: `${guild.credits.minimumLength}`, - inline: true, - }, - { name: 'Timeout', value: `${guild.credits.timeout}`, inline: true }, - { - name: 'Work Rate', - value: `${guild.credits.workRate}`, - inline: true, - }, - { - name: 'Work Timeout', - value: `${guild.credits.workTimeout}`, - inline: true, - }, - ], - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - return interaction.editReply({ embeds: [embed], ephemeral: true }); - } catch (e) { - logger.error(e); - } -}; diff --git a/src/commands/credits/addons/take.js b/src/commands/credits/addons/take.js deleted file mode 100644 index e4fce37..0000000 --- a/src/commands/credits/addons/take.js +++ /dev/null @@ -1,60 +0,0 @@ -const { Permissions } = require('discord.js'); -const config = require('../../../../config.json'); - -const credits = require('../../../helpers/database/models/creditSchema'); -const logger = require('../../../handlers/logger'); -const creditNoun = require('../../../helpers/creditNoun'); - -module.exports = async (interaction) => { - if (!interaction.member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { - const embed = { - title: 'Take', - description: 'You need to have permission to manage this guild (MANAGE_GUILD)', - color: 0xbb2124, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - return interaction.editReply({ embeds: [embed], ephemeral: true }); - } - const user = await interaction.options.getUser('user'); - const amount = await interaction.options.getInteger('amount'); - - if (amount <= 0) { - const embed = { - title: 'Take', - description: "You can't take zero or below.", - color: 0xbb2124, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - return interaction.editReply({ embeds: [embed], ephemeral: true }); - } - const toUser = await credits.findOne({ userId: user.id, guildId: interaction.member.guild.id }); - - if (!toUser) { - const embed = { - title: 'Take', - description: 'That user has no credits, I can not take credits from the user', - color: config.colors.error, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - return interaction.editReply({ embeds: [embed], ephemeral: true }); - } - toUser.balance -= amount; - await toUser.save(); - - const embed = { - title: 'Take', - description: `You took ${creditNoun(amount)} to ${user}.`, - color: 0x22bb33, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - await logger.debug( - `Administrator: ${interaction.user.username} took ${ - amount <= 1 ? `${amount} credit` : `${amount} credits` - } from ${user.username}`, - ); - return interaction.editReply({ embeds: [embed], ephemeral: true }); -}; diff --git a/src/commands/credits/addons/transfer.js b/src/commands/credits/addons/transfer.js deleted file mode 100644 index ac7a5c9..0000000 --- a/src/commands/credits/addons/transfer.js +++ /dev/null @@ -1,104 +0,0 @@ -const { Permissions } = require('discord.js'); - -const config = require('../../../../config.json'); -const logger = require('../../../handlers/logger'); - -const credits = require('../../../helpers/database/models/creditSchema'); -const saveUser = require('../../../helpers/saveUser'); -const creditNoun = require('../../../helpers/creditNoun'); - -module.exports = async (interaction) => { - try { - if (!interaction.member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { - const embed = { - title: 'Transfer failed', - description: 'You need to have permission to manage this guild (MANAGE_GUILD)', - }; - return await interaction.editReply({ embeds: [embed], ephemeral: true }); - } - - const from = await interaction.options.getUser('from'); - const to = await interaction.options.getUser('to'); - const amount = await interaction.options.getInteger('amount'); - // eslint-disable-next-line max-len - const fromUser = await credits.findOne({ - userId: from.id, - guildId: interaction.member.guild.id, - }); - const toUser = await credits.findOne({ userId: to.id, guildId: interaction.member.guild.id }); - - if (!fromUser) { - const embed = { - title: 'Transfer', - description: 'That user has no credits, I can not transfer credits from the user', - color: config.colors.error, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - return interaction.editReply({ embeds: [embed], ephemeral: true }); - } - - if (!toUser) { - const embed = { - title: 'Transfer', - description: 'That user has no credits, I can not transfer credits to the user', - color: config.colors.error, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - return interaction.editReply({ embeds: [embed], ephemeral: true }); - } - - if (amount <= 0) { - const embed = { - title: 'Transfer failed', - description: "You can't transfer zero or below.", - color: 0xbb2124, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - return await interaction.editReply({ embeds: [embed], ephemeral: true }); - } - if (fromUser.balance < amount) { - const embed = { - title: 'Transfer', - description: `${from.username} has insufficient credits. ${from.username} balance is ${fromUser.balance}`, - color: 0xbb2124, - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - return await interaction.editReply({ embeds: [embed], ephemeral: true }); - } - - fromUser.balance -= amount; - toUser.balance += amount; - - await saveUser(fromUser, toUser); - - const embed = { - title: 'Transfer', - description: `You sent ${creditNoun(amount)} from ${from} to ${to}.`, - color: 0x22bb33, - fields: [ - { - name: `${from.username} Balance`, - value: `${fromUser.balance}`, - inline: true, - }, - { - name: `${to.username} Balance`, - value: `${toUser.balance}`, - inline: true, - }, - ], - timestamp: new Date(), - footer: { iconURL: config.footer.icon, text: config.footer.text }, - }; - - await logger.debug(`Gift sent from: ${interaction.user.username} to: ${to.username}`); - return await interaction.editReply({ embeds: [embed], ephemeral: true }); - } catch (e) { - logger.error(e); - } - return true; -}; diff --git a/src/commands/credits/index.js b/src/commands/credits/index.js index f7e1a34..bb78fbd 100644 --- a/src/commands/credits/index.js +++ b/src/commands/credits/index.js @@ -6,13 +6,8 @@ const guilds = require('../../helpers/database/models/guildSchema'); const balance = require('./addons/balance'); const gift = require('./addons/gift'); -const give = require('./addons/give'); const redeem = require('./addons/redeem'); -const take = require('./addons/take'); const top = require('./addons/top'); -const transfer = require('./addons/transfer'); -const set = require('./addons/set'); -const settings = require('./addons/settings'); const work = require('./addons/work'); module.exports = { @@ -25,19 +20,6 @@ module.exports = { data: new SlashCommandBuilder() .setName('credits') .setDescription('Manage your credits.') - .addSubcommand((subcommand) => subcommand - .setName('give') - .setDescription('Give credits to a user. (ADMIN)') - .addUserOption((option) => option.setName('user').setDescription('The user you want to pay.').setRequired(true)) - .addIntegerOption((option) => option.setName('amount').setDescription('The amount you will pay.').setRequired(true))) - .addSubcommand((subcommand) => subcommand - .setName('take') - .setDescription('Take credits from a user. (ADMIN)') - .addUserOption((option) => option - .setName('user') - .setDescription('The user you want to take credits from.') - .setRequired(true)) - .addIntegerOption((option) => option.setName('amount').setDescription('The amount you will take.').setRequired(true))) .addSubcommand((subcommand) => subcommand .setName('balance') .setDescription("Check a user's balance.") @@ -56,47 +38,10 @@ module.exports = { .addIntegerOption((option) => option.setName('amount').setDescription('The amount you will pay.').setRequired(true)) .addStringOption((option) => option.setName('reason').setDescription('Your reason.'))) .addSubcommand((subcommand) => subcommand.setName('top').setDescription('Check the top balance.')) - .addSubcommand((subcommand) => subcommand - .setName('transfer') - .setDescription('Transfer credits from a user to another user. (ADMIN)') - .addUserOption((option) => option - .setName('from') - .setDescription('The user you want to take credits from.') - .setRequired(true)) - .addUserOption((option) => option - .setName('to') - .setDescription('The user you want to give credits to.') - .setRequired(true)) - .addIntegerOption((option) => option.setName('amount').setDescription('The amount you will transfer.').setRequired(true))) - .addSubcommand((subcommand) => subcommand - .setName('set') - .setDescription('Set credits on a user. (ADMIN)') - .addUserOption((option) => option - .setName('user') - .setDescription('The user you want to set credits on.') - .setRequired(true)) - .addIntegerOption((option) => option.setName('amount').setDescription('The amount you will set.').setRequired(true))) - .addSubcommand((subcommand) => subcommand - .setName('settings') - .setDescription('Manage credit settings. (ADMIN)') - .addBooleanOption((option) => option.setName('status').setDescription('Toggle credits.')) - .addStringOption((option) => option.setName('url').setDescription('Controlpanel.gg URL.')) - .addStringOption((option) => option.setName('token').setDescription('Controlpanel.gg token.')) - .addNumberOption((option) => option.setName('rate').setDescription('Credits rate.')) - .addNumberOption((option) => option.setName('minimum-length').setDescription('Minimum length for credits.')) - .addNumberOption((option) => option.setName('work-rate').setDescription('Work rate (rate).')) - .addNumberOption((option) => option - .setName('work-timeout') - .setDescription('Timeout between working for credits (milliseconds).')) - .addNumberOption((option) => option.setName('timeout').setDescription('Timeout between credits (milliseconds).'))) .addSubcommand((subcommand) => subcommand.setName('work').setDescription('Work for credits.')), async execute(interaction) { const guild = await guilds.findOne({ guildId: interaction.member.guild.id }); - if (interaction.options.getSubcommand() === 'settings') { - await settings(interaction); - } - if (guild.credits.status === false && interaction.options.getSubcommand() !== 'settings') { const embed = { title: 'Credits', @@ -112,18 +57,10 @@ module.exports = { await balance(interaction); } else if (interaction.options.getSubcommand() === 'gift') { await gift(interaction); - } else if (interaction.options.getSubcommand() === 'give') { - await give(interaction); } else if (interaction.options.getSubcommand() === 'redeem') { await redeem(interaction); - } else if (interaction.options.getSubcommand() === 'take') { - await take(interaction); } else if (interaction.options.getSubcommand() === 'top') { await top(interaction); - } else if (interaction.options.getSubcommand() === 'transfer') { - await transfer(interaction); - } else if (interaction.options.getSubcommand() === 'set') { - await set(interaction); } else if (interaction.options.getSubcommand() === 'work') { await work(interaction); } diff --git a/src/commands/profile/addons/view.js b/src/commands/profile/addons/view.js new file mode 100644 index 0000000..1beca33 --- /dev/null +++ b/src/commands/profile/addons/view.js @@ -0,0 +1,70 @@ +const i18next = require('i18next'); +const config = require('../../../../config.json'); +const logger = require('../../../handlers/logger'); + +const { users, credits, experiences } = require('../../../helpers/database/models'); + +module.exports = async (interaction) => { + try { + const { member } = await interaction; + + // Options + const target = await interaction.options.getUser('target'); + + const discordUser = await interaction.client.users.fetch(`${target ? target.id : member.id}`); + + // Databases + // Fetch user from user + const user = await users.findOne( + { userId: await discordUser.id }, + ); + + // Fetch credit from user and guild + const experience = await experiences.findOne( + { + userId: await discordUser.id, + guildId: await member.guild.id, + }, + ); + + // Fetch credit from user and guild + const credit = await credits.findOne( + { + userId: await discordUser.id, + guildId: await member.guild.id, + }, + ); + + // Language variables + const notAvailableText = i18next.t('general:not_available', { lng: await user.language }); + const reputationText = i18next.t('commands:profile:addons:view:embed:reputation', { lng: await user.language }); + const levelText = i18next.t('commands:profile:addons:view:embed:level', { lng: await user.language }); + const pointsText = i18next.t('commands:profile:addons:view:embed:points', { lng: await user.language }); + const creditsText = i18next.t('commands:profile:addons:view:embed:credits', { lng: await user.language }); + const languageCodeText = i18next.t('commands:profile:addons:view:embed:language_code', { lng: await user.language }); + + // Create embed + const embed = { + author: { + name: `${await discordUser.username}#${await discordUser.discriminator}`, + icon_url: await discordUser.displayAvatarURL(), + }, + color: config.colors.success, + fields: [ + { name: `:loudspeaker: ${reputationText}`, value: `${await user.reputation || `${notAvailableText}`}`, inline: true }, + { name: `:squeeze_bottle: ${levelText}`, value: `${await experience.level || `${notAvailableText}`}`, inline: true }, + { name: `:squeeze_bottle: ${pointsText}`, value: `${await experience.points || `${notAvailableText}`}`, inline: true }, + { name: `:money_with_wings: ${creditsText}`, value: `${await credit.balance || `${notAvailableText}`}`, inline: true }, + { name: `:rainbow_flag: ${languageCodeText}`, value: `${await user.language || `${notAvailableText}`}`, inline: true }, + ], + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + + // Send reply + return await interaction.editReply({ embeds: [embed], ephemeral: true }); + } catch (e) { + await logger.error(e); + } + return true; +}; diff --git a/src/commands/profile/index.js b/src/commands/profile/index.js new file mode 100644 index 0000000..a4d9afb --- /dev/null +++ b/src/commands/profile/index.js @@ -0,0 +1,17 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); + +const view = require('./addons/view'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('profile') + .setDescription('Your profile.') + .addSubcommand((subcommand) => subcommand.setName('view').setDescription('View a profile.').addUserOption((option) => option.setName('target') + .setDescription('The profile you wish to view'))), + async execute(interaction) { + if (interaction.options.getSubcommand() === 'view') { + await view(interaction); + } + return true; + }, +}; diff --git a/src/commands/reputation/addons/give.js b/src/commands/reputation/addons/give.js new file mode 100644 index 0000000..34587e0 --- /dev/null +++ b/src/commands/reputation/addons/give.js @@ -0,0 +1,59 @@ +const i18next = require('i18next'); +const config = require('../../../../config.json'); +const logger = require('../../../handlers/logger'); + +const users = require('../../../helpers/database/models/userSchema'); + +module.exports = async (interaction) => { + // Destructure member + + const { member } = interaction; + + // Get options + + const target = await interaction.options.getUser('target'); + const type = await interaction.options.getString('type'); + + // Do not allow self reputation + + if (target.id === interaction.member.id) { + // Build embed + + const embed = { title: 'Reputation', description: 'You can not repute yourself' }; + + // Send reply + + return interaction.editReply({ embeds: [embed] }); + } + + // Get user object + + const user = await users.findOne({ userId: interaction.member.id }); + + // Math operators depending on type of reputation + + if (type === 'positive') { user.reputation += 1; } + if (type === 'negative') { user.reputation -= 1; } + + // Save user + + await user.save(); + + // Build embed + + const embed = { + title: 'Reputation', + description: `You have given ${target} a ${type} reputation!`, + timestamp: new Date(), + color: config.colors.success, + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + + // Send reply + + await interaction.editReply({ embeds: [embed] }); + + // Send debug message + + await logger.debug(`Guild: ${member.guild.id} User: ${member.id} has given ${target.id} a ${type} reputation.`); +}; diff --git a/src/commands/reputation/index.js b/src/commands/reputation/index.js new file mode 100644 index 0000000..30bc41a --- /dev/null +++ b/src/commands/reputation/index.js @@ -0,0 +1,35 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { Permissions } = require('discord.js'); +const logger = require('../../handlers/logger'); + +const give = require('./addons/give'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('reputation') + .setDescription('Manage reputation.') + .addSubcommand((subcommand) => subcommand + .setName('give') + .setDescription('Give reputation for a user') + .addUserOption((option) => option.setName('target').setDescription('The user you want to repute.').setRequired(true)) + .addStringOption((option) => option.setName('type') + .setDescription('What type of reputation you want to repute').setRequired(true) + .addChoice('Positive', 'positive') + .addChoice('Negative', 'negative'))), + async execute(interaction) { + // Destructure member + + const { member } = interaction; + + // Command handler + + if (interaction.options.getSubcommand() === 'give') { + // Execute give addon + + await give(interaction); + } + // Send debug message + + await logger.debug(`Guild: ${member.guild.id} User: ${member.id} executed /${interaction.commandName} ${interaction.options.getSubcommand()}`); + }, +}; diff --git a/src/commands/settings/guild/addons/credits.js b/src/commands/settings/guild/addons/credits.js new file mode 100644 index 0000000..4917cdd --- /dev/null +++ b/src/commands/settings/guild/addons/credits.js @@ -0,0 +1,102 @@ +const { Permissions } = require('discord.js'); +const config = require('../../../../../config.json'); +const logger = require('../../../../handlers/logger'); + +// Database models + +const { guilds } = require('../../../../helpers/database/models'); + +module.exports = async (interaction) => { + // Destructure member + + const { member } = interaction; + + // Check permission + + if (!member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { + const embed = { + title: 'Settings', + color: config.colors.error, + description: 'You do not have permission to manage this!', + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Get options + + const status = await interaction.options.getBoolean('status'); + const rate = await interaction.options.getNumber('rate'); + const timeout = await interaction.options.getNumber('timeout'); + const minimumLength = await interaction.options.getNumber('minimum-length'); + const workRate = await interaction.options.getNumber('work-rate'); + const workTimeout = await interaction.options.getNumber('work-timeout'); + + // Get guild object + + const guild = await guilds.findOne({ guildId: interaction.member.guild.id }); + + // Modify values + + guild.credits.status = status !== null + ? status + : guild.credits.status; + guild.credits.rate = rate !== null + ? rate + : guild.credits.rate; + guild.credits.timeout = timeout !== null + ? timeout + : guild.credits.timeout; + guild.credits.workRate = workRate !== null + ? workRate + : guild.credits.workRate; + guild.credits.workTimeout = workTimeout !== null + ? workTimeout + : guild.credits.workTimeout; + guild.credits.minimumLength = minimumLength !== null + ? minimumLength + : guild.credits.minimumLength; + + // Save guild + + await guild.save().then(async () => { + // Build embed + + const embed = { + title: 'Credits', + description: 'Following settings is set!', + color: config.colors.success, + fields: [ + { name: '🤖 Status', value: `${guild.credits.status}`, inline: true }, + { name: '📈 Rate', value: `${guild.credits.rate}`, inline: true }, + { + name: '📈 Work Rate', + value: `${guild.credits.workRate}`, + inline: true, + }, + { + name: '🔨 Minimum Length', + value: `${guild.credits.minimumLength}`, + inline: true, + }, + { name: '⏰ Timeout', value: `${guild.credits.timeout}`, inline: true }, + { + name: '⏰ Work Timeout', + value: `${guild.credits.workTimeout}`, + inline: true, + }, + ], + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + + // Send reply + + await interaction.editReply({ embeds: [embed], ephemeral: true }); + + // Send debug message + + await logger.debug(`Guild: ${member.guild.id} User: ${member.id} has changed credit details.`); + }); +}; diff --git a/src/commands/settings/guild/addons/index.js b/src/commands/settings/guild/addons/index.js new file mode 100644 index 0000000..8a3eb63 --- /dev/null +++ b/src/commands/settings/guild/addons/index.js @@ -0,0 +1,4 @@ +const pterodactyl = require('./pterodactyl'); +const credits = require('./credits'); + +module.exports = { pterodactyl, credits }; diff --git a/src/commands/settings/guild/addons/pterodactyl.js b/src/commands/settings/guild/addons/pterodactyl.js new file mode 100644 index 0000000..cc1b1a7 --- /dev/null +++ b/src/commands/settings/guild/addons/pterodactyl.js @@ -0,0 +1,57 @@ +const { Permissions } = require('discord.js'); +const config = require('../../../../../config.json'); +const logger = require('../../../../handlers/logger'); + +// Database models + +const { apis } = require('../../../../helpers/database/models'); + +module.exports = async (interaction) => { + // Destructure member + + const { member } = interaction; + + // Check permission + + if (!member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { + const embed = { + title: 'Settings', + color: config.colors.error, + description: 'You do not have permission to manage this!', + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + return interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Get options + + const url = await interaction.options.getString('url'); + const token = await interaction.options.getString('token'); + + // Update API credentials + + await apis.findOneAndUpdate( + { guildId: member.guild.id }, + { url, token }, + { new: true, upsert: true }, + ).then(async () => { + // Build embed + + const embed = { + title: 'Settings', + color: config.colors.success, + description: 'Pterodactyl settings is saved!', + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + + // Send reply + + await interaction.editReply({ embeds: [embed], ephemeral: true }); + + // Send debug message + + await logger.debug(`Guild: ${member.guild.id} User: ${member.id} has changed api credentials.`); + }); +}; diff --git a/src/commands/settings/guild/index.js b/src/commands/settings/guild/index.js new file mode 100644 index 0000000..22d60a1 --- /dev/null +++ b/src/commands/settings/guild/index.js @@ -0,0 +1,40 @@ +const { Permissions } = require('discord.js'); +const config = require('../../../../config.json'); +const logger = require('../../../handlers/logger'); + +const { pterodactyl, credits } = require('./addons'); + +module.exports = async (interaction) => { + // Destructure member + + const { member } = interaction; + + // Check permission + + if (!member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { + const embed = { + title: 'Settings', + color: config.colors.error, + description: 'You do not have permission to manage this!', + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + await interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Command handler + + if (interaction.options.getSubcommand() === 'pterodactyl') { + // Execute pterodactyl addon + + await pterodactyl(interaction); + } else if (interaction.options.getSubcommand() === 'credits') { + // Execute credits addon + + await credits(interaction); + } + + // Send debug message + + await logger.debug(`Guild: ${member.guild.id} User: ${member.id} executed /${interaction.commandName} ${interaction.options.getSubcommandGroup()} ${interaction.options.getSubcommand()}`); +}; diff --git a/src/commands/settings/index.js b/src/commands/settings/index.js new file mode 100644 index 0000000..86c91e7 --- /dev/null +++ b/src/commands/settings/index.js @@ -0,0 +1,53 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { Permissions } = require('discord.js'); + +const guild = require('./guild'); +const user = require('./user'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('settings') + .setDescription('Manage settings.') + .addSubcommandGroup((group) => group + .setName('guild') + .setDescription('Manage guild settings.') + .addSubcommand((command) => command + .setName('pterodactyl') + .setDescription('Controlpanel.gg') + .addStringOption((option) => option.setName('url').setDescription('The api url').setRequired(true)) + .addStringOption((option) => option.setName('token').setDescription('The api token').setRequired(true))) + .addSubcommand((command) => command + .setName('credits') + .setDescription('Credits') + .addBooleanOption((option) => option.setName('status').setDescription('Should credits be enabled?')) + .addNumberOption((option) => option.setName('rate').setDescription('Amount of credits per message.')) + .addNumberOption((option) => option + .setName('minimum-length') + .setDescription('Minimum length of message to earn credits.')) + .addNumberOption((option) => option.setName('work-rate').setDescription('Maximum amount of credits on work.')) + .addNumberOption((option) => option + .setName('work-timeout') + .setDescription('Timeout between work schedules (milliseconds).')) + .addNumberOption((option) => option + .setName('timeout') + .setDescription('Timeout between earning credits (milliseconds).')))) + .addSubcommandGroup((group) => group + .setName('user') + .setDescription('Manage user settings.') + .addSubcommand((command) => command + .setName('appearance') + .setDescription('Manage your appearance') + .addStringOption((option) => option + .setName('language') + .setDescription('Configure your language') + .addChoice('English', 'en') + .addChoice('Swedish', 'se')))), + async execute(interaction) { + if (interaction.options.getSubcommandGroup() === 'guild') { + await guild(interaction); + } else if (interaction.options.getSubcommandGroup() === 'user') { + await user(interaction); + } + return true; + }, +}; diff --git a/src/commands/settings/user/addons/appearance.js b/src/commands/settings/user/addons/appearance.js new file mode 100644 index 0000000..6ee3571 --- /dev/null +++ b/src/commands/settings/user/addons/appearance.js @@ -0,0 +1,54 @@ +const { Permissions } = require('discord.js'); +const config = require('../../../../../config.json'); +const logger = require('../../../../handlers/logger'); + +// Database models + +const { users } = require('../../../../helpers/database/models'); + +module.exports = async (interaction) => { + // Destructure member + + const { member } = interaction; + + // Get options + + const language = await interaction.options.getString('language'); + + // Get user object + + const user = await users.findOne({ userId: interaction.member.id }); + + // Modify values + + user.language = language !== null ? language : user.language; + + // Save guild + + await user.save().then(async () => { + // Build embed + + const embed = { + title: 'Appearance', + description: 'Following settings is set!', + color: config.colors.success, + fields: [ + { + name: '🏳️‍🌈 Language', + value: `${user.language}`, + inline: true, + }, + ], + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + + // Send reply + + await interaction.editReply({ embeds: [embed], ephemeral: true }); + + // Send debug message + + await logger.debug(`Guild: ${member.guild.id} User: ${member.id} has changed appearance settings.`); + }); +}; diff --git a/src/commands/settings/user/addons/index.js b/src/commands/settings/user/addons/index.js new file mode 100644 index 0000000..1892e7a --- /dev/null +++ b/src/commands/settings/user/addons/index.js @@ -0,0 +1,3 @@ +const appearance = require('./appearance'); + +module.exports = { appearance }; diff --git a/src/commands/settings/user/index.js b/src/commands/settings/user/index.js new file mode 100644 index 0000000..8a8c304 --- /dev/null +++ b/src/commands/settings/user/index.js @@ -0,0 +1,36 @@ +const { Permissions } = require('discord.js'); +const config = require('../../../../config.json'); +const logger = require('../../../handlers/logger'); + +const { appearance } = require('./addons'); + +module.exports = async (interaction) => { + // Destructure member + + const { member } = interaction; + + // Check permission + + if (!member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { + const embed = { + title: 'Settings', + color: config.colors.error, + description: 'You do not have permission to manage this!', + timestamp: new Date(), + footer: { iconURL: config.footer.icon, text: config.footer.text }, + }; + await interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // Command handler + + if (interaction.options.getSubcommand() === 'appearance') { + // Execute appearance addon + + await appearance(interaction); + } + + // Send debug message + + await logger.debug(`Guild: ${member.guild.id} User: ${member.id} executed /${interaction.commandName} ${interaction.options.getSubcommandGroup()} ${interaction.options.getSubcommand()}`); +}; diff --git a/src/commands/utilities/addons/users.js b/src/commands/utilities/addons/users.js new file mode 100644 index 0000000..a879777 --- /dev/null +++ b/src/commands/utilities/addons/users.js @@ -0,0 +1,30 @@ +const { Permissions } = require('discord.js'); + +const config = require('../../../../config.json'); +const logger = require('../../../handlers/logger'); + +module.exports = async (interaction) => { + try { + if (!interaction.member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { + const embed = { + title: 'Users failed', + description: 'You need to have permission to manage this guild (MANAGE_GUILD)', + }; + return await interaction.editReply({ embeds: [embed], ephemeral: true }); + } + + // eslint-disable-next-line max-len + const userList = await interaction.client.users.cache.filter((user) => !user.bot); + + userList.map((user) => { logger.info(user); }); + + // await interaction.client.guilds.cache.get(interaction.member.guild.id).then((user) => logger.info(user)); + + // await interaction.client.users.fetch().then(async (user) => await logger.info(`${user}`)); + // // interaction.client.users.fetch().then((user) => { + // // console.log(user); + // // }).catch(console.error); + } catch { + await logger.error(); + } +}; diff --git a/src/commands/utilities/index.js b/src/commands/utilities/index.js index 1910ed7..2c455fc 100644 --- a/src/commands/utilities/index.js +++ b/src/commands/utilities/index.js @@ -2,6 +2,7 @@ const { SlashCommandBuilder } = require('@discordjs/builders'); const { Permissions } = require('discord.js'); const lookup = require('./addons/lookup'); +const users = require('./addons/users'); module.exports = { permissions: new Permissions([ @@ -19,10 +20,15 @@ module.exports = { .addStringOption((option) => option .setName('target') .setDescription('The target you want to look up.') - .setRequired(true))), + .setRequired(true))) + .addSubcommand((subcommand) => subcommand + .setName('users') + .setDescription('Iterate all users (ADMIN)')), async execute(interaction) { if (interaction.options.getSubcommand() === 'lookup') { await lookup(interaction); + } else if (interaction.options.getSubcommand() === 'users') { + await users(interaction); } }, }; diff --git a/src/events/guildCreate.js b/src/events/guildCreate.js index b68efb7..5ba143a 100644 --- a/src/events/guildCreate.js +++ b/src/events/guildCreate.js @@ -3,7 +3,7 @@ const logger = require('../handlers/logger'); const guilds = require('../helpers/database/models/guildSchema'); module.exports = { - name: 'interactionCreate', + name: 'guildCreate', async execute(guild) { const guildExist = await guilds .findOne({ guildId: guild.id }) diff --git a/src/events/interactionCreate.js b/src/events/interactionCreate.js index 64092cf..b8bcbaa 100644 --- a/src/events/interactionCreate.js +++ b/src/events/interactionCreate.js @@ -6,53 +6,83 @@ const guilds = require('../helpers/database/models/guildSchema'); module.exports = { name: 'interactionCreate', async execute(interaction) { - if (!interaction.isCommand()) return; + if (interaction.isCommand()) { + const command = interaction.client.commands.get(interaction.commandName); - const command = interaction.client.commands.get(interaction.commandName); + if (!command) return; - if (!command) return; + const guildExist = await guilds.findOne({ guildId: interaction.member.guild.id }); - const guildExist = await guilds.findOne({ guildId: interaction.member.guild.id }); + if (!guildExist) { + await guilds.create({ guildId: interaction.member.guild.id }); + } - if (!guildExist) { await guilds.create({ guildId: interaction.member.guild.id }); } - - try { - await interaction.deferReply({ - embeds: [ - { - author: { - name: interaction.client.user.username, - icon_url: interaction.client.user.displayAvatarURL(), - url: 'https://bot.zyner.org/', + try { + await interaction.deferReply({ + embeds: [ + { + author: { + name: interaction.client.user.username, + icon_url: interaction.client.user.displayAvatarURL(), + url: 'https://bot.zyner.org/', + }, + title: 'Check', + description: 'Please wait...', + color: config.colors.wait, + timestamp: new Date(), }, - title: 'Check', - description: 'Please wait...', - color: config.colors.wait, - timestamp: new Date(), - }, - ], - ephemeral: true, - }); - await command.execute(interaction); - await logger.debug(`Executing command: ${interaction.commandName}`); - } catch (err) { - await logger.error(err); - await interaction.reply({ - embeds: [ - { - author: { - name: interaction.client.user.username, - icon_url: interaction.client.user.displayAvatarURL(), - url: 'https://bot.zyner.org/', + ], + ephemeral: true, + }); + await command.execute(interaction); + await logger.debug(`Executing command: ${interaction.commandName}`); + } catch (err) { + await logger.error(err); + await interaction.reply({ + embeds: [ + { + author: { + name: interaction.client.user.username, + icon_url: interaction.client.user.displayAvatarURL(), + url: 'https://bot.zyner.org/', + }, + title: 'Error', + description: 'There was an error while executing this command!', + color: config.colors.error, + timestamp: new Date(), }, - title: 'Error', - description: 'There was an error while executing this command!', - color: config.colors.error, - timestamp: new Date(), - }, - ], - ephemeral: true, - }); + ], + ephemeral: true, + }); + } + } else if (interaction.isButton()) { + const button = interaction.client.buttons.get(interaction.customId); + + try { + if (!button) { + await interaction.deferReply(); + await interaction.editReply({ content: `Button not exist: ${interaction.customId}` }); + } + + await button.execute(interaction); + await logger.debug(`Button pressed: ${interaction.customId}`); + } catch (err) { + await logger.error(err); + } + } else if (interaction.isSelectMenu()) { + const menu = interaction.client.menus.get(interaction.customId); + + try { + if (!menu) { + await interaction.deferReply(); + await interaction.editReply({ content: `Menu not exist: ${interaction.customId}` }); + } + + await menu.execute(interaction); + await logger.debug(`Menu pressed: ${interaction.customId}`); + } catch (err) { + await logger.error(err); + } } }, }; diff --git a/src/events/memberCreate.js b/src/events/memberCreate.js new file mode 100644 index 0000000..ea6bc42 --- /dev/null +++ b/src/events/memberCreate.js @@ -0,0 +1,20 @@ +const logger = require('../handlers/logger'); + +const users = require('../helpers/database/models/userSchema'); + +module.exports = { + name: 'interactionCreate', + async execute(user) { + // const guildExist = await guilds + // .findOne({ guildId: guild.id }) + // .then(logger.debug(`Found guild: ${guild.id}`)) + // .catch(logger.error); + + // if (!guildExist) { + // await guilds + // .create({ guildId: guild.id }) + // .then(() => logger.debug(`Create guild: ${guild.id} was success`)) + // .catch((e) => logger.error(e)); + // } + }, +}; diff --git a/src/events/messageCreate.js b/src/events/messageCreate.js index ed879c9..10dbbbd 100644 --- a/src/events/messageCreate.js +++ b/src/events/messageCreate.js @@ -1,8 +1,11 @@ const config = require('../../config.json'); const logger = require('../handlers/logger'); +const users = require('../helpers/database/models/userSchema'); const guilds = require('../helpers/database/models/guildSchema'); +const experiences = require('../helpers/database/models/experienceSchema'); const credits = require('../helpers/database/models/creditSchema'); +const timeouts = require('../helpers/database/models/timeoutSchema'); const talkedRecently = new Set(); @@ -12,9 +15,23 @@ module.exports = { const guild = await guilds.findOne({ guildId: message.guild.id }); if (message.author.bot) return; + + const userExist = await users.findOne({ userId: message.author.id }); + + if (!userExist) { await users.create({ userId: message.author.id }); } + if (message.content.length < guild.credits.minimumLength) return; if (config.credits.excludedChannels.includes(message.channel.id)) return; - if (!talkedRecently.has(message.author.id)) { + + const isTimeout = await timeouts.findOne( + { + guildId: message.guild.id, + userId: message.author.id, + timeoutId: 1, + }, + ); + + if (!isTimeout) { await credits .findOneAndUpdate( { userId: message.author.id, guildId: message.guild.id }, @@ -25,17 +42,43 @@ module.exports = { .catch(async (err) => { await logger.error(err); }); - talkedRecently.add(message.author.id); - setTimeout(() => { - logger.debug( + + // Experience System + await experiences + .findOneAndUpdate( + { userId: message.author.id, guildId: message.guild.id }, + { $inc: { points: guild.points.rate } }, + { new: true, upsert: true }, + ) + .then(async () => logger.debug(`Credits added to user: ${message.author.id}`)) + .catch(async (err) => { + await logger.error(err); + }); + + await timeouts.create( + { + guildId: message.guild.id, + userId: message.author.id, + timeoutId: 1, + }, + ); + + // talkedRecently.add(message.author.id); + setTimeout(async () => { + await logger.debug( `User: ${message.author.id} has not talked within last ${ guild.credits.timeout / 1000 } seconds, credits can be given`, ); - talkedRecently.delete(message.author.id); + await timeouts.deleteOne({ + guildId: message.guild.id, + userId: message.author.id, + timeoutId: 1, + }); + // talkedRecently.delete(message.author.id); }, guild.credits.timeout); } else { - logger.debug( + await logger.debug( `User: ${message.author.id} has talked within last ${ guild.credits.timeout / 1000 } seconds, no credits given`, diff --git a/src/handlers/locale.js b/src/handlers/locale.js new file mode 100644 index 0000000..526619c --- /dev/null +++ b/src/handlers/locale.js @@ -0,0 +1,55 @@ +const i18next = require('i18next'); + +module.exports = async () => { + await i18next.init({ + lng: 'en', // if you're using a language detector, do not define the lng option + // debug: true, + fallbackLng: 'en', + resources: { + en: { + general: { not_available: 'Not Available' }, + commands: { + credits: { + general: { + credits_one: '{{count}} credit', + credits_other: '{{count}} credits', + }, + addons: { balance: { embed: { title: 'Credits' } }, gift: { embed: { title: 'Gift' } } }, + }, + profile: { + addons: { + view: { + embed: { + title: 'Profile', reputation: 'Reputation (Global)', level: 'Level (Global)', points: 'Points (Global)', credits: 'Credits (Guild)', language_code: 'Language Code (Global)', + }, + }, + settings: { embed: { title: 'Profile', description: 'Following settings is set', fields: { language: 'Language' } } }, + }, + }, + }, + }, + sv: { + general: { not_available: 'Ej tillgängligt' }, + commands: { + credits: { + general: { + credits_one: '{{count}} krona', + credits_other: '{{count}} kronor', + }, + addons: { balance: { embed: { title: 'Krediter' } }, gift: { embed: { title: 'Gåva' } } }, + }, + profile: { + addons: { + view: { + embed: { + title: 'Profil', reputation: 'Omdöme (Globalt)', level: 'Nivå (Globalt)', points: 'Poäng (Globalt)', credits: 'Krediter (Server)', language_code: 'Språkkod (Globalt)', + }, + }, + settings: { embed: { title: 'Profil', description: 'Följande inställningar är satta', fields: { language: 'Språk' } } }, + }, + }, + }, + }, + }, + }); +}; diff --git a/src/helpers/database/models/apiSchema.js b/src/helpers/database/models/apiSchema.js new file mode 100644 index 0000000..bdd3345 --- /dev/null +++ b/src/helpers/database/models/apiSchema.js @@ -0,0 +1,28 @@ +const mongoose = require('mongoose'); + +const apiSchema = new mongoose.Schema( + { + + guildId: { + type: mongoose.SchemaTypes.Decimal128, + required: true, + unique: false, + index: true, + }, + url: { + type: mongoose.SchemaTypes.String, + required: true, + unique: false, + index: true, + }, + token: { + type: mongoose.SchemaTypes.String, + required: true, + unique: false, + index: true, + }, + }, + { timestamps: true }, +); + +module.exports = mongoose.model('api', apiSchema); diff --git a/src/helpers/database/models/creditSchema.js b/src/helpers/database/models/creditSchema.js index c98e500..c00740c 100644 --- a/src/helpers/database/models/creditSchema.js +++ b/src/helpers/database/models/creditSchema.js @@ -11,7 +11,7 @@ const creditSchema = new mongoose.Schema( guildId: { type: mongoose.SchemaTypes.Decimal128, required: true, - unique: true, + unique: false, index: true, }, balance: { diff --git a/src/helpers/database/models/experienceSchema.js b/src/helpers/database/models/experienceSchema.js new file mode 100644 index 0000000..e139073 --- /dev/null +++ b/src/helpers/database/models/experienceSchema.js @@ -0,0 +1,35 @@ +const mongoose = require('mongoose'); + +const experienceSchema = new mongoose.Schema( + { + userId: { + type: mongoose.SchemaTypes.Decimal128, + required: true, + unique: false, + index: true, + }, + guildId: { + type: mongoose.SchemaTypes.Decimal128, + required: true, + unique: false, + index: true, + }, + level: { + type: mongoose.SchemaTypes.Number, + required: true, + unique: false, + default: 0, + index: false, + }, + points: { + type: mongoose.SchemaTypes.Number, + required: true, + unique: false, + default: 0, + index: false, + }, + }, + { timestamps: true }, +); + +module.exports = mongoose.model('experience', experienceSchema); diff --git a/src/helpers/database/models/guildSchema.js b/src/helpers/database/models/guildSchema.js index f6e2d20..1c03097 100644 --- a/src/helpers/database/models/guildSchema.js +++ b/src/helpers/database/models/guildSchema.js @@ -40,8 +40,40 @@ const guildSchema = new mongoose.Schema( default: 900000, }, }, + points: { + status: { + type: mongoose.SchemaTypes.Boolean, + default: false, + }, + url: { + type: mongoose.SchemaTypes.String, + }, + token: { + type: mongoose.SchemaTypes.String, + }, + rate: { + type: mongoose.SchemaTypes.Number, + default: 1, + }, + minimumLength: { + type: mongoose.SchemaTypes.Number, + default: 5, + }, + timeout: { + type: mongoose.SchemaTypes.Number, + default: 5000, + }, + workRate: { + type: mongoose.SchemaTypes.Number, + default: 15, + }, + workTimeout: { + type: mongoose.SchemaTypes.Number, + default: 900000, + }, + }, }, - { timestamps: true } + { timestamps: true }, ); module.exports = mongoose.model('guild', guildSchema); diff --git a/src/helpers/database/models/index.js b/src/helpers/database/models/index.js new file mode 100644 index 0000000..b79468b --- /dev/null +++ b/src/helpers/database/models/index.js @@ -0,0 +1,10 @@ +const credits = require('./creditSchema'); +const experiences = require('./experienceSchema'); +const users = require('./userSchema'); +const guilds = require('./guildSchema'); +const apis = require('./apiSchema'); +const timeouts = require('./timeoutSchema'); + +module.exports = { + credits, experiences, users, guilds, apis, timeouts, +}; diff --git a/src/helpers/database/models/timeoutSchema.js b/src/helpers/database/models/timeoutSchema.js new file mode 100644 index 0000000..9dd012a --- /dev/null +++ b/src/helpers/database/models/timeoutSchema.js @@ -0,0 +1,22 @@ +const mongoose = require('mongoose'); + +const timeoutSchema = new mongoose.Schema( + { + userId: { + type: mongoose.SchemaTypes.Decimal128, + required: true, + unique: false, + index: true, + }, + guildId: { + type: mongoose.SchemaTypes.Decimal128, + required: true, + unique: false, + index: true, + }, + timeoutId: { type: mongoose.SchemaTypes.Number }, + }, + { timestamps: true }, +); + +module.exports = mongoose.model('timeout', timeoutSchema); diff --git a/src/helpers/database/models/userSchema.js b/src/helpers/database/models/userSchema.js new file mode 100644 index 0000000..41b42cd --- /dev/null +++ b/src/helpers/database/models/userSchema.js @@ -0,0 +1,20 @@ +const mongoose = require('mongoose'); + +const userSchema = new mongoose.Schema( + { + userId: { + type: mongoose.SchemaTypes.Decimal128, + required: true, + unique: true, + index: true, + }, + language: { + type: mongoose.SchemaTypes.String, + default: 'en', + }, + reputation: { type: mongoose.SchemaTypes.Number, default: 0 }, + }, + { timestamps: true }, +); + +module.exports = mongoose.model('user', userSchema); diff --git a/src/index.js b/src/index.js index 39b3853..8abea71 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ /* eslint-disable no-restricted-syntax */ require('./deploy-commands')(); require('./helpers/database')(); +require('./handlers/locale')(); const fs = require('fs'); const { Client, Collection, Intents } = require('discord.js'); @@ -20,6 +21,24 @@ for (const file of commandFiles) { client.commands.set(command.data.name, command); } +client.buttons = new Collection(); +const buttonFiles = fs.readdirSync('./src/buttons'); + +for (const file of buttonFiles) { + // eslint-disable-next-line import/no-dynamic-require, global-require + const button = require(`./buttons/${file}`); + client.buttons.set(button.customId, button); +} + +client.menus = new Collection(); +const menuFiles = fs.readdirSync('./src/menus'); + +for (const file of menuFiles) { + // eslint-disable-next-line import/no-dynamic-require, global-require + const menu = require(`./menus/${file}`); + client.menus.set(menu.customId, menu); +} + for (const file of eventFiles) { // eslint-disable-next-line import/no-dynamic-require, global-require const event = require(`./events/${file}`);