如何为discord.py机器人实现子帮助命令功能
Discord.py 机器人子帮助功能实现方案
我已经完成了discord.py机器人的基础分页帮助命令,现在需要添加子帮助功能:当用户输入;help 命令名(例如;help mute)时,展示对应命令的详细使用方法,包括参数说明,类似Dyno机器人的?help <命令名>功能。之前尝试的代码未生效,求可行实现方案,附原代码:
@client.hybrid_command(name = "help", with_app_command=True, description="Get a list of commands") @commands.guild_only() async def help(ctx, arg = None): pages = 3 cur_page = 1 roleplayembed = discord.Embed(color=embedcolor, title="Roleplay Commands") roleplayembed.add_field(name=f"{client.command_prefix}Cuddle", value="Cuddle a user and add a message(Optional)",inline=False) roleplayembed.add_field(name=f"{client.command_prefix}Hug", value="Hug a user and add a message(Optional)",inline=False) roleplayembed.add_field(name=f"{client.command_prefix}Kiss", value="Kiss a user and add a message(Optional)",inline=False) roleplayembed.add_field(name=f"{client.command_prefix}Slap", value="Slap a user and add a message(Optional)",inline=False) roleplayembed.add_field(name=f"{client.command_prefix}Pat", value="Pat a user and add a message(Optional)",inline=False) roleplayembed.set_footer(text=f"Page {cur_page+1} of {pages}") roleplayembed.timestamp = datetime.datetime.utcnow() basicembed = discord.Embed(color=embedcolor, title="Basic Commands") basicembed.add_field(name=f"{client.command_prefix}Waifu", value="Posts a random AI Generated Image of a waifu",inline=False) basicembed.add_field(name=f"{client.command_prefix}8ball", value="Works as an 8 ball",inline=False) basicembed.add_field(name=f"{client.command_prefix}Ara", value="Gives you a random ara ara from Kurumi Tokisaki",inline=False) basicembed.add_field(name=f"{client.command_prefix}Wikipedia", value="Search something up on the wiki",inline=False) basicembed.add_field(name=f"{client.command_prefix}Userinfo", value="Look up info about a user",inline=False) basicembed.add_field(name=f"{client.command_prefix}Ask", value="Ask the bot a question",inline=False) basicembed.add_field(name=f"{client.command_prefix}Askwhy", value="Ask the boy a question beginning with 'why'",inline=False) basicembed.add_field(name=f"{client.command_prefix}Avatar", value="Get a user's avatar or your own avatar",inline=False) basicembed.set_footer(text=f"Page {cur_page} of {pages}") basicembed.timestamp = datetime.datetime.utcnow() moderationembed = discord.Embed(color=embedcolor, title="Moderation Commands") moderationembed.add_field(name=f"{client.command_prefix}Kick", value="Kick a member",inline=False) moderationembed.add_field(name=f"{client.command_prefix}Ban", value="Ban a member",inline=False) moderationembed.add_field(name=f"{client.command_prefix}Slowmode", value="Set the slowmode of a channel",inline=False) moderationembed.add_field(name=f"{client.command_prefix}Purge", value="Purge an amount of messages in a channel",inline=False) moderationembed.add_field(name=f"{client.command_prefix}Mute", value="Mute a member for a time and reason",inline=False) moderationembed.add_field(name=f"{client.command_prefix}Unmute", value="Unmute a member for a time and reason",inline=False) moderationembed.set_footer(text=f"Page {cur_page+2} of {pages}") moderationembed.timestamp = datetime.datetime.utcnow() contents = [basicembed, roleplayembed, moderationembed] if arg == None: message = await ctx.send(embed=contents[cur_page-1]) await message.add_reaction("◀️") await message.add_reaction("▶️") def check(reaction, user): return user == ctx.author and str(reaction.emoji) in ["◀️", "▶️"] while True: try: reaction, user = await client.wait_for("reaction_add", timeout=60, check=check) if str(reaction.emoji) == "▶️": cur_page += 1 elif str(reaction.emoji) == "◀️": cur_page -= 1 if cur_page > pages: #check if forward on last page cur_page = 1 elif cur_page < 1: #check if back on first page cur_page = pages await message.edit(embed=contents[cur_page-1]) await message.remove_reaction(reaction, user) except asyncio.TimeoutError: await message.delete() break if arg.lower() == client.command_name: await ctx.reply(f"{client.command_prefix}{client.command_name}{client.command_argument}")
原代码问题分析
原代码中处理子帮助的逻辑if arg.lower() == client.command_name:完全无效,client.command_name并非有效变量,无法匹配用户输入的命令名,导致子帮助功能无法触发。
可行实现方案
思路
- 维护一个命令详情字典,统一存储每个命令的使用格式、功能描述、参数说明;
- 在help命令中判断用户是否传入参数:
- 无参数时,保留原分页帮助逻辑;
- 有参数时,匹配字典中的命令,存在则生成详细帮助Embed,不存在则提示用户。
修改后的完整代码
import discord from discord import app_commands from discord.ext import commands import datetime import asyncio # 自定义Embed颜色,可根据需求修改 embedcolor = discord.Color.blue() # 核心:命令详情字典,新增命令只需在此补充 command_details = { "cuddle": { "usage": f"{client.command_prefix}cuddle <用户> [消息]", "description": "拥抱指定用户,可附加自定义消息(可选)", "arguments": "- `<用户>`: 要拥抱的服务器成员(@提及或ID)\n- `[消息]`: 可选的自定义消息内容" }, "hug": { "usage": f"{client.command_prefix}hug <用户> [消息]", "description": "抱抱指定用户,可附加自定义消息(可选)", "arguments": "- `<用户>`: 要抱抱的服务器成员(@提及或ID)\n- `[消息]`: 可选的自定义消息内容" }, "kiss": { "usage": f"{client.command_prefix}kiss <用户> [消息]", "description": "亲吻指定用户,可附加自定义消息(可选)", "arguments": "- `<用户>`: 要亲吻的服务器成员(@提及或ID)\n- `[消息]`: 可选的自定义消息内容" }, "slap": { "usage": f"{client.command_prefix}slap <用户> [消息]", "description": "打指定用户一下,可附加自定义消息(可选)", "arguments": "- `<用户>`: 要打的服务器成员(@提及或ID)\n- `[消息]`: 可选的自定义消息内容" }, "pat": { "usage": f"{client.command_prefix}pat <用户> [消息]", "description": "拍拍指定用户,可附加自定义消息(可选)", "arguments": "- `<用户>`: 要拍的服务器成员(@提及或ID)\n- `[消息]`: 可选的自定义消息内容" }, "waifu": { "usage": f"{client.command_prefix}waifu", "description": "发送一张随机AI生成的二次元老婆图片", "arguments": "无参数" }, "8ball": { "usage": f"{client.command_prefix}8ball <问题>", "description": "模拟魔法8球回答你的问题", "arguments": "- `<问题>`: 你要询问的问题内容" }, "ara": { "usage": f"{client.command_prefix}ara", "description": "发送时崎狂三的随机「あらあら」内容", "arguments": "无参数" }, "wikipedia": { "usage": f"{client.command_prefix}wikipedia <关键词>", "description": "在维基百科上搜索指定关键词的内容", "arguments": "- `<关键词>`: 要搜索的维基百科词条关键词" }, "userinfo": { "usage": f"{client.command_prefix}userinfo [用户]", "description": "查看指定用户的服务器信息,不填则查看自己的信息", "arguments": "- `[用户]`: 可选,要查看的服务器成员(@提及或ID)" }, "ask": { "usage": f"{client.command_prefix}ask <问题>", "description": "向机器人提问任意问题", "arguments": "- `<问题>`: 你要提问的内容" }, "askwhy": { "usage": f"{client.command_prefix}askwhy <问题>", "description": "向机器人提问以「为什么」开头的问题", "arguments": "- `<问题>`: 以「为什么」开头的提问内容" }, "avatar": { "usage": f"{client.command_prefix}avatar [用户]", "description": "获取指定用户的头像,不填则获取自己的头像", "arguments": "- `[用户]`: 可选,要获取头像的服务器成员(@提及或ID)" }, "kick": { "usage": f"{client.command_prefix}kick <用户> [原因]", "description": "踢出服务器中的指定成员", "arguments": "- `<用户>`: 要踢出的服务器成员(@提及或ID)\n- `[原因]`: 可选,踢出原因" }, "ban": { "usage": f"{client.command_prefix}ban <用户> [原因]", "description": "封禁服务器中的指定成员", "arguments": "- `<用户>`: 要封禁的服务器成员(@提及或ID)\n- `[原因]`: 可选,封禁原因" }, "slowmode": { "usage": f"{client.command_prefix}slowmode <时长>", "description": "设置当前频道的慢模式时长", "arguments": "- `<时长>`: 慢模式间隔秒数,设为0则关闭慢模式" }, "purge": { "usage": f"{client.command_prefix}purge <数量>", "description": "批量删除当前频道中的指定数量消息", "arguments": "- `<数量>`: 要删除的消息数量(1-100)" }, "mute": { "usage": f"{client.command_prefix}mute <用户> <时长> [原因]", "description": "将指定成员静音一段时间", "arguments": "- `<用户>`: 要静音的服务器成员(@提及或ID)\n- `<时长>`: 静音时长,格式如`1h`(1小时)、`30m`(30分钟)、`1d`(1天)\n- `[原因]`: 可选,静音原因" }, "unmute": { "usage": f"{client.command_prefix}unmute <用户> [原因]", "description": "解除指定成员的静音状态", "arguments": "- `<用户>`: 要解除静音的服务器成员(@提及或ID)\n- `[原因]`: 可选,解除静音原因" } } @client.hybrid_command(name="help", with_app_command=True, description="获取命令列表或指定命令的详细帮助") @commands.guild_only() async def help(ctx, arg: str = None): pages = 3 cur_page = 1 # 生成分类帮助Embed(保留原逻辑,优化文本为中文) roleplayembed = discord.Embed(color=embedcolor, title="角色扮演命令") roleplayembed.add_field(name=f"{client.command_prefix}Cuddle", value="拥抱用户,可附加消息(可选)", inline=False) roleplayembed.add_field(name=f"{client.command_prefix}Hug", value="抱抱用户,可附加消息(可选)", inline=False) roleplayembed.add_field(name=f"{client.command_prefix}Kiss", value="亲吻用户,可附加消息(可选)", inline=False) roleplayembed.add_field(name=f"{client.command_prefix}Slap", value="打用户一下,可附加消息(可选)", inline=False) roleplayembed.add_field(name=f"{client.command_prefix}Pat", value="拍拍用户,可附加消息(可选)", inline=False) roleplayembed.set_footer(text=f"第 {cur_page+1} 页,共 {pages} 页") roleplayembed.timestamp = datetime.datetime.utcnow() basicembed = discord.Embed(color=embedcolor, title="基础命令") basicembed.add_field(name=f"{client.command_prefix}Waifu", value="发送随机AI生成的二次元老婆图片", inline=False) basicembed.add_field(name=f"{client.command_prefix}8ball", value="模拟魔法8球回答问题", inline=False) basicembed.add_field(name=f"{client.command_prefix}Ara", value="发送时崎狂三的随机「あらあら」内容", inline=False) basicembed.add_field(name=f"{client.command_prefix}Wikipedia", value="在维基百科搜索内容", inline=False) basicembed.add_field(name=f"{client.command_prefix}Userinfo", value="查看用户服务器信息", inline=False) basicembed.add_field(name=f"{client.command_prefix}Ask", value="向机器人提问任意问题", inline=False) basicembed.add_field(name=f"{client.command_prefix}Askwhy", value="向机器人提问「为什么」类问题", inline=False) basicembed.add_field(name=f"{client.command_prefix}Avatar", value="获取用户头像", inline=False) basicembed.set_footer(text=f"第 {cur_page} 页,共 {pages} 页") basicembed.timestamp = datetime.datetime.utcnow() moderationembed = discord.Embed(color=embedcolor, title=" moderation命令") moderationembed.add_field(name=f"{client.command_prefix}Kick", value="踢出成员", inline=False) moderationembed.add_field(name=f"{client.command_prefix}Ban", value="封禁成员", inline=False) moderationembed.add_field(name=f"{client.command_prefix}Slowmode", value="设置频道慢模式", inline=False) moderationembed.add_field(name=f"{client.command_prefix}Purge", value="批量删除消息", inline=False) moderationembed.add_field(name=f"{client.command_prefix}Mute", value="静音成员一段时间,可添加原因", inline=False) moderationembed.add_field(name=f"{client.command_prefix}Unmute", value="解除成员静音,可添加原因", inline=False) moderationembed.set_footer(text=f"第 {cur_page+2} 页,共 {pages} 页") moderationembed.timestamp = datetime.datetime.utcnow() contents = [basicembed, roleplayembed, moderationembed] if arg is None: # 无参数时展示分页帮助(保留原逻辑) message = await ctx.send(embed=contents[cur_page-1]) await message.add_reaction("◀️") await message.add_reaction("▶️") def check(reaction, user): return user == ctx.author and str(reaction.emoji) in ["◀️", "▶️"] while True: try: reaction, user = await client.wait_for("reaction_add", timeout=60, check=check) if str(reaction.emoji) == "▶️": cur_page += 1 elif str(reaction.emoji) == "◀️": cur_page -= 1 if cur_page > pages: cur_page = 1 elif cur_page < 1: cur_page = pages await message.edit(embed=contents[cur_page-1]) await message.remove_reaction(reaction, user) except asyncio.TimeoutError: await message.delete() break else: # 有参数时处理子帮助 cmd_name = arg.lower() if cmd_name in command_details: # 生成详细帮助Embed cmd_info = command_details[cmd_name] help_embed = discord.Embed(color=embedcolor, title=f"命令帮助:{cmd_name.capitalize()}") help_embed.add_field(name="使用格式", value=f"`{cmd_info['usage']}`", inline=False) help_embed.add_field(name="命令描述", value=cmd_info['description'], inline=False) help_embed.add_field(name="参数说明", value=cmd_info['arguments'], inline=False) help_embed.timestamp = datetime.datetime.utcnow() await ctx.reply(embed=help_embed) else: # 命令不存在时提示 await ctx.reply(f"未找到命令 `{arg}`,输入 `{client.command_prefix}help` 查看所有命令列表")
关键修改点
- 新增
command_details字典,统一管理所有命令的详细信息,后续新增命令只需在字典中补充; - 替换原无效
相关产品推荐
相关产品推荐

