From 6e25d4e75a511a879d53296d9b27c22b7a76ab4a Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 5 Mar 2025 10:49:46 -0500 Subject: [PATCH 01/37] Move the logger into own module for importing. --- cogs/commands/submission.py | 4 ++-- main.py | 13 ++++--------- utilities/logger.py | 10 ++++++++++ 3 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 utilities/logger.py diff --git a/cogs/commands/submission.py b/cogs/commands/submission.py index fab15dc..6a57008 100644 --- a/cogs/commands/submission.py +++ b/cogs/commands/submission.py @@ -11,7 +11,7 @@ from sqlmodel import col from cogs.submission.verification_view import VerificationView from database.db import engine from database.models import Category, CategoryGroup, Guild, Submission -from main import logger +from main import agon_logger from utilities.utils import autofill_categories, autofill_groups, submit_score @@ -108,7 +108,7 @@ class SubmissionCog(commands.Cog): if not isinstance(channel, nextcord.TextChannel): await interaction.response.send_message("An error happened with submission.") - logger.error( + agon_logger.error( "Channel id %s in guild %s is does not correspond to a TextChannel.", channel.id, channel.guild.id ) return diff --git a/main.py b/main.py index 639d6c8..4dcb589 100644 --- a/main.py +++ b/main.py @@ -8,6 +8,7 @@ import nextcord from nextcord.ext import commands from utilities import config +from utilities.logger import agon_logger nextcord_logger = logging.getLogger("nextcord") nextcord_logger.setLevel(logging.DEBUG) @@ -15,18 +16,12 @@ nextcord_handler = logging.FileHandler(filename="nextcord.log", encoding="utf-8" nextcord_handler.setFormatter(logging.Formatter("%(asctime)s:%(levelname)s:%(name)s: %(message)s")) nextcord_logger.addHandler(nextcord_handler) -logger = logging.getLogger("default") -logger.setLevel(logging.INFO) -handler = logging.StreamHandler(sys.stdout) -handler.setFormatter(logging.Formatter("%(asctime)s:%(levelname)s:%(name)s: %(message)s")) -logger.addHandler(handler) - def main() -> None: """Main function for bot.""" min_python_version = (3, 12) if sys.version_info < min_python_version: - logger.error("ERROR: Python version must be >= 3.12") + agon_logger.error("ERROR: Python version must be >= 3.12") sys.exit() # Allows privileged intents for monitoring members joining, roles editing, and role assignments @@ -46,9 +41,9 @@ def main() -> None: async def on_ready() -> None: """When Discord is connected.""" if bot.user is None: - logger.error("Discord connection failed.") + agon_logger.error("Discord connection failed.") return - logger.info("%s has connected to Discord!", bot.user.name) + agon_logger.info("%s has connected to Discord!", bot.user.name) # Run Discord bot bot.run(config.DISCORD_TOKEN) diff --git a/utilities/logger.py b/utilities/logger.py new file mode 100644 index 0000000..b8fb2a6 --- /dev/null +++ b/utilities/logger.py @@ -0,0 +1,10 @@ +"""Creates logger for Agon bot.""" + +import logging +import sys + +agon_logger = logging.getLogger("default") +agon_logger.setLevel(logging.INFO) +handler = logging.StreamHandler(sys.stdout) +handler.setFormatter(logging.Formatter("%(asctime)s:%(levelname)s:%(name)s: %(message)s")) +agon_logger.addHandler(handler) From d703c767048166477ecc608a1048f40dc5cd28df Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 5 Mar 2025 11:02:09 -0500 Subject: [PATCH 02/37] Add a command to set the category size. --- cogs/commands/set.py | 66 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index d2bd194..1179eed 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -7,8 +7,9 @@ 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 +from database.models import Category, CategoryGroup, Guild +from utilities.logger import agon_logger +from utilities.utils import MAX_LINE_LENGTH, autofill_categories, autofill_groups, send_highscore_message class SetCog(commands.Cog, name="Set command."): @@ -21,6 +22,50 @@ class SetCog(commands.Cog, name="Set command."): async def set(self, interaction: nextcord.Interaction) -> None: """Parent slash command for setting settings. Never called.""" + @set.subcommand(description="") + async def category_size( + self, + interaction: nextcord.Interaction, + group_id: str = nextcord.SlashOption( + name="group", description="Category Group that Category is in.", required=True + ), + category_id: str = nextcord.SlashOption( + name="category", description="Category to update size of.", required=True + ), + size: int = nextcord.SlashOption(description="Number of entries to show for the category.", required=True), + ) -> None: + """ + Command to update a category's size. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + group_id (str): String representation of Group id to register channel to. Is SlashOption. + category_id (str): String representation of Category id to register channel to. Is SlashOption. + size (int): Size to set. Is SlashOption. + """ + stmt = select(Category).where(col(CategoryGroup.id == group_id)).where(col(Category.id) == int(category_id)) + + with Session(engine) as session: + category = session.scalar(stmt) + if category is None: + await interaction.response.send_message("Category or Group was not found.", ephemeral=True) + return + category.size = size + # session.add(category) test if this is needed. SQLAlchemy can do the update without adding. + session.commit() + + # Use the relationship to get group category is in. + group = category.category_group + if group is None: + await interaction.response.send_message( + f"An error with {category.name} and group relationship. Contact developer.", ephemeral=True + ) + agon_logger.error(f"{category.name}:{category.id} group relationship was None.") + return + + await send_highscore_message(session, interaction.guild, group) + await interaction.response.send_message(f"{category.name} size has been updated to {size}.", ephemeral=True) + @set.subcommand(description="Registers the channel for a Category Group's messages.") async def group_output_channel( self, @@ -41,7 +86,7 @@ class SetCog(commands.Cog, name="Set command."): 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 + 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 @@ -183,6 +228,21 @@ class SetCog(commands.Cog, name="Set command."): session.commit() await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) + @category_size.on_autocomplete("category_id") + async def category_autocomplete(self, interaction: nextcord.Interaction, category_id: str, group_id: str) -> None: + """ + Autocomplete function for category names. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + category_id (str): String to be autocompleted with Category name. + group_id (str): Group to find Category from. + """ + await interaction.response.send_autocomplete( + autofill_categories(interaction.guild_id, int(group_id), category_id) + ) + + @category_size.on_autocomplete("group_id") @group_output_channel.on_autocomplete("group_id") @pad_length.on_autocomplete("group_id") @username_length.on_autocomplete("group_id") From f37844c953bff71daad9f83ef94111753544c4a0 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 5 Mar 2025 11:05:07 -0500 Subject: [PATCH 03/37] Update error message. --- cogs/commands/set.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index 1179eed..f1a5994 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -58,7 +58,8 @@ class SetCog(commands.Cog, name="Set command."): group = category.category_group if group is None: await interaction.response.send_message( - f"An error with {category.name} and group relationship. Contact developer.", ephemeral=True + f"An error with {category.name} and group relationship. Contact developer. Size was still updated.", + ephemeral=True, ) agon_logger.error(f"{category.name}:{category.id} group relationship was None.") return From e2ddd5412a1a420f7e28aa4ca978b4311ccc3536 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 5 Mar 2025 15:27:57 -0500 Subject: [PATCH 04/37] Add set is_ascending command. --- cogs/commands/set.py | 54 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index f1a5994..9decf06 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -103,6 +103,58 @@ class SetCog(commands.Cog, name="Set command."): session.commit() await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) + @set.subcommand(description="") + async def is_ascending( + self, + interaction: nextcord.Interaction, + group_id: str = nextcord.SlashOption( + name="group", description="Category Group that Category is in.", required=True + ), + category_id: str = nextcord.SlashOption( + name="category", description="Category to update is_ascending of.", required=True + ), + ascending: bool = nextcord.SlashOption( # noqa: FBT001 + description="Whether the scores are sorted ascending or not.", required=True + ), + ) -> None: + """ + Command to update a category's is_ascending boolean. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + group_id (str): String representation of Group id to register channel to. Is SlashOption. + category_id (str): String representation of Category id to register channel to. Is SlashOption. + ascending (bool): Boolean to set. Determines whether scores are sorted ascending or not. Is SlashOption. + """ + stmt = select(Category).where(col(CategoryGroup.id == group_id)).where(col(Category.id) == int(category_id)) + + with Session(engine) as session: + category = session.scalar(stmt) + if category is None: + await interaction.response.send_message("Category or Group was not found.", ephemeral=True) + return + category.is_ascending = ascending + # session.add(category) test if this is needed. SQLAlchemy can do the update without adding. + session.commit() + + # Use the relationship to get group category is in. + group = category.category_group + if group is None: + await interaction.response.send_message( + ( + f"An error with {category.name} and group relationship. Contact developer. " + "Is_ascending was still updated." + ), + ephemeral=True, + ) + agon_logger.error(f"{category.name}:{category.id} group relationship was None.") + return + + await send_highscore_message(session, interaction.guild, group) + await interaction.response.send_message( + f"{category.name} is_ascending has been updated to {ascending}.", ephemeral=True + ) + @set.subcommand( description="Set character length for a category. Can cut off username/score. Affects all categories." ) @@ -230,6 +282,7 @@ class SetCog(commands.Cog, name="Set command."): await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) @category_size.on_autocomplete("category_id") + @is_ascending.on_autocomplete("category_id") async def category_autocomplete(self, interaction: nextcord.Interaction, category_id: str, group_id: str) -> None: """ Autocomplete function for category names. @@ -245,6 +298,7 @@ class SetCog(commands.Cog, name="Set command."): @category_size.on_autocomplete("group_id") @group_output_channel.on_autocomplete("group_id") + @is_ascending.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: From 8674eed0c57aa1d8a8ea3375a872e1b437f5820f Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 5 Mar 2025 15:32:20 -0500 Subject: [PATCH 05/37] Forgot a command description. --- cogs/commands/set.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index 9decf06..c437d95 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -103,7 +103,7 @@ class SetCog(commands.Cog, name="Set command."): session.commit() await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) - @set.subcommand(description="") + @set.subcommand(description="Update the is_ascending value for a category.") async def is_ascending( self, interaction: nextcord.Interaction, From 0ff1b0709699f1f74d7df4bcb5d785e8f3ac4f9b Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 5 Mar 2025 15:47:01 -0500 Subject: [PATCH 06/37] Add category and group subcommand structure. --- cogs/commands/set.py | 94 +++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index c437d95..94b3f7e 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -22,7 +22,11 @@ class SetCog(commands.Cog, name="Set command."): async def set(self, interaction: nextcord.Interaction) -> None: """Parent slash command for setting settings. Never called.""" - @set.subcommand(description="") + @set.subcommand("Commands for editing a category.") + async def category(self, interaction: nextcord.Interaction) -> None: + """Parent slash subcommand for setting category settings. Never called.""" + + @category.subcommand(description="Update the number of entries to show for a category.", name="size") async def category_size( self, interaction: nextcord.Interaction, @@ -67,43 +71,7 @@ class SetCog(commands.Cog, name="Set command."): await send_highscore_message(session, interaction.guild, group) await interaction.response.send_message(f"{category.name} size has been updated to {size}.", ephemeral=True) - @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)) - ) - group = session.scalar(stmt) - group.ChannelId = channel_id - session.commit() - await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) - - @set.subcommand(description="Update the is_ascending value for a category.") + @category.subcommand(description="Update the is_ascending value for a category.") async def is_ascending( self, interaction: nextcord.Interaction, @@ -155,15 +123,51 @@ class SetCog(commands.Cog, name="Set command."): f"{category.name} is_ascending has been updated to {ascending}.", ephemeral=True ) - @set.subcommand( + @set.subcommand(description="Commands for editing a group.") + async def group(self, interaction: nextcord.Interaction) -> None: + """Parent slash subcommand for setting group settings. Never called.""" + + @group.subcommand(description="Registers the channel for a Group's messages.") + async def output_channel( + self, + interaction: nextcord.Interaction, + group_id: str = nextcord.SlashOption(name="group", description="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)) + ) + group = session.scalar(stmt) + group.ChannelId = channel_id + session.commit() + await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) + + @group.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 - ), + group_id: str = nextcord.SlashOption(name="group", description="Group to assign pad length to.", required=True), length: int = nextcord.SlashOption( description="Number of characters alloted to a category.", required=True, @@ -193,7 +197,7 @@ class SetCog(commands.Cog, name="Set command."): f"Category pad length set to {length} for {group.name}", ephemeral=True ) - @set.subcommand( + @group.subcommand( description="Registers the channel for submission messages. Currently this information is deprecated." ) async def submission_channel( @@ -223,7 +227,7 @@ class SetCog(commands.Cog, name="Set command."): session.commit() await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) - @set.subcommand(description="Set username length for a Group of Categories.") + @group.subcommand(description="Set username length for a Group of Categories.") async def username_length( self, interaction: nextcord.Interaction, @@ -297,7 +301,7 @@ class SetCog(commands.Cog, name="Set command."): ) @category_size.on_autocomplete("group_id") - @group_output_channel.on_autocomplete("group_id") + @output_channel.on_autocomplete("group_id") @is_ascending.on_autocomplete("group_id") @pad_length.on_autocomplete("group_id") @username_length.on_autocomplete("group_id") From feeb47d3da9d09882778f42929ffffc004ae0063 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 7 Mar 2025 11:24:45 -0500 Subject: [PATCH 07/37] Update the message when updating pad length. --- cogs/commands/set.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index 94b3f7e..2750b0c 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -191,11 +191,15 @@ class SetCog(commands.Cog, name="Set command."): .where(col(CategoryGroup.id) == int(group_id)) ) group = session.scalar(stmt) + if group is None: + await interaction.response.send_message("Group was not found.", ephemeral=True) + return group.PadLength = length session.commit() await interaction.response.send_message( f"Category pad length set to {length} for {group.name}", ephemeral=True ) + await send_highscore_message(session, interaction.guild, group) @group.subcommand( description="Registers the channel for submission messages. Currently this information is deprecated." From f61ad83e11308981af607c3017c8dd51c6b9c75f Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 7 Mar 2025 11:39:39 -0500 Subject: [PATCH 08/37] Make commands more robust against errors. --- cogs/commands/set.py | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index 2750b0c..d3ce18e 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -58,15 +58,16 @@ class SetCog(commands.Cog, name="Set command."): # session.add(category) test if this is needed. SQLAlchemy can do the update without adding. session.commit() - # Use the relationship to get group category is in. - group = category.category_group - if group is None: - await interaction.response.send_message( - f"An error with {category.name} and group relationship. Contact developer. Size was still updated.", - ephemeral=True, - ) - agon_logger.error(f"{category.name}:{category.id} group relationship was None.") - return + # Use the relationship to get group category is in. + group = category.category_group + if group is None: + agon_logger.error(f"{category.name}:{category.id} group relationship was None.") + + stmt = select(CategoryGroup).where(col(CategoryGroup.id) == group_id) + group = session.scalar(stmt) + if group is None: + await interaction.response.send_message("Group was not found.", ephemeral=True) + return await send_highscore_message(session, interaction.guild, group) await interaction.response.send_message(f"{category.name} size has been updated to {size}.", ephemeral=True) @@ -105,18 +106,16 @@ class SetCog(commands.Cog, name="Set command."): # session.add(category) test if this is needed. SQLAlchemy can do the update without adding. session.commit() - # Use the relationship to get group category is in. - group = category.category_group - if group is None: - await interaction.response.send_message( - ( - f"An error with {category.name} and group relationship. Contact developer. " - "Is_ascending was still updated." - ), - ephemeral=True, - ) - agon_logger.error(f"{category.name}:{category.id} group relationship was None.") - return + # Use the relationship to get group category is in. + group = category.category_group + if group is None: + agon_logger.error(f"{category.name}:{category.id} group relationship was None.") + + stmt = select(CategoryGroup).where(col(CategoryGroup.id) == group_id) + group = session.scalar(stmt) + if group is None: + await interaction.response.send_message("Group was not found.", ephemeral=True) + return await send_highscore_message(session, interaction.guild, group) await interaction.response.send_message( From 6e02bc877f18f68611ae7c55530d4c244479159f Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 7 Mar 2025 11:40:27 -0500 Subject: [PATCH 09/37] Only want a warning as I can get the group another way. --- cogs/commands/set.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index d3ce18e..15d1ea3 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -61,7 +61,7 @@ class SetCog(commands.Cog, name="Set command."): # Use the relationship to get group category is in. group = category.category_group if group is None: - agon_logger.error(f"{category.name}:{category.id} group relationship was None.") + agon_logger.warning(f"{category.name}:{category.id} group relationship was None.") stmt = select(CategoryGroup).where(col(CategoryGroup.id) == group_id) group = session.scalar(stmt) @@ -109,7 +109,7 @@ class SetCog(commands.Cog, name="Set command."): # Use the relationship to get group category is in. group = category.category_group if group is None: - agon_logger.error(f"{category.name}:{category.id} group relationship was None.") + agon_logger.warning(f"{category.name}:{category.id} group relationship was None.") stmt = select(CategoryGroup).where(col(CategoryGroup.id) == group_id) group = session.scalar(stmt) From 2649ceb6bb19ce38d54fec3aa18f89cc3363eee1 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 7 Mar 2025 11:45:05 -0500 Subject: [PATCH 10/37] Add command to edit is_validated. --- cogs/commands/set.py | 57 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index 15d1ea3..eb4cd2c 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -47,7 +47,7 @@ class SetCog(commands.Cog, name="Set command."): category_id (str): String representation of Category id to register channel to. Is SlashOption. size (int): Size to set. Is SlashOption. """ - stmt = select(Category).where(col(CategoryGroup.id == group_id)).where(col(Category.id) == int(category_id)) + stmt = select(Category).where(col(CategoryGroup.id) == group_id).where(col(Category.id) == int(category_id)) with Session(engine) as session: category = session.scalar(stmt) @@ -95,7 +95,7 @@ class SetCog(commands.Cog, name="Set command."): category_id (str): String representation of Category id to register channel to. Is SlashOption. ascending (bool): Boolean to set. Determines whether scores are sorted ascending or not. Is SlashOption. """ - stmt = select(Category).where(col(CategoryGroup.id == group_id)).where(col(Category.id) == int(category_id)) + stmt = select(Category).where(col(CategoryGroup.id) == group_id).where(col(Category.id) == int(category_id)) with Session(engine) as session: category = session.scalar(stmt) @@ -122,6 +122,55 @@ class SetCog(commands.Cog, name="Set command."): f"{category.name} is_ascending has been updated to {ascending}.", ephemeral=True ) + @category.subcommand(description="Update the is_validated value for a category.") + async def is_validated( + self, + interaction: nextcord.Interaction, + group_id: str = nextcord.SlashOption( + name="group", description="Category Group that Category is in.", required=True + ), + category_id: str = nextcord.SlashOption( + name="category", description="Category to update is_ascending of.", required=True + ), + validated: bool = nextcord.SlashOption( # noqa: FBT001 + description="Whether the scores need to be validated.", required=True + ), + ) -> None: + """ + Command to update a category's is_validated boolean. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + group_id (str): String representation of Group id to register channel to. Is SlashOption. + category_id (str): String representation of Category id to register channel to. Is SlashOption. + validated (bool): Boolean to set. Determines whether scores are validated or not. Is SlashOption. + """ + stmt = select(Category).where(col(CategoryGroup.id) == group_id).where(col(Category.id) == int(category_id)) + + with Session(engine) as session: + category = session.scalar(stmt) + if category is None: + await interaction.response.send_message("Category or Group was not found.", ephemeral=True) + return + category.is_validated = validated + # session.add(category) test if this is needed. SQLAlchemy can do the update without adding. + session.commit() + + # Use the relationship to get group category is in. + group = category.category_group + if group is None: + agon_logger.warning(f"{category.name}:{category.id} group relationship was None.") + + stmt = select(CategoryGroup).where(col(CategoryGroup.id) == group_id) + group = session.scalar(stmt) + if group is None: + await interaction.response.send_message("Group was not found.", ephemeral=True) + return + + await interaction.response.send_message( + f"{category.name} is_validated has been updated to {validated}.", ephemeral=True + ) + @set.subcommand(description="Commands for editing a group.") async def group(self, interaction: nextcord.Interaction) -> None: """Parent slash subcommand for setting group settings. Never called.""" @@ -290,6 +339,7 @@ class SetCog(commands.Cog, name="Set command."): @category_size.on_autocomplete("category_id") @is_ascending.on_autocomplete("category_id") + @is_validated.on_autocomplete("category_id") async def category_autocomplete(self, interaction: nextcord.Interaction, category_id: str, group_id: str) -> None: """ Autocomplete function for category names. @@ -304,8 +354,9 @@ class SetCog(commands.Cog, name="Set command."): ) @category_size.on_autocomplete("group_id") - @output_channel.on_autocomplete("group_id") @is_ascending.on_autocomplete("group_id") + @is_validated.on_autocomplete("group_id") + @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: From 81ae867a430b7368951e0f020ac2703777782939 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 7 Mar 2025 12:56:45 -0500 Subject: [PATCH 11/37] Add set group and category name commands. --- cogs/commands/set.py | 94 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 11 deletions(-) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index eb4cd2c..684f951 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -30,9 +30,7 @@ class SetCog(commands.Cog, name="Set command."): async def category_size( self, interaction: nextcord.Interaction, - group_id: str = nextcord.SlashOption( - name="group", description="Category Group that Category is in.", required=True - ), + group_id: str = nextcord.SlashOption(name="group", description="Group that Category is in.", required=True), category_id: str = nextcord.SlashOption( name="category", description="Category to update size of.", required=True ), @@ -69,16 +67,14 @@ class SetCog(commands.Cog, name="Set command."): await interaction.response.send_message("Group was not found.", ephemeral=True) return - await send_highscore_message(session, interaction.guild, group) + await send_highscore_message(session, interaction.guild, group) await interaction.response.send_message(f"{category.name} size has been updated to {size}.", ephemeral=True) @category.subcommand(description="Update the is_ascending value for a category.") async def is_ascending( self, interaction: nextcord.Interaction, - group_id: str = nextcord.SlashOption( - name="group", description="Category Group that Category is in.", required=True - ), + group_id: str = nextcord.SlashOption(name="group", description="Group that Category is in.", required=True), category_id: str = nextcord.SlashOption( name="category", description="Category to update is_ascending of.", required=True ), @@ -117,7 +113,7 @@ class SetCog(commands.Cog, name="Set command."): await interaction.response.send_message("Group was not found.", ephemeral=True) return - await send_highscore_message(session, interaction.guild, group) + await send_highscore_message(session, interaction.guild, group) await interaction.response.send_message( f"{category.name} is_ascending has been updated to {ascending}.", ephemeral=True ) @@ -126,9 +122,7 @@ class SetCog(commands.Cog, name="Set command."): async def is_validated( self, interaction: nextcord.Interaction, - group_id: str = nextcord.SlashOption( - name="group", description="Category Group that Category is in.", required=True - ), + group_id: str = nextcord.SlashOption(name="group", description="Group that Category is in.", required=True), category_id: str = nextcord.SlashOption( name="category", description="Category to update is_ascending of.", required=True ), @@ -171,10 +165,85 @@ class SetCog(commands.Cog, name="Set command."): f"{category.name} is_validated has been updated to {validated}.", ephemeral=True ) + @category.subcommand(name="name", description="Change the name of a category.") + async def category_name( + self, + interaction: nextcord.Interaction, + group_id: str = nextcord.SlashOption(name="group", description="Group that Category is in.", required=True), + category_id: str = nextcord.SlashOption( + name="category", description="Category to update the name of.", required=True + ), + name: str = nextcord.SlashOption(description="Name to update to.", required=True, min_length=1, max_length=30), + ) -> None: + """ + Command to update a category's name. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + group_id (str): String representation of Group id to register channel to. Is SlashOption. + category_id (str): String representation of Category id to register channel to. Is SlashOption. + name (str): The name to update the category's name to. Is SlashOption. + """ + stmt = select(Category).where(col(CategoryGroup.id) == group_id).where(col(Category.id) == int(category_id)) + + with Session(engine) as session: + category = session.scalar(stmt) + if category is None: + await interaction.response.send_message("Category or Group was not found.", ephemeral=True) + return + old_name = category.name + category.name = name + # session.add(category) test if this is needed. SQLAlchemy can do the update without adding. + session.commit() + + # Use the relationship to get group category is in. + group = category.category_group + if group is None: + agon_logger.warning(f"{category.name}:{category.id} group relationship was None.") + + stmt = select(CategoryGroup).where(col(CategoryGroup.id) == group_id) + group = session.scalar(stmt) + if group is None: + await interaction.response.send_message("Group was not found.", ephemeral=True) + return + + await send_highscore_message(session, interaction.guild, group) + await interaction.response.send_message(f"{old_name} has been updated to {category.name}.", ephemeral=True) + @set.subcommand(description="Commands for editing a group.") async def group(self, interaction: nextcord.Interaction) -> None: """Parent slash subcommand for setting group settings. Never called.""" + @group.subcommand(name="name", description="Change the name of a Group.") + async def group_name( + self, + interaction: nextcord.Interaction, + group_id: str = nextcord.SlashOption(name="group", description="Group that Category is in.", required=True), + name: str = nextcord.SlashOption(description="Name to update to.", required=True, min_length=1, max_length=50), + ) -> None: + """ + Command to update a group's name. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + group_id (str): String representation of Group id to register channel to. Is SlashOption. + name (str): The name to update the group's name to. Is SlashOption. + """ + stmt = select(CategoryGroup).where(col(CategoryGroup.id) == group_id) + + with Session(engine) as session: + group = session.scalar(stmt) + if group is None: + await interaction.response.send_message("Group was not found.", ephemeral=True) + return + old_name = group.name + group.name = name + # session.add(group) test if this is needed. SQLAlchemy can do the update without adding. + session.commit() + + await send_highscore_message(session, interaction.guild, group) + await interaction.response.send_message(f"{old_name} has been updated to {group.name}.", ephemeral=True) + @group.subcommand(description="Registers the channel for a Group's messages.") async def output_channel( self, @@ -337,6 +406,7 @@ class SetCog(commands.Cog, name="Set command."): session.commit() await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) + @category_name.on_autocomplete("category_id") @category_size.on_autocomplete("category_id") @is_ascending.on_autocomplete("category_id") @is_validated.on_autocomplete("category_id") @@ -353,7 +423,9 @@ class SetCog(commands.Cog, name="Set command."): autofill_categories(interaction.guild_id, int(group_id), category_id) ) + @category_name.on_autocomplete("group_id") @category_size.on_autocomplete("group_id") + @group_name.on_autocomplete("group_id") @is_ascending.on_autocomplete("group_id") @is_validated.on_autocomplete("group_id") @output_channel.on_autocomplete("group_id") From 50868988c0d30480a465258d0be5521bf3c2a495 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 7 Mar 2025 15:59:13 -0500 Subject: [PATCH 12/37] Create teh get cog, add it to init for commands. --- cogs/commands/__init__.py | 18 ++++++++++-------- cogs/commands/get.py | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 cogs/commands/get.py diff --git a/cogs/commands/__init__.py b/cogs/commands/__init__.py index 38bffbc..85407e7 100644 --- a/cogs/commands/__init__.py +++ b/cogs/commands/__init__.py @@ -2,14 +2,15 @@ from nextcord.ext import commands -from .create import CreateCog -from .delete import DeleteCog -from .help import HelpCog -from .refresh import RefreshCog -from .set import SetCog -from .submission import SubmissionCog -from .update import UpdateCog -from .view import ViewCog +from cogs.commands.create import CreateCog +from cogs.commands.delete import DeleteCog +from cogs.commands.get import GetCog +from cogs.commands.help import HelpCog +from cogs.commands.refresh import RefreshCog +from cogs.commands.set import SetCog +from cogs.commands.submission import SubmissionCog +from cogs.commands.update import UpdateCog +from cogs.commands.view import ViewCog # This function will be called when this extension is loaded. @@ -18,6 +19,7 @@ def setup(bot: commands.Bot) -> None: """Adds all command classes to bot.""" bot.add_cog(CreateCog(bot)) bot.add_cog(DeleteCog()) + bot.add_cog(GetCog()) bot.add_cog(HelpCog()) bot.add_cog(RefreshCog(bot)) bot.add_cog(SetCog()) diff --git a/cogs/commands/get.py b/cogs/commands/get.py new file mode 100644 index 0000000..0f557b5 --- /dev/null +++ b/cogs/commands/get.py @@ -0,0 +1,15 @@ +"""Get command hierarchy.""" + +import nextcord +from nextcord.ext import commands + + +class GetCog(commands.Cog, name="Get 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 get(self, interaction: nextcord.Interaction) -> None: + """Parent slash command for setting settings. Never called.""" From f9d765ad92763db599349ace736e29beb6013896 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 7 Mar 2025 16:09:33 -0500 Subject: [PATCH 13/37] Forgot to convert some ids to int. --- cogs/commands/set.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index 684f951..9aa84a1 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -45,7 +45,9 @@ class SetCog(commands.Cog, name="Set command."): category_id (str): String representation of Category id to register channel to. Is SlashOption. size (int): Size to set. Is SlashOption. """ - stmt = select(Category).where(col(CategoryGroup.id) == group_id).where(col(Category.id) == int(category_id)) + stmt = ( + select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + ) with Session(engine) as session: category = session.scalar(stmt) @@ -91,7 +93,9 @@ class SetCog(commands.Cog, name="Set command."): category_id (str): String representation of Category id to register channel to. Is SlashOption. ascending (bool): Boolean to set. Determines whether scores are sorted ascending or not. Is SlashOption. """ - stmt = select(Category).where(col(CategoryGroup.id) == group_id).where(col(Category.id) == int(category_id)) + stmt = ( + select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + ) with Session(engine) as session: category = session.scalar(stmt) @@ -139,7 +143,9 @@ class SetCog(commands.Cog, name="Set command."): category_id (str): String representation of Category id to register channel to. Is SlashOption. validated (bool): Boolean to set. Determines whether scores are validated or not. Is SlashOption. """ - stmt = select(Category).where(col(CategoryGroup.id) == group_id).where(col(Category.id) == int(category_id)) + stmt = ( + select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + ) with Session(engine) as session: category = session.scalar(stmt) @@ -184,7 +190,9 @@ class SetCog(commands.Cog, name="Set command."): category_id (str): String representation of Category id to register channel to. Is SlashOption. name (str): The name to update the category's name to. Is SlashOption. """ - stmt = select(Category).where(col(CategoryGroup.id) == group_id).where(col(Category.id) == int(category_id)) + stmt = ( + select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + ) with Session(engine) as session: category = session.scalar(stmt) @@ -229,7 +237,7 @@ class SetCog(commands.Cog, name="Set command."): group_id (str): String representation of Group id to register channel to. Is SlashOption. name (str): The name to update the group's name to. Is SlashOption. """ - stmt = select(CategoryGroup).where(col(CategoryGroup.id) == group_id) + stmt = select(CategoryGroup).where(col(CategoryGroup.id) == int(group_id)) with Session(engine) as session: group = session.scalar(stmt) From 4785271ebbfe3a7e50161a3d347c01ce99b09188 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 7 Mar 2025 16:10:42 -0500 Subject: [PATCH 14/37] Add command to get a category's size. --- cogs/commands/get.py | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/cogs/commands/get.py b/cogs/commands/get.py index 0f557b5..c4f06ac 100644 --- a/cogs/commands/get.py +++ b/cogs/commands/get.py @@ -2,6 +2,10 @@ import nextcord from nextcord.ext import commands +from sqlmodel import Session, col, select + +from database.db import engine +from database.models import Category, CategoryGroup class GetCog(commands.Cog, name="Get command."): @@ -12,4 +16,39 @@ class GetCog(commands.Cog, name="Get command."): @nextcord.slash_command(default_member_permissions=nextcord.Permissions(administrator=True)) async def get(self, interaction: nextcord.Interaction) -> None: - """Parent slash command for setting settings. Never called.""" + """Parent slash command for getting. Never called.""" + + @get.subcommand("Commands for getting category information.") + async def category(self, interaction: nextcord.Interaction) -> None: + """Parent slash subcommand for getting category information. Never called.""" + + @category.subcommand(description="Get the size for a category.") + async def size( + self, + interaction: nextcord.Interaction, + group_id: str = nextcord.SlashOption(name="group", description="Group that Category is in.", required=True), + category_id: str = nextcord.SlashOption(name="category", description="Category to get size of.", required=True), + ) -> None: + """ + Command to view a category's size. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + group_id (str): String representation of Group id to register channel to. Is SlashOption. + category_id (str): String representation of Category id to register channel to. Is SlashOption. + """ + stmt = ( + select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + ) + + with Session(engine) as session: + category = session.scalar(stmt) + if category is None: + await interaction.response.send_message("Group or Category was not found.", ephemeral=True) + return + + await interaction.response.send_message(f"{category.name} has a size of {category.size}.", ephemeral=True) + + @get.subcommand(description="Commands for getting group information.") + async def group(self, interaction: nextcord.Interaction) -> None: + """Parent slash subcommand for getting group information. Never called.""" From 1fcb25193d330000470910c806874e7cb36b4fe2 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Mon, 10 Mar 2025 14:27:24 -0400 Subject: [PATCH 15/37] Add get is_ascending command and autocomplete functions. --- cogs/commands/get.py | 60 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/cogs/commands/get.py b/cogs/commands/get.py index c4f06ac..43f97a0 100644 --- a/cogs/commands/get.py +++ b/cogs/commands/get.py @@ -6,6 +6,7 @@ from sqlmodel import Session, col, select from database.db import engine from database.models import Category, CategoryGroup +from utilities.utils import autofill_categories, autofill_groups class GetCog(commands.Cog, name="Get command."): @@ -18,10 +19,40 @@ class GetCog(commands.Cog, name="Get command."): async def get(self, interaction: nextcord.Interaction) -> None: """Parent slash command for getting. Never called.""" - @get.subcommand("Commands for getting category information.") + @get.subcommand(description="Commands for getting category information.") async def category(self, interaction: nextcord.Interaction) -> None: """Parent slash subcommand for getting category information. Never called.""" + @category.subcommand(description="Get whether a category is sorted in ascending or descending order.") + async def is_ascending( + self, + interaction: nextcord.Interaction, + group_id: str = nextcord.SlashOption(name="group", description="Group that Category is in.", required=True), + category_id: str = nextcord.SlashOption(name="category", description="Category to get size of.", required=True), + ) -> None: + """ + Command to view how a category is sorted. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + group_id (str): String representation of Group id to register channel to. Is SlashOption. + category_id (str): String representation of Category id to register channel to. Is SlashOption. + """ + stmt = ( + select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + ) + + with Session(engine) as session: + category = session.scalar(stmt) + if category is None: + await interaction.response.send_message("Group or Category was not found.", ephemeral=True) + return + + await interaction.response.send_message( + f"{category.name} is sorted in {'ascending' if category.is_ascending else 'descending'} order.", + ephemeral=True, + ) + @category.subcommand(description="Get the size for a category.") async def size( self, @@ -52,3 +83,30 @@ class GetCog(commands.Cog, name="Get command."): @get.subcommand(description="Commands for getting group information.") async def group(self, interaction: nextcord.Interaction) -> None: """Parent slash subcommand for getting group information. Never called.""" + + @is_ascending.on_autocomplete("category_id") + @size.on_autocomplete("category_id") + async def category_autocomplete(self, interaction: nextcord.Interaction, category_id: str, group_id: str) -> None: + """ + Autocomplete function for category names. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + category_id (str): String to be autocompleted with Category name. + group_id (str): Group to find Category from. + """ + await interaction.response.send_autocomplete( + autofill_categories(interaction.guild_id, int(group_id), category_id) + ) + + @is_ascending.on_autocomplete("group_id") + @size.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)) From 84c910b19c1788f87300d8b123b879cbcc80e84a Mon Sep 17 00:00:00 2001 From: imcompiling Date: Mon, 10 Mar 2025 16:06:28 -0400 Subject: [PATCH 16/37] Add get is_validated command. --- cogs/commands/get.py | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/cogs/commands/get.py b/cogs/commands/get.py index 43f97a0..3d5b58d 100644 --- a/cogs/commands/get.py +++ b/cogs/commands/get.py @@ -28,7 +28,9 @@ class GetCog(commands.Cog, name="Get command."): self, interaction: nextcord.Interaction, group_id: str = nextcord.SlashOption(name="group", description="Group that Category is in.", required=True), - category_id: str = nextcord.SlashOption(name="category", description="Category to get size of.", required=True), + category_id: str = nextcord.SlashOption( + name="category", description="Category to information from.", required=True + ), ) -> None: """ Command to view how a category is sorted. @@ -53,6 +55,38 @@ class GetCog(commands.Cog, name="Get command."): ephemeral=True, ) + @category.subcommand(description="Get whether a category required validation.") + async def is_validated( + self, + interaction: nextcord.Interaction, + group_id: str = nextcord.SlashOption(name="group", description="Group that Category is in.", required=True), + category_id: str = nextcord.SlashOption( + name="category", description="Category to information from.", required=True + ), + ) -> None: + """ + Command to view if a category required photo validation. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + group_id (str): String representation of Group id to register channel to. Is SlashOption. + category_id (str): String representation of Category id to register channel to. Is SlashOption. + """ + stmt = ( + select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + ) + + with Session(engine) as session: + category = session.scalar(stmt) + if category is None: + await interaction.response.send_message("Group or Category was not found.", ephemeral=True) + return + + await interaction.response.send_message( + f"{category.name} does {'not ' if not category.is_validated else ''} require validation.", + ephemeral=True, + ) + @category.subcommand(description="Get the size for a category.") async def size( self, @@ -85,6 +119,7 @@ class GetCog(commands.Cog, name="Get command."): """Parent slash subcommand for getting group information. Never called.""" @is_ascending.on_autocomplete("category_id") + @is_validated.on_autocomplete("category_id") @size.on_autocomplete("category_id") async def category_autocomplete(self, interaction: nextcord.Interaction, category_id: str, group_id: str) -> None: """ @@ -100,6 +135,7 @@ class GetCog(commands.Cog, name="Get command."): ) @is_ascending.on_autocomplete("group_id") + @is_validated.on_autocomplete("group_id") @size.on_autocomplete("group_id") async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str) -> None: """ From 983b9b6f34ae306084704ae9d0d24e546ae3dfd3 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Tue, 11 Mar 2025 09:03:54 -0400 Subject: [PATCH 17/37] Add command for getting group's pad length. --- cogs/commands/get.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/cogs/commands/get.py b/cogs/commands/get.py index 3d5b58d..4d784c0 100644 --- a/cogs/commands/get.py +++ b/cogs/commands/get.py @@ -118,6 +118,31 @@ class GetCog(commands.Cog, name="Get command."): async def group(self, interaction: nextcord.Interaction) -> None: """Parent slash subcommand for getting group information. Never called.""" + @group.subcommand(description="Get the pad length of a group.") + async def pad_length( + self, + interaction: nextcord.Interaction, + group_id: str = nextcord.SlashOption(name="group", description="Group to get pad length of.", required=True), + ) -> None: + """ + Command to view a group's pad length. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + group_id (str): String representation of Group id get information from. Is SlashOption. + """ + stmt = select(CategoryGroup).where(col(CategoryGroup.id) == int(group_id)) + + with Session(engine) as session: + group = session.scalar(stmt) + if group is None: + await interaction.response.send_message("Group was not found.", ephemeral=True) + return + + await interaction.response.send_message( + f"{group.name} has a pad length of {group.pad_length}.", ephemeral=True + ) + @is_ascending.on_autocomplete("category_id") @is_validated.on_autocomplete("category_id") @size.on_autocomplete("category_id") From a8d775ca09e24021dde019bacac35bbc781da031 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Tue, 11 Mar 2025 09:05:36 -0400 Subject: [PATCH 18/37] Correct some doc strings. --- cogs/commands/get.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cogs/commands/get.py b/cogs/commands/get.py index 4d784c0..d0fa769 100644 --- a/cogs/commands/get.py +++ b/cogs/commands/get.py @@ -37,8 +37,8 @@ class GetCog(commands.Cog, name="Get command."): Args: interaction (nextcord.Interaction): Interaction that invoked the command. - group_id (str): String representation of Group id to register channel to. Is SlashOption. - category_id (str): String representation of Category id to register channel to. Is SlashOption. + group_id (str): String representation of Group id get information from. Is SlashOption. + category_id (str): String representation of Category id to get information from. Is SlashOption. """ stmt = ( select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) @@ -69,8 +69,8 @@ class GetCog(commands.Cog, name="Get command."): Args: interaction (nextcord.Interaction): Interaction that invoked the command. - group_id (str): String representation of Group id to register channel to. Is SlashOption. - category_id (str): String representation of Category id to register channel to. Is SlashOption. + group_id (str): String representation of Group id get information from. Is SlashOption. + category_id (str): String representation of Category id to get information from. Is SlashOption. """ stmt = ( select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) @@ -99,8 +99,8 @@ class GetCog(commands.Cog, name="Get command."): Args: interaction (nextcord.Interaction): Interaction that invoked the command. - group_id (str): String representation of Group id to register channel to. Is SlashOption. - category_id (str): String representation of Category id to register channel to. Is SlashOption. + group_id (str): String representation of Group id get information from. Is SlashOption. + category_id (str): String representation of Category id to get information from. Is SlashOption. """ stmt = ( select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) From 7204e882f1075195f98dc0823eb4d63d807789ed Mon Sep 17 00:00:00 2001 From: imcompiling Date: Tue, 11 Mar 2025 09:10:17 -0400 Subject: [PATCH 19/37] Forgot to do group autocomplete. --- cogs/commands/get.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cogs/commands/get.py b/cogs/commands/get.py index d0fa769..0dbeb1d 100644 --- a/cogs/commands/get.py +++ b/cogs/commands/get.py @@ -161,6 +161,7 @@ class GetCog(commands.Cog, name="Get command."): @is_ascending.on_autocomplete("group_id") @is_validated.on_autocomplete("group_id") + @pad_length.on_autocomplete("group_id") @size.on_autocomplete("group_id") async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str) -> None: """ From 76fbba739f77f967fb9675ac87abb1368b45d5b5 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Tue, 11 Mar 2025 09:12:54 -0400 Subject: [PATCH 20/37] Add command to view a group's username length. --- cogs/commands/get.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cogs/commands/get.py b/cogs/commands/get.py index 0dbeb1d..184cb5c 100644 --- a/cogs/commands/get.py +++ b/cogs/commands/get.py @@ -143,6 +143,33 @@ class GetCog(commands.Cog, name="Get command."): f"{group.name} has a pad length of {group.pad_length}.", ephemeral=True ) + @group.subcommand(description="Get the username length of a group.") + async def username_length( + self, + interaction: nextcord.Interaction, + group_id: str = nextcord.SlashOption( + name="group", description="Group to get username length of.", required=True + ), + ) -> None: + """ + Command to view a group's username length. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + group_id (str): String representation of Group id get information from. Is SlashOption. + """ + stmt = select(CategoryGroup).where(col(CategoryGroup.id) == int(group_id)) + + with Session(engine) as session: + group = session.scalar(stmt) + if group is None: + await interaction.response.send_message("Group was not found.", ephemeral=True) + return + + await interaction.response.send_message( + f"{group.name} has a username length of {group.username_length}.", ephemeral=True + ) + @is_ascending.on_autocomplete("category_id") @is_validated.on_autocomplete("category_id") @size.on_autocomplete("category_id") @@ -163,6 +190,7 @@ class GetCog(commands.Cog, name="Get command."): @is_validated.on_autocomplete("group_id") @pad_length.on_autocomplete("group_id") @size.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. From 29a163ec46c665acc8b060873f5e7e1615bfbdd2 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Tue, 11 Mar 2025 09:37:27 -0400 Subject: [PATCH 21/37] correct some sql statement usages. Wasn't matching things properly. --- cogs/commands/get.py | 6 +++--- cogs/commands/set.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cogs/commands/get.py b/cogs/commands/get.py index 184cb5c..9b52241 100644 --- a/cogs/commands/get.py +++ b/cogs/commands/get.py @@ -41,7 +41,7 @@ class GetCog(commands.Cog, name="Get command."): category_id (str): String representation of Category id to get information from. Is SlashOption. """ stmt = ( - select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + select(Category).where(col(Category.group_id) == int(group_id)).where(col(Category.id) == int(category_id)) ) with Session(engine) as session: @@ -73,7 +73,7 @@ class GetCog(commands.Cog, name="Get command."): category_id (str): String representation of Category id to get information from. Is SlashOption. """ stmt = ( - select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + select(Category).where(col(Category.group_id) == int(group_id)).where(col(Category.id) == int(category_id)) ) with Session(engine) as session: @@ -103,7 +103,7 @@ class GetCog(commands.Cog, name="Get command."): category_id (str): String representation of Category id to get information from. Is SlashOption. """ stmt = ( - select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + select(Category).where(col(Category.group_id) == int(group_id)).where(col(Category.id) == int(category_id)) ) with Session(engine) as session: diff --git a/cogs/commands/set.py b/cogs/commands/set.py index 9aa84a1..0808d37 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -46,7 +46,7 @@ class SetCog(commands.Cog, name="Set command."): size (int): Size to set. Is SlashOption. """ stmt = ( - select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + select(Category).where(col(Category.group_id) == int(group_id)).where(col(Category.id) == int(category_id)) ) with Session(engine) as session: @@ -94,7 +94,7 @@ class SetCog(commands.Cog, name="Set command."): ascending (bool): Boolean to set. Determines whether scores are sorted ascending or not. Is SlashOption. """ stmt = ( - select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + select(Category).where(col(Category.group_id) == int(group_id)).where(col(Category.id) == int(category_id)) ) with Session(engine) as session: @@ -144,7 +144,7 @@ class SetCog(commands.Cog, name="Set command."): validated (bool): Boolean to set. Determines whether scores are validated or not. Is SlashOption. """ stmt = ( - select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + select(Category).where(col(Category.group_id) == int(group_id)).where(col(Category.id) == int(category_id)) ) with Session(engine) as session: @@ -191,7 +191,7 @@ class SetCog(commands.Cog, name="Set command."): name (str): The name to update the category's name to. Is SlashOption. """ stmt = ( - select(Category).where(col(CategoryGroup.id) == int(group_id)).where(col(Category.id) == int(category_id)) + select(Category).where(col(Category.group_id) == int(group_id)).where(col(Category.id) == int(category_id)) ) with Session(engine) as session: From 304b089113be1b621c73d433f7cf38322d4ad289 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 12 Mar 2025 09:35:44 -0400 Subject: [PATCH 22/37] Use the walrus operator when assigning and checking for None. --- cogs/commands/get.py | 15 +++++--------- cogs/commands/set.py | 47 +++++++++++--------------------------------- 2 files changed, 17 insertions(+), 45 deletions(-) diff --git a/cogs/commands/get.py b/cogs/commands/get.py index 9b52241..4f62177 100644 --- a/cogs/commands/get.py +++ b/cogs/commands/get.py @@ -45,8 +45,7 @@ class GetCog(commands.Cog, name="Get command."): ) with Session(engine) as session: - category = session.scalar(stmt) - if category is None: + if (category := session.scalar(stmt)) is None: await interaction.response.send_message("Group or Category was not found.", ephemeral=True) return @@ -77,8 +76,7 @@ class GetCog(commands.Cog, name="Get command."): ) with Session(engine) as session: - category = session.scalar(stmt) - if category is None: + if (category := session.scalar(stmt)) is None: await interaction.response.send_message("Group or Category was not found.", ephemeral=True) return @@ -107,8 +105,7 @@ class GetCog(commands.Cog, name="Get command."): ) with Session(engine) as session: - category = session.scalar(stmt) - if category is None: + if (category := session.scalar(stmt)) is None: await interaction.response.send_message("Group or Category was not found.", ephemeral=True) return @@ -134,8 +131,7 @@ class GetCog(commands.Cog, name="Get command."): stmt = select(CategoryGroup).where(col(CategoryGroup.id) == int(group_id)) with Session(engine) as session: - group = session.scalar(stmt) - if group is None: + if (group := session.scalar(stmt)) is None: await interaction.response.send_message("Group was not found.", ephemeral=True) return @@ -161,8 +157,7 @@ class GetCog(commands.Cog, name="Get command."): stmt = select(CategoryGroup).where(col(CategoryGroup.id) == int(group_id)) with Session(engine) as session: - group = session.scalar(stmt) - if group is None: + if (group := session.scalar(stmt)) is None: await interaction.response.send_message("Group was not found.", ephemeral=True) return diff --git a/cogs/commands/set.py b/cogs/commands/set.py index 0808d37..f69171a 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -50,8 +50,7 @@ class SetCog(commands.Cog, name="Set command."): ) with Session(engine) as session: - category = session.scalar(stmt) - if category is None: + if (category := session.scalar(stmt)) is None: await interaction.response.send_message("Category or Group was not found.", ephemeral=True) return category.size = size @@ -59,13 +58,11 @@ class SetCog(commands.Cog, name="Set command."): session.commit() # Use the relationship to get group category is in. - group = category.category_group - if group is None: + if (group := category.category_group) is None: agon_logger.warning(f"{category.name}:{category.id} group relationship was None.") stmt = select(CategoryGroup).where(col(CategoryGroup.id) == group_id) - group = session.scalar(stmt) - if group is None: + if (group := session.scalar(stmt)) is None: await interaction.response.send_message("Group was not found.", ephemeral=True) return @@ -98,8 +95,7 @@ class SetCog(commands.Cog, name="Set command."): ) with Session(engine) as session: - category = session.scalar(stmt) - if category is None: + if (category := session.scalar(stmt)) is None: await interaction.response.send_message("Category or Group was not found.", ephemeral=True) return category.is_ascending = ascending @@ -107,13 +103,11 @@ class SetCog(commands.Cog, name="Set command."): session.commit() # Use the relationship to get group category is in. - group = category.category_group - if group is None: + if (group := category.category_group) is None: agon_logger.warning(f"{category.name}:{category.id} group relationship was None.") stmt = select(CategoryGroup).where(col(CategoryGroup.id) == group_id) - group = session.scalar(stmt) - if group is None: + if (group := session.scalar(stmt)) is None: await interaction.response.send_message("Group was not found.", ephemeral=True) return @@ -148,25 +142,13 @@ class SetCog(commands.Cog, name="Set command."): ) with Session(engine) as session: - category = session.scalar(stmt) - if category is None: + if (category := session.scalar(stmt)) is None: await interaction.response.send_message("Category or Group was not found.", ephemeral=True) return category.is_validated = validated # session.add(category) test if this is needed. SQLAlchemy can do the update without adding. session.commit() - # Use the relationship to get group category is in. - group = category.category_group - if group is None: - agon_logger.warning(f"{category.name}:{category.id} group relationship was None.") - - stmt = select(CategoryGroup).where(col(CategoryGroup.id) == group_id) - group = session.scalar(stmt) - if group is None: - await interaction.response.send_message("Group was not found.", ephemeral=True) - return - await interaction.response.send_message( f"{category.name} is_validated has been updated to {validated}.", ephemeral=True ) @@ -195,8 +177,7 @@ class SetCog(commands.Cog, name="Set command."): ) with Session(engine) as session: - category = session.scalar(stmt) - if category is None: + if (category := session.scalar(stmt)) is None: await interaction.response.send_message("Category or Group was not found.", ephemeral=True) return old_name = category.name @@ -205,13 +186,11 @@ class SetCog(commands.Cog, name="Set command."): session.commit() # Use the relationship to get group category is in. - group = category.category_group - if group is None: + if (group := category.category_group) is None: agon_logger.warning(f"{category.name}:{category.id} group relationship was None.") stmt = select(CategoryGroup).where(col(CategoryGroup.id) == group_id) - group = session.scalar(stmt) - if group is None: + if (group := session.scalar(stmt)) is None: await interaction.response.send_message("Group was not found.", ephemeral=True) return @@ -240,8 +219,7 @@ class SetCog(commands.Cog, name="Set command."): stmt = select(CategoryGroup).where(col(CategoryGroup.id) == int(group_id)) with Session(engine) as session: - group = session.scalar(stmt) - if group is None: + if (group := session.scalar(stmt)) is None: await interaction.response.send_message("Group was not found.", ephemeral=True) return old_name = group.name @@ -315,8 +293,7 @@ class SetCog(commands.Cog, name="Set command."): .where(col(CategoryGroup.guild_id) == interaction.guild_id) .where(col(CategoryGroup.id) == int(group_id)) ) - group = session.scalar(stmt) - if group is None: + if (group := session.scalar(stmt)) is None: await interaction.response.send_message("Group was not found.", ephemeral=True) return group.PadLength = length From ed68c4174f502da7e03efe978370dc73dfd7c085 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 12 Mar 2025 09:57:17 -0400 Subject: [PATCH 23/37] Update send highscore message to be more robust. --- utilities/utils.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/utilities/utils.py b/utilities/utils.py index 3ad97cc..3d52bdc 100644 --- a/utilities/utils.py +++ b/utilities/utils.py @@ -10,6 +10,7 @@ from sqlmodel import col from database.db import engine from database.models import Category, CategoryGroup, Guild, Score +from main import agon_logger MAX_LINE_LENGTH = 142 @@ -327,7 +328,9 @@ def get_time_str(time_in: float) -> str: return time.strftime(f"%-M:%S.{milliseconds}", time.gmtime(time_in)) -async def send_highscore_message(session: Session, guild: nextcord.Guild, group: CategoryGroup) -> nextcord.Message: +async def send_highscore_message( + session: Session, guild: nextcord.Guild, group: CategoryGroup +) -> nextcord.Message | None: """ Function takes care of checking if a message exists for a group. @@ -339,11 +342,17 @@ async def send_highscore_message(session: Session, guild: nextcord.Guild, group: group (CategoryGroup): group to post to the message. Returns: - nextcord.Message: Message object that was posted with group contents. + nextcord.Message: Message object that was posted with group contents. None if cannot send message. """ highscore_string = format_highscore_message(session, group) channel = guild.get_channel(group.channel_id) + if not isinstance(channel, nextcord.TextChannel): + agon_logger.error( + "Channel id %s in guild %s is does not correspond to a TextChannel.", channel.id, channel.guild.id + ) + return None + if group.message_id is None: # message doesn't exist. message: nextcord.Message = await channel.send(highscore_string) From dbc6474fc33b706966c5aef5dd811433f93caf08 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 12 Mar 2025 10:02:32 -0400 Subject: [PATCH 24/37] send highscore message doesn't need to return the message, its never used. --- utilities/utils.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/utilities/utils.py b/utilities/utils.py index 3d52bdc..a026dab 100644 --- a/utilities/utils.py +++ b/utilities/utils.py @@ -328,9 +328,7 @@ def get_time_str(time_in: float) -> str: return time.strftime(f"%-M:%S.{milliseconds}", time.gmtime(time_in)) -async def send_highscore_message( - session: Session, guild: nextcord.Guild, group: CategoryGroup -) -> nextcord.Message | None: +async def send_highscore_message(session: Session, guild: nextcord.Guild, group: CategoryGroup) -> None: """ Function takes care of checking if a message exists for a group. @@ -340,9 +338,6 @@ async def send_highscore_message( session (Session): The sqlalchemy session being used for this function call. guild (nextcord.Guild): the nextcord.Guild object requesting this message. group (CategoryGroup): group to post to the message. - - Returns: - nextcord.Message: Message object that was posted with group contents. None if cannot send message. """ highscore_string = format_highscore_message(session, group) channel = guild.get_channel(group.channel_id) @@ -351,7 +346,7 @@ async def send_highscore_message( agon_logger.error( "Channel id %s in guild %s is does not correspond to a TextChannel.", channel.id, channel.guild.id ) - return None + return if group.message_id is None: # message doesn't exist. @@ -362,7 +357,7 @@ async def send_highscore_message( message: nextcord.Message = await channel.fetch_message(group.message_id) await message.edit(content=highscore_string) - return message + return async def submit_score( From edf51aac2dab446c430ae5c214692a8daaac1cb8 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 12 Mar 2025 10:12:54 -0400 Subject: [PATCH 25/37] Add a todo regarding possible bug. --- utilities/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utilities/utils.py b/utilities/utils.py index a026dab..1757333 100644 --- a/utilities/utils.py +++ b/utilities/utils.py @@ -354,6 +354,8 @@ async def send_highscore_message(session: Session, guild: nextcord.Guild, group: group.MessageId = message.id session.commit() else: + # TODO(imcompiling): check what happens when message is deleted. + # https://gitea.cheezers.org/imcompiling/agon/issues/83 message: nextcord.Message = await channel.fetch_message(group.message_id) await message.edit(content=highscore_string) From adab97f5058108f5eef93315aee5c0f3a7ef4635 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 12 Mar 2025 10:18:16 -0400 Subject: [PATCH 26/37] Add another TODO --- utilities/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utilities/utils.py b/utilities/utils.py index 1757333..f9d4113 100644 --- a/utilities/utils.py +++ b/utilities/utils.py @@ -276,6 +276,8 @@ def format_highscore_message(session: Session, group: CategoryGroup) -> str: return ret_string + "```" +# TODO(imcompiling): rework into two functions to remove the boolean and reduce function arguments. +# 084 def format_score_string( username: str, score: float, From 289113661f0adaa21a11e914060bcc4d9652c66f Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 12 Mar 2025 09:50:58 -0400 Subject: [PATCH 27/37] Use walrus operator when assigning and checking for None. --- cogs/commands/submission.py | 21 +++++++++------------ cogs/guild_listener/__init__.py | 3 +-- cogs/submission/verification_view.py | 4 +--- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/cogs/commands/submission.py b/cogs/commands/submission.py index 6a57008..ad53caa 100644 --- a/cogs/commands/submission.py +++ b/cogs/commands/submission.py @@ -64,10 +64,7 @@ class SubmissionCog(commands.Cog): .where(col(Category.group_id) == int(group_id)) .where(col(Category.id) == int(category_id)) ) - - category: Category | None = session.scalar(stmt) - - if category is None: + if (category := session.scalar(stmt)) is None: await interaction.response.send_message("Category not found.", ephemeral=True) return @@ -79,10 +76,13 @@ class SubmissionCog(commands.Cog): return # check with regex if score is in correct format - verified_score = await self.verify_score(interaction, score, is_time_record=category.is_time_record) - # check if verify_score was successful. It replies with corrections required itself. - if verified_score is None: + if ( + verified_score := await self.verify_score(interaction, score, is_time_record=category.is_time_record) + ) is None: + # This response message will be filled out better once command is split up to + # know which type it expects... + await interaction.response.send_message("Format was incorrect.", ephemeral=True) return # Create submission verification request or submit score if verification not needed. @@ -92,16 +92,13 @@ class SubmissionCog(commands.Cog): return stmt = select(col(Guild.verification_channel)).where(col(Guild.id) == interaction.guild_id) - verification_channel_id: int | None = session.scalar(stmt) - if verification_channel_id is None: + if (verification_channel_id := session.scalar(stmt)) is None: error_response = "No verification channel was registered. Contact server admins." await interaction.response.send_message(error_response, ephemeral=True) return - channel = interaction.guild.get_channel(verification_channel_id) - - if channel is None: + if (channel := interaction.guild.get_channel(verification_channel_id)) is None: error_response = "Registered Verification channel does not exist. Contact server admins." await interaction.response.send_message(error_response, ephemeral=True) return diff --git a/cogs/guild_listener/__init__.py b/cogs/guild_listener/__init__.py index 9e6fc61..2707f6b 100644 --- a/cogs/guild_listener/__init__.py +++ b/cogs/guild_listener/__init__.py @@ -26,10 +26,9 @@ class GuildListener(commands.Cog, name="Guild Listener"): """ with Session(engine) as session: stmt = select(Guild).where(col(Guild.id == guild.id)) - guild_data = session.scalar(stmt) # just in case check if the guild already exists - if guild_data is None: + if (guild_data := session.scalar(stmt)) is None: new_guild = Guild(id=guild.id, name=guild.name) session.add(new_guild) else: diff --git a/cogs/submission/verification_view.py b/cogs/submission/verification_view.py index 9a41e55..6a71e93 100644 --- a/cogs/submission/verification_view.py +++ b/cogs/submission/verification_view.py @@ -39,9 +39,7 @@ class VerificationView(nextcord.ui.View): .where(col(Submission.message_id) == interaction.message.id) ) - submission = session.scalar(stmt) - - if submission is None: + if (submission := session.scalar(stmt)) is None: await interaction.response.send_message("Could not find submission data in database.", ephemeral=True) await interaction.message.delete() return From 3ccaa7004e614bd78402c5aa463002e2ad8d9e75 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 12 Mar 2025 21:27:12 -0400 Subject: [PATCH 28/37] Had col around the wrong variables. --- cogs/loops/guild_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/loops/guild_data.py b/cogs/loops/guild_data.py index 8ed6c83..f686d49 100644 --- a/cogs/loops/guild_data.py +++ b/cogs/loops/guild_data.py @@ -31,7 +31,7 @@ class GuildData(commands.Cog, name="Guild Data"): with Session(engine) as session: for guild in self.bot.guilds: # update given guild name for guild id - stmt = select(Guild).where(col(Guild.id == guild.id)) + stmt = select(Guild).where(col(Guild.id) == guild.id) guild_data = session.scalar(stmt) # just in case checking if the guild doesn't exist. From 2c56c614f3e30bc477be2da4f134f7ebe6d66074 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 12 Mar 2025 21:27:29 -0400 Subject: [PATCH 29/37] Typo on col usage. --- utilities/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/utils.py b/utilities/utils.py index f9d4113..080a3c6 100644 --- a/utilities/utils.py +++ b/utilities/utils.py @@ -65,7 +65,7 @@ def autofill_groups(guild_id: int, group_begin: str) -> "dict[str, str]": """ with Session(engine) as session: # Select all groups in guild. - stmt = select(CategoryGroup).wherecol((CategoryGroup.guild_id) == guild_id) + stmt = select(CategoryGroup).where(col(CategoryGroup.guild_id) == guild_id) # dict has to have key values of same type for discord. group_dict: dict[str, str] = {group.name: str(group.id) for group in session.scalars(stmt)} From 9b3bd9d02cf733e8f041731c22ccd6534ef3c8d8 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 12 Mar 2025 21:29:01 -0400 Subject: [PATCH 30/37] Use correct variable for guild name. --- cogs/loops/guild_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/loops/guild_data.py b/cogs/loops/guild_data.py index f686d49..3ce385f 100644 --- a/cogs/loops/guild_data.py +++ b/cogs/loops/guild_data.py @@ -39,6 +39,6 @@ class GuildData(commands.Cog, name="Guild Data"): new_guild = Guild(id=guild.id, name=guild.name) session.add(new_guild) else: - guild_data.GuildName = guild.name + guild_data.name = guild.name session.commit() From 627112b114fe5be88a84ef82c81c81767530b168 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Wed, 12 Mar 2025 21:30:56 -0400 Subject: [PATCH 31/37] Use correct message id reference. --- utilities/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/utils.py b/utilities/utils.py index 080a3c6..ab3909e 100644 --- a/utilities/utils.py +++ b/utilities/utils.py @@ -353,7 +353,7 @@ async def send_highscore_message(session: Session, guild: nextcord.Guild, group: if group.message_id is None: # message doesn't exist. message: nextcord.Message = await channel.send(highscore_string) - group.MessageId = message.id + group.id = message.id session.commit() else: # TODO(imcompiling): check what happens when message is deleted. From 785a4eff464597b280ffb633a17b4f2b46fb0d97 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Thu, 13 Mar 2025 00:39:47 -0400 Subject: [PATCH 32/37] Was saving the message id to the wrong spot. --- utilities/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/utils.py b/utilities/utils.py index ab3909e..ecb8474 100644 --- a/utilities/utils.py +++ b/utilities/utils.py @@ -353,7 +353,7 @@ async def send_highscore_message(session: Session, guild: nextcord.Guild, group: if group.message_id is None: # message doesn't exist. message: nextcord.Message = await channel.send(highscore_string) - group.id = message.id + group.message_id = message.id session.commit() else: # TODO(imcompiling): check what happens when message is deleted. From e24340448029c28f23b5449dec3b423149ba4737 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 14 Mar 2025 16:53:15 -0400 Subject: [PATCH 33/37] Forgot to specify that is a description. --- cogs/commands/set.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index ca3b437..7bcf4f2 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -22,7 +22,7 @@ class SetCog(commands.Cog, name="Set command."): async def set(self, interaction: nextcord.Interaction) -> None: """Parent slash command for setting settings. Never called.""" - @set.subcommand("Commands for editing a category.") + @set.subcommand(description="Commands for editing a category.") async def category(self, interaction: nextcord.Interaction) -> None: """Parent slash subcommand for setting category settings. Never called.""" From 65de7baedaed5e3ab3bc807c9b3dc66493f19d89 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 14 Mar 2025 16:57:38 -0400 Subject: [PATCH 34/37] Added some log statements to provide helpful information. --- database/db.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/database/db.py b/database/db.py index d86cd41..7a55afc 100644 --- a/database/db.py +++ b/database/db.py @@ -2,13 +2,16 @@ from sqlmodel import SQLModel, create_engine from utilities import config +from utilities.logger import agon_logger from . import models # noqa: F401 - Need this import for creating the models. if config.ENVIRONMENT == "prod": url = f"mysql+pymysql://{config.SQL_USER}:{config.SQL_PASS}@{config.SQL_HOST}/{config.SQL_DB}" + agon_logger.info("Connected to prod database.") else: url = "sqlite:///database.db" + agon_logger.info("Connected to local dev database.") engine = create_engine(url) # Don't need to create all when connected to prod. From 7759bbc6486ea1cca6fc54b6ee1b4cddab013a41 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 14 Mar 2025 17:04:20 -0400 Subject: [PATCH 35/37] Add to set's return messages. --- cogs/commands/set.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index 7bcf4f2..993d093 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -67,7 +67,9 @@ class SetCog(commands.Cog, name="Set command."): return await send_highscore_message(session, interaction.guild, group) - await interaction.response.send_message(f"{category.name} size has been updated to {size}.", ephemeral=True) + await interaction.response.send_message( + f"**{category.name}** size has been updated to **{size}**.", ephemeral=True + ) @category.subcommand(description="Update the is_ascending value for a category.") async def is_ascending( @@ -113,7 +115,7 @@ class SetCog(commands.Cog, name="Set command."): await send_highscore_message(session, interaction.guild, group) await interaction.response.send_message( - f"{category.name} is_ascending has been updated to {ascending}.", ephemeral=True + f"**{category.name}** is_ascending has been updated to **{ascending}**.", ephemeral=True ) @category.subcommand(description="Update the is_validated value for a category.") @@ -150,7 +152,7 @@ class SetCog(commands.Cog, name="Set command."): session.commit() await interaction.response.send_message( - f"{category.name} is_validated has been updated to {validated}.", ephemeral=True + f"**{category.name}** is_validated has been updated to **{validated}**.", ephemeral=True ) @category.subcommand(name="name", description="Change the name of a category.") @@ -195,7 +197,9 @@ class SetCog(commands.Cog, name="Set command."): return await send_highscore_message(session, interaction.guild, group) - await interaction.response.send_message(f"{old_name} has been updated to {category.name}.", ephemeral=True) + await interaction.response.send_message( + f"**{old_name}** has been updated to **{category.name}**.", ephemeral=True + ) @set.subcommand(description="Commands for editing a group.") async def group(self, interaction: nextcord.Interaction) -> None: @@ -228,7 +232,7 @@ class SetCog(commands.Cog, name="Set command."): session.commit() await send_highscore_message(session, interaction.guild, group) - await interaction.response.send_message(f"{old_name} has been updated to {group.name}.", ephemeral=True) + await interaction.response.send_message(f"**{old_name}** has been updated to **{group.name}**.", ephemeral=True) @group.subcommand(description="Registers the channel for a Group's messages.") async def output_channel( @@ -302,7 +306,7 @@ class SetCog(commands.Cog, name="Set command."): group.pad_length = length session.commit() await interaction.response.send_message( - f"Category pad length set to {length} for {group.name}", ephemeral=True + f"Category pad length set to **{length}** for **{group.name}**.", ephemeral=True ) await send_highscore_message(session, interaction.guild, group) @@ -369,7 +373,9 @@ class SetCog(commands.Cog, name="Set command."): group.username_length = length session.commit() - await interaction.response.send_message(f"Username length set to {length}.", ephemeral=True) + await interaction.response.send_message( + f"Username length for **{group.name}** set to **{length}**.", ephemeral=True + ) @set.subcommand(description="Registers the channel for verification messages.") async def verify_channel( From f722eb1a8376991fd6cbfb938475b41433141548 Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 14 Mar 2025 17:05:39 -0400 Subject: [PATCH 36/37] Add to get's return messages. --- cogs/commands/get.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cogs/commands/get.py b/cogs/commands/get.py index 4f62177..e05e72f 100644 --- a/cogs/commands/get.py +++ b/cogs/commands/get.py @@ -50,7 +50,7 @@ class GetCog(commands.Cog, name="Get command."): return await interaction.response.send_message( - f"{category.name} is sorted in {'ascending' if category.is_ascending else 'descending'} order.", + f"**{category.name}** is sorted in **{'ascending' if category.is_ascending else 'descending'}** order.", ephemeral=True, ) @@ -109,7 +109,9 @@ class GetCog(commands.Cog, name="Get command."): await interaction.response.send_message("Group or Category was not found.", ephemeral=True) return - await interaction.response.send_message(f"{category.name} has a size of {category.size}.", ephemeral=True) + await interaction.response.send_message( + f"**{category.name}** has a size of **{category.size}**.", ephemeral=True + ) @get.subcommand(description="Commands for getting group information.") async def group(self, interaction: nextcord.Interaction) -> None: @@ -136,7 +138,7 @@ class GetCog(commands.Cog, name="Get command."): return await interaction.response.send_message( - f"{group.name} has a pad length of {group.pad_length}.", ephemeral=True + f"**{group.name}** has a pad length of **{group.pad_length}**.", ephemeral=True ) @group.subcommand(description="Get the username length of a group.") @@ -162,7 +164,7 @@ class GetCog(commands.Cog, name="Get command."): return await interaction.response.send_message( - f"{group.name} has a username length of {group.username_length}.", ephemeral=True + f"**{group.name}** has a username length of **{group.username_length}**.", ephemeral=True ) @is_ascending.on_autocomplete("category_id") From 5eb637a3a8a2c124cf5d3ddbffd364ac2357d45d Mon Sep 17 00:00:00 2001 From: imcompiling Date: Fri, 14 Mar 2025 17:20:50 -0400 Subject: [PATCH 37/37] Indent so that a command can properly use session. Remove commented out code. Also add work to an issue. --- cogs/commands/set.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/cogs/commands/set.py b/cogs/commands/set.py index 993d093..780c147 100644 --- a/cogs/commands/set.py +++ b/cogs/commands/set.py @@ -54,7 +54,6 @@ class SetCog(commands.Cog, name="Set command."): await interaction.response.send_message("Category or Group was not found.", ephemeral=True) return category.size = size - # session.add(category) test if this is needed. SQLAlchemy can do the update without adding. session.commit() # Use the relationship to get group category is in. @@ -101,7 +100,6 @@ class SetCog(commands.Cog, name="Set command."): await interaction.response.send_message("Category or Group was not found.", ephemeral=True) return category.is_ascending = ascending - # session.add(category) test if this is needed. SQLAlchemy can do the update without adding. session.commit() # Use the relationship to get group category is in. @@ -148,12 +146,11 @@ class SetCog(commands.Cog, name="Set command."): await interaction.response.send_message("Category or Group was not found.", ephemeral=True) return category.is_validated = validated - # session.add(category) test if this is needed. SQLAlchemy can do the update without adding. session.commit() - await interaction.response.send_message( - f"**{category.name}** is_validated has been updated to **{validated}**.", ephemeral=True - ) + await interaction.response.send_message( + f"**{category.name}** is_validated has been updated to **{validated}**.", ephemeral=True + ) @category.subcommand(name="name", description="Change the name of a category.") async def category_name( @@ -184,7 +181,6 @@ class SetCog(commands.Cog, name="Set command."): return old_name = category.name category.name = name - # session.add(category) test if this is needed. SQLAlchemy can do the update without adding. session.commit() # Use the relationship to get group category is in. @@ -268,6 +264,9 @@ class SetCog(commands.Cog, name="Set command."): return group.channel_id = channel_id session.commit() + # TODO(imcompiling): delete the message and call send_highscore_message to send a new one. Bug needs fixed + # first. + # 082 await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) @group.subcommand(