From a0f160c801d1e5a8436c5e0c8de0a1cefad1491d Mon Sep 17 00:00:00 2001 From: imcompiling Date: Thu, 2 Nov 2023 16:22:02 -0400 Subject: [PATCH] Rework to allow users to edit their nomination message. --- classes/nominate_views.py | 91 +++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 14 deletions(-) diff --git a/classes/nominate_views.py b/classes/nominate_views.py index a184844..b66075f 100644 --- a/classes/nominate_views.py +++ b/classes/nominate_views.py @@ -4,23 +4,29 @@ Contains various views to be used in the 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 get_election_cycle_name +NOMINEE_SPLITTER = "========================================================\n\n" + 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, config): + def __init__(self, config: DakinyConfig, usr_id: int, usr_nominated: bool, speech_content: str): super().__init__( "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", @@ -28,9 +34,9 @@ class NominateModal(nextcord.ui.Modal): placeholder="Please write your speech here.", required=True, max_length=1500, + default_value=speech_content, ) self.add_item(self.speech) - self.config: DakinyConfig = config async def callback(self, interaction: Interaction) -> None: """ @@ -40,20 +46,33 @@ class NominateModal(nextcord.ui.Modal): interaction (Interaction): Interaction with user. """ - # TODO add nominee to database, make sure user hasn't nominated themself before, - nomination_message = f"**Clan Council Nominee: <@{interaction.user.id}>**\n" - nomination_message += "========================================================\n\n" - nomination_message += self.speech.value - - msg = await interaction.channel.send(nomination_message) + speech = decorate_nomination(interaction.user.id, self.speech.value) with Session(engine) as session: - council_member = CouncilMembers( - ElectionCycle=get_election_cycle_name(self.config), MemberId=interaction.user.id, SpeechMsgId=msg.id - ) - session.add(council_member) - session.commit() + if not self.usr_nominated: + msg = await interaction.channel.send(speech) + + council_member = CouncilMembers( + ElectionCycle=get_election_cycle_name(self.config), + MemberId=interaction.user.id, + SpeechMsgId=msg.id, + ) + session.add(council_member) + session.commit() + else: + # user already nominated, just need to update the election speech + cycle = get_election_cycle_name(self.config) + stmt = ( + select(CouncilMembers) + .where(CouncilMembers.ElectionCycle == cycle) + .where(CouncilMembers.MemberId == self.usr_id) + ) + obj = session.scalar(stmt) + obj.SpeechMsgContents = self.speech.value + + 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): @@ -67,4 +86,48 @@ class NominateView(nextcord.ui.View): @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: - await interaction.response.send_modal(NominateModal(self.config)) + """ + 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 + """ + + 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) + 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(self.config, interaction.user.id, usr_nominated, speech_content) + ) + + +def decorate_nomination(user_id, speech) -> str: + """ + Decorates a nomination speech so that it sits within multiple speeches better. + + Args: + user_id (_type_): ID of user sending the speech + speech (_type_): Speech from the user + + Returns: + str: Decorated speech + """ + msg = f"**Clan Council Nominee: <@{user_id}>**\n" + msg += NOMINEE_SPLITTER + msg += speech + + return msg