"""Contains various views to be used in the nomination process.""" import nextcord from DakinySettings import settings from database_setup.sql_data_classes import CouncilMembers, engine from nextcord.interactions import Interaction from sqlalchemy import select from sqlalchemy.orm import Session from utils import NOMINEE_SPLITTER, decorate_nomination, get_election_name class NominateModal(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, usr_id: int, usr_nominated: bool, # noqa: FBT001 speech_content: str, ): super().__init__( "Nomination", timeout=5 * 60, # 5 minutes ) self.usr_id: int = usr_id 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) election_name = get_election_name() with Session(engine) as session: if not self.usr_nominated: msg = await interaction.channel.send(speech) council_member = CouncilMembers( ElectionName=election_name, MemberId=interaction.user.id, SpeechMsgId=msg.id, ) session.add(council_member) session.commit() else: # user already nominated, just need to update the election speech stmt = ( select(CouncilMembers) .where(CouncilMembers.ElectionName == election_name) .where(CouncilMembers.MemberId == self.usr_id) ) obj = session.scalar(stmt) msg: nextcord.Message = await interaction.channel.fetch_message(obj.SpeechMsgId) await msg.edit(content=decorate_nomination(interaction.user.id, self.speech.value)) class NominateView(nextcord.ui.View): """The button to press to start your nomination.""" def __init__(self, guild: nextcord.Guild): super().__init__(timeout=None) self.guild: nextcord.Guild = guild @nextcord.ui.button( label="Nominate Yourself", style=nextcord.ButtonStyle.primary, custom_id="nominate", ) async def nominate(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002 """ Button to nominate oneself for Clan Council. 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 members only if self.guild.get_role(settings.role_ids.clan_member) not in interaction.user.roles: await interaction.response.send_message( f"You must have the <@&{settings.role_ids.clan_member}> role to vote.", ephemeral=True, ) return election_name = get_election_name() usr_nominated = False speech_content = "" with Session(engine) as session: stmt = ( select(CouncilMembers) .where(CouncilMembers.ElectionName == election_name) .where(CouncilMembers.MemberId == interaction.user.id) ) obj = session.scalar(stmt) if obj is not None: usr_nominated = True msg = await interaction.channel.fetch_message(obj.SpeechMsgId) speech_content = msg.content.split(NOMINEE_SPLITTER)[1] await interaction.response.send_modal(NominateModal(interaction.user.id, usr_nominated, speech_content))