@@ -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' ;
1518import { 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+
93129const 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
317367export 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