Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate single and multi-user versions of commands #40

Merged
merged 9 commits into from
Aug 9, 2024
96 changes: 59 additions & 37 deletions src/commands/ban.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,44 @@
import { EmbedBuilder, MessageMentions } from 'discord.js';
import { EmbedBuilder } from 'discord.js';
import { SlashCommandBuilder } from '@discordjs/builders';
import { Ban } from '@/models/bans';
import { sendEventLogMessage, ordinal } from '@/util';
import { banMessageDeleteChoices, sendEventLogMessage, ordinal } from '@/util';
import { untrustUser } from '@/leveling';
import { notifyUser } from '@/notifications';
import type { ChatInputCommandInteraction } from 'discord.js';
import type { ChatInputCommandInteraction, CommandInteraction, ModalSubmitInteraction } from 'discord.js';

async function banHandler(interaction: ChatInputCommandInteraction): Promise<void> {
async function banCommandHandler(interaction: ChatInputCommandInteraction): Promise<void> {
const subcommand = interaction.options.getSubcommand();
const reason = interaction.options.getString('reason', true);
const deleteMessages = interaction.options.getNumber('delete_messages');

let userIDs;
if (subcommand === 'user') {
const user = interaction.options.getUser('user', true);
userIDs = [user.id];
} else if (subcommand === 'multiuser') {
const users = interaction.options.getString('users', true);
userIDs = [...new Set(Array.from(users.matchAll(/\d{17,18}/g), match => match[0]))];
} else {
throw new Error(`Unknown ban subcommand: ${subcommand}`);
}

await banHandler(interaction, userIDs, reason, deleteMessages);
}

export async function banHandler(interaction: CommandInteraction | ModalSubmitInteraction, userIDs: string[], reason: string, deleteMessages?: number | null): Promise<void> {
await interaction.deferReply({
ephemeral: true
});

const guild = await interaction.guild!.fetch();
const executor = interaction.user;
const users = interaction.options.getString('users', true);
const reason = interaction.options.getString('reason', true);
const deleteMessages = interaction.options.getNumber('delete_messages');

const userIds = [...new Set(Array.from(users!.matchAll(new RegExp(MessageMentions.UsersPattern, 'g')), match => match[1]))];

const bansListEmbed = new EmbedBuilder();
bansListEmbed.setTitle('User Bans :thumbsdown:');
bansListEmbed.setColor(0xFFA500);

for (const userId of userIds) {
const member = await interaction.guild!.members.fetch(userId);
for (const userID of userIDs) {
const member = await interaction.guild!.members.fetch(userID);
const user = member.user;

await untrustUser(member, interaction.createdAt);
Expand Down Expand Up @@ -157,40 +171,48 @@ async function banHandler(interaction: ChatInputCommandInteraction): Promise<voi
]);
}

await interaction.editReply({ embeds: [bansListEmbed] });
await interaction.followUp({ embeds: [bansListEmbed], ephemeral: true });
}

const command = new SlashCommandBuilder()
.setDefaultMemberPermissions('0')
.setName('ban')
.setDescription('Ban user(s)')
.addStringOption(option => {
return option.setName('users')
.setDescription('User(s) to ban')
.setRequired(true);
})
.addStringOption(option => {
return option.setName('reason')
.setDescription('Reason for the ban')
.setRequired(true);
})
.addNumberOption(option => {
return option.setName('delete_messages')
.setDescription('How much of their recent message history to delete')
.addChoices(
{ name: 'Previous 30 Minutes', value: 30 * 60 },
{ name: 'Previous Hour', value: 60 * 60 },
{ name: 'Previous 3 Hours', value: 3 * 60 * 60 },
{ name: 'Previous 6 Hours', value: 6 * 60 * 60 },
{ name: 'Previous 12 Hours', value: 12 * 60 * 60 },
{ name: 'Previous Day', value: 24 * 60 * 60 },
{ name: 'Previous 3 Days', value: 3 * 24 * 60 * 60 },
{ name: 'Previous Week', value: 7 * 24 * 60 * 60 },
);
});
MatthewL246 marked this conversation as resolved.
Show resolved Hide resolved
.addSubcommand(subcommand =>
subcommand.setName('user')
.setDescription('Ban a single user')
.addUserOption(option =>
option.setName('user')
.setDescription('User to ban')
.setRequired(true))
.addStringOption(option =>
option.setName('reason')
.setDescription('Reason for the ban')
.setRequired(true))
.addNumberOption(option =>
option.setName('delete_messages')
.setDescription('How much of their recent message history to delete')
.addChoices(banMessageDeleteChoices))
)
.addSubcommand(subcommand =>
subcommand.setName('multiuser')
.setDescription('Ban multiple users')
.addStringOption(option =>
option.setName('users')
.setDescription('User(s) to ban')
.setRequired(true))
.addStringOption(option =>
option.setName('reason')
.setDescription('Reason for the ban')
.setRequired(true))
.addNumberOption(option =>
option.setName('delete_messages')
.setDescription('How much of their recent message history to delete')
.addChoices(banMessageDeleteChoices))
);

