Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0e3162123 | ||
|
|
8c1eb8d11f | ||
|
|
40d220e2bb | ||
|
|
4e8032823d | ||
|
|
678fcd37e1 | ||
|
|
7530c59a94 | ||
|
|
6abab5c4e5 | ||
|
|
088de263cc |
@@ -69,7 +69,6 @@ class NominateModal(nextcord.ui.Modal):
|
|||||||
.where(CouncilMembers.MemberId == self.usr_id)
|
.where(CouncilMembers.MemberId == self.usr_id)
|
||||||
)
|
)
|
||||||
obj = session.scalar(stmt)
|
obj = session.scalar(stmt)
|
||||||
obj.SpeechMsgContents = self.speech.value
|
|
||||||
|
|
||||||
msg: nextcord.Message = await interaction.channel.fetch_message(obj.SpeechMsgId)
|
msg: nextcord.Message = await interaction.channel.fetch_message(obj.SpeechMsgId)
|
||||||
await msg.edit(content=decorate_nomination(interaction.user.id, self.speech.value))
|
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.
|
Decorates a nomination speech so that it sits within multiple speeches better.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
user_id (_type_): ID of user sending the speech
|
user_id (int): ID of user sending the speech
|
||||||
speech (_type_): Speech from the user
|
speech (str): Speech from the user
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: Decorated speech
|
str: Decorated speech
|
||||||
|
|||||||
+41
-14
@@ -7,11 +7,16 @@ from typing import List
|
|||||||
import nextcord
|
import nextcord
|
||||||
from nextcord import SelectOption
|
from nextcord import SelectOption
|
||||||
from nextcord.interactions import Interaction
|
from nextcord.interactions import Interaction
|
||||||
from sqlalchemy import exc, select
|
from sqlalchemy import exc, select, update
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from config import DakinyConfig
|
from config import DakinyConfig
|
||||||
from database_setup.sql_data_classes import CouncilMembers, ElectionInformation, Votes, engine
|
from database_setup.sql_data_classes import (
|
||||||
|
CouncilMembers,
|
||||||
|
ElectionInformation,
|
||||||
|
Votes,
|
||||||
|
engine,
|
||||||
|
)
|
||||||
from utils import build_votes_str, get_election_cycle_name
|
from utils import build_votes_str, get_election_cycle_name
|
||||||
|
|
||||||
|
|
||||||
@@ -38,7 +43,11 @@ class VoteSelect(nextcord.ui.StringSelect):
|
|||||||
else:
|
else:
|
||||||
voted_for = int(self.values[0])
|
voted_for = int(self.values[0])
|
||||||
|
|
||||||
new_vote = Votes(ElectionCycle=election_name, VoterId=interaction.user.id, VotedForId=voted_for)
|
new_vote = Votes(
|
||||||
|
ElectionCycle=election_name,
|
||||||
|
VoterId=interaction.user.id,
|
||||||
|
VotedForId=voted_for,
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
session.add(new_vote)
|
session.add(new_vote)
|
||||||
@@ -47,16 +56,18 @@ class VoteSelect(nextcord.ui.StringSelect):
|
|||||||
except exc.IntegrityError:
|
except exc.IntegrityError:
|
||||||
session.rollback()
|
session.rollback()
|
||||||
stmt = (
|
stmt = (
|
||||||
select(Votes)
|
update(Votes)
|
||||||
.where(Votes.ElectionCycle == election_name)
|
.where(Votes.ElectionCycle == election_name)
|
||||||
.where(Votes.VoterId == interaction.user.id)
|
.where(Votes.VoterId == interaction.user.id)
|
||||||
|
.values(VotedForId=voted_for)
|
||||||
)
|
)
|
||||||
vote = session.scalar(stmt)
|
session.execute(stmt)
|
||||||
vote.VotedForId = voted_for
|
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
vote_message_str = build_votes_str(self.config)
|
vote_message_str = build_votes_str(self.config)
|
||||||
vote_msg: nextcord.Message = await interaction.channel.fetch_message(vote_msg_id)
|
vote_msg: nextcord.Message = await interaction.channel.fetch_message(
|
||||||
|
vote_msg_id
|
||||||
|
)
|
||||||
await vote_msg.edit(content=vote_message_str)
|
await vote_msg.edit(content=vote_message_str)
|
||||||
|
|
||||||
if voted_for is not None:
|
if voted_for is not None:
|
||||||
@@ -77,10 +88,15 @@ class VoteView(nextcord.ui.View):
|
|||||||
self.config = config
|
self.config = config
|
||||||
self.guild = guild
|
self.guild = guild
|
||||||
|
|
||||||
@nextcord.ui.button(label="Vote", style=nextcord.ButtonStyle.primary, custom_id="vote")
|
@nextcord.ui.button(
|
||||||
async def vote(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None:
|
label="Vote", style=nextcord.ButtonStyle.primary, custom_id="vote"
|
||||||
|
)
|
||||||
|
async def vote(
|
||||||
|
self, button: nextcord.ui.Button, interaction: nextcord.Interaction
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
TODO
|
Enforces only members vote. Gets election cycle, creates voting options (checking if user has voted already),
|
||||||
|
then sends the voting view.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
button (nextcord.ui.Button): Unused. idk why its needed in the decorator
|
button (nextcord.ui.Button): Unused. idk why its needed in the decorator
|
||||||
@@ -88,9 +104,13 @@ class VoteView(nextcord.ui.View):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# enforce members only
|
# enforce members only
|
||||||
if self.guild.get_role(self.config.params.clan_member_role_id) not in interaction.user.roles:
|
if (
|
||||||
|
self.guild.get_role(self.config.params.clan_member_role_id)
|
||||||
|
not in interaction.user.roles
|
||||||
|
):
|
||||||
await interaction.response.send_message(
|
await interaction.response.send_message(
|
||||||
f"You must have the <@&{self.config.params.clan_member_role_id}> role to vote.", ephemeral=True
|
f"You must have the <@&{self.config.params.clan_member_role_id}> role to vote.",
|
||||||
|
ephemeral=True,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -104,7 +124,9 @@ class VoteView(nextcord.ui.View):
|
|||||||
)
|
)
|
||||||
voted_for = session.scalar(stmt)
|
voted_for = session.scalar(stmt)
|
||||||
|
|
||||||
stmt = select(CouncilMembers.MemberId).where(CouncilMembers.ElectionCycle == election)
|
stmt = select(CouncilMembers.MemberId).where(
|
||||||
|
CouncilMembers.ElectionCycle == election
|
||||||
|
)
|
||||||
|
|
||||||
options = [
|
options = [
|
||||||
SelectOption(
|
SelectOption(
|
||||||
@@ -115,7 +137,12 @@ class VoteView(nextcord.ui.View):
|
|||||||
)
|
)
|
||||||
for nominee in session.scalars(stmt)
|
for nominee in session.scalars(stmt)
|
||||||
]
|
]
|
||||||
options.append(SelectOption(label="Abstain ☑️" if voted_for is None else "Abstain", value="Abstain"))
|
options.append(
|
||||||
|
SelectOption(
|
||||||
|
label="Abstain ☑️" if voted_for is None else "Abstain",
|
||||||
|
value="Abstain",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
view = nextcord.ui.View()
|
view = nextcord.ui.View()
|
||||||
view.add_item(VoteSelect(options=options, config=self.config))
|
view.add_item(VoteSelect(options=options, config=self.config))
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from nextcord.ext import commands
|
|||||||
from cogs.commands.request import RequestCog
|
from cogs.commands.request import RequestCog
|
||||||
from cogs.commands.set import setCog
|
from cogs.commands.set import setCog
|
||||||
from cogs.commands.test import TestCog
|
from cogs.commands.test import TestCog
|
||||||
|
from cogs.commands.view import ViewCog
|
||||||
|
|
||||||
|
|
||||||
# This function will be called when this extension is loaded.
|
# 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(RequestCog(bot))
|
||||||
bot.add_cog(TestCog(bot))
|
bot.add_cog(TestCog(bot))
|
||||||
bot.add_cog(setCog())
|
bot.add_cog(setCog())
|
||||||
|
bot.add_cog(ViewCog())
|
||||||
|
|||||||
@@ -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])
|
||||||
Reference in New Issue
Block a user