diff --git a/.vscode/extensions.json b/.vscode/extensions.json index cdc6a09..14826d3 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -11,14 +11,14 @@ "donjayamanne.githistory", "eamodio.gitlens", "esbenp.prettier-vscode", - "GitHub.github-vscode-theme", - "IronGeek.vscode-env", - "xabikos.JavaScriptSnippets", + "github.github-vscode-theme", + "irongeek.vscode-env", + "xabikos.javascriptsnippets", "wix.vscode-import-cost", "vscode-icons-team.vscode-icons", - "VisualStudioExptTeam.vscodeintellicode", + "visualstudioexptteam.vscodeintellicode", "teledemic.branch-warnings", - "TabNine.tabnine-vscode", + "tabnine.tabnine-vscode", "streetsidesoftware.code-spell-checker", "seatonjiang.gitmoji-vscode", "sburg.vscode-javascript-booster", @@ -34,13 +34,19 @@ "ms-vscode.vscode-js-profile-table", "pflannery.vscode-versionlens", "adpyke.codesnap", - "Anan.devdocstab", + "anan.devdocstab", "axosoft.gitkraken-glo", - "Gruntfuggly.todo-tree", + "gruntfuggly.todo-tree", "kiteco.kite", "lkytal.pomodoro", "wayou.vscode-todo-highlight", - "johnpapa.vscode-peacock" + "johnpapa.vscode-peacock", + "stepsize.stepsize", + "nicoespeon.abracadabra", + "sonarsource.sonarlint-vscode", + "nicoespeon.hocus-pocus", + "aaron-bond.better-comments", + "oouo-diogo-perdigao.docthis" ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [] diff --git a/config.json.example b/config.json.example index 878b03d..d9d5409 100644 --- a/config.json.example +++ b/config.json.example @@ -27,5 +27,6 @@ "reputation": { "timeout": 86400000 }, - "importToDB": false + "importToDB": false, + "clearUnused": false } diff --git a/src/commands/admin/credits/modules/give.ts b/src/commands/admin/credits/modules/give.ts index bb4bd3d..5fcfb98 100644 --- a/src/commands/admin/credits/modules/give.ts +++ b/src/commands/admin/credits/modules/give.ts @@ -1,17 +1,17 @@ // Dependencies -import { CommandInteraction, ColorResolvable } from "discord.js"; +import { CommandInteraction, ColorResolvable } from 'discord.js'; // Configurations -import config from "../../../../../config.json"; +import config from '../../../../../config.json'; // Handlers -import logger from "../../../../handlers/logger"; +import logger from '../../../../handlers/logger'; // Helpers -import creditNoun from "../../../../helpers/creditNoun"; +import creditNoun from '../../../../helpers/creditNoun'; // Models -import userSchema from "../../../../helpers/database/models/userSchema"; +import fetchUser from '../../../../helpers/fetchUser'; // Function export default async (interaction: CommandInteraction) => { @@ -19,17 +19,17 @@ export default async (interaction: CommandInteraction) => { const { guild, user, options } = interaction; // User option - const optionUser = options?.getUser("user"); + const optionUser = options?.getUser('user'); // Amount option - const optionAmount = options?.getInteger("amount"); + const optionAmount = options?.getInteger('amount'); // If amount option is null if (optionAmount === null) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Give]" as string, - description: "We could not read your requested amount." as string, + title: ':toolbox: Admin - Credits [Give]' as string, + description: 'We could not read your requested amount.' as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, footer: { @@ -46,8 +46,8 @@ export default async (interaction: CommandInteraction) => { if (optionAmount <= 0) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Give]" as string, - description: "You can not give zero credits or below." as string, + title: ':toolbox: Admin - Credits [Give]' as string, + description: 'You can not give zero credits or below.' as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, footer: { @@ -60,17 +60,17 @@ export default async (interaction: CommandInteraction) => { return await interaction?.editReply({ embeds: [embed] }); } + if (optionUser === null) return; + if (guild === null) return; + // toUser Information - const toUser = await userSchema?.findOne({ - userId: optionUser?.id, - guildId: guild?.id, - }); + const toUser = await fetchUser(optionUser, guild); // If toUser does not exist if (!toUser) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Give]" as string, + title: ':toolbox: Admin - Credits [Give]' as string, description: `We could not find ${optionUser} in our database.` as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, @@ -88,7 +88,7 @@ export default async (interaction: CommandInteraction) => { if (!toUser?.credits) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Give]" as string, + title: ':toolbox: Admin - Credits [Give]' as string, description: `We could not find credits for ${optionUser} in our database.` as string, color: config?.colors?.error as ColorResolvable, @@ -110,7 +110,7 @@ export default async (interaction: CommandInteraction) => { await toUser?.save()?.then(async () => { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Give]" as string, + title: ':toolbox: Admin - Credits [Give]' as string, description: `We have given ${optionUser}, ${creditNoun( optionAmount )}.` as string, diff --git a/src/commands/admin/credits/modules/set.ts b/src/commands/admin/credits/modules/set.ts index c291f4a..7fbafce 100644 --- a/src/commands/admin/credits/modules/set.ts +++ b/src/commands/admin/credits/modules/set.ts @@ -1,17 +1,17 @@ // Dependencies -import { Permissions, CommandInteraction, ColorResolvable } from "discord.js"; +import { Permissions, CommandInteraction, ColorResolvable } from 'discord.js'; // Configurations -import config from "../../../../../config.json"; +import config from '../../../../../config.json'; // Handlers -import logger from "../../../../handlers/logger"; +import logger from '../../../../handlers/logger'; // Helpers -import creditNoun from "../../../../helpers/creditNoun"; +import creditNoun from '../../../../helpers/creditNoun'; // Models -import userSchema from "../../../../helpers/database/models/userSchema"; +import fetchUser from '../../../../helpers/fetchUser'; // Function export default async (interaction: CommandInteraction) => { @@ -19,17 +19,17 @@ export default async (interaction: CommandInteraction) => { const { options, user, guild } = interaction; // User Option - const optionUser = options.getUser("user"); + const optionUser = options.getUser('user'); // Amount Option - const optionAmount = options.getInteger("amount"); + const optionAmount = options.getInteger('amount'); // If amount is null if (optionAmount === null) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Set]" as string, - description: "We could not read your requested amount." as string, + title: ':toolbox: Admin - Credits [Set]' as string, + description: 'We could not read your requested amount.' as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, footer: { @@ -42,17 +42,17 @@ export default async (interaction: CommandInteraction) => { return await interaction?.editReply({ embeds: [embed] }); } + if (optionUser === null) return; + if (guild === null) return; + // toUser Information - const toUser = await userSchema?.findOne({ - userId: optionUser?.id, - guildId: guild?.id, - }); + const toUser = await fetchUser(optionUser, guild); // If toUser does not exist if (!toUser) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Set]" as string, + title: ':toolbox: Admin - Credits [Set]' as string, description: `We could not find ${optionUser} in our database.` as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, @@ -70,7 +70,7 @@ export default async (interaction: CommandInteraction) => { if (!toUser?.credits) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Set]" as string, + title: ':toolbox: Admin - Credits [Set]' as string, description: `We could not find credits for ${optionUser} in our database.` as string, color: config?.colors?.error as ColorResolvable, @@ -92,7 +92,7 @@ export default async (interaction: CommandInteraction) => { await toUser?.save()?.then(async () => { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Set]" as string, + title: ':toolbox: Admin - Credits [Set]' as string, description: `We have set ${optionUser} to ${creditNoun( optionAmount )}` as string, diff --git a/src/commands/admin/credits/modules/take.ts b/src/commands/admin/credits/modules/take.ts index f9680b7..b78412a 100644 --- a/src/commands/admin/credits/modules/take.ts +++ b/src/commands/admin/credits/modules/take.ts @@ -1,17 +1,17 @@ // Dependencies -import { Permissions, CommandInteraction, ColorResolvable } from "discord.js"; +import { Permissions, CommandInteraction, ColorResolvable } from 'discord.js'; // Configurations -import config from "../../../../../config.json"; +import config from '../../../../../config.json'; // Handlers -import logger from "../../../../handlers/logger"; +import logger from '../../../../handlers/logger'; // Helpers -import creditNoun from "../../../../helpers/creditNoun"; +import creditNoun from '../../../../helpers/creditNoun'; // Models -import userSchema from "../../../../helpers/database/models/userSchema"; +import fetchUser from '../../../../helpers/fetchUser'; // Function export default async (interaction: CommandInteraction) => { @@ -19,17 +19,17 @@ export default async (interaction: CommandInteraction) => { const { guild, user, options } = interaction; // User option - const optionUser = options?.getUser("user"); + const optionUser = options?.getUser('user'); // Amount option - const optionAmount = options?.getInteger("amount"); + const optionAmount = options?.getInteger('amount'); // If amount is null if (optionAmount === null) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Take]" as string, - description: "We could not read your requested amount." as string, + title: ':toolbox: Admin - Credits [Take]' as string, + description: 'We could not read your requested amount.' as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, footer: { @@ -46,8 +46,8 @@ export default async (interaction: CommandInteraction) => { if (optionAmount <= 0) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Take]" as string, - description: "You can not take zero credits or below." as string, + title: ':toolbox: Admin - Credits [Take]' as string, + description: 'You can not take zero credits or below.' as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, footer: { @@ -60,17 +60,17 @@ export default async (interaction: CommandInteraction) => { return await interaction?.editReply({ embeds: [embed] }); } + if (optionUser === null) return; + if (guild === null) return; + // toUser Information - const toUser = await userSchema?.findOne({ - userId: optionUser?.id, - guildId: guild?.id, - }); + const toUser = await fetchUser(optionUser, guild); // If toUser does not exist if (!toUser) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Take]" as string, + title: ':toolbox: Admin - Credits [Take]' as string, description: `We could not find ${optionUser} in our database.` as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, @@ -88,7 +88,7 @@ export default async (interaction: CommandInteraction) => { if (!toUser?.credits) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Take]" as string, + title: ':toolbox: Admin - Credits [Take]' as string, description: `We could not find credits for ${optionUser} in our database.` as string, color: config?.colors?.error as ColorResolvable, @@ -110,7 +110,7 @@ export default async (interaction: CommandInteraction) => { await toUser?.save()?.then(async () => { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Set]" as string, + title: ':toolbox: Admin - Credits [Set]' as string, description: `We have taken ${creditNoun( optionAmount )} from ${optionUser}` as string, diff --git a/src/commands/admin/credits/modules/transfer.ts b/src/commands/admin/credits/modules/transfer.ts index 04a00cc..1c7101d 100644 --- a/src/commands/admin/credits/modules/transfer.ts +++ b/src/commands/admin/credits/modules/transfer.ts @@ -1,18 +1,18 @@ // Dependencies -import { CommandInteraction, ColorResolvable } from "discord.js"; +import { CommandInteraction, ColorResolvable } from 'discord.js'; // Configurations -import config from "../../../../../config.json"; +import config from '../../../../../config.json'; // Handlers -import logger from "../../../../handlers/logger"; +import logger from '../../../../handlers/logger'; // Helpers -import creditNoun from "../../../../helpers/creditNoun"; -import saveUser from "../../../../helpers/saveUser"; +import creditNoun from '../../../../helpers/creditNoun'; +import saveUser from '../../../../helpers/saveUser'; // Models -import userSchema from "../../../../helpers/database/models/userSchema"; +import fetchUser from '../../../../helpers/fetchUser'; // Function export default async (interaction: CommandInteraction) => { @@ -20,16 +20,16 @@ export default async (interaction: CommandInteraction) => { const { guild, options, user } = interaction; // Get options - const optionFromUser = options?.getUser("from"); - const optionToUser = options?.getUser("to"); - const optionAmount = options?.getInteger("amount"); + const optionFromUser = options?.getUser('from'); + const optionToUser = options?.getUser('to'); + const optionAmount = options?.getInteger('amount'); // If amount is null if (optionAmount === null) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Transfer]" as string, - description: "We could not read your requested amount." as string, + title: ':toolbox: Admin - Credits [Transfer]' as string, + description: 'We could not read your requested amount.' as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, footer: { @@ -42,23 +42,21 @@ export default async (interaction: CommandInteraction) => { return await interaction?.editReply({ embeds: [embed] }); } + if (guild === null) return; + if (optionFromUser === null) return; + if (optionToUser === null) return; + // Get fromUser object - const fromUser = await userSchema?.findOne({ - userId: optionFromUser?.id, - guildId: guild?.id, - }); + const fromUser = await fetchUser(optionFromUser, guild); // Get toUser object - const toUser = await userSchema.findOne({ - userId: optionToUser?.id, - guildId: guild?.id, - }); + const toUser = await fetchUser(optionToUser, guild); // If toUser does not exist if (!fromUser) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Transfer]" as string, + title: ':toolbox: Admin - Credits [Transfer]' as string, description: `We could not find ${optionFromUser} in our database.` as string, color: config?.colors?.error as ColorResolvable, @@ -77,7 +75,7 @@ export default async (interaction: CommandInteraction) => { if (!fromUser?.credits) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Transfer]" as string, + title: ':toolbox: Admin - Credits [Transfer]' as string, description: `We could not find credits for ${optionFromUser} in our database.` as string, color: config?.colors?.error as ColorResolvable, @@ -96,7 +94,7 @@ export default async (interaction: CommandInteraction) => { if (!toUser) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Transfer]" as string, + title: ':toolbox: Admin - Credits [Transfer]' as string, description: `We could not find ${optionToUser} in our database.` as string, color: config?.colors?.error as ColorResolvable, @@ -115,7 +113,7 @@ export default async (interaction: CommandInteraction) => { if (!toUser?.credits) { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Transfer]" as string, + title: ':toolbox: Admin - Credits [Transfer]' as string, description: `We could not find credits for ${optionToUser} in our database.` as string, color: config?.colors?.error as ColorResolvable, @@ -140,20 +138,20 @@ export default async (interaction: CommandInteraction) => { await saveUser(fromUser, toUser)?.then(async () => { // Embed object const embed = { - title: ":toolbox: Admin - Credits [Transfer]" as string, + title: ':toolbox: Admin - Credits [Transfer]' as string, description: `You sent ${creditNoun( optionAmount )} from ${optionFromUser} to ${optionToUser}.` as string, color: config?.colors?.success as ColorResolvable, fields: [ { - name: `${optionFromUser?.username as string} Balance`, - value: `${fromUser?.credits as string}`, + name: `${optionFromUser?.username} Balance`, + value: `${fromUser?.credits}`, inline: true, }, { - name: `${optionToUser?.username as string} Balance`, - value: `${toUser?.credits as string}`, + name: `${optionToUser?.username} Balance`, + value: `${toUser?.credits}`, inline: true, }, ], diff --git a/src/commands/credits/modules/balance.ts b/src/commands/credits/modules/balance.ts index e7d5e4d..5f1b2af 100644 --- a/src/commands/credits/modules/balance.ts +++ b/src/commands/credits/modules/balance.ts @@ -1,14 +1,14 @@ // Dependencies -import { CommandInteraction, ColorResolvable } from "discord.js"; +import { CommandInteraction, ColorResolvable } from 'discord.js'; // Configurations -import config from "../../../../config.json"; +import config from '../../../../config.json'; // Helpers -import creditNoun from "../../../helpers/creditNoun"; +import creditNoun from '../../../helpers/creditNoun'; // Models -import userSchema from "../../../helpers/database/models/userSchema"; +import fetchUser from '../../../helpers/fetchUser'; // Function export default async (interaction: CommandInteraction) => { @@ -16,21 +16,20 @@ export default async (interaction: CommandInteraction) => { const { options, user, guild } = interaction; // User option - const optionUser = options?.getUser("user"); + const optionUser = options?.getUser('user'); + + if (guild === null) return; // Get credit object - const userDB = await userSchema?.findOne({ - userId: optionUser ? optionUser?.id : user?.id, - guildId: guild?.id, - }); + const userDB = await fetchUser(optionUser || user, guild); // If userDB does not exist - if (!userDB) { + if (userDB === null) { // Embed object const embed = { - title: ":dollar: Credits [Balance]" as string, + title: ':dollar: Credits [Balance]' as string, description: `We can not find ${ - optionUser || "you" + optionUser || 'you' } in our database.` as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, @@ -45,12 +44,12 @@ export default async (interaction: CommandInteraction) => { } // If userDB.credits does not exist - if (!userDB.credits) { + if (userDB.credits === null) { // Embed object const embed = { - title: ":dollar: Credits [Balance]" as string, + title: ':dollar: Credits [Balance]' as string, description: `We can not find credits for ${ - optionUser || "you" + optionUser || 'you' } in our database.` as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, @@ -65,9 +64,9 @@ export default async (interaction: CommandInteraction) => { } else { // Embed object const embed = { - title: ":dollar: Credits [Balance]" as string, + title: ':dollar: Credits [Balance]' as string, description: `${ - optionUser ? `${optionUser} has` : "You have" + optionUser ? `${optionUser} has` : 'You have' } ${creditNoun(userDB.credits)}.` as string, color: config?.colors?.success as ColorResolvable, timestamp: new Date() as Date, diff --git a/src/commands/credits/modules/gift.ts b/src/commands/credits/modules/gift.ts index fb0313a..86a54ab 100644 --- a/src/commands/credits/modules/gift.ts +++ b/src/commands/credits/modules/gift.ts @@ -1,18 +1,18 @@ // Dependencies -import { CommandInteraction, ColorResolvable } from "discord.js"; +import { CommandInteraction, ColorResolvable } from 'discord.js'; // Configurations -import config from "../../../../config.json"; +import config from '../../../../config.json'; // Handlers -import logger from "../../../handlers/logger"; +import logger from '../../../handlers/logger'; // Helpers -import saveUser from "../../../helpers/saveUser"; -import creditNoun from "../../../helpers/creditNoun"; +import saveUser from '../../../helpers/saveUser'; +import creditNoun from '../../../helpers/creditNoun'; // Models -import userSchema from "../../../helpers/database/models/userSchema"; +import fetchUser from '../../../helpers/fetchUser'; // Function export default async (interaction: CommandInteraction) => { @@ -20,31 +20,31 @@ export default async (interaction: CommandInteraction) => { const { options, user, guild, client } = interaction; // User option - const optionUser = options?.getUser("user"); + const optionUser = options?.getUser('user'); // Amount option - const optionAmount = options?.getInteger("amount"); + const optionAmount = options?.getInteger('amount'); // Reason option - const optionReason = options?.getString("reason"); + const optionReason = options?.getString('reason'); + + if (guild === null) return; + if (optionUser === null) return; // Get fromUserDB object - const fromUserDB = await userSchema?.findOne({ - userId: user?.id, - guildId: guild?.id, - }); + const fromUserDB = await fetchUser(user, guild); // Get toUserDB object - const toUserDB = await userSchema?.findOne({ - userId: optionUser?.id, - guildId: guild?.id, - }); + const toUserDB = await fetchUser(optionUser, guild); + + if (fromUserDB === null) return; + if (toUserDB === null) return; // If receiver is same as sender if (optionUser?.id === user?.id) { // Create embed object const embed = { - title: ":dollar: Credits [Gift]" as string, + title: ':dollar: Credits [Gift]' as string, description: "You can't pay yourself." as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, @@ -62,8 +62,8 @@ export default async (interaction: CommandInteraction) => { if (optionAmount === null) { // Embed object const embed = { - title: ":dollar: Credits [Gift]" as string, - description: "We could not read your requested amount." as string, + title: ':dollar: Credits [Gift]' as string, + description: 'We could not read your requested amount.' as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, footer: { @@ -80,7 +80,7 @@ export default async (interaction: CommandInteraction) => { if (optionAmount <= 0) { // Embed object const embed = { - title: ":dollar: Credits [Gift]" as string, + title: ':dollar: Credits [Gift]' as string, description: "You can't pay zero or below." as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, @@ -98,7 +98,7 @@ export default async (interaction: CommandInteraction) => { if (fromUserDB?.credits < optionAmount) { // Embed object const embed = { - title: ":dollar: Credits [Gift]" as string, + title: ':dollar: Credits [Gift]' as string, description: `You have insufficient credits. Your credits is ${fromUserDB?.credits}` as string, color: config?.colors?.error as ColorResolvable, @@ -117,7 +117,7 @@ export default async (interaction: CommandInteraction) => { if (!toUserDB) { // Embed object const embed = { - title: ":dollar: Credits [Gift]" as string, + title: ':dollar: Credits [Gift]' as string, description: `That user has no credits, I can not gift credits to ${optionUser}` as string, color: config?.colors?.error as ColorResolvable, @@ -142,9 +142,9 @@ export default async (interaction: CommandInteraction) => { await saveUser(fromUserDB, toUserDB)?.then(async () => { // Interaction embed object const interactionEmbed = { - title: ":dollar: Credits [Gift]", + title: ':dollar: Credits [Gift]', description: `You sent ${creditNoun(optionAmount)} to ${optionUser}${ - optionReason ? ` with reason: ${optionReason}` : "" + optionReason ? ` with reason: ${optionReason}` : '' }. Your new credits is ${creditNoun(fromUserDB?.credits)}.`, color: config?.colors?.success as ColorResolvable, timestamp: new Date() as Date, @@ -156,9 +156,9 @@ export default async (interaction: CommandInteraction) => { // DM embed object const dmEmbed = { - title: ":dollar: Credits [Gift]" as string, + title: ':dollar: Credits [Gift]' as string, description: `You received ${creditNoun(optionAmount)} from ${user}${ - optionReason ? ` with reason: ${optionReason}` : "" + optionReason ? ` with reason: ${optionReason}` : '' }. Your new credits is ${creditNoun(toUserDB?.credits)}.` as string, color: config?.colors?.success as ColorResolvable, timestamp: new Date() as Date, diff --git a/src/commands/credits/modules/work.ts b/src/commands/credits/modules/work.ts index 295e085..f2d4512 100644 --- a/src/commands/credits/modules/work.ts +++ b/src/commands/credits/modules/work.ts @@ -9,12 +9,12 @@ import config from '../../../../config.json'; import logger from '../../../handlers/logger'; // Models -import guildSchema from '../../../helpers/database/models/guildSchema'; -import userSchema from '../../../helpers/database/models/userSchema'; import timeouts from '../../../helpers/database/models/timeoutSchema'; // Helpers import creditNoun from '../../../helpers/creditNoun'; +import fetchUser from '../../../helpers/fetchUser'; +import fetchGuild from '../../../helpers/fetchGuild'; // Function export default async (interaction: CommandInteraction) => { @@ -31,9 +31,9 @@ export default async (interaction: CommandInteraction) => { timeoutId: '2022-03-15-19-16', }); - const guildDB = await guildSchema?.findOne({ - guildId: guild?.id, - }); + if (guild === null) return; + + const guildDB = await fetchGuild(guild); // If user is not on timeout if (!isTimeout) { @@ -42,10 +42,9 @@ export default async (interaction: CommandInteraction) => { max: guildDB?.credits?.workRate, }); - const userDB = await userSchema?.findOne({ - userId: user?.id, - guildId: guild?.id, - }); + const userDB = await fetchUser(user, guild); + + if (userDB === null) return; userDB.credits += creditsEarned; @@ -80,7 +79,7 @@ export default async (interaction: CommandInteraction) => { // Send debug message logger?.debug( `Guild: ${guild?.id} User: ${user?.id} has not worked within the last ${ - guildDB?.work?.timeout / 1000 + guildDB?.credits?.workTimeout / 1000 } seconds, work can be done` ); diff --git a/src/commands/profile/modules/view.ts b/src/commands/profile/modules/view.ts index e7cb8fd..2e84f85 100644 --- a/src/commands/profile/modules/view.ts +++ b/src/commands/profile/modules/view.ts @@ -1,11 +1,11 @@ // Dependencies -import { CommandInteraction, ColorResolvable } from "discord.js"; +import { CommandInteraction, ColorResolvable } from 'discord.js'; // Configurations -import config from "../../../../config.json"; +import config from '../../../../config.json'; // Models -import userSchema from "../../../helpers/database/models/userSchema"; +import fetchUser from '../../../helpers/fetchUser'; // Function export default async (interaction: CommandInteraction) => { @@ -13,18 +13,17 @@ export default async (interaction: CommandInteraction) => { const { client, options, user, guild } = interaction; // Target information - const target = options?.getUser("target"); + const target = options?.getUser('target'); // Discord User Information const discordUser = await client?.users?.fetch( `${target ? target?.id : user?.id}` ); + if (guild === null) return; + // User Information - const userObj = await userSchema?.findOne({ - userId: discordUser?.id, - guildId: guild?.id, - }); + const userObj = await fetchUser(discordUser, guild); // Embed object const embed = { @@ -36,27 +35,27 @@ export default async (interaction: CommandInteraction) => { fields: [ { name: `:dollar: Credits` as string, - value: `${userObj?.credits || "Not found"}` as string, + value: `${userObj?.credits || 'Not found'}` as string, inline: true, }, { name: `:squeeze_bottle: Level` as string, - value: `${userObj?.level || "Not found"}` as string, + value: `${userObj?.level || 'Not found'}` as string, inline: true, }, { name: `:squeeze_bottle: Points` as string, - value: `${userObj?.points || "Not found"}` as string, + value: `${userObj?.points || 'Not found'}` as string, inline: true, }, { name: `:loudspeaker: Reputation` as string, - value: `${userObj?.reputation || "Not found"}` as string, + value: `${userObj?.reputation || 'Not found'}` as string, inline: true, }, { name: `:rainbow_flag: Language` as string, - value: `${userObj?.language || "Not found"}` as string, + value: `${userObj?.language || 'Not found'}` as string, inline: true, }, ], diff --git a/src/commands/reputation/modules/give.ts b/src/commands/reputation/modules/give.ts index c188946..1f5e86a 100644 --- a/src/commands/reputation/modules/give.ts +++ b/src/commands/reputation/modules/give.ts @@ -1,15 +1,15 @@ // Dependencies -import { CommandInteraction, ColorResolvable } from "discord.js"; +import { CommandInteraction, ColorResolvable } from 'discord.js'; // Configurations -import config from "../../../../config.json"; +import config from '../../../../config.json'; // Handlers -import logger from "../../../handlers/logger"; +import logger from '../../../handlers/logger'; // Models -import userSchema from "../../../helpers/database/models/userSchema"; -import timeoutSchema from "../../../helpers/database/models/timeoutSchema"; +import timeoutSchema from '../../../helpers/database/models/timeoutSchema'; +import fetchUser from '../../../helpers/fetchUser'; // Function export default async (interaction: CommandInteraction) => { @@ -17,22 +17,23 @@ export default async (interaction: CommandInteraction) => { const { options, user, guild } = interaction; // Target option - const optionTarget = options?.getUser("target"); + const optionTarget = options?.getUser('target'); // Type information - const optionType = options?.getString("type"); + const optionType = options?.getString('type'); + + if (guild === null) return; // User information - const userObj = await userSchema?.findOne({ - userId: user?.id, - guildId: guild?.id, - }); + const userObj = await fetchUser(user, guild); + + if (userObj === null) return; // Check if user has a timeout const isTimeout = await timeoutSchema?.findOne({ guildId: guild?.id, userId: user?.id, - timeoutId: "2022-04-10-16-42", + timeoutId: '2022-04-10-16-42', }); // If user is not on timeout @@ -41,8 +42,8 @@ export default async (interaction: CommandInteraction) => { if (optionTarget?.id === user?.id) { // Embed object const embed = { - title: ":loudspeaker: Reputation [Give]" as string, - description: "You can not repute yourself." as string, + title: ':loudspeaker: Reputation [Give]' as string, + description: 'You can not repute yourself.' as string, timestamp: new Date() as Date, color: config?.colors?.error as ColorResolvable, footer: { @@ -56,12 +57,12 @@ export default async (interaction: CommandInteraction) => { } // If type is positive - if (optionType === "positive") { + if (optionType === 'positive') { userObj.reputation += 1; } // If type is negative - else if (optionType === "negative") { + else if (optionType === 'negative') { userObj.reputation -= 1; } @@ -69,7 +70,7 @@ export default async (interaction: CommandInteraction) => { await userObj?.save()?.then(async () => { // Embed object const embed = { - title: ":loudspeaker: Reputation [Give]" as string, + title: ':loudspeaker: Reputation [Give]' as string, description: `You have given ${optionTarget} a ${optionType} reputation!` as string, timestamp: new Date() as Date, @@ -89,7 +90,7 @@ export default async (interaction: CommandInteraction) => { await timeoutSchema?.create({ guildId: guild?.id, userId: user?.id, - timeoutId: "2022-04-10-16-42", + timeoutId: '2022-04-10-16-42', }); // Return interaction reply return await interaction?.editReply({ embeds: [embed] }); @@ -107,13 +108,13 @@ export default async (interaction: CommandInteraction) => { await timeoutSchema?.deleteOne({ guildId: guild?.id, userId: user?.id, - timeoutId: "2022-04-10-16-42", + timeoutId: '2022-04-10-16-42', }); }, config?.reputation?.timeout); } else { // Create embed object const embed = { - title: ":loudspeaker: Reputation [Give]" as string, + title: ':loudspeaker: Reputation [Give]' as string, description: `You have given reputation within the last ${ config?.reputation?.timeout / 1000 } seconds, you can not repute now!` as string, diff --git a/src/commands/settings/user/modules/appearance.ts b/src/commands/settings/user/modules/appearance.ts index 6fe7cec..4e6a5d1 100644 --- a/src/commands/settings/user/modules/appearance.ts +++ b/src/commands/settings/user/modules/appearance.ts @@ -1,14 +1,14 @@ // Dependencies -import { CommandInteraction, ColorResolvable } from "discord.js"; +import { CommandInteraction, ColorResolvable } from 'discord.js'; // Configurations -import config from "../../../../../config.json"; +import config from '../../../../../config.json'; // Handlers -import logger from "../../../../handlers/logger"; +import logger from '../../../../handlers/logger'; // Models -import userSchema from "../../../../helpers/database/models/userSchema"; +import fetchUser from '../../../../helpers/fetchUser'; // Function export default async (interaction: CommandInteraction) => { @@ -16,13 +16,14 @@ export default async (interaction: CommandInteraction) => { const { options, user, guild } = interaction; // Get options - const language = options?.getString("language"); + const language = options?.getString('language'); + + if (guild === null) return; // Get user object - const userDB = await userSchema?.findOne({ - userId: user?.id, - guildId: guild?.id, - }); + const userDB = await fetchUser(user, guild); + + if (userDB === null) return; // Modify values userDB.language = language !== null ? language : userDB?.language; @@ -31,12 +32,12 @@ export default async (interaction: CommandInteraction) => { await userDB?.save()?.then(async () => { // Embed object const embed = { - title: ":hammer: Settings - User [Appearance]" as string, - description: "Following settings is set!" as string, + title: ':hammer: Settings - User [Appearance]' as string, + description: 'Following settings is set!' as string, color: config?.colors?.success as ColorResolvable, fields: [ { - name: "🏳️‍🌈 Language" as string, + name: '🏳️‍🌈 Language' as string, value: `${userDB?.language}` as string, inline: true, }, diff --git a/src/commands/shop/modules/pterodactyl.ts b/src/commands/shop/modules/pterodactyl.ts index 6c865bc..aa55120 100644 --- a/src/commands/shop/modules/pterodactyl.ts +++ b/src/commands/shop/modules/pterodactyl.ts @@ -1,34 +1,34 @@ // Dependencies -import { CommandInteraction, ColorResolvable } from "discord.js"; -import { v4 as uuidv4 } from "uuid"; -import axios from "axios"; +import { CommandInteraction, ColorResolvable } from 'discord.js'; +import { v4 as uuidv4 } from 'uuid'; +import axios from 'axios'; // Configurations -import config from "../../../../config.json"; +import config from '../../../../config.json'; // Handlers -import logger from "../../../handlers/logger"; +import logger from '../../../handlers/logger'; // Helpers -import creditNoun from "../../../helpers/creditNoun"; +import creditNoun from '../../../helpers/creditNoun'; // Models -import apiSchema from "../../../helpers/database/models/apiSchema"; -import userSchema from "../../../helpers/database/models/userSchema"; +import apiSchema from '../../../helpers/database/models/apiSchema'; +import fetchUser from '../../../helpers/fetchUser'; // Function export default async (interaction: CommandInteraction) => { const { options, guild, user, client } = interaction; // Get options - const optionAmount = options?.getInteger("amount"); + const optionAmount = options?.getInteger('amount'); // If amount is null if (optionAmount === null) { // Embed object const embed = { - title: ":dollar: Credits [Gift]" as string, - description: "We could not read your requested amount." as string, + title: ':dollar: Credits [Gift]' as string, + description: 'We could not read your requested amount.' as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, footer: { @@ -41,11 +41,12 @@ export default async (interaction: CommandInteraction) => { return await interaction?.editReply({ embeds: [embed] }); } + if (guild === null) return; + // Get user object - const userDB = await userSchema?.findOne({ - userId: user?.id, - guildId: guild?.id, - }); + const userDB = await fetchUser(user, guild); + + if (userDB === null) return; // Get DM user object const dmUser = client?.users?.cache?.get(user?.id); @@ -53,13 +54,13 @@ export default async (interaction: CommandInteraction) => { // Stop if amount or user credits is below 100 if ((optionAmount || userDB?.credits) < 100) { const embed = { - title: ":shopping_cart: Shop [Pterodactyl]" as string, + title: ':shopping_cart: Shop [Pterodactyl]' as string, description: `You **can't** withdraw for __Pterodactyl__ below **100**.` as string, color: config?.colors?.error as ColorResolvable, fields: [ { - name: "Your balance" as string, + name: 'Your balance' as string, value: `${creditNoun(userDB?.credits)}` as string, }, ], @@ -75,13 +76,13 @@ export default async (interaction: CommandInteraction) => { // Stop if amount or user credits is above 1.000.000 if ((optionAmount || userDB?.credits) > 1000000) { const embed = { - title: ":shopping_cart: Shop [Pterodactyl]" as string, + title: ':shopping_cart: Shop [Pterodactyl]' as string, description: `You **can't** withdraw for __Pterodactyl__ above **1.000.000**.` as string, color: config?.colors?.error as ColorResolvable, fields: [ { - name: "Your balance" as string, + name: 'Your balance' as string, value: `${creditNoun(userDB?.credits)}` as string, }, ], @@ -97,12 +98,12 @@ export default async (interaction: CommandInteraction) => { // Stop if user credits is below amount if (userDB?.credits < optionAmount) { const embed = { - title: ":shopping_cart: Shop [Pterodactyl]" as string, + title: ':shopping_cart: Shop [Pterodactyl]' as string, description: `You have **insufficient** credits.` as string, color: config.colors.error as ColorResolvable, fields: [ { - name: "Your balance" as string, + name: 'Your balance' as string, value: `${creditNoun(userDB?.credits)}` as string, }, ], @@ -130,13 +131,13 @@ export default async (interaction: CommandInteraction) => { }); // Get shop URL - const shopUrl = apiCredentials?.url?.replace("/api", "/store"); + const shopUrl = apiCredentials?.url?.replace('/api', '/store'); // Make API request await api // Make a post request to the API - ?.post("vouchers", { + ?.post('vouchers', { uses: 1, code, credits: optionAmount || userDB?.credits, @@ -147,12 +148,12 @@ export default async (interaction: CommandInteraction) => { ?.then(async () => { // Create DM embed object const dmEmbed = { - title: ":shopping_cart: Shop [Pterodactyl]" as string, + title: ':shopping_cart: Shop [Pterodactyl]' as string, description: `Redeem this voucher [here](${shopUrl})!` as string, fields: [ - { name: "Code" as string, value: `${code}` as string, inline: true }, + { name: 'Code' as string, value: `${code}` as string, inline: true }, { - name: "Credits" as string, + name: 'Credits' as string, value: `${optionAmount || userDB?.credits}` as string, inline: true, }, @@ -167,8 +168,8 @@ export default async (interaction: CommandInteraction) => { // Create interaction embed object const interactionEmbed = { - title: ":shopping_cart: Shop [Pterodactyl]" as string, - description: "I have sent you the code in DM!" as string, + title: ':shopping_cart: Shop [Pterodactyl]' as string, + description: 'I have sent you the code in DM!' as string, color: config?.colors?.success as ColorResolvable, timestamp: new Date() as Date, footer: { @@ -203,9 +204,9 @@ export default async (interaction: CommandInteraction) => { .catch(async (e: any) => { logger?.error(e); const embed = { - title: ":shopping_cart: Shop [Pterodactyl]" as string, + title: ':shopping_cart: Shop [Pterodactyl]' as string, description: - "Something went wrong, please try again later." as string, + 'Something went wrong, please try again later.' as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, footer: { @@ -221,8 +222,8 @@ export default async (interaction: CommandInteraction) => { .catch(async (e) => { logger?.error(e); const embed = { - title: ":shopping_cart: Shop [Pterodactyl]" as string, - description: "Something went wrong, please try again later." as string, + title: ':shopping_cart: Shop [Pterodactyl]' as string, + description: 'Something went wrong, please try again later.' as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, footer: { diff --git a/src/commands/shop/roles/modules/buy.ts b/src/commands/shop/roles/modules/buy.ts index 8ec08da..e9636ed 100644 --- a/src/commands/shop/roles/modules/buy.ts +++ b/src/commands/shop/roles/modules/buy.ts @@ -3,31 +3,31 @@ import { CommandInteraction, ColorResolvable, GuildMemberRoleManager, -} from "discord.js"; +} from 'discord.js'; // Configurations -import config from "../../../../../config.json"; +import config from '../../../../../config.json'; // Models -import userSchema from "../../../../helpers/database/models/userSchema"; -import shopRolesSchema from "../../../../helpers/database/models/shopRolesSchema"; -import guildSchema from "../../../../helpers/database/models/guildSchema"; +import shopRolesSchema from '../../../../helpers/database/models/shopRolesSchema'; +import guildSchema from '../../../../helpers/database/models/guildSchema'; // Helpers -import creditNoun from "../../../../helpers/creditNoun"; +import creditNoun from '../../../../helpers/creditNoun'; +import fetchUser from '../../../../helpers/fetchUser'; // Function export default async (interaction: CommandInteraction) => { const { options, guild, user, member } = interaction; - const optionName = options?.getString("name"); + const optionName = options?.getString('name'); // If amount is null if (optionName === null) { // Embed object const embed = { - title: ":dollar: Shop - Roles [Buy]" as string, - description: "We could not read your requested name." as string, + title: ':dollar: Shop - Roles [Buy]' as string, + description: 'We could not read your requested name.' as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, footer: { @@ -43,7 +43,7 @@ export default async (interaction: CommandInteraction) => { await guild?.roles .create({ name: optionName, - color: "RED", + color: 'RED', reason: `${user?.id} bought from shop`, }) .then(async (role) => { @@ -52,10 +52,9 @@ export default async (interaction: CommandInteraction) => { guildId: guild?.id, }); - const userDB = await userSchema?.findOne({ - userId: user?.id, - guildId: guild?.id, - }); + const userDB = await fetchUser(user, guild); + + if (userDB === null) return; const { pricePerHour } = guildDB?.shop?.roles; @@ -75,13 +74,13 @@ export default async (interaction: CommandInteraction) => { await shopRolesSchema?.find()?.then((role: any) => console.log(role)); const embed = { - title: ":shopping_cart: Shop - Roles [Buy]" as string, + title: ':shopping_cart: Shop - Roles [Buy]' as string, description: `You have bought ${role?.name} for ${guildDB?.shop?.roles?.pricePerHour} per hour.` as string, color: config?.colors?.success as ColorResolvable, fields: [ { - name: "Your balance" as string, + name: 'Your balance' as string, value: `${creditNoun(userDB?.credits)}` as string, }, ], diff --git a/src/commands/shop/roles/modules/cancel.ts b/src/commands/shop/roles/modules/cancel.ts index c8d637d..6253ea3 100644 --- a/src/commands/shop/roles/modules/cancel.ts +++ b/src/commands/shop/roles/modules/cancel.ts @@ -3,30 +3,30 @@ import { CommandInteraction, ColorResolvable, GuildMemberRoleManager, -} from "discord.js"; +} from 'discord.js'; // Configurations -import config from "../../../../../config.json"; +import config from '../../../../../config.json'; // Models -import userSchema from "../../../../helpers/database/models/userSchema"; -import shopRolesSchema from "../../../../helpers/database/models/shopRolesSchema"; +import shopRolesSchema from '../../../../helpers/database/models/shopRolesSchema'; // Helpers -import creditNoun from "../../../../helpers/creditNoun"; +import creditNoun from '../../../../helpers/creditNoun'; +import fetchUser from '../../../../helpers/fetchUser'; // Function export default async (interaction: CommandInteraction) => { const { options, guild, user, member } = interaction; - const optionRole = options.getRole("role"); + const optionRole = options.getRole('role'); // If amount is null if (optionRole === null) { // Embed object const embed = { - title: ":dollar: Shop - Roles [Cancel]" as string, - description: "We could not read your requested role." as string, + title: ':dollar: Shop - Roles [Cancel]' as string, + description: 'We could not read your requested role.' as string, color: config?.colors?.error as ColorResolvable, timestamp: new Date() as Date, footer: { @@ -51,10 +51,9 @@ export default async (interaction: CommandInteraction) => { await guild?.roles .delete(optionRole?.id, `${user?.id} canceled from shop`) .then(async () => { - const userDB = await userSchema?.findOne({ - userId: user?.id, - guildId: guild?.id, - }); + const userDB = await fetchUser(user, guild); + + if (userDB === null) return; await shopRolesSchema?.deleteOne({ roleId: optionRole?.id, @@ -63,12 +62,12 @@ export default async (interaction: CommandInteraction) => { }); const embed = { - title: ":shopping_cart: Shop - Roles [Cancel]" as string, + title: ':shopping_cart: Shop - Roles [Cancel]' as string, description: `You have canceled ${optionRole.name}.` as string, color: config?.colors?.success as ColorResolvable, fields: [ { - name: "Your balance" as string, + name: 'Your balance' as string, value: `${creditNoun(userDB?.credits)}` as string, }, ], diff --git a/src/events/guildCreate.ts b/src/events/guildCreate.ts deleted file mode 100644 index 7cdd1d9..0000000 --- a/src/events/guildCreate.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Guild } from 'discord.js'; -import dbGuildFix from '../helpers/dbGuildFix'; -import dbMemberFix from '../helpers/dbMemberFix'; - -export default { - name: 'guildCreate', - async execute(guild: Guild) { - // Destructure client - const { client } = guild; - - await guild.members.fetch().then(async (members) => { - members.forEach(async (member) => { - const { user } = member; - - dbMemberFix(user, guild); - }); - }); - await dbGuildFix(guild); - - // Set client status - client?.user?.setPresence({ - activities: [ - { type: 'WATCHING', name: `${client?.guilds?.cache?.size} guilds` }, - ], - status: 'online', - }); - }, -}; diff --git a/src/events/guildCreate/index.ts b/src/events/guildCreate/index.ts new file mode 100644 index 0000000..8c18da0 --- /dev/null +++ b/src/events/guildCreate/index.ts @@ -0,0 +1,19 @@ +// Dependencies +import { Guild } from 'discord.js'; + +// Helpers +import updatePresence from '../../helpers/updatePresence'; +import fetchGuild from '../../helpers/fetchGuild'; + +// Function +export default { + name: 'guildCreate', + async execute(guild: Guild) { + // Destructure + const { client } = guild; + + await fetchGuild(guild); + + await updatePresence(client); + }, +}; diff --git a/src/events/guildDelete.ts b/src/events/guildDelete.ts deleted file mode 100644 index 3ea009d..0000000 --- a/src/events/guildDelete.ts +++ /dev/null @@ -1,75 +0,0 @@ -import guilds from '../helpers/database/models/guildSchema'; -import users from '../helpers/database/models/userSchema'; -import apis from '../helpers/database/models/apiSchema'; -import counters from '../helpers/database/models/counterSchema'; -import shopRoles from '../helpers/database/models/shopRolesSchema'; -import timeouts from '../helpers/database/models/timeoutSchema'; - -import logger from '../handlers/logger'; - -import { Guild } from 'discord.js'; - -export default { - name: 'guildDelete', - async execute(guild: Guild) { - // Destructure client - const { client } = guild; - - guilds - .deleteMany({ guildId: guild.id }) - .then(async () => { - logger.debug(`Successfully deleted guild: ${guild.id}`); - }) - .catch(async (e) => { - logger.error(`Failed to delete guild: ${guild.id} ${e}`); - }); - users - .deleteMany({ guildId: guild.id }) - .then(async () => { - logger.debug(`Successfully deleted guild: ${guild.id}'s users`); - }) - .catch(async (e) => { - logger.error(`Failed to delete guild: ${guild.id}'s users ${e}`); - }); - apis - .deleteMany({ guildId: guild.id }) - .then(async () => { - logger.debug(`Successfully deleted guild: ${guild.id}'s apis`); - }) - .catch(async (e) => { - logger.error(`Failed to delete guild: ${guild.id}'s apis ${e}`); - }); - counters - .deleteMany({ guildId: guild.id }) - .then(async () => { - logger.debug(`Successfully deleted guild: ${guild.id}'s counters`); - }) - .catch(async (e) => { - logger.error(`Failed to delete guild: ${guild.id}'s counters ${e}`); - }); - shopRoles - .deleteMany({ guildId: guild.id }) - .then(async () => { - logger.debug(`Successfully deleted guild: ${guild.id}'s shop roles`); - }) - .catch(async (e) => { - logger.error(`Failed to delete guild: ${guild.id}'s shop roles ${e}`); - }); - timeouts - .deleteMany({ guildId: guild.id }) - .then(async () => { - logger.debug(`Successfully deleted guild: ${guild.id}'s timeouts`); - }) - .catch(async (e) => { - logger.error(`Failed to delete guild: ${guild.id}'s timeouts ${e}`); - }); - - // Set client status - await client?.user?.setPresence({ - activities: [ - { type: 'WATCHING', name: `${client.guilds.cache.size} guilds` }, - ], - status: 'online', - }); - }, -}; diff --git a/src/events/guildDelete/index.ts b/src/events/guildDelete/index.ts new file mode 100644 index 0000000..e06094d --- /dev/null +++ b/src/events/guildDelete/index.ts @@ -0,0 +1,19 @@ +// Dependencies +import { Guild } from 'discord.js'; + +// Helpers +import updatePresence from '../../helpers/updatePresence'; +import dropGuild from '../../helpers/dropGuild'; + +// Function +export default { + name: 'guildDelete', + async execute(guild: Guild) { + // Destructure client + const { client } = guild; + + await dropGuild(guild); + + await updatePresence(client); + }, +}; diff --git a/src/events/guildMemberAdd.ts b/src/events/guildMemberAdd.ts deleted file mode 100644 index a1375c0..0000000 --- a/src/events/guildMemberAdd.ts +++ /dev/null @@ -1,17 +0,0 @@ -import users from '../helpers/database/models/userSchema'; -import logger from '../handlers/logger'; - -import { GuildMember } from 'discord.js'; - -export default { - name: 'guildMemberAdd', - async execute(member: GuildMember) { - await users - .create({ userId: member?.id, guildId: member?.guild?.id }) - .then(async () => - logger.debug( - `Guild: ${member?.guild?.id} User: ${member?.id} created successfully` - ) - ); - }, -}; diff --git a/src/events/guildMemberAdd/index.ts b/src/events/guildMemberAdd/index.ts new file mode 100644 index 0000000..facebd2 --- /dev/null +++ b/src/events/guildMemberAdd/index.ts @@ -0,0 +1,17 @@ +import users from '../../helpers/database/models/userSchema'; +import logger from '../../handlers/logger'; + +import { GuildMember } from 'discord.js'; +import updatePresence from '../../helpers/updatePresence'; +import fetchUser from '../../helpers/fetchUser'; + +export default { + name: 'guildMemberAdd', + async execute(member: GuildMember) { + const { client, user, guild } = member; + + await fetchUser(user, guild); + + await updatePresence(client); + }, +}; diff --git a/src/events/guildMemberRemove.ts b/src/events/guildMemberRemove.ts deleted file mode 100644 index c785189..0000000 --- a/src/events/guildMemberRemove.ts +++ /dev/null @@ -1,17 +0,0 @@ -import users from '../helpers/database/models/userSchema'; -import logger from '../handlers/logger'; - -import { GuildMember } from 'discord.js'; - -export default { - name: 'guildMemberRemove', - async execute(member: GuildMember) { - await users - .deleteOne({ userId: member?.id, guildId: member?.guild?.id }) - .then(async () => - logger.debug( - `Guild: ${member?.guild?.id} User: ${member?.id} deleted successfully` - ) - ); - }, -}; diff --git a/src/events/guildMemberRemove/index.ts b/src/events/guildMemberRemove/index.ts new file mode 100644 index 0000000..178fd7c --- /dev/null +++ b/src/events/guildMemberRemove/index.ts @@ -0,0 +1,17 @@ +import users from '../../helpers/database/models/userSchema'; +import logger from '../../handlers/logger'; + +import { GuildMember } from 'discord.js'; +import updatePresence from '../../helpers/updatePresence'; +import dropUser from '../../helpers/dropUser'; + +export default { + name: 'guildMemberRemove', + async execute(member: GuildMember) { + const { client, user, guild } = member; + + await dropUser(user, guild); + + await updatePresence(client); + }, +}; diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate/index.ts similarity index 91% rename from src/events/interactionCreate.ts rename to src/events/interactionCreate/index.ts index af4c3e0..f611f11 100644 --- a/src/events/interactionCreate.ts +++ b/src/events/interactionCreate/index.ts @@ -1,6 +1,6 @@ -import config from '../../config.json'; -import logger from '../handlers/logger'; -import guilds from '../helpers/database/models/guildSchema'; +import config from '../../../config.json'; +import logger from '../../handlers/logger'; +import guilds from '../../helpers/database/models/guildSchema'; import { Interaction, ColorResolvable } from 'discord.js'; diff --git a/src/events/messageCreate/index.ts b/src/events/messageCreate/index.ts index 017554e..ddfb729 100644 --- a/src/events/messageCreate/index.ts +++ b/src/events/messageCreate/index.ts @@ -1,35 +1,41 @@ -import guilds from '../../helpers/database/models/guildSchema'; -import users from '../../helpers/database/models/userSchema'; +// Dependencies +import { Message } from 'discord.js'; + +// Models +import userSchema from '../../helpers/database/models/userSchema'; +import guildSchema from '../../helpers/database/models/guildSchema'; + +// Modules import points from './modules/points'; import credits from './modules/credits'; -import counter from './modules/counter'; +import counters from './modules/counters'; +import fetchUser from '../../helpers/fetchUser'; +import fetchGuild from '../../helpers/fetchGuild'; -import { Message } from 'discord.js'; +// Function export default { name: 'messageCreate', async execute(message: Message) { - const { guild, author } = message; + const { author, guild } = message; // If message author is bot - if (author.bot) return; + if (author?.bot) return; + + if (guild === null) return; // Get guild object - const guildDB = await guilds.findOne({ guildId: guild?.id }); + const guildObj = await fetchGuild(guild); // Get guild object - const userDB = await users.findOne({ - guildId: guild?.id, - userId: author?.id, - }); + const userObj = await fetchUser(author, guild); - // Manage credits + // Execute Module - Credits + await credits(guildObj, userObj, message); - await credits(guildDB, userDB, message); + // Execute Module - Points + await points(guildObj, userObj, message); - // Manage points - await points(guildDB, userDB, message); - - // Manage counter - await counter(guildDB, userDB, message); + // Execute Module - Counters + await counters(guildObj, userObj, message); }, }; diff --git a/src/events/messageCreate/modules/counter.ts b/src/events/messageCreate/modules/counters.ts similarity index 96% rename from src/events/messageCreate/modules/counter.ts rename to src/events/messageCreate/modules/counters.ts index 9a350f4..e4e39f1 100644 --- a/src/events/messageCreate/modules/counter.ts +++ b/src/events/messageCreate/modules/counters.ts @@ -1,32 +1,32 @@ -import logger from '../../../handlers/logger'; -import counters from '../../../helpers/database/models/counterSchema'; - -import { Message } from 'discord.js'; - -export default async (guildDB: any, userDB: any, message: Message) => { - const { guild, channel, content } = message; - - // Get counter object - const counter = await counters.findOne({ - guildId: guild?.id, - channelId: channel.id, - }); - - // If counter for the message channel - if (counter) { - // If message content is not strictly the same as counter word - if (content !== counter.word) { - // Delete the message - await message.delete(); - } else { - // Add 1 to the counter object - await counters.findOneAndUpdate( - { - guildId: guild?.id, - channelId: channel.id, - }, - { $inc: { counter: 1 } } - ); - } - } -}; +import logger from '../../../handlers/logger'; +import counters from '../../../helpers/database/models/counterSchema'; + +import { Message } from 'discord.js'; + +export default async (guildDB: any, userDB: any, message: Message) => { + const { guild, channel, content } = message; + + // Get counter object + const counter = await counters.findOne({ + guildId: guild?.id, + channelId: channel.id, + }); + + // If counter for the message channel + if (counter) { + // If message content is not strictly the same as counter word + if (content !== counter.word) { + // Delete the message + await message.delete(); + } else { + // Add 1 to the counter object + await counters.findOneAndUpdate( + { + guildId: guild?.id, + channelId: channel.id, + }, + { $inc: { counter: 1 } } + ); + } + } +}; diff --git a/src/events/messageCreate/modules/index.ts b/src/events/messageCreate/modules/index.ts deleted file mode 100644 index 599442a..0000000 --- a/src/events/messageCreate/modules/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import points from './points'; -import credits from './credits'; -import counter from './counter'; - -export default { points, credits, counter }; diff --git a/src/events/messageUpdate.ts b/src/events/messageUpdate/index.ts similarity index 88% rename from src/events/messageUpdate.ts rename to src/events/messageUpdate/index.ts index 4c08256..9728c27 100644 --- a/src/events/messageUpdate.ts +++ b/src/events/messageUpdate/index.ts @@ -1,27 +1,27 @@ -import counters from '../helpers/database/models/counterSchema'; -import { Message } from 'discord.js'; -export default { - name: 'messageUpdate', - async execute(oldMessage: Message, newMessage: Message) { - // If message author is bot - if (newMessage.author.bot) return; - - // Get counter object - const counter = await counters.findOne({ - guildId: newMessage.guild?.id, - channelId: newMessage.channel.id, - }); - - // If counter for the message channel - if (counter) { - // If message content is not strictly the same as counter word - if (newMessage.content !== counter.word) { - // Delete the message - await newMessage.delete(); - await newMessage.channel.send( - `${newMessage.author} said **${counter.word}**.` - ); - } - } - }, -}; +import counters from '../../helpers/database/models/counterSchema'; +import { Message } from 'discord.js'; +export default { + name: 'messageUpdate', + async execute(oldMessage: Message, newMessage: Message) { + // If message author is bot + if (newMessage.author.bot) return; + + // Get counter object + const counter = await counters.findOne({ + guildId: newMessage.guild?.id, + channelId: newMessage.channel.id, + }); + + // If counter for the message channel + if (counter) { + // If message content is not strictly the same as counter word + if (newMessage.content !== counter.word) { + // Delete the message + await newMessage.delete(); + await newMessage.channel.send( + `${newMessage.author} said **${counter.word}**.` + ); + } + } + }, +}; diff --git a/src/events/ready.ts b/src/events/ready.ts deleted file mode 100644 index 0712472..0000000 --- a/src/events/ready.ts +++ /dev/null @@ -1,39 +0,0 @@ -import logger from '../handlers/logger'; -import config from '../../config.json'; -import deployCommands from '../helpers/deployCommands'; -import dbGuildFix from '../helpers/dbGuildFix'; -import dbMemberFix from '../helpers/dbMemberFix'; - -import { Client } from 'discord.js'; -export default { - name: 'ready', - once: true, - async execute(client: Client) { - console.log('Test'); - // Send info message - await logger.info(`Ready! Logged in as ${client?.user?.tag}`); - - // Set client status - await client?.user?.setPresence({ - activities: [ - { type: 'WATCHING', name: `${client.guilds.cache.size} guilds` }, - ], - status: 'online', - }); - - if (config.importToDB) { - const guilds = client.guilds.cache; - await guilds.map(async (guild) => { - await guild?.members.fetch().then(async (members) => { - await members.forEach(async (member) => { - const { user } = member; - dbMemberFix(user, guild); - }); - }); - await dbGuildFix(guild); - }); - } - - await deployCommands(); - }, -}; diff --git a/src/events/ready/index.ts b/src/events/ready/index.ts new file mode 100644 index 0000000..604924e --- /dev/null +++ b/src/events/ready/index.ts @@ -0,0 +1,58 @@ +import logger from '../../handlers/logger'; +import config from '../../../config.json'; +import deployCommands from '../../helpers/deployCommands'; +import dbGuildFix from '../../helpers/dbGuildFix'; +import dbMemberFix from '../../helpers/dbMemberFix'; + +import userSchema from '../../helpers/database/models/userSchema'; + +import { Client } from 'discord.js'; +import updatePresence from '../../helpers/updatePresence'; +export default { + name: 'ready', + once: true, + async execute(client: Client) { + // Send info message + await logger.info(`Ready! Logged in as ${client?.user?.tag}`); + + await updatePresence(client); + + if (config.importToDB) { + const guilds = client.guilds.cache; + await guilds.map(async (guild) => { + await guild?.members.fetch().then(async (members) => { + await members.forEach(async (member) => { + const { user } = member; + dbMemberFix(user, guild); + }); + }); + await dbGuildFix(guild); + }); + } + + if (config.clearUnused) { + await userSchema.find().then( + async (result) => + await result.map(async (user) => { + if ( + user.credits !== 0 || + user.reputation !== 0 || + user.points !== 0 + ) { + logger.info(`Not removing user: ${user}`); + } else { + logger.warn(`Removing user: ${user}`); + console.log({ userId: user.userId, guildId: user.guildId }); + await userSchema + .deleteOne({ _id: user._id }) + .then(async (result) => { + logger.error(`Removed user: ${user} ${result}`); + }); + } + }) + ); + } + + await deployCommands(); + }, +}; diff --git a/src/handlers/schedules.ts b/src/handlers/schedules.ts index 7119d25..5aee35b 100644 --- a/src/handlers/schedules.ts +++ b/src/handlers/schedules.ts @@ -4,8 +4,9 @@ import shopRoles from '../helpers/database/models/shopRolesSchema'; import guilds from '../helpers/database/models/guildSchema'; import logger from './logger'; import { Client } from 'discord.js'; + export default async (client: Client) => { - schedule.scheduleJob('*/30 * * * *', async () => { + schedule.scheduleJob('*/5 * * * *', async () => { shopRoles.find().then(async (shopRoles: any) => { shopRoles.map(async (shopRole: any) => { const payed = new Date(shopRole.lastPayed); @@ -13,6 +14,12 @@ export default async (client: Client) => { const oneHourAfterPayed = payed.setHours(payed.getHours() + 1); if (new Date() > new Date(oneHourAfterPayed)) { + logger.debug( + `Role: ${shopRole.roleId} Expires: ${ + new Date() < new Date(oneHourAfterPayed) + } Last Payed: ${shopRole.lastPayed}` + ); + // Get guild object const guild = await guilds.findOne({ guildId: shopRole.guildId, @@ -24,14 +31,16 @@ export default async (client: Client) => { }); const { pricePerHour } = guild.shop.roles; + if (userDB === null) return; + if (userDB.credits < pricePerHour) { const rGuild = await client.guilds.cache.get(`${shopRole.guildId}`); const rMember = await rGuild?.members.fetch(`${shopRole.userId}`); await rMember?.roles .remove(`${shopRole.roleId}`) - .then(console.log) - .catch(console.error); // Removes all roles + .then(async (test) => console.log('4', test)) + .catch(async (test) => console.log('5', test)); // Removes all roles } shopRole.lastPayed = new Date(); @@ -45,6 +54,6 @@ export default async (client: Client) => { }); }); - await logger.debug('Checking schedules! (Every 30 minutes)'); + await logger.debug('Checking schedules! (Every 5 minutes)'); }); }; diff --git a/src/helpers/database/models/userSchema.ts b/src/helpers/database/models/userSchema.ts index ea14a27..728eb8d 100644 --- a/src/helpers/database/models/userSchema.ts +++ b/src/helpers/database/models/userSchema.ts @@ -1,29 +1,42 @@ -import mongoose from 'mongoose'; +import { Snowflake } from 'discord.js'; +import { Schema, model } from 'mongoose'; -const userSchema = new mongoose.Schema( +export interface IUser { + guildId: Snowflake; + userId: Snowflake; + language: string; + reputation: number; + credits: number; + level: number; + points: number; + updatedAt: Date; + createdAt: Date; +} + +const userSchema = new Schema( { guildId: { - type: mongoose.SchemaTypes.Decimal128, + type: String, required: true, unique: false, index: true, }, userId: { - type: mongoose.SchemaTypes.Decimal128, + type: String, required: true, unique: false, index: true, }, language: { - type: mongoose.SchemaTypes.String, + type: String, default: 'en', }, - reputation: { type: mongoose.SchemaTypes.Number, default: 0 }, - credits: { type: mongoose.SchemaTypes.Number, default: 0 }, - levels: { type: mongoose.SchemaTypes.Number, default: 0 }, - points: { type: mongoose.SchemaTypes.Number, default: 0 }, + reputation: { type: Number, default: 0 }, + credits: { type: Number, default: 0 }, + level: { type: Number, default: 0 }, + points: { type: Number, default: 0 }, }, { timestamps: true } ); -export default mongoose.model('user', userSchema); +export default model('user', userSchema); diff --git a/src/helpers/dropGuild.ts b/src/helpers/dropGuild.ts new file mode 100644 index 0000000..25df703 --- /dev/null +++ b/src/helpers/dropGuild.ts @@ -0,0 +1,62 @@ +import guilds from '../helpers/database/models/guildSchema'; +import users from '../helpers/database/models/userSchema'; +import apis from '../helpers/database/models/apiSchema'; +import counters from '../helpers/database/models/counterSchema'; +import shopRoles from '../helpers/database/models/shopRolesSchema'; +import timeouts from '../helpers/database/models/timeoutSchema'; + +import logger from '../handlers/logger'; + +import { Guild } from 'discord.js'; +import updatePresence from '../helpers/updatePresence'; + +export default async (guild: Guild) => { + guilds + .deleteMany({ guildId: guild.id }) + .then(async () => { + logger.debug(`Successfully deleted guild: ${guild.id}`); + }) + .catch(async (e) => { + logger.error(`Failed to delete guild: ${guild.id} ${e}`); + }); + users + .deleteMany({ guildId: guild.id }) + .then(async () => { + logger.debug(`Successfully deleted guild: ${guild.id}'s users`); + }) + .catch(async (e) => { + logger.error(`Failed to delete guild: ${guild.id}'s users ${e}`); + }); + apis + .deleteMany({ guildId: guild.id }) + .then(async () => { + logger.debug(`Successfully deleted guild: ${guild.id}'s apis`); + }) + .catch(async (e) => { + logger.error(`Failed to delete guild: ${guild.id}'s apis ${e}`); + }); + counters + .deleteMany({ guildId: guild.id }) + .then(async () => { + logger.debug(`Successfully deleted guild: ${guild.id}'s counters`); + }) + .catch(async (e) => { + logger.error(`Failed to delete guild: ${guild.id}'s counters ${e}`); + }); + shopRoles + .deleteMany({ guildId: guild.id }) + .then(async () => { + logger.debug(`Successfully deleted guild: ${guild.id}'s shop roles`); + }) + .catch(async (e) => { + logger.error(`Failed to delete guild: ${guild.id}'s shop roles ${e}`); + }); + timeouts + .deleteMany({ guildId: guild.id }) + .then(async () => { + logger.debug(`Successfully deleted guild: ${guild.id}'s timeouts`); + }) + .catch(async (e) => { + logger.error(`Failed to delete guild: ${guild.id}'s timeouts ${e}`); + }); +}; diff --git a/src/helpers/dropUser.ts b/src/helpers/dropUser.ts new file mode 100644 index 0000000..ef2e65c --- /dev/null +++ b/src/helpers/dropUser.ts @@ -0,0 +1,13 @@ +import users from '../helpers/database/models/userSchema'; + +import logger from '../handlers/logger'; + +import { Guild, User } from 'discord.js'; + +export default async (user: User, guild: Guild) => { + await users + .deleteOne({ userId: user?.id, guildId: guild?.id }) + .then(async () => + logger.debug(`Guild: ${guild?.id} User: ${user?.id} deleted successfully`) + ); +}; diff --git a/src/helpers/fetchGuild.ts b/src/helpers/fetchGuild.ts new file mode 100644 index 0000000..2a61018 --- /dev/null +++ b/src/helpers/fetchGuild.ts @@ -0,0 +1,31 @@ +// Dependencies +import { Guild } from 'discord.js'; + +// Models +import guildSchema from './database/models/guildSchema'; + +// Handlers +import logger from '../handlers/logger'; + +// Function +export default async (guild: Guild) => { + const guildObj = await guildSchema?.findOne({ guildId: guild.id }); + if (guildObj === null) { + const guildObj = new guildSchema({ guildId: guild.id }); + + await guildObj + .save() + .then(async () => { + logger.debug( + `Guild: ${guild.id} has successfully been added to the database.` + ); + }) + .catch(async (err: any) => { + logger.error(err); + }); + + return guildObj; + } else { + return guildObj; + } +}; diff --git a/src/helpers/fetchUser.ts b/src/helpers/fetchUser.ts new file mode 100644 index 0000000..16adb52 --- /dev/null +++ b/src/helpers/fetchUser.ts @@ -0,0 +1,37 @@ +// Dependencies +import { Guild, User } from 'discord.js'; + +// Models +import userSchema from './database/models/userSchema'; + +// Handlers +import logger from '../handlers/logger'; + +// Function +export default async (user: User, guild: Guild) => { + const userObj = await userSchema?.findOne({ + userId: user.id, + guildId: guild.id, + }); + if (userObj === null) { + const userObj = new userSchema({ + userId: user.id, + guildId: guild.id, + }); + + await userObj + .save() + .then(async () => { + logger.debug( + `Member: ${user.id} has successfully been added to the database.` + ); + }) + .catch(async (err: any) => { + logger.error(err); + }); + + return userObj; + } else { + return userObj; + } +}; diff --git a/src/helpers/updatePresence.ts b/src/helpers/updatePresence.ts new file mode 100644 index 0000000..3b82aae --- /dev/null +++ b/src/helpers/updatePresence.ts @@ -0,0 +1,13 @@ +// Dependencies +import { Client } from 'discord.js'; + +// Function +export default async (client: Client) => { + // Set client status + client?.user?.setPresence({ + activities: [ + { type: 'WATCHING', name: `${client?.guilds?.cache?.size} guilds` }, + ], + status: 'online', + }); +}; diff --git a/src/index.ts b/src/index.ts index 86afd4e..c67e48e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,21 +1,21 @@ // Dependencies -import { Client, Intents } from "discord.js"; // discord.js +import { Client, Intents } from 'discord.js'; // discord.js -import database from "./helpers/database"; -import events from "./handlers/events"; -import commands from "./handlers/commands"; -import locale from "./handlers/locale"; -import schedules from "./handlers/schedules"; +import database from './helpers/database'; +import events from './handlers/events'; +import commands from './handlers/commands'; +import locale from './handlers/locale'; +import schedules from './handlers/schedules'; -import config from "../config.json"; // config.json +import config from '../config.json'; // config.json (async () => { // Initialize discord.js client const client = new Client({ intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - Intents.FLAGS.GUILD_MEMBERS, + Intents?.FLAGS?.GUILDS, + Intents?.FLAGS?.GUILD_MESSAGES, + Intents?.FLAGS?.GUILD_MEMBERS, ], }); @@ -24,5 +24,5 @@ import config from "../config.json"; // config.json await events(client); await commands(client); await schedules(client); - await client.login(config.bot.token); + await client?.login(config?.bot?.token); })();