const { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits, AttachmentBuilder } = require('discord.js'); const { generateWelcomeCard } = require('../utils/welcomeCard'); module.exports = { data: new SlashCommandBuilder() .setName('welcome-card') .setDescription('Configure custom welcome image cards') .setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild) .addSubcommand(sub => sub.setName('enable').setDescription('Enable welcome image cards')) .addSubcommand(sub => sub.setName('disable').setDescription('Disable welcome image cards (use text only)')) .addSubcommand(sub => sub.setName('preview').setDescription('Preview the welcome card for yourself')) .addSubcommand(sub => sub.setName('settings').setDescription('View current welcome card settings')) .addSubcommand(sub => sub.setName('title').setDescription('Set the welcome title text') .addStringOption(opt => opt.setName('text').setDescription('Title text (e.g., WELCOME, HELLO, etc.)').setRequired(true).setMaxLength(20))) .addSubcommand(sub => sub.setName('colors').setDescription('Customize card colors') .addStringOption(opt => opt.setName('background').setDescription('Background color (hex, e.g., #1a1a2e)')) .addStringOption(opt => opt.setName('accent').setDescription('Accent color (hex, e.g., #7c3aed)')) .addStringOption(opt => opt.setName('text').setDescription('Text color (hex, e.g., #ffffff)')) .addStringOption(opt => opt.setName('subtext').setDescription('Subtext color (hex, e.g., #a0a0a0)'))), async execute(interaction, supabase) { if (!supabase) { return interaction.reply({ content: 'Database not available.', ephemeral: true }); } const subcommand = interaction.options.getSubcommand(); const { data: config } = await supabase .from('server_config') .select('welcome_card_enabled, welcome_card_title, welcome_card_bg_color, welcome_card_accent_color, welcome_card_text_color, welcome_card_subtext_color') .eq('guild_id', interaction.guildId) .maybeSingle(); const safeConfig = config || {}; if (subcommand === 'enable') { const { error } = await supabase .from('server_config') .upsert({ guild_id: interaction.guildId, welcome_card_enabled: true, updated_at: new Date().toISOString() }, { onConflict: 'guild_id' }); if (error) { console.error('Welcome card enable error:', error); return interaction.reply({ content: 'Failed to enable welcome cards.', ephemeral: true }); } const embed = new EmbedBuilder() .setColor(0x22c55e) .setTitle('Welcome Cards Enabled') .setDescription('New members will now receive custom welcome image cards!') .setFooter({ text: 'Use /welcome-card preview to see how it looks' }) .setTimestamp(); await interaction.reply({ embeds: [embed] }); } if (subcommand === 'disable') { const { error } = await supabase .from('server_config') .upsert({ guild_id: interaction.guildId, welcome_card_enabled: false, updated_at: new Date().toISOString() }, { onConflict: 'guild_id' }); if (error) { return interaction.reply({ content: 'Failed to disable welcome cards.', ephemeral: true }); } const embed = new EmbedBuilder() .setColor(0xef4444) .setTitle('Welcome Cards Disabled') .setDescription('Welcome messages will now be text-only embeds.') .setTimestamp(); await interaction.reply({ embeds: [embed] }); } if (subcommand === 'preview') { await interaction.deferReply(); try { const cardConfig = { title: safeConfig.welcome_card_title || 'WELCOME', background_color: safeConfig.welcome_card_bg_color || '#1a1a2e', accent_color: safeConfig.welcome_card_accent_color || '#7c3aed', text_color: safeConfig.welcome_card_text_color || '#ffffff', subtext_color: safeConfig.welcome_card_subtext_color || '#a0a0a0' }; const buffer = await generateWelcomeCard(interaction.member, cardConfig); const attachment = new AttachmentBuilder(buffer, { name: 'welcome-preview.png' }); const embed = new EmbedBuilder() .setColor(0x7c3aed) .setTitle('Welcome Card Preview') .setDescription('This is how welcome cards will look for new members.') .setImage('attachment://welcome-preview.png') .setTimestamp(); await interaction.editReply({ embeds: [embed], files: [attachment] }); } catch (err) { console.error('Welcome card preview error:', err); await interaction.editReply({ content: 'Failed to generate preview. Please try again.' }); } } if (subcommand === 'settings') { const embed = new EmbedBuilder() .setColor(0x7c3aed) .setTitle('Welcome Card Settings') .addFields( { name: 'Enabled', value: safeConfig.welcome_card_enabled ? '✅ Yes' : '❌ No', inline: true }, { name: 'Title', value: safeConfig.welcome_card_title || 'WELCOME', inline: true }, { name: '\u200B', value: '\u200B', inline: true }, { name: 'Background Color', value: safeConfig.welcome_card_bg_color || '#1a1a2e', inline: true }, { name: 'Accent Color', value: safeConfig.welcome_card_accent_color || '#7c3aed', inline: true }, { name: 'Text Color', value: safeConfig.welcome_card_text_color || '#ffffff', inline: true }, { name: 'Subtext Color', value: safeConfig.welcome_card_subtext_color || '#a0a0a0', inline: true } ) .setFooter({ text: 'Use /welcome-card commands to customize' }) .setTimestamp(); await interaction.reply({ embeds: [embed] }); } if (subcommand === 'title') { const titleText = interaction.options.getString('text').toUpperCase(); const { error } = await supabase .from('server_config') .upsert({ guild_id: interaction.guildId, welcome_card_title: titleText, updated_at: new Date().toISOString() }, { onConflict: 'guild_id' }); if (error) { return interaction.reply({ content: 'Failed to update title.', ephemeral: true }); } const embed = new EmbedBuilder() .setColor(0x22c55e) .setTitle('Title Updated') .setDescription(`Welcome card title set to: **${titleText}**`) .setTimestamp(); await interaction.reply({ embeds: [embed] }); } if (subcommand === 'colors') { const bgColor = interaction.options.getString('background'); const accentColor = interaction.options.getString('accent'); const textColor = interaction.options.getString('text'); const subtextColor = interaction.options.getString('subtext'); if (!bgColor && !accentColor && !textColor && !subtextColor) { return interaction.reply({ content: 'Please provide at least one color to update.', ephemeral: true }); } const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/; const updates = { updated_at: new Date().toISOString() }; const changes = []; if (bgColor) { if (!hexRegex.test(bgColor)) { return interaction.reply({ content: 'Invalid background color format. Use hex (e.g., #1a1a2e)', ephemeral: true }); } updates.welcome_card_bg_color = bgColor; changes.push(`Background: ${bgColor}`); } if (accentColor) { if (!hexRegex.test(accentColor)) { return interaction.reply({ content: 'Invalid accent color format. Use hex (e.g., #7c3aed)', ephemeral: true }); } updates.welcome_card_accent_color = accentColor; changes.push(`Accent: ${accentColor}`); } if (textColor) { if (!hexRegex.test(textColor)) { return interaction.reply({ content: 'Invalid text color format. Use hex (e.g., #ffffff)', ephemeral: true }); } updates.welcome_card_text_color = textColor; changes.push(`Text: ${textColor}`); } if (subtextColor) { if (!hexRegex.test(subtextColor)) { return interaction.reply({ content: 'Invalid subtext color format. Use hex (e.g., #a0a0a0)', ephemeral: true }); } updates.welcome_card_subtext_color = subtextColor; changes.push(`Subtext: ${subtextColor}`); } const { error } = await supabase .from('server_config') .upsert({ guild_id: interaction.guildId, ...updates }, { onConflict: 'guild_id' }); if (error) { return interaction.reply({ content: 'Failed to update colors.', ephemeral: true }); } const embed = new EmbedBuilder() .setColor(parseInt((accentColor || safeConfig.welcome_card_accent_color || '#7c3aed').replace('#', ''), 16)) .setTitle('Colors Updated') .setDescription(`Updated:\n${changes.join('\n')}`) .setFooter({ text: 'Use /welcome-card preview to see changes' }) .setTimestamp(); await interaction.reply({ embeds: [embed] }); } }, };