Improve help command (#116)
Some checks failed
Deploy MkDocs / deploy (push) Has been cancelled
Some checks failed
Deploy MkDocs / deploy (push) Has been cancelled
This commit is contained in:
parent
17751d3b09
commit
cec747a575
@ -1,6 +1,8 @@
|
||||
from collections import defaultdict
|
||||
from typing import List, Optional
|
||||
|
||||
from .core import Command, CommandContext, CommandHandler
|
||||
from ...utils import Paginator
|
||||
from .core import Command, CommandContext, CommandHandler, Group
|
||||
|
||||
|
||||
class HelpCommand(Command):
|
||||
@ -15,17 +17,12 @@ class HelpCommand(Command):
|
||||
if not cmd or cmd.name.lower() != command.lower():
|
||||
await ctx.send(f"Command '{command}' not found.")
|
||||
return
|
||||
description = cmd.description or cmd.brief or "No description provided."
|
||||
await ctx.send(f"**{ctx.prefix}{cmd.name}**\n{description}")
|
||||
if isinstance(cmd, Group):
|
||||
await self.send_group_help(ctx, cmd)
|
||||
else:
|
||||
lines: List[str] = []
|
||||
for registered in dict.fromkeys(handler.commands.values()):
|
||||
brief = registered.brief or registered.description or ""
|
||||
lines.append(f"{ctx.prefix}{registered.name} - {brief}".strip())
|
||||
if lines:
|
||||
await ctx.send("\n".join(lines))
|
||||
await self.send_command_help(ctx, cmd)
|
||||
else:
|
||||
await ctx.send("No commands available.")
|
||||
await self.send_bot_help(ctx)
|
||||
|
||||
super().__init__(
|
||||
callback,
|
||||
@ -33,3 +30,42 @@ class HelpCommand(Command):
|
||||
brief="Show command help.",
|
||||
description="Displays help for commands.",
|
||||
)
|
||||
|
||||
async def send_bot_help(self, ctx: CommandContext) -> None:
|
||||
groups = defaultdict(list)
|
||||
for cmd in dict.fromkeys(self.handler.commands.values()):
|
||||
key = cmd.cog.cog_name if cmd.cog else "No Category"
|
||||
groups[key].append(cmd)
|
||||
|
||||
paginator = Paginator()
|
||||
for cog_name, cmds in groups.items():
|
||||
paginator.add_line(f"**{cog_name}**")
|
||||
for cmd in cmds:
|
||||
brief = cmd.brief or cmd.description or ""
|
||||
paginator.add_line(f"{ctx.prefix}{cmd.name} - {brief}".strip())
|
||||
paginator.add_line("")
|
||||
|
||||
pages = paginator.pages
|
||||
if not pages:
|
||||
await ctx.send("No commands available.")
|
||||
return
|
||||
for page in pages:
|
||||
await ctx.send(page)
|
||||
|
||||
async def send_command_help(self, ctx: CommandContext, command: Command) -> None:
|
||||
description = command.description or command.brief or "No description provided."
|
||||
await ctx.send(f"**{ctx.prefix}{command.name}**\n{description}")
|
||||
|
||||
async def send_group_help(self, ctx: CommandContext, group: Group) -> None:
|
||||
paginator = Paginator()
|
||||
description = group.description or group.brief or "No description provided."
|
||||
paginator.add_line(f"**{ctx.prefix}{group.name}**\n{description}")
|
||||
if group.commands:
|
||||
for sub in dict.fromkeys(group.commands.values()):
|
||||
brief = sub.brief or sub.description or ""
|
||||
paginator.add_line(
|
||||
f"{ctx.prefix}{group.name} {sub.name} - {brief}".strip()
|
||||
)
|
||||
|
||||
for page in paginator.pages:
|
||||
await ctx.send(page)
|
||||
|
@ -11,7 +11,11 @@ The command handler registers a `help` command automatically. Use it to list all
|
||||
!help ping # shows help for the "ping" command
|
||||
```
|
||||
|
||||
The help command will show each command's brief description if provided.
|
||||
Commands are grouped by their Cog name and paginated so that long help
|
||||
lists are split into multiple messages using the `Paginator` utility.
|
||||
|
||||
If you need custom formatting you can subclass
|
||||
`HelpCommand` and override `send_command_help` or `send_group_help`.
|
||||
|
||||
## Checks
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from disagreement.ext.commands.core import CommandHandler, Command
|
||||
from disagreement.ext import commands
|
||||
from disagreement.ext.commands.core import CommandHandler, Command, Group
|
||||
from disagreement.models import Message
|
||||
|
||||
|
||||
@ -13,15 +14,21 @@ class DummyBot:
|
||||
return {"id": "1", "channel_id": channel_id, "content": content}
|
||||
|
||||
|
||||
class MyCog(commands.Cog):
|
||||
def __init__(self, client) -> None:
|
||||
super().__init__(client)
|
||||
|
||||
@commands.command()
|
||||
async def foo(self, ctx: commands.CommandContext) -> None:
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_help_lists_commands():
|
||||
bot = DummyBot()
|
||||
handler = CommandHandler(client=bot, prefix="!")
|
||||
|
||||
async def foo(ctx):
|
||||
pass
|
||||
|
||||
handler.add_command(Command(foo, name="foo", brief="Foo cmd"))
|
||||
handler.add_cog(MyCog(bot))
|
||||
|
||||
msg_data = {
|
||||
"id": "1",
|
||||
@ -33,6 +40,7 @@ async def test_help_lists_commands():
|
||||
msg = Message(msg_data, client_instance=bot)
|
||||
await handler.process_commands(msg)
|
||||
assert any("foo" in m for m in bot.sent)
|
||||
assert any("MyCog" in m for m in bot.sent)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@ -55,3 +63,39 @@ async def test_help_specific_command():
|
||||
msg = Message(msg_data, client_instance=bot)
|
||||
await handler.process_commands(msg)
|
||||
assert any("Bar desc" in m for m in bot.sent)
|
||||
|
||||
|
||||
from disagreement.ext.commands.help import HelpCommand
|
||||
|
||||
|
||||
class CustomHelp(HelpCommand):
|
||||
async def send_command_help(self, ctx, command):
|
||||
await ctx.send(f"custom {command.name}")
|
||||
|
||||
async def send_group_help(self, ctx, group):
|
||||
await ctx.send(f"group {group.name}")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_custom_help_methods():
|
||||
bot = DummyBot()
|
||||
handler = CommandHandler(client=bot, prefix="!")
|
||||
handler.remove_command("help")
|
||||
handler.add_command(CustomHelp(handler))
|
||||
|
||||
async def sub(ctx):
|
||||
pass
|
||||
|
||||
group = Group(sub, name="grp")
|
||||
handler.add_command(group)
|
||||
|
||||
msg_data = {
|
||||
"id": "1",
|
||||
"channel_id": "c",
|
||||
"author": {"id": "2", "username": "u", "discriminator": "0001"},
|
||||
"content": "!help grp",
|
||||
"timestamp": "t",
|
||||
}
|
||||
msg = Message(msg_data, client_instance=bot)
|
||||
await handler.process_commands(msg)
|
||||
assert any("group grp" in m for m in bot.sent)
|
||||
|
Loading…
x
Reference in New Issue
Block a user