You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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并非有效变量,无法匹配用户输入的命令名,导致子帮助功能无法触发。

可行实现方案

思路

  1. 维护一个命令详情字典,统一存储每个命令的使用格式、功能描述、参数说明;
  2. 在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` 查看所有命令列表")

关键修改点

  1. 新增command_details字典,统一管理所有命令的详细信息,后续新增命令只需在字典中补充;
  2. 替换原无效
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 23:55:19