From 354823ca1f310633ee129a4af0aaa0594f793d83 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Thu, 31 Jul 2025 13:42:27 -0400 Subject: [PATCH] Feat: use models in voting highcouncil views. --- .../classes/voting_highcouncil_views.py | 105 ++++++++++-------- 1 file changed, 59 insertions(+), 46 deletions(-) diff --git a/dakiny_bot/classes/voting_highcouncil_views.py b/dakiny_bot/classes/voting_highcouncil_views.py index 17c9236..05869dc 100644 --- a/dakiny_bot/classes/voting_highcouncil_views.py +++ b/dakiny_bot/classes/voting_highcouncil_views.py @@ -1,18 +1,17 @@ """Contains various views to be used while voting for high council. Controls the logic when performing the vote.""" 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.interactions import Interaction from sqlalchemy import exc, select, update 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): @@ -37,20 +36,32 @@ class VoteSelect(nextcord.ui.StringSelect): Args: 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() with Session(engine) as session: - stmt = select(ElectionInformation.HighCouncilVoteMsgId).where( - ElectionInformation.ElectionName == election_name + stmt = select(col(ElectionInformation.high_council_vote_msg_id)).where( + 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]) - new_vote = Votes( - ElectionName=election_name, - VoterId=interaction.user.id, - VotedForId=voted_for, - Type=self.election_type, + new_vote = Vote( + election_name=election_name, + voter_id=interaction.user.id, + voted_for_id=voted_for, + type=self.election_type, ) try: @@ -61,10 +72,10 @@ class VoteSelect(nextcord.ui.StringSelect): # user already has a vote in the election and election type session.rollback() stmt = ( - update(Votes) - .where(Votes.ElectionName == election_name) - .where(Votes.VoterId == interaction.user.id) - .where(Votes.Type == self.election_type) + update(Vote) + .where(col(Vote.election_name == election_name)) + .where(col(Vote.voter_id == interaction.user.id)) + .where(col(Vote.type == self.election_type)) .values(VotedForId=voted_for) ) session.execute(stmt) @@ -103,6 +114,10 @@ class VoteHighcouncilView(nextcord.ui.View): button (nextcord.ui.Button): Unused. idk why its needed in the decorator 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 if self.guild.get_role(settings.role_ids.clan_council_elect) not in interaction.user.roles: await interaction.response.send_message( @@ -115,32 +130,29 @@ class VoteHighcouncilView(nextcord.ui.View): with Session(engine) as session: stmt = ( - select(Votes.VotedForId) - .where(Votes.ElectionName == election_name) - .where(Votes.VoterId == interaction.user.id) - .where(Votes.Type == VoteType.CLANLEADER) + select(col(Vote.voted_for_id)) + .where(col(Vote.election_name == election_name)) + .where(col(Vote.voter_id == interaction.user.id)) + .where(col(Vote.type == VoteType.CLANLEADER)) ) voted_for = session.scalar(stmt) stmt = ( - select(CouncilMembers.MemberId) - .where(CouncilMembers.ElectionName == election_name) - .filter(CouncilMembers.ClanLeaderSpeechId.is_not(None)) + select(col(CouncilMember.member_id)) + .where(col(CouncilMember.election_name == election_name)) + .filter(col(CouncilMember.clan_leader_speech_id is not None)) ) options = [ SelectOption( - label=( - f"{self.guild.get_member(nominee).display_name} ☑️" - if voted_for == nominee - else f"{self.guild.get_member(nominee).display_name}" - ), + label=(f"{member.display_name} ☑️" if voted_for == nominee else f"{member.display_name}"), value=str(nominee), ) for nominee in sorted( 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( SelectOption( @@ -175,6 +187,10 @@ class VoteHighcouncilView(nextcord.ui.View): button (nextcord.ui.Button): Unused. idk why its needed in the decorator 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 if self.guild.get_role(settings.role_ids.clan_council_elect) not in interaction.user.roles: await interaction.response.send_message( @@ -187,32 +203,29 @@ class VoteHighcouncilView(nextcord.ui.View): with Session(engine) as session: stmt = ( - select(Votes.VotedForId) - .where(Votes.ElectionName == election_name) - .where(Votes.VoterId == interaction.user.id) - .where(Votes.Type == VoteType.DISCORDMANAGER) + select(col(Vote.voted_for_id)) + .where(col(Vote.election_name == election_name)) + .where(col(Vote.voter_id == interaction.user.id)) + .where(col(Vote.type == VoteType.DISCORDMANAGER)) ) voted_for = session.scalar(stmt) stmt = ( - select(CouncilMembers.MemberId) - .where(CouncilMembers.ElectionName == election_name) - .filter(CouncilMembers.DiscordManagerSpeechId.is_not(None)) + select(col(CouncilMember.member_id)) + .where(col(CouncilMember.election_name == election_name)) + .filter(col(CouncilMember.discord_manager_speech_id is not None)) ) options = [ SelectOption( - label=( - f"{self.guild.get_member(nominee).display_name} ☑️" - if voted_for == nominee - else f"{self.guild.get_member(nominee).display_name}" - ), + label=(f"{member.display_name} ☑️" if voted_for == nominee else f"{member.display_name}"), value=str(nominee), ) for nominee in sorted( 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( SelectOption(