From ea0ebcc2e9c48392e7772cd28fc4111cd61ee8e2 Mon Sep 17 00:00:00 2001 From: alwayscompiling Date: Thu, 1 Dec 2022 18:06:43 -0500 Subject: [PATCH] Update data management to use new database. --- cogs/commands/data_management.py | 146 ++++++++++++--------------- cogs/commands/settings_management.py | 2 +- 2 files changed, 67 insertions(+), 81 deletions(-) diff --git a/cogs/commands/data_management.py b/cogs/commands/data_management.py index 8bce454..d1f80ec 100644 --- a/cogs/commands/data_management.py +++ b/cogs/commands/data_management.py @@ -6,12 +6,15 @@ from typing import Optional import nextcord from nextcord.ext import commands +from sqlalchemy import distinct, select -from highscores import highscores_data # pylint: disable=import-error -from utilities.utils import ( # pylint: disable=import-error +# pylint: disable=import-error +from highscores import Category, CategoryGroup, Guild, Score, session +from utilities.utils import ( autofill_categories, - autofill_tables, - autofill_users, + autofill_groups, + autofill_users_in_group_category, + autofill_users_in_guild, send_highscore_message, ) @@ -42,27 +45,6 @@ class DataManagementCog(commands.Cog, name="Table Management"): Parent slash command for deleting things. Never called. """ - @delete.subcommand(description="Deletes all scores for this guild. Used for testing. Do Not Use.") - async def scores(self, interaction: nextcord.Interaction): - """ - Warning: This command only works for developers. - - A command which deletes all scores in all tables for this guild. - Command limits to admins to prevent devs from usings on non-test servers. - """ - # only allow AlwaysCompiling to use. - # If you are a developer and want to use command, can add name to list - if interaction.user.id == 206602713511886849: - for table in highscores_data.get_guild(interaction.guild_id).tables: - for category in table.categories: - category.clear() - highscores_data.save_guild_data(highscores_data.get_guild(interaction.guild_id)) - await interaction.response.send_message(f"Cleared score data for {interaction.guild.name}.", ephemeral=True) - else: - await interaction.response.send_message( - "You shouldn't be using this command. Deletes everything.", ephemeral=True - ) - @delete.subcommand() async def user(self, interaction: nextcord.Interaction): """ @@ -76,7 +58,7 @@ class DataManagementCog(commands.Cog, name="Table Management"): self, interaction: nextcord.Interaction, username: str = nextcord.SlashOption( - description="User to remove scores for. Note: This is not always a user's discord name." + description="User to remove scores for. Note: This is not always a user's discord name.", required=True ), ): """ @@ -87,90 +69,82 @@ class DataManagementCog(commands.Cog, name="Table Management"): interaction (nextcord.Interaction): Interaction that invoked the command. username (str): User to remove from highscores """ - guild = highscores_data.get_guild(interaction.guild_id) - user_was_found: bool = False + stmt = select(distinct(Score.CategoryId)).where(Score.UserName == username) + category_ids: "list[int]" = list(session.scalars(stmt)) - # remove user from all tables and categories - for table in guild.tables: - table_updated: bool = False - for category in table.categories: - # user has a score in category - if category.remove_score(username): - user_was_found = True - table_updated = True + stmt = select(Score).where(Score.UserName == username) + for score in session.scalars(stmt): + session.delete(score) - if table_updated: - await send_highscore_message(interaction.guild.get_channel(guild.highscore_channel), guild, table) + group_ids = select(Category.GroupId).where(Category.CategoryId.in_(category_ids)).subquery() - if not user_was_found: - await interaction.send(f'User "{username}" was not found.', ephemeral=True) - else: - await interaction.send(f'User "{username}" was removed from all tables.') - highscores_data.save_guild_data(guild) + stmt = select(CategoryGroup).where(CategoryGroup.GroupId.in_(group_ids)) + + for group in session.scalars(stmt): + await send_highscore_message(interaction.guild.get_channel(group.ChannelId), group) + + await interaction.send(f'User "{username}" was removed from all tables.') @user.subcommand(description="Deletes a user's scores from a category.") async def from_category( self, interaction: nextcord.Interaction, - table_name: str = nextcord.SlashOption(description="Table to delete user from.", required=True), - category_name: str = nextcord.SlashOption(description="Category to delete user from.", required=True), + group_id: int = nextcord.SlashOption(description="Group to delete user from.", required=True), + category_id: int = nextcord.SlashOption(description="Category to delete user from.", required=True), user_name: str = nextcord.SlashOption(description="User to delete.", required=True), ): """ - Removes a user from a category. Uses autofill functions to fill out table_name, category_name, and user_name. + Removes a user from a category. Uses autofill functions to fill out group_id, category_name, and user_name. Args: interaction (nextcord.Interaction): Interaction that invoked the command. - table_name (str): Table to remove user from. Is SlashOption. - category_name (str): Category to remove user from. Is SlashOption. + group_id (int): Group to remove user from. Is SlashOption. + category_id (int): Category to remove user from. Is SlashOption. user_name (str): The user to remove. Is SlashOption. """ - guild = highscores_data.get_guild(interaction.guild_id) + stmt = select(CategoryGroup).where(CategoryGroup.GroupId == group_id) + group = session.scalar(stmt) + stmt = select(Score).where(Score.CategoryId == category_id) - try: - guild.get_table(table_name).get_category(category_name).remove_score(user_name) - await send_highscore_message( - interaction.guild.get_channel(guild.highscore_channel), guild, guild.get_table(table_name) - ) - await interaction.response.send_message( - f'User "{user_name}" removed from "{category_name}".', ephemeral=True - ) + for score in session.scalars(stmt): + session.delete(score) + session.commit() - except nextcord.errors.ApplicationInvokeError: - await interaction.response.send_message("Invalid parameter(s).", ephemeral=True) + await send_highscore_message(interaction.guild.get_channel(group.ChannelId), group) + await interaction.response.send_message(f'User "{user_name}" removed from "{category_id}".', ephemeral=True) - @user.subcommand(description="Deletes a user's scores from entire table.") - async def from_table( + @user.subcommand(description="Deletes a user's scores from entire group.") + async def from_group( self, interaction: nextcord.Interaction, - table_name: str = nextcord.SlashOption(description="Table to delete user from.", required=True), + group_id: int = nextcord.SlashOption(description="Group to delete user from.", required=True), user_name: str = nextcord.SlashOption(description="User to delete.", required=True), ): """ - Removes user from a table. Uses autofill functions to fill out table_name and user_name. + Removes user from a goup. Uses autofill functions to fill out group_id and user_name. Args: interaction (nextcord.Interaction): Interaction that invoked the command. - table_name (str): Table to remove user from. Is SlashOption. + group_id (int): Group to remove user from. Is SlashOption. user_name (str): The user to remove. Is SlashOption. """ - guild = highscores_data.get_guild(interaction.guild_id) - try: - for category in guild.get_table(table_name).categories: - category.remove_score(user_name) - await send_highscore_message( - interaction.guild.get_channel(guild.highscore_channel), guild, guild.get_table(table_name) - ) - await interaction.response.send_message(f'User "{user_name}" removed from all categories.', ephemeral=True) + stmt = select(CategoryGroup).where(CategoryGroup.GroupId == group_id) + group = session.scalar(stmt) + category_ids = select(Category.Id).where(Category.GroupId == group_id).subquery() + stmt = select(Score).where(Score.CategoryId.in_(category_ids)).where(Score.UserName == user_name) - except nextcord.errors.ApplicationInvokeError: - await interaction.response.send_message("Invalid parameter(s).", ephemeral=True) + for score in session.scalars(stmt): + session.delete(score) + session.commit() + + await send_highscore_message(interaction.guild.get_channel(group.ChannelId), group) + await interaction.response.send_message(f'User "{user_name}" removed from all categories.', ephemeral=True) @from_category.on_autocomplete("table_name") - @from_table.on_autocomplete("table_name") + @from_group.on_autocomplete("table_name") async def autocomplete_table(self, interaction: nextcord.Interaction, table_name: str): """ Autocomplete function for table names. @@ -179,7 +153,7 @@ class DataManagementCog(commands.Cog, name="Table Management"): interaction (nextcord.Interaction): Interaction that invoked the command. table_name (str): String to be autocompleted with Table name. """ - await interaction.response.send_autocomplete(autofill_tables(interaction.guild_id, table_name)) + await interaction.response.send_autocomplete(autofill_groups(interaction.guild_id, table_name)) @from_category.on_autocomplete("category_name") async def autocomplete_category(self, interaction: nextcord.Interaction, category_name: str, table_name: str): @@ -196,7 +170,7 @@ class DataManagementCog(commands.Cog, name="Table Management"): ) @from_category.on_autocomplete("user_name") - @from_table.on_autocomplete("user_name") + @from_group.on_autocomplete("user_name") async def autocomplete_user( self, interaction: nextcord.Interaction, user_name: str, table_name: str, category_name: Optional[str] ): @@ -210,7 +184,7 @@ class DataManagementCog(commands.Cog, name="Table Management"): category_name (Optional[str]): Category to find User from, can be None. """ await interaction.response.send_autocomplete( - autofill_users(interaction.guild_id, table_name, category_name, user_name) + autofill_users_in_group_category(interaction.guild_id, table_name, category_name, user_name) ) @nextcord.slash_command(description="Request a username update. Admins must approve.") @@ -229,8 +203,8 @@ class DataManagementCog(commands.Cog, name="Table Management"): old_username (str): Username to replace. new_username (str): Username to replace old with. """ - guild = highscores_data.get_guild(interaction.guild_id) - verify_channel = interaction.guild.get_channel(guild.verification_channel) + stmt = select(Guild.VerificationChannel).where(Guild.GuildId == interaction.guild_id) + verify_channel = interaction.guild.get_channel(session.scalar(stmt)) embed: nextcord.Embed = nextcord.Embed(title="Username change request.") embed.add_field(name="Old Username", value=old_username) @@ -241,3 +215,15 @@ class DataManagementCog(commands.Cog, name="Table Management"): view=UpdateUsernameVerifyView(), ) await interaction.send("Request sent to admins for verification.", ephemeral=True) + + @update_username.on_autocomplete("old_username") + @from_all.on_autocomplete("username") + async def username_autofill(self, interaction: nextcord.Interaction, username: str): + """ + Sends response from autofill_users_in_guild back to update_username for autocompletion of old_username. + + Args: + interaction (nextcord.Interaction): Interaction with command. + old_username (str): String to run autocompletion against. + """ + await interaction.response.send_autocomplete(autofill_users_in_guild(interaction.guild_id, username)) diff --git a/cogs/commands/settings_management.py b/cogs/commands/settings_management.py index c69e173..d40cb5f 100644 --- a/cogs/commands/settings_management.py +++ b/cogs/commands/settings_management.py @@ -157,7 +157,7 @@ class SettingsManagementCog(commands.Cog, name="Settings Management"): @category_pad_length.on_autocomplete("category_group") async def group_id_autocomplete(self, interaction: nextcord.Interaction, category_group: str): """ - Sends results from autofill_groups back to group_output_channel for autocompletion of categoru_group. + Sends results from autofill_groups back to group_output_channel for autocompletion of category_group. Args: interaction (nextcord.Interaction): Interaction with command.