diff --git a/classes/nominate_dm_views.py b/classes/nominate_dm_views.py new file mode 100644 index 0000000..5a0ea09 --- /dev/null +++ b/classes/nominate_dm_views.py @@ -0,0 +1,141 @@ +""" +Contains various views to be used in the discord manager nomination process. +""" + +import nextcord +from nextcord.interactions import Interaction +from sqlalchemy import select +from sqlalchemy.orm import Session + +from config import DakinyConfig +from database_setup.sql_data_classes import CouncilMembers, engine +from utils import NOMINEE_SPLITTER, decorate_nomination, get_election_cycle_name + + +class NominateDMModal(nextcord.ui.Modal): + """ + Modal for nominating oneself. User writes a speech and then the callback sends the speech into the correct channel. + """ + + def __init__( + self, + config: DakinyConfig, + usr_id: int, + usr_nominated: bool, + speech_content: str, + ): + super().__init__( + "Discord Manager Nomination", + timeout=5 * 60, # 5 minutes + ) + self.usr_id: int = usr_id + self.config: DakinyConfig = config + self.usr_nominated = usr_nominated + + self.speech = nextcord.ui.TextInput( + label="Nomination Speech", + style=nextcord.TextInputStyle.paragraph, + placeholder="Please write your speech here.", + required=True, + max_length=1500, + default_value=speech_content, + ) + self.add_item(self.speech) + + async def callback(self, interaction: Interaction) -> None: + """ + Sends the nomination speech into the voting channel and enters the user into the voting database. + + Args: + interaction (Interaction): Interaction with user. + + """ + + speech = decorate_nomination(interaction.user.id, self.speech.value) + + with Session(engine) as session: + # user already in table + cycle = get_election_cycle_name(self.config) + stmt = ( + select(CouncilMembers) + .where(CouncilMembers.ElectionCycle == cycle) + .where(CouncilMembers.MemberId == self.usr_id) + ) + council_elect = session.scalar(stmt) + + if not self.usr_nominated: + msg = await interaction.channel.send(speech) + + council_elect.DiscordManagerSpeechId = msg.id + session.commit() + else: + msg: nextcord.Message = await interaction.channel.fetch_message( + council_elect.DiscordManagerSpeechId + ) + await msg.edit( + content=decorate_nomination(interaction.user.id, self.speech.value) + ) + + +class NominateDMView(nextcord.ui.View): + """ + The button to press to start your Discord Manager nomination. + """ + + def __init__(self, config: DakinyConfig, guild: nextcord.Guild): + super().__init__(timeout=None) + self.config: DakinyConfig = config + self.guild: nextcord.Guild = guild + + @nextcord.ui.button( + label="Nominate for Discord Manager", + style=nextcord.ButtonStyle.primary, + custom_id="nominate-dm", + ) + async def nominate( + self, button: nextcord.ui.Button, interaction: nextcord.Interaction + ) -> None: + """ + Gathers previous information about the user if they have already nominated themselves, then launches + the nomination modal to get their speech. + + Args: + button (nextcord.ui.Button): Unused. idk why its needed in the decorator + interaction (nextcord.Interaction): Interaction of user who pressed the button + """ + + # enforce council elect only + if ( + self.guild.get_role(self.config.params.clan_council_elect_role_id) + not in interaction.user.roles + ): + await interaction.response.send_message( + f"You must have the <@&{self.config.params.clan_council_elect_role_id}> role to vote.", + ephemeral=True, + ) + return + + cycle = get_election_cycle_name(self.config) + usr_nominated = False + speech_content = "" + with Session(engine) as session: + stmt = ( + select(CouncilMembers) + .where(CouncilMembers.ElectionCycle == cycle) + .where(CouncilMembers.MemberId == interaction.user.id) + ) + obj = session.scalar(stmt) + + # user needs to exist to get here anyways... + if obj.DiscordManagerSpeechId is not None: + usr_nominated = True + msg = await interaction.channel.fetch_message( + obj.DiscordManagerSpeechId + ) + speech_content = msg.content.split(NOMINEE_SPLITTER)[1] + + await interaction.response.send_modal( + NominateDMModal( + self.config, interaction.user.id, usr_nominated, speech_content + ) + )