export default {
name: command.name,
handler: banHandler,
handler: banCommandHandler,
deploy: command.toJSON()
};
96 changes: 59 additions & 37 deletions src/commands/kick.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,45 @@
import { MessageMentions, EmbedBuilder } from 'discord.js';
import { EmbedBuilder } from 'discord.js';
import { SlashCommandBuilder } from '@discordjs/builders';
import { Kick } from '@/models/kicks';
import { Ban } from '@/models/bans';
import { ordinal, sendEventLogMessage } from '@/util';
import { banMessageDeleteChoices, ordinal, sendEventLogMessage } from '@/util';
import { untrustUser } from '@/leveling';
import { notifyUser } from '@/notifications';
import type { ChatInputCommandInteraction } from 'discord.js';
import type { ChatInputCommandInteraction, CommandInteraction, ModalSubmitInteraction } from 'discord.js';

async function kickHandler(interaction: ChatInputCommandInteraction): Promise<void> {
async function kickCommandHandler(interaction: ChatInputCommandInteraction): Promise<void> {
const subcommand = interaction.options.getSubcommand();
const reason = interaction.options.getString('reason', true);
const deleteMessages = interaction.options.getNumber('delete_messages');

let userIDs;
if (subcommand === 'user') {
const user = interaction.options.getUser('user', true);
userIDs = [user.id];
} else if (subcommand === 'multiuser') {
const users = interaction.options.getString('users', true);
userIDs = [...new Set(Array.from(users.matchAll(/\d{17,18}/g), match => match[0]))];
} else {
throw new Error(`Unknown kick subcommand: ${subcommand}`);
}

await kickHandler(interaction, userIDs, reason, deleteMessages);
}

export async function kickHandler(interaction: CommandInteraction | ModalSubmitInteraction, userIDs: string[], reason: string, deleteMessages?: number | null): Promise<void> {
await interaction.deferReply({
ephemeral: true
});

const guild = await interaction.guild!.fetch();
const executor = interaction.user;
const users = interaction.options.getString('users', true);
const reason = interaction.options.getString('reason', true);
const deleteMessages = interaction.options.getNumber('delete_messages');

const userIds = [...new Set(Array.from(users.matchAll(new RegExp(MessageMentions.UsersPattern, 'g')), match => match[1]))];

const kicksListEmbed = new EmbedBuilder();
kicksListEmbed.setTitle('User Kicks :thumbsdown:');
kicksListEmbed.setColor(0xFFA500);

for (const userId of userIds) {
const member = await interaction.guild!.members.fetch(userId);
for (const userID of userIDs) {
const member = await interaction.guild!.members.fetch(userID);
const user = member.user;

await untrustUser(member, interaction.createdAt);
Expand Down Expand Up @@ -219,40 +233,48 @@ async function kickHandler(interaction: ChatInputCommandInteraction): Promise<vo
]);
}

await interaction.editReply({ embeds: [kicksListEmbed] });
await interaction.followUp({ embeds: [kicksListEmbed], ephemeral: true });
}

const command = new SlashCommandBuilder()
.setDefaultMemberPermissions('0')
.setName('kick')
.setDescription('Kick user(s)')
.addStringOption(option => {
return option.setName('users')
.setDescription('User(s) to kick')
.setRequired(true);
})
.addStringOption(option => {
return option.setName('reason')
.setDescription('Reason for the kick')
.setRequired(true);
})
.addNumberOption(option => {
return option.setName('delete_messages')
.setDescription('How much of their recent message history to delete')
.addChoices(
{ name: 'Previous 30 Minutes', value: 30 * 60 },
{ name: 'Previous Hour', value: 60 * 60 },
{ name: 'Previous 3 Hours', value: 3 * 60 * 60 },
{ name: 'Previous 6 Hours', value: 6 * 60 * 60 },
{ name: 'Previous 12 Hours', value: 12 * 60 * 60 },
{ name: 'Previous Day', value: 24 * 60 * 60 },
{ name: 'Previous 3 Days', value: 3 * 24 * 60 * 60 },
{ name: 'Previous Week', value: 7 * 24 * 60 * 60 },
);
});
.addSubcommand(subcommand =>
subcommand.setName('user')
.setDescription('Kick user')
.addUserOption(option =>
option.setName('user')
.setDescription('User to kick')
.setRequired(true))
.addStringOption(option =>
option.setName('reason')
.setDescription('Reason for the kick')
.setRequired(true))
.addNumberOption(option =>
option.setName('delete_messages')
.setDescription('How much of their recent message history to delete')
.addChoices(banMessageDeleteChoices))
)
.addSubcommand(subcommand =>
subcommand.setName('multiuser')
.setDescription('Kick multiple users')
.addStringOption(option =>
option.setName('users')
.setDescription('User(s) to kick')
.setRequired(true))
.addStringOption(option =>
option.setName('reason')
.setDescription('Reason for the kick')
.setRequired(true))
.addNumberOption(option =>
option.setName('delete_messages')
.setDescription('How much of their recent message history to delete')
.addChoices(banMessageDeleteChoices))
);

