Moderation Update
This commit is contained in:
172
discord-bot/commands/ban.js
Normal file
172
discord-bot/commands/ban.js
Normal file
@@ -0,0 +1,172 @@
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
167
discord-bot/commands/kick.js
Normal file
167
discord-bot/commands/kick.js
Normal file
@@ -0,0 +1,167 @@
|
||||
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: 'kick',
|
||||
description: 'Kick a user from the server',
|
||||
enabled: true,
|
||||
builder: new SlashCommandBuilder()
|
||||
.setName('kick')
|
||||
.setDescription('Kick a user from the server')
|
||||
.addStringOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('The user to kick (mention or user ID)')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Reason for the kick (minimum 3 words)')
|
||||
.setRequired(true)),
|
||||
async execute(interaction) {
|
||||
// Check if user has kick permissions
|
||||
if (!interaction.member.permissions.has(PermissionsBitField.Flags.KickMembers)) {
|
||||
return await interaction.reply({
|
||||
content: 'You do not have permission to kick members.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
|
||||
// Check if bot has kick permissions
|
||||
if (!interaction.guild.members.me.permissions.has(PermissionsBitField.Flags.KickMembers)) {
|
||||
return await interaction.reply({
|
||||
content: 'I do not have permission to kick members.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
|
||||
const userInput = interaction.options.getString('user');
|
||||
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 kick yourself
|
||||
if (user.id === interaction.user.id) {
|
||||
return await interaction.reply({
|
||||
content: 'You cannot kick yourself.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
|
||||
// Cannot kick the bot
|
||||
if (user.id === interaction.guild.members.me.id) {
|
||||
return await interaction.reply({
|
||||
content: 'I cannot kick 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 kick 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 kick a member with a higher or equal role.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await member.kick(reason);
|
||||
await interaction.reply({
|
||||
content: `Successfully kicked ${user.global_name || user.username} for: ${reason}`,
|
||||
flags: 64
|
||||
});
|
||||
|
||||
// Log the action
|
||||
await logModerationAction(interaction.guildId, 'kick', user.id, user.global_name || user.username, interaction.user.id, interaction.user.global_name || interaction.user.username, reason);
|
||||
} catch (error) {
|
||||
console.error('Error kicking user:', error);
|
||||
await interaction.reply({
|
||||
content: 'Failed to kick the user. Please try again.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
123
discord-bot/commands/setup-adminlogs.js
Normal file
123
discord-bot/commands/setup-adminlogs.js
Normal file
@@ -0,0 +1,123 @@
|
||||
const { SlashCommandBuilder, PermissionsBitField } = require('discord.js');
|
||||
|
||||
module.exports = {
|
||||
name: 'setup-adminlogs',
|
||||
description: 'Configure admin moderation logging settings',
|
||||
enabled: true,
|
||||
builder: new SlashCommandBuilder()
|
||||
.setName('setup-adminlogs')
|
||||
.setDescription('Configure admin moderation logging settings')
|
||||
.addChannelOption(option =>
|
||||
option.setName('channel')
|
||||
.setDescription('Channel to send admin logs to')
|
||||
.setRequired(false))
|
||||
.addBooleanOption(option =>
|
||||
option.setName('enabled')
|
||||
.setDescription('Enable or disable admin logging')
|
||||
.setRequired(false))
|
||||
.addBooleanOption(option =>
|
||||
option.setName('kick_logs')
|
||||
.setDescription('Log kick actions')
|
||||
.setRequired(false))
|
||||
.addBooleanOption(option =>
|
||||
option.setName('ban_logs')
|
||||
.setDescription('Log ban actions')
|
||||
.setRequired(false))
|
||||
.addBooleanOption(option =>
|
||||
option.setName('timeout_logs')
|
||||
.setDescription('Log timeout actions')
|
||||
.setRequired(false)),
|
||||
async execute(interaction) {
|
||||
// Check if user has administrator permissions
|
||||
if (!interaction.member.permissions.has(PermissionsBitField.Flags.Administrator)) {
|
||||
return interaction.reply({
|
||||
content: 'You need Administrator permissions to configure admin logs.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
|
||||
const channel = interaction.options.getChannel('channel');
|
||||
const enabled = interaction.options.getBoolean('enabled');
|
||||
const kickLogs = interaction.options.getBoolean('kick_logs');
|
||||
const banLogs = interaction.options.getBoolean('ban_logs');
|
||||
const timeoutLogs = interaction.options.getBoolean('timeout_logs');
|
||||
|
||||
try {
|
||||
// Get current settings
|
||||
const response = await fetch(`${process.env.BACKEND_BASE || 'http://localhost:3001'}/api/servers/${interaction.guildId}/admin-logs-settings`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch current settings');
|
||||
}
|
||||
const currentSettings = await response.json();
|
||||
|
||||
// Update settings
|
||||
const updatedSettings = { ...currentSettings };
|
||||
|
||||
if (enabled !== null) {
|
||||
updatedSettings.enabled = enabled;
|
||||
}
|
||||
|
||||
if (channel) {
|
||||
// Check if it's a text channel
|
||||
if (channel.type !== 0) { // 0 = GUILD_TEXT
|
||||
return interaction.reply({
|
||||
content: 'Please select a text channel for admin logs.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
updatedSettings.channelId = channel.id;
|
||||
}
|
||||
|
||||
// Update command-specific settings
|
||||
updatedSettings.commands = { ...updatedSettings.commands };
|
||||
if (kickLogs !== null) {
|
||||
updatedSettings.commands.kick = kickLogs;
|
||||
}
|
||||
if (banLogs !== null) {
|
||||
updatedSettings.commands.ban = banLogs;
|
||||
}
|
||||
if (timeoutLogs !== null) {
|
||||
updatedSettings.commands.timeout = timeoutLogs;
|
||||
}
|
||||
|
||||
// Save settings
|
||||
const saveResponse = await fetch(`${process.env.BACKEND_BASE || 'http://localhost:3001'}/api/servers/${interaction.guildId}/admin-logs-settings`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(updatedSettings)
|
||||
});
|
||||
|
||||
if (!saveResponse.ok) {
|
||||
throw new Error('Failed to save settings');
|
||||
}
|
||||
|
||||
const result = await saveResponse.json();
|
||||
|
||||
// Create response message
|
||||
let responseMessage = 'Admin logs settings updated!\n\n';
|
||||
responseMessage += `**Enabled:** ${result.settings.enabled ? 'Yes' : 'No'}\n`;
|
||||
if (result.settings.channelId) {
|
||||
responseMessage += `**Channel:** <#${result.settings.channelId}>\n`;
|
||||
} else {
|
||||
responseMessage += `**Channel:** Not set\n`;
|
||||
}
|
||||
responseMessage += `**Kick Logs:** ${result.settings.commands.kick ? 'Enabled' : 'Disabled'}\n`;
|
||||
responseMessage += `**Ban Logs:** ${result.settings.commands.ban ? 'Enabled' : 'Disabled'}\n`;
|
||||
responseMessage += `**Timeout Logs:** ${result.settings.commands.timeout ? 'Enabled' : 'Disabled'}`;
|
||||
|
||||
await interaction.reply({
|
||||
content: responseMessage,
|
||||
flags: 64
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error configuring admin logs:', error);
|
||||
await interaction.reply({
|
||||
content: 'An error occurred while configuring admin logs. Please try again later.',
|
||||
flags: 64
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -37,4 +37,24 @@ const deployCommands = async (guildId) => {
|
||||
}
|
||||
};
|
||||
|
||||
// Standalone execution
|
||||
if (require.main === module) {
|
||||
const { Client, GatewayIntentBits } = require('discord.js');
|
||||
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
|
||||
|
||||
client.once('ready', async () => {
|
||||
console.log(`Logged in as ${client.user.tag}`);
|
||||
console.log(`Deploying commands to ${client.guilds.cache.size} guilds...`);
|
||||
|
||||
for (const [guildId, guild] of client.guilds.cache) {
|
||||
await deployCommands(guildId);
|
||||
}
|
||||
|
||||
console.log('All commands deployed!');
|
||||
client.destroy();
|
||||
});
|
||||
|
||||
client.login(process.env.DISCORD_BOT_TOKEN);
|
||||
}
|
||||
|
||||
module.exports = deployCommands;
|
||||
|
||||
15
discord-bot/events/guildCreate.js
Normal file
15
discord-bot/events/guildCreate.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const api = require('../api');
|
||||
|
||||
module.exports = {
|
||||
name: 'guildCreate',
|
||||
execute: async (guild, client) => {
|
||||
console.log(`Bot joined guild: ${guild.name} (${guild.id})`);
|
||||
|
||||
try {
|
||||
// Publish SSE event for bot status change
|
||||
await api.publishEvent('*', 'botStatusUpdate', { guildId: guild.id, isBotInServer: true });
|
||||
} catch (error) {
|
||||
console.error('Error publishing bot join event:', error);
|
||||
}
|
||||
},
|
||||
};
|
||||
15
discord-bot/events/guildDelete.js
Normal file
15
discord-bot/events/guildDelete.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const api = require('../api');
|
||||
|
||||
module.exports = {
|
||||
name: 'guildDelete',
|
||||
execute: async (guild, client) => {
|
||||
console.log(`Bot left guild: ${guild.name} (${guild.id})`);
|
||||
|
||||
try {
|
||||
// Publish SSE event for bot status change
|
||||
await api.publishEvent('*', 'botStatusUpdate', { guildId: guild.id, isBotInServer: false });
|
||||
} catch (error) {
|
||||
console.error('Error publishing bot leave event:', error);
|
||||
}
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user