1
Fork 0
mirror of https://github.com/wlinator/luminara.git synced 2024-10-02 18:03:12 +00:00

Refactor birthday module

This commit is contained in:
wlinator 2024-08-14 05:44:39 -04:00
parent ccf2b1236b
commit 05561495ab
5 changed files with 136 additions and 85 deletions

View file

@ -17,6 +17,21 @@
"admin_sync_error_title": "Sync Error",
"admin_sync_title": "Sync Successful",
"bet_limit": "❌ | **{0}** you cannot place any bets above **${1}**.",
"birthday_check_started": "Daily birthday check started.",
"birthday_check_skipped": "Birthday announcements in guild with ID {0} skipped: no birthday channel.",
"birthday_check_success": "Birthday announcement Success! user/guild/chan ID: {0}/{1}/{2}",
"birthday_check_error": "Birthday announcement skipped processing user/guild {0}/{1} | {2}",
"birthday_check_finished": "Daily birthday check finished. {0} birthdays processed. {1} birthdays failed.",
"birthday_add_invalid_date": "The date you entered is invalid.",
"birthday_add_success_author": "Birthday Set",
"birthday_add_success_description": "your birthday has been set to **{0} {1}**.",
"birthday_delete_success_author": "Birthday Deleted",
"birthday_delete_success_description": "your birthday has been deleted from this server.",
"birthday_upcoming_author": "Upcoming Birthdays!",
"birthday_upcoming_description_line": "🎂 {0} - {1}",
"birthday_upcoming_no_birthdays_author": "No Upcoming Birthdays",
"birthday_upcoming_no_birthdays": "there are no upcoming birthdays in this server.",
"birthday_leap_year": "February 29",
"case_case_field": "Case:",
"case_case_field_value": "`{0}`",
"case_duration_field": "Duration:",

View file

@ -85,6 +85,7 @@ class Constants:
# birthdays
BIRTHDAY_MESSAGES = JsonCache.read_json("birthday")["birthday_messages"]
BIRTHDAY_MONTHS = JsonCache.read_json("birthday")["months"]
BIRTHDAY_GIF_URL = "https://media1.tenor.com/m/NXvU9jbBUGMAAAAC/fireworks.gif"
CONST = Constants()

View file

