Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c0997624f | ||
|
|
67090e0d6f | ||
|
|
385129c434 | ||
|
|
327126307d | ||
|
|
36dad683d8 |
@@ -147,7 +147,7 @@ class CreateCog(commands.Cog, name="Create Cog"):
|
||||
@category.on_autocomplete("group_id")
|
||||
async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str) -> None:
|
||||
"""
|
||||
Collects list of table names and compares to input table name for autocomplete assistance.
|
||||
Collects list of group names and compares to input group name for autocomplete assistance.
|
||||
|
||||
Args:
|
||||
interaction (nextcord.Interaction): Interaction with command.
|
||||
|
||||
+10
-10
@@ -18,7 +18,7 @@ from utilities.utils import (
|
||||
from .views.delete_confirm import DeleteConfirmView, create_delete_id
|
||||
|
||||
|
||||
class DeleteCog(commands.Cog, name="Table Management"):
|
||||
class DeleteCog(commands.Cog, name="Delete Cog"):
|
||||
"""Class holds commands for deleting."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
@@ -32,7 +32,7 @@ class DeleteCog(commands.Cog, name="Table Management"):
|
||||
async def all(self, interaction: nextcord.Interaction) -> None:
|
||||
"""Subcommand parent for deleting all of a thing. Never called."""
|
||||
|
||||
@all.subcommand(description="Clears highscores channel of all table messages. Does not change data.")
|
||||
@all.subcommand(description="Clears highscores channel of all highscore messages. Does not change data.")
|
||||
async def channel_messages(
|
||||
self,
|
||||
interaction: nextcord.Interaction,
|
||||
@@ -69,16 +69,16 @@ class DeleteCog(commands.Cog, name="Table Management"):
|
||||
|
||||
for group in groups:
|
||||
try:
|
||||
table_message: nextcord.Message = await channel.fetch_message(group.MessageId)
|
||||
await table_message.delete()
|
||||
message: nextcord.Message = await channel.fetch_message(group.MessageId)
|
||||
await message.delete()
|
||||
except nextcord.NotFound:
|
||||
# silently ignore that messages are not found. They got deleted already.
|
||||
pass
|
||||
|
||||
await interaction.send("Table messages deleted.", ephemeral=True)
|
||||
await interaction.send("Highscore messages deleted.", ephemeral=True)
|
||||
|
||||
@all.subcommand(
|
||||
description="Removes all of a user's scores. Warning: data is destroyed, use with case.",
|
||||
description="Removes all of a user's scores. Warning: data is destroyed, use with care.",
|
||||
)
|
||||
async def users(
|
||||
self,
|
||||
@@ -90,7 +90,7 @@ class DeleteCog(commands.Cog, name="Table Management"):
|
||||
"""
|
||||
Searches all of guild's scores data for any score from the user and removes.
|
||||
|
||||
Updates table message is user was removed from that table.
|
||||
Updates highscore message if user was removed from that Category Group.
|
||||
|
||||
Args:
|
||||
interaction (nextcord.Interaction): Interaction that invoked the command.
|
||||
@@ -112,7 +112,7 @@ class DeleteCog(commands.Cog, name="Table Management"):
|
||||
for group in session.scalars(stmt):
|
||||
await send_highscore_message(session, interaction.guild, group)
|
||||
|
||||
await interaction.send(f'User "{user_name}" was removed from all tables.', ephemeral=True)
|
||||
await interaction.send(f'User "{user_name}" was removed from all Category Groups.', ephemeral=True)
|
||||
|
||||
@delete.subcommand(description="Delete a category from a group. Deletion is perminant.")
|
||||
async def category(
|
||||
@@ -225,7 +225,7 @@ class DeleteCog(commands.Cog, name="Table Management"):
|
||||
@group.on_autocomplete("group_id")
|
||||
async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str) -> None:
|
||||
"""
|
||||
Autocomplete function for table names.
|
||||
Autocomplete function for group names.
|
||||
|
||||
Args:
|
||||
interaction (nextcord.Interaction): Interaction that invoked the command.
|
||||
@@ -264,7 +264,7 @@ class DeleteCog(commands.Cog, name="Table Management"):
|
||||
"""
|
||||
await interaction.response.send_autocomplete(
|
||||
autofill_users_in_group_category(
|
||||
interaction.guild_id, int(group_id), category_id if category_id else 0, user_name
|
||||
interaction.guild_id, int(group_id), int(category_id) if category_id else 0, user_name
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class HelpCog(commands.Cog, name="Help commands."):
|
||||
help_str: str = "Welcome to Agon! Three simple steps are needed to get started."
|
||||
help_str += '1.) Set a channel to receive submission verifications with "/set verify_channel."\n'
|
||||
help_str += "This channel is used to allow moderators to check if a submission is real/valid.\n\n"
|
||||
help_str += '2.) Set up your highscore tables! Use "/create group" to first create a group message in the'
|
||||
help_str += '2.) Set up your highscores! Use "/create group" to first create a group message in the'
|
||||
help_str += 'channel you would like and then use "/create category" to create a category in that group message!'
|
||||
help_str += "\n\n"
|
||||
help_str += '3.) Users can then submit scores with the "/submit" command.'
|
||||
|
||||
+13
-20
@@ -14,13 +14,11 @@ from utilities.utils import autofill_groups, send_highscore_message
|
||||
|
||||
|
||||
class RefreshCog(commands.Cog, name="Refresh Cog"):
|
||||
"""
|
||||
Class holds commands for refreshing.
|
||||
"""
|
||||
"""Class holds commands for refreshing."""
|
||||
|
||||
def __init__(self, bot: commands.Bot) -> None:
|
||||
"""
|
||||
Default constructor for RefreshCog class
|
||||
Default constructor for RefreshCog class.
|
||||
|
||||
Args:
|
||||
bot (commands.Bot): Bot object. Required to register submission button view.
|
||||
@@ -28,19 +26,17 @@ class RefreshCog(commands.Cog, name="Refresh Cog"):
|
||||
self._bot = bot
|
||||
|
||||
@nextcord.slash_command(default_member_permissions=nextcord.Permissions(administrator=True))
|
||||
async def refresh(self, interaction: nextcord.Interaction):
|
||||
"""
|
||||
Parent slash command for refreshing things. Never called.
|
||||
"""
|
||||
async def refresh(self, interaction: nextcord.Interaction) -> None:
|
||||
"""Parent slash command for refreshing things. Never called."""
|
||||
|
||||
@refresh.subcommand(description="Manually refresh a table. Use when changing settings or data manually changed.")
|
||||
@refresh.subcommand(description="Manually refresh a group. Use when changing settings or data manually changed.")
|
||||
async def group(
|
||||
self,
|
||||
interaction: nextcord.Interaction,
|
||||
group_id: str = nextcord.SlashOption(name="group", description="Name of Group.", required=True),
|
||||
) -> None:
|
||||
"""
|
||||
Refreshes a table given by user.
|
||||
Refreshes a group given by user.
|
||||
|
||||
Args:
|
||||
interaction (nextcord.Interaction): Interaction that invoked the command.
|
||||
@@ -57,22 +53,19 @@ class RefreshCog(commands.Cog, name="Refresh Cog"):
|
||||
message: nextcord.Message = await send_highscore_message(session, interaction.guild, group)
|
||||
await message.edit(view=SubmissionCreateButton(self._bot))
|
||||
|
||||
await interaction.response.send_message(f"Updated table {group.GroupName}!", ephemeral=True)
|
||||
await interaction.response.send_message(f"Updated group {group.GroupName}!", ephemeral=True)
|
||||
|
||||
@refresh.subcommand()
|
||||
async def all(self, interaction: nextcord.Interaction):
|
||||
"""
|
||||
Subcommand parent for refreshing all things. Never called.
|
||||
"""
|
||||
async def all(self, interaction: nextcord.Interaction) -> None:
|
||||
"""Subcommand parent for refreshing all things. Never called."""
|
||||
|
||||
@all.subcommand(description="Triggers post/update of highscores to registered highscore channels.")
|
||||
async def groups(self, interaction: nextcord.Interaction) -> None:
|
||||
"""
|
||||
A command which posts the highscore in the registered channel.
|
||||
Sends warning if no channel has been registered.
|
||||
|
||||
Either creates new messages for each table if one doesn't exist
|
||||
or edits the existing message.
|
||||
Sends warning if no channel has been registered. Either creates new messages for each group if one doesn't
|
||||
exist or edits the existing message.
|
||||
|
||||
Args:
|
||||
interaction (nextcord.Interaction): Interaction that invoked the command.
|
||||
@@ -90,9 +83,9 @@ class RefreshCog(commands.Cog, name="Refresh Cog"):
|
||||
await interaction.send(f"Posted all groups in {interaction.guild.name}'s highscores.", ephemeral=True)
|
||||
|
||||
@group.on_autocomplete("group_id")
|
||||
async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str):
|
||||
async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str) -> None:
|
||||
"""
|
||||
Collects list of table names and compares to input table name for autocomplete assistance.
|
||||
Collects list of group names and compares to input group name for autocomplete assistance.
|
||||
|
||||
Args:
|
||||
interaction (nextcord.Interaction): Interaction with command.
|
||||
|
||||
@@ -10,7 +10,7 @@ from sqlalchemy.orm import Session
|
||||
from cogs.submission.verification_view import VerificationView
|
||||
from database_setup.sql_data_classes import Category, CategoryGroup, Guild, Submission, engine
|
||||
from main import logger
|
||||
from utilities.utils import GUILDS, autofill_categories, autofill_groups, submit_score
|
||||
from utilities.utils import autofill_categories, autofill_groups, submit_score
|
||||
|
||||
|
||||
class SubmissionCog(commands.Cog):
|
||||
@@ -19,7 +19,7 @@ class SubmissionCog(commands.Cog):
|
||||
def __init__(self) -> None:
|
||||
return
|
||||
|
||||
@nextcord.slash_command(guild_ids=GUILDS)
|
||||
@nextcord.slash_command()
|
||||
async def submit( # noqa: PLR0913
|
||||
self,
|
||||
interaction: nextcord.Interaction,
|
||||
@@ -47,6 +47,7 @@ class SubmissionCog(commands.Cog):
|
||||
group_id (str): Is SlashOption. Group that the score category belongs in.
|
||||
category_id (str): Is SlashOption. Category to submit the score in.
|
||||
score (str): Is SlashOption. The score.
|
||||
proof (nextcord.Attachment): Is SlashOption. Picture to provide proof of score.
|
||||
username (str, optional): Is SlashOption. Username to associate with the score.
|
||||
"""
|
||||
# fill out username if not passed in
|
||||
@@ -208,7 +209,7 @@ class SubmissionCog(commands.Cog):
|
||||
@submit.on_autocomplete("group_id")
|
||||
async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str) -> None:
|
||||
"""
|
||||
Autocomplete function for table names.
|
||||
Autocomplete function for group names.
|
||||
|
||||
Args:
|
||||
interaction (nextcord.Interaction): Interaction that invoked the command.
|
||||
|
||||
+19
-20
@@ -1,6 +1,4 @@
|
||||
"""
|
||||
View command heirarchy.
|
||||
"""
|
||||
"""View command hierarchy."""
|
||||
|
||||
import nextcord
|
||||
import pandas as pd
|
||||
@@ -14,20 +12,14 @@ from utilities.utils import MAX_LINE_LENGTH, autofill_categories, autofill_group
|
||||
|
||||
|
||||
class ViewCog(commands.Cog, name="View Command"):
|
||||
"""
|
||||
Class holds commands for viewing data.
|
||||
"""
|
||||
"""Class holds commands for viewing data."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""
|
||||
Default constructor for ViewCog class. Does nothing.
|
||||
"""
|
||||
"""Default constructor for ViewCog class. Does nothing."""
|
||||
|
||||
@nextcord.slash_command()
|
||||
async def view(self, interaction: nextcord.Interaction):
|
||||
"""
|
||||
Parent slash command for view. Never called.
|
||||
"""
|
||||
async def view(self, interaction: nextcord.Interaction) -> None:
|
||||
"""Parent slash command for view. Never called."""
|
||||
|
||||
@view.subcommand(description="Lists all scores for a given category.")
|
||||
async def leaderboard(
|
||||
@@ -39,10 +31,12 @@ class ViewCog(commands.Cog, name="View Command"):
|
||||
category_id: str = nextcord.SlashOption(
|
||||
name="category", description="Category to show leaderboard.", required=True
|
||||
),
|
||||
):
|
||||
) -> None:
|
||||
"""
|
||||
Gathers all users that have a submission in the group/category combo and returns a message with them
|
||||
in ranked order.
|
||||
Create message with leaderboard of a group and category.
|
||||
|
||||
Gathers all users that have a submission in the group/category combo and returns a
|
||||
message with them in ranked order.
|
||||
|
||||
Args:
|
||||
interaction (nextcord.Interaction): Interaction that invoked the command.
|
||||
@@ -71,7 +65,12 @@ class ViewCog(commands.Cog, name="View Command"):
|
||||
for i, row in scores.iterrows():
|
||||
str_list.append(
|
||||
format_score_string(
|
||||
row["UserName"], row["Score"], longest_str, category.IsTimeRecord, i + 1, MAX_LINE_LENGTH
|
||||
row["UserName"],
|
||||
row["Score"],
|
||||
longest_str,
|
||||
category.IsTimeRecord,
|
||||
i + 1, # type: ignore[reportOperatorIssue]
|
||||
MAX_LINE_LENGTH,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -87,9 +86,9 @@ class ViewCog(commands.Cog, name="View Command"):
|
||||
await interaction.response.send_message(content=message_str)
|
||||
|
||||
@leaderboard.on_autocomplete("group_id")
|
||||
async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str):
|
||||
async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str) -> None:
|
||||
"""
|
||||
Autocomplete function for table names.
|
||||
Autocomplete function for group names.
|
||||
|
||||
Args:
|
||||
interaction (nextcord.Interaction): Interaction that invoked the command.
|
||||
@@ -98,7 +97,7 @@ class ViewCog(commands.Cog, name="View Command"):
|
||||
await interaction.response.send_autocomplete(autofill_groups(interaction.guild_id, group_id))
|
||||
|
||||
@leaderboard.on_autocomplete("category_id")
|
||||
async def category_autocomplete(self, interaction: nextcord.Interaction, category_id: str, group_id: str):
|
||||
async def category_autocomplete(self, interaction: nextcord.Interaction, category_id: str, group_id: str) -> None:
|
||||
"""
|
||||
Autocomplete function for category names.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""View for verification buttons."""
|
||||
|
||||
import nextcord
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy import delete, select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from database_setup.sql_data_classes import Submission, engine
|
||||
@@ -19,6 +19,14 @@ class VerificationView(nextcord.ui.View):
|
||||
@nextcord.ui.button(label="Deny", style=nextcord.ButtonStyle.red, custom_id="deny-button-submission")
|
||||
async def deny_button(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002
|
||||
"""Button for denying score submission."""
|
||||
with Session(engine) as session:
|
||||
stmt = (
|
||||
delete(Submission)
|
||||
.where(Submission.GuildId == interaction.guild_id)
|
||||
.where(Submission.MessageId == interaction.message.id)
|
||||
)
|
||||
session.execute(stmt)
|
||||
session.commit()
|
||||
await interaction.message.delete()
|
||||
|
||||
@nextcord.ui.button(label="Approve", style=nextcord.ButtonStyle.green, custom_id="approve-button-submission")
|
||||
@@ -41,6 +49,8 @@ class VerificationView(nextcord.ui.View):
|
||||
await submit_score(
|
||||
interaction, submission.GroupId, submission.CategoryId, submission.UserName, submission.Score
|
||||
)
|
||||
session.delete(submission)
|
||||
session.commit()
|
||||
content = interaction.message.content
|
||||
content += f"\nApproved by <@{interaction.user.id}>."
|
||||
# remove the bot information embed. it should always be the first one.
|
||||
|
||||
+8
-40
@@ -1,8 +1,5 @@
|
||||
"""
|
||||
Contains various utlity functions for highscores bot
|
||||
"""
|
||||
"""Contains various utility functions for highscores bot."""
|
||||
|
||||
import json
|
||||
import time
|
||||
|
||||
import nextcord
|
||||
@@ -15,12 +12,11 @@ from database_setup.sql_data_classes import Category, CategoryGroup, Guild, Scor
|
||||
|
||||
MAX_LINE_LENGTH = 142
|
||||
|
||||
GUILDS = [1000247361639030804]
|
||||
|
||||
|
||||
def autofill_categories(guild_id: int, group_id: int, category_begin: str) -> "dict[str, str]":
|
||||
"""
|
||||
Returns all category names that start with category_begin.
|
||||
|
||||
If category_begin is empty, returns list of all category names.
|
||||
|
||||
Args:
|
||||
@@ -164,9 +160,12 @@ def autofill_users_in_guild(guild_id: int, user_begin: str) -> "list[str]":
|
||||
return users[:25]
|
||||
|
||||
|
||||
# TODO(imcompiling): #73 Address complexity warning.
|
||||
# 073
|
||||
def format_highscore_message(session: Session, group: CategoryGroup) -> str:
|
||||
"""
|
||||
Creates a formatted string for a boss's highscore discord message.
|
||||
Creates a formatted string for a category's highscore discord message.
|
||||
|
||||
This formatted string is in discord's code block to ensure monospace text.
|
||||
Loops through each category to build the message one place at a time.
|
||||
|
||||
@@ -213,7 +212,6 @@ def format_highscore_message(session: Session, group: CategoryGroup) -> str:
|
||||
str_list: list[str] = ["" for i in range(max_cat_size + 1)]
|
||||
groups_df = d_f.groupby("CategoryId")
|
||||
|
||||
# TODO figure out how to have less nests.
|
||||
for category in categories:
|
||||
# category name string
|
||||
str_list[0] += f"{category.CategoryName}".ljust(pad_length, " ")
|
||||
@@ -269,10 +267,8 @@ def format_highscore_message(session: Session, group: CategoryGroup) -> str:
|
||||
ret_string += string.rstrip() + "\n"
|
||||
|
||||
# add extra newline at category split unless there is already a space.
|
||||
if ((ind + 1) % (max_cat_size + 1)) == 0:
|
||||
# checking inside the other if to ensure called as little as possible.
|
||||
if not ret_string.endswith("\n\n"):
|
||||
ret_string += "\n"
|
||||
if ((ind + 1) % (max_cat_size + 1)) == 0 and not ret_string.endswith("\n\n"):
|
||||
ret_string += "\n"
|
||||
|
||||
return ret_string + "```"
|
||||
|
||||
@@ -400,31 +396,3 @@ async def submit_score(
|
||||
group = session.scalar(stmt)
|
||||
|
||||
await send_highscore_message(session, interaction.guild, group)
|
||||
|
||||
|
||||
def add_preset_configuration(guild_id: int, config_str: str) -> None:
|
||||
"""
|
||||
Adds an example configuration to a Guild. Uses guild id to know which guild and
|
||||
config name to open a file in example_config.
|
||||
|
||||
Args:
|
||||
guild_id (int): Guild id to add config to
|
||||
config_str (str): Config name to add
|
||||
"""
|
||||
with Session(engine) as session:
|
||||
with open(f"example_config/{config_str}.json", encoding="utf-8") as file:
|
||||
config = json.load(file)
|
||||
|
||||
for group_name, categorys in config["tables"].items():
|
||||
group_obj = CategoryGroup(GroupName=group_name, GuildId=guild_id)
|
||||
session.add(group_obj)
|
||||
for category_name in categorys:
|
||||
cat_obj = Category(
|
||||
CategoryName=category_name,
|
||||
Size=config["table_size"],
|
||||
IsTimeRecord=config["categories"][category_name]["is_time_record"],
|
||||
IsAscending=config["categories"][category_name]["ascending"],
|
||||
)
|
||||
session.add(cat_obj)
|
||||
|
||||
session.commit()
|
||||
|
||||
Reference in New Issue
Block a user