Enhance bot functionality with new features and improvements

- Updated package dependencies to include `@sentry/node` for error tracking.
- Refactored command routing to incorporate user and guild blacklisting checks, improving command execution safety.
- Enhanced health server metrics to include queue waiting times, providing better insights into system performance.
- Introduced confirmation handling for guild backup commands, streamlining user interactions.
- Improved moderation commands with better error handling and case management, ensuring robust moderation capabilities.
- Added new duration parsing functions to handle timeout durations effectively, enhancing moderation features.
- Updated localization files to reflect new command structures and user guidance improvements.
This commit is contained in:
smueller
2026-07-23 09:53:44 +02:00
parent 4e135bcf43
commit ffaa1e26fd
31 changed files with 1831 additions and 363 deletions

View File

@@ -0,0 +1,154 @@
import type {
ButtonInteraction,
ChannelSelectMenuInteraction,
MentionableSelectMenuInteraction,
ModalSubmitInteraction,
RoleSelectMenuInteraction,
StringSelectMenuInteraction,
UserSelectMenuInteraction
} from 'discord.js';
import type { BotContext } from './types.js';
import {
handleModerationConfirmation,
isModerationConfirmation
} from './modules/moderation/confirmations.js';
import { handleVerificationButton } from './modules/verification/handlers.js';
import { isVerificationButton } from './modules/verification/service.js';
import {
handleBlackjackButton,
isBlackjackButton
} from './modules/economy/blackjack-buttons.js';
import {
handleEmbedModal,
handlePollButton,
isEmbedModal,
isPollButton
} from './modules/utility/index.js';
import { handleFunButton, isFunButton } from './modules/fun/index.js';
import { handleGiveawayButton, isGiveawayButton } from './modules/giveaways/index.js';
import { handleTicketInteraction, isTicketInteraction } from './modules/tickets/index.js';
import {
handleSelfRoleInteraction,
isSelfRoleInteraction
} from './modules/selfroles/index.js';
import {
handleSuggestionButton,
isSuggestionButton
} from './modules/suggestions/index.js';
import {
handleTempVoiceInteraction,
isTempVoiceInteraction,
isTempVoiceModal
} from './modules/tempvoice/index.js';
import { handleGuildBackupButton, isGuildBackupButton } from './modules/guildbackup/index.js';
import {
handleComponentsV2Interaction,
isComponentsV2Interaction
} from './modules/components-v2/index.js';
type AnyComponentInteraction =
| ButtonInteraction
| StringSelectMenuInteraction
| UserSelectMenuInteraction
| RoleSelectMenuInteraction
| ChannelSelectMenuInteraction
| MentionableSelectMenuInteraction
| ModalSubmitInteraction;
type InteractionHandler = {
match: (customId: string) => boolean;
handle: (interaction: AnyComponentInteraction, context: BotContext) => Promise<void>;
};
function asButton(interaction: AnyComponentInteraction): ButtonInteraction {
return interaction as ButtonInteraction;
}
function asModal(interaction: AnyComponentInteraction): ModalSubmitInteraction {
return interaction as ModalSubmitInteraction;
}
const handlers: InteractionHandler[] = [
{
match: isModerationConfirmation,
handle: (interaction, context) => handleModerationConfirmation(asButton(interaction), context)
},
{
match: isVerificationButton,
handle: (interaction, context) => handleVerificationButton(asButton(interaction), context)
},
{
match: isBlackjackButton,
handle: (interaction, context) => handleBlackjackButton(asButton(interaction), context)
},
{
match: isPollButton,
handle: (interaction, context) => handlePollButton(asButton(interaction), context)
},
{
match: isFunButton,
handle: (interaction, context) => handleFunButton(asButton(interaction), context)
},
{
match: isGiveawayButton,
handle: (interaction, context) => handleGiveawayButton(asButton(interaction), context)
},
{
match: isTicketInteraction,
handle: (interaction, context) =>
handleTicketInteraction(
interaction as Parameters<typeof handleTicketInteraction>[0],
context
)
},
{
match: isSelfRoleInteraction,
handle: (interaction, context) =>
handleSelfRoleInteraction(
interaction as Parameters<typeof handleSelfRoleInteraction>[0],
context
)
},
{
match: isSuggestionButton,
handle: (interaction, context) => handleSuggestionButton(asButton(interaction), context)
},
{
match: (customId) => isTempVoiceInteraction(customId) || isTempVoiceModal(customId),
handle: (interaction, context) =>
handleTempVoiceInteraction(
interaction as Parameters<typeof handleTempVoiceInteraction>[0],
context
)
},
{
match: isGuildBackupButton,
handle: (interaction, context) => handleGuildBackupButton(asButton(interaction), context)
},
{
match: isEmbedModal,
handle: (interaction, context) => handleEmbedModal(asModal(interaction), context)
},
{
match: isComponentsV2Interaction,
handle: (interaction, context) =>
handleComponentsV2Interaction(
interaction as Parameters<typeof handleComponentsV2Interaction>[0],
context
)
}
];
export async function routeComponentInteraction(
interaction: AnyComponentInteraction,
context: BotContext
): Promise<boolean> {
const customId = interaction.customId;
for (const handler of handlers) {
if (handler.match(customId)) {
await handler.handle(interaction, context);
return true;
}
}
return false;
}