export default {
name: command.name,
handler: kickHandler,
handler: kickCommandHandler,
deploy: command.toJSON()
};
72 changes: 52 additions & 20 deletions src/commands/warn.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,45 @@
import { EmbedBuilder, MessageMentions } from 'discord.js';
import { EmbedBuilder } from 'discord.js';
import { SlashCommandBuilder } from '@discordjs/builders';
import { Warning } from '@/models/warnings';
import { Kick } from '@/models/kicks';
import { Ban } from '@/models/bans';
import { ordinal, sendEventLogMessage } from '@/util';
import { untrustUser } from '@/leveling';
import { notifyUser } from '@/notifications';
import type { ChatInputCommandInteraction } from 'discord.js';
import type { ChatInputCommandInteraction, CommandInteraction, ModalSubmitInteraction } from 'discord.js';

async function warnHandler(interaction: ChatInputCommandInteraction): Promise<void> {
async function warnCommandHandler(interaction: ChatInputCommandInteraction): Promise<void> {
const subcommand = interaction.options.getSubcommand();
const reason = interaction.options.getString('reason', true);

let userIDs;
if (subcommand === 'user') {
const user = interaction.options.getUser('user', true);
userIDs = [user.id];
} else if (subcommand === 'multiuser') {
const users = interaction.options.getString('users', true);
userIDs = [...new Set(Array.from(users.matchAll(/\d{17,18}/g), match => match[0]))];
} else {
throw new Error(`Unknown warn subcommand: ${subcommand}`);
}

await warnHandler(interaction, userIDs, reason);
}

export async function warnHandler(interaction: CommandInteraction | ModalSubmitInteraction, userIDs: string[], reason: string): Promise<void> {
await interaction.deferReply({
ephemeral: true
});

const guild = await interaction.guild!.fetch();
const executor = interaction.user;
const users = interaction.options.getString('users', true);
const reason = interaction.options.getString('reason', true);

const userIds = [...new Set(Array.from(users.matchAll(new RegExp(MessageMentions.UsersPattern, 'g')), match => match[1]))];

const warningListEmbed = new EmbedBuilder();
warningListEmbed.setTitle('User Warnings :thumbsdown:');
warningListEmbed.setColor(0xFFA500);

for (const userId of userIds) {
const member = await interaction.guild!.members.fetch(userId);
for (const userID of userIDs) {
const member = await interaction.guild!.members.fetch(userID);
const user = member.user;

await untrustUser(member, interaction.createdAt);
Expand Down Expand Up @@ -254,26 +268,44 @@ async function warnHandler(interaction: ChatInputCommandInteraction): Promise<vo
]);
}

await interaction.editReply({ embeds: [warningListEmbed] });
await interaction.followUp({ embeds: [warningListEmbed], ephemeral: true });
}

const command = new SlashCommandBuilder()
.setDefaultMemberPermissions('0')
.setName('warn')
.setDescription('Warn user(s)')
.addStringOption(option => {
return option.setName('users')
.setDescription('User(s) to warn')
.setRequired(true);
.addSubcommand(subcommand => {
return subcommand.setName('user')
.setDescription('Warn a user')
.addUserOption(option => {
return option.setName('user')
.setDescription('User to warn')
.setRequired(true);
})
.addStringOption(option => {
return option.setName('reason')
.setDescription('Reason for the warning')
.setRequired(true);
});
})
.addStringOption(option => {
return option.setName('reason')
.setDescription('Reason for the warning')
.setRequired(true);
.addSubcommand(subcommand => {
return subcommand.setName('multiuser')
.setDescription('Warn multiple users')
.addStringOption(option => {
return option.setName('users')
.setDescription('User(s) to warn')
.setRequired(true);
})
.addStringOption(option => {
return option.setName('reason')
.setDescription('Reason for the warning')
.setRequired(true);
});
});

export default {
name: command.name,
handler: warnHandler,
handler: warnCommandHandler,
deploy: command.toJSON()
};
};
Loading