Files
Civita/src/commands/moderation.ts
2025-10-20 16:30:50 +02:00

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: [] } });
}