feat: paste detailed help via FlaskPaste for !help command
!help <cmd> now pastes the command's docstring and appends the URL. !help <plugin> pastes detail for all plugin commands. !help (no args) pastes a full reference grouped by plugin. Falls back gracefully when flaskpaste is not loaded or paste fails. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,36 @@
|
||||
"""Core plugin: ping, help, version, plugin management."""
|
||||
|
||||
import asyncio
|
||||
import textwrap
|
||||
from collections import Counter
|
||||
|
||||
from derp import __version__
|
||||
from derp.plugin import command
|
||||
|
||||
|
||||
def _build_cmd_detail(handler, prefix: str) -> str:
|
||||
"""Extract and format a command's docstring into a detail block."""
|
||||
doc = textwrap.dedent(handler.callback.__doc__ or "").strip()
|
||||
if not doc:
|
||||
return ""
|
||||
header = f"{prefix}{handler.name}"
|
||||
if handler.help:
|
||||
header += f" -- {handler.help}"
|
||||
return f"{header}\n{doc}"
|
||||
|
||||
|
||||
async def _paste(bot, text: str) -> str | None:
|
||||
"""Create a paste via FlaskPaste. Returns URL or None."""
|
||||
fp = bot.registry._modules.get("flaskpaste")
|
||||
if not fp:
|
||||
return None
|
||||
loop = asyncio.get_running_loop()
|
||||
try:
|
||||
return await loop.run_in_executor(None, fp.create_paste, bot, text)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
@command("ping", help="Check if the bot is alive")
|
||||
async def cmd_ping(bot, message):
|
||||
"""Respond with pong."""
|
||||
@@ -27,7 +52,13 @@ async def cmd_help(bot, message):
|
||||
handler = bot.registry.commands.get(name)
|
||||
if handler and bot._plugin_allowed(handler.plugin, channel):
|
||||
help_text = handler.help or "No help available."
|
||||
await bot.reply(message, f"{bot.prefix}{name} -- {help_text}")
|
||||
reply = f"{bot.prefix}{name} -- {help_text}"
|
||||
detail = _build_cmd_detail(handler, bot.prefix)
|
||||
if detail:
|
||||
url = await _paste(bot, detail)
|
||||
if url:
|
||||
reply += f" | {url}"
|
||||
await bot.reply(message, reply)
|
||||
return
|
||||
|
||||
# Check plugin
|
||||
@@ -41,7 +72,19 @@ async def cmd_help(bot, message):
|
||||
lines = [f"{name} -- {desc}" if desc else name]
|
||||
if cmds:
|
||||
lines.append(f"Commands: {', '.join(bot.prefix + c for c in cmds)}")
|
||||
await bot.reply(message, " | ".join(lines))
|
||||
reply = " | ".join(lines)
|
||||
# Build detail block for all plugin commands
|
||||
blocks = []
|
||||
for cmd_name in cmds:
|
||||
h = bot.registry.commands[cmd_name]
|
||||
blk = _build_cmd_detail(h, bot.prefix)
|
||||
if blk:
|
||||
blocks.append(blk)
|
||||
if blocks:
|
||||
url = await _paste(bot, "\n\n".join(blocks))
|
||||
if url:
|
||||
reply += f" | {url}"
|
||||
await bot.reply(message, reply)
|
||||
return
|
||||
|
||||
await bot.reply(message, f"Unknown command or plugin: {name}")
|
||||
@@ -52,7 +95,37 @@ async def cmd_help(bot, message):
|
||||
k for k, v in bot.registry.commands.items()
|
||||
if bot._plugin_allowed(v.plugin, channel)
|
||||
)
|
||||
await bot.reply(message, ", ".join(names))
|
||||
reply = ", ".join(names)
|
||||
|
||||
# Build full reference grouped by plugin
|
||||
plugins: dict[str, list[str]] = {}
|
||||
for cmd_name in names:
|
||||
h = bot.registry.commands[cmd_name]
|
||||
plugins.setdefault(h.plugin, []).append(cmd_name)
|
||||
blocks = []
|
||||
for plugin_name in sorted(plugins):
|
||||
mod = bot.registry._modules.get(plugin_name)
|
||||
desc = (getattr(mod, "__doc__", "") or "").split("\n")[0].strip() if mod else ""
|
||||
header = f"[{plugin_name}]"
|
||||
if desc:
|
||||
header += f" {desc}"
|
||||
cmd_lines = []
|
||||
for cmd_name in plugins[plugin_name]:
|
||||
h = bot.registry.commands[cmd_name]
|
||||
detail = _build_cmd_detail(h, bot.prefix)
|
||||
if detail:
|
||||
cmd_lines.append(detail)
|
||||
else:
|
||||
line = f"{bot.prefix}{cmd_name}"
|
||||
if h.help:
|
||||
line += f" -- {h.help}"
|
||||
cmd_lines.append(line)
|
||||
blocks.append(header + "\n" + "\n\n".join(cmd_lines))
|
||||
if blocks:
|
||||
url = await _paste(bot, "\n\n".join(blocks))
|
||||
if url:
|
||||
reply += f" | {url}"
|
||||
await bot.reply(message, reply)
|
||||
|
||||
|
||||
@command("version", help="Show bot version")
|
||||
|
||||
Reference in New Issue
Block a user