如何在 discord.py 中通过 Slash 命令检测用户是否提及了成员

本文详解如何在 discord.py 的 `@app_commands`(slash 命令)中,通过类型提示自动解析并验证用户是否提及了有效成员,并给出清晰的响应逻辑与健壮的错误处理。

在使用 discord.py 构建 Slash 命令时,无需手动解析消息文本中的 @ 提及——Discord 客户端会在用户选择成员时,自动将该成员作为结构化参数传递给后端。关键在于:正确声明参数类型,并利用可选参数 + 类型安全机制实现“有无提及”的逻辑判断

以你的 /ping 命令为例,原始代码中将 kimi: str 作为纯字符串接收,这会导致 Discord 无法识别提及意图,也无法自动补全/校验成员,更无法保证输入是合法用户。正确做法是将参数类型设为 discord.Member(或 discord.User),并设为可选(=None)。Discord.py 会自动完成以下工作:

  • 若用户在命令中选择了某位成员(如 /ping kimi:@Arda),kimi 将被实例化为 Member 对象;
  • 若用户未提供该参数,kimi 值为 None,此时可触发提示逻辑;
  • 所有无效提及(如已退出服务器的用户、不存在的 ID)会被 Discord 前端拦截,不会传入命令;即使极端情况发生,也可额外加 try/except 防御。

✅ 正确实现如下:

@bot.tree.command(name="ping")
@app_commands.describe(kimi="要提及的服务器成员(必填)")
async def ping(interaction: discord.Interaction, kimi: discord.Member = None):
    if kimi is None:
        await interaction.response.send_message("❌ You should mention someone!", ephemeral=True)
        return
    await interaction.response.send_message(
        f"✅ {interaction.user.mention} mentioned {kimi.mention}!",
        allowed_mentions=discord.AllowedMentions(users=True)  # 确保提及能被正常展示(非默认禁用)
    )

? 重要注意事项:

  • ephemeral=True 可让提示仅对执行者可见,提升用户体验(如错误提示);
  • allowed_mentions 参数必须显式设置,否则 kimi.mention 在响应中可能显示为纯文本(如 而不触发高亮),尤其在私信或受限频道中更易失效;
  • 若需支持跨服务器用户(如 Bot 公共命令),应改用 discord.User 类型(但无法获取昵称、角色等服务器专属信息);
  • 不推荐使用 str 类型 + 手动正则匹配 @(如 re.search(r'', message)),因为该方式绕过 Discord 安全校验,易受伪造 ID、格式错误、权限越界等风险影响,且不兼容前端自动补全与类型提示。

? 进阶建议:
若希望命令更友好,可添加 @app_commands.choices() 或自定义 Autocomplete 实现成员搜索补全;如需检测「消息内容中是否包含提及」(非参数形式,例如监听普通消息),则需监听 on_message 并结合 message.mentions 属性——但该场景与 Slash 命令设计初衷相悖,应优先采用参数化交互。

综上,Discord.py 的 Slash 命令本质是结构化 API 调用,“提及”不是文本特征,而是语义参数——善用类型系统,既简洁又安全。