> ## Documentation Index
> Fetch the complete documentation index at: https://bun.zhcndoc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 创建一个 Discord 机器人

Discord.js 可直接运行在 Bun 上，无需额外配置。本指南将构建一个响应 `/ping` 斜杠命令的机器人：你只需注册一次命令，然后启动机器人并在你的服务器中使用它。如果这是你第一次创建机器人，建议在读到每个代码块时就直接复制。

***

为你的机器人创建一个文件夹，并使用 `bun init` 进行初始化。出现提示时选择默认选项。

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
mkdir my-bot
cd my-bot
bun init
```

***

将 Discord.js 添加到项目中。

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun add discord.js
```

***

你的机器人需要自己的账号，你需要在 Discord 的开发者门户中创建它。打开 [开发者门户](https://discord.com/developers/applications)，登录，然后创建一个 **Application**。进入后，打开 **Bot** 选项卡来创建机器人用户。如果你遇到困难，Discord 的 [设置教程](https://discordjs.guide/legacy/preparations/app-setup) 有截图可供参考。

从门户中复制两个值：

* **Bot** 选项卡中的 **token**。它是代码用于登录的密码，所以请像对待密码一样保密。
* **General Information** 选项卡中的 **Application ID**。Discord 使用它将你的命令绑定到这个应用。

***

机器人在被邀请到服务器之前，无法在服务器中执行任何操作。在门户的 **OAuth2** 部分，生成一个带有 `bot` 和 `applications.commands` 作用域的邀请链接，打开它，并将机器人添加到你管理的服务器中。斜杠命令需要 `applications.commands` 作用域，所以不要跳过它。最简单的起点是你自己用于测试的个人服务器，Discord 的 [添加机器人指南](https://discordjs.guide/legacy/preparations/adding-your-app) 也有带截图的步骤说明。

***

你还需要服务器的 ID，才能在该服务器中注册命令。在 Discord 中，打开 **Settings > Advanced > Developer Mode**，然后右键单击服务器图标并选择 **Copy Server ID**。

***

将这三个值保存到 `.env.local` 中。Bun 会在启动时读取这个文件并将其加载到 `process.env`，因此你的代码里不会出现任何密钥。

```ini .env.local icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
DISCORD_TOKEN=your-bot-token
DISCORD_CLIENT_ID=your-application-id
DISCORD_GUILD_ID=your-server-id
```

***

在提交任何内容之前，先将 `.env.local` 添加到 `.gitignore` 中。任何读取到 token 的人都可以控制你的机器人，所以它绝不能进入版本控制。

```txt .gitignore icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}}
node_modules
.env.local
```

***

在任何人能使用命令之前，Discord 必须先知道这个命令。使用一个名为 `deploy-commands.ts` 的简短脚本注册 `/ping`。

```ts deploy-commands.ts icon="https://mintcdn.com/bun-zhcndoc/cnUTwgMuf4cCrwC-/icons/typescript.svg?fit=max&auto=format&n=cnUTwgMuf4cCrwC-&q=85&s=e7767043c9e885c34f2d6c8fe2a95217" theme={"theme":{"light":"github-light","dark":"dracula"}}
import { REST, Routes, SlashCommandBuilder } from "discord.js";

const { DISCORD_TOKEN, DISCORD_CLIENT_ID, DISCORD_GUILD_ID } = process.env;
if (!DISCORD_TOKEN || !DISCORD_CLIENT_ID || !DISCORD_GUILD_ID) {
  throw new Error("在 .env.local 中设置 DISCORD_TOKEN、DISCORD_CLIENT_ID 和 DISCORD_GUILD_ID");
}

// 你想要注册的命令
const commands = [new SlashCommandBuilder().setName("ping").setDescription("回复 Pong!").toJSON()];

const rest = new REST().setToken(DISCORD_TOKEN);

// 在你的测试服务器中注册它们
await rest.put(Routes.applicationGuildCommands(DISCORD_CLIENT_ID, DISCORD_GUILD_ID), { body: commands });

console.log("已注册 /ping");
```

运行一次即可。

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun run deploy-commands.ts
```

只有在你添加命令，或者更改命令名称或描述时，才需要再次运行它，而不是每次机器人启动时都运行。注册到你的服务器而不是全局注册，可以让命令只在你的测试范围内可用。

***

接下来是机器人本体。将其保存为 `bot.ts`。

```ts bot.ts icon="https://mintcdn.com/bun-zhcndoc/cnUTwgMuf4cCrwC-/icons/typescript.svg?fit=max&auto=format&n=cnUTwgMuf4cCrwC-&q=85&s=e7767043c9e885c34f2d6c8fe2a95217" theme={"theme":{"light":"github-light","dark":"dracula"}}
import { Client, Events, GatewayIntentBits } from "discord.js";

const { DISCORD_TOKEN } = process.env;
if (!DISCORD_TOKEN) {
  throw new Error("在 .env.local 中设置 DISCORD_TOKEN");
}

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

// 在机器人连接后立即运行一次
client.once(Events.ClientReady, readyClient => {
  console.log(`Logged in as ${readyClient.user.tag}`);
});

// 每次有人使用斜杠命令时运行
client.on(Events.InteractionCreate, async interaction => {
  if (!interaction.isChatInputCommand()) return;

  if (interaction.commandName === "ping") {
    await interaction.reply("Pong!");
  }
});

client.login(DISCORD_TOKEN);
```

ready 处理器会在机器人连接后输出一行日志。之后，只要有人使用斜杠命令，`interactionCreate` 就会运行；它会确认命令是否为 `/ping`，并回复 `Pong!`。

***

使用 `bun run` 启动机器人。

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun run bot.ts
```

首次连接需要几秒钟。等登录信息打印出来后，切换到 Discord，在你的服务器中输入 `/ping`。

```txt theme={"theme":{"light":"github-light","dark":"dracula"}}
Logged in as my-bot#1234
```

机器人会回复 `Pong!`。你已经拥有一个可工作的 Discord 机器人了。

***

要添加另一个命令，只需在 `deploy-commands.ts` 中定义它，再运行一次脚本，并在 `bot.ts` 中为它的名称添加一个 `if` 分支。[Discord.js 文档](https://discord.js.org/docs) 涵盖了命令选项、权限、按钮、嵌入消息以及 API 的其余部分。

***

当你部署时，不需要构建或打包步骤。Bun 会直接运行 `bot.ts` 及其导入的每个文件，因此你可以原样部署源码，并使用开发时相同的 `bun run bot.ts` 启动它。

`deploy-commands.ts` 会在你的测试服务器中注册 `/ping`，这在开发阶段是正确的作用范围。若要将机器人发布到它加入的每个服务器中，请改为全局注册：将路由改为 `Routes.applicationCommands(DISCORD_CLIENT_ID)`。全局注册不需要服务器，因此你也可以从脚本的检查和 `.env.local` 中移除 `DISCORD_GUILD_ID`。

为了让机器人保持在线，并在崩溃或重启后恢复运行，请在进程管理器下运行它。

<Columns cols={2}>
  <Card title="systemd" href="/guides/ecosystem/systemd" icon="server">
    将你的机器人作为 Linux 守护进程运行
  </Card>

  <Card title="PM2" href="/guides/ecosystem/pm2" icon="cog">
    使用 PM2 管理你的机器人
  </Card>
</Columns>
