import { ChatInputCommandInteraction, PermissionFlagsBits, SlashCommandBuilder, time, userMention } from 'discord.js'; import ms from 'ms'; function base() { return new SlashCommandBuilder() .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers | PermissionFlagsBits.KickMembers | PermissionFlagsBits.ModerateMembers); } export const banData = base() .setName('ban') .setDescription('Ban a user') .addUserOption(o => o.setName('user').setDescription('User to ban').setRequired(true)) .addStringOption(o => o.setName('reason').setDescription('Reason').setRequired(false)); export async function banExecute(interaction: ChatInputCommandInteraction) { if (!interaction.guild) return interaction.reply({ content: 'Guild only.', ephemeral: true }); const user = interaction.options.getUser('user', true); const reason = interaction.options.getString('reason') || 'No reason provided'; const member = await interaction.guild.members.fetch(user.id).catch(() => null); if (!member) return interaction.reply({ content: 'User not found in guild.', ephemeral: true }); await user.send(`You have been banned from ${interaction.guild.name}. Reason: ${reason}`).catch(() => null); await member.ban({ reason }); await interaction.reply({ content: `Banned ${userMention(user.id)}.`, allowedMentions: { parse: [] } }); } export const kickData = base() .setName('kick') .setDescription('Kick a user') .addUserOption(o => o.setName('user').setDescription('User to kick').setRequired(true)) .addStringOption(o => o.setName('reason').setDescription('Reason').setRequired(false)); export async function kickExecute(interaction: ChatInputCommandInteraction) { if (!interaction.guild) return interaction.reply({ content: 'Guild only.', ephemeral: true }); const user = interaction.options.getUser('user', true); const reason = interaction.options.getString('reason') || 'No reason provided'; const member = await interaction.guild.members.fetch(user.id).catch(() => null); if (!member) return interaction.reply({ content: 'User not found in guild.', ephemeral: true }); await user.send(`You have been kicked from ${interaction.guild.name}. Reason: ${reason}`).catch(() => null); await member.kick(reason); await interaction.reply({ content: `Kicked ${userMention(user.id)}.`, allowedMentions: { parse: [] } }); } export const timeoutData = base() .setName('timeout') .setDescription('Timeout a user') .addUserOption(o => o.setName('user').setDescription('User to timeout').setRequired(true)) .addStringOption(o => o.setName('duration').setDescription('Duration (e.g. 10m, 1h)').setRequired(true)) .addStringOption(o => o.setName('reason').setDescription('Reason').setRequired(false)); export async function timeoutExecute(interaction: ChatInputCommandInteraction) { if (!interaction.guild) return interaction.reply({ content: 'Guild only.', ephemeral: true }); const user = interaction.options.getUser('user', true); const duration = interaction.options.getString('duration', true); const msDur = ms(duration); if (!msDur || msDur < 1000 || msDur > 28 * 24 * 60 * 60 * 1000) { return interaction.reply({ content: 'Invalid duration. Use between 1s and 28d.', ephemeral: true }); } const reason = interaction.options.getString('reason') || 'No reason provided'; const member = await interaction.guild.members.fetch(user.id).catch(() => null); if (!member) return interaction.reply({ content: 'User not found in guild.', ephemeral: true }); const until = new Date(Date.now() + msDur); await user.send(`You have been timed out in ${interaction.guild.name} until ${time(until, 'F')} UTC. Reason: ${reason}`).catch(() => null); await member.timeout(msDur, reason); await interaction.reply({ content: `Timed out ${userMention(user.id)} until ${time(until, 'F')} UTC.`, allowedMentions: { parse: [] } }); }