const { SlashCommandBuilder, EmbedBuilder, MessageFlags } = require('discord.js') const { mClient } = require('../../../index') const { configDotenv } = require('dotenv') configDotenv() function isValidDate(day, month) { // Define the number of days in each month const daysInMonth = { 1: 31, // January 2: 28, // February (fuck leap years, me an' the homies hate that) 3: 31, // March 4: 30, // April 5: 31, // May 6: 30, // June 7: 31, // July 8: 31, // August 9: 30, // September 10: 31, // October 11: 30, // November 12: 31 // December }; // Check if month is valid if (month < 1 || month > 12) { return false; } // Check if day is valid for the given month if (day < 1 || day > daysInMonth[month]) { return false; } return true; } function getNextBirthdayTimestamp(day, month) { const now = new Date(); now.setHours(0, 0, 0, 0); const currentYear = now.getFullYear(); let nextBirthday = new Date(currentYear, month - 1, day); // If birthday already passed this year → next year if (nextBirthday < now) { nextBirthday.setFullYear(currentYear + 1); } return Math.floor(nextBirthday.getTime() / 1000); // Unix timestamp } async function birthdaySet(interaction) { let target = await interaction.options.getUser('user') let day = await interaction.options.getNumber('day') let month = await interaction.options.getNumber('month') if (!isValidDate(day, month)) { return interaction.reply({ content: "Invalid Date", flags: MessageFlags.Ephemeral }) } const db = mClient.db(process.env.M_DB) const bdayColl = db.collection('items_birthdays') const found = await bdayColl.findOne({ userID: target.id }) if (found) { return interaction.reply({ content: "Already in Database", flags: MessageFlags.Ephemeral }) } const data = { guildID: interaction.guild.id, userID: target.id, day: day, month: month } const res = await bdayColl.insertOne(data) if (res.acknowledged) { return interaction.reply({ content: "Birthday added successfully!" }) } else { return interaction.reply({ content: "There was an issue!" }) } } async function birthdayDelete(interaction) { var target = await interaction.options.getUser('user') const guild = await interaction.client.guilds.cache.get(interaction.guild.id) if (!target) { target = await guild.members.cache.get(await interaction.options.getString('id')) } if (!target) { return interaction.reply({ content: "Invalid or No User specified!" }) } const db = mClient.db(process.env.M_DB) const bdayColl = db.collection('items_birthdays') const found = await bdayColl.findOne({ userID: target.id }) if (!found) { return interaction.reply({ content: "Not yet in Database", flags: MessageFlags.Ephemeral }) } const res = await bdayColl.deleteOne({ userID: target.id }) if (res.acknowledged) { return interaction.reply({ content: "Birthday removed successfully!" }) } else { return interaction.reply({ content: "There was an issue!" }) } } async function birthdayGet(interaction) { const target = await interaction.options.getUser('user'); const db = mClient.db(process.env.M_DB); const bdayColl = db.collection('items_birthdays'); const found = await bdayColl.findOne({ userID: target.id }); if (!found) { return interaction.reply({ content: "Date not in Database!", flags: MessageFlags.Ephemeral }); } const now = new Date(); const isToday = now.getDate() === found.day && now.getMonth() === (found.month - 1); let description; if (isToday) { description = `IS TODAY! 🥳🎉`; } else { const unix = getNextBirthdayTimestamp(found.day, found.month); description = `is on the \n`; } const embed = new EmbedBuilder() .setThumbnail(target.displayAvatarURL()) .setTitle(`${target.globalName ?? target.username}'s Birthday...`) .setDescription(description); await interaction.reply({ embeds: [embed] }); } module.exports = { data: new SlashCommandBuilder() .setName('birthday') .setDescription('manage birthdays') .addSubcommand(s => s .setName('set') .setDescription('set date to birthday') .addUserOption((option) => option .setName('user') .setDescription('user') .setRequired(true)) .addNumberOption((option) => option .setName('day') .setDescription('day') .setMinValue(1) .setMaxValue(31) .setRequired(true)) .addNumberOption((option) => option .setName('month') .setDescription('month') .setMinValue(1) .setMaxValue(12) .setRequired(true)) ) .addSubcommand(s => s .setName('delete') .setDescription('deletes a birthday') .addUserOption((option) => option.setName('user').setDescription('user')) .addStringOption((option) => option.setName('id').setDescription('ID'))) .addSubcommand(s => s .setName('get') .setDescription('gets a birthday') .addUserOption((option) => option.setName('user').setDescription('user').setRequired(true))), async execute(interaction) { switch (interaction.options._subcommand) { case 'set': if (!interaction.member.permissions.has("ADMINISTRATOR")) { return await interaction.reply({ content: "Unprivileged Access!", flags: MessageFlags.Ephemeral }) } birthdaySet(interaction) break; case 'delete': if (!interaction.member.permissions.has("ADMINISTRATOR")) { return await interaction.reply({ content: "Unprivileged Access!", flags: MessageFlags.Ephemeral }) } birthdayDelete(interaction) break; case 'get': birthdayGet(interaction) break; default: break; } } }