Skip to content

Commit 9382bf2

Browse files
authored
🌟 feat: add DM notification for repel action (#41)
1 parent 4c4d1e8 commit 9382bf2

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

‎src/commands/moderation/repel.ts‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ import {
33
ApplicationCommandType,
44
ChannelType,
55
type ChatInputCommandInteraction,
6+
Colors,
7+
ContainerBuilder,
68
EmbedBuilder,
79
GuildMember,
810
type Message,
911
MessageFlags,
1012
PermissionFlagsBits,
1113
type Role,
1214
type TextChannel,
15+
TextDisplayBuilder,
1316
type User,
1417
} from 'discord.js';
1518
import { HOUR, MINUTE, timeToString } from '../../constants/time.js';
@@ -90,6 +93,39 @@ const checkCanRepelTarget = ({
9093
return { ok: true };
9194
};
9295

96+
const sendReasonToTarget = async ({
97+
target,
98+
reason,
99+
guildName,
100+
timeoutDuration,
101+
}: {
102+
target: GuildMember | User;
103+
reason: string;
104+
guildName: string;
105+
timeoutDuration?: number;
106+
}): Promise<boolean> => {
107+
const parts: string[] = [];
108+
parts.push(`You have been repelled from **${guildName}**.`);
109+
if (timeoutDuration && timeoutDuration > 0) {
110+
parts.push(`You have been timed out for ${timeToString(timeoutDuration)}.`);
111+
}
112+
parts.push(`**Reason:** ${reason}`);
113+
const messageContent = parts.join('\n');
114+
115+
const containerComponent = new ContainerBuilder()
116+
.setAccentColor(Colors.DarkRed)
117+
.addTextDisplayComponents(new TextDisplayBuilder().setContent(messageContent));
118+
try {
119+
await target.send({
120+
flags: MessageFlags.IsComponentsV2,
121+
components: [containerComponent],
122+
});
123+
return true;
124+
} catch {
125+
return false;
126+
}
127+
};
128+
93129
const getTargetFromInteraction = async (
94130
interaction: ChatInputCommandInteraction
95131
): Promise<GuildMember | User> => {
@@ -215,6 +251,7 @@ const logRepelAction = async ({
215251
deleteCount,
216252
reason,
217253
failedChannels,
254+
dm,
218255
}: {
219256
interaction: ChatInputCommandInteraction;
220257
member: GuildMember;
@@ -223,6 +260,10 @@ const logRepelAction = async ({
223260
duration?: number;
224261
deleteCount: number;
225262
failedChannels: string[];
263+
dm: {
264+
sent: boolean;
265+
shouldSend: boolean;
266+
};
226267
}) => {
227268
const channelInfo =
228269
interaction.channel?.type === ChannelType.GuildVoice
@@ -276,6 +317,14 @@ const logRepelAction = async ({
276317
.setColor('Orange')
277318
.setTimestamp();
278319

320+
if (dm.shouldSend) {
321+
resultEmbed.addFields({
322+
name: 'DM Sent',
323+
value: dm.sent ? 'Yes' : 'No',
324+
inline: true,
325+
});
326+
}
327+
279328
const failedChannelsEmbed =
280329
failedChannels.length > 0
281330
? new EmbedBuilder()
@@ -312,6 +361,7 @@ const RepelOptions = {
312361
LOOK_BACK: 'look_back',
313362
TIMEOUT_DURATION: 'timeout_duration',
314363
MESSAGE_FOR_MODS: 'message_for_mods',
364+
DM_USER: 'dm_user',
315365
} as const;
316366

317367
export const repelCommand = createCommand({
@@ -372,6 +422,12 @@ export const repelCommand = createCommand({
372422
type: ApplicationCommandOptionType.String,
373423
description: 'Optional message to include for moderators in the log',
374424
},
425+
{
426+
name: RepelOptions.DM_USER,
427+
required: false,
428+
type: ApplicationCommandOptionType.Boolean,
429+
description: 'Whether to DM the user about the repel action (Defaults to true)',
430+
},
375431
],
376432
},
377433
execute: async (interaction) => {
@@ -443,6 +499,17 @@ export const repelCommand = createCommand({
443499
lookBack: lookBack ?? DEFAULT_LOOK_BACK_MS,
444500
});
445501

502+
const shouldDMUser = interaction.options.getBoolean(RepelOptions.DM_USER) ?? true;
503+
let dmSent = false;
504+
if (shouldDMUser) {
505+
dmSent = await sendReasonToTarget({
506+
target,
507+
reason,
508+
guildName: interaction.guild.name,
509+
timeoutDuration: timeout,
510+
});
511+
}
512+
446513
logRepelAction({
447514
interaction,
448515
member: commandUser,
@@ -451,6 +518,10 @@ export const repelCommand = createCommand({
451518
duration: timeout,
452519
deleteCount: deleted,
453520
failedChannels,
521+
dm: {
522+
sent: dmSent,
523+
shouldSend: shouldDMUser,
524+
},
454525
});
455526

456527
await interaction.editReply({

0 commit comments

Comments
 (0)