""" Contains various views to be used while voting. Controls the logic when performing the vote. """ from typing import List import nextcord from nextcord import SelectOption from nextcord.ext import commands from nextcord.interactions import Interaction from sqlalchemy import select from sqlalchemy.orm import Session from config import DakinyConfig, ElectionCycle from database_setup.sql_data_classes import CouncilMembers, ElectionInformation, engine from utils import build_votes_str, get_election_cycle_name class VoteSelect(nextcord.ui.StringSelect): def __init__(self, options: List["SelectOption"], config: DakinyConfig) -> None: super().__init__( placeholder="Choose 1", min_values=1, max_values=1, options=options, ) self.config = config async def callback(self, interaction: Interaction): election_name = get_election_cycle_name(self.config) with Session(engine) as session: stmt = select(ElectionInformation.CouncilVoteMsgId).where( ElectionInformation.ElectionCycle == election_name ) vote_msg_id = session.scalar(stmt) voted_for = int(self.values[0]) new_vote = Votes(ElectionCycle=election_name, VoterId=interaction.user.id, VotedForId=voted_for) try: session.add(new_vote) session.commit() except exc.IntegrityError: session.rollback() stmt = ( select(Votes) .where(Votes.ElectionCycle == election_name) .where(Votes.VoterId == interaction.user.id) ) vote = session.scalar(stmt) vote.VotedForId = voted_for session.commit() vote_message_str = build_votes_str(self.config) vote_msg = await interaction.channel.fetch_message(vote_msg_id) await vote_msg.edit(content=vote_message_str) await interaction.edit(content=f"You have voted for <@{self.values[0]}>", view=None) class VoteView(nextcord.ui.View): """ The button to press to start your nomination. """ def __init__(self, config: DakinyConfig, guild: nextcord.Guild): super().__init__(timeout=None) self.config = config self.guild = guild @nextcord.ui.button(label="Vote", style=nextcord.ButtonStyle.primary, custom_id="vote") async def vote(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: """ TODO Args: button (nextcord.ui.Button): Unused. idk why its needed in the decorator interaction (nextcord.Interaction): Interaction of user who pressed the button """ election: str = get_election_cycle_name(self.config) with Session(engine) as session: stmt = ( select(Votes.VotedForId) .where(Votes.ElectionCycle == election) .where(Votes.VoterId == interaction.user.id) ) voted_for = session.scalar(stmt) stmt = select(CouncilMembers.MemberId).where(CouncilMembers.ElectionCycle == election) options = [ SelectOption( label=f"{self.guild.get_member(nominee).name} ☑️" if voted_for == nominee else f"{self.guild.get_member(nominee).name}", value=str(nominee), ) for nominee in session.scalars(stmt) ] view = nextcord.ui.View() view.add_item(VoteSelect(options=options, config=self.config)) await interaction.response.send_message( content="Please vote for a clan member!", view=view, ephemeral=True, )