Files
dakiny-bot/classes/voting_views.py
T

110 lines
3.8 KiB
Python

"""
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,
)