@ -1,16 +1,12 @@
import asyncio
import random
import datetime
import pytz
import discord
from discord.commands import SlashCommandGroup
from discord.ext import commands, tasks
from loguru import logger
from lib import checks, time
from lib import checks
from lib.constants import CONST
from modules.birthdays import birthday
from services.birthday_service import Birthday
from services.config_service import GuildConfig
from modules.birthdays import birthday, daily_check
class Birthdays(commands.Cog):
@ -18,9 +14,6 @@ class Birthdays(commands.Cog):
self.client = client
self.daily_birthday_check.start()
"""
birthday module - slash command only
"""
birthday = SlashCommandGroup(
name="birthday",
description="Birthday commands.",
@ -43,47 +36,9 @@ class Birthdays(commands.Cog):
async def upcoming_birthdays(self, ctx):
await birthday.upcoming(ctx)
@tasks.loop(hours=23, minutes=55)
@tasks.loop(time=datetime.time(hour=12, minute=0, tzinfo=pytz.UTC)) # 12 PM UTC
async def daily_birthday_check(self):
wait_time = time.seconds_until(7, 0)
logger.debug(
f"Waiting until 7 AM Eastern for the daily birthday check: {round(wait_time)}s left.",
)
await asyncio.sleep(wait_time)
embed = discord.Embed(color=discord.Color.embed_background())
embed.set_image(url="https://media1.tenor.com/m/NXvU9jbBUGMAAAAC/fireworks.gif")
for user_id, guild_id in Birthday.get_birthdays_today():
try:
guild = await self.client.fetch_guild(guild_id)
member = await guild.fetch_member(user_id)
guild_config = GuildConfig(guild.id)
if not guild_config.birthday_channel_id:
logger.debug(
f"Birthday announcements in guild with ID {guild.id} skipped: no birthday channel.",
)
return
message = random.choice(CONST.BIRTHDAY_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)
logger.debug(
f"Birthday announcement Success! user/guild/chan ID: {member.id}/{guild.id}/{channel.id}",
)
except Exception as e:
logger.warning(
f"Birthday announcement skipped processing user/guild {user_id}/{guild_id} | {e}",
)
# wait one second to avoid rate limits
await asyncio.sleep(1)
await daily_check.daily_birthday_check(self.client)
def setup(client):

View file

@ -4,7 +4,8 @@ import datetime
import discord
from discord.ext import commands
from lib.embeds.info import BdayInfo
from lib.embed_builder import EmbedBuilder
from lib.constants import CONST
from services.birthday_service import Birthday
@ -13,59 +14,75 @@ async def add(ctx, month, month_index, day):
leap_year = 2020
max_days = calendar.monthrange(leap_year, month_index)[1]
if not (1 <= day <= max_days):
raise commands.BadArgument("the date you entered is invalid.")
if not 1 <= day <= max_days:
raise commands.BadArgument(CONST.STRINGS["birthday_add_invalid_date"])
date_str = f"{leap_year}-{month_index:02d}-{day:02d}"
date_obj = datetime.datetime.strptime(date_str, "%Y-%m-%d")
date_obj = datetime.datetime(leap_year, month_index, day)
birthday = Birthday(ctx.author.id, ctx.guild.id)
birthday.set(date_obj)
await ctx.respond(embed=BdayInfo.set_month(ctx, month, day))
embed = EmbedBuilder.create_success_embed(
ctx,
author_text=CONST.STRINGS["birthday_add_success_author"],
description=CONST.STRINGS["birthday_add_success_description"].format(
month,
day,
),
show_name=True,
)
await ctx.respond(embed=embed)
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))
Birthday(ctx.author.id, ctx.guild.id).delete()
embed = EmbedBuilder.create_success_embed(
ctx,
author_text=CONST.STRINGS["birthday_delete_success_author"],
description=CONST.STRINGS["birthday_delete_success_description"],
show_name=True,
)
await ctx.respond(embed=embed)
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"
embed = discord.Embed(
color=discord.Color.embed_background(),
if not upcoming_birthdays:
embed = EmbedBuilder.create_warning_embed(
ctx,
author_text=CONST.STRINGS["birthday_upcoming_no_birthdays_author"],
description=CONST.STRINGS["birthday_upcoming_no_birthdays"],
show_name=True,
)
await ctx.respond(embed=embed)
return
embed = EmbedBuilder.create_success_embed(
ctx,
author_text=CONST.STRINGS["birthday_upcoming_author"],
description="",
show_name=False,
)
embed.set_author(name="Upcoming Birthdays!", icon_url=icon)
embed.set_thumbnail(url="https://i.imgur.com/79XfsbS.png")
embed.set_thumbnail(url=CONST.LUMI_LOGO_TRANSPARENT)
found_birthdays = 0
for user_id, birthday in upcoming_birthdays:
birthday_lines = []
for user_id, birthday in upcoming_birthdays[:10]:
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
birthday_lines.append(
CONST.STRINGS["birthday_upcoming_description_line"].format(
member.name,
formatted_birthday,
),
)
except (discord.HTTPException, ValueError):
continue
embed.description = "\n".join(birthday_lines)
await ctx.respond(embed=embed)

View file

@ -0,0 +1,63 @@
import asyncio
import random
from loguru import logger
from lib.constants import CONST
from services.birthday_service import Birthday
from services.config_service import GuildConfig
from lib.embed_builder import EmbedBuilder
async def daily_birthday_check(client):
logger.info(CONST.STRINGS["birthday_check_started"])
birthdays_today = Birthday.get_birthdays_today()
processed_birthdays = 0
failed_birthdays = 0
if birthdays_today:
for user_id, guild_id in birthdays_today:
try:
guild = await client.fetch_guild(guild_id)
member = await guild.fetch_member(user_id)
guild_config = GuildConfig(guild.id)
if not guild_config.birthday_channel_id:
logger.debug(
CONST.STRINGS["birthday_check_skipped"].format(guild.id),
)
continue
message = random.choice(CONST.BIRTHDAY_MESSAGES)
embed = EmbedBuilder.create_success_embed(
None,
author_text="Happy Birthday!",
description=message.format(member.name),
show_name=False,
)
embed.set_image(url=CONST.BIRTHDAY_GIF_URL)
channel = await guild.fetch_channel(guild_config.birthday_channel_id)
await channel.send(embed=embed, content=member.mention)
logger.debug(
CONST.STRINGS["birthday_check_success"].format(
member.id,
guild.id,
channel.id,
),
)
processed_birthdays += 1
except Exception as e:
logger.warning(
CONST.STRINGS["birthday_check_error"].format(user_id, guild_id, e),
)
failed_birthdays += 1
# wait one second to avoid rate limits
await asyncio.sleep(1)
logger.info(
CONST.STRINGS["birthday_check_finished"].format(
processed_birthdays,
failed_birthdays,
),
)