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:
@@ -1,8 +1,9 @@
|
||||
import { TextChannel, type ButtonInteraction } from 'discord.js';
|
||||
import { type Locale, t } from '@nexumi/shared';
|
||||
import { type Locale, t, tf } from '@nexumi/shared';
|
||||
import type { BotContext } from '../../types.js';
|
||||
import { assertBannableForConfirm } from '../../hierarchy.js';
|
||||
import { createCase, scheduleTempBanExpire } from './service.js';
|
||||
import { parseDuration } from './duration.js';
|
||||
import { tryParseDuration } from './duration.js';
|
||||
|
||||
type BanPayload = {
|
||||
userId: string;
|
||||
@@ -36,8 +37,24 @@ export async function executeBan(
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(await assertBannableForConfirm(interaction, locale, payload.userId))) {
|
||||
return;
|
||||
}
|
||||
|
||||
let durationMs: number | null = null;
|
||||
if (payload.duration) {
|
||||
durationMs = tryParseDuration(payload.duration);
|
||||
if (durationMs === null || durationMs <= 0) {
|
||||
await interaction.update({
|
||||
content: t(locale, 'moderation.duration.invalid'),
|
||||
components: []
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await guild.members.ban(payload.userId, { reason: payload.reason });
|
||||
await createCase(context, {
|
||||
const modCase = await createCase(context, {
|
||||
guildId: guild.id,
|
||||
targetUserId: payload.userId,
|
||||
moderatorId: interaction.user.id,
|
||||
@@ -47,21 +64,17 @@ export async function executeBan(
|
||||
source: 'button_confirmation',
|
||||
metadata: {
|
||||
confirmed: true,
|
||||
duration: payload.duration
|
||||
duration: payload.duration,
|
||||
durationMs
|
||||
}
|
||||
});
|
||||
|
||||
if (payload.duration) {
|
||||
await scheduleTempBanExpire(
|
||||
guild.id,
|
||||
payload.userId,
|
||||
parseDuration(payload.duration),
|
||||
payload.reason
|
||||
);
|
||||
if (durationMs !== null) {
|
||||
await scheduleTempBanExpire(guild.id, payload.userId, durationMs, payload.reason);
|
||||
}
|
||||
|
||||
await interaction.update({
|
||||
content: t(locale, 'moderation.success'),
|
||||
content: tf(locale, 'moderation.success.case', { caseNumber: modCase.caseNumber }),
|
||||
components: []
|
||||
});
|
||||
}
|
||||
@@ -97,7 +110,7 @@ export async function executePurge(
|
||||
deletedCount = deleted.size;
|
||||
}
|
||||
|
||||
await createCase(context, {
|
||||
const modCase = await createCase(context, {
|
||||
guildId: guild.id,
|
||||
targetUserId: interaction.user.id,
|
||||
moderatorId: interaction.user.id,
|
||||
@@ -122,7 +135,10 @@ export async function executePurge(
|
||||
});
|
||||
|
||||
await interaction.update({
|
||||
content: t(locale, 'moderation.success'),
|
||||
content: tf(locale, 'moderation.purge.done', {
|
||||
deletedCount,
|
||||
caseNumber: modCase.caseNumber
|
||||
}),
|
||||
components: []
|
||||
});
|
||||
}
|
||||
@@ -143,7 +159,7 @@ export async function executeCaseDelete(
|
||||
where: { guildId_caseNumber: { guildId, caseNumber: payload.caseNumber } }
|
||||
});
|
||||
|
||||
if (!existing) {
|
||||
if (!existing || existing.deletedAt) {
|
||||
await interaction.update({
|
||||
content: t(locale, 'moderation.case.notFound'),
|
||||
components: []
|
||||
@@ -156,7 +172,7 @@ export async function executeCaseDelete(
|
||||
data: { deletedAt: new Date() }
|
||||
});
|
||||
|
||||
await createCase(context, {
|
||||
const modCase = await createCase(context, {
|
||||
guildId,
|
||||
targetUserId: existing.targetUserId,
|
||||
moderatorId: interaction.user.id,
|
||||
@@ -172,7 +188,7 @@ export async function executeCaseDelete(
|
||||
});
|
||||
|
||||
await interaction.update({
|
||||
content: t(locale, 'moderation.success'),
|
||||
content: tf(locale, 'moderation.success.case', { caseNumber: modCase.caseNumber }),
|
||||
components: []
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user