172 lines
5.5 KiB
JavaScript
172 lines
5.5 KiB
JavaScript
const { SlashCommandBuilder, PermissionsBitField } = require('discord.js');
|
|
|
|
// Helper function to parse user from mention or ID
|
|
function parseUser(input, guild) {
|
|
// Check if it's a mention <@123456> or <@!123456>
|
|
const mentionMatch = input.match(/^<@!?(\d+)>$/);
|
|
if (mentionMatch) {
|
|
return guild.members.cache.get(mentionMatch[1])?.user;
|
|
}
|
|
|
|
// Check if it's a user ID
|
|
if (/^\d{15,20}$/.test(input)) {
|
|
return guild.members.cache.get(input)?.user;
|
|
}
|
|
|
|
// Try to find by username or global name
|
|
const member = guild.members.cache.find(m =>
|
|
(m.user.global_name && m.user.global_name.toLowerCase().includes(input.toLowerCase())) ||
|
|
m.user.username.toLowerCase().includes(input.toLowerCase()) ||
|
|
(m.user.global_name && m.user.global_name.toLowerCase() === input.toLowerCase()) ||
|
|
m.user.username.toLowerCase() === input.toLowerCase()
|
|
);
|
|
return member?.user;
|
|
}
|
|
|
|
// Helper function to log moderation actions
|
|
async function logModerationAction(guildId, action, targetUserId, targetUsername, moderatorUserId, moderatorUsername, reason, duration = null, endDate = null) {
|
|
try {
|
|
const logData = {
|
|
guildId,
|
|
action,
|
|
targetUserId,
|
|
targetUsername,
|
|
moderatorUserId,
|
|
moderatorUsername,
|
|
reason,
|
|
duration,
|
|
endDate
|
|
};
|
|
|
|
const response = await fetch(`${process.env.BACKEND_BASE || 'http://localhost:3001'}/internal/log-moderation`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(logData)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
console.error('Failed to log moderation action:', response.statusText);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error logging moderation action:', error);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
name: 'ban',
|
|
description: 'Ban a user from the server',
|
|
enabled: true,
|
|
builder: new SlashCommandBuilder()
|
|
.setName('ban')
|
|
.setDescription('Ban a user from the server')
|
|
.addStringOption(option =>
|
|
option.setName('user')
|
|
.setDescription('The user to ban (mention or user ID)')
|
|
.setRequired(true))
|
|
.addStringOption(option =>
|
|
option.setName('reason')
|
|
.setDescription('Reason for the ban (minimum 3 words)')
|
|
.setRequired(true))
|
|
.addIntegerOption(option =>
|
|
option.setName('days')
|
|
.setDescription('Number of days of messages to delete (0-7)')
|
|
.setRequired(false)
|
|
.setMinValue(0)
|
|
.setMaxValue(7)),
|
|
async execute(interaction) {
|
|
// Check if user has ban permissions
|
|
if (!interaction.member.permissions.has(PermissionsBitField.Flags.BanMembers)) {
|
|
return await interaction.reply({
|
|
content: 'You do not have permission to ban members.',
|
|
flags: 64
|
|
});
|
|
}
|
|
|
|
// Check if bot has ban permissions
|
|
if (!interaction.guild.members.me.permissions.has(PermissionsBitField.Flags.BanMembers)) {
|
|
return await interaction.reply({
|
|
content: 'I do not have permission to ban members.',
|
|
flags: 64
|
|
});
|
|
}
|
|
|
|
const userInput = interaction.options.getString('user');
|
|
const reason = interaction.options.getString('reason');
|
|
const days = interaction.options.getInteger('days') || 0;
|
|
|
|
// Parse the user from the input
|
|
const user = parseUser(userInput, interaction.guild);
|
|
if (!user) {
|
|
return await interaction.reply({
|
|
content: 'Could not find that user. Please provide a valid user mention or user ID.',
|
|
flags: 64
|
|
});
|
|
}
|
|
|
|
// Validate reason has at least 3 words
|
|
const reasonWords = reason.trim().split(/\s+/);
|
|
if (reasonWords.length < 3) {
|
|
return await interaction.reply({
|
|
content: 'Reason must be at least 3 words long.',
|
|
flags: 64
|
|
});
|
|
}
|
|
|
|
// Cannot ban yourself
|
|
if (user.id === interaction.user.id) {
|
|
return await interaction.reply({
|
|
content: 'You cannot ban yourself.',
|
|
flags: 64
|
|
});
|
|
}
|
|
|
|
// Cannot ban the bot
|
|
if (user.id === interaction.guild.members.me.id) {
|
|
return await interaction.reply({
|
|
content: 'I cannot ban myself.',
|
|
flags: 64
|
|
});
|
|
}
|
|
|
|
// Check if user is in the server
|
|
const member = interaction.guild.members.cache.get(user.id);
|
|
if (member) {
|
|
// Check role hierarchy
|
|
if (member.roles.highest.position >= interaction.member.roles.highest.position && interaction.user.id !== interaction.guild.ownerId) {
|
|
return await interaction.reply({
|
|
content: 'You cannot ban a member with a higher or equal role.',
|
|
flags: 64
|
|
});
|
|
}
|
|
|
|
if (member.roles.highest.position >= interaction.guild.members.me.roles.highest.position) {
|
|
return await interaction.reply({
|
|
content: 'I cannot ban a member with a higher or equal role.',
|
|
flags: 64
|
|
});
|
|
}
|
|
}
|
|
|
|
try {
|
|
await interaction.guild.members.ban(user, {
|
|
reason: reason,
|
|
deleteMessageDays: days
|
|
});
|
|
await interaction.reply({
|
|
content: `Successfully banned ${user.global_name || user.username} for: ${reason}${days > 0 ? ` (deleted ${days} days of messages)` : ''}`,
|
|
flags: 64
|
|
});
|
|
|
|
// Log the action
|
|
await logModerationAction(interaction.guildId, 'ban', user.id, user.global_name || user.username, interaction.user.id, interaction.user.global_name || interaction.user.username, reason, 'permanent');
|
|
} catch (error) {
|
|
console.error('Error banning user:', error);
|
|
await interaction.reply({
|
|
content: 'Failed to ban the user. Please try again.',
|
|
flags: 64
|
|
});
|
|
}
|
|
}
|
|
}; |