AeThex-Bot-Master/aethex-bot/commands/rolepanel.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

394 lines
12 KiB
JavaScript

const {
SlashCommandBuilder,
EmbedBuilder,
PermissionFlagsBits,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
ChannelType
} = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('rolepanel')
.setDescription('Create and manage role button panels')
.setDefaultMemberPermissions(PermissionFlagsBits.ManageRoles)
.addSubcommand(sub =>
sub.setName('create')
.setDescription('Create a new role panel')
.addChannelOption(option =>
option.setName('channel')
.setDescription('Channel to send the panel to')
.setRequired(true)
.addChannelTypes(ChannelType.GuildText)
)
.addStringOption(option =>
option.setName('title')
.setDescription('Panel title')
.setRequired(true)
.setMaxLength(256)
)
.addStringOption(option =>
option.setName('description')
.setDescription('Panel description')
.setRequired(false)
.setMaxLength(2000)
)
.addStringOption(option =>
option.setName('color')
.setDescription('Embed color')
.setRequired(false)
.addChoices(
{ name: '🟣 Purple', value: '7c3aed' },
{ name: '🟢 Green', value: '22c55e' },
{ name: '🔵 Blue', value: '3b82f6' },
{ name: '🟡 Yellow', value: 'eab308' },
{ name: '🟠 Orange', value: 'f97316' }
)
)
)
.addSubcommand(sub =>
sub.setName('addrole')
.setDescription('Add a role button to a panel')
.addStringOption(option =>
option.setName('message_id')
.setDescription('Message ID of the role panel')
.setRequired(true)
)
.addRoleOption(option =>
option.setName('role')
.setDescription('Role to add')
.setRequired(true)
)
.addStringOption(option =>
option.setName('label')
.setDescription('Button label (optional, uses role name if not set)')
.setRequired(false)
.setMaxLength(80)
)
.addStringOption(option =>
option.setName('emoji')
.setDescription('Button emoji (optional)')
.setRequired(false)
)
.addStringOption(option =>
option.setName('style')
.setDescription('Button style')
.setRequired(false)
.addChoices(
{ name: 'Blue (Primary)', value: 'primary' },
{ name: 'Gray (Secondary)', value: 'secondary' },
{ name: 'Green (Success)', value: 'success' },
{ name: 'Red (Danger)', value: 'danger' }
)
)
)
.addSubcommand(sub =>
sub.setName('removerole')
.setDescription('Remove a role button from a panel')
.addStringOption(option =>
option.setName('message_id')
.setDescription('Message ID of the role panel')
.setRequired(true)
)
.addRoleOption(option =>
option.setName('role')
.setDescription('Role to remove')
.setRequired(true)
)
)
.addSubcommand(sub =>
sub.setName('list')
.setDescription('List all role panels in this server')
),
async execute(interaction, supabase, client) {
const subcommand = interaction.options.getSubcommand();
if (subcommand === 'create') {
await handleCreate(interaction, supabase);
} else if (subcommand === 'addrole') {
await handleAddRole(interaction, supabase, client);
} else if (subcommand === 'removerole') {
await handleRemoveRole(interaction, supabase, client);
} else if (subcommand === 'list') {
await handleList(interaction, supabase);
}
},
};
async function handleCreate(interaction, supabase) {
await interaction.deferReply({ ephemeral: true });
const channel = interaction.options.getChannel('channel');
const title = interaction.options.getString('title');
const description = interaction.options.getString('description') || 'Click a button below to get or remove a role!';
const color = parseInt(interaction.options.getString('color') || '7c3aed', 16);
const embed = new EmbedBuilder()
.setColor(color)
.setTitle(`🎭 ${title}`)
.setDescription(description)
.setFooter({ text: 'Click a button to toggle the role' })
.setTimestamp();
try {
const message = await channel.send({ embeds: [embed] });
if (supabase) {
await supabase.from('role_panels').insert({
message_id: message.id,
channel_id: channel.id,
guild_id: interaction.guildId,
title: title,
description: description,
color: color.toString(16),
roles: [],
created_by: interaction.user.id
});
}
const successEmbed = new EmbedBuilder()
.setColor(0x22c55e)
.setTitle('✅ Role Panel Created')
.setDescription(`Panel created in ${channel}!\n\nUse \`/rolepanel addrole\` with message ID:\n\`${message.id}\``)
.setTimestamp();
await interaction.editReply({ embeds: [successEmbed] });
} catch (error) {
console.error('Role panel create error:', error);
await interaction.editReply({ content: 'Failed to create role panel. Check bot permissions.', ephemeral: true });
}
}
async function handleAddRole(interaction, supabase, client) {
await interaction.deferReply({ ephemeral: true });
const messageId = interaction.options.getString('message_id');
const role = interaction.options.getRole('role');
const label = interaction.options.getString('label') || role.name;
const emoji = interaction.options.getString('emoji');
const styleStr = interaction.options.getString('style') || 'primary';
const styleMap = {
'primary': ButtonStyle.Primary,
'secondary': ButtonStyle.Secondary,
'success': ButtonStyle.Success,
'danger': ButtonStyle.Danger
};
const style = styleMap[styleStr];
try {
let channel = null;
let message = null;
if (supabase) {
const { data: panel } = await supabase
.from('role_panels')
.select('channel_id')
.eq('message_id', messageId)
.eq('guild_id', interaction.guildId)
.single();
if (panel?.channel_id) {
channel = await interaction.guild.channels.fetch(panel.channel_id).catch(() => null);
}
}
if (!channel) {
channel = interaction.channel;
}
message = await channel.messages.fetch(messageId).catch(() => null);
if (!message) {
return interaction.editReply({ content: 'Could not find that message. Make sure the message ID is correct and the panel exists.' });
}
if (message.author.id !== client.user.id) {
return interaction.editReply({ content: 'That message was not sent by me. I can only edit my own messages.' });
}
const buttonData = {
role_id: role.id,
role_name: role.name,
label: label,
emoji: emoji,
style: styleStr
};
const existingRows = message.components.map(row => ActionRowBuilder.from(row));
const button = new ButtonBuilder()
.setCustomId(`role_${role.id}`)
.setLabel(label)
.setStyle(style);
if (emoji) {
button.setEmoji(emoji);
}
let added = false;
for (const row of existingRows) {
if (row.components.length < 5) {
row.addComponents(button);
added = true;
break;
}
}
if (!added) {
if (existingRows.length >= 5) {
return interaction.editReply({ content: 'Maximum buttons reached (25). Remove some roles first.' });
}
const newRow = new ActionRowBuilder().addComponents(button);
existingRows.push(newRow);
}
await message.edit({ components: existingRows });
if (supabase) {
const { data: panel } = await supabase
.from('role_panels')
.select('roles')
.eq('message_id', messageId)
.single();
const roles = panel?.roles || [];
roles.push(buttonData);
await supabase
.from('role_panels')
.update({ roles: roles })
.eq('message_id', messageId);
}
const successEmbed = new EmbedBuilder()
.setColor(0x22c55e)
.setTitle('✅ Role Added')
.setDescription(`Added ${role} to the panel!`)
.setTimestamp();
await interaction.editReply({ embeds: [successEmbed] });
} catch (error) {
console.error('Add role error:', error);
await interaction.editReply({ content: `Failed to add role: ${error.message}` });
}
}
async function handleRemoveRole(interaction, supabase, client) {
await interaction.deferReply({ ephemeral: true });
const messageId = interaction.options.getString('message_id');
const role = interaction.options.getRole('role');
try {
let channel = null;
let message = null;
if (supabase) {
const { data: panel } = await supabase
.from('role_panels')
.select('channel_id')
.eq('message_id', messageId)
.eq('guild_id', interaction.guildId)
.single();
if (panel?.channel_id) {
channel = await interaction.guild.channels.fetch(panel.channel_id).catch(() => null);
}
}
if (!channel) {
channel = interaction.channel;
}
message = await channel.messages.fetch(messageId).catch(() => null);
if (!message) {
return interaction.editReply({ content: 'Could not find that message. Make sure the message ID is correct and the panel exists.' });
}
const existingRows = message.components.map(row => ActionRowBuilder.from(row));
for (const row of existingRows) {
const buttonIndex = row.components.findIndex(btn => btn.data.custom_id === `role_${role.id}`);
if (buttonIndex !== -1) {
row.components.splice(buttonIndex, 1);
}
}
const filteredRows = existingRows.filter(row => row.components.length > 0);
await message.edit({ components: filteredRows });
if (supabase) {
const { data: panel } = await supabase
.from('role_panels')
.select('roles')
.eq('message_id', messageId)
.single();
const roles = (panel?.roles || []).filter(r => r.role_id !== role.id);
await supabase
.from('role_panels')
.update({ roles: roles })
.eq('message_id', messageId);
}
const successEmbed = new EmbedBuilder()
.setColor(0x22c55e)
.setTitle('✅ Role Removed')
.setDescription(`Removed ${role} from the panel!`)
.setTimestamp();
await interaction.editReply({ embeds: [successEmbed] });
} catch (error) {
console.error('Remove role error:', error);
await interaction.editReply({ content: `Failed to remove role: ${error.message}` });
}
}
async function handleList(interaction, supabase) {
await interaction.deferReply({ ephemeral: true });
if (!supabase) {
return interaction.editReply({ content: 'This feature requires database connection.' });
}
try {
const { data: panels, error } = await supabase
.from('role_panels')
.select('*')
.eq('guild_id', interaction.guildId)
.order('created_at', { ascending: false });
if (error) throw error;
if (!panels || panels.length === 0) {
return interaction.editReply({ content: 'No role panels found in this server.' });
}
const embed = new EmbedBuilder()
.setColor(0x7c3aed)
.setTitle('🎭 Role Panels')
.setDescription(panels.map(p =>
`**${p.title}**\n` +
`Channel: <#${p.channel_id}>\n` +
`Message ID: \`${p.message_id}\`\n` +
`Roles: ${p.roles?.length || 0}`
).join('\n\n'))
.setFooter({ text: `${panels.length} panel(s)` })
.setTimestamp();
await interaction.editReply({ embeds: [embed] });
} catch (error) {
console.error('List panels error:', error);
await interaction.editReply({ content: 'Failed to fetch panels.' });
}
}