mirror of
https://github.com/wlinator/luminara.git
synced 2024-10-02 18:03:12 +00:00
feat: Add birthday command and daily task
This commit is contained in:
parent
aaabfa42ed
commit
106171339e
5 changed files with 157 additions and 3 deletions
19
lib/checks.py
Normal file
19
lib/checks.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
from discord.ext import commands
|
||||
|
||||
from lib.exceptions import BirthdaysDisabled
|
||||
from services.config_service import GuildConfig
|
||||
|
||||
|
||||
def birthdays_enabled():
|
||||
async def predicate(ctx: commands.Context[commands.Bot]) -> bool:
|
||||
if ctx.guild is None:
|
||||
return True
|
||||
|
||||
guild_config = GuildConfig(ctx.guild.id)
|
||||
|
||||
if not guild_config.birthday_channel_id:
|
||||
raise BirthdaysDisabled
|
||||
|
||||
return True
|
||||
|
||||
return commands.check(predicate)
|
|
@ -125,8 +125,8 @@ class Constants:
|
|||
LEVEL_MESSAGES: Final = _p.read_json("levels.en-US")
|
||||
|
||||
_bday: Final = _p.read_json("bdays.en-US")
|
||||
BIRTHDAY_MESSAGES: Final = _bday["birthday_messages"]
|
||||
BIRTHDAY_MONTHS: Final = _bday["months"]
|
||||
BIRTHDAY_MESSAGES: Final[list[str]] = _bday["birthday_messages"]
|
||||
BIRTHDAY_MONTHS: Final[list[str]] = _bday["months"]
|
||||
|
||||
|
||||
CONST = Constants()
|
||||
|
|
0
modules/birthdays/__init__.py
Normal file
0
modules/birthdays/__init__.py
Normal file
135
modules/birthdays/birthday.py
Normal file
135
modules/birthdays/birthday.py
Normal file
|
@ -0,0 +1,135 @@
|
|||
import asyncio
|
||||
import calendar
|
||||
import datetime
|
||||
import random
|
||||
|
||||
import discord
|
||||
import pytz
|
||||
from discord import app_commands
|
||||
from discord.ext import commands, tasks
|
||||
from loguru import logger
|
||||
|
||||
from lib.checks import birthdays_enabled
|
||||
from lib.const import CONST
|
||||
from services.birthday_service import BirthdayService
|
||||
from services.config_service import GuildConfig
|
||||
from ui.embeds import Builder
|
||||
|
||||
tz = pytz.timezone("America/New_York")
|
||||
|
||||
|
||||
@app_commands.guild_only()
|
||||
@app_commands.default_permissions(manage_guild=True)
|
||||
class Birthday(commands.GroupCog, group_name="birthday"):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self.daily_birthday_check.start()
|
||||
|
||||
@tasks.loop(time=datetime.time(hour=12, minute=0, tzinfo=pytz.UTC))
|
||||
async def daily_birthday_check(self):
|
||||
logger.info(CONST.STRINGS["birthday_check_started"])
|
||||
birthdays_today = BirthdayService.get_birthdays_today()
|
||||
processed_birthdays = 0
|
||||
failed_birthdays = 0
|
||||
|
||||
if birthdays_today:
|
||||
for user_id, guild_id in birthdays_today:
|
||||
try:
|
||||
guild = await self.bot.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 = Builder.create_embed(
|
||||
theme="success",
|
||||
author_text="Happy Birthday!",
|
||||
description=message.format(member.name),
|
||||
hide_name_in_description=True,
|
||||
)
|
||||
embed.set_image(url=CONST.BIRTHDAY_GIF_URL)
|
||||
|
||||
channel = await guild.fetch_channel(guild_config.birthday_channel_id)
|
||||
assert isinstance(channel, discord.TextChannel)
|
||||
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,
|
||||
),
|
||||
)
|
||||
|
||||
@app_commands.command(name="set")
|
||||
@birthdays_enabled()
|
||||
@app_commands.choices(
|
||||
month=[discord.app_commands.Choice(name=month_name, value=month_name) for month_name in CONST.BIRTHDAY_MONTHS],
|
||||
)
|
||||
async def set_birthday(
|
||||
self,
|
||||
interaction: discord.Interaction,
|
||||
month: str,
|
||||
day: int,
|
||||
) -> None:
|
||||
"""
|
||||
Set your birthday.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction : discord.Interaction
|
||||
The interaction object.
|
||||
month : Month
|
||||
The month of your birthday.
|
||||
day : int
|
||||
The day of your birthday.
|
||||
"""
|
||||
assert interaction.guild
|
||||
leap_year = 2020
|
||||
month_index = CONST.BIRTHDAY_MONTHS.index(month) + 1
|
||||
max_days = calendar.monthrange(leap_year, month_index)[1]
|
||||
|
||||
if not 1 <= day <= max_days:
|
||||
raise commands.BadArgument(CONST.STRINGS["birthday_add_invalid_date"])
|
||||
|
||||
date_obj = datetime.datetime(leap_year, month_index, day, tzinfo=tz)
|
||||
|
||||
birthday = BirthdayService(interaction.user.id, interaction.guild.id)
|
||||
birthday.set(date_obj)
|
||||
|
||||
embed = Builder.create_embed(
|
||||
theme="success",
|
||||
user_name=interaction.user.name,
|
||||
author_text=CONST.STRINGS["birthday_add_success_author"],
|
||||
description=CONST.STRINGS["birthday_add_success_description"].format(
|
||||
month,
|
||||
day,
|
||||
),
|
||||
)
|
||||
|
||||
await interaction.response.send_message(embed=embed)
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot) -> None:
|
||||
await bot.add_cog(Birthday(bot))
|
|
@ -5,7 +5,7 @@ import pytz
|
|||
from db import database
|
||||
|
||||
|
||||
class Birthday:
|
||||
class BirthdayService:
|
||||
def __init__(self, user_id: int, guild_id: int) -> None:
|
||||
self.user_id: int = user_id
|
||||
self.guild_id: int = guild_id
|
||||
|
|
Loading…
Reference in a new issue