From bfe718b50a7c2cd0b0fe17c223a3928b8134a446 Mon Sep 17 00:00:00 2001 From: wlinator Date: Mon, 2 Sep 2024 04:16:43 -0400 Subject: [PATCH] feat: Add fully functional help command --- handlers/error.py | 8 +- lib/format.py | 56 +++++++++ lib/help.py | 213 ++++++++++++++++++++++++--------- locales/strings.en-US.json | 1 + main.py | 3 +- modules/admin/admin.py | 3 + modules/admin/award.py | 2 + modules/admin/blacklist.py | 2 + modules/admin/dev.py | 5 +- modules/economy/balance.py | 4 +- modules/economy/blackjack.py | 2 + modules/economy/daily.py | 2 + modules/economy/give.py | 2 + modules/economy/slots.py | 2 + modules/levels/leaderboard.py | 2 + modules/levels/level.py | 4 +- modules/misc/avatar.py | 5 +- modules/misc/backup.py | 5 - modules/misc/info.py | 2 + modules/misc/introduction.py | 2 + modules/misc/invite.py | 2 + modules/misc/ping.py | 2 + modules/misc/uptime.py | 4 +- modules/moderation/ban.py | 4 +- modules/moderation/cases.py | 5 + modules/moderation/kick.py | 1 + modules/moderation/slowmode.py | 2 + modules/moderation/softban.py | 5 +- modules/moderation/timeout.py | 2 + modules/moderation/warn.py | 2 + 30 files changed, 281 insertions(+), 73 deletions(-) diff --git a/handlers/error.py b/handlers/error.py index 86f6d13..64eb9c1 100644 --- a/handlers/error.py +++ b/handlers/error.py @@ -41,7 +41,13 @@ async def log_command_error( log_msg = f"{user_name} executed {command_type}{command_name or 'Unknown'}" log_msg += " in DMs" if guild_id is None else f" | guild: {guild_id}" - logger.error(f"{log_msg} | {error.__module__}.{error.__class__.__name__}") + + if CONST.INSTANCE == "dev": + logger.exception( + f"{log_msg} | {error.__module__}.{error.__class__.__name__} | {''.join(traceback.format_exception(type(error), error, error.__traceback__))}", + ) + else: + logger.error(f"{log_msg} | {error.__module__}.{error.__class__.__name__}") class ErrorHandler(commands.Cog): diff --git a/lib/format.py b/lib/format.py index 153f30a..7d7f777 100644 --- a/lib/format.py +++ b/lib/format.py @@ -1,4 +1,6 @@ +import inspect import textwrap +from typing import Any import discord from discord.ext import commands @@ -140,3 +142,57 @@ def format_seconds_to_duration_string(seconds: int) -> str: return f"{hours}h{minutes}m" if minutes > 0 else f"{hours}h" return f"{minutes}m" + + +def generate_usage( + command: commands.Command[Any, Any, Any], + flag_converter: type[commands.FlagConverter] | None = None, +) -> str: + """ + Generate a usage string for a command with flags. + Credit to https://github.com/allthingslinux/tux (thanks kaizen ;p) + + Parameters + ---------- + command : commands.Command + The command for which to generate the usage string. + flag_converter : type[commands.FlagConverter] + The flag converter class for the command. + + Returns + ------- + str + The usage string for the command. Example: "ban [target] -[reason] -" + """ + + # Get the name of the command + command_name = command.qualified_name + + # Start the usage string with the command name + usage = f"{command_name}" + + # Get the parameters of the command (excluding the `ctx` and `flags` parameters) + parameters: dict[str, commands.Parameter] = command.clean_params + + flag_prefix = getattr(flag_converter, "__commands_flag_prefix__", "-") + flags: dict[str, commands.Flag] = flag_converter.get_flags() if flag_converter else {} + + # Add non-flag arguments to the usage string + for param_name, param in parameters.items(): + # Ignore these parameters + if param_name in ["ctx", "flags"]: + continue + # Determine if the parameter is required + is_required = param.default == inspect.Parameter.empty + # Add the parameter to the usage string with required or optional wrapping + usage += f" <{param_name}>" if is_required else f" [{param_name}]" + + # Add flag arguments to the usage string + for flag_name, flag_obj in flags.items(): + # Determine if the flag is required or optional + if flag_obj.required: + usage += f" {flag_prefix}<{flag_name}>" + else: + usage += f" {flag_prefix}[{flag_name}]" + + return usage diff --git a/lib/help.py b/lib/help.py index 566b9ce..436236f 100644 --- a/lib/help.py +++ b/lib/help.py @@ -3,81 +3,178 @@ from collections.abc import Mapping from pathlib import Path from typing import Any +import discord from discord.ext import commands from lib.const import CONST -from lib.exceptions import LumiException from ui.embeds import Builder -class LumiHelp(commands.HelpCommand): - def __init__(self, **options: Any) -> None: - super().__init__(**options) - self.verify_checks: bool = True - self.command_attrs: dict[str, list[str] | str | bool] = { - "aliases": ["h"], - "help": "Show a list of commands, or information about a specific command when an argument is passed.", - "name": "help", - "hidden": True, - } - - def get_command_qualified_name(self, command: commands.Command[Any, Any, Any]) -> str: - return f"`{self.context.clean_prefix}{command.qualified_name}`" - - async def send_bot_help(self, mapping: Mapping[commands.Cog | None, list[commands.Command[Any, ..., Any]]]) -> None: - embed = Builder.create_embed( - theme="success", - author_text="Help Command", - user_name=self.context.author.name, - hide_name_in_description=True, +class LuminaraHelp(commands.HelpCommand): + def __init__(self): + """Initializes the LuminaraHelp command with necessary attributes.""" + super().__init__( + command_attrs={ + "help": "Lists all commands and sub-commands.", + "aliases": ["h"], + "usage": "$help or ", + }, ) - modules_dir = Path(__file__).parent.parent / "modules" - module_names = [name for name in os.listdir(modules_dir) if Path(modules_dir / name).is_dir()] + async def _get_prefix(self) -> str: + """ + Dynamically fetches the prefix from the context or uses a default prefix constant. - for module_name in module_names: - module_commands: list[commands.Command[Any, ..., Any]] = [] - for cog, lumi_commands in mapping.items(): - if cog and cog.__module__.startswith(f"modules.{module_name}"): - filtered = await self.filter_commands(lumi_commands, sort=True) - module_commands.extend(filtered) + Returns + ------- + str + The prefix used to invoke the bot. + """ + return "." - if module_commands: - command_signatures = [self.get_command_qualified_name(c) for c in module_commands] - unique_command_signatures = list(set(command_signatures)) - embed.add_field( - name=module_name.capitalize(), - value=", ".join(sorted(unique_command_signatures)), - inline=False, - ) + def _embed_base(self, author: str, description: str | None = None) -> discord.Embed: + """ + Creates a base embed with uniform styling. - channel = self.get_destination() - await channel.send(embed=embed) + Parameters + ---------- + title : str + The title of the embed. + description : str | None + The description of the embed. + + Returns + ------- + discord.Embed + The created embed. + """ + return Builder.create_embed( + theme="info", + author_text=author, + description=description, + footer_text=CONST.STRINGS["help_footer"], + ) + + def _get_cog_groups(self) -> list[str]: + """ + Retrieves a list of cog groups from the 'modules' folder. + + Returns + ------- + list[str] + A list of cog groups. + """ + cog_groups = sorted( + [ + d + for d in os.listdir("./modules") + if Path(f"./modules/{d}").is_dir() and d not in ("__pycache__", "admin") + ], + ) + if "moderation" in cog_groups: + cog_groups.remove("moderation") + cog_groups.insert(0, "moderation") + return cog_groups + + async def send_bot_help( + self, + mapping: Mapping[commands.Cog | None, list[commands.Command[Any, Any, Any]]], + ) -> None: + """ + Sends an overview of all commands in a single embed, grouped by module. + + Parameters + ---------- + mapping : Mapping[commands.Cog | None, list[commands.Command[Any, Any, Any]]] + The mapping of cogs to commands. + """ + embed = self._embed_base("Luminara Help Overview") + + cog_groups = self._get_cog_groups() + for group in cog_groups: + group_commands: list[commands.Command[Any, Any, Any]] = [] + for cog, commands_list in mapping.items(): + if cog and commands_list and cog.__module__.startswith(f"modules.{group}"): + group_commands.extend(commands_list) + if group_commands: + command_list = ", ".join(f"`{c.name}`" for c in group_commands) + embed.add_field(name=group.capitalize(), value=command_list, inline=False) + + await self.get_destination().send(embed=embed) + + async def _add_command_help_fields(self, embed: discord.Embed, command: commands.Command[Any, Any, Any]) -> None: + """ + Adds fields with usage and alias information for a command to an embed. + + Parameters + ---------- + embed : discord.Embed + The embed to which the fields will be added. + command : commands.Command[Any, Any, Any] + The command whose details are to be added. + """ + prefix = await self._get_prefix() + + embed.add_field( + name="Usage", + value=f"`{prefix}{command.usage or 'No usage.'}`", + inline=False, + ) async def send_command_help(self, command: commands.Command[Any, Any, Any]) -> None: - embed = Builder.create_embed( - theme="success", - author_text=f"{self.context.clean_prefix}{command.qualified_name}", - description=command.description, - user_name=self.context.author.name, - hide_name_in_description=True, + """ + Sends a help message for a specific command. + + Parameters + ---------- + command : commands.Command[Any, Any, Any] + The command for which the help message is to be sent. + """ + prefix = await self._get_prefix() + + author = f"{prefix}{command.qualified_name}" + author += f" ({', '.join(command.aliases)})" if command.aliases else "" + + embed = self._embed_base( + author=author, + description=f"> {command.help}" or "No description available.", ) - usage_value: str = f"`{self.context.clean_prefix}{command.usage}`" - embed.add_field(name="Usage", value=usage_value, inline=False) - - channel = self.get_destination() - await channel.send(embed=embed) - - async def send_error_message(self, error: str) -> None: - raise LumiException(error) + await self._add_command_help_fields(embed, command) + await self.get_destination().send(embed=embed) async def send_group_help(self, group: commands.Group[Any, Any, Any]) -> None: - raise LumiException( - CONST.STRINGS["error_command_not_found"].format(group.qualified_name), + """ + Sends a help message for a specific command group. + + Parameters + ---------- + group : commands.Group[Any, Any, Any] + The group for which the help message is to be sent. + """ + prefix = await self._get_prefix() + embed = self._embed_base( + author=f"{prefix}{group.qualified_name}", + description=group.help or "No description available.", ) - async def send_cog_help(self, cog: commands.Cog) -> None: - raise LumiException( - CONST.STRINGS["error_command_not_found"].format(cog.qualified_name), + for command in group.commands: + embed.add_field(name=command.name, value=command.short_doc or "No description available.", inline=False) + + await self.get_destination().send(embed=embed) + + async def send_error_message(self, error: str) -> None: + """ + Sends an error message. + + Parameters + ---------- + error : str + The error message to be sent. + """ + embed = Builder.create_embed( + theme="error", + title="Error in help command", + description=error, ) + await self.get_destination().send(embed=embed, delete_after=30) diff --git a/locales/strings.en-US.json b/locales/strings.en-US.json index 9d06b82..2470c31 100644 --- a/locales/strings.en-US.json +++ b/locales/strings.en-US.json @@ -190,6 +190,7 @@ "give_success": "you gave **${1}** to {2}.", "greet_default_description": "_ _\n**Welcome** to **{0}**", "greet_template_description": "\u2193\u2193\u2193\n{0}", + "help_footer": "Help Service", "help_use_prefix": "Please use Lumi's prefix to get help. Type `{0}help`", "info_api_version": "**discord.py:** v{0}\n", "info_database_records": "**Database:** {0} records", diff --git a/main.py b/main.py index 8ae2737..63a81ee 100644 --- a/main.py +++ b/main.py @@ -7,6 +7,7 @@ from loguru import logger from lib.client import Luminara from lib.const import CONST +from lib.help import LuminaraHelp from services.config_service import GuildConfig logger.remove() @@ -30,7 +31,7 @@ async def main() -> None: allowed_mentions=discord.AllowedMentions(everyone=False), case_insensitive=True, strip_after_prefix=True, - help_command=None, + help_command=LuminaraHelp(), ) try: diff --git a/modules/admin/admin.py b/modules/admin/admin.py index 87b1f34..6053bea 100644 --- a/modules/admin/admin.py +++ b/modules/admin/admin.py @@ -1,6 +1,7 @@ import mysql.connector from discord.ext import commands +import lib.format from db import database from lib.const import CONST from lib.format import shorten @@ -10,6 +11,8 @@ from ui.embeds import Builder class Sql(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.select_cmd.usage = lib.format.generate_usage(self.select_cmd) + self.inject_cmd.usage = lib.format.generate_usage(self.inject_cmd) @commands.command(name="sqlselect", aliases=["sqls"]) @commands.is_owner() diff --git a/modules/admin/award.py b/modules/admin/award.py index 0102bf3..c9c9d51 100644 --- a/modules/admin/award.py +++ b/modules/admin/award.py @@ -1,6 +1,7 @@ import discord from discord.ext import commands +import lib.format from lib.const import CONST from services.currency_service import Currency from ui.embeds import Builder @@ -9,6 +10,7 @@ from ui.embeds import Builder class Award(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.award_command.usage = lib.format.generate_usage(self.award_command) @commands.command(name="award", aliases=["aw"]) @commands.is_owner() diff --git a/modules/admin/blacklist.py b/modules/admin/blacklist.py index fed6479..f9c1538 100644 --- a/modules/admin/blacklist.py +++ b/modules/admin/blacklist.py @@ -1,6 +1,7 @@ import discord from discord.ext import commands +import lib.format from lib.const import CONST from services.blacklist_service import BlacklistUserService from ui.embeds import Builder @@ -9,6 +10,7 @@ from ui.embeds import Builder class Blacklist(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.blacklist_command.usage = lib.format.generate_usage(self.blacklist_command) @commands.command(name="blacklist") @commands.is_owner() diff --git a/modules/admin/dev.py b/modules/admin/dev.py index a546e04..9591290 100644 --- a/modules/admin/dev.py +++ b/modules/admin/dev.py @@ -1,12 +1,15 @@ import discord from discord.ext import commands +import lib.format from lib.const import CONST class Dev(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.sync.usage = lib.format.generate_usage(self.sync) + self.clear.usage = lib.format.generate_usage(self.clear) @commands.group(name="dev", description="Lumi developer commands") @commands.guild_only() @@ -44,7 +47,7 @@ class Dev(commands.Cog): name="clear_tree", aliases=["clear"], ) - async def sync_global( + async def clear( self, ctx: commands.Context[commands.Bot], guild: discord.Guild | None = None, diff --git a/modules/economy/balance.py b/modules/economy/balance.py index 083f833..c2d365d 100644 --- a/modules/economy/balance.py +++ b/modules/economy/balance.py @@ -1,5 +1,6 @@ from discord.ext import commands +import lib.format from lib.const import CONST from services.currency_service import Currency from ui.embeds import Builder @@ -8,13 +9,14 @@ from ui.embeds import Builder class Balance(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot: commands.Bot = bot + self.balance.usage = lib.format.generate_usage(self.balance) @commands.hybrid_command( name="balance", aliases=["bal", "$"], ) @commands.guild_only() - async def daily( + async def balance( self, ctx: commands.Context[commands.Bot], ) -> None: diff --git a/modules/economy/blackjack.py b/modules/economy/blackjack.py index eb4cb49..61197bb 100644 --- a/modules/economy/blackjack.py +++ b/modules/economy/blackjack.py @@ -5,6 +5,7 @@ import discord from discord.ext import commands from loguru import logger +import lib.format from lib.const import CONST from lib.exceptions import LumiException from services.currency_service import Currency @@ -22,6 +23,7 @@ Hand = list[Card] class Blackjack(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot: commands.Bot = bot + self.blackjack.usage = lib.format.generate_usage(self.blackjack) @commands.hybrid_command( name="blackjack", diff --git a/modules/economy/daily.py b/modules/economy/daily.py index d6b3dac..bf5833f 100644 --- a/modules/economy/daily.py +++ b/modules/economy/daily.py @@ -4,6 +4,7 @@ from zoneinfo import ZoneInfo from discord import Embed from discord.ext import commands +import lib.format from lib.const import CONST from services.currency_service import Currency from services.daily_service import Dailies @@ -25,6 +26,7 @@ def seconds_until(hours: int, minutes: int) -> int: class Daily(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot: commands.Bot = bot + self.daily.usage = lib.format.generate_usage(self.daily) @commands.hybrid_command( name="daily", diff --git a/modules/economy/give.py b/modules/economy/give.py index e92dfcf..05f9ea5 100644 --- a/modules/economy/give.py +++ b/modules/economy/give.py @@ -1,6 +1,7 @@ import discord from discord.ext import commands +import lib.format from lib.const import CONST from lib.exceptions import LumiException from services.currency_service import Currency @@ -10,6 +11,7 @@ from ui.embeds import Builder class Give(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot: commands.Bot = bot + self.give.usage = lib.format.generate_usage(self.give) @commands.hybrid_command( name="give", diff --git a/modules/economy/slots.py b/modules/economy/slots.py index b0d2f25..c55f1f6 100644 --- a/modules/economy/slots.py +++ b/modules/economy/slots.py @@ -7,6 +7,7 @@ from zoneinfo import ZoneInfo import discord from discord.ext import commands +import lib.format from lib.const import CONST from lib.exceptions import LumiException from services.currency_service import Currency @@ -18,6 +19,7 @@ est = ZoneInfo("US/Eastern") class Slots(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot: commands.Bot = bot + self.slots.usage = lib.format.generate_usage(self.slots) @commands.hybrid_command( name="slots", diff --git a/modules/levels/leaderboard.py b/modules/levels/leaderboard.py index a845568..c1f7813 100644 --- a/modules/levels/leaderboard.py +++ b/modules/levels/leaderboard.py @@ -3,6 +3,7 @@ from typing import cast from discord import Embed, Guild, Member from discord.ext import commands +import lib.format from lib.const import CONST from ui.embeds import Builder from ui.views.leaderboard import LeaderboardCommandOptions, LeaderboardCommandView @@ -11,6 +12,7 @@ from ui.views.leaderboard import LeaderboardCommandOptions, LeaderboardCommandVi class Leaderboard(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot: commands.Bot = bot + self.leaderboard.usage = lib.format.generate_usage(self.leaderboard) @commands.hybrid_command( name="leaderboard", diff --git a/modules/levels/level.py b/modules/levels/level.py index 01a1f62..f55da57 100644 --- a/modules/levels/level.py +++ b/modules/levels/level.py @@ -1,6 +1,7 @@ from discord import Embed from discord.ext import commands +import lib.format from lib.const import CONST from services.xp_service import XpService from ui.embeds import Builder @@ -9,12 +10,13 @@ from ui.embeds import Builder class Level(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.level.usage = lib.format.generate_usage(self.level) @commands.hybrid_command( name="level", aliases=["rank", "lvl", "xp"], ) - async def ping(self, ctx: commands.Context[commands.Bot]) -> None: + async def level(self, ctx: commands.Context[commands.Bot]) -> None: """ Get the level of the user. diff --git a/modules/misc/avatar.py b/modules/misc/avatar.py index 5f760f4..f04221d 100644 --- a/modules/misc/avatar.py +++ b/modules/misc/avatar.py @@ -5,6 +5,8 @@ import httpx from discord import File from discord.ext import commands +import lib.format + async def create_avatar_file(url: str) -> File: """ @@ -32,6 +34,7 @@ async def create_avatar_file(url: str) -> File: class Avatar(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.avatar.usage = lib.format.generate_usage(self.avatar) @commands.hybrid_command( name="avatar", @@ -45,7 +48,7 @@ class Avatar(commands.Cog): """ Get the avatar of a member. - Parameters: + Parameters ----------- ctx : ApplicationContext The discord context object. diff --git a/modules/misc/backup.py b/modules/misc/backup.py index d419ae8..8e4d3ff 100644 --- a/modules/misc/backup.py +++ b/modules/misc/backup.py @@ -90,11 +90,6 @@ class Backup(commands.Cog): await self.bot.wait_until_ready() await asyncio.sleep(30) - @commands.command() - async def backup(self, ctx: commands.Context[commands.Bot]) -> None: - await backup() - await ctx.send("Backup successful.") - async def setup(bot: commands.Bot) -> None: await bot.add_cog(Backup(bot)) diff --git a/modules/misc/info.py b/modules/misc/info.py index a20fcae..6a5b8ef 100644 --- a/modules/misc/info.py +++ b/modules/misc/info.py @@ -5,6 +5,7 @@ import discord import psutil from discord.ext import commands +import lib.format from lib.const import CONST from ui.embeds import Builder @@ -12,6 +13,7 @@ from ui.embeds import Builder class Info(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.info.usage = lib.format.generate_usage(self.info) @commands.hybrid_command( name="info", diff --git a/modules/misc/introduction.py b/modules/misc/introduction.py index 44b3e30..152e876 100644 --- a/modules/misc/introduction.py +++ b/modules/misc/introduction.py @@ -1,6 +1,7 @@ import discord from discord.ext import commands +import lib.format from lib.const import CONST from ui.embeds import Builder from ui.views.introduction import ( @@ -12,6 +13,7 @@ from ui.views.introduction import ( class Introduction(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.introduction.usage = lib.format.generate_usage(self.introduction) @commands.hybrid_command(name="introduction", aliases=["intro"]) async def introduction(self, ctx: commands.Context[commands.Bot]) -> None: diff --git a/modules/misc/invite.py b/modules/misc/invite.py index 37e8f16..b237737 100644 --- a/modules/misc/invite.py +++ b/modules/misc/invite.py @@ -1,5 +1,6 @@ from discord.ext import commands +import lib.format from lib.const import CONST from ui.embeds import Builder from ui.views.invite import InviteButton @@ -8,6 +9,7 @@ from ui.views.invite import InviteButton class Invite(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.invite.usage = lib.format.generate_usage(self.invite) @commands.hybrid_command(name="invite", aliases=["inv"]) async def invite(self, ctx: commands.Context[commands.Bot]) -> None: diff --git a/modules/misc/ping.py b/modules/misc/ping.py index f5a2c72..746830b 100644 --- a/modules/misc/ping.py +++ b/modules/misc/ping.py @@ -1,5 +1,6 @@ from discord.ext import commands +import lib.format from lib.const import CONST from ui.embeds import Builder @@ -7,6 +8,7 @@ from ui.embeds import Builder class Ping(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.ping.usage = lib.format.generate_usage(self.ping) @commands.hybrid_command(name="ping") async def ping(self, ctx: commands.Context[commands.Bot]) -> None: diff --git a/modules/misc/uptime.py b/modules/misc/uptime.py index 81150f9..3169ef5 100644 --- a/modules/misc/uptime.py +++ b/modules/misc/uptime.py @@ -4,6 +4,7 @@ import discord from discord import Embed from discord.ext import commands +import lib.format from lib.const import CONST from ui.embeds import Builder @@ -12,8 +13,9 @@ class Uptime(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot: commands.Bot = bot self.start_time: datetime = discord.utils.utcnow() + self.uptime.usage = lib.format.generate_usage(self.uptime) - @commands.hybrid_command(name="uptime", aliases=["ut"]) + @commands.hybrid_command(name="uptime") async def uptime(self, ctx: commands.Context[commands.Bot]) -> None: """ Uptime command. diff --git a/modules/moderation/ban.py b/modules/moderation/ban.py index 1894316..271b7ff 100644 --- a/modules/moderation/ban.py +++ b/modules/moderation/ban.py @@ -15,8 +15,10 @@ from ui.embeds import Builder class Ban(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.ban.usage = lib.format.generate_usage(self.ban) + self.unban.usage = lib.format.generate_usage(self.unban) - @commands.hybrid_command(name="ban") + @commands.hybrid_command(name="ban", aliases=["b"]) @commands.has_permissions(ban_members=True) @commands.bot_has_permissions(ban_members=True) @commands.guild_only() diff --git a/modules/moderation/cases.py b/modules/moderation/cases.py index a452994..187b93f 100644 --- a/modules/moderation/cases.py +++ b/modules/moderation/cases.py @@ -4,6 +4,7 @@ import discord from discord.ext import commands from reactionmenu import ViewButton, ViewMenu +import lib.format from lib.case_handler import edit_case_modlog from lib.const import CONST from lib.exceptions import LumiException @@ -46,6 +47,10 @@ def create_case_view_menu(ctx: commands.Context[commands.Bot]) -> ViewMenu: class Cases(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.view_case_by_number.usage = lib.format.generate_usage(self.view_case_by_number) + self.view_all_cases_in_guild.usage = lib.format.generate_usage(self.view_all_cases_in_guild) + self.view_all_cases_by_mod.usage = lib.format.generate_usage(self.view_all_cases_by_mod) + self.edit_case_reason.usage = lib.format.generate_usage(self.edit_case_reason) @commands.hybrid_command(name="case", aliases=["c", "ca"]) @commands.has_permissions(manage_messages=True) diff --git a/modules/moderation/kick.py b/modules/moderation/kick.py index d537bff..42a1b37 100644 --- a/modules/moderation/kick.py +++ b/modules/moderation/kick.py @@ -14,6 +14,7 @@ from ui.embeds import Builder class Kick(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.kick.usage = lib.format.generate_usage(self.kick) @commands.hybrid_command(name="kick", aliases=["k"]) @commands.has_permissions(kick_members=True) diff --git a/modules/moderation/slowmode.py b/modules/moderation/slowmode.py index 87bf0f1..a2651c0 100644 --- a/modules/moderation/slowmode.py +++ b/modules/moderation/slowmode.py @@ -4,6 +4,7 @@ import discord from discord import app_commands from discord.ext import commands +import lib.format from lib.const import CONST from lib.exceptions import LumiException from lib.format import format_duration_to_seconds @@ -12,6 +13,7 @@ from lib.format import format_duration_to_seconds class Slowmode(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.slowmode.usage = lib.format.generate_usage(self.slowmode) async def _set_slowmode( self, diff --git a/modules/moderation/softban.py b/modules/moderation/softban.py index 7634112..e712f73 100644 --- a/modules/moderation/softban.py +++ b/modules/moderation/softban.py @@ -4,7 +4,7 @@ from typing import cast import discord from discord.ext import commands -import lib.format as formatter +import lib.format from lib.actionable import async_actionable from lib.case_handler import create_case from lib.const import CONST @@ -14,6 +14,7 @@ from ui.embeds import Builder class Softban(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.softban.usage = lib.format.generate_usage(self.softban) @commands.hybrid_command(name="softban", aliases=["sb"]) @commands.has_permissions(ban_members=True) @@ -67,7 +68,7 @@ class Softban(commands.Cog): target, reason=CONST.STRINGS["mod_reason"].format( ctx.author.name, - formatter.shorten(output_reason, 200), + lib.format.shorten(output_reason, 200), ), delete_message_seconds=86400, ) diff --git a/modules/moderation/timeout.py b/modules/moderation/timeout.py index eb010d8..a7da908 100644 --- a/modules/moderation/timeout.py +++ b/modules/moderation/timeout.py @@ -16,6 +16,8 @@ from ui.embeds import Builder class Timeout(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.timeout.usage = lib.format.generate_usage(self.timeout) + self.untimeout.usage = lib.format.generate_usage(self.untimeout) @commands.hybrid_command(name="timeout", aliases=["t", "to"]) @commands.has_permissions(moderate_members=True) diff --git a/modules/moderation/warn.py b/modules/moderation/warn.py index 14cc496..c10807e 100644 --- a/modules/moderation/warn.py +++ b/modules/moderation/warn.py @@ -4,6 +4,7 @@ from typing import cast import discord from discord.ext import commands +import lib.format from lib.actionable import async_actionable from lib.case_handler import create_case from lib.const import CONST @@ -14,6 +15,7 @@ from ui.embeds import Builder class Warn(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.warn.usage = lib.format.generate_usage(self.warn) @commands.hybrid_command(name="warn", aliases=["w"]) @commands.has_permissions(manage_messages=True)