Files
agon/cogs/commands/create.py
T

173 lines
7.4 KiB
Python

"""
Commands for creating items in bot.
"""
from typing import Optional
import nextcord
from nextcord.ext import commands
from sqlalchemy import exc, select
from sqlalchemy.orm import Session
# pylint: disable=import-error
from cogs.submission.submission_views import SubmissionCreateButton
from utilities.sql_data_classes import Category, CategoryGroup, engine
from utilities.utils import MAX_LINE_LENGTH, autofill_groups, send_highscore_message
class CreateCog(commands.Cog, name="Create Cog"):
"""
Class holds commands for creating things.
"""
def __init__(self, bot: commands.Bot) -> None:
"""
Default constructor for CreateCog class.
"""
self._bot = bot
@nextcord.slash_command(default_member_permissions=nextcord.Permissions(administrator=True))
async def create(self, interaction: nextcord.Interaction):
"""
Parent slash command for creating things. Never called.
"""
# need all these arguments because discord command.
# pylint: disable=too-many-arguments
@create.subcommand(description="Create a new Category. Must not exist already in Group.")
async def category(
self,
interaction: nextcord.Interaction,
group_id: str = nextcord.SlashOption(name="group", description="Group to add Category to.", required=True),
category_name: str = nextcord.SlashOption(description="Name of new Category.", required=True),
is_ascending: bool = nextcord.SlashOption(description="If lower value is a better score.", required=True),
is_time_record: bool = nextcord.SlashOption(
description="If the score should be shown in time format. Cannot be changed.", required=True
),
is_validated: bool = nextcord.SlashOption(
description="If scores need to be validated before posted.", required=True
),
size: int = nextcord.SlashOption(
description="How many scores to post in Category. Default is 3.", required=False, default=3, min_value=1
),
) -> None:
"""
Creates a new category to be placed into group_id group. Fails if the category name already exists within the
group. Then calls send_highscore_message().
Args:
interaction (nextcord.Interaction): Interaction for the command.
group_id (str): Id of group to add category to. Is SlashOption.
category_name (str): Name of new category. Is SlashOption.
is_ascending (bool): If the scores are sorted ascending or not. Is SlashOption.
is_time_record (bool): If the scores are a time record or not. Is SlashOption.
is_validated (bool): If the scores should be validated or not. Is SlashOption.
size (int): How many sores to show in the category message. Is SlashOption.
"""
new_category = Category(
CategoryName=category_name,
GroupId=int(group_id),
Size=size,
IsAscending=is_ascending,
IsTimeRecord=is_time_record,
IsValidated=is_validated,
)
# Open connection to engine and add new category.
with Session(engine) as session:
stmt = select(CategoryGroup).where(CategoryGroup.GroupId == int(group_id))
group = session.scalar(stmt)
try:
session.add(new_category)
session.commit()
await send_highscore_message(session, interaction.guild, group)
await interaction.response.send_message(
f'"{category_name}" has been added to "{group.GroupName}"!', ephemeral=True
)
except exc.IntegrityError:
# Category name already exists in group
session.rollback()
await interaction.response.send_message(
f'"{category_name}" already exists in "{group.GroupName}". Please rename.', ephemeral=True
)
# need all these arguments because discord command.
# pylint: disable=too-many-arguments
@create.subcommand(description="Create a new Category Group. Must not exist already for Guild.")
async def group(
self,
interaction: nextcord.Interaction,
group_name: str = nextcord.SlashOption(description="Name of new Group.", required=True),
pad_length: int = nextcord.SlashOption(
description="Number of characters wide a category is printed. Default is 26.",
required=False,
default=26,
min_value=7,
max_value=MAX_LINE_LENGTH,
),
username_length: int = nextcord.SlashOption(
description="Number of characters of a username to display. Default is 12.",
required=False,
default=12,
min_value=1,
max_value=30,
),
channel: Optional[nextcord.abc.GuildChannel] = nextcord.SlashOption(
description="Channel to post Group in. If left empty, defaults to current channel.",
required=False,
channel_types=[nextcord.ChannelType.text],
default=None,
),
) -> None:
"""
Creates a new category group to be placed into the database with the guild's id. Fails if the category group
name already exists within the guild. Then calls send_highscore_message().
Args:
interaction (nextcord.Interaction): Interaction for the command.
group_name (str): Name of new Group. Is SlashOption.
pad_length (int): Number of characters wide a category is printed. Is SlashOption.
username_length (int): Number of characters of a username to display. Is SlashOption.
channel (Optional[nextcord.abc.GuildChannel]): Channel to post group in. If None, defaults to current
channel. Is SlashOption.
"""
# if no channel provided, use current channel.
if channel is None:
channel = interaction.channel
new_group = CategoryGroup(
GroupName=group_name,
ChannelId=channel.id,
GuildId=interaction.guild_id,
PadLength=pad_length,
UsernameLength=username_length,
)
with Session(engine) as session:
try:
session.add(new_group)
session.commit()
message: nextcord.Message = await send_highscore_message(session, interaction.guild, new_group)
await message.edit(view=SubmissionCreateButton(self._bot))
await interaction.response.send_message(f'"{group_name}" has been created!', ephemeral=True)
except exc.IntegrityError:
# Category Group already exists in guild
session.rollback()
await interaction.response.send_message(
f'"{group_name}" already exists in "{interaction.guild.name}". Please rename.', ephemeral=True
)
@category.on_autocomplete("group_id")
async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str):
"""
Collects list of table names and compares to input table name for autocomplete assistance.
Args:
interaction (nextcord.Interaction): Interaction with command.
group_id (str): String to run autocomplete compared to.
"""
await interaction.response.send_autocomplete(autofill_groups(interaction.guild_id, group_id))