Files
agon/cogs/commands/data_management.py
T

244 lines
10 KiB
Python

"""
Commands for managing the tables/categories/scores for a Guild.
"""
from typing import Optional
import nextcord
from nextcord.ext import commands
from highscores import highscores_data # pylint: disable=import-error
from utilities.utils import ( # pylint: disable=import-error
autofill_categories,
autofill_tables,
autofill_users,
send_highscore_message,
)
from .views.update_username_verify import UpdateUsernameVerifyView
class DataManagementCog(commands.Cog, name="Table Management"):
"""
Class holds commands for managing the data storage of the highscores.
"""
def __init__(self, bot: commands.Bot):
"""
Default constructor for DataManagement class. Sets internal bot variable.
"""
self._bot: commands.Bot = bot
@commands.Cog.listener()
async def on_ready(self):
"""
Called when cog is loaded. Adds views required for DataManagement commands.
"""
self._bot.add_view(UpdateUsernameVerifyView())
@nextcord.slash_command(default_member_permissions=nextcord.Permissions(administrator=True))
async def delete(self, interaction: nextcord.Interaction):
"""
Parent slash command for deleting things. Never called.
"""
@delete.subcommand(description="Deletes all scores for this guild. Used for testing. Do Not Use.")
async def scores(self, interaction: nextcord.Interaction):
"""
Warning: This command only works for developers.
A command which deletes all scores in all tables for this guild.
Command limits to admins to prevent devs from usings on non-test servers.
"""
# only allow AlwaysCompiling to use.
# If you are a developer and want to use command, can add name to list
if interaction.user.id == 206602713511886849:
for table in highscores_data.get_guild(interaction.guild_id).tables:
for category in table.categories:
category.clear()
highscores_data.save_guild_data(highscores_data.get_guild(interaction.guild_id))
await interaction.response.send_message(f"Cleared score data for {interaction.guild.name}.", ephemeral=True)
else:
await interaction.response.send_message(
"You shouldn't be using this command. Deletes everything.", ephemeral=True
)
@delete.subcommand()
async def user(self, interaction: nextcord.Interaction):
"""
Subcommand parent for deleting user information. Never called.
"""
@user.subcommand(
description="Removes all of a user's scores. Warning: data is destroyed, use with case.",
)
async def from_all(
self,
interaction: nextcord.Interaction,
username: str = nextcord.SlashOption(
description="User to remove scores for. Note: This is not always a user's discord name."
),
):
"""
Searches all of guild's scores data for any score from the user. Removes. Updates table
message is user was removed from that table.
Args:
interaction (nextcord.Interaction): Interaction that invoked the command.
username (str): User to remove from highscores
"""
guild = highscores_data.get_guild(interaction.guild_id)
user_was_found: bool = False
# remove user from all tables and categories
for table in guild.tables:
table_updated: bool = False
for category in table.categories:
# user has a score in category
if category.remove_score(username):
user_was_found = True
table_updated = True
if table_updated:
await send_highscore_message(interaction.guild.get_channel(guild.highscore_channel), guild, table)
if not user_was_found:
await interaction.send(f'User "{username}" was not found.', ephemeral=True)
else:
await interaction.send(f'User "{username}" was removed from all tables.')
highscores_data.save_guild_data(guild)
@user.subcommand(description="Deletes a user's scores from a category.")
async def from_category(
self,
interaction: nextcord.Interaction,
table_name: str = nextcord.SlashOption(description="Table to delete user from.", required=True),
category_name: str = nextcord.SlashOption(description="Category to delete user from.", required=True),
user_name: str = nextcord.SlashOption(description="User to delete.", required=True),
):
"""
Removes a user from a category. Uses autofill functions to fill out table_name, category_name, and user_name.
Args:
interaction (nextcord.Interaction): Interaction that invoked the command.
table_name (str): Table to remove user from. Is SlashOption.
category_name (str): Category to remove user from. Is SlashOption.
user_name (str): The user to remove. Is SlashOption.
"""
guild = highscores_data.get_guild(interaction.guild_id)
try:
guild.get_table(table_name).get_category(category_name).remove_score(user_name)
await send_highscore_message(
interaction.guild.get_channel(guild.highscore_channel), guild, guild.get_table(table_name)
)
await interaction.response.send_message(
f'User "{user_name}" removed from "{category_name}".', ephemeral=True
)
except nextcord.errors.ApplicationInvokeError:
await interaction.response.send_message("Invalid parameter(s).", ephemeral=True)
@user.subcommand(description="Deletes a user's scores from entire table.")
async def from_table(
self,
interaction: nextcord.Interaction,
table_name: str = nextcord.SlashOption(description="Table to delete user from.", required=True),
user_name: str = nextcord.SlashOption(description="User to delete.", required=True),
):
"""
Removes user from a table. Uses autofill functions to fill out table_name and user_name.
Args:
interaction (nextcord.Interaction): Interaction that invoked the command.
table_name (str): Table to remove user from. Is SlashOption.
user_name (str): The user to remove. Is SlashOption.
"""
guild = highscores_data.get_guild(interaction.guild_id)
try:
for category in guild.get_table(table_name).categories:
category.remove_score(user_name)
await send_highscore_message(
interaction.guild.get_channel(guild.highscore_channel), guild, guild.get_table(table_name)
)
await interaction.response.send_message(f'User "{user_name}" removed from all categories.', ephemeral=True)
except nextcord.errors.ApplicationInvokeError:
await interaction.response.send_message("Invalid parameter(s).", ephemeral=True)
@from_category.on_autocomplete("table_name")
@from_table.on_autocomplete("table_name")
async def autocomplete_table(self, interaction: nextcord.Interaction, table_name: str):
"""
Autocomplete function for table names.
Args:
interaction (nextcord.Interaction): Interaction that invoked the command.
table_name (str): String to be autocompleted with Table name.
"""
await interaction.response.send_autocomplete(autofill_tables(interaction.guild_id, table_name))
@from_category.on_autocomplete("category_name")
async def autocomplete_category(self, interaction: nextcord.Interaction, category_name: str, table_name: str):
"""
Autocomplete function for category names.
Args:
interaction (nextcord.Interaction): Interaction that invoked the command.
category_name (str): String to be autocompleted with Category name.
table_name (str): Table to find Category from.
"""
await interaction.response.send_autocomplete(
autofill_categories(interaction.guild_id, table_name, category_name)
)
@from_category.on_autocomplete("user_name")
@from_table.on_autocomplete("user_name")
async def autocomplete_user(
self, interaction: nextcord.Interaction, user_name: str, table_name: str, category_name: Optional[str]
):
"""
Autocomplete functions for user names.
Args:
interaction (nextcord.Interaction): Interaction that invoked the command.
user_name (str): String to be autocompleted with User name.
table_name (str): Table to find category from.
category_name (Optional[str]): Category to find User from, can be None.
"""
await interaction.response.send_autocomplete(
autofill_users(interaction.guild_id, table_name, category_name, user_name)
)
@nextcord.slash_command(description="Request a username update. Admins must approve.")
async def update_username(
self,
interaction: nextcord.Interaction,
old_username: str = nextcord.SlashOption(description="Username currently stored in highscores.", required=True),
new_username: str = nextcord.SlashOption(description="Username to update to.", required=True),
):
"""
Creates a request to send to admins for changing a username. Uses
UpdateUsernameVerifyView to do the work.
Args:
interaction (nextcord.Interaction): Interaction that invoked the command
old_username (str): Username to replace.
new_username (str): Username to replace old with.
"""
guild = highscores_data.get_guild(interaction.guild_id)
verify_channel = interaction.guild.get_channel(guild.verification_channel)
embed: nextcord.Embed = nextcord.Embed(title="Username change request.")
embed.add_field(name="Old Username", value=old_username)
embed.add_field(name="New Username", value=new_username)
await verify_channel.send(
content=f"Username change request from <@{interaction.user.id}>.",
embed=embed,
view=UpdateUsernameVerifyView(),
)
await interaction.send("Request sent to admins for verification.", ephemeral=True)