const { SlashCommandBuilder, EmbedBuilder } = require('discord.js'); const { getServerMode, getEmbedColor, EMBED_COLORS } = require('../utils/modeHelper'); module.exports = { data: new SlashCommandBuilder() .setName('birthday') .setDescription('Set or view birthdays') .addSubcommand(subcommand => subcommand .setName('set') .setDescription('Set your birthday') .addIntegerOption(option => option.setName('month') .setDescription('Birth month (1-12)') .setRequired(true) .setMinValue(1) .setMaxValue(12) ) .addIntegerOption(option => option.setName('day') .setDescription('Birth day (1-31)') .setRequired(true) .setMinValue(1) .setMaxValue(31) ) ) .addSubcommand(subcommand => subcommand .setName('view') .setDescription('View someone\'s birthday') .addUserOption(option => option.setName('user') .setDescription('The user to check') .setRequired(false) ) ) .addSubcommand(subcommand => subcommand .setName('upcoming') .setDescription('View upcoming birthdays in this server') ) .addSubcommand(subcommand => subcommand .setName('remove') .setDescription('Remove your birthday') ), async execute(interaction, supabase, client) { const subcommand = interaction.options.getSubcommand(); const mode = await getServerMode(supabase, interaction.guildId); const guildId = interaction.guildId; const userId = interaction.user.id; if (subcommand === 'set') { const month = interaction.options.getInteger('month'); const day = interaction.options.getInteger('day'); const daysInMonth = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; if (day > daysInMonth[month - 1]) { return interaction.reply({ content: `Invalid day for month ${month}. Maximum is ${daysInMonth[month - 1]}.`, ephemeral: true }); } if (supabase) { try { await supabase.from('birthdays').upsert({ guild_id: guildId, user_id: userId, username: interaction.user.username, month: month, day: day, updated_at: new Date().toISOString() }, { onConflict: 'guild_id,user_id' }); } catch (e) {} } const monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; const embed = new EmbedBuilder() .setColor(EMBED_COLORS.success) .setTitle('🎂 Birthday Set!') .setDescription(`Your birthday is now set to **${monthNames[month - 1]} ${day}**!`) .setTimestamp(); await interaction.reply({ embeds: [embed], ephemeral: true }); } else if (subcommand === 'view') { const targetUser = interaction.options.getUser('user') || interaction.user; if (!supabase) { return interaction.reply({ content: 'Birthday system unavailable.', ephemeral: true }); } const { data } = await supabase .from('birthdays') .select('month, day') .eq('guild_id', guildId) .eq('user_id', targetUser.id) .maybeSingle(); if (!data) { return interaction.reply({ content: targetUser.id === userId ? 'You haven\'t set your birthday yet! Use `/birthday set`.' : `${targetUser.username} hasn't set their birthday.`, ephemeral: true }); } const monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; const embed = new EmbedBuilder() .setColor(getEmbedColor(mode)) .setTitle('🎂 Birthday') .setDescription(`**${targetUser.username}**'s birthday is on **${monthNames[data.month - 1]} ${data.day}**!`) .setThumbnail(targetUser.displayAvatarURL({ size: 128 })) .setTimestamp(); await interaction.reply({ embeds: [embed] }); } else if (subcommand === 'upcoming') { if (!supabase) { return interaction.reply({ content: 'Birthday system unavailable.', ephemeral: true }); } const { data } = await supabase .from('birthdays') .select('user_id, username, month, day') .eq('guild_id', guildId); if (!data || data.length === 0) { return interaction.reply({ content: 'No birthdays set in this server yet!', ephemeral: true }); } const now = new Date(); const currentMonth = now.getMonth() + 1; const currentDay = now.getDate(); const sorted = data.map(b => { let daysUntil = (b.month - currentMonth) * 30 + (b.day - currentDay); if (daysUntil < 0) daysUntil += 365; return { ...b, daysUntil }; }).sort((a, b) => a.daysUntil - b.daysUntil).slice(0, 10); const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const list = sorted.map((b, i) => { const emoji = b.daysUntil === 0 ? '🎉' : '🎂'; const status = b.daysUntil === 0 ? '**TODAY!**' : `in ${b.daysUntil} days`; return `${i + 1}. ${emoji} **${b.username}** - ${monthNames[b.month - 1]} ${b.day} (${status})`; }).join('\n'); const embed = new EmbedBuilder() .setColor(getEmbedColor(mode)) .setTitle('🎂 Upcoming Birthdays') .setDescription(list || 'No upcoming birthdays.') .setTimestamp(); await interaction.reply({ embeds: [embed] }); } else if (subcommand === 'remove') { if (supabase) { await supabase .from('birthdays') .delete() .eq('guild_id', guildId) .eq('user_id', userId); } const embed = new EmbedBuilder() .setColor(EMBED_COLORS.success) .setTitle('🗑️ Birthday Removed') .setDescription('Your birthday has been removed from this server.') .setTimestamp(); await interaction.reply({ embeds: [embed], ephemeral: true }); } }, };