"""Contains commands and views for request commands.""" import nextcord from nextcord.ext import commands from sqlalchemy.orm import Session from dakiny_bot.DakinySettings import settings from dakiny_bot.database.sql_data_classes import Presences, engine class RequestCog(commands.Cog, name="Request Commands"): """Class holds request commands.""" def __init__(self, bot: commands.Bot) -> None: """Default constructor for RequestCog class. Does nothing.""" self.bot: commands.Bot = bot @nextcord.slash_command() async def request(self, interaction: nextcord.Interaction) -> None: """Parent slash command for request. Never called.""" @request.subcommand(description="Request to add a presence to the bot's presence list.") async def add_presence( self, interaction: nextcord.Interaction, presence: str = nextcord.SlashOption( required=True, min_length=1, max_length=100, description="The presence you want to add.", ), ) -> None: """ Sends a message to admins to request to add a presence. Args: interaction (nextcord.Interaction): Interaction that invoked the command. presence (str): The presence to add. """ content = f'<@{interaction.user.id}> would like to add presence "{presence}."' view = PresenceChange(presence) await self.bot.get_channel(settings.channel_ids.admin).send(content=content, view=view) await interaction.response.send_message("Request sent to admins.", ephemeral=True) @request.subcommand(description="Request to change your Dakiny nickname") async def change_nickname( self, interaction: nextcord.Interaction, new_nickname: str = nextcord.SlashOption( required=True, min_length=2, max_length=32, description="Your requested new nickname.", ), ) -> None: """ Sends a message to admins to request a nickname change. Args: interaction (nextcord.Interaction): Interaction that invoked the command. new_nickname(str): The username to change to. """ content = f'<@{interaction.user.id}> would like to change their username to "{new_nickname}."' view = UsernameRequest(interaction.user.id, new_nickname) await self.bot.get_channel(settings.channel_ids.admin).send(content=content, view=view) await interaction.response.send_message("Request sent to admins.", ephemeral=True) class UsernameRequest(nextcord.ui.View): """View provides approve and deny buttons and action for a username change request.""" def __init__( self, user_id: int, new_nickname: str, ): super().__init__(timeout=None, auto_defer=True) self.user_id = user_id self.new_nickname = new_nickname @nextcord.ui.button(label="Approve", style=nextcord.ButtonStyle.green) async def approve(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002 """ Approve button for a nickname change request. Changes the target's nickname to self.new_nickname. Catches an error if the target as a higher role than the bot. Removes the view from the interaction message. Args: button (nextcord.ui.Button): Unused. interaction (nextcord.Interaction): The interaction of the user clicking the button. """ user = interaction.guild.get_member(self.user_id) if user is not None: try: await user.edit(nick=self.new_nickname) content = interaction.message.content + f"\nApproved by <@{interaction.user.id}>." await interaction.response.edit_message(content=content, view=None) except nextcord.errors.Forbidden: await interaction.response.send_message( content="Please change manually.", ephemeral=True, ) content = ( interaction.message.content + "\n\nFailed. User has too high permissions for bot to change nickname." ) await interaction.followup.edit_message(interaction.message.id, content=content, view=None) else: await interaction.response.edit_message( content="An error occurred while changing the user's nickname.", view=None, ) @nextcord.ui.button(label="Deny", style=nextcord.ButtonStyle.red) async def deny(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002 """ Deny button for a nickname request. Just removes the view and logs who denied the request. Args: button (nextcord.ui.Button): Unused. interaction (nextcord.Interaction): The interaction of the user clicking the button. """ content = interaction.message.content + f"\nDenied by <@{interaction.user.id}>." await interaction.response.edit_message(content=content, view=None) class PresenceChange(nextcord.ui.View): """View provides approve and deny buttons and action for a username change request.""" def __init__( self, presence: str, ): super().__init__(timeout=None, auto_defer=True) self.presence = presence @nextcord.ui.button(label="Approve", style=nextcord.ButtonStyle.green) async def approve(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002 """ Approve button for a presence add request. Adds the presence to the database. Removes the view from the interaction message. Args: button (nextcord.ui.Button): Unused. interaction (nextcord.Interaction): The interaction of the user clicking the button. """ with Session(engine) as session: session.add(Presences(Presence=self.presence)) session.commit() content = interaction.message.content + f"\nApproved by <@{interaction.user.id}>." await interaction.response.edit_message(content=content, view=None) @nextcord.ui.button(label="Deny", style=nextcord.ButtonStyle.red) async def deny(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002 """ Deny button for a presence add request. Just removes the view and logs who denied the request. Args: button (nextcord.ui.Button): Unused. interaction (nextcord.Interaction): The interaction of the user clicking the button. """ content = interaction.message.content + f"\nDenied by <@{interaction.user.id}>." await interaction.response.edit_message(content=content, view=None)