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

@@ -119,12 +119,70 @@ export function startWorkers(context: BotContext): Worker[] {
return;
}
const guild = await context.client.guilds.fetch(job.data.guildId);
const me = await guild.members.fetchMe();
if (!me.permissions.has(PermissionFlagsBits.BanMembers)) {
throw new Error('Missing BanMembers permission for temp ban expiration');
const { guildId, userId, reason } = job.data;
const guild = context.client.guilds.cache.get(guildId);
if (!guild) {
if (!context.client.shard) {
throw new Error(`Guild ${guildId} not available for temp ban expiration`);
}
const results = await context.client.shard.broadcastEval(
async (c, payload) => {
const g = c.guilds.cache.get(payload.guildId);
if (!g) {
return false;
}
const me = await g.members.fetchMe();
if (!me.permissions.has(PermissionFlagsBits.BanMembers)) {
throw new Error('Missing BanMembers permission for temp ban expiration');
}
try {
await g.members.unban(payload.userId, payload.reason ?? 'Temporary ban expired');
} catch (error) {
const code =
typeof error === 'object' && error && 'code' in error
? Number((error as { code: unknown }).code)
: 0;
// Unknown ban (10026) — already unbanned
if (code === 10026) {
return true;
}
throw error;
}
return true;
},
{ context: { guildId, userId, reason } }
);
if (!results.some(Boolean)) {
throw new Error(`Guild ${guildId} not found on any shard for temp ban expiration`);
}
} else {
const me = await guild.members.fetchMe();
if (!me.permissions.has(PermissionFlagsBits.BanMembers)) {
throw new Error('Missing BanMembers permission for temp ban expiration');
}
try {
await guild.members.unban(userId, reason ?? 'Temporary ban expired');
} catch (error) {
const code =
typeof error === 'object' && error && 'code' in error
? Number((error as { code: unknown }).code)
: 0;
if (code !== 10026) {
throw error;
}
}
}
await guild.members.unban(job.data.userId, job.data.reason ?? 'Temporary ban expired');
const { createCase } = await import('./modules/moderation/service.js');
await createCase(context, {
guildId,
targetUserId: userId,
moderatorId: context.client.user?.id ?? 'system',
action: 'UNBAN',
reason: reason ?? 'Temporary ban expired',
source: 'job',
metadata: { tempBanExpire: true }
});
},
{ connection: redis }
);