223 lines
9.2 KiB
Python
223 lines
9.2 KiB
Python
"""
|
|
Contains the election cycle class
|
|
"""
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
import nextcord
|
|
from nextcord.ext import commands
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from config import DakinyConfig
|
|
from database.sql_data_classes import ElectionInformation, engine
|
|
from utils import get_datetime
|
|
|
|
|
|
class ElectionCycle:
|
|
"""
|
|
This class represents all the dates required for an election cycle along with all the functions needed to operate
|
|
the cycle.
|
|
"""
|
|
|
|
def __init__(self, cycle: int, bot: commands.Bot) -> None:
|
|
"""
|
|
Generates all dates relevant to the election cycle from input election start, term start and end dates.
|
|
|
|
Args:
|
|
election_start (datetime): Date the election cycle starts.
|
|
term_start (datetime): Date the term being elected starts.
|
|
term_end (datetime): Date the term being elected ends.
|
|
bot: the discord bot instance
|
|
"""
|
|
self.config: DakinyConfig = bot.config
|
|
self.cycle = cycle
|
|
self.elecion_cycle = self.config.election_cycles[self.cycle]
|
|
self.election_start: datetime = get_datetime(self.elecion_cycle.election_start)
|
|
self.term_start: datetime = get_datetime(self.elecion_cycle.term_start)
|
|
self.term_end: datetime = get_datetime(self.elecion_cycle.term_end)
|
|
self.voting_start: datetime = get_datetime(self.elecion_cycle.voting_start)
|
|
self.voting_end: datetime = get_datetime(self.elecion_cycle.voting_end)
|
|
self.highcouncil_election_announce: datetime = self.voting_end + timedelta(days=1)
|
|
self.highcouncil_election_start: datetime = self.highcouncil_election_announce + timedelta(days=3)
|
|
self.highcouncil_election_end: datetime = self.term_start - timedelta(days=1)
|
|
self.guild: nextcord.Guild = bot.get_guild(self.config.params.guild_id)
|
|
|
|
def build_election_announcement(self) -> list[str]:
|
|
"""
|
|
Builds the messages to announce the election is starting.
|
|
|
|
Returns:
|
|
list[str]: A list of message contents in the correct order. Must be a string because the message is too
|
|
long.
|
|
"""
|
|
|
|
with open("bot_messages/election_announcement.txt", mode="r", encoding="utf8") as file:
|
|
message = file.read()
|
|
|
|
next_election = get_datetime(self.config.election_cycles[(self.cycle + 1) % 4].election_start)
|
|
|
|
message = message.format(
|
|
clan_council_id=self.config.params.clan_council_role_id,
|
|
high_council_id=self.config.params.high_council_role_id,
|
|
election_start_date=self.election_start.strftime("%B %d"),
|
|
term_start_date=self.term_start.strftime("%B %d"),
|
|
term_end_date=self.term_end.strftime("%B %d"),
|
|
voting_start_date=self.voting_start.strftime("%B %d"),
|
|
voting_end_date=self.voting_end.strftime("%B %d"),
|
|
highcouncil_election_date=self.highcouncil_election_start.strftime("%B %d"),
|
|
next_election_start_date=next_election.strftime("%B %d"),
|
|
)
|
|
|
|
return message.split("---message_break---")
|
|
|
|
def build_highcouncil_election_announce(self) -> str:
|
|
"""
|
|
Builds message to announce highcouncil election start.
|
|
|
|
Returns:
|
|
str: Message to send.
|
|
"""
|
|
|
|
with open("bot_messages/highcouncil_election.txt", mode="r", encoding="utf8") as file:
|
|
message = file.read()
|
|
|
|
return message.format(
|
|
clan_council_elect_role_id=self.config.params.clan_council_elect_role_id,
|
|
highcouncil_election_announce=self.highcouncil_election_announce.strftime("%B %d"),
|
|
highcouncil_election_start=self.highcouncil_election_start.strftime("%B %d"),
|
|
highcouncil_election_end=self.highcouncil_election_end.strftime("%B %d"),
|
|
term_start_date=self.term_start.strftime("%B %d"),
|
|
)
|
|
|
|
def build_vote_start(self) -> str:
|
|
"""
|
|
Builds the voting start message out of template and configurations.
|
|
|
|
Returns:
|
|
str: Message to send
|
|
"""
|
|
|
|
with open("bot_messages/vote_start.txt", mode="r", encoding="utf8") as file:
|
|
message = file.read()
|
|
vote_end: datetime = get_datetime(self.config.election_cycles[self.cycle].voting_end)
|
|
|
|
return message.format(
|
|
clan_member_id=self.config.params.clan_member_role_id,
|
|
voting_emote_id=self.config.params.voting_emote_id,
|
|
voting_end_date=vote_end.strftime("%B %d"),
|
|
voting_end_day=vote_end.strftime("%A"),
|
|
)
|
|
|
|
async def check_date(self) -> None:
|
|
"""
|
|
Function checks current date to see if something needs to be run.
|
|
"""
|
|
today = datetime.today()
|
|
|
|
# check all dates if action is needed
|
|
if today.date() == self.election_start.date():
|
|
await self.election_start_action()
|
|
elif today.date() == self.voting_start.date():
|
|
await self.voting_end_action()
|
|
elif today.date() == self.voting_end.date():
|
|
await self.voting_end_action()
|
|
elif today.date() == self.highcouncil_election_start.date():
|
|
await self.highcouncil_election_action()
|
|
elif today.date() == self.term_start.date():
|
|
await self.term_start_action()
|
|
elif today.date() == self.term_end.date():
|
|
await self.term_end_action()
|
|
|
|
async def election_start_action(self) -> None:
|
|
"""
|
|
Performs required actions for when the election cycle starts.
|
|
"""
|
|
# create new channel for election
|
|
category: nextcord.CategoryChannel = self.guild.get_channel(self.config.params.active_category_id)
|
|
quarter_name: str = self.get_election_cycle_name()
|
|
|
|
# create new entry into database.
|
|
election_channel = await category.create_text_channel(quarter_name)
|
|
with Session(engine) as session:
|
|
new_cycle = ElectionInformation(ElectionCycle=quarter_name, ElectionChannel=election_channel.id)
|
|
session.add(new_cycle)
|
|
session.commit()
|
|
|
|
# post message announcing election
|
|
# election start message is returned as an array of string because it is too long. send each string
|
|
# individually.
|
|
messages = self.build_election_announcement()
|
|
for message in messages:
|
|
await election_channel.send(message)
|
|
|
|
async def voting_start_action(self) -> None:
|
|
"""
|
|
Sends message informing members that voting has started.
|
|
Removes write permission from the general clan member role.
|
|
Adds the voting emote to all messages not sent by the vote. (This is temporary until voting is managed.)
|
|
"""
|
|
message = self.build_vote_start()
|
|
clan_member_role: nextcord.Role = self.guild.get_role(self.config.params.clan_member_role_id)
|
|
with Session(engine) as session:
|
|
stmt = select(ElectionInformation).where(
|
|
ElectionInformation.ElectionCycle == self.get_election_cycle_name()
|
|
)
|
|
election_info = session.scalar(stmt)
|
|
election_channel = self.guild.get_channel(election_info.ElectionChannel)
|
|
await election_channel.send(message)
|
|
await election_channel.set_permissions(clan_member_role, send_messages=False)
|
|
|
|
async def voting_end_action(self) -> None:
|
|
"""
|
|
Performs required actions for when voting time has ended.
|
|
"""
|
|
message = self.build_highcouncil_election_announce()
|
|
council_elect_role: nextcord.Role = self.guild.get_role(self.config.params.clan_council_elect_role_id)
|
|
with Session(engine) as session:
|
|
stmt = select(ElectionInformation).where(
|
|
ElectionInformation.ElectionCycle == self.get_election_cycle_name()
|
|
)
|
|
election_info = session.scalar(stmt)
|
|
election_channel = self.guild.get_channel(election_info.ElectionChannel)
|
|
await election_channel.send(message)
|
|
await election_channel.set_permissions(council_elect_role, send_messages=True)
|
|
|
|
async def highcouncil_election_action(self) -> None:
|
|
"""
|
|
Performs required actions for when the highcouncil is elected.
|
|
"""
|
|
print("Highcouncil election has started.")
|
|
|
|
async def term_start_action(self) -> None:
|
|
msg: str = "the term has started"
|
|
print(msg)
|
|
|
|
async def term_end_action(self):
|
|
msg: str = "the term has ended"
|
|
print(msg)
|
|
|
|
def get_election_cycle_name(self) -> str:
|
|
"""
|
|
Builds the unique name of the current election cycle
|
|
|
|
Returns:
|
|
str: the name of the election cycle
|
|
"""
|
|
|
|
return f"{self.election_start.year} {self.elecion_cycle.name} election"
|
|
|
|
def get_election_info(self) -> ElectionInformation:
|
|
"""
|
|
Gets information for current election.
|
|
|
|
Returns:
|
|
ElectionInformation: The information from the database about the current election.
|
|
"""
|
|
|
|
with Session(engine) as session:
|
|
stmt = select(ElectionInformation).where(
|
|
ElectionInformation.ElectionCycle == self.get_election_cycle_name()
|
|
)
|
|
return session.scalar(stmt)
|