AeThex-Bot-Master/aethex-bot/commands/birthday.js
sirpiglr c2a34f398e Add server mode configuration and dynamic status updates
Introduces a new server mode configuration system (Federation/Standalone) with associated command changes, dynamic status rotation for the bot, and adds new commands and features.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: aed2e46d-25bb-4b73-81a1-bb9e8437c261
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: b08e6ba5-7498-4b9f-b1c9-7dc11b362ddd
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/aed2e46d-25bb-4b73-81a1-bb9e8437c261/R9PkDi8
Replit-Helium-Checkpoint-Created: true
2025-12-09 23:26:33 +00:00

187 lines
6.2 KiB
JavaScript

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 });
}
},
};