Feat: use models in voting highcouncil views.
build_develop / build (push) Successful in 40s

This commit is contained in:
2025-07-31 13:48:11 -04:00
parent 45f17e09d3
commit 354823ca1f
+59 -46
View File
@@ -1,18 +1,17 @@
"""Contains various views to be used while voting for high council. Controls the logic when performing the vote.""" """Contains various views to be used while voting for high council. Controls the logic when performing the vote."""
import nextcord import nextcord
from dakiny_bot.dakiny_settings import settings
from dakiny_bot.database.sql_data_classes import (
CouncilMembers,
ElectionInformation,
Votes,
engine,
)
from dakiny_bot.utils import VoteType, build_highcouncil_votes_str, get_election_name
from nextcord import SelectOption from nextcord import SelectOption
from nextcord.interactions import Interaction from nextcord.interactions import Interaction
from sqlalchemy import exc, select, update from sqlalchemy import exc, select, update
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from sqlmodel import col
from dakiny_bot.dakiny_settings import settings
from dakiny_bot.database.db import engine
from dakiny_bot.database.models import CouncilMember, ElectionInformation, Vote
from dakiny_bot.logger import dakiny_logger
from dakiny_bot.utils import VoteType, build_highcouncil_votes_str, get_election_name
class VoteSelect(nextcord.ui.StringSelect): class VoteSelect(nextcord.ui.StringSelect):
@@ -37,20 +36,32 @@ class VoteSelect(nextcord.ui.StringSelect):
Args: Args:
interaction (Interaction): Interaction with this callback. interaction (Interaction): Interaction with this callback.
""" """
if (
interaction.user is None
or not isinstance(interaction.channel, nextcord.TextChannel)
or interaction.guild is None
):
# ignore none... Don't know what situation this is.
# if not textchannel, don't know how callback happened
# if no guild, is problem because should only be in guild.
return
election_name: str = get_election_name() election_name: str = get_election_name()
with Session(engine) as session: with Session(engine) as session:
stmt = select(ElectionInformation.HighCouncilVoteMsgId).where( stmt = select(col(ElectionInformation.high_council_vote_msg_id)).where(
ElectionInformation.ElectionName == election_name col(ElectionInformation.name == election_name)
) )
vote_msg_id = session.scalar(stmt) if (vote_msg_id := session.scalar(stmt)) is None:
dakiny_logger.error("Unable to find a Highcouncil Vote Message ID in database.")
return
voted_for = None if self.values[0] == "Abstain" else int(self.values[0]) voted_for = None if self.values[0] == "Abstain" else int(self.values[0])
new_vote = Votes( new_vote = Vote(
ElectionName=election_name, election_name=election_name,
VoterId=interaction.user.id, voter_id=interaction.user.id,
VotedForId=voted_for, voted_for_id=voted_for,
Type=self.election_type, type=self.election_type,
) )
try: try:
@@ -61,10 +72,10 @@ class VoteSelect(nextcord.ui.StringSelect):
# user already has a vote in the election and election type # user already has a vote in the election and election type
session.rollback() session.rollback()
stmt = ( stmt = (
update(Votes) update(Vote)
.where(Votes.ElectionName == election_name) .where(col(Vote.election_name == election_name))
.where(Votes.VoterId == interaction.user.id) .where(col(Vote.voter_id == interaction.user.id))
.where(Votes.Type == self.election_type) .where(col(Vote.type == self.election_type))
.values(VotedForId=voted_for) .values(VotedForId=voted_for)
) )
session.execute(stmt) session.execute(stmt)
@@ -103,6 +114,10 @@ class VoteHighcouncilView(nextcord.ui.View):
button (nextcord.ui.Button): Unused. idk why its needed in the decorator button (nextcord.ui.Button): Unused. idk why its needed in the decorator
interaction (nextcord.Interaction): Interaction of user who pressed the button interaction (nextcord.Interaction): Interaction of user who pressed the button
""" """
if not isinstance(interaction.user, nextcord.Member):
# the user should only be a member of the guild.
return
# enforce council elect only # enforce council elect only
if self.guild.get_role(settings.role_ids.clan_council_elect) not in interaction.user.roles: if self.guild.get_role(settings.role_ids.clan_council_elect) not in interaction.user.roles:
await interaction.response.send_message( await interaction.response.send_message(
@@ -115,32 +130,29 @@ class VoteHighcouncilView(nextcord.ui.View):
with Session(engine) as session: with Session(engine) as session:
stmt = ( stmt = (
select(Votes.VotedForId) select(col(Vote.voted_for_id))
.where(Votes.ElectionName == election_name) .where(col(Vote.election_name == election_name))
.where(Votes.VoterId == interaction.user.id) .where(col(Vote.voter_id == interaction.user.id))
.where(Votes.Type == VoteType.CLANLEADER) .where(col(Vote.type == VoteType.CLANLEADER))
) )
voted_for = session.scalar(stmt) voted_for = session.scalar(stmt)
stmt = ( stmt = (
select(CouncilMembers.MemberId) select(col(CouncilMember.member_id))
.where(CouncilMembers.ElectionName == election_name) .where(col(CouncilMember.election_name == election_name))
.filter(CouncilMembers.ClanLeaderSpeechId.is_not(None)) .filter(col(CouncilMember.clan_leader_speech_id is not None))
) )
options = [ options = [
SelectOption( SelectOption(
label=( label=(f"{member.display_name} ☑️" if voted_for == nominee else f"{member.display_name}"),
f"{self.guild.get_member(nominee).display_name} ☑️"
if voted_for == nominee
else f"{self.guild.get_member(nominee).display_name}"
),
value=str(nominee), value=str(nominee),
) )
for nominee in sorted( for nominee in sorted(
session.scalars(stmt), session.scalars(stmt),
key=lambda nominee: self.guild.get_member(nominee).display_name.lower(), key=lambda nominee: self.guild.get_member(nominee).display_name.lower(), # pyright: ignore[reportOptionalMemberAccess]
) )
if (member := self.guild.get_member(nominee)) is not None
] ]
options.append( options.append(
SelectOption( SelectOption(
@@ -175,6 +187,10 @@ class VoteHighcouncilView(nextcord.ui.View):
button (nextcord.ui.Button): Unused. idk why its needed in the decorator button (nextcord.ui.Button): Unused. idk why its needed in the decorator
interaction (nextcord.Interaction): Interaction of user who pressed the button interaction (nextcord.Interaction): Interaction of user who pressed the button
""" """
if not isinstance(interaction.user, nextcord.Member):
# the user should only be a member of the guild.
return
# enforce council elect only # enforce council elect only
if self.guild.get_role(settings.role_ids.clan_council_elect) not in interaction.user.roles: if self.guild.get_role(settings.role_ids.clan_council_elect) not in interaction.user.roles:
await interaction.response.send_message( await interaction.response.send_message(
@@ -187,32 +203,29 @@ class VoteHighcouncilView(nextcord.ui.View):
with Session(engine) as session: with Session(engine) as session:
stmt = ( stmt = (
select(Votes.VotedForId) select(col(Vote.voted_for_id))
.where(Votes.ElectionName == election_name) .where(col(Vote.election_name == election_name))
.where(Votes.VoterId == interaction.user.id) .where(col(Vote.voter_id == interaction.user.id))
.where(Votes.Type == VoteType.DISCORDMANAGER) .where(col(Vote.type == VoteType.DISCORDMANAGER))
) )
voted_for = session.scalar(stmt) voted_for = session.scalar(stmt)
stmt = ( stmt = (
select(CouncilMembers.MemberId) select(col(CouncilMember.member_id))
.where(CouncilMembers.ElectionName == election_name) .where(col(CouncilMember.election_name == election_name))
.filter(CouncilMembers.DiscordManagerSpeechId.is_not(None)) .filter(col(CouncilMember.discord_manager_speech_id is not None))
) )
options = [ options = [
SelectOption( SelectOption(
label=( label=(f"{member.display_name} ☑️" if voted_for == nominee else f"{member.display_name}"),
f"{self.guild.get_member(nominee).display_name} ☑️"
if voted_for == nominee
else f"{self.guild.get_member(nominee).display_name}"
),
value=str(nominee), value=str(nominee),
) )
for nominee in sorted( for nominee in sorted(
session.scalars(stmt), session.scalars(stmt),
key=lambda nominee: self.guild.get_member(nominee).display_name.lower(), key=lambda nominee: self.guild.get_member(nominee).display_name.lower(), # pyright: ignore[reportOptionalMemberAccess]
) )
if (member := self.guild.get_member(nominee)) is not None
] ]
options.append( options.append(
SelectOption( SelectOption(