AeThex-Bot-Master/aethex-bot/commands/automod.js
sirpiglr 6f5c37959f Add new commands and improve existing ones for better user experience
Introduces new commands like `/automod`, `/giveaway`, `/rolepanel`, and `/schedule`. Enhances existing commands such as `/announce`, `/help`, `/leaderboard`, `/profile`, and `/serverinfo` with new features and improved embed designs. Updates welcome and goodbye listeners with rich embeds. Fixes a critical issue in the `/rolepanel` command regarding channel fetching. Adds interaction handling for role buttons and giveaway entries.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: aed2e46d-25bb-4b73-81a1-bb9e8437c261
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: eefee140-1301-4b6f-9439-2b0b883aa40a
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/aed2e46d-25bb-4b73-81a1-bb9e8437c261/qAaysIh
Replit-Helium-Checkpoint-Created: true
2025-12-08 07:24:49 +00:00

424 lines
13 KiB
JavaScript

const {
SlashCommandBuilder,
EmbedBuilder,
PermissionFlagsBits
} = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('automod')
.setDescription('Configure auto-moderation settings')
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild)
.addSubcommand(sub =>
sub.setName('status')
.setDescription('View current auto-mod settings')
)
.addSubcommand(sub =>
sub.setName('links')
.setDescription('Toggle link filtering')
.addBooleanOption(option =>
option.setName('enabled')
.setDescription('Enable or disable link filtering')
.setRequired(true)
)
.addStringOption(option =>
option.setName('action')
.setDescription('Action to take')
.setRequired(false)
.addChoices(
{ name: 'Delete only', value: 'delete' },
{ name: 'Delete + Warn', value: 'warn' },
{ name: 'Delete + Timeout (5min)', value: 'timeout' }
)
)
)
.addSubcommand(sub =>
sub.setName('spam')
.setDescription('Toggle spam detection')
.addBooleanOption(option =>
option.setName('enabled')
.setDescription('Enable or disable spam detection')
.setRequired(true)
)
.addIntegerOption(option =>
option.setName('threshold')
.setDescription('Messages per 5 seconds to trigger')
.setRequired(false)
.setMinValue(3)
.setMaxValue(20)
)
)
.addSubcommand(sub =>
sub.setName('badwords')
.setDescription('Manage banned words')
.addStringOption(option =>
option.setName('action')
.setDescription('Add or remove words')
.setRequired(true)
.addChoices(
{ name: 'Add word', value: 'add' },
{ name: 'Remove word', value: 'remove' },
{ name: 'List words', value: 'list' },
{ name: 'Clear all', value: 'clear' }
)
)
.addStringOption(option =>
option.setName('word')
.setDescription('Word to add/remove')
.setRequired(false)
)
)
.addSubcommand(sub =>
sub.setName('invites')
.setDescription('Toggle Discord invite filtering')
.addBooleanOption(option =>
option.setName('enabled')
.setDescription('Enable or disable invite filtering')
.setRequired(true)
)
)
.addSubcommand(sub =>
sub.setName('mentions')
.setDescription('Toggle mass mention detection')
.addBooleanOption(option =>
option.setName('enabled')
.setDescription('Enable or disable mention spam detection')
.setRequired(true)
)
.addIntegerOption(option =>
option.setName('limit')
.setDescription('Maximum mentions per message')
.setRequired(false)
.setMinValue(3)
.setMaxValue(50)
)
)
.addSubcommand(sub =>
sub.setName('exempt')
.setDescription('Exempt a role from auto-mod')
.addRoleOption(option =>
option.setName('role')
.setDescription('Role to exempt')
.setRequired(true)
)
.addBooleanOption(option =>
option.setName('exempt')
.setDescription('Exempt or un-exempt')
.setRequired(true)
)
),
async execute(interaction, supabase, client) {
const subcommand = interaction.options.getSubcommand();
switch (subcommand) {
case 'status':
await handleStatus(interaction, supabase);
break;
case 'links':
await handleLinks(interaction, supabase, client);
break;
case 'spam':
await handleSpam(interaction, supabase, client);
break;
case 'badwords':
await handleBadwords(interaction, supabase, client);
break;
case 'invites':
await handleInvites(interaction, supabase, client);
break;
case 'mentions':
await handleMentions(interaction, supabase, client);
break;
case 'exempt':
await handleExempt(interaction, supabase, client);
break;
}
},
};
async function getAutomodConfig(guildId, supabase) {
if (!supabase) return getDefaultConfig();
try {
const { data, error } = await supabase
.from('automod_config')
.select('*')
.eq('guild_id', guildId)
.single();
if (error || !data) return getDefaultConfig();
return data;
} catch {
return getDefaultConfig();
}
}
function getDefaultConfig() {
return {
links_enabled: false,
links_action: 'delete',
spam_enabled: false,
spam_threshold: 5,
badwords: [],
invites_enabled: false,
mentions_enabled: false,
mentions_limit: 5,
exempt_roles: []
};
}
async function saveAutomodConfig(guildId, config, supabase) {
if (!supabase) return;
try {
await supabase.from('automod_config').upsert({
guild_id: guildId,
...config,
updated_at: new Date().toISOString()
});
} catch (error) {
console.error('Save automod config error:', error);
}
}
async function handleStatus(interaction, supabase) {
await interaction.deferReply({ ephemeral: true });
const config = await getAutomodConfig(interaction.guildId, supabase);
const embed = new EmbedBuilder()
.setColor(0x7c3aed)
.setTitle('🛡️ Auto-Moderation Settings')
.addFields(
{
name: '🔗 Link Filter',
value: config.links_enabled ? `✅ Enabled (${config.links_action})` : '❌ Disabled',
inline: true
},
{
name: '📨 Spam Detection',
value: config.spam_enabled ? `✅ Enabled (${config.spam_threshold} msg/5s)` : '❌ Disabled',
inline: true
},
{
name: '🚫 Bad Words',
value: config.badwords?.length > 0 ? `${config.badwords.length} words` : '❌ None set',
inline: true
},
{
name: '📩 Invite Filter',
value: config.invites_enabled ? '✅ Enabled' : '❌ Disabled',
inline: true
},
{
name: '📢 Mass Mentions',
value: config.mentions_enabled ? `✅ Enabled (max ${config.mentions_limit})` : '❌ Disabled',
inline: true
},
{
name: '🎭 Exempt Roles',
value: config.exempt_roles?.length > 0
? config.exempt_roles.map(r => `<@&${r}>`).join(', ')
: 'None',
inline: true
}
)
.setFooter({ text: 'Use /automod [setting] to configure' })
.setTimestamp();
await interaction.editReply({ embeds: [embed] });
}
async function handleLinks(interaction, supabase, client) {
await interaction.deferReply({ ephemeral: true });
const enabled = interaction.options.getBoolean('enabled');
const action = interaction.options.getString('action') || 'delete';
const config = await getAutomodConfig(interaction.guildId, supabase);
config.links_enabled = enabled;
config.links_action = action;
await saveAutomodConfig(interaction.guildId, config, supabase);
client.automodConfig = client.automodConfig || new Map();
client.automodConfig.set(interaction.guildId, config);
const embed = new EmbedBuilder()
.setColor(enabled ? 0x22c55e : 0xef4444)
.setTitle(enabled ? '✅ Link Filter Enabled' : '❌ Link Filter Disabled')
.setDescription(enabled ? `Links will be ${action === 'delete' ? 'deleted' : action === 'warn' ? 'deleted and user warned' : 'deleted and user timed out'}` : 'Links will no longer be filtered')
.setTimestamp();
await interaction.editReply({ embeds: [embed] });
}
async function handleSpam(interaction, supabase, client) {
await interaction.deferReply({ ephemeral: true });
const enabled = interaction.options.getBoolean('enabled');
const threshold = interaction.options.getInteger('threshold') || 5;
const config = await getAutomodConfig(interaction.guildId, supabase);
config.spam_enabled = enabled;
config.spam_threshold = threshold;
await saveAutomodConfig(interaction.guildId, config, supabase);
client.automodConfig = client.automodConfig || new Map();
client.automodConfig.set(interaction.guildId, config);
const embed = new EmbedBuilder()
.setColor(enabled ? 0x22c55e : 0xef4444)
.setTitle(enabled ? '✅ Spam Detection Enabled' : '❌ Spam Detection Disabled')
.setDescription(enabled ? `Spam threshold set to ${threshold} messages per 5 seconds` : 'Spam will no longer be detected')
.setTimestamp();
await interaction.editReply({ embeds: [embed] });
}
async function handleBadwords(interaction, supabase, client) {
await interaction.deferReply({ ephemeral: true });
const action = interaction.options.getString('action');
const word = interaction.options.getString('word')?.toLowerCase();
const config = await getAutomodConfig(interaction.guildId, supabase);
config.badwords = config.badwords || [];
let embed;
switch (action) {
case 'add':
if (!word) {
return interaction.editReply({ content: 'Please provide a word to add.' });
}
if (!config.badwords.includes(word)) {
config.badwords.push(word);
}
embed = new EmbedBuilder()
.setColor(0x22c55e)
.setTitle('✅ Word Added')
.setDescription(`Added "${word}" to the filter list.`)
.setTimestamp();
break;
case 'remove':
if (!word) {
return interaction.editReply({ content: 'Please provide a word to remove.' });
}
config.badwords = config.badwords.filter(w => w !== word);
embed = new EmbedBuilder()
.setColor(0x22c55e)
.setTitle('✅ Word Removed')
.setDescription(`Removed "${word}" from the filter list.`)
.setTimestamp();
break;
case 'list':
embed = new EmbedBuilder()
.setColor(0x7c3aed)
.setTitle('🚫 Banned Words')
.setDescription(config.badwords.length > 0
? config.badwords.map(w => `\`${w}\``).join(', ')
: 'No words in the filter list.')
.setTimestamp();
break;
case 'clear':
config.badwords = [];
embed = new EmbedBuilder()
.setColor(0x22c55e)
.setTitle('✅ List Cleared')
.setDescription('All banned words have been removed.')
.setTimestamp();
break;
}
await saveAutomodConfig(interaction.guildId, config, supabase);
client.automodConfig = client.automodConfig || new Map();
client.automodConfig.set(interaction.guildId, config);
await interaction.editReply({ embeds: [embed] });
}
async function handleInvites(interaction, supabase, client) {
await interaction.deferReply({ ephemeral: true });
const enabled = interaction.options.getBoolean('enabled');
const config = await getAutomodConfig(interaction.guildId, supabase);
config.invites_enabled = enabled;
await saveAutomodConfig(interaction.guildId, config, supabase);
client.automodConfig = client.automodConfig || new Map();
client.automodConfig.set(interaction.guildId, config);
const embed = new EmbedBuilder()
.setColor(enabled ? 0x22c55e : 0xef4444)
.setTitle(enabled ? '✅ Invite Filter Enabled' : '❌ Invite Filter Disabled')
.setDescription(enabled ? 'Discord invites will be automatically deleted' : 'Discord invites will no longer be filtered')
.setTimestamp();
await interaction.editReply({ embeds: [embed] });
}
async function handleMentions(interaction, supabase, client) {
await interaction.deferReply({ ephemeral: true });
const enabled = interaction.options.getBoolean('enabled');
const limit = interaction.options.getInteger('limit') || 5;
const config = await getAutomodConfig(interaction.guildId, supabase);
config.mentions_enabled = enabled;
config.mentions_limit = limit;
await saveAutomodConfig(interaction.guildId, config, supabase);
client.automodConfig = client.automodConfig || new Map();
client.automodConfig.set(interaction.guildId, config);
const embed = new EmbedBuilder()
.setColor(enabled ? 0x22c55e : 0xef4444)
.setTitle(enabled ? '✅ Mass Mention Detection Enabled' : '❌ Mass Mention Detection Disabled')
.setDescription(enabled ? `Messages with more than ${limit} mentions will be deleted` : 'Mass mentions will no longer be filtered')
.setTimestamp();
await interaction.editReply({ embeds: [embed] });
}
async function handleExempt(interaction, supabase, client) {
await interaction.deferReply({ ephemeral: true });
const role = interaction.options.getRole('role');
const exempt = interaction.options.getBoolean('exempt');
const config = await getAutomodConfig(interaction.guildId, supabase);
config.exempt_roles = config.exempt_roles || [];
if (exempt) {
if (!config.exempt_roles.includes(role.id)) {
config.exempt_roles.push(role.id);
}
} else {
config.exempt_roles = config.exempt_roles.filter(r => r !== role.id);
}
await saveAutomodConfig(interaction.guildId, config, supabase);
client.automodConfig = client.automodConfig || new Map();
client.automodConfig.set(interaction.guildId, config);
const embed = new EmbedBuilder()
.setColor(0x22c55e)
.setTitle(exempt ? '✅ Role Exempted' : '✅ Role Un-exempted')
.setDescription(exempt
? `${role} is now exempt from auto-moderation`
: `${role} is no longer exempt from auto-moderation`)
.setTimestamp();
await interaction.editReply({ embeds: [embed] });
}