68 lines
3.8 KiB
TypeScript
68 lines
3.8 KiB
TypeScript
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: [] } });
|
|
}
|
|
|
|
|