""" Commands for managing/displaying the highscores messages. """ from typing import Optional import nextcord from nextcord.ext import commands from sqlalchemy import select # pylint: disable=import-error from cogs.submission.submission_views import SubmissionCreateButton from utilities.sql_alchemy_connection import CategoryGroup, session from utilities.utils import autofill_groups, send_highscore_message class MessageManagementCog(commands.Cog, name="Message Management"): """ Class holds commands for managing the messages that display highscores. """ def __init__(self, bot: commands.Bot) -> None: """ Default constructor for MessageManagement class Args: bot (commands.Bot): Bot object. Required to register submission button view. """ self.bot = bot @nextcord.slash_command( description="Clears highscores channel of all table messages. Does not change data.", default_member_permissions=nextcord.Permissions(administrator=True), ) async def delete_channel_messages( self, interaction: nextcord.Interaction, channel: Optional[nextcord.abc.GuildChannel] = nextcord.SlashOption( description="Channel to clear of messages.", required=False, channel_types=[nextcord.ChannelType.text], default=None, ), ) -> None: """ Deletes all group messages from channel. Does not change data. Does not delete highscores channel id. Uses current channel if not supplied a channel. Args: interaction (nextcord.Interaction): Interaction that invoked the command channel (Optional[nextcord.abc.GuildChannel], optional): Channel to clear of messages. Is a SlashOption. Limited to text channels. Defaults to None. """ if not channel: channel = interaction.channel stmt = ( select(CategoryGroup) .where(CategoryGroup.GuildId == interaction.guild_id) .where(CategoryGroup.ChannelId == channel.id) ) # TODO test when nothing in channel groups = session.scalars(stmt) await interaction.response.defer(ephemeral=True) for group in groups: try: table_message: nextcord.Message = await channel.fetch_message(group.MessageId) await table_message.delete() except nextcord.NotFound: # silently ignore that messages are not found. They got deleted already. pass await interaction.send("Table messages deleted.", ephemeral=True) @nextcord.slash_command( description="Triggers post/update of highscores to registered highscore channel.", default_member_permissions=nextcord.Permissions(administrator=True), ) async def post_highscore_groups(self, interaction: nextcord.Interaction) -> None: """ A command which posts the highscore in the registered channel. Sends warning if no channel has been registered. Either creates new messages for each table if one doesn't exist or edits the existing message. Args: interaction (nextcord.Interaction): Interaction that invoked the command. """ stmt = select(CategoryGroup).where(CategoryGroup.GuildId == interaction.guild_id) # awaiting response because posting scores takes a while await interaction.response.defer(ephemeral=True) for group in session.scalars(stmt): channel = interaction.guild.get_channel(group.ChannelId) # Error checking for registered highscore channel error_response = "Registered Highscores channel does not exist or was never registered. " error_response += 'Use "/register" to register channels.' assert channel is not None, await interaction.response(error_response, ephemeral=True) message: nextcord.Message = await send_highscore_message(channel, group) await message.edit(view=SubmissionCreateButton(self.bot)) await interaction.send(f"Posted all groups in {interaction.guild.name}'s highscores.", ephemeral=True) @nextcord.slash_command( description="Manually refresh a table. Use when changing settings or data manually changed.", default_member_permissions=nextcord.Permissions(administrator=True), ) async def refresh_group( self, interaction: nextcord.Interaction, group_id: Optional[int] = nextcord.SlashOption(description="Name of table.", required=True), ) -> None: """ Refreshes a table given by user. Args: interaction (nextcord.Interaction): Interaction that invoked the command. group_id (Optional[int]): Group id to refresh. Not optional. Is SlashOption. """ stmt = ( select(CategoryGroup) .where(CategoryGroup.GuildId == interaction.guild_id) .where(CategoryGroup.GroupId == group_id) ) group = session.scalar(stmt) channel = interaction.guild.get_channel(group.ChannelId) message: nextcord.Message = await send_highscore_message(channel, group) await message.edit(view=SubmissionCreateButton(self.bot)) await interaction.response.send_message(f"Updated table {group.GroupName}!", ephemeral=True) @refresh_group.on_autocomplete("group_id") async def refresh_table_autofill(self, interaction: nextcord.Interaction, group_id: str): """ Collects list of table names and compares to input table name for autocomplete assistance. Args: interaction (nextcord.Interaction): Interaction with command. group_id (str): String to run autocomplete compared to. """ await interaction.response.send_autocomplete(autofill_groups(interaction.guild_id, group_id))