diff --git a/bot_messages/council_members.txt b/bot_messages/council_members.txt index 093aee1..d0eeb86 100644 --- a/bot_messages/council_members.txt +++ b/bot_messages/council_members.txt @@ -1,7 +1,8 @@ -Here's the {quarter} Clan Council: - -Dakiny Council: -{council} +Here's the **{quarter}** Clan Council: Dakiny High Council: -{high_council} \ No newline at end of file +<@{clan_leader}> - Clan Leader +<@{discord_manager}> - Discord Manager + +Dakiny Council: +{council} \ No newline at end of file diff --git a/classes/election_cycle.py b/classes/election_cycle.py index ef73269..a60cdd4 100644 --- a/classes/election_cycle.py +++ b/classes/election_cycle.py @@ -23,6 +23,7 @@ from database_setup.sql_data_classes import ( from utils import ( build_highcouncil_votes_str, build_votes_str, + edit_clan_council_info, get_cl_election_name, get_datetime, get_dm_election_name, @@ -437,6 +438,7 @@ class ElectionCycle: ) await election_thread.edit(archived=True, locked=True) + await edit_clan_council_info(self.guild, self.config) def get_election_info(self) -> ElectionInformation: """ diff --git a/cogs/commands/__init__.py b/cogs/commands/__init__.py index 725f143..df6a0c2 100644 --- a/cogs/commands/__init__.py +++ b/cogs/commands/__init__.py @@ -21,7 +21,7 @@ def setup(bot: commands.Bot): """ bot.add_cog(RecordCog(bot)) - bot.add_cog(RefreshCog()) + bot.add_cog(RefreshCog(bot)) bot.add_cog(RemoveCog()) bot.add_cog(RequestCog(bot)) bot.add_cog(TestCog(bot)) diff --git a/cogs/commands/refresh.py b/cogs/commands/refresh.py index e04b067..cadc1a5 100644 --- a/cogs/commands/refresh.py +++ b/cogs/commands/refresh.py @@ -5,7 +5,7 @@ Contained commands and views for refresh commands. import nextcord from nextcord.ext import commands -from utils import update_clan_messages +from utils import edit_clan_council_info, update_clan_messages class RefreshCog(commands.Cog, name="Refresh Commands"): @@ -13,6 +13,13 @@ class RefreshCog(commands.Cog, name="Refresh Commands"): Class holds refresh commands. """ + def __init__(self, bot) -> None: + """ + Default constructor for RefreshCog class. Does nothing. + """ + super().__init__() + self.bot: commands.Bot = bot + @nextcord.slash_command( default_member_permissions=nextcord.Permissions(administrator=True) ) @@ -32,3 +39,16 @@ class RefreshCog(commands.Cog, name="Refresh Commands"): await interaction.response.defer(ephemeral=True) await update_clan_messages(interaction.guild) await interaction.followup.send("Messages have been refreshed.", ephemeral=True) + + @refresh.subcommand(description="Updates the current council info message.") + async def council_info(self, interaction: nextcord.Interaction): + """ + Calls edit_clan_council_info(). + + Args: + interaction (nextcord.Interaction): Interaction with the command. + """ + await edit_clan_council_info(interaction.guild, self.bot.config) + await interaction.response.send_message( + "Clan Council Info message updated.", ephemeral=True + ) diff --git a/utils.py b/utils.py index b462915..0dbbfdb 100644 --- a/utils.py +++ b/utils.py @@ -6,7 +6,7 @@ import os from datetime import datetime import nextcord -from sqlalchemy import select, update +from sqlalchemy import select, true, update from sqlalchemy.orm import Session from config import DakinyConfig @@ -397,11 +397,10 @@ async def update_clan_messages(guild: nextcord.Guild): Updates all clan messages to contents in MESSAGES_DIR. Does not to any git work. Is expected to be called after git is pulled. - for ever directory, sort the files by number then post - posting involves checking if there is a message for that particular file then editing it or creating a - new one. the message could be deleted, which would cause a new message to be sent and database updated. + for ever directory, sort the files by number then edits/sends the message. Channel fetching/management is handled by another function. + Message editing and sending is handled by another function. Args: guild (nextcord.Guild): Guild object that all channels and messages belong to. @@ -426,27 +425,9 @@ async def update_clan_messages(guild: nextcord.Guild): message_name = f"{dir_name}/{file_name}" file_path = f"{dir_path}/{file_name}" with open(file_path, "r", encoding="utf8") as reader: - stmt = select(Messages.Id).where(Messages.Path == message_name) - msg_id = session.scalar(stmt) - if msg_id is None: - # don't have a message for this file - msg = await channel.send(reader.read(2000)) - new_message = Messages(Path=message_name, Id=msg.id) - session.add(new_message) - session.commit() - else: - try: - msg: nextcord.Message = await channel.fetch_message(msg_id) - await msg.edit(reader.read(2000)) - except nextcord.NotFound: - msg = await channel.send(reader.read(2000)) - stmt = ( - update(Messages) - .where(Messages.Path == message_name) - .values(Id=msg.id) - ) - session.execute(stmt) - session.commit() + await edit_clan_message( + session, channel, message_name, reader.read(2000) + ) async def get_clan_message_channel( @@ -508,3 +489,97 @@ async def get_clan_message_channel( session.execute(stmt) session.commit() return ret_channel + + +async def edit_clan_message( + session: Session, + channel: nextcord.TextChannel, + message_name: str, + message_content: str, +): + """ + Obtains a message id from database. If no id, then need to send a new message and record the id. + If there is a message, then edit the message. If that message is not found in discord, then need to + send a new message and record the id in the database. + + Args: + session (Session): Open connection to database. + channel (nextcord.TextChannel): Channel object that message belongs to. + message_name (str): Name of the message. Corresponds to the file that contains message content. + message_content (str): Content of the message to edit/send. + """ + stmt = select(Messages.Id).where(Messages.Path == message_name) + msg_id = session.scalar(stmt) + if msg_id is None: + # don't have a message for this file + msg = await channel.send(message_content) + new_message = Messages(Path=message_name, Id=msg.id) + session.add(new_message) + session.commit() + else: + try: + msg: nextcord.Message = await channel.fetch_message(msg_id) + await msg.edit(message_content) + except nextcord.NotFound: + msg = await channel.send(message_content) + stmt = ( + update(Messages).where(Messages.Path == message_name).values(Id=msg.id) + ) + session.execute(stmt) + session.commit() + + +async def edit_clan_council_info(guild: nextcord.Guild, config: DakinyConfig): + """ + Gets the winners of the elections and updates the perminant message that states the current council. + + Args: + guild (nextcord.Guild): Guild object that to use to get channel. + config (DakinyConfig): Configs + """ + clan_info_channel: nextcord.TextChannel = await guild.fetch_channel( + config.params.clan_info_channel_id + ) + + election = get_election_cycle_name(config) + with Session(engine) as session: + stmt = ( + select(CouncilMembers.MemberId) + .where(CouncilMembers.ElectionCycle == election) + .where(CouncilMembers.DiscordManager == true()) + ) + discord_manager = session.scalar(stmt) + stmt = ( + select(CouncilMembers.MemberId) + .where(CouncilMembers.ElectionCycle == election) + .where(CouncilMembers.ClanLeader == true()) + ) + clan_leader = session.scalar(stmt) + stmt = ( + select(CouncilMembers.MemberId) + .where(CouncilMembers.ElectionCycle == election) + .where(CouncilMembers.Elected == true()) + ) + + council_members_strs = [ + f"<@{id}>" + for id in session.scalars(stmt) + if id not in (discord_manager, clan_leader) + ] + + quarter = get_cycle_name(config) + + with open( + "bot_messages/council_members.txt", mode="r", encoding="utf8" + ) as file: + message = file.read() + message = message.format( + quarter=quarter, + council="\n".join(council_members_strs), + clan_leader=clan_leader, + discord_manager=discord_manager, + ) + + await edit_clan_message( + session, clan_info_channel, "council_members.txt", message + )