111 lines
4.1 KiB
TypeScript
111 lines
4.1 KiB
TypeScript
import { ApplicationIntegrationType, ChatInputCommandInteraction, Client, GuildMember, InteractionContextType, MessageMentions, PermissionFlagsBits, SlashCommandBuilder, time, TimestampStyles } from 'discord.js';
|
|
import { Database } from '../shared/Database';
|
|
import { deferInteraction } from '../utils';
|
|
|
|
const mentionRegex = new RegExp(MessageMentions.UsersPattern);
|
|
|
|
export default {
|
|
name: 'ban',
|
|
data: new SlashCommandBuilder()
|
|
.setName('ban')
|
|
.setDescription('Bans a user.')
|
|
.setIntegrationTypes(ApplicationIntegrationType.GuildInstall)
|
|
.setContexts(InteractionContextType.Guild)
|
|
.setDefaultMemberPermissions(PermissionFlagsBits.BanMembers)
|
|
.addStringOption(option =>
|
|
option
|
|
.setName('user')
|
|
.setDescription('The discord user mention, or ID, to ban.')
|
|
.setRequired(true)
|
|
)
|
|
.addStringOption(option =>
|
|
option
|
|
.setName('reason')
|
|
.setDescription('The reason for the ban')
|
|
.setRequired(false)
|
|
.setMaxLength(400)
|
|
)
|
|
.addNumberOption(option =>
|
|
option
|
|
.setName('hours')
|
|
.setDescription('The duration of the ban, added with other options (0 for permanent).')
|
|
.setRequired(false)
|
|
)
|
|
.addNumberOption(option =>
|
|
option
|
|
.setName('minutes')
|
|
.setDescription('The duration of the ban, added with other options (0 for permanent).')
|
|
.setRequired(false)
|
|
)
|
|
.addNumberOption(option =>
|
|
option
|
|
.setName('seconds')
|
|
.setDescription('The duration of the ban, added with other options (0 for permanent).')
|
|
.setRequired(false)
|
|
)
|
|
.addNumberOption(option =>
|
|
option
|
|
.setName('delete-message-days')
|
|
.setDescription('How far back to delete messages (in days, default: 0 days).')
|
|
.setRequired(false)
|
|
.setMinValue(0)
|
|
.setMaxValue(7)
|
|
),
|
|
handler: async function (client: Client, interaction: ChatInputCommandInteraction) {
|
|
await deferInteraction(interaction);
|
|
|
|
if (!interaction.guild) return interaction.editReply('This command must be used in a server');
|
|
|
|
if (!interaction.guild.members.me) return interaction.editReply('An error has occurred. Please try again later.');
|
|
|
|
const input = interaction.options.getString('user', true);
|
|
|
|
const matches = mentionRegex.exec(input);
|
|
mentionRegex.lastIndex = 0;
|
|
|
|
const idToUse = matches ? matches.groups!.id : input;
|
|
const reason = interaction.options.getString('reason') ?? '';
|
|
|
|
const hours = (interaction.options.getNumber('hours') ?? 0) * 3.6e+6;
|
|
const minutes = (interaction.options.getNumber('minutes') ?? 0) * 60000;
|
|
const seconds = (interaction.options.getNumber('seconds') ?? 0) * 1000;
|
|
|
|
const duration = hours + minutes + seconds;
|
|
|
|
const deleteMessageDays = (interaction.options.getNumber('delete-message-days') ?? 0) * 86400;
|
|
|
|
let banMember: GuildMember | null = null;
|
|
|
|
try {
|
|
banMember = await interaction.guild.members.fetch(idToUse);
|
|
} catch (e) {
|
|
// Member not in server.
|
|
}
|
|
|
|
const member = await interaction.guild.members.fetch(interaction.user.id);
|
|
|
|
if (banMember && member.roles.highest.comparePositionTo(banMember.roles.highest) <= 0) {
|
|
return await interaction.editReply('You do not have permission to ban this user.');
|
|
}
|
|
|
|
if (banMember && !banMember.bannable) {
|
|
return await interaction.editReply('I do not have permission to ban this user.');
|
|
}
|
|
|
|
const expiresAt = new Date(Date.now() + duration);
|
|
|
|
if (duration > 0) await Database.putBan(idToUse, expiresAt);
|
|
|
|
try {
|
|
await interaction.guild.bans.create(idToUse, {
|
|
reason: (reason + ` Banned by ${interaction.user.username} (${interaction.user.id})${duration > 0 ? `. Expires at: ${time(expiresAt, TimestampStyles.ShortDateTime)}` : ''}`).trim(),
|
|
deleteMessageSeconds: deleteMessageDays
|
|
});
|
|
} catch (e) {
|
|
console.error(e);
|
|
return await interaction.editReply("Error banning user (couldn't ban).");
|
|
}
|
|
|
|
await interaction.editReply(`<@${idToUse}> (${idToUse}) has been banned.`);
|
|
}
|
|
}; |