diff --git a/config/JSON/birthday.json b/config/JSON/birthday.json index f449afa..e7b7180 100644 --- a/config/JSON/birthday.json +++ b/config/JSON/birthday.json @@ -1,18 +1,9 @@ { - "month_mapping": { - "jan": "January", - "feb": "February", - "mar": "March", - "apr": "April", - "may": "May", - "jun": "June", - "jul": "July", - "aug": "August", - "sep": "September", - "oct": "October", - "nov": "November", - "dec": "December" - }, + "months": [ + "January", "February", "March", "April", + "May", "June", "July", "August", + "September", "October", "November", "December" + ], "birthday_messages": [ "🎂 Happy Birthday, **{0}**! 🎉 Wishing you a day filled with joy and laughter.", "🎈 It's party time! Happy Birthday, **{0}**! 🎉", diff --git a/modules/birthdays/__init__.py b/modules/birthdays/__init__.py index e026a72..2536a7e 100644 --- a/modules/birthdays/__init__.py +++ b/modules/birthdays/__init__.py @@ -4,17 +4,18 @@ import random import discord from discord.ext import commands, tasks, bridge +from discord.commands import SlashCommandGroup from config.parser import JsonCache from lib import time, checks -from modules.birthdays import upcoming, birthday +from modules.birthdays import birthday from services.birthday_service import Birthday from services.config_service import GuildConfig -logs = logging.getLogger('Lumi.Core') -data = JsonCache.read_json("birthday") -month_mapping = data["month_mapping"] -messages = data["birthday_messages"] +_logs = logging.getLogger('Lumi.Core') +_data = JsonCache.read_json("birthday") +_months = _data["months"] +_messages = _data["birthday_messages"] class Birthdays(commands.Cog): @@ -22,59 +23,32 @@ class Birthdays(commands.Cog): self.client = client self.daily_birthday_check.start() - @bridge.bridge_command( - name="birthday", - aliases=["bday"], - description="Set your birthday.", - guild_only=True - ) - @commands.guild_only() + """ + birthday module - slash command only + """ + birthday = SlashCommandGroup(name="birthday", description="Birthday commands.", guild_only=True) + + @birthday.command(name="set", description="Set your birthday in this server.") @checks.birthdays_enabled() - @checks.allowed_in_channel() - async def set_birthday(self, ctx, month: str, *, day: int): - """ - Set your birthday. You can use abbreviations for months, like "jan" and "nov". - """ + async def set_birthday(self, ctx, month: discord.Option(choices=_months), day: int): + index = _months.index(month) + 1 + await birthday.add(ctx, month, index, day) - month_name = await birthday.get_month_name(month, month_mapping) - month_index = await birthday.get_month_index(month_name, month_mapping) - await birthday.set_birthday(ctx, month_name, month_index, day) - - @bridge.bridge_command( - name="deletebirthday", - aliases=["deletebday"], - description="Delete your birthday in this server.", - guild_only=True - ) + @birthday.command(name="delete", description="Delete your birthday in this server.") @commands.guild_only() async def delete_birthday(self, ctx): - """ - Delete your birthday in this server. - """ + await birthday.delete(ctx) - await birthday.delete_birthday(ctx) - - @bridge.bridge_command( - name="upcoming", - aliases=["upcomingbirthdays"], - description="Shows the upcoming birthdays in this server.", - guild_only=True - ) - @commands.guild_only() + @birthday.command(name="upcoming", description="Shows the upcoming birthdays in this server.") @checks.birthdays_enabled() - @checks.allowed_in_channel() async def upcoming_birthdays(self, ctx): - """ - Shows the upcoming birthdays in this server. - """ - - await upcoming.cmd(ctx) + await birthday.upcoming(ctx) @tasks.loop(hours=23, minutes=55) async def daily_birthday_check(self): wait_time = time.seconds_until(7, 0) - logs.info(f"[BirthdayHandler] Waiting until 7 AM Eastern for daily check: {round(wait_time)}s") + _logs.info(f"[BirthdayHandler] Waiting until 7 AM Eastern for daily check: {round(wait_time)}s") await asyncio.sleep(wait_time) embed = discord.Embed(color=discord.Color.embed_background()) @@ -87,17 +61,17 @@ class Birthdays(commands.Cog): guild_config = GuildConfig(guild.id) if not guild_config.birthday_channel_id: - logs.info(f"[BirthdayHandler] Guild with ID {guild.id} skipped: no birthday channel defined.") + _logs.info(f"[BirthdayHandler] Guild with ID {guild.id} skipped: no birthday channel defined.") return - message = random.choice(messages) + message = random.choice(_messages) embed.description = message.format(member.name) channel = await self.client.get_or_fetch_channel(guild, guild_config.birthday_channel_id) await channel.send(embed=embed, content=member.mention) - logs.info(f"[BirthdayHandler] Success! user/guild/channel ID: {member.id}/{guild.id}/{channel.id}") + _logs.info(f"[BirthdayHandler] Success! user/guild/channel ID: {member.id}/{guild.id}/{channel.id}") except Exception as error: - logs.info(f"[BirthdayHandler] Skipped processing user/guild {user_id}/{guild_id}") + _logs.info(f"[BirthdayHandler] Skipped processing user/guild {user_id}/{guild_id}") # wait one second to avoid rate limits await asyncio.sleep(1) diff --git a/modules/birthdays/birthday.py b/modules/birthdays/birthday.py index 208eaf9..0a3818e 100644 --- a/modules/birthdays/birthday.py +++ b/modules/birthdays/birthday.py @@ -1,13 +1,15 @@ import calendar import datetime +import discord from discord.ext import commands from lib.embeds.info import BdayInfo from services.birthday_service import Birthday -async def set_birthday(ctx, month, month_index, day): +async def add(ctx, month, month_index, day): + """Set a user's birthday in a specific guild.""" leap_year = 2020 max_days = calendar.monthrange(leap_year, month_index)[1] @@ -23,22 +25,47 @@ async def set_birthday(ctx, month, month_index, day): await ctx.respond(embed=BdayInfo.set_month(ctx, month, day)) -async def delete_birthday(ctx): +async def delete(ctx): + """Delete a user's birthday in a specific server.""" birthday = Birthday(ctx.author.id, ctx.guild.id) birthday.delete() await ctx.respond(embed=BdayInfo.delete(ctx)) -async def get_month_name(string, mapping): - string = string.lower() +async def upcoming(ctx): + """Get the upcoming birthdays for a specific server.""" + upcoming_birthdays = Birthday.get_upcoming_birthdays(ctx.guild.id) + icon = ctx.guild.icon if ctx.guild.icon else "https://i.imgur.com/79XfsbS.png" - for month in mapping: - if string.startswith(month): - return mapping[month] + embed = discord.Embed( + color=discord.Color.embed_background() + ) + embed.set_author(name="Upcoming Birthdays!", icon_url=icon) + embed.set_thumbnail(url="https://i.imgur.com/79XfsbS.png") - raise commands.BadArgument("I couldn't recognize that month.") + found_birthdays = 0 + for user_id, birthday in upcoming_birthdays: + try: + member = await ctx.guild.fetch_member(user_id) + name = member.name + except discord.HTTPException: + continue # skip user if not in guild + try: + birthday_date = datetime.datetime.strptime(birthday, "%m-%d") + formatted_birthday = birthday_date.strftime("%B %-d") + except ValueError: + # leap year error + formatted_birthday = "February 29" -async def get_month_index(string, mapping): - values = list(mapping.values()) - return values.index(string) + 1 + embed.add_field( + name=f"{name}", + value=f"🎂 {formatted_birthday}", + inline=False + ) + + found_birthdays += 1 + if found_birthdays >= 5: + break + + await ctx.respond(embed=embed) diff --git a/modules/birthdays/upcoming.py b/modules/birthdays/upcoming.py deleted file mode 100644 index d3ab0ba..0000000 --- a/modules/birthdays/upcoming.py +++ /dev/null @@ -1,43 +0,0 @@ -import datetime - -import discord - -from services.birthday_service import Birthday - - -async def cmd(ctx): - upcoming_birthdays = Birthday.get_upcoming_birthdays(ctx.guild.id) - icon = ctx.guild.icon if ctx.guild.icon else "https://i.imgur.com/79XfsbS.png" - - embed = discord.Embed( - color=discord.Color.embed_background() - ) - embed.set_author(name="Upcoming Birthdays!", icon_url=icon) - embed.set_thumbnail(url="https://i.imgur.com/79XfsbS.png") - - found_birthdays = 0 - for user_id, birthday in upcoming_birthdays: - try: - member = await ctx.guild.fetch_member(user_id) - name = member.name - except discord.HTTPException: - continue # skip user if not in guild - - try: - birthday_date = datetime.datetime.strptime(birthday, "%m-%d") - formatted_birthday = birthday_date.strftime("%B %-d") - except ValueError: - # leap year error - formatted_birthday = "February 29" - - embed.add_field( - name=f"{name}", - value=f"🎂 {formatted_birthday}", - inline=False - ) - - found_birthdays += 1 - if found_birthdays >= 5: - break - - await ctx.respond(embed=embed)