diff --git a/classes/nominate_cl_views.py b/classes/nominate_cl_views.py deleted file mode 100644 index 297b105..0000000 --- a/classes/nominate_cl_views.py +++ /dev/null @@ -1,139 +0,0 @@ -""" -Contains various views to be used in the clan leader 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 NominateCLModal(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__( - "Clan Leader 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.ClanLeaderSpeechId = msg.id - session.commit() - else: - msg: nextcord.Message = await interaction.channel.fetch_message( - council_elect.ClanLeaderSpeechId - ) - await msg.edit( - content=decorate_nomination(interaction.user.id, self.speech.value) - ) - - -class NominateCLView(nextcord.ui.View): - """ - The button to press to start your Clan Leader 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 Clan Leader", - style=nextcord.ButtonStyle.primary, - custom_id="nominate-cl", - ) - 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.ClanLeaderSpeechId is not None: - usr_nominated = True - msg = await interaction.channel.fetch_message(obj.ClanLeaderSpeechId) - speech_content = msg.content.split(NOMINEE_SPLITTER)[1] - - await interaction.response.send_modal( - NominateCLModal( - self.config, interaction.user.id, usr_nominated, speech_content - ) - ) diff --git a/classes/nominate_dm_views.py b/classes/nominate_highcouncil_views.py similarity index 51% rename from classes/nominate_dm_views.py rename to classes/nominate_highcouncil_views.py index 5a0ea09..36fc005 100644 --- a/classes/nominate_dm_views.py +++ b/classes/nominate_highcouncil_views.py @@ -1,5 +1,5 @@ """ -Contains various views to be used in the discord manager nomination process. +Contains various views to be used in the high council nomination process. """ import nextcord @@ -77,9 +77,74 @@ class NominateDMModal(nextcord.ui.Modal): ) -class NominateDMView(nextcord.ui.View): +class NominateCLModal(nextcord.ui.Modal): """ - The button to press to start your Discord Manager nomination. + 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__( + "Clan Leader 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.ClanLeaderSpeechId = msg.id + session.commit() + else: + msg: nextcord.Message = await interaction.channel.fetch_message( + council_elect.ClanLeaderSpeechId + ) + await msg.edit( + content=decorate_nomination(interaction.user.id, self.speech.value) + ) + + +class NominateHighCouncilView(nextcord.ui.View): + """ + The buttons to press to start your High Council nomination. """ def __init__(self, config: DakinyConfig, guild: nextcord.Guild): @@ -92,7 +157,7 @@ class NominateDMView(nextcord.ui.View): style=nextcord.ButtonStyle.primary, custom_id="nominate-dm", ) - async def nominate( + async def nominate_dm( self, button: nextcord.ui.Button, interaction: nextcord.Interaction ) -> None: """ @@ -139,3 +204,54 @@ class NominateDMView(nextcord.ui.View): self.config, interaction.user.id, usr_nominated, speech_content ) ) + + @nextcord.ui.button( + label="Nominate for Clan Leader", + style=nextcord.ButtonStyle.primary, + custom_id="nominate-cl", + ) + async def nominate_cl( + 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.ClanLeaderSpeechId is not None: + usr_nominated = True + msg = await interaction.channel.fetch_message(obj.ClanLeaderSpeechId) + speech_content = msg.content.split(NOMINEE_SPLITTER)[1] + + await interaction.response.send_modal( + NominateCLModal( + self.config, interaction.user.id, usr_nominated, speech_content + ) + ) diff --git a/dakiny_bot.py b/dakiny_bot.py index bef7ff6..0d3cadf 100644 --- a/dakiny_bot.py +++ b/dakiny_bot.py @@ -8,8 +8,7 @@ from hydra.core.config_store import ConfigStore from nextcord.ext import commands import database_setup.create_database as create_database -from classes.nominate_cl_views import NominateCLView -from classes.nominate_dm_views import NominateDMView +from classes.nominate_highcouncil_views import NominateHighCouncilView from classes.nominate_views import NominateView from classes.voting_views import VoteView from config import DakinyConfig @@ -56,8 +55,7 @@ def main(cfg: DakinyConfig): assert bot.user is not None create_database # pylint: disable=pointless-statement bot.add_view(NominateView(cfg, bot.get_guild(cfg.params.guild_id))) - bot.add_view(NominateCLView(cfg, bot.get_guild(cfg.params.guild_id))) - bot.add_view(NominateDMView(cfg, bot.get_guild(cfg.params.guild_id))) + bot.add_view(NominateHighCouncilView(cfg, bot.get_guild(cfg.params.guild_id))) bot.add_view(VoteView(cfg, bot.get_guild(cfg.params.guild_id))) print(f"{bot.user.name} has connected to Discord!")