Moderation Update
This commit is contained in:
187
discord-bot/commands/timeout.js
Normal file
187
discord-bot/commands/timeout.js
Normal file
@@ -0,0 +1,187 @@
|
||||
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: 'timeout',
|
||||
description: 'Timeout a user in the server',
|
||||
enabled: true,
|
||||
builder: new SlashCommandBuilder()
|
||||
.setName('timeout')
|
||||
.setDescription('Timeout a user in the server')
|
||||
.addStringOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('The user to timeout (mention or user ID)')
|
||||
.setRequired(true))
|
||||
.addIntegerOption(option =>
|
||||
option.setName('duration')
|
||||
.setDescription('Duration in minutes (max 40320 minutes = 28 days)')
|
||||
.setRequired(true)
|
||||
.setMinValue(1)
|
||||
.setMaxValue(40320))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Reason for the timeout (minimum 3 words)')
|
||||
.setRequired(true)),
|
||||
async execute(interaction) {
|
||||
// Check if user has moderate members permissions (required for timeout)
|
||||
if (!interaction.member.permissions.has(PermissionsBitField.Flags.ModerateMembers)) {
|
||||
return await interaction.reply({
|
||||
content: 'You do not have permission to timeout members.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
|
||||
// Check if bot has moderate members permissions
|
||||
if (!interaction.guild.members.me.permissions.has(PermissionsBitField.Flags.ModerateMembers)) {
|
||||
return await interaction.reply({
|
||||
content: 'I do not have permission to timeout members.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
|
||||
const userInput = interaction.options.getString('user');
|
||||
const duration = interaction.options.getInteger('duration');
|
||||
const reason = interaction.options.getString('reason');
|
||||
|
||||
// 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 timeout yourself
|
||||
if (user.id === interaction.user.id) {
|
||||
return await interaction.reply({
|
||||
content: 'You cannot timeout yourself.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
|
||||
// Cannot timeout the bot
|
||||
if (user.id === interaction.guild.members.me.id) {
|
||||
return await interaction.reply({
|
||||
content: 'I cannot timeout myself.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
|
||||
// Check if user is in the server
|
||||
const member = interaction.guild.members.cache.get(user.id);
|
||||
if (!member) {
|
||||
return await interaction.reply({
|
||||
content: 'That user is not in this server.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
|
||||
// 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 timeout 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 timeout a member with a higher or equal role.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
|
||||
// Check if user is already timed out
|
||||
if (member.communicationDisabledUntil) {
|
||||
return await interaction.reply({
|
||||
content: 'This user is already timed out.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const timeoutDuration = duration * 60 * 1000; // Convert minutes to milliseconds
|
||||
const timeoutUntil = new Date(Date.now() + timeoutDuration);
|
||||
|
||||
await member.timeout(timeoutDuration, reason);
|
||||
await interaction.reply({
|
||||
content: `Successfully timed out ${user.global_name || user.username} for ${duration} minutes. Reason: ${reason}`,
|
||||
flags: 64
|
||||
});
|
||||
|
||||
// Log the action
|
||||
const durationString = duration >= 1440 ? `${Math.floor(duration / 1440)}d ${Math.floor((duration % 1440) / 60)}h ${duration % 60}m` :
|
||||
duration >= 60 ? `${Math.floor(duration / 60)}h ${duration % 60}m` : `${duration}m`;
|
||||
await logModerationAction(interaction.guildId, 'timeout', user.id, user.global_name || user.username, interaction.user.id, interaction.user.global_name || interaction.user.username, reason, durationString, timeoutUntil);
|
||||
} catch (error) {
|
||||
console.error('Error timing out user:', error);
|
||||
await interaction.reply({
|
||||
content: 'Failed to timeout the user. Please try again.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user