diff --git a/classes/nominate_views.py b/classes/nominate_views.py index 5f56963..d51a752 100644 --- a/classes/nominate_views.py +++ b/classes/nominate_views.py @@ -69,7 +69,6 @@ class NominateModal(nextcord.ui.Modal): .where(CouncilMembers.MemberId == self.usr_id) ) obj = session.scalar(stmt) - obj.SpeechMsgContents = self.speech.value msg: nextcord.Message = await interaction.channel.fetch_message(obj.SpeechMsgId) await msg.edit(content=decorate_nomination(interaction.user.id, self.speech.value)) @@ -115,13 +114,13 @@ class NominateView(nextcord.ui.View): ) -def decorate_nomination(user_id, speech) -> str: +def decorate_nomination(user_id: int, speech: str) -> str: """ Decorates a nomination speech so that it sits within multiple speeches better. Args: - user_id (_type_): ID of user sending the speech - speech (_type_): Speech from the user + user_id (int): ID of user sending the speech + speech (str): Speech from the user Returns: str: Decorated speech diff --git a/cogs/commands/__init__.py b/cogs/commands/__init__.py index 7232b00..f161699 100644 --- a/cogs/commands/__init__.py +++ b/cogs/commands/__init__.py @@ -7,6 +7,7 @@ from nextcord.ext import commands from cogs.commands.request import RequestCog from cogs.commands.set import setCog from cogs.commands.test import TestCog +from cogs.commands.view import ViewCog # This function will be called when this extension is loaded. @@ -19,3 +20,4 @@ def setup(bot: commands.Bot): bot.add_cog(RequestCog(bot)) bot.add_cog(TestCog(bot)) bot.add_cog(setCog()) + bot.add_cog(ViewCog()) diff --git a/cogs/commands/view.py b/cogs/commands/view.py new file mode 100644 index 0000000..2bd9175 --- /dev/null +++ b/cogs/commands/view.py @@ -0,0 +1,96 @@ +""" +Commands for viewing information in the database. +""" + +import nextcord +from nextcord.ext import commands +from sqlalchemy import select +from sqlalchemy.orm import Session + +from database_setup.sql_data_classes import ElectionInformation, Votes, engine + + +class ViewCog(commands.Cog, name="View Commands"): + """ + Holds the view commands. + """ + + def __init__(self) -> None: + """ + Default constructor for ViewCog class. Does nothing. + """ + + @nextcord.slash_command() + async def view(self, interaction: nextcord.Interaction): + """ + Parent slash command for set. Never called. + """ + + @view.subcommand( + description="Shows all voters and who they voted for in a given election." + ) + async def votes( + self, + interaction: nextcord.Interaction, + election_name: str = nextcord.SlashOption( + required=True, description="The election you want to view votes for." + ), + ): + """ + Takes in an election name and sends a response message to the user with a list of people who voted in that + election and who they voted for. Notes those tho abstained. Tells a user if the election is invalid. Uses + autocompletion to assist with getting elections. + + Args: + interaction (nextcord.Interaction): User's interaction with the command. + election_name (str): Is SlashOption. The name of the election to view votes for. + """ + + stmt = select(Votes).where(Votes.ElectionCycle == election_name) + + with Session(engine) as session: + # Check if election exists. + if session.scalar(stmt) is None: + await interaction.response.send_message( + f"Invalid election: {election_name}.", ephemeral=True + ) + return + + votes = session.scalars(stmt) + content = "" + for vote in votes: + content += ( + f"<@{vote.VoterId}> voted for <@{vote.VotedForId}>.\n" + if vote.VotedForId is not None + else f"<@{vote.VoterId}> abstained from voted.\n" + ) + + await interaction.response.send_message(content=content, ephemeral=True) + + @votes.on_autocomplete("election_name") + async def election_autocomplete( + self, interaction: nextcord.Interaction, election_name: str + ): + """ + Collects all elections that start with the election string. + + Args: + interaction (nextcord.Interaction): Interaction with command. + election_name (str): String to run autocomplete on. + """ + + with Session(engine) as session: + stmt = select(ElectionInformation.ElectionCycle) + elections = session.scalars(stmt) + + # if empty compare string + if not election_name: + await interaction.response.send_autocomplete(elections) + return + + autofilled_elections: "list[str]" = [ + election + for election in elections + if election.lower().startswith(election_name.lower()) + ] + await interaction.response.send_autocomplete(autofilled_elections[:25])