Enhance verification module with improved command handling and localization

- Updated the verification command to utilize a new `ephemeral` utility for consistent ephemeral message replies.
- Refactored the `buildVerificationPanel` function to include localization support for panel titles and descriptions.
- Added permission checks to ensure the bot can post in the designated verification channel.
- Introduced a new verification queue in the queue management system for better handling of verification tasks.
- Updated localization files to include new keys for verification-related messages in both English and German.
This commit is contained in:
smueller
2026-07-23 10:54:21 +02:00
parent 4b6736444c
commit e24f99ad38
8 changed files with 229 additions and 22 deletions

View File

@@ -1,21 +1,41 @@
import { PermissionFlagsBits } from 'discord.js';
import {
PermissionFlagsBits,
type GuildBasedChannel,
type GuildTextBasedChannel
} from 'discord.js';
import { t } from '@nexumi/shared';
import type { SlashCommand } from '../../types.js';
import { getGuildLocale } from '../../i18n.js';
import { requirePermission } from '../../permissions.js';
import { ephemeral } from '../../interaction-reply.js';
import { verifyCommandData } from './command-definitions.js';
import {
getVerificationConfig,
updateVerificationConfig
} from './service.js';
import { getVerificationConfig, updateVerificationConfig } from './service.js';
import { buildVerificationPanel } from './handlers.js';
function botCanPostPanel(
channel: GuildBasedChannel,
meId: string
): channel is GuildTextBasedChannel {
if (!channel.isTextBased() || channel.isDMBased()) {
return false;
}
const permissions = channel.permissionsFor(meId);
if (!permissions) {
return false;
}
return (
permissions.has(PermissionFlagsBits.ViewChannel) &&
permissions.has(PermissionFlagsBits.SendMessages) &&
permissions.has(PermissionFlagsBits.EmbedLinks)
);
}
const verifyCommand: SlashCommand = {
data: verifyCommandData,
async execute(interaction, context) {
const locale = await getGuildLocale(context.prisma, interaction.guildId);
if (!interaction.inGuild()) {
await interaction.reply({ content: t(locale, 'generic.guildOnly'), ephemeral: true });
await interaction.reply({ content: t(locale, 'generic.guildOnly'), ...ephemeral() });
return;
}
if (!(await requirePermission(interaction, PermissionFlagsBits.ManageGuild, locale))) {
@@ -46,13 +66,16 @@ const verifyCommand: SlashCommand = {
failAction
});
await interaction.reply({ content: t(locale, 'verification.setupDone'), ephemeral: true });
await interaction.reply({ content: t(locale, 'verification.setupDone'), ...ephemeral() });
return;
}
const config = await getVerificationConfig(context.prisma, guildId);
if (!config.enabled || !config.verifiedRoleId) {
await interaction.reply({ content: t(locale, 'verification.notConfigured'), ephemeral: true });
await interaction.reply({
content: t(locale, 'verification.notConfigured'),
...ephemeral()
});
return;
}
@@ -63,12 +86,16 @@ const verifyCommand: SlashCommand = {
? await interaction.guild!.channels.fetch(config.channelId)
: null;
if (!panelChannel?.isTextBased() || panelChannel.isDMBased()) {
await interaction.reply({ content: t(locale, 'verification.invalidChannel'), ephemeral: true });
const me = interaction.guild!.members.me;
if (!panelChannel || !me || !botCanPostPanel(panelChannel, me.id)) {
await interaction.reply({
content: t(locale, 'verification.panelMissingPermission'),
...ephemeral()
});
return;
}
const panel = buildVerificationPanel(config);
const panel = buildVerificationPanel(config, locale);
const message = await panelChannel.send(panel);
await context.prisma.verificationConfig.update({
where: { guildId },
@@ -77,7 +104,7 @@ const verifyCommand: SlashCommand = {
panelMessageId: message.id
}
});
await interaction.reply({ content: t(locale, 'verification.panelPosted'), ephemeral: true });
await interaction.reply({ content: t(locale, 'verification.panelPosted'), ...ephemeral() });
}
};