diff --git a/backend-flask/discord_bot.py b/backend-flask/discord_bot.py index 3fec968..0959e9a 100644 --- a/backend-flask/discord_bot.py +++ b/backend-flask/discord_bot.py @@ -6,6 +6,7 @@ import models from models.event import Event from models.player import Player from models.player_event import PlayerEvent +from models.player_team import PlayerTeam app_db.db_session = app_db.create_isolated_db_session(None) @@ -17,6 +18,80 @@ discord_token = os.getenv("DISCORD_TOKEN") if not discord_token: raise ValueError("DISCORD_TOKEN environment variable not set.") +class EventModal(discord.ui.Modal): + event_name = discord.ui.TextInput( + label="Event Name", + placeholder="Enter the event name", + ) + + event_description = discord.ui.TextInput( + label="Event Description", + placeholder="Describe the event", + style=discord.TextStyle.long, + ) + + def __init__(self, event: Event): + self.event = event + self.event_name.default = event.name + self.event_description.default = event.description + super().__init__(title="Event Details") + + async def on_submit(self, interaction: discord.Interaction): + player_team = app_db.db_session.query( + PlayerTeam + ).where( + PlayerTeam.team_id == self.event.team_id, + ).join( + Player, + Player.steam_id == PlayerTeam.player_id + ).where( + Player.discord_id == interaction.user.id + ).one_or_none() + + if not player_team or not player_team.is_team_leader: + await interaction.response.send_message( + "You are not authorized to edit this event.", + ephemeral=True + ) + + self.event.name = self.event_name.value + self.event.description = self.event_description.value + app_db.db_session.commit() + self.event.update_discord_message() + + await interaction.response.send_message("Event details updated.", ephemeral=True) + +async def handle_update_attendance( + player: Player, + event: Event, + interaction: discord.Interaction, + custom_id: str +): + player_event = app_db.db_session.query( + PlayerEvent + ).where( + PlayerEvent.player_id == player.steam_id, + PlayerEvent.event_id == event.id + ).one_or_none() + + if custom_id == "click_not_attending": + if player_event: + app_db.db_session.delete(player_event) + app_db.db_session.commit() + event.update_discord_message() + await interaction.response.defer() + + if not player_event: + player_event = PlayerEvent() + player_event.event_id = event.id + player_event.player_id = player.steam_id + app_db.db_session.add(player_event) + + player_event.has_confirmed = custom_id == "click_attending" + app_db.db_session.commit() + event.update_discord_message() + await interaction.response.defer() + class Client(commands.Bot): async def on_ready(self): if guild_id: @@ -36,16 +111,14 @@ class Client(commands.Bot): if interaction.data is None or not "custom_id" in interaction.data: return - has_interaction = False + interactions = [ + "click_attending", + "click_pending", + "click_not_attending", + "click_edit_event", + ] - if interaction.data["custom_id"] == "click_attending": - has_interaction = True - elif interaction.data["custom_id"] == "click_pending": - has_interaction = True - elif interaction.data["custom_id"] == "click_not_attending": - has_interaction = True - - if has_interaction: + if interaction.data["custom_id"] in interactions: interaction_type = interaction.data["custom_id"] player = app_db.db_session.query( @@ -60,6 +133,15 @@ class Client(commands.Bot): "Contact <@195789918474207233> to link your account.", ephemeral=True ) + + # log the interaction + user = await self.fetch_user(195789918474207233) + if user: + await user.send( + f"User <@{interaction.user.id}> tried to " + + "interact with an event but their account is " + + "not linked to a player." + ) return event = app_db.db_session.query( @@ -69,30 +151,10 @@ class Client(commands.Bot): ).one_or_none() if event and player: - player_event = app_db.db_session.query( - PlayerEvent - ).where( - PlayerEvent.player_id == player.steam_id, - PlayerEvent.event_id == event.id - ).one_or_none() - - if interaction_type == "click_not_attending": - if player_event: - app_db.db_session.delete(player_event) - app_db.db_session.commit() - event.update_discord_message() - await interaction.response.defer() - - if not player_event: - player_event = PlayerEvent() - player_event.event_id = event.id - player_event.player_id = player.steam_id - app_db.db_session.add(player_event) - - player_event.has_confirmed = interaction_type == "click_attending" - app_db.db_session.commit() - event.update_discord_message() - await interaction.response.defer() + if interaction_type == "click_edit_event": + await interaction.response.send_modal(EventModal(event)) + else: + await handle_update_attendance(player, event, interaction, interaction_type) intents = discord.Intents.default() client = Client(command_prefix="!", intents=intents) @@ -102,6 +164,7 @@ client = Client(command_prefix="!", intents=intents) description="Set up announcements webhook in this channel", guild=guild_id ) +@discord.app_commands.guild_only() @discord.app_commands.default_permissions(manage_webhooks=True) async def setup_announcements(interaction: discord.Interaction): await interaction.response.send_message( @@ -112,12 +175,7 @@ async def setup_announcements(interaction: discord.Interaction): channel = interaction.channel - if not isinstance(channel, discord.TextChannel): - await interaction.followup.send( - "This command can only be used in a text channel.", - ephemeral=True - ) - return + assert isinstance(channel, discord.TextChannel) for webhook in await channel.webhooks(): if webhook.user == client.user: @@ -132,25 +190,3 @@ async def setup_announcements(interaction: discord.Interaction): await interaction.followup.send(content, ephemeral=True) client.run(discord_token) - -#@client.tree.command( -# name="link-team", -# description="Link this Discord guild to a team with an invite key", -# guild=guild_id -#) -#@app_commands.describe(key="Team invite key") -#async def link_team(interaction: discord.Interaction, key: str): -# team_invite = db_session.query( -# models.TeamInvite -# ).where( -# models.TeamInvite.key == key -# ).one_or_none() -# -# if not team_invite: -# await interaction.response.send_message( -# "Invalid team invite key.", -# ephemeral=True -# ) -# return -# -# # consume the invite and link the team to the guild diff --git a/backend-flask/models/event.py b/backend-flask/models/event.py index 810e058..fc33cbe 100644 --- a/backend-flask/models/event.py +++ b/backend-flask/models/event.py @@ -135,22 +135,28 @@ class Event(app_db.BaseModel): "components": [ { "type": 2, - "label": "✅ Attending", + "label": "✅", "style": 3, "custom_id": "click_attending" }, { "type": 2, - "label": "⌛ Pending", + "label": "⌛", "style": 2, "custom_id": "click_pending" }, { "type": 2, - "label": "❌ Not attending", + "label": "❌", "style": 2, "custom_id": "click_not_attending" }, + { + "type": 2, + "label": "Edit", + "style": 2, + "custom_id": "click_edit_event" + }, { "type": 2, "label": "View in browser",