diff --git a/classes/election_cycle.py b/classes/election_cycle.py index 3638217..3197891 100644 --- a/classes/election_cycle.py +++ b/classes/election_cycle.py @@ -12,7 +12,12 @@ from sqlalchemy.orm import Session from classes.nominate_views import NominateView from classes.voting_views import VoteView 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_datetime, get_election_cycle_name @@ -40,9 +45,15 @@ class ElectionCycle: self.term_end: datetime = get_datetime(self.election_cycle.term_end) self.voting_start: datetime = get_datetime(self.election_cycle.voting_start) self.voting_end: datetime = get_datetime(self.election_cycle.voting_end) - self.highcouncil_election_announce: datetime = get_datetime(self.election_cycle.highcouncil_election_announce) - self.highcouncil_election_start: datetime = get_datetime(self.election_cycle.highcouncil_election_start) - self.highcouncil_election_end: datetime = get_datetime(self.election_cycle.highcouncil_election_end) + self.highcouncil_election_announce: datetime = get_datetime( + self.election_cycle.highcouncil_election_announce + ) + self.highcouncil_election_start: datetime = get_datetime( + self.election_cycle.highcouncil_election_start + ) + self.highcouncil_election_end: datetime = get_datetime( + self.election_cycle.highcouncil_election_end + ) self.guild: nextcord.Guild = guild self.election_over: bool = False @@ -55,11 +66,15 @@ class ElectionCycle: long. """ - with open("bot_messages/election_announcement.txt", mode="r", encoding="utf8") as file: + 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) % len(self.config.election_cycles)].election_start + self.config.election_cycles[ + (self.cycle + 1) % len(self.config.election_cycles) + ].election_start ) message = message.format( @@ -84,14 +99,22 @@ class ElectionCycle: str: Message to send. """ - with open("bot_messages/highcouncil_election.txt", mode="r", encoding="utf8") as file: + 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"), + 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=self.term_start.strftime("%B %d"), ) @@ -103,7 +126,9 @@ class ElectionCycle: str: Message to send. """ - with open("bot_messages/highcouncil_vote.txt", mode="r", encoding="utf8") as file: + with open( + "bot_messages/highcouncil_vote.txt", mode="r", encoding="utf8" + ) as file: message = file.read() return message.format( @@ -121,7 +146,9 @@ class ElectionCycle: 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) + 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, @@ -140,7 +167,11 @@ class ElectionCycle: await self.election_start_action() elif today.date() == self.voting_start.date(): await self.voting_start_action() - elif (self.voting_end - timedelta(3)).date() <= today.date() < self.voting_end.date(): + elif ( + (self.voting_end - timedelta(3)).date() + <= today.date() + < self.voting_end.date() + ): await self.election_reminder() elif today.date() == self.voting_end.date(): await self.voting_end_action() @@ -154,15 +185,21 @@ class ElectionCycle: 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) + parent: nextcord.TextChannel = self.guild.get_channel( + self.config.params.voting_parent_id + ) quarter_name: str = get_election_cycle_name(self.config) + thread_msg: nextcord.Message = await parent.send(content=quarter_name) + # create new entry into database. - election_channel: nextcord.TextChannel = await category.create_text_channel(quarter_name) - clan_member_role: nextcord.Role = self.guild.get_role(self.config.params.clan_member_role_id) - await election_channel.set_permissions(clan_member_role, add_reactions=True) + thread: nextcord.Thread = await parent.create_thread( + name=quarter_name, message=thread_msg + ) with Session(engine) as session: - new_cycle = ElectionInformation(ElectionCycle=quarter_name, ElectionChannel=election_channel.id) + new_cycle = ElectionInformation( + ElectionCycle=quarter_name, ThreadId=thread.id + ) session.add(new_cycle) session.commit() @@ -173,9 +210,9 @@ class ElectionCycle: for index, message in enumerate(messages): # if last item, add the nominate button if index + 1 == len(messages): - await election_channel.send(message, view=NominateView(self.config)) + await thread.send(message, view=NominateView(self.config)) else: - await election_channel.send(message) + await thread.send(message) async def voting_start_action(self) -> None: """ @@ -183,30 +220,35 @@ class ElectionCycle: Removes write permission from the general clan member role. """ message = self.build_vote_start() - clan_member_role: nextcord.Role = self.guild.get_role(self.config.params.clan_member_role_id) - election_channel: nextcord.TextChannel = self.guild.get_channel(self.get_election_info().ElectionChannel) - await election_channel.send(message) - vote_msg = await election_channel.send(build_votes_str(self.config), view=VoteView(self.config, self.guild)) + election_thread: nextcord.Thread = self.guild.get_thread( + self.get_election_info().ThreadId + ) + await election_thread.send(message) + vote_msg = await election_thread.send( + build_votes_str(self.config), view=VoteView(self.config, self.guild) + ) with Session(engine) as session: stmt = select(ElectionInformation).where( - ElectionInformation.ElectionCycle == get_election_cycle_name(self.config) + ElectionInformation.ElectionCycle + == get_election_cycle_name(self.config) ) info = session.scalar(stmt) info.CouncilVoteMsgId = vote_msg.id session.commit() - 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) - election_channel: nextcord.TextChannel = self.guild.get_channel(self.get_election_info().ElectionChannel) - clan_member_role: nextcord.Role = self.guild.get_role(self.config.params.clan_member_role_id) + council_elect_role: nextcord.Role = self.guild.get_role( + self.config.params.clan_council_elect_role_id + ) + election_thread: nextcord.Thread = self.guild.get_thread( + self.get_election_info().ThreadId + ) # remove vote button from vote message election_name = get_election_cycle_name(self.config) @@ -215,7 +257,7 @@ class ElectionCycle: ElectionInformation.ElectionCycle == election_name ) vote_msg_id = session.scalar(stmt) - vote_msg: nextcord.Message = await election_channel.fetch_message(vote_msg_id) + vote_msg: nextcord.Message = await election_thread.fetch_message(vote_msg_id) await vote_msg.edit(view=None) # add the highcouncil role to everyone with 3 or more votes. set elected to true in database @@ -238,9 +280,7 @@ class ElectionCycle: await user.add_roles(council_elect_role) - await election_channel.send(message) - await election_channel.set_permissions(council_elect_role, send_messages=True, add_reactions=True) - await election_channel.set_permissions(clan_member_role, add_reactions=False) + await election_thread.send(message) async def highcouncil_election_start_action(self) -> None: """ @@ -248,19 +288,27 @@ class ElectionCycle: """ message = self.build_highcouncil_vote_start() - election_channel: nextcord.TextChannel = self.guild.get_channel(self.get_election_info().ElectionChannel) - await election_channel.send(message) + election_thread: nextcord.Thread = self.guild.get_thread( + self.get_election_info().ThreadId + ) + await election_thread.send(message) async def term_start_action(self) -> None: """ - Moves the election channel into the archive category. + Marks the election as over. """ self.election_over = True - election_channel: nextcord.TextChannel = self.guild.get_channel(self.get_election_info().ElectionChannel) - archive: nextcord.CategoryChannel = self.guild.get_channel(self.config.params.archive_channel_group_id) - await election_channel.move(beginning=True, category=archive) + election_thread: nextcord.Thread = self.guild.get_thread( + self.get_election_info().ThreadId + ) + + await election_thread.send( + "This election cycle is now over. Thank you everyone for participating!" + ) + + await election_thread.edit(archived=True, locked=True) def get_election_info(self) -> ElectionInformation: """ @@ -272,7 +320,8 @@ class ElectionCycle: with Session(engine) as session: stmt = select(ElectionInformation).where( - ElectionInformation.ElectionCycle == get_election_cycle_name(self.config) + ElectionInformation.ElectionCycle + == get_election_cycle_name(self.config) ) return session.scalar(stmt) @@ -281,9 +330,11 @@ class ElectionCycle: Sends a message to general chat reminder clan about election. """ - general: nextcord.TextChannel = self.guild.get_channel(self.config.params.general_channel_id) + general: nextcord.TextChannel = self.guild.get_channel( + self.config.params.general_channel_id + ) message = f"Reminder to <@&{self.config.params.clan_member_role_id}>! Clan elections are happening! Head over " - message += f"to <#{self.get_election_info().ElectionChannel}> to cast your vote!" + message += f"to <#{self.get_election_info().ThreadId}> to cast your vote!" await general.send(content=message) diff --git a/cogs/commands/test.py b/cogs/commands/test.py index 1838b08..8d91434 100644 --- a/cogs/commands/test.py +++ b/cogs/commands/test.py @@ -35,6 +35,7 @@ class TestCog(commands.Cog, name="Test commands."): """ @test.subcommand() + @is_me() async def msg_builder(self, interaction: nextcord.Interaction): """ Tests the message builder. @@ -52,6 +53,7 @@ class TestCog(commands.Cog, name="Test commands."): await interaction.channel.send(content=m) @test.subcommand() + @is_me() async def election_start(self, interaction: nextcord.Interaction): """ idc @@ -61,10 +63,15 @@ class TestCog(commands.Cog, name="Test commands."): """ config: DakinyConfig = self.bot.config - cycle = ElectionCycle(get_current_cycle(config), config, self.bot.get_guild(config.params.guild_id)) + cycle = ElectionCycle( + get_current_cycle(config), + config, + self.bot.get_guild(config.params.guild_id), + ) await cycle.election_start_action() @test.subcommand() + @is_me() async def voting_start(self, interaction: nextcord.Interaction): """ tests the voting start action @@ -73,10 +80,15 @@ class TestCog(commands.Cog, name="Test commands."): interaction (nextcord.Interaction): _description_ """ config: DakinyConfig = self.bot.config - cycle = ElectionCycle(get_current_cycle(config), config, self.bot.get_guild(config.params.guild_id)) + cycle = ElectionCycle( + get_current_cycle(config), + config, + self.bot.get_guild(config.params.guild_id), + ) await cycle.voting_start_action() @test.subcommand() + @is_me() async def voting_end(self, interaction: nextcord.Interaction): """ tests the voting start action @@ -85,17 +97,42 @@ class TestCog(commands.Cog, name="Test commands."): interaction (nextcord.Interaction): _description_ """ config: DakinyConfig = self.bot.config - cycle = ElectionCycle(get_current_cycle(config), config, self.bot.get_guild(config.params.guild_id)) + cycle = ElectionCycle( + get_current_cycle(config), + config, + self.bot.get_guild(config.params.guild_id), + ) await cycle.voting_end_action() @test.subcommand() + @is_me() async def election_reminder(self, interaction: nextcord.Interaction): config: DakinyConfig = self.bot.config - cycle = ElectionCycle(get_current_cycle(config), config, self.bot.get_guild(config.params.guild_id)) + cycle = ElectionCycle( + get_current_cycle(config), + config, + self.bot.get_guild(config.params.guild_id), + ) await cycle.election_reminder() @test.subcommand() + @is_me() async def daily(self, interaction: nextcord.Interaction): config: DakinyConfig = self.bot.config - cycle = ElectionCycle(get_current_cycle(config), config, self.bot.get_guild(config.params.guild_id)) + cycle = ElectionCycle( + get_current_cycle(config), + config, + self.bot.get_guild(config.params.guild_id), + ) await cycle.check_date() + + @test.subcommand() + @is_me() + async def term_start(self, interaction: nextcord.Interaction): + config: DakinyConfig = self.bot.config + cycle = ElectionCycle( + get_current_cycle(config), + config, + self.bot.get_guild(config.params.guild_id), + ) + await cycle.term_start_action() diff --git a/config.py b/config.py index 1dfc500..f7f10b1 100644 --- a/config.py +++ b/config.py @@ -22,6 +22,7 @@ class Params: general_channel_id: int guild_id: int high_council_role_id: int + voting_parent_id: int @dataclass diff --git a/database_setup/database.sql b/database_setup/database.sql index 299e621..64f77a9 100644 --- a/database_setup/database.sql +++ b/database_setup/database.sql @@ -1,6 +1,6 @@ CREATE TABLE ElectionInformation( ElectionCycle varchar(30) not null unique, - ElectionChannel bigint unsigned not null, + ThreadId bigint unsigned not null, CouncilVoteMsgId bigint unsigned, PRIMARY KEY (ElectionCycle) );