diff --git a/cogs/commands/settings_management.py b/cogs/commands/settings_management.py index 13f2820..bca7364 100644 --- a/cogs/commands/settings_management.py +++ b/cogs/commands/settings_management.py @@ -159,8 +159,36 @@ class SettingsManagementCog(commands.Cog, name="Settings Management"): f"Category pad length set to {length} for {group.GroupName}", 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), + ) -> None: + """ + Changes guild's username length limit. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command + length (int): Number of characters. Is SlashOption. Defaults to 12. + """ + + stmt = ( + select(CategoryGroup) + .where(CategoryGroup.GuildId == interaction.guild_id) + .where(CategoryGroup.GroupId == int(group_id)) + ) + group = session.scalar(stmt) + group.UsernameLength = length + session.commit() + await interaction.response.send_message(f"Username length set to {length}.", ephemeral=True) + @group_output_channel.on_autocomplete("group_id") @category_pad_length.on_autocomplete("group_id") + @username_length.on_autocomplete("group_id") async def group_id_autocomplete(self, interaction: nextcord.Interaction, group_id: str): """ Sends results from autofill_groups back to group_output_channel for autocompletion of group_id. @@ -170,23 +198,3 @@ class SettingsManagementCog(commands.Cog, name="Settings Management"): group_id (str): String to run autocompletion against. """ await interaction.response.send_autocomplete(autofill_groups(interaction.guild_id, group_id)) - - @set.subcommand(description="Set username length. Limits all submissions to this length.") - async def username_length( - self, - interaction: nextcord.Interaction, - length: int = nextcord.SlashOption(description="Number of characters.", required=True, default=12), - ) -> None: - """ - Changes guild's username length limit. - - Args: - interaction (nextcord.Interaction): Interaction that invoked the command - length (int): Number of charactesr. Is SlashOption. Defaults to 12. - """ - - stmt = select(Guild).where(Guild.GuildId == interaction.guild_id) - guild = session.scalar(stmt) - guild.UsernameLength = length - session.commit() - await interaction.response.send_message(f"Username length set to {length}", ephemeral=True) diff --git a/cogs/commands/views/update_username_verify.py b/cogs/commands/views/update_username_verify.py index 23ec00c..b3d539c 100644 --- a/cogs/commands/views/update_username_verify.py +++ b/cogs/commands/views/update_username_verify.py @@ -1,7 +1,7 @@ """View for allowing a username update.""" import nextcord -from sqlalchemy import distinct, select +from sqlalchemy import distinct, exc, select # pylint: disable=import-error from utilities.sql_alchemy_connection import Category, CategoryGroup, Score, session @@ -42,25 +42,33 @@ class UpdateUsernameVerifyView(nextcord.ui.View): button (nextcord.ui.Button): unused interaction (nextcord.Interaction): Interaction with the button """ - embed_content = interaction.message.embeds[0].to_dict() - old_username: str = embed_content["fields"][0]["value"] - new_username: str = embed_content["fields"][1]["value"] - stmt = select(distinct(Score.CategoryId)).where(Score.UserName == old_username) - category_ids: "list[int]" = list(session.scalars(stmt)) + try: + embed_content = interaction.message.embeds[0].to_dict() + old_username: str = embed_content["fields"][0]["value"] + new_username: str = embed_content["fields"][1]["value"] - stmt = select(Score).where(Score.UserName == old_username) - for score in session.scalars(stmt): - score.UserName = new_username - session.commit() + stmt = select(distinct(Score.CategoryId)).where(Score.UserName == old_username) + category_ids: "list[int]" = list(session.scalars(stmt)) - group_ids = select(Category.GroupId).where(Category.CategoryId.in_(category_ids)) + stmt = select(Score).where(Score.UserName == old_username) + for score in session.scalars(stmt): + score.UserName = new_username + session.commit() - stmt = select(CategoryGroup).where(CategoryGroup.GroupId.in_(group_ids)) + group_ids = select(Category.GroupId).where(Category.CategoryId.in_(category_ids)) - for group in session.scalars(stmt): - await send_highscore_message(interaction.guild.get_channel(group.ChannelId), group) + stmt = select(CategoryGroup).where(CategoryGroup.GroupId.in_(group_ids)) - content = interaction.message.content - content += f"\nApproved by <@{interaction.user.id}>." - await interaction.message.edit(content=content, embeds=interaction.message.embeds, view=None) + for group in session.scalars(stmt): + await send_highscore_message(interaction.guild.get_channel(group.ChannelId), group) + + content = interaction.message.content + content += f"\nApproved by <@{interaction.user.id}>." + await interaction.message.edit(content=content, embeds=interaction.message.embeds, view=None) + except exc.DataError: + session.rollback() + content = interaction.message.content + content += "\nError, UserName is too long." + await interaction.message.edit(content=content, embeds=interaction.message.embeds, view=None) + await interaction.response.send_message(content="User must resubmit with shorter name.", ephemeral=True) diff --git a/utilities/utils.py b/utilities/utils.py index 11e8b79..8c1c336 100644 --- a/utilities/utils.py +++ b/utilities/utils.py @@ -176,7 +176,6 @@ def format_highscore_message(group: CategoryGroup) -> str: ret_string = f"**{group.GroupName}**\n```" stmt = select(Guild).where(Guild.GuildId == group.GuildId) - guild = session.scalars(stmt).one() # Get all categories in the group subq = ( @@ -201,13 +200,12 @@ def format_highscore_message(group: CategoryGroup) -> str: category_ids.append(cat.CategoryId) # get all scores in category group, load into data frame. - # FIXME there is some slice warning here from pandas. d_f = pd.read_sql_query(sql=session.query(Score).where(Score.CategoryId.in_(category_ids)).statement, con=engine) # this list is what will be printed in the discord message # first string will be category list, others will be score printouts str_list: "list[str]" = ["" for i in range(max_cat_size + 1)] - groups = d_f.groupby("CategoryId") + groups_df = d_f.groupby("CategoryId") # TODO figure out how to have less nests. for category in categories: @@ -215,18 +213,18 @@ def format_highscore_message(group: CategoryGroup) -> str: str_list[0] += f"{category.CategoryName}".ljust(pad_length, " ") # ensure there is data to print - if category.CategoryId in groups.indices: - group = groups.get_group(category.CategoryId) + if category.CategoryId in groups_df.indices: + group_df = groups_df.get_group(category.CategoryId) # process data. Want each group sorted correctly and only top X results processed_group = ( - group.sort_values("Score", ascending=category.IsAscending).head(category.Size).reset_index() + group_df.sort_values("Score", ascending=category.IsAscending).head(category.Size).reset_index() ) # add each score to list for ind in range(max_cat_size): # need to subtract to deal with category name string if ind in processed_group.index: - user_length = guild.UsernameLength + user_length = group.UsernameLength username = processed_group["UserName"][ind][:user_length].ljust(user_length, " ") # get score, pad to correct length