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:
@@ -7,6 +7,11 @@ import type {
|
||||
StringSelectMenuInteraction,
|
||||
UserSelectMenuInteraction
|
||||
} from 'discord.js';
|
||||
import { decodeComponentCustomId, t, type DashboardModuleId } from '@nexumi/shared';
|
||||
import { env } from './env.js';
|
||||
import { getGuildLocale } from './i18n.js';
|
||||
import { isModuleEnabled, moduleForComponent } from './module-gates.js';
|
||||
import { isMaintenanceMode } from './presence.js';
|
||||
import type { BotContext } from './types.js';
|
||||
import {
|
||||
handleModerationConfirmation,
|
||||
@@ -139,11 +144,67 @@ const handlers: InteractionHandler[] = [
|
||||
}
|
||||
];
|
||||
|
||||
function moduleForComponentsV2(customId: string): DashboardModuleId | null {
|
||||
const decoded = decodeComponentCustomId(customId);
|
||||
if (!decoded) {
|
||||
return null;
|
||||
}
|
||||
switch (decoded.source) {
|
||||
case 'w':
|
||||
return 'welcome';
|
||||
case 't':
|
||||
return 'tags';
|
||||
case 's':
|
||||
return 'scheduler';
|
||||
case 'm':
|
||||
return 'messages';
|
||||
default:
|
||||
return 'messages';
|
||||
}
|
||||
}
|
||||
|
||||
export async function routeComponentInteraction(
|
||||
interaction: AnyComponentInteraction,
|
||||
context: BotContext
|
||||
): Promise<boolean> {
|
||||
const customId = interaction.customId;
|
||||
const locale = await getGuildLocale(context.prisma, interaction.guildId);
|
||||
|
||||
const maintenance = await isMaintenanceMode(context);
|
||||
const ownerIds = env.OWNER_USER_IDS ?? [];
|
||||
if (maintenance.enabled && !ownerIds.includes(interaction.user.id)) {
|
||||
if (!interaction.replied && !interaction.deferred) {
|
||||
await interaction.reply({
|
||||
content: maintenance.message?.trim() || t(locale, 'generic.maintenance'),
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
let moduleId = moduleForComponent(customId);
|
||||
if (!moduleId && isComponentsV2Interaction(customId)) {
|
||||
moduleId = moduleForComponentsV2(customId);
|
||||
}
|
||||
|
||||
if (moduleId && interaction.guildId) {
|
||||
const enabled = await isModuleEnabled(
|
||||
context.prisma,
|
||||
context.redis,
|
||||
interaction.guildId,
|
||||
moduleId
|
||||
);
|
||||
if (!enabled) {
|
||||
if (!interaction.replied && !interaction.deferred) {
|
||||
await interaction.reply({
|
||||
content: t(locale, 'generic.moduleDisabled'),
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (const handler of handlers) {
|
||||
if (handler.match(customId)) {
|
||||
await handler.handle(interaction, context);
|
||||
|
||||
Reference in New Issue
Block a user