跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

如何在 Discord.py 中正确将 Slash 命令注册到 Cog 中

本文详解为何加载 Cog 后显示 “0 commands synced”,核心原因在于混淆了传统文本命令(@commands.command)与应用命令(@app_commands.command)的注册机制,需使用正确的装饰器并确保 Cog 正确支持 Slash 命令。 本文详解为何加载 cog 后显示 “0 commands synced”,核心原因在于混淆了传统文本命令(`@commands.command`)与应用命令(`@app_commands.command`)的注册机制,需使用正确的装饰器并确保 cog 正确支持 slash 命令。 在 Discord.py 2.0+(尤其是启用 discord.app_commands 的 Slash 命令场景)中, Cog 必须显式继承 app_commands.Group 或通过 @app_commands.command 定义命令,并配合 Tree.sync() 才能被识别为可同步的全局/服务器命令 。你当前的代码中使用了 @commands.command(name="say") —— 这是一个传统的前缀命令(如 .say hello),它 完全不会被 client.tree.sync() 检测或同步 ,因此日志中始终显示 synced 0 commands,且无法在 Discord 客户端看到或触发 /say。 ✅ 正确做法:在 Cog 中定义 Slash 命令 你需要将命令装饰器从 @commands.command 改为 @app_commands.command,并确保该命令定义在继承自 commands.Cog 的类中(无需额外继承 app_commands.Group,除非需分组)。同时,setup() 函数必须调用 await client.add_cog(...),这是 Discord.py 加载 Slash 命令 Cog 的标准入口。 以下是修复后的 say_cog.py 示例(建议文件名小写、无空格):
import discord from discord import app_commands from discord.ext import commands class SayCog(commands.Cog): def __init__(self, client: commands.Bot): self.client = client @app_commands.command( name="say", description="让机器人发送指定消息(仅管理员可用)" ) @app_commands.describe(thing_to_say="要发送的文本内容") @app_commands.checks.has_permissions(administrator=True) async def say(self, interaction: discord.Interaction, thing_to_say: str): # 注意:app_commands.command 不支持 None 类型参数的默认值处理, # 若需可选参数,请使用 app_commands.Range[str, 1, 2000] 或保留必填 + 提供帮助说明 await interaction.response.send_message(f"✅ 已发送:{thing_to_say}") # 可选:添加权限检查的错误处理器 @say.error async def say_error(self, interaction: discord.Interaction, error: app_commands.AppCommandError): if isinstance(error, app_commands.MissingPermissions): await interaction.response.send_message("❌ 你没有管理员权限,无法使用此命令。", ephemeral=True) else: await interaction.response.send_message("⚠️ 命令执行出错,请联系开发者。", ephemeral=True) # 必须提供 setup 函数,且签名需为 async def setup(bot: commands.Bot) async def setup(client: commands.Bot): await client.add_cog(SayCog(client))
⚠️ 关键注意事项 装饰器不可混用 :@commands.command 和 @app_commands.command 是两类独立系统,前者用于 .prefix 命令,后者用于 /slash 命令;二者不能共存于同一函数。 参数类型约束 :app_commands.command 的参数不支持 str | None 写法(会引发同步失败)。如需可选文本,请改用 str = "" 默认值 + 逻辑判断,或使用 app_commands.Transform 自定义转换器。 权限检查推荐用 @app_commands.checks :如 @app_commands.checks.has_permissions(administrator=True),比手动 if not interaction.user.guild_permissions... 更安全、更易维护,且自动返回标准拒绝响应。 setup() 是唯一加载入口 :确保 main.py 中 await client.load_extension("cogs.say_cog")(注意模块名匹配文件名),且 say_cog.py 位于 cogs/ 目录下。 同步时机很重要 :client.tree.sync() 应在所有 Cog 加载完成后调用(你当前代码中放在 on_ready 内是正确的),但首次同步可能需等待 Discord API 缓存刷新(最多 1 小时),可加 guild=discord.Object(id=YOUR_GUILD_ID) 实现测试服即时同步。 ✅ 验证是否成功 启动 Bot 后查看控制台输出:应显示 synced 1 commands; 在 Discord 中输入 /,检查是否出现 /say 命令; 若未出现,尝试重启 Bot、清空客户端缓存,或在开发服务器中指定 guild 参数进行局部同步(调试更高效)。 遵循以上规范,你的 Slash 命令即可被正确识别、同步并投入使用。记住: Cog 中的 Slash 命令 = @app_commands.command + await client.add_cog() + client.tree.sync() —— 缺一不可。

相关文章