"""Set command hierarchy.""" import nextcord from nextcord.ext import commands from sqlalchemy import select from sqlalchemy.orm import Session from sqlmodel import col from database.db import engine from database.models import CategoryGroup, Guild from utilities.utils import MAX_LINE_LENGTH, autofill_groups class SetCog(commands.Cog, name="Set command."): """Class holds commands for setting variables in guild's database.""" def __init__(self) -> None: """Default constructor for SetCog class. Does nothing.""" @nextcord.slash_command(default_member_permissions=nextcord.Permissions(administrator=True)) async def set(self, interaction: nextcord.Interaction) -> None: """Parent slash command for setting settings. Never called.""" @set.subcommand(description="Registers the channel for a Category Group's messages.") async def group_output_channel( self, interaction: nextcord.Interaction, group_id: str = nextcord.SlashOption( name="group", description="Category Group to assign to channel.", required=True ), channel: nextcord.abc.GuildChannel | None = nextcord.SlashOption( description="Channel to register", required=False, channel_types=[nextcord.ChannelType.text], default=None, ), ) -> None: """ Command function to register a CategoryGroup's output channel. Args: interaction (nextcord.Interaction): Interaction that invoked the command. group_id (str): String representation of Group id to register channel to. Is SlashOption. channel (nextcord.abc.GuildChannel, optional): Channel to register Is a SlashOption. Limited to text channels, Defaults to None. """ channel_id = interaction.channel.id if not channel else channel.id with Session(engine) as session: stmt = ( select(CategoryGroup) .where(col(CategoryGroup.guild_id) == interaction.guild_id) .where(col(CategoryGroup.id) == int(group_id)) ) if (group := session.scalar(stmt)) is None: await interaction.response.send_message("Group or Category was not found.", ephemeral=True) return group.channel_id = channel_id session.commit() await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) @set.subcommand( description="Set character length for a category. Can cut off username/score. Affects all categories." ) async def pad_length( self, interaction: nextcord.Interaction, group_id: str = nextcord.SlashOption( name="group", description="Category Group to assign pad length to.", required=True ), length: int = nextcord.SlashOption( description="Number of characters alloted to a category.", required=True, default=26, min_value=7, max_value=MAX_LINE_LENGTH, ), ) -> None: """ Changes guild's category pad length. Args: interaction (nextcord.Interaction): Interaction that invoked the command group_id (str): String representation of Group id to set pad length in. Is SlashOption. length (int): Number of characters. Is SlashOption. Defaults to 26. """ with Session(engine) as session: stmt = ( select(CategoryGroup) .where(col(CategoryGroup.guild_id) == interaction.guild_id) .where(col(CategoryGroup.id) == int(group_id)) ) if (group := session.scalar(stmt)) is None: await interaction.response.send_message("Group or Category was not found.", ephemeral=True) return group.pad_length = length session.commit() await interaction.response.send_message( f"Category pad length set to {length} for {group.name}", ephemeral=True ) @set.subcommand( description="Registers the channel for submission messages. Currently this information is deprecated." ) async def submission_channel( self, interaction: nextcord.Interaction, channel: nextcord.abc.GuildChannel | None = nextcord.SlashOption( description="Channel to register", required=False, channel_types=[nextcord.ChannelType.text], default=None, ), ) -> None: """ Command function to register the submission message channel. Args: interaction (nextcord.Interaction): Interaction that invoked the command channel (nextcord.abc.GuildChannel): Channel to register Is a SlashOption. Limited to text channels, Defaults to None. """ channel_id = interaction.channel.id if not channel else channel.id with Session(engine) as session: stmt = select(Guild).where(col(Guild.id) == interaction.guild_id) if (guild := session.scalar(stmt)) is None: await interaction.response.send_message("Guild was not found.", ephemeral=True) return guild.submission_channel = channel_id session.commit() await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) @set.subcommand(description="Set username length for a Group of Categories.") async def username_length( self, interaction: nextcord.Interaction, group_id: str = nextcord.SlashOption( name="group", description="Group to change username length of.", required=True ), length: int = nextcord.SlashOption( description="Number of characters.", required=True, default=12, min_value=1, max_value=30 ), ) -> None: """ Changes guild's username length limit. Args: interaction (nextcord.Interaction): Interaction that invoked the command group_id (str): String representation of Group id to set username length in. Is SlashOption. length (int): Number of characters. Is SlashOption. Defaults to 12. """ with Session(engine) as session: stmt = ( select(CategoryGroup) .where(col(CategoryGroup.guild_id) == interaction.guild_id) .where(col(CategoryGroup.id) == int(group_id)) ) if (group := session.scalar(stmt)) is None: await interaction.response.send_message("Group or Category was not found.", ephemeral=True) return group.username_length = length session.commit() await interaction.response.send_message(f"Username length set to {length}.", ephemeral=True) @set.subcommand(description="Registers the channel for verification messages.") async def verify_channel( self, interaction: nextcord.Interaction, channel: nextcord.abc.GuildChannel | None = nextcord.SlashOption( description="Channel to register", required=False, channel_types=[nextcord.ChannelType.text], default=None, ), ) -> None: """ Command function to register the verification message channel. Args: interaction (nextcord.Interaction): Interaction that invoked the command channel (Optional[nextcord.abc.GuildChannel]): Channel to register Is a SlashOption. Limited to text channels, Defaults to None. """ channel_id = interaction.channel.id if not channel else channel.id with Session(engine) as session: stmt = select(Guild).where(col(Guild.id) == interaction.guild_id) if (guild := session.scalar(stmt)) is None: await interaction.response.send_message("Guild was not found.", ephemeral=True) return guild.verification_channel = channel_id session.commit() await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) @group_output_channel.on_autocomplete("group_id") @pad_length.on_autocomplete("group_id") @username_length.on_autocomplete("group_id") async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str) -> None: """ Sends results from autofill_groups back to group_output_channel for autocompletion of group_id. Args: interaction (nextcord.Interaction): Interaction with command. group_id (str): String to run autocompletion against. """ await interaction.response.send_autocomplete(autofill_groups(interaction.guild_id, group_id))