diff --git a/.vscode/settings.json b/.vscode/settings.json index d1507a4..b36b1b4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,11 @@ "reportArgumentType": "information", "reportAttributeAccessIssue": "warning" }, - "cSpell.words": ["cakeday", "cakedays", "cooldown", "nextcord"] -} + "cSpell.words": [ + "blurple", + "cakeday", + "cakedays", + "cooldown", + "nextcord" + ] +} \ No newline at end of file diff --git a/off_cooldown_bot/app.py b/off_cooldown_bot/app.py index ead9053..e2e85b4 100644 --- a/off_cooldown_bot/app.py +++ b/off_cooldown_bot/app.py @@ -7,6 +7,8 @@ import pathlib import nextcord from nextcord.ext import commands +from off_cooldown_bot.open_raid import OpenRaid + from .logger import ocd_logger from .settings import settings @@ -40,6 +42,7 @@ def run() -> None: if bot.user is None: ocd_logger.critical("Discord connection failed.") return + bot.add_view(OpenRaid()) ocd_logger.info("%s has connected to Discord!", bot.user.name) # Run Discord bot diff --git a/off_cooldown_bot/cogs/commands/test.py b/off_cooldown_bot/cogs/commands/test.py index 54a9147..e99a5e0 100644 --- a/off_cooldown_bot/cogs/commands/test.py +++ b/off_cooldown_bot/cogs/commands/test.py @@ -3,7 +3,7 @@ import nextcord from nextcord.ext import application_checks, commands -from off_cooldown_bot.open_raid import OpenRaid +from off_cooldown_bot.open_raid import OpenRaid, build_raid_embed from off_cooldown_bot.utils import GUILDS ME = 206602713511886849 @@ -13,6 +13,8 @@ def is_me(): # noqa: ANN201 """Predicate that makes sure only I can run the test commands.""" def predicate(interaction: nextcord.Interaction) -> bool: + if interaction.user is None: + return False return interaction.user.id == ME return application_checks.check(predicate) @@ -38,4 +40,4 @@ class TestCog(commands.Cog, name="Test commands."): interaction (nextcord.Interaction): Interaction with the message. """ - await interaction.response.send_message("Starting an open raid.", view=OpenRaid()) + await interaction.response.send_message("Starting an open raid.", embed=build_raid_embed(), view=OpenRaid()) diff --git a/off_cooldown_bot/open_raid.py b/off_cooldown_bot/open_raid.py index bfa61b8..3018e6b 100644 --- a/off_cooldown_bot/open_raid.py +++ b/off_cooldown_bot/open_raid.py @@ -1,7 +1,15 @@ """Contains functions for open raid sign-ups.""" +import datetime + import nextcord +from off_cooldown_bot.logger import ocd_logger + +MAX_TANKS = 2 +MAX_HEALERS = 2 +MAX_DPS = 25 + class OpenRaid(nextcord.ui.View): """Class defines view for buttons on an open raid schedule message.""" @@ -9,8 +17,8 @@ class OpenRaid(nextcord.ui.View): def __init__(self) -> None: super().__init__(timeout=None, auto_defer=True) - @nextcord.ui.button(label="Tank", style=nextcord.ButtonStyle.blurple, emoji="🛡️") - async def tank(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: + @nextcord.ui.button(label="Tank", style=nextcord.ButtonStyle.blurple, emoji="🛡️", custom_id="open_raid_tank") + async def tank(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002 """ Signs a user up as a tank. @@ -21,9 +29,32 @@ class OpenRaid(nextcord.ui.View): interaction (nextcord.Interaction): Interaction with command. """ + if interaction.message is None or interaction.user is None: + ocd_logger.warning("Command was called without a message or user.") + return - @nextcord.ui.button(label="Healer", style=nextcord.ButtonStyle.green, emoji="❤️") - async def healer(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: + embed = interaction.message.embeds[0] + user_str = f"<@{interaction.user.id}>" + + for index, field in enumerate(embed.fields): + if field.name == "Tanks": + values = [] if field.value is None else field.value.split("\n") + if user_str in values: + values.remove(user_str) + else: + if len(values) >= MAX_TANKS: + await interaction.response.send_message( + "Enough tanks have signed up, please choose another role.", ephemeral=True + ) + return + values.append(user_str) + embed.set_field_at(index, name=field.name, value="\n".join(values), inline=False) + break + + await interaction.edit(embed=embed) + + @nextcord.ui.button(label="Healer", style=nextcord.ButtonStyle.green, emoji="❤️", custom_id="open_raid_healer") + async def healer(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002 """ Signs a user up as a healer. @@ -34,9 +65,32 @@ class OpenRaid(nextcord.ui.View): interaction (nextcord.Interaction): Interaction with command. """ + if interaction.message is None or interaction.user is None: + ocd_logger.warning("Command was called without a message or user.") + return - @nextcord.ui.button(label="DPS", style=nextcord.ButtonStyle.red, emoji="⚔️") - async def dps(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: + embed = interaction.message.embeds[0] + user_str = f"<@{interaction.user.id}>" + + for index, field in enumerate(embed.fields): + if field.name == "Healers": + values = [] if field.value is None else field.value.split("\n") + if user_str in values: + values.remove(user_str) + else: + if len(values) >= MAX_HEALERS: + await interaction.response.send_message( + "Enough healers have signed up, please choose another role.", ephemeral=True + ) + return + values.append(user_str) + embed.set_field_at(index, name=field.name, value="\n".join(values), inline=False) + break + + await interaction.edit(embed=embed) + + @nextcord.ui.button(label="DPS", style=nextcord.ButtonStyle.red, emoji="⚔️", custom_id="open_raid_dps") + async def dps(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002 """ Signs a user up as dps. @@ -47,3 +101,43 @@ class OpenRaid(nextcord.ui.View): interaction (nextcord.Interaction): Interaction with command. """ + if interaction.message is None or interaction.user is None: + ocd_logger.warning("Command was called without a message or user.") + return + + embed = interaction.message.embeds[0] + user_str = f"<@{interaction.user.id}>" + + for index, field in enumerate(embed.fields): + if field.name == "DPS": + values = [] if field.value is None else field.value.split("\n") + if user_str in values: + values.remove(user_str) + else: + if len(values) >= MAX_DPS: + await interaction.response.send_message( + "Enough dps have signed up, please choose another role.", ephemeral=True + ) + return + values.append(user_str) + embed.set_field_at(index, name=field.name, value="\n".join(values), inline=False) + break + + await interaction.edit(embed=embed) + + +def build_raid_embed() -> nextcord.Embed: + """ + Build the open raid embed. + + Returns: + nextcord.Embed: _description_ + + """ + raid_time = datetime.datetime.now(tz=datetime.UTC) # TODO make this to the next saturday at 8pm CST + embed = nextcord.Embed(title="Off Cooldown Open Raid", timestamp=raid_time) + embed.add_field(name="Tanks", value="", inline=False) + embed.add_field(name="Healers", value="", inline=False) + embed.add_field(name="DPS", value="", inline=False) + + return embed