Merge pull request #660 from ZynerOrg/dev
Improvements and new cooldown feature
This commit is contained in:
commit
ec05cd75ec
15 changed files with 72 additions and 63 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "xyter",
|
||||
"version": "2.2.1",
|
||||
"version": "2.3.0-dev.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "xyter",
|
||||
"version": "2.2.1",
|
||||
"version": "2.3.0-dev.1",
|
||||
"license": "GPL-3.0-only",
|
||||
"dependencies": {
|
||||
"@prisma/client": "^4.7.1",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "xyter",
|
||||
"version": "2.2.1",
|
||||
"version": "2.3.0-dev.1",
|
||||
"private": true,
|
||||
"description": "A multi purpose Discord bot written in TypeScript with Discord.js",
|
||||
"main": "dist/index.js",
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { addDays, startOfDay } from "date-fns";
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
|
@ -60,12 +61,10 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
|
|||
|
||||
await sendResponse(interaction, { embeds: [embed] });
|
||||
|
||||
const cooldownDuration = 24 * 60 * 60; // 24 hours in seconds
|
||||
const cooldownName = await generateCooldownName(interaction);
|
||||
await cooldownManager.setCooldown(
|
||||
cooldownName,
|
||||
await generateCooldownName(interaction),
|
||||
guild,
|
||||
user,
|
||||
cooldownDuration
|
||||
startOfDay(addDays(new Date(), 1))
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { addMonths, startOfDay } from "date-fns";
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
|
@ -66,12 +67,10 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
|
|||
|
||||
await sendResponse(interaction, { embeds: [embed] });
|
||||
|
||||
const cooldownDuration = 4 * 7 * 24 * 60 * 60; // 1 month in seconds
|
||||
const cooldownName = await generateCooldownName(interaction);
|
||||
await cooldownManager.setCooldown(
|
||||
cooldownName,
|
||||
await generateCooldownName(interaction),
|
||||
guild,
|
||||
user,
|
||||
cooldownDuration
|
||||
startOfDay(addMonths(new Date(), 1))
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { addWeeks, startOfDay } from "date-fns";
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
|
@ -62,12 +63,10 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
|
|||
|
||||
await sendResponse(interaction, { embeds: [embed] });
|
||||
|
||||
const cooldownDuration = 7 * 24 * 60 * 60; // 1 week in seconds
|
||||
const cooldownName = await generateCooldownName(interaction);
|
||||
await cooldownManager.setCooldown(
|
||||
cooldownName,
|
||||
await generateCooldownName(interaction),
|
||||
guild,
|
||||
user,
|
||||
cooldownDuration
|
||||
startOfDay(addWeeks(new Date(), 1))
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Chance from "chance";
|
||||
import { addHours } from "date-fns";
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
|
@ -132,6 +133,6 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
|
|||
await generateCooldownName(interaction),
|
||||
guild,
|
||||
user,
|
||||
86400
|
||||
addHours(new Date(), 1)
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import axios from "axios";
|
||||
import { addSeconds } from "date-fns";
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
|
@ -70,14 +71,11 @@ export const execute = async (
|
|||
],
|
||||
});
|
||||
|
||||
const cooldownName = await generateCooldownName(interaction);
|
||||
const cooldownDuration = 5;
|
||||
|
||||
await cooldownManager.setCooldown(
|
||||
cooldownName,
|
||||
await generateCooldownName(interaction),
|
||||
guild || null,
|
||||
user,
|
||||
cooldownDuration
|
||||
addSeconds(new Date(), 5)
|
||||
);
|
||||
} catch (error: unknown) {
|
||||
if ((error as NodeJS.ErrnoException).code === "ENOTFOUND") {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import axios from "axios";
|
||||
import { addSeconds } from "date-fns";
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
|
@ -39,8 +40,6 @@ export const execute = async (
|
|||
await deferReply(interaction, false);
|
||||
|
||||
const { channel, guild, user } = interaction;
|
||||
const cooldownItem = await generateCooldownName(interaction);
|
||||
const cooldownDuration = 15; // 10 seconds
|
||||
|
||||
try {
|
||||
const content: MemeContent = await fetchRandomMeme();
|
||||
|
@ -65,10 +64,10 @@ export const execute = async (
|
|||
}
|
||||
|
||||
await cooldownManager.setCooldown(
|
||||
cooldownItem,
|
||||
await generateCooldownName(interaction),
|
||||
guild || null,
|
||||
user,
|
||||
cooldownDuration
|
||||
addSeconds(new Date(), 5)
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { addMinutes } from "date-fns";
|
||||
import {
|
||||
ChannelType,
|
||||
ChatInputCommandInteraction,
|
||||
|
@ -99,6 +100,6 @@ export const execute = async (
|
|||
await generateCooldownName(interaction),
|
||||
guild,
|
||||
user,
|
||||
5 * 60
|
||||
addMinutes(new Date(), 5)
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { addDays } from "date-fns";
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
|
@ -82,6 +83,6 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
|
|||
await generateCooldownName(interaction),
|
||||
guild,
|
||||
user,
|
||||
24 * 60 * 60
|
||||
addDays(new Date(), 1)
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,6 +5,9 @@ import generateCooldownName from "../../../../helpers/generateCooldownName";
|
|||
import handleCooldown from "./handlers/handleCooldown";
|
||||
import handleUnavailableCommand from "./handlers/handleUnavailableCommand";
|
||||
|
||||
// Create a map to store locks for each identifier (guild ID + user ID + cooldown item)
|
||||
const commandLocks = new Map();
|
||||
|
||||
const cooldownManager = new CooldownManager();
|
||||
|
||||
export default async function handleCommandInteraction(
|
||||
|
@ -24,6 +27,14 @@ export default async function handleCommandInteraction(
|
|||
|
||||
try {
|
||||
const cooldownItem = await generateCooldownName(interaction);
|
||||
|
||||
// Check if the identifier is already locked
|
||||
if (commandLocks.has(cooldownItem)) {
|
||||
throw new Error(
|
||||
"You are unable to execute the same command simultaneously."
|
||||
);
|
||||
}
|
||||
|
||||
const { guildCooldown, userCooldown, guildMemberCooldown } =
|
||||
await cooldownManager.checkCooldowns(cooldownItem, guild, user);
|
||||
|
||||
|
@ -38,10 +49,23 @@ export default async function handleCommandInteraction(
|
|||
userCooldown,
|
||||
guildMemberCooldown
|
||||
);
|
||||
} else {
|
||||
await currentCommand.execute(interaction);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a promise that represents the current command execution
|
||||
const commandExecutionPromise = currentCommand.execute(interaction);
|
||||
|
||||
// Acquire the lock for the identifier and store the command execution promise
|
||||
commandLocks.set(cooldownItem, commandExecutionPromise);
|
||||
|
||||
// Wait for the current command execution to complete
|
||||
await commandExecutionPromise;
|
||||
} catch (error) {
|
||||
await interactionErrorHandler(interaction, error);
|
||||
} finally {
|
||||
const cooldownItem = await generateCooldownName(interaction);
|
||||
|
||||
// Release the lock for the identifier
|
||||
commandLocks.delete(cooldownItem);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { addSeconds } from "date-fns";
|
||||
import { Channel, ChannelType, Guild, Message, User } from "discord.js";
|
||||
import CooldownManager from "../../../handlers/CooldownManager";
|
||||
import CreditsManager from "../../../handlers/CreditsManager";
|
||||
|
@ -93,5 +94,10 @@ async function isUserOnCooldown(guild: Guild, author: User): Promise<boolean> {
|
|||
}
|
||||
|
||||
async function setCooldown(guild: Guild, user: User) {
|
||||
await cooldownManager.setCooldown(cooldownName, guild, user, 5);
|
||||
await cooldownManager.setCooldown(
|
||||
cooldownName,
|
||||
guild,
|
||||
user,
|
||||
addSeconds(new Date(), 5)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,9 +8,8 @@ class CooldownManager {
|
|||
cooldownItem: string,
|
||||
guild: Guild | null,
|
||||
user: User | null,
|
||||
cooldownSeconds: number
|
||||
expiresAt: Date
|
||||
): Promise<void> {
|
||||
const expiresAt = new Date(Date.now() + cooldownSeconds * 1000);
|
||||
const data = {
|
||||
cooldownItem,
|
||||
expiresAt,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { UserReputation } from "@prisma/client";
|
||||
import { User } from "discord.js";
|
||||
import prisma from "./prisma";
|
||||
|
||||
|
@ -38,42 +39,30 @@ class ReputationManager {
|
|||
}
|
||||
|
||||
async repute(user: User, type: "positive" | "negative") {
|
||||
const userData = await prisma.user.upsert({
|
||||
where: { id: user.id },
|
||||
update: {},
|
||||
create: {
|
||||
id: user.id,
|
||||
userReputation: {
|
||||
create: {
|
||||
positive: 0,
|
||||
negative: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
userReputation: true,
|
||||
},
|
||||
});
|
||||
|
||||
let userReputation: any = {};
|
||||
|
||||
if (!userData.userReputation) return null;
|
||||
let userReputation: UserReputation | null = null;
|
||||
|
||||
if (type === "positive") {
|
||||
userReputation = await prisma.userReputation.upsert({
|
||||
where: { id: userData.userReputation.id },
|
||||
where: { id: user.id },
|
||||
update: { positive: { increment: 1 } },
|
||||
create: {
|
||||
positive: 1,
|
||||
negative: 0,
|
||||
user: { connect: { id: user.id } },
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
create: { id: user.id },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (type === "negative") {
|
||||
userReputation = await prisma.userReputation.upsert({
|
||||
where: { id: userData.userReputation.id },
|
||||
where: { id: user.id },
|
||||
update: { negative: { increment: 1 } },
|
||||
create: {
|
||||
positive: 0,
|
||||
|
|
|
@ -25,18 +25,12 @@ export default async (
|
|||
const errorEmbed = new EmbedBuilder()
|
||||
.setAuthor({ name: "⚠️ | Request Failed" })
|
||||
.setDescription(
|
||||
"An error occurred while processing your request. Please try again later."
|
||||
error.message ??
|
||||
"An error occurred while processing your request. Please try again later."
|
||||
)
|
||||
.setColor("#FFCC66")
|
||||
.setTimestamp();
|
||||
|
||||
if (error.message !== undefined) {
|
||||
errorEmbed.addFields({
|
||||
name: "Error Message",
|
||||
value: codeBlock(error.message),
|
||||
});
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === "development" && error.stack !== undefined) {
|
||||
errorEmbed.addFields({
|
||||
name: "Error Stack",
|
||||
|
|
Loading…
Add table
Reference in a new issue