导读:本期聚焦于黑豹创作的《如何让 Discord 机器人在启动时自动发送其 Slash 命令对应的内容》,敬请观看详情。想让 Discord 机器人在上线那一刻就主动把 Slash 命令的用法或欢迎信息推送到指定频道?本文围绕 discord.py 和 discord.js 两种主流框架,详细讲解 on_ready 钩子的正确使用方式,包括如何获取已注册的斜杠命令列表、通过 fetch_commands 或 REST API 读取命令描述、以及在启动时自动发送命令帮助内容的完整实现思路。文中还分析了同步延迟、事件重复触发、 intents 权限缺失等常见坑点,并给出可直接运行的示例代码,帮你快速实现机器人启动即推送命令说明的效果。

不少人在写 Discord 机器人时会想到一个需求:机器人一上线,就自动把当前可用的 Slash 命令清单或对应的帮助内容发到某个频道,方便群成员第一时间了解能用哪些指令。这个需求看起来简单,但实际实现时涉及事件钩子的选择、命令对象的读取方式以及频道权限的获取,稍不注意就会踩坑。本文以 Python 的 discord.py 为主、discord.js 为辅,完整讲解实现思路。

如何让 Discord 机器人在启动时自动发送其 Slash 命令对应的内容

一、核心思路:在 on_ready 中读取并推送命令

discord.py 提供了 setup_hook 和 on_ready 两个可以用来做启动逻辑的钩子。两者的区别在于触发时机:setup_hook 在机器人登录完成、但还没有连接到网关之前触发,此时不能进行任何需要网关连接的操作;而 on_ready 在与 Discord 网关建立连接后触发,此时可以正常获取频道、发送消息。因此发送消息的操作要放在 on_ready 或者 setup_hook 中通过 await bot.wait_until_ready() 等待就绪后再执行。

另一个需要注意的点是 on_ready 并不保证只触发一次。网络波动导致重连时,这个事件会被再次调用,如果不做防护,机器人会把命令列表重复发送多次。常见的处理办法是用一个模块级布尔变量做标记,或者在第一次发送后取消监听。

二、用 discord.py 获取 Slash 命令并自动发送

discord.py 从 2.0 版本开始原生支持应用命令,通过 bot.tree 可以访问已注册的斜杠命令。注意 bot.tree.get_commands() 拿到的是本地缓存的命令对象,如果命令尚未同步到 Discord 服务器,本地列表和实际列表可能不一致。更稳妥的做法是调用 await bot.tree.fetch_commands(),它会向 Discord 发起真实请求,返回全局命令;如果命令注册在特定服务器(guild),则需要传入 guild 参数。

下面的示例演示了完整流程:机器人就绪后,拉取已同步的 Slash 命令,把命令名和描述拼成一条消息,发送到指定频道。频道获取可以通过 ID 也可以通过名称加服务器对象。

import discord
from discord import app_commands
from discord.ext import commands

TOKEN = "你的机器人令牌"
CHANNEL_ID = 123456789012345678  # 要推送的频道ID

class MyBot(commands.Bot):
    def __init__(self):
        super().__init__(command_prefix="!", intents=discord.Intents.default())

    async def setup_hook(self):
        # 同步斜杠命令到当前服务器(开发阶段建议绑定单个guild,同步更快)
        guild = discord.Object(id=987654321098765432)
        self.tree.copy_global_to(guild=guild)
        await self.tree.sync(guild=guild)

bot = MyBot()

@bot.tree.command(name="ping", description="测试延迟")
async def ping(interaction: discord.Interaction):
    await interaction.response.send_message("pong!")

_sent = False

@bot.event
async def on_ready():
    global _sent
    if _sent:  # 防止重连时重复发送
        return
    _sent = True
    # 从 Discord 服务器拉取真实已注册的命令
    cmds = await bot.tree.fetch_commands()
    lines = [f"/{c.name} —— {c.description or '暂无描述'}" for c in cmds]
    embed = discord.Embed(
        title="我已上线,以下是当前可用的命令",
        description="\n".join(lines) if lines else "暂无命令",
        color=discord.Color.green()
    )
    channel = bot.get_channel(CHANNEL_ID)
    if channel is None:
        channel = await bot.fetch_channel(CHANNEL_ID)
    await channel.send(embed=embed)

bot.run(TOKEN)

代码里有几个细节值得说明。第一,copy_global_to 加 sync(guild=...) 的组合适合开发阶段,命令会立刻在目标服务器生效;上线后再改成全局同步即可。第二,fetch_commands 返回的对象类型是 app_commands.AppCommand,它和装饰器注册时的 Command 对象不同,前者是 Discord 返回的原始数据,包含命令 ID、描述、选项等字段,适合用来生成帮助文本。第三,发送前最好判断频道类型,避免机器人被拉进语音频道类目时报错。

三、用 discord.js 实现同样的效果

如果技术栈是 Node.js,思路完全一致:在 Client 的 ready 事件中调用 client.application.commands.fetch() 拿到已注册命令,再通过 client.channels.fetch 定位频道发送。discord.js 的事件注册从 v14 开始推荐使用 once 参数,天然解决了重复触发问题。

const { Client, GatewayIntentBits, EmbedBuilder, Events } = require('discord.js');

const client = new Client({ intents: [GatewayIntentBits.Guilds] });

client.once(Events.ClientReady, async (c) => {
    // 拉取全局已注册的斜杠命令
    const cmds = await c.application.commands.fetch();
    const lines = cmds.map(cmd => `/${cmd.name} —— ${cmd.description || '暂无描述'}`);

    const embed = new EmbedBuilder()
        .setTitle('我已上线,以下是当前可用的命令')
        .setDescription(lines.length ? lines.join('\n') : '暂无命令')
        .setColor(0x57F287);

    const channel = await c.channels.fetch('123456789012345678');
    if (channel && channel.isTextBased()) {
        await channel.send({ embeds: [embed] });
    }
});

client.login('你的机器人令牌');

这里用 client.once 代替 client.on,事件只触发一次,不需要额外做防重标记。如果命令是按服务器注册的,则要改成通过 guild.commands.fetch() 获取对应服务器的命令列表。

四、常见坑点与优化建议

首先是消息权限问题。机器人向频道发送消息需要在该频道拥有 Send Messages 和 Embed Links 权限,缺了后者 Embed 会被当作空消息发送失败。上线前建议在服务器设置里给机器人的角色补齐这两个权限,或在代码中捕获 Forbidden 异常并记录日志。

其次是命令同步延迟。全局命令同步有时需要几分钟才生效,如果你发现 fetch_commands 拿到的列表和预期不符,多半是同步还没完成。开发阶段绑定单一 guild 可以把同步时间压缩到秒级,这是官方文档明确推荐的调试方式。

最后可以考虑把推送逻辑做得更通用一些,比如把频道 ID 存到配置文件或数据库,支持多个服务器各自配置推送频道;或者给每条命令加上参数说明和用法示例,让推送出来的内容本身就是一份使用手册。这样机器人每次上线或命令更新后重新推送,群成员始终能看到最新的命令说明,体验会好很多。

Discord机器人Slash命令discord.py修改时间:2026-09-16 00:04:39

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0916/57584.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。