Implement command cooldown management and enhance command execution flow
- Introduced `applyCommandCooldown` function to manage per-command cooldowns after execution, improving command rate limiting. - Updated command execution flow to include cooldown application, ensuring users are informed of cooldown status. - Enhanced error handling in interaction replies, allowing for more graceful error management and user feedback. - Improved the handling of interaction responses across various commands, ensuring consistent user experience. - Added permission checks for new commands, ensuring only authorized users can execute specific actions.
This commit is contained in:
@@ -1,14 +1,49 @@
|
||||
import { type ChatInputCommandInteraction } from 'discord.js';
|
||||
import { PermissionFlagsBits, type ChatInputCommandInteraction } from 'discord.js';
|
||||
import { t } from '@nexumi/shared';
|
||||
import type { Locale } from '@nexumi/shared';
|
||||
|
||||
const PERMISSION_LABELS: Partial<Record<string, string>> = {
|
||||
[PermissionFlagsBits.Administrator.toString()]: 'Administrator',
|
||||
[PermissionFlagsBits.ManageGuild.toString()]: 'Manage Server',
|
||||
[PermissionFlagsBits.ManageChannels.toString()]: 'Manage Channels',
|
||||
[PermissionFlagsBits.ManageRoles.toString()]: 'Manage Roles',
|
||||
[PermissionFlagsBits.ManageMessages.toString()]: 'Manage Messages',
|
||||
[PermissionFlagsBits.ManageNicknames.toString()]: 'Manage Nicknames',
|
||||
[PermissionFlagsBits.ManageGuildExpressions.toString()]: 'Manage Expressions',
|
||||
[PermissionFlagsBits.KickMembers.toString()]: 'Kick Members',
|
||||
[PermissionFlagsBits.BanMembers.toString()]: 'Ban Members',
|
||||
[PermissionFlagsBits.ModerateMembers.toString()]: 'Timeout Members',
|
||||
[PermissionFlagsBits.ViewChannel.toString()]: 'View Channel',
|
||||
[PermissionFlagsBits.SendMessages.toString()]: 'Send Messages',
|
||||
[PermissionFlagsBits.EmbedLinks.toString()]: 'Embed Links',
|
||||
[PermissionFlagsBits.AttachFiles.toString()]: 'Attach Files',
|
||||
[PermissionFlagsBits.ReadMessageHistory.toString()]: 'Read Message History'
|
||||
};
|
||||
|
||||
function permissionLabel(permission: bigint): string {
|
||||
return PERMISSION_LABELS[permission.toString()] ?? permission.toString();
|
||||
}
|
||||
|
||||
export type RequirePermissionOptions = {
|
||||
/**
|
||||
* Discord permissions the bot itself must hold. Omit for dashboard-style
|
||||
* member gates (e.g. ManageGuild) where the bot does not need the same bit.
|
||||
*/
|
||||
botPermissions?: bigint | readonly bigint[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensures the invoking member has `memberPermission`. Optionally also checks
|
||||
* that the bot has one or more `botPermissions` (moderation actions).
|
||||
*/
|
||||
export async function requirePermission(
|
||||
interaction: ChatInputCommandInteraction,
|
||||
permission: bigint,
|
||||
locale: Locale
|
||||
memberPermission: bigint,
|
||||
locale: Locale,
|
||||
options?: RequirePermissionOptions
|
||||
): Promise<boolean> {
|
||||
const member = interaction.memberPermissions;
|
||||
if (!member?.has(permission)) {
|
||||
if (!member?.has(memberPermission)) {
|
||||
await interaction.reply({
|
||||
content: t(locale, 'generic.noPermission'),
|
||||
ephemeral: true
|
||||
@@ -16,16 +51,36 @@ export async function requirePermission(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!interaction.guild?.members.me?.permissions.has(permission)) {
|
||||
const botBits = options?.botPermissions;
|
||||
if (botBits === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const required = Array.isArray(botBits) ? botBits : [botBits];
|
||||
const me = interaction.guild?.members.me;
|
||||
if (!me) {
|
||||
await interaction.reply({
|
||||
content: t(locale, 'generic.botMissingPermission').replace(
|
||||
'{permission}',
|
||||
permission.toString()
|
||||
required.map(permissionLabel).join(', ')
|
||||
),
|
||||
ephemeral: true
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const bit of required) {
|
||||
if (!me.permissions.has(bit)) {
|
||||
await interaction.reply({
|
||||
content: t(locale, 'generic.botMissingPermission').replace(
|
||||
'{permission}',
|
||||
permissionLabel(bit)
|
||||
),
|
||||
ephemeral: true
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user