Merge pull request #462 from VermiumSifell/dev
Refactoring some handlers and middlewares
This commit is contained in:
commit
8257f0e137
33 changed files with 567 additions and 934 deletions
19
package-lock.json
generated
19
package-lock.json
generated
|
@ -16,6 +16,7 @@
|
|||
"chance": "^1.1.8",
|
||||
"common": "^0.2.5",
|
||||
"crypto": "^1.0.1",
|
||||
"date-fns": "^2.29.3",
|
||||
"discord-api-types": "^0.37.0",
|
||||
"discord.js": "^14.0.0",
|
||||
"dotenv": "^16.0.1",
|
||||
|
@ -25,6 +26,7 @@
|
|||
"i18next-fs-backend": "^1.1.4",
|
||||
"i18next-http-backend": "^1.4.0",
|
||||
"i18next-resources-to-backend": "^1.0.0",
|
||||
"moment": "^2.29.4",
|
||||
"mongoose": "^6.2.3",
|
||||
"node-schedule": "^2.1.0",
|
||||
"ts-node": "^10.7.0",
|
||||
|
@ -2647,6 +2649,18 @@
|
|||
"integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==",
|
||||
"deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in."
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "2.29.3",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
|
||||
"integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==",
|
||||
"engines": {
|
||||
"node": ">=0.11"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/date-fns"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
|
@ -9706,6 +9720,11 @@
|
|||
"resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
|
||||
"integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig=="
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "2.29.3",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
|
||||
"integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"description": "Earn credits while chatting! And more",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"dev": "tsc --watch & nodemon dist",
|
||||
"dev": "tsc --watch & NODE_ENV=development nodemon dist",
|
||||
"build": "tsc -p .",
|
||||
"prisma:generate": "prisma generate",
|
||||
"test": "jest",
|
||||
|
@ -40,6 +40,7 @@
|
|||
"chance": "^1.1.8",
|
||||
"common": "^0.2.5",
|
||||
"crypto": "^1.0.1",
|
||||
"date-fns": "^2.29.3",
|
||||
"discord-api-types": "^0.37.0",
|
||||
"discord.js": "^14.0.0",
|
||||
"dotenv": "^16.0.1",
|
||||
|
@ -49,6 +50,7 @@
|
|||
"i18next-fs-backend": "^1.1.4",
|
||||
"i18next-http-backend": "^1.4.0",
|
||||
"i18next-resources-to-backend": "^1.0.0",
|
||||
"moment": "^2.29.4",
|
||||
"mongoose": "^6.2.3",
|
||||
"node-schedule": "^2.1.0",
|
||||
"ts-node": "^10.7.0",
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import { success as BaseEmbedSuccess } from "../../../../helpers/baseEmbeds";
|
||||
import { transfer as CreditsTransfer } from "../../../../helpers/credits";
|
||||
import creditsTransfer from "../../../../helpers/credits/transfer";
|
||||
|
||||
// 1. Export a builder function.
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
|
@ -55,7 +55,7 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
|
|||
const EmbedSuccess = await BaseEmbedSuccess(guild, "[:dollar:] Gift");
|
||||
|
||||
// 5. Start an transaction of the credits.
|
||||
await CreditsTransfer(guild, user, target, credits);
|
||||
await creditsTransfer(guild, user, target, credits);
|
||||
|
||||
// 6. Tell the target that they have been gifted credits.
|
||||
await target.send({
|
||||
|
|
|
@ -2,10 +2,11 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
|||
import Chance from "chance";
|
||||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
import { command as CooldownCommand } from "../../../../handlers/cooldown";
|
||||
import prisma from "../../../../handlers/database";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import { success as BaseEmbedSuccess } from "../../../../helpers/baseEmbeds";
|
||||
import creditsGive from "../../../../helpers/credits/give";
|
||||
import cooldown from "../../../../middlewares/cooldown";
|
||||
import logger from "../../../../middlewares/logger";
|
||||
|
||||
// 1. Export a builder function.
|
||||
|
@ -19,7 +20,7 @@ export const execute = async (interaction: CommandInteraction) => {
|
|||
await deferReply(interaction, true);
|
||||
|
||||
// 2. Destructure interaction object.
|
||||
const { guild, user } = interaction;
|
||||
const { guild, user, commandId } = interaction;
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
if (!user) throw new Error("User not found");
|
||||
|
||||
|
@ -43,7 +44,7 @@ export const execute = async (interaction: CommandInteraction) => {
|
|||
if (!createGuild) throw new Error("Guild not found");
|
||||
|
||||
// 6. Create a cooldown for the user.
|
||||
await CooldownCommand(interaction, createGuild.creditsWorkTimeout);
|
||||
await cooldown(guild, user, commandId, createGuild.creditsWorkTimeout);
|
||||
|
||||
// 6. Generate a random number between 0 and creditsWorkRate.
|
||||
const creditsEarned = chance.integer({
|
||||
|
@ -51,51 +52,13 @@ export const execute = async (interaction: CommandInteraction) => {
|
|||
max: createGuild.creditsWorkRate,
|
||||
});
|
||||
|
||||
// 7. Upsert the guildMember in the database.
|
||||
const createGuildMember = await prisma.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
update: { creditsEarned: { increment: creditsEarned } },
|
||||
create: {
|
||||
creditsEarned,
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
logger.silly(createGuildMember);
|
||||
if (!createGuildMember) throw new Error("GuildMember not found");
|
||||
const upsertGuildMember = await creditsGive(guild, user, creditsEarned);
|
||||
|
||||
// 8. Send embed.
|
||||
await interaction.editReply({
|
||||
embeds: [
|
||||
EmbedSuccess.setDescription(
|
||||
`You worked and earned **${creditsEarned}** credits! You now have **${createGuildMember.creditsEarned}** credits. :tada:`
|
||||
`You worked and earned **${creditsEarned}** credits! You now have **${upsertGuildMember.creditsEarned}** credits. :tada:`
|
||||
),
|
||||
],
|
||||
});
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import axios from "axios";
|
||||
import { CommandInteraction, EmbedBuilder } from "discord.js";
|
||||
import { command as CooldownCommand } from "../../../../handlers/cooldown";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
import cooldown from "../../../../middlewares/cooldown";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
|
@ -13,9 +13,11 @@ export default {
|
|||
execute: async (interaction: CommandInteraction) => {
|
||||
await deferReply(interaction, false);
|
||||
|
||||
await CooldownCommand(interaction, 15);
|
||||
const { guild, user, commandId } = interaction;
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
if (!user) throw new Error("User not found");
|
||||
|
||||
const { guild } = interaction;
|
||||
await cooldown(guild, user, commandId, 15);
|
||||
|
||||
const embedConfig = await getEmbedConfig(guild);
|
||||
|
||||
|
|
|
@ -1,21 +1,12 @@
|
|||
// Dependencies
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
} from "discord.js";
|
||||
import logger from "../../../../../../middlewares/logger";
|
||||
// Configurations
|
||||
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
|
||||
// Helpers../../../../../../../helpers/userData
|
||||
import pluralize from "../../../../../../helpers/pluralize";
|
||||
// Models
|
||||
// Handlers
|
||||
import prisma from "../../../../../../handlers/database";
|
||||
import { ChatInputCommandInteraction, PermissionsBitField } from "discord.js";
|
||||
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
// Function
|
||||
import creditsGive from "../../../../../../helpers/credits/give";
|
||||
import pluralize from "../../../../../../helpers/pluralize";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
|
@ -34,81 +25,41 @@ export default {
|
|||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
// 1. Defer reply as ephemeral.
|
||||
await deferReply(interaction, true);
|
||||
|
||||
// 2. Check if the user has the MANAGE_GUILD permission.
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
); // Destructure
|
||||
// 3. Destructure interaction object.
|
||||
const { guild, options } = interaction;
|
||||
if (!guild)
|
||||
throw new Error("We could not get the current guild from discord.");
|
||||
if (!options) throw new Error("We could not get the options from discord.");
|
||||
|
||||
const discordReceiver = options?.getUser("user");
|
||||
const creditAmount = options?.getInteger("amount");
|
||||
|
||||
// If amount option is null
|
||||
if (creditAmount === null)
|
||||
// 4. Get the user and amount from the options.
|
||||
const discordReceiver = options.getUser("user");
|
||||
const creditsAmount = options.getInteger("amount");
|
||||
if (typeof creditsAmount !== "number")
|
||||
throw new Error("You need to provide a credit amount.");
|
||||
|
||||
// If amount is zero or below
|
||||
if (creditAmount <= 0)
|
||||
throw new Error("You must provide a credit amount greater than zero");
|
||||
|
||||
if (discordReceiver === null)
|
||||
if (!discordReceiver)
|
||||
throw new Error("We could not get the receiving user from Discord");
|
||||
|
||||
if (guild === null)
|
||||
throw new Error("We could not get the current guild from discord.");
|
||||
// 5. Create base embeds.
|
||||
const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Give");
|
||||
|
||||
const createGuildMember = await prisma.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: discordReceiver.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
update: { creditsEarned: { increment: creditAmount } },
|
||||
create: {
|
||||
creditsEarned: creditAmount,
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: discordReceiver.id,
|
||||
},
|
||||
where: {
|
||||
id: discordReceiver.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
// 6. Give the credits.
|
||||
await creditsGive(guild, discordReceiver, creditsAmount);
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
|
||||
// Save toUser
|
||||
await interaction?.editReply({
|
||||
// 7. Send embed.
|
||||
return await interaction.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Manage - Credits (Give)")
|
||||
.setDescription(
|
||||
`Successfully gave ${pluralize(creditAmount, "credit")}`
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embedSuccess.setDescription(
|
||||
`Successfully gave ${pluralize(creditsAmount, "credit")}`
|
||||
),
|
||||
],
|
||||
});
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,21 +1,14 @@
|
|||
// Dependencies
|
||||
// Helpers
|
||||
// Models
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
// Configurations
|
||||
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
|
||||
// Handlers
|
||||
import prisma from "../../../../../../handlers/database";
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
import logger from "../../../../../../middlewares/logger";
|
||||
|
||||
// Function
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
import creditsSet from "../../../../../../helpers/credits/set";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
|
@ -35,107 +28,35 @@ export default {
|
|||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
// 1. Defer reply as ephemeral.
|
||||
await deferReply(interaction, true);
|
||||
|
||||
// 2. Check if the user has the permission to manage the guild.
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { errorColor, successColor, footerText, footerIcon } =
|
||||
await getEmbedConfig(interaction.guild);
|
||||
// 3. Destructure interaction object.
|
||||
const { options, guild } = interaction;
|
||||
if (!guild) throw new Error(`We could not find this guild.`);
|
||||
if (!options) throw new Error(`We could not find the options.`);
|
||||
|
||||
// 4. Get the user and amount from the options.
|
||||
const discordUser = options.getUser("user");
|
||||
const creditAmount = options.getInteger("amount");
|
||||
if (typeof creditAmount !== "number") throw new Error("Amount is not set.");
|
||||
if (!discordUser) throw new Error("User is not specified");
|
||||
|
||||
// If amount is null
|
||||
if (creditAmount === null) {
|
||||
logger?.silly(`Amount is null`);
|
||||
// 5. Set the credits.
|
||||
await creditsSet(guild, discordUser, creditAmount);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Manage - Credits (Set)")
|
||||
.setDescription(`You must provide an amount.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
}
|
||||
// 6. Create base embeds.
|
||||
const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Set");
|
||||
|
||||
if (discordUser === null) {
|
||||
logger?.silly(`User is null`);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Manage - Credits (Set)")
|
||||
.setDescription(`You must provide a user.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
}
|
||||
if (guild === null) {
|
||||
logger?.silly(`Guild is null`);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Manage - Credits (Set)")
|
||||
.setDescription(`You must provide a guild.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
const createGuildMember = await prisma.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: discordUser.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
update: { creditsEarned: creditAmount },
|
||||
create: {
|
||||
creditsEarned: creditAmount,
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: discordUser.id,
|
||||
},
|
||||
where: {
|
||||
id: discordUser.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
|
||||
return interaction?.editReply({
|
||||
// 7. Send embed.
|
||||
return await interaction.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Manage - Credits (Set)")
|
||||
.setDescription(
|
||||
`Set **${discordUser}**'s credits to **${creditAmount}**.`
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embedSuccess.setDescription(
|
||||
`Set **${discordUser}**'s credits to **${creditAmount}**.`
|
||||
),
|
||||
],
|
||||
});
|
||||
},
|
||||
|
|
|
@ -1,22 +1,15 @@
|
|||
// Dependencies
|
||||
// Models
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
// Configurations
|
||||
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
|
||||
// Helpers../../../../../../../helpers/userData
|
||||
import pluralize from "../../../../../../helpers/pluralize";
|
||||
// Handlers
|
||||
import prisma from "../../../../../../handlers/database";
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
import logger from "../../../../../../middlewares/logger";
|
||||
|
||||
// Function
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
import creditsTake from "../../../../../../helpers/credits/take";
|
||||
import pluralize from "../../../../../../helpers/pluralize";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
|
@ -36,127 +29,36 @@ export default {
|
|||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
// 1. Defer reply as ephemeral.
|
||||
await deferReply(interaction, true);
|
||||
|
||||
// 2. Check if the user has the MANAGE_GUILD permission.
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { errorColor, successColor, footerText, footerIcon } =
|
||||
await getEmbedConfig(interaction.guild); // Destructure
|
||||
// 3. Destructure interaction object.
|
||||
const { guild, options } = interaction;
|
||||
if (!guild) throw new Error("Invalid guild.");
|
||||
if (!options) throw new Error("Invalid options.");
|
||||
|
||||
// User option
|
||||
const discordReceiver = options?.getUser("user");
|
||||
// 4. Get the user and amount from the options.
|
||||
const discordReceiver = options.getUser("user");
|
||||
const optionAmount = options.getInteger("amount");
|
||||
if (typeof optionAmount !== "number") throw new Error("Invalid amount.");
|
||||
if (!discordReceiver) throw new Error("Invalid user.");
|
||||
|
||||
// Amount option
|
||||
const optionAmount = options?.getInteger("amount");
|
||||
// 5. Create base embeds.
|
||||
const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Take");
|
||||
|
||||
// If amount is null
|
||||
if (optionAmount === null) {
|
||||
logger?.silly(`Amount is null`);
|
||||
// 6. Take the credits.
|
||||
await creditsTake(guild, discordReceiver, optionAmount);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Manage - Credits (Take)")
|
||||
.setDescription(`You must provide an amount.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
// If amount is zero or below
|
||||
if (optionAmount <= 0) {
|
||||
logger?.silly(`Amount is zero or below`);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Manage - Credits (Take)")
|
||||
.setDescription(`You must provide an amount greater than zero.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (discordReceiver === null) {
|
||||
logger?.silly(`Discord receiver is null`);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Manage - Credits (Take)")
|
||||
.setDescription(`You must provide a user.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
}
|
||||
if (guild === null) {
|
||||
logger?.silly(`Guild is null`);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Manage - Credits (Take)")
|
||||
.setDescription(`You must be in a guild.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
const createGuildMember = await prisma.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: discordReceiver.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
update: { creditsEarned: { decrement: optionAmount } },
|
||||
create: {
|
||||
creditsEarned: -optionAmount,
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: discordReceiver.id,
|
||||
},
|
||||
where: {
|
||||
id: discordReceiver.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
await interaction?.editReply({
|
||||
// 7. Send embed.
|
||||
return await interaction.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Manage - Credits (Take)")
|
||||
.setDescription(
|
||||
`Took ${pluralize(optionAmount, "credit")} from ${discordReceiver}.`
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embedSuccess.setDescription(
|
||||
`Took ${pluralize(optionAmount, "credit")} from ${discordReceiver}.`
|
||||
),
|
||||
],
|
||||
});
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
} from "discord.js";
|
||||
import { transfer as CreditsTransfer } from "../../../../../../helpers/credits";
|
||||
import creditsTransfer from "../../../../../../helpers/credits/transfer";
|
||||
// Configurations
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
|
@ -65,7 +65,7 @@ export default {
|
|||
if (!optionToUser)
|
||||
throw new Error("You must provide a user to transfer to.");
|
||||
|
||||
await CreditsTransfer(guild, optionFromUser, optionToUser, optionAmount);
|
||||
await creditsTransfer(guild, optionFromUser, optionToUser, optionAmount);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js";
|
||||
import { command as CooldownCommand } from "../../../../handlers/cooldown";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../middlewares/logger";
|
||||
import noSelfReputation from "./components/noSelfReputation";
|
||||
|
||||
import prisma from "../../../../handlers/database";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import cooldown from "../../../../middlewares/cooldown";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
|
@ -36,7 +36,7 @@ export default {
|
|||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
const { options, user, guild } = interaction;
|
||||
const { options, user, guild, commandId } = interaction;
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
guild
|
||||
|
@ -52,8 +52,10 @@ export default {
|
|||
noSelfReputation(optionTarget, user);
|
||||
|
||||
// Check if user is on cooldown otherwise create one
|
||||
await CooldownCommand(
|
||||
interaction,
|
||||
await cooldown(
|
||||
guild,
|
||||
user,
|
||||
commandId,
|
||||
parseInt(process.env.REPUTATION_TIMEOUT)
|
||||
);
|
||||
|
||||
|
|
|
@ -1,35 +1,14 @@
|
|||
// Dependencies
|
||||
import { BaseInteraction } from "discord.js";
|
||||
import { button as CooldownButton } from "../../../../handlers/cooldown";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
|
||||
export default async (interaction: BaseInteraction) => {
|
||||
if (!interaction.isButton()) return;
|
||||
|
||||
const { guild, customId, memberPermissions } = interaction;
|
||||
const { customId } = interaction;
|
||||
|
||||
const currentButton = await import(`../../../buttons/${customId}`);
|
||||
|
||||
if (!currentButton) throw new Error(`Unknown button ${customId}`);
|
||||
|
||||
const metadata = currentButton.metadata;
|
||||
|
||||
await deferReply(interaction, metadata.ephemeral || false);
|
||||
|
||||
if (metadata.guildOnly && !guild)
|
||||
throw new Error("This command is guild only.");
|
||||
|
||||
if (
|
||||
metadata.permissions &&
|
||||
metadata.guildOnly &&
|
||||
!memberPermissions?.has(metadata.permissions)
|
||||
)
|
||||
throw new Error("You don't have the required permissions");
|
||||
|
||||
if (metadata.dmOnly && guild)
|
||||
throw new Error("This command is only available in DM");
|
||||
|
||||
if (metadata.cooldown) await CooldownButton(interaction, metadata.cooldown);
|
||||
|
||||
await currentButton.execute(interaction);
|
||||
};
|
||||
|
|
|
@ -8,24 +8,5 @@ export default async (interaction: ChatInputCommandInteraction) => {
|
|||
const currentCommand = client.commands.get(commandName);
|
||||
if (!currentCommand) throw new Error(`Unknown command ${commandName}`);
|
||||
|
||||
// const metadata = await getCommandMetadata(interaction, currentCommand);
|
||||
// await deferReply(interaction, metadata.ephemeral || false);
|
||||
|
||||
// if (metadata.guildOnly && !interaction.guild)
|
||||
// throw new Error("This command is guild only.");
|
||||
|
||||
// if (metadata.dmOnly && interaction.guild)
|
||||
// throw new Error("This command is only available in DM");
|
||||
|
||||
// if (
|
||||
// metadata.permissions &&
|
||||
// metadata.guildOnly &&
|
||||
// !interaction.memberPermissions?.has(metadata.permissions)
|
||||
// )
|
||||
// throw new Error("You don't have the required permissions");
|
||||
|
||||
// if (metadata.cooldown) {
|
||||
// await CooldownCommand(interaction, metadata.cooldown);
|
||||
// }
|
||||
await currentCommand.execute(interaction);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { ChannelType, Message } from "discord.js";
|
||||
import { message as CooldownMessage } from "../../../../handlers/cooldown";
|
||||
import prisma from "../../../../handlers/database";
|
||||
import creditsGive from "../../../../helpers/credits/give";
|
||||
import cooldown from "../../../../middlewares/cooldown";
|
||||
import logger from "../../../../middlewares/logger";
|
||||
|
||||
export default {
|
||||
|
@ -51,30 +52,14 @@ export default {
|
|||
|
||||
if (content.length < createGuildMember.guild.creditsMinimumLength) return;
|
||||
|
||||
const isOnCooldown = await CooldownMessage(
|
||||
message,
|
||||
await cooldown(
|
||||
guild,
|
||||
author,
|
||||
"event-messageCreate-credits",
|
||||
createGuildMember.guild.creditsTimeout,
|
||||
"messageCreate-credits"
|
||||
true
|
||||
);
|
||||
if (isOnCooldown) return;
|
||||
|
||||
const updateGuildMember = await prisma.guildMember.update({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: author.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
creditsEarned: {
|
||||
increment: createGuildMember.guild.creditsRate,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(updateGuildMember);
|
||||
|
||||
if (!updateGuildMember)
|
||||
throw new Error("Failed to update guildMember object");
|
||||
await creditsGive(guild, author, createGuildMember.guild.creditsRate);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { ChannelType, Message } from "discord.js";
|
||||
import { message as CooldownMessage } from "../../../../handlers/cooldown";
|
||||
import prisma from "../../../../handlers/database";
|
||||
import cooldown from "../../../../middlewares/cooldown";
|
||||
import logger from "../../../../middlewares/logger";
|
||||
|
||||
export default {
|
||||
|
@ -51,12 +51,13 @@ export default {
|
|||
|
||||
if (content.length < createGuildMember.guild.pointsMinimumLength) return;
|
||||
|
||||
const isOnCooldown = await CooldownMessage(
|
||||
message,
|
||||
await cooldown(
|
||||
guild,
|
||||
author,
|
||||
"event-messageCreate-points",
|
||||
createGuildMember.guild.pointsTimeout,
|
||||
"messageCreate-points"
|
||||
true
|
||||
);
|
||||
if (isOnCooldown) return;
|
||||
|
||||
const updateGuildMember = await prisma.guildMember.update({
|
||||
where: {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import { Client } from "discord.js";
|
||||
// Helpers
|
||||
import deployCommands from "../../handlers/deployCommands";
|
||||
import devMode from "../../handlers/devMode";
|
||||
import updatePresence from "../../handlers/updatePresence";
|
||||
import { IEventOptions } from "../../interfaces/EventOptions";
|
||||
import logger from "../../middlewares/logger";
|
||||
|
@ -16,6 +15,5 @@ export const execute = async (client: Client) => {
|
|||
logger.info("Discord's API client is ready!");
|
||||
|
||||
updatePresence(client);
|
||||
await devMode(client);
|
||||
await deployCommands(client);
|
||||
};
|
||||
|
|
|
@ -1,54 +1,36 @@
|
|||
/* eslint-disable no-loops/no-loops */
|
||||
import { Client } from "discord.js";
|
||||
import listDir from "../../helpers/checkDirectory";
|
||||
import checkDirectory from "../../helpers/checkDirectory";
|
||||
import { ICommand } from "../../interfaces/Command";
|
||||
import logger from "../../middlewares/logger";
|
||||
|
||||
// Register the commands.
|
||||
export const register = async (client: Client) => {
|
||||
// Get name of directories containing commands
|
||||
const commandNames = await listDir("commands");
|
||||
if (!commandNames) throw new Error("📦 No commands available");
|
||||
logger.info("🔧 Started command management");
|
||||
|
||||
const amountOfCommands = commandNames.length;
|
||||
let importedCommandAmount = 0;
|
||||
logger.info(`📦 Trying to load ${amountOfCommands} commands`);
|
||||
const commandNames = await checkDirectory("commands");
|
||||
if (!commandNames) return logger.warn("No available commands found");
|
||||
|
||||
const importCommand = async (commandName: string) => {
|
||||
// Import command from commands
|
||||
const command: ICommand = await import(`../../commands/${commandName}`);
|
||||
if (!command)
|
||||
throw new Error(`📦 No command found while importing "${commandName}"`);
|
||||
if (!command.builder)
|
||||
throw new Error(
|
||||
`📦 No command builder found while importing "${commandName}"`
|
||||
);
|
||||
const totalCommands = commandNames.length;
|
||||
let loadedCommands = 0;
|
||||
|
||||
logger.info(`🔧 Loading ${totalCommands} commands`);
|
||||
|
||||
// Import an command.
|
||||
const importCommand = async (name: string) => {
|
||||
const command: ICommand = await import(`../../commands/${name}`);
|
||||
|
||||
// Add command to collection
|
||||
client.commands.set(command.builder.name, command);
|
||||
importedCommandAmount += 1;
|
||||
loadedCommands++;
|
||||
};
|
||||
|
||||
// Send log message when it's done loading commands
|
||||
const doneImporting = () => {
|
||||
if (importedCommandAmount !== amountOfCommands) {
|
||||
return logger.warn(
|
||||
`📦 Failed importing ${
|
||||
amountOfCommands - importedCommandAmount
|
||||
} of ${amountOfCommands} commands`
|
||||
);
|
||||
}
|
||||
|
||||
return logger.info(`📦 Managed to load all commands`);
|
||||
};
|
||||
|
||||
// Start importing commands
|
||||
commandNames.forEach(async (commandName: string, index: number) => {
|
||||
for await (const commandName of commandNames) {
|
||||
await importCommand(commandName).then(() => {
|
||||
logger.debug(`📦 Imported the "${commandName}" command`);
|
||||
logger.verbose(`🔧 Loaded command "${commandName}"`);
|
||||
});
|
||||
|
||||
// If done importing
|
||||
if (index + 1 === amountOfCommands) {
|
||||
await doneImporting();
|
||||
if (loadedCommands === totalCommands) {
|
||||
logger.info("🔧 All commands loaded");
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,277 +0,0 @@
|
|||
// Dependencies
|
||||
import { ButtonInteraction, CommandInteraction, Message } from "discord.js";
|
||||
import addSeconds from "../../helpers/addSeconds";
|
||||
import logger from "../../middlewares/logger";
|
||||
import prisma from "../database";
|
||||
|
||||
// Command cooldown
|
||||
export const command = async (i: CommandInteraction, cooldown: number) => {
|
||||
const { guild, user, commandId } = i;
|
||||
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
|
||||
// Check if user has a timeout
|
||||
const hasTimeout = await prisma.cooldown.findUnique({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
guildId: guild.id,
|
||||
userId: user.id,
|
||||
timeoutId: commandId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(hasTimeout);
|
||||
|
||||
// If user is not on timeout
|
||||
if (hasTimeout) {
|
||||
const { userId, timeoutId, createdAt } = hasTimeout;
|
||||
const overDue = addSeconds(cooldown, createdAt) < new Date();
|
||||
|
||||
if (!overDue) {
|
||||
const diff = Math.round(
|
||||
(new Date(hasTimeout.createdAt).getTime() - new Date().getTime()) / 1000
|
||||
);
|
||||
|
||||
throw new Error(
|
||||
`You must wait ${diff} seconds before using this command.`
|
||||
);
|
||||
}
|
||||
|
||||
// Delete timeout
|
||||
const deleteCooldown = await prisma.cooldown.delete({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
guildId: guild.id,
|
||||
userId: user.id,
|
||||
timeoutId: commandId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(deleteCooldown);
|
||||
|
||||
logger.debug(
|
||||
`Timeout document ${timeoutId} has been deleted from user ${userId}.`
|
||||
);
|
||||
}
|
||||
|
||||
// Create timeout
|
||||
const createCooldown = await prisma.cooldown.upsert({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
timeoutId: commandId,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
timeoutId: commandId,
|
||||
cooldown,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createCooldown);
|
||||
};
|
||||
|
||||
// Button cooldown
|
||||
export const button = async (i: ButtonInteraction, cooldown: number) => {
|
||||
const { guild, user, customId } = i;
|
||||
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
|
||||
// Check if user has a timeout
|
||||
const hasTimeout = await prisma.cooldown.findUnique({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
guildId: guild.id,
|
||||
userId: user.id,
|
||||
timeoutId: customId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(hasTimeout);
|
||||
|
||||
// If user is not on timeout
|
||||
if (hasTimeout) {
|
||||
const { userId, timeoutId, createdAt } = hasTimeout;
|
||||
const overDue = addSeconds(cooldown, createdAt) < new Date();
|
||||
|
||||
if (!overDue) {
|
||||
const diff = Math.round(
|
||||
(new Date(hasTimeout.createdAt).getTime() - new Date().getTime()) / 1000
|
||||
);
|
||||
|
||||
throw new Error(
|
||||
`You must wait ${diff} seconds before using this command.`
|
||||
);
|
||||
}
|
||||
|
||||
// Delete timeout
|
||||
const deleteCooldown = await prisma.cooldown.delete({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
guildId: guild.id,
|
||||
userId: user.id,
|
||||
timeoutId: customId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(deleteCooldown);
|
||||
|
||||
logger.debug(
|
||||
`Timeout document ${timeoutId} has been deleted from user ${userId}.`
|
||||
);
|
||||
}
|
||||
|
||||
// Create timeout
|
||||
const createCooldown = await prisma.cooldown.upsert({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
timeoutId: customId,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
timeoutId: customId,
|
||||
cooldown,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createCooldown);
|
||||
};
|
||||
|
||||
// Message cooldown
|
||||
export const message = async (msg: Message, cooldown: number, id: string) => {
|
||||
const { guild, member } = msg;
|
||||
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
if (!member) throw new Error("Member is undefined");
|
||||
|
||||
// Check if user has a timeout
|
||||
const hasTimeout = await prisma.cooldown.findUnique({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
guildId: guild.id,
|
||||
userId: member.id,
|
||||
timeoutId: id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(hasTimeout);
|
||||
|
||||
// If user is not on timeout
|
||||
if (hasTimeout) {
|
||||
const { userId, timeoutId, createdAt } = hasTimeout;
|
||||
const overDue = addSeconds(cooldown, createdAt) < new Date();
|
||||
|
||||
if (!overDue) {
|
||||
const diff = Math.round(
|
||||
(new Date(hasTimeout.createdAt).getTime() - new Date().getTime()) / 1000
|
||||
);
|
||||
|
||||
return `User: ${userId} on timeout-id: ${id} with cooldown: ${cooldown} secs with remaining: ${diff} secs.`;
|
||||
}
|
||||
|
||||
// Delete timeout
|
||||
const deleteCooldown = await prisma.cooldown.delete({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
guildId: guild.id,
|
||||
userId: member.id,
|
||||
timeoutId: id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(deleteCooldown);
|
||||
|
||||
logger.debug(
|
||||
`Timeout document ${timeoutId} has been deleted from user ${userId}.`
|
||||
);
|
||||
}
|
||||
|
||||
// Create timeout
|
||||
const createCooldown = await prisma.cooldown.upsert({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
userId: member.id,
|
||||
guildId: guild.id,
|
||||
timeoutId: id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: member.id,
|
||||
},
|
||||
where: {
|
||||
id: member.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
timeoutId: id,
|
||||
cooldown,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createCooldown);
|
||||
};
|
|
@ -1,3 +1,20 @@
|
|||
import { PrismaClient } from '@prisma/client'
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import logger from "../../middlewares/logger";
|
||||
|
||||
export default new PrismaClient()
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
prisma.$use(async (params, next) => {
|
||||
const before = Date.now();
|
||||
|
||||
const result = await next(params);
|
||||
|
||||
const after = Date.now();
|
||||
|
||||
logger.debug(
|
||||
`Query ${params.model}.${params.action} took ${after - before}ms`
|
||||
);
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
export default prisma;
|
||||
|
|
|
@ -1,38 +1,39 @@
|
|||
import { RESTPostAPIApplicationCommandsJSONBody } from "discord-api-types/v10";
|
||||
import { Client } from "discord.js";
|
||||
import { Client, RESTPostAPIApplicationCommandsJSONBody } from "discord.js";
|
||||
import { ICommand } from "../../interfaces/Command";
|
||||
import logger from "../../middlewares/logger";
|
||||
|
||||
export default async (client: Client) => {
|
||||
const commandList: Array<RESTPostAPIApplicationCommandsJSONBody> = [];
|
||||
// 1. Destructure the client.
|
||||
const { application } = client;
|
||||
if (!application) throw new Error("No application found");
|
||||
|
||||
if (!client.commands) {
|
||||
throw new Error("client.commands is not defined");
|
||||
}
|
||||
// 2. Log that we are starting the command management.
|
||||
logger.info("🔧 Started command deployment");
|
||||
|
||||
logger.info("Gathering command list");
|
||||
// 3. Get the commands.
|
||||
const commands: Array<RESTPostAPIApplicationCommandsJSONBody> = [];
|
||||
client.commands.forEach((command: ICommand) => {
|
||||
commands.push(command.builder.toJSON());
|
||||
|
||||
await Promise.all(
|
||||
client.commands.map((commandData: ICommand) => {
|
||||
commandList.push(commandData.builder.toJSON());
|
||||
|
||||
logger.verbose(`${commandData.builder.name} pushed to list`);
|
||||
})
|
||||
)
|
||||
.then(() => {
|
||||
logger.info(`Finished gathering command list.`);
|
||||
})
|
||||
.catch((error) => {
|
||||
throw new Error(`Could not gather command list: ${error}`);
|
||||
});
|
||||
|
||||
await client.application?.commands.set(commandList).then(() => {
|
||||
logger.info(`Finished updating command list.`);
|
||||
logger.verbose(`🔧 Loaded command "${command.builder.name}"`);
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
await client.application?.commands
|
||||
.set(commandList, process.env.DISCORD_GUILD_ID)
|
||||
.then(() => logger.info(`Finished updating guild command list.`));
|
||||
// 4. Set the commands.
|
||||
await application.commands.set(commands).then(() => {
|
||||
logger.info("🔧 Deployed commands globally");
|
||||
});
|
||||
|
||||
// 5. Tell the user that development mode is enabled.
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
logger.info("🔧 Development mode enabled");
|
||||
|
||||
await application.commands
|
||||
.set(commands, process.env.DISCORD_GUILD_ID)
|
||||
.then(() => {
|
||||
logger.info(`🔧 Deployed commands to guild`);
|
||||
});
|
||||
}
|
||||
|
||||
// 6. Log that we are done with the command management.
|
||||
logger.info("🔧 Finished command deployment");
|
||||
};
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import { Client } from "discord.js";
|
||||
import logger from "../../middlewares/logger";
|
||||
|
||||
export default async (client: Client) => {
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
await client?.application?.commands
|
||||
?.set([], process.env.DISCORD_GUILD_ID)
|
||||
.then(() => {
|
||||
return logger.verbose(`Development mode is disabled.`);
|
||||
});
|
||||
}
|
||||
|
||||
return logger.info(`Development mode is enabled.`);
|
||||
};
|
|
@ -1,96 +1,52 @@
|
|||
/* eslint-disable no-loops/no-loops */
|
||||
import { Client } from "discord.js";
|
||||
import listDir from "../../helpers/checkDirectory";
|
||||
import checkDirectory from "../../helpers/checkDirectory";
|
||||
import { IEvent } from "../../interfaces/Event";
|
||||
import logger from "../../middlewares/logger";
|
||||
|
||||
// Registers all available events
|
||||
// Registers all available events.
|
||||
export const register = async (client: Client) => {
|
||||
const eventNames = await listDir("events");
|
||||
if (!eventNames) throw new Error("📦 No events available");
|
||||
logger.info("📡 Started event management");
|
||||
|
||||
const amountOfEvents = eventNames.length;
|
||||
let importedEventAmount = 0;
|
||||
logger.info(`📦 Trying to load ${amountOfEvents} events`);
|
||||
const eventNames = await checkDirectory("events");
|
||||
if (!eventNames) return logger.warn("No available events found");
|
||||
|
||||
const importEvent = async (eventName: string) => {
|
||||
// Import event from events
|
||||
const event: IEvent = await import(`../../events/${eventName}`);
|
||||
if (!event)
|
||||
throw new Error(`📦 No event found while importing "${eventName}"`);
|
||||
if (!event.options)
|
||||
throw new Error(
|
||||
`📦 No event options found while importing "${eventName}"`
|
||||
);
|
||||
if (!event.execute)
|
||||
throw new Error(
|
||||
`📦 No event execute found while importing "${eventName}"`
|
||||
);
|
||||
const totalEvents = eventNames.length;
|
||||
let loadedEvents = 0;
|
||||
|
||||
// Register event
|
||||
logger.info(`📡 Loading ${totalEvents} events`);
|
||||
|
||||
// Import an event.
|
||||
const importEvent = async (name: string) => {
|
||||
const event: IEvent = await import(`../../events/${name}`);
|
||||
|
||||
// Create a new event execute function.
|
||||
const eventExecutor = async (...args: Promise<void>[]) => {
|
||||
await event.execute(...args).catch((err) => {
|
||||
logger.error(`${err}`);
|
||||
});
|
||||
await event.execute(...args);
|
||||
};
|
||||
|
||||
if (!event.options?.type)
|
||||
throw new Error(`📦 No event type found while importing "${eventName}"`);
|
||||
|
||||
switch (event.options.type) {
|
||||
case "once":
|
||||
client.once(eventName, eventExecutor);
|
||||
client.once(name, eventExecutor);
|
||||
break;
|
||||
|
||||
case "on":
|
||||
client.on(eventName, eventExecutor);
|
||||
client.on(name, eventExecutor);
|
||||
break;
|
||||
default:
|
||||
logger.error(`${eventName} does not have a valid type`);
|
||||
}
|
||||
importedEventAmount += 1;
|
||||
};
|
||||
|
||||
// Send log message when it's done loading events
|
||||
const doneImporting = () => {
|
||||
if (importedEventAmount !== amountOfEvents) {
|
||||
return logger.warn(
|
||||
`📦 Failed importing ${
|
||||
amountOfEvents - importedEventAmount
|
||||
} of ${amountOfEvents} events`
|
||||
);
|
||||
throw new Error(`📡 Invalid event type for event: ${name}`);
|
||||
}
|
||||
|
||||
return logger.info(`📦 Managed to load all events`);
|
||||
loadedEvents++;
|
||||
};
|
||||
|
||||
eventNames.forEach(async (eventName: string, index: number) => {
|
||||
for await (const eventName of eventNames) {
|
||||
await importEvent(eventName).then(() => {
|
||||
logger.debug(`📦 Imported the "${eventName}" event`);
|
||||
logger.verbose(`📡 Loaded event "${eventName}"`);
|
||||
});
|
||||
|
||||
// If done importing
|
||||
if (index + 1 === amountOfEvents) {
|
||||
await doneImporting();
|
||||
if (loadedEvents === totalEvents) {
|
||||
logger.info("📡 All events loaded");
|
||||
}
|
||||
});
|
||||
|
||||
// for await (const eventName of eventNames) {
|
||||
// const event: IEvent = await import(`../../events/${eventName}`);
|
||||
// const eventExecutor = async (...args: Promise<void>[]) =>
|
||||
// event.execute(...args).catch(async (err) => {
|
||||
// logger.error(`${err}`);
|
||||
// });
|
||||
// if (!event.options?.type) return;
|
||||
|
||||
// switch (event.options.type) {
|
||||
// case "once":
|
||||
// client.once(eventName, eventExecutor);
|
||||
// break;
|
||||
|
||||
// case "on":
|
||||
// client.on(eventName, eventExecutor);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@ export const start = async (client: Client) => {
|
|||
logger.info("⏰ Started job management");
|
||||
|
||||
const jobNames = await checkDirectory("schedules");
|
||||
if (!jobNames) return logger.warn("No available jobs found");
|
||||
if (!jobNames) return logger.warn("⏰ No available jobs found");
|
||||
|
||||
await Promise.all(
|
||||
jobNames.map(async (jobName) => {
|
||||
|
|
|
@ -4,17 +4,26 @@ import logger from "../../middlewares/logger";
|
|||
|
||||
// Function
|
||||
export default (client: Client) => {
|
||||
if (!client?.user) throw new Error("Client's user is undefined.");
|
||||
const { guilds } = client;
|
||||
// 1. Destructure the client.
|
||||
const { guilds, user } = client;
|
||||
if (!user) throw new Error("No user found");
|
||||
|
||||
// 2. Get the total number of guilds and members.
|
||||
const memberCount = guilds.cache.reduce((a, g) => a + g.memberCount, 0);
|
||||
const guildCount = guilds.cache.size;
|
||||
|
||||
const status = `${memberCount} users in ${guildCount} guilds.`;
|
||||
client.user.setPresence({
|
||||
activities: [{ type: ActivityType.Watching, name: status }],
|
||||
status: "online",
|
||||
// 3. Set the presence.
|
||||
user.setPresence({
|
||||
activities: [
|
||||
{
|
||||
name: `${guildCount} guilds | ${memberCount} members`,
|
||||
type: ActivityType.Watching,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
logger.info(`Client's presence is set to "${status}"`);
|
||||
// 4. Log the presence.
|
||||
return logger.info(
|
||||
`👀 Presence set to "${guildCount} guilds | ${memberCount} members"`
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
export default (seconds: number, date: Date) => {
|
||||
date.setSeconds(date.getSeconds() + seconds);
|
||||
return date;
|
||||
};
|
54
src/helpers/credits/give.ts
Normal file
54
src/helpers/credits/give.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
import { Guild, User } from "discord.js";
|
||||
import prisma from "../../handlers/database";
|
||||
import transactionRules from "./transactionRules";
|
||||
|
||||
export default async (guild: Guild, user: User, amount: number) => {
|
||||
return await prisma.$transaction(async (tx) => {
|
||||
// 1. Check if the transaction is valid.
|
||||
transactionRules(guild, user, amount);
|
||||
|
||||
// 2. Make the transaction.
|
||||
const recipient = await tx.guildMember.upsert({
|
||||
update: {
|
||||
creditsEarned: {
|
||||
increment: amount,
|
||||
},
|
||||
},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
creditsEarned: amount,
|
||||
},
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 3. Verify that the recipient actually is created.
|
||||
if (!recipient) throw new Error("No recipient available");
|
||||
|
||||
// 4. Return the recipient.
|
||||
return recipient;
|
||||
});
|
||||
};
|
52
src/helpers/credits/set.ts
Normal file
52
src/helpers/credits/set.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { Guild, User } from "discord.js";
|
||||
import prisma from "../../handlers/database";
|
||||
import transactionRules from "./transactionRules";
|
||||
|
||||
export default async (guild: Guild, user: User, amount: number) => {
|
||||
return await prisma.$transaction(async (tx) => {
|
||||
// 1. Check if the transaction is valid.
|
||||
transactionRules(guild, user, amount);
|
||||
|
||||
// 2. Make the transaction.
|
||||
const recipient = await tx.guildMember.upsert({
|
||||
update: {
|
||||
creditsEarned: amount,
|
||||
},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
creditsEarned: amount,
|
||||
},
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 3. Verify that the recipient actually is created.
|
||||
if (!recipient) throw new Error("No recipient available");
|
||||
|
||||
// 4. Return the recipient.
|
||||
return recipient;
|
||||
});
|
||||
};
|
55
src/helpers/credits/take.ts
Normal file
55
src/helpers/credits/take.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
import { Guild, User } from "discord.js";
|
||||
import prisma from "../../handlers/database";
|
||||
import transactionRules from "./transactionRules";
|
||||
|
||||
export default async (guild: Guild, user: User, amount: number) => {
|
||||
return await prisma.$transaction(async (tx) => {
|
||||
// 1. Check if the transaction is valid.
|
||||
transactionRules(guild, user, amount);
|
||||
|
||||
// 2. Make the transaction.
|
||||
const recipient = await tx.guildMember.upsert({
|
||||
update: {
|
||||
creditsEarned: {
|
||||
decrement: amount,
|
||||
},
|
||||
},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
creditsEarned: -amount,
|
||||
},
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 3. Verify that the recipient credits are not below zero.
|
||||
if (recipient.creditsEarned < -100)
|
||||
throw new Error("User do not have enough credits");
|
||||
|
||||
// 4. Return the recipient.
|
||||
return recipient;
|
||||
});
|
||||
};
|
18
src/helpers/credits/transactionRules.ts
Normal file
18
src/helpers/credits/transactionRules.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { Guild, User } from "discord.js";
|
||||
|
||||
export default (guild: Guild, user: User, amount: number) => {
|
||||
// 1. Verify that the amount is not above 100.000.000 credits.
|
||||
if (amount > 100000000) {
|
||||
throw new Error("You can't give more than 1.000.000 credits.");
|
||||
}
|
||||
|
||||
// 2. Verify that the amount is not below 1 credits.
|
||||
if (amount <= 0) {
|
||||
throw new Error("You can't give below one credit.");
|
||||
}
|
||||
|
||||
// 3. Verify that the user is not an bot.
|
||||
if (user.bot) {
|
||||
throw new Error("You can't give to an bot.");
|
||||
}
|
||||
};
|
|
@ -1,13 +1,8 @@
|
|||
import { Guild, User } from "discord.js";
|
||||
import prisma from "../../handlers/database";
|
||||
import transactionRules from "./transactionRules";
|
||||
|
||||
// Start an transaction between two users in a guild.
|
||||
export const transfer = async (
|
||||
guild: Guild,
|
||||
from: User,
|
||||
to: User,
|
||||
amount: number
|
||||
) => {
|
||||
export default async (guild: Guild, from: User, to: User, amount: number) => {
|
||||
return await prisma.$transaction(async (tx) => {
|
||||
// 1. Decrement amount from the sender.
|
||||
const sender = await tx.guildMember.upsert({
|
||||
|
@ -47,34 +42,19 @@ export const transfer = async (
|
|||
},
|
||||
});
|
||||
|
||||
// 2. Verify that the sender actually is created.
|
||||
if (!sender) throw new Error("No sender available");
|
||||
|
||||
// 3. Verify that the sender's balance exists.
|
||||
if (!sender.creditsEarned) throw new Error("No credits available");
|
||||
|
||||
// 4. Verify that the sender's balance didn't go below zero.
|
||||
if (sender.creditsEarned < 0) {
|
||||
throw new Error(`${from} doesn't have enough to send ${amount}`);
|
||||
}
|
||||
|
||||
// 5. Verify that the sender is not trying to send less that one credits.
|
||||
if (amount <= 0) {
|
||||
throw new Error("You can't transfer below one credit.");
|
||||
}
|
||||
// 5. Check if the transactions is valid.
|
||||
transactionRules(guild, from, amount);
|
||||
transactionRules(guild, to, amount);
|
||||
|
||||
// 6. Verify that the sender is not trying to send more than 100.000.000 credits.
|
||||
if (amount > 100000000) {
|
||||
throw new Error("You can't transfer more than 100.000.000 credits.");
|
||||
}
|
||||
|
||||
// 7. Verify that recipient are not an bot.
|
||||
if (to.bot) throw new Error("You can't transfer to an bot.");
|
||||
|
||||
// 8. Verify that sender and recipient are not the same user.
|
||||
// 6. Verify that sender and recipient are not the same user.
|
||||
if (from.id === to.id) throw new Error("You can't transfer to yourself.");
|
||||
|
||||
// 9. Increment the recipient's balance by amount.
|
||||
// 7. Increment the recipient's balance by amount.
|
||||
const recipient = await tx.guildMember.upsert({
|
||||
update: {
|
||||
creditsEarned: {
|
|
@ -1,9 +1,9 @@
|
|||
import { Client, Collection, GatewayIntentBits } from "discord.js"; // discord.js
|
||||
import "dotenv/config";
|
||||
|
||||
import { register as commandRegister } from "./handlers/command";
|
||||
import { register as eventRegister } from "./handlers/event";
|
||||
import { start as scheduleStart } from "./handlers/schedule";
|
||||
|
||||
// Main process that starts all other sub processes
|
||||
const main = async () => {
|
||||
// Initiate client object
|
||||
|
|
95
src/middlewares/cooldown/index.ts
Normal file
95
src/middlewares/cooldown/index.ts
Normal file
|
@ -0,0 +1,95 @@
|
|||
import { add, formatDuration, intervalToDuration, isPast } from "date-fns";
|
||||
import { Guild, User } from "discord.js";
|
||||
import prisma from "../../handlers/database";
|
||||
import logger from "../logger";
|
||||
|
||||
export default async (
|
||||
guild: Guild,
|
||||
user: User,
|
||||
id: string,
|
||||
cooldown: number,
|
||||
silent?: boolean
|
||||
) => {
|
||||
// Check if user has a timeout
|
||||
const isOnCooldown = await prisma.cooldown.findUnique({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
guildId: guild.id,
|
||||
userId: user.id,
|
||||
timeoutId: id,
|
||||
},
|
||||
},
|
||||
});
|
||||
logger.silly(isOnCooldown);
|
||||
|
||||
if (isOnCooldown) {
|
||||
const { userId, timeoutId, createdAt } = isOnCooldown;
|
||||
const dueDate = add(createdAt, { seconds: cooldown });
|
||||
|
||||
const duration = formatDuration(
|
||||
intervalToDuration({
|
||||
start: new Date(),
|
||||
end: dueDate,
|
||||
})
|
||||
);
|
||||
|
||||
if (isPast(dueDate)) {
|
||||
return await prisma.cooldown.delete({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
guildId: guild.id,
|
||||
userId: user.id,
|
||||
timeoutId: id,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
return logger.verbose(
|
||||
`User ${userId} is on cooldown for ${timeoutId}, it ends in ${duration}.`
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error(`You are still on cooldown for ${duration}`);
|
||||
}
|
||||
|
||||
const createCooldown = await prisma.cooldown.upsert({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
timeoutId: id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
timeoutId: id,
|
||||
cooldown,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createCooldown);
|
||||
|
||||
return createCooldown;
|
||||
};
|
43
src/schedules/cooldowns/index.ts
Normal file
43
src/schedules/cooldowns/index.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* eslint-disable no-loops/no-loops */
|
||||
import { add, formatDuration, intervalToDuration, isPast } from "date-fns";
|
||||
|
||||
import prisma from "../../handlers/database";
|
||||
import logger from "../../middlewares/logger";
|
||||
|
||||
export const options = {
|
||||
schedule: "*/30 * * * *", // https://crontab.guru/
|
||||
};
|
||||
|
||||
// Execute the job
|
||||
export const execute = async () => {
|
||||
const cooldownsObj = await prisma.cooldown.findMany();
|
||||
|
||||
for await (const cooldownObj of cooldownsObj) {
|
||||
const { guildId, userId, timeoutId, cooldown, createdAt } = cooldownObj;
|
||||
|
||||
const dueDate = add(createdAt, { seconds: cooldown });
|
||||
if (!isPast(dueDate)) return;
|
||||
|
||||
const duration = formatDuration(
|
||||
intervalToDuration({
|
||||
start: new Date(),
|
||||
end: dueDate,
|
||||
})
|
||||
);
|
||||
|
||||
const deleteCooldown = await prisma.cooldown.delete({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
guildId,
|
||||
userId,
|
||||
timeoutId,
|
||||
},
|
||||
},
|
||||
});
|
||||
logger.silly(deleteCooldown);
|
||||
|
||||
logger.verbose(
|
||||
`User ${userId} is on cooldown for ${timeoutId}, it ends in ${duration}.`
|
||||
);
|
||||
}
|
||||
};
|
|
@ -1,40 +0,0 @@
|
|||
/* eslint-disable no-loops/no-loops */
|
||||
import logger from "../../middlewares/logger";
|
||||
|
||||
import addSeconds from "../../helpers/addSeconds";
|
||||
|
||||
import prisma from "../../handlers/database";
|
||||
|
||||
export const options = {
|
||||
schedule: "*/30 * * * *", // https://crontab.guru/
|
||||
};
|
||||
|
||||
// Execute the job
|
||||
export const execute = async () => {
|
||||
const getCooldown = await prisma.cooldown.findMany();
|
||||
|
||||
for await (const timeout of getCooldown) {
|
||||
const { guildId, userId, timeoutId, cooldown, createdAt } = timeout;
|
||||
|
||||
const overDue = addSeconds(cooldown, createdAt) < new Date();
|
||||
|
||||
if (overDue) {
|
||||
logger.info(timeout);
|
||||
const deleteCooldown = await prisma.cooldown.delete({
|
||||
where: {
|
||||
guildId_userId_timeoutId: {
|
||||
guildId,
|
||||
userId,
|
||||
timeoutId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(deleteCooldown);
|
||||
|
||||
logger.debug(
|
||||
`Timeout document ${timeoutId} has been deleted from user ${userId}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
Loading…
Add table
Reference in a new issue