Archived
generated from imcompiling/discord-bot-template
104 lines
3.9 KiB
Python
104 lines
3.9 KiB
Python
"""Defines the daily loop that runs the Off Cooldown bot functions."""
|
|
|
|
from datetime import UTC, datetime, time
|
|
|
|
import nextcord
|
|
from nextcord.ext import commands, tasks
|
|
from pytz import timezone
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
from sqlmodel import col
|
|
|
|
from off_cooldown_bot.app import birthday_list
|
|
from off_cooldown_bot.database.db import engine
|
|
from off_cooldown_bot.database.models import UserBirthday
|
|
from off_cooldown_bot.logger import ocd_logger
|
|
from off_cooldown_bot.open_raid import OpenRaid, build_raid_embed
|
|
from off_cooldown_bot.settings import settings
|
|
|
|
|
|
class DailyLoop(commands.Cog, name="Daily Loop"):
|
|
"""Class for performing daily functions."""
|
|
|
|
def __init__(self, bot: commands.Bot) -> None:
|
|
self.bot = bot
|
|
self.current_election = None
|
|
self.update_birthdays()
|
|
self.daily_loop.start()
|
|
|
|
@tasks.loop(time=time(hour=0, tzinfo=UTC))
|
|
async def daily_loop(self) -> None:
|
|
"""Run daily repeated functions."""
|
|
self.update_birthdays()
|
|
|
|
await self.cakedays()
|
|
|
|
@tasks.loop(time=time(hour=20, tzinfo=timezone("CST")))
|
|
async def open_raid(self) -> None:
|
|
"""
|
|
Define the open raid loop.
|
|
|
|
Checks daily if it is Thursday and then posts the open raid sign up.
|
|
"""
|
|
today = datetime.now(timezone("CST"))
|
|
if today.day + 2 == 5:
|
|
# open raid is on Saturday, post 2 days before
|
|
if (guild := self.bot.get_guild(settings.params.guild_id)) is None:
|
|
ocd_logger.error("Guild id not correct.")
|
|
return
|
|
if (channel := guild.get_channel(settings.channel_ids.raid)) is None or not isinstance(
|
|
channel, nextcord.TextChannel
|
|
):
|
|
ocd_logger.error("Raid channel is not defined or is not a text channel.")
|
|
return
|
|
await channel.send(embed=build_raid_embed(), view=OpenRaid())
|
|
|
|
@daily_loop.before_loop
|
|
@open_raid.before_loop
|
|
async def before_loop(self) -> None:
|
|
"""Actions run before the loop starts. Want to wait for bot to be ready and get the current cycle."""
|
|
await self.bot.wait_until_ready()
|
|
|
|
def update_birthdays(self) -> None:
|
|
"""Goes through database to collect all birthdays that are today. Adds user's id to birthday list."""
|
|
birthday_list.clear()
|
|
|
|
today = datetime.now(tz=UTC).date()
|
|
|
|
stmt = (
|
|
select(col(UserBirthday.user_id))
|
|
.where(col(UserBirthday.month) == today.month)
|
|
.where(col(UserBirthday.day) == today.day)
|
|
)
|
|
with Session(engine) as session:
|
|
to_add = session.scalars(stmt)
|
|
birthday_list.extend(to_add.all())
|
|
|
|
async def cakedays(self) -> None:
|
|
"""
|
|
Loops through the guild's humans checking for joined_at dates that match today's date.
|
|
|
|
Sends a message saying happy cakeday.
|
|
"""
|
|
today = datetime.now(tz=UTC).date()
|
|
if (guild := self.bot.get_guild(settings.params.guild_id)) is None:
|
|
ocd_logger.warning("Guild not found in bot.")
|
|
return
|
|
if (announce_channel := guild.get_channel(settings.channel_ids.general)) is None or not isinstance(
|
|
announce_channel, nextcord.TextChannel
|
|
):
|
|
ocd_logger.warning("Set general channel isn't found or isn't a text channel.")
|
|
return
|
|
|
|
cakedays: list[nextcord.Member] = [
|
|
human
|
|
for human in guild.humans
|
|
if human.joined_at is not None and human.joined_at.month == today.month and human.joined_at.day == today.day
|
|
]
|
|
|
|
for member in cakedays:
|
|
years = today.year - member.joined_at.year # type: ignore reportOptionalMemberAccess
|
|
year_str = "years" if years > 1 else "year"
|
|
msg = f"Happy Cake day! <@{member.id}> joined the discord {years} {year_str} ago!"
|
|
await announce_channel.send(msg)
|