Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions src/commands/moderation/repel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ import {
ApplicationCommandType,
ChannelType,
type ChatInputCommandInteraction,
Colors,
ContainerBuilder,
EmbedBuilder,
GuildMember,
type Message,
MessageFlags,
PermissionFlagsBits,
type Role,
type TextChannel,
TextDisplayBuilder,
type User,
} from 'discord.js';
import { HOUR, MINUTE, timeToString } from '../../constants/time.js';
Expand Down Expand Up @@ -90,6 +93,39 @@ const checkCanRepelTarget = ({
return { ok: true };
};

const sendReasonToTarget = async ({
target,
reason,
guildName,
timeoutDuration,
}: {
target: GuildMember | User;
reason: string;
guildName: string;
timeoutDuration?: number;
}): Promise<boolean> => {
const parts: string[] = [];
parts.push(`You have been repelled from **${guildName}**.`);
if (timeoutDuration && timeoutDuration > 0) {
parts.push(`You have been timed out for ${timeToString(timeoutDuration)}.`);
}
parts.push(`**Reason:** ${reason}`);
const messageContent = parts.join('\n');

const containerComponent = new ContainerBuilder()
.setAccentColor(Colors.DarkRed)
.addTextDisplayComponents(new TextDisplayBuilder().setContent(messageContent));
try {
await target.send({
flags: MessageFlags.IsComponentsV2,
components: [containerComponent],
});
return true;
} catch {
return false;
}
Comment on lines +118 to +126
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personally i would not return anything, and instead throw an error on catch, as well as console.log the error

Suggested change
try {
await target.send({
flags: MessageFlags.IsComponentsV2,
components: [containerComponent],
});
return true;
} catch {
return false;
}
try {
await target.send({
flags: MessageFlags.IsComponentsV2,
components: [containerComponent],
});
} catch (error) {
console.log("Unable to send DM to user:\n", error);
throw new Error(""Unable to send DM to user.");
}

and then ... (see next comment) 1/2

};

const getTargetFromInteraction = async (
interaction: ChatInputCommandInteraction
): Promise<GuildMember | User> => {
Expand Down Expand Up @@ -215,6 +251,7 @@ const logRepelAction = async ({
deleteCount,
reason,
failedChannels,
dm,
}: {
interaction: ChatInputCommandInteraction;
member: GuildMember;
Expand All @@ -223,6 +260,10 @@ const logRepelAction = async ({
duration?: number;
deleteCount: number;
failedChannels: string[];
dm: {
sent: boolean;
shouldSend: boolean;
};
}) => {
const channelInfo =
interaction.channel?.type === ChannelType.GuildVoice
Expand Down Expand Up @@ -276,6 +317,14 @@ const logRepelAction = async ({
.setColor('Orange')
.setTimestamp();

if (dm.shouldSend) {
resultEmbed.addFields({
name: 'DM Sent',
value: dm.sent ? 'Yes' : 'No',
inline: true,
});
}

const failedChannelsEmbed =
failedChannels.length > 0
? new EmbedBuilder()
Expand Down Expand Up @@ -312,6 +361,7 @@ const RepelOptions = {
LOOK_BACK: 'look_back',
TIMEOUT_DURATION: 'timeout_duration',
MESSAGE_FOR_MODS: 'message_for_mods',
DM_USER: 'dm_user',
} as const;

export const repelCommand = createCommand({
Expand Down Expand Up @@ -372,6 +422,12 @@ export const repelCommand = createCommand({
type: ApplicationCommandOptionType.String,
description: 'Optional message to include for moderators in the log',
},
{
name: RepelOptions.DM_USER,
required: false,
type: ApplicationCommandOptionType.Boolean,
description: 'Whether to DM the user about the repel action (Defaults to true)',
},
],
},
execute: async (interaction) => {
Expand Down Expand Up @@ -442,6 +498,17 @@ export const repelCommand = createCommand({
lookBack: lookBack ?? DEFAULT_LOOK_BACK_MS,
});

const shouldDMUser = interaction.options.getBoolean(RepelOptions.DM_USER) ?? true;
let dmSent = false;
if (shouldDMUser) {
dmSent = await sendReasonToTarget({
target,
reason,
guildName: interaction.guild.name,
timeoutDuration: timeout,
});
}
Comment on lines +503 to +510
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and then (2/2) we do this here

Suggested change
if (shouldDMUser) {
dmSent = await sendReasonToTarget({
target,
reason,
guildName: interaction.guild.name,
timeoutDuration: timeout,
});
}
if (shouldDMUser) {
try {
await sendReasonToTarget({
target,
reason,
guildName: interaction.guild.name,
timeoutDuration: timeout,
});
}
dmSent = true; // but could also be default to true
} catch {
dmSent = false;
}


logRepelAction({
interaction,
member: commandUser,
Expand All @@ -450,6 +517,10 @@ export const repelCommand = createCommand({
duration: timeout,
deleteCount: deleted,
failedChannels,
dm: {
sent: dmSent,
shouldSend: shouldDMUser,
},
});

await interaction.editReply({
Expand Down