build_develop / build (push) Successful in 37s
Also handle the list error from pylance.
229 lines
8.3 KiB
Python
229 lines
8.3 KiB
Python
"""Contains various views to be used in the high council nomination process."""
|
|
|
|
import nextcord
|
|
from dakiny_bot.dakiny_settings import settings
|
|
from dakiny_bot.database.sql_data_classes import CouncilMembers, engine
|
|
from dakiny_bot.utils import (
|
|
NOMINEE_SPLITTER,
|
|
decorate_cl_nomination,
|
|
decorate_dm_nomination,
|
|
get_election_name,
|
|
)
|
|
from nextcord.interactions import Interaction
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
|
|
|
|
class NominateDMModal(nextcord.ui.Modal):
|
|
"""
|
|
Modal for nominating oneself.
|
|
|
|
User writes a speech and then the callback sends the speech into the correct channel.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
usr_id: int,
|
|
usr_nominated: bool, # noqa: FBT001
|
|
speech_content: str,
|
|
):
|
|
super().__init__(
|
|
"Discord Manager Nomination",
|
|
timeout=5 * 60, # 5 minutes
|
|
)
|
|
self.usr_id: int = usr_id
|
|
self.usr_nominated = usr_nominated
|
|
|
|
self.speech = nextcord.ui.TextInput(
|
|
label="Nomination Speech",
|
|
style=nextcord.TextInputStyle.paragraph,
|
|
placeholder="Please write your speech here.",
|
|
required=True,
|
|
max_length=1500,
|
|
default_value=speech_content,
|
|
)
|
|
self.add_item(self.speech)
|
|
|
|
async def callback(self, interaction: Interaction) -> None:
|
|
"""
|
|
Sends the nomination speech into the voting channel and enters the user into the voting database.
|
|
|
|
Args:
|
|
interaction (Interaction): Interaction with user.
|
|
|
|
"""
|
|
speech = decorate_dm_nomination(interaction.user.id, self.speech.value)
|
|
|
|
with Session(engine) as session:
|
|
# user already in table
|
|
election_name = get_election_name()
|
|
stmt = (
|
|
select(CouncilMembers)
|
|
.where(CouncilMembers.ElectionName == election_name)
|
|
.where(CouncilMembers.MemberId == self.usr_id)
|
|
)
|
|
council_elect = session.scalar(stmt)
|
|
|
|
if not self.usr_nominated:
|
|
msg = await interaction.channel.send(speech)
|
|
|
|
council_elect.DiscordManagerSpeechId = msg.id
|
|
session.commit()
|
|
else:
|
|
msg: nextcord.Message = await interaction.channel.fetch_message(council_elect.DiscordManagerSpeechId)
|
|
await msg.edit(content=decorate_dm_nomination(interaction.user.id, self.speech.value))
|
|
|
|
|
|
class NominateCLModal(nextcord.ui.Modal):
|
|
"""
|
|
Modal for nominating oneself.
|
|
|
|
User writes a speech and then the callback sends the speech into the correct channel.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
usr_id: int,
|
|
usr_nominated: bool, # noqa: FBT001
|
|
speech_content: str,
|
|
):
|
|
super().__init__(
|
|
"Clan Leader Nomination",
|
|
timeout=5 * 60, # 5 minutes
|
|
)
|
|
self.usr_id: int = usr_id
|
|
self.usr_nominated = usr_nominated
|
|
|
|
self.speech = nextcord.ui.TextInput(
|
|
label="Nomination Speech",
|
|
style=nextcord.TextInputStyle.paragraph,
|
|
placeholder="Please write your speech here.",
|
|
required=True,
|
|
max_length=1500,
|
|
default_value=speech_content,
|
|
)
|
|
self.add_item(self.speech)
|
|
|
|
async def callback(self, interaction: Interaction) -> None:
|
|
"""
|
|
Sends the nomination speech into the voting channel and enters the user into the voting database.
|
|
|
|
Args:
|
|
interaction (Interaction): Interaction with user.
|
|
|
|
"""
|
|
speech = decorate_cl_nomination(interaction.user.id, self.speech.value)
|
|
|
|
with Session(engine) as session:
|
|
# user already in table
|
|
election_name = get_election_name()
|
|
stmt = (
|
|
select(CouncilMembers)
|
|
.where(CouncilMembers.ElectionName == election_name)
|
|
.where(CouncilMembers.MemberId == self.usr_id)
|
|
)
|
|
council_elect = session.scalar(stmt)
|
|
|
|
if not self.usr_nominated:
|
|
msg = await interaction.channel.send(speech)
|
|
|
|
council_elect.ClanLeaderSpeechId = msg.id
|
|
session.commit()
|
|
else:
|
|
msg: nextcord.Message = await interaction.channel.fetch_message(council_elect.ClanLeaderSpeechId)
|
|
await msg.edit(content=decorate_cl_nomination(interaction.user.id, self.speech.value))
|
|
|
|
|
|
class NominateHighCouncilView(nextcord.ui.View):
|
|
"""The buttons to press to start your High Council nomination."""
|
|
|
|
def __init__(self, guild: nextcord.Guild):
|
|
super().__init__(timeout=None)
|
|
self.guild: nextcord.Guild = guild
|
|
|
|
@nextcord.ui.button(
|
|
label="Nominate for Discord Manager",
|
|
style=nextcord.ButtonStyle.primary,
|
|
custom_id="nominate-dm",
|
|
)
|
|
async def nominate_dm(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002
|
|
"""
|
|
Button for nominating oneself for Discord Manager.
|
|
|
|
Gathers previous information about the user if they have already nominated themselves, then launches
|
|
the nomination modal to get their speech.
|
|
|
|
Args:
|
|
button (nextcord.ui.Button): Unused. idk why its needed in the decorator
|
|
interaction (nextcord.Interaction): Interaction of user who pressed the button
|
|
"""
|
|
# 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(
|
|
f"You must have the <@&{settings.role_ids.clan_council_elect}> role to vote.",
|
|
ephemeral=True,
|
|
)
|
|
return
|
|
|
|
election_name = get_election_name()
|
|
usr_nominated = False
|
|
speech_content = ""
|
|
with Session(engine) as session:
|
|
stmt = (
|
|
select(CouncilMembers)
|
|
.where(CouncilMembers.ElectionName == election_name)
|
|
.where(CouncilMembers.MemberId == interaction.user.id)
|
|
)
|
|
obj = session.scalar(stmt)
|
|
|
|
# user needs to exist to get here anyways...
|
|
if obj.DiscordManagerSpeechId is not None:
|
|
usr_nominated = True
|
|
msg = await interaction.channel.fetch_message(obj.DiscordManagerSpeechId)
|
|
speech_content = msg.content.split(NOMINEE_SPLITTER)[1]
|
|
|
|
await interaction.response.send_modal(NominateDMModal(interaction.user.id, usr_nominated, speech_content))
|
|
|
|
@nextcord.ui.button(
|
|
label="Nominate for Clan Leader",
|
|
style=nextcord.ButtonStyle.primary,
|
|
custom_id="nominate-cl",
|
|
)
|
|
async def nominate_cl(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002
|
|
"""
|
|
Button for nominating oneself for Clan Leader.
|
|
|
|
Gathers previous information about the user if they have already nominated themselves, then launches
|
|
the nomination modal to get their speech.
|
|
|
|
Args:
|
|
button (nextcord.ui.Button): Unused. idk why its needed in the decorator
|
|
interaction (nextcord.Interaction): Interaction of user who pressed the button
|
|
"""
|
|
# 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(
|
|
f"You must have the <@&{settings.role_ids.clan_council_elect}> role to vote.",
|
|
ephemeral=True,
|
|
)
|
|
return
|
|
|
|
election_name = get_election_name()
|
|
usr_nominated = False
|
|
speech_content = ""
|
|
with Session(engine) as session:
|
|
stmt = (
|
|
select(CouncilMembers)
|
|
.where(CouncilMembers.ElectionName == election_name)
|
|
.where(CouncilMembers.MemberId == interaction.user.id)
|
|
)
|
|
obj = session.scalar(stmt)
|
|
|
|
# user needs to exist to get here anyways...
|
|
if obj.ClanLeaderSpeechId is not None:
|
|
usr_nominated = True
|
|
msg = await interaction.channel.fetch_message(obj.ClanLeaderSpeechId)
|
|
speech_content = msg.content.split(NOMINEE_SPLITTER)[1]
|
|
|
|
await interaction.response.send_modal(NominateCLModal(interaction.user.id, usr_nominated, speech_content))
|