Compare commits

...
6 Commits
4 changed files with 148 additions and 24 deletions
+132 -13
View File
@@ -7,8 +7,9 @@ from sqlalchemy.orm import Session
from sqlmodel import col from sqlmodel import col
from database.db import engine from database.db import engine
from database.models import CategoryGroup, Guild from database.models import Category, CategoryGroup, Guild
from utilities.utils import MAX_LINE_LENGTH, autofill_groups 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."): class SetCog(commands.Cog, name="Set command."):
@@ -21,13 +22,116 @@ class SetCog(commands.Cog, name="Set command."):
async def set(self, interaction: nextcord.Interaction) -> None: async def set(self, interaction: nextcord.Interaction) -> None:
"""Parent slash command for setting settings. Never called.""" """Parent slash command for setting settings. Never called."""
@set.subcommand(description="Registers the channel for a Category Group's messages.") @set.subcommand("Commands for editing a category.")
async def group_output_channel( 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, self,
interaction: nextcord.Interaction, interaction: nextcord.Interaction,
group_id: str = nextcord.SlashOption( group_id: str = nextcord.SlashOption(
name="group", description="Category Group to assign to channel.", required=True 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. Size 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} 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
),
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="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( channel: nextcord.abc.GuildChannel | None = nextcord.SlashOption(
description="Channel to register", description="Channel to register",
required=False, required=False,
@@ -41,7 +145,7 @@ class SetCog(commands.Cog, name="Set command."):
Args: Args:
interaction (nextcord.Interaction): Interaction that invoked the command. interaction (nextcord.Interaction): Interaction that invoked the command.
group_id (str): String representation of Group id to register channel to. Is SlashOption. 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. Is a SlashOption. Limited to text channels, Defaults to None.
""" """
channel_id = interaction.channel.id if not channel else channel.id channel_id = interaction.channel.id if not channel else channel.id
@@ -57,15 +161,13 @@ class SetCog(commands.Cog, name="Set command."):
session.commit() session.commit()
await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True)
@set.subcommand( @group.subcommand(
description="Set character length for a category. Can cut off username/score. Affects all categories." description="Set character length for a category. Can cut off username/score. Affects all categories."
) )
async def pad_length( async def pad_length(
self, self,
interaction: nextcord.Interaction, interaction: nextcord.Interaction,
group_id: str = nextcord.SlashOption( group_id: str = nextcord.SlashOption(name="group", description="Group to assign pad length to.", required=True),
name="group", description="Category Group to assign pad length to.", required=True
),
length: int = nextcord.SlashOption( length: int = nextcord.SlashOption(
description="Number of characters alloted to a category.", description="Number of characters alloted to a category.",
required=True, required=True,
@@ -95,7 +197,7 @@ class SetCog(commands.Cog, name="Set command."):
f"Category pad length set to {length} for {group.name}", ephemeral=True 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." description="Registers the channel for submission messages. Currently this information is deprecated."
) )
async def submission_channel( async def submission_channel(
@@ -125,7 +227,7 @@ class SetCog(commands.Cog, name="Set command."):
session.commit() session.commit()
await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) 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( async def username_length(
self, self,
interaction: nextcord.Interaction, interaction: nextcord.Interaction,
@@ -183,7 +285,24 @@ class SetCog(commands.Cog, name="Set command."):
session.commit() session.commit()
await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True) await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True)
@group_output_channel.on_autocomplete("group_id") @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.
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")
@output_channel.on_autocomplete("group_id")
@is_ascending.on_autocomplete("group_id")
@pad_length.on_autocomplete("group_id") @pad_length.on_autocomplete("group_id")
@username_length.on_autocomplete("group_id") @username_length.on_autocomplete("group_id")
async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str) -> None: async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str) -> None:
+2 -2
View File
@@ -11,7 +11,7 @@ from sqlmodel import col
from cogs.submission.verification_view import VerificationView from cogs.submission.verification_view import VerificationView
from database.db import engine from database.db import engine
from database.models import Category, CategoryGroup, Guild, Submission 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 from utilities.utils import autofill_categories, autofill_groups, submit_score
@@ -108,7 +108,7 @@ class SubmissionCog(commands.Cog):
if not isinstance(channel, nextcord.TextChannel): if not isinstance(channel, nextcord.TextChannel):
await interaction.response.send_message("An error happened with submission.") 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 "Channel id %s in guild %s is does not correspond to a TextChannel.", channel.id, channel.guild.id
) )
return return
+4 -9
View File
@@ -8,6 +8,7 @@ import nextcord
from nextcord.ext import commands from nextcord.ext import commands
from utilities import config from utilities import config
from utilities.logger import agon_logger
nextcord_logger = logging.getLogger("nextcord") nextcord_logger = logging.getLogger("nextcord")
nextcord_logger.setLevel(logging.DEBUG) 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_handler.setFormatter(logging.Formatter("%(asctime)s:%(levelname)s:%(name)s: %(message)s"))
nextcord_logger.addHandler(nextcord_handler) 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: def main() -> None:
"""Main function for bot.""" """Main function for bot."""
min_python_version = (3, 12) min_python_version = (3, 12)
if sys.version_info < min_python_version: 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() sys.exit()
# Allows privileged intents for monitoring members joining, roles editing, and role assignments # Allows privileged intents for monitoring members joining, roles editing, and role assignments
@@ -46,9 +41,9 @@ def main() -> None:
async def on_ready() -> None: async def on_ready() -> None:
"""When Discord is connected.""" """When Discord is connected."""
if bot.user is None: if bot.user is None:
logger.error("Discord connection failed.") agon_logger.error("Discord connection failed.")
return 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 # Run Discord bot
bot.run(config.DISCORD_TOKEN) bot.run(config.DISCORD_TOKEN)
+10
View File
@@ -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)