如何使用Node.js构建Discord机器人
作为 Write for DOnations 计划的一部分,作者选择了 Free and Open Source Fund 来接受捐赠。
介绍
Discord 是一个聊天应用程序,它允许全球数百万用户在称为 guilds 或服务器的社区中进行在线消息和语音聊天。 Discord 还提供了一个广泛的 API,开发人员可以使用它来构建强大的 Discord 机器人。 机器人可以执行各种操作,例如向服务器发送消息、DM 用户、管理服务器以及在语音聊天中播放音频。 这允许开发人员制作功能强大的机器人,其中包括高级、复杂的功能,如审核工具甚至游戏。 例如,实用程序机器人 Dyno 为数百万行会提供服务,并包含垃圾邮件防护、音乐播放器和其他实用程序功能等有用功能。 学习如何创建 Discord 机器人可以让您实现许多可能性,每天都有成千上万的人可以与之互动。
在本教程中,您将从头开始构建一个 Discord 机器人,使用 Node.js 和 Discord.js 库,它允许用户直接与 Discord API 交互。 您将为 Discord 机器人设置配置文件,获取机器人的身份验证令牌,并对机器人进行编程,使其能够处理带有用户参数的命令。
先决条件
在开始之前,您将需要以下内容:
- Node.js 安装在您的开发机器上。 要在 macOS 或 Ubuntu 20.04 上安装它,请按照 如何在 macOS 上安装 Node.js 和创建本地开发环境中的步骤或 使用 NodeSource PPA 使用 Apt 安装 Node.js [X207X ] 如何在 Ubuntu 20.04 上安装 Node.js 部分。
- 您选择的任何文本编辑器,例如 Visual Studio Code、Atom、Sublime 或 nano。
- 一个 免费的 Discord 帐户 和一个经过验证的电子邮件帐户和一个 免费的 Discord 服务器 ,您将使用它来测试您的 Discord 机器人。
第 1 步 — 设置 Discord 机器人
在此步骤中,您将使用 Discord 开发人员图形用户界面 (GUI) 来设置 Discord 机器人并获取机器人的令牌,然后将其传递到您的程序中。
要在 Discord 平台上注册机器人,请使用 Discord 应用程序仪表板。 在这里,开发人员可以创建 Discord 应用程序,包括 Discord 机器人。
要开始使用,请单击 新建应用程序。 Discord 会要求您输入新应用程序的名称。 然后点击Create创建应用程序。
注意: 应用程序的名称与机器人的名称无关,机器人不必与应用程序同名。
现在打开您的应用程序仪表板。 要将机器人添加到应用程序,请导航到左侧导航栏上的 Bot 选项卡。
单击 Add Bot 按钮将机器人添加到应用程序。 当提示您确认时,单击 Yes, do it! 按钮。 然后,您将位于一个仪表板上,其中包含您的机器人名称、身份验证令牌和个人资料图片的详细信息。
您可以在仪表板上修改机器人的名称或个人资料图片。 您还需要通过单击 Click to Reveal Token 并复制出现的令牌来复制机器人的身份验证令牌。
警告: 切勿共享或上传您的机器人令牌,因为它允许任何人登录您的机器人。
现在您需要创建一个邀请,将机器人添加到 Discord 公会,您可以在其中对其进行测试。 首先,导航到应用程序仪表板的 OAuth2 选项卡下的 URL Generator 页面。 要创建邀请,请向下滚动并选择 scopes 下的 bot。 您还必须设置权限来控制您的机器人可以在公会中执行的操作。 出于本教程的目的,选择 Administrator,这将授予您的机器人执行公会中几乎所有操作的权限。 使用 Copy 按钮复制链接。
接下来,将机器人添加到服务器。 按照您刚刚创建的邀请链接。 您可以从下拉菜单中将机器人添加到您拥有或拥有管理员权限的任何服务器。
现在单击 继续 。 确保您勾选了 Administrator 旁边的复选框——这将授予机器人管理员权限。 然后点击授权。 Discord 会在机器人加入服务器之前要求您解决 CAPTCHA。 现在,您将在 offline 下添加机器人的服务器的成员列表中拥有 Discord 机器人。
您已成功创建 Discord 机器人并将其添加到服务器。 接下来,您将编写一个程序来登录机器人。
第 2 步 - 创建您的项目
在此步骤中,您将设置基本的编码环境,您将在其中构建您的机器人并以编程方式登录到机器人。
首先,您需要为机器人设置一个项目文件夹和必要的项目文件。
创建您的项目文件夹:
mkdir discord-bot
移动到您刚刚创建的项目文件夹中:
cd discord-bot
接下来,使用您的文本编辑器创建一个名为 config.json
的文件来存储您的机器人的身份验证令牌:
nano config.json
然后将以下代码添加到配置文件中,将突出显示的文本替换为您的机器人的身份验证令牌:
不和谐机器人/config.json
{ "BOT_TOKEN": "YOUR BOT TOKEN" }
保存并退出文件。
接下来,您将创建一个 package.json
文件,该文件将存储您的项目的详细信息以及有关您将用于项目的依赖项的信息。 您将通过运行以下 npm
命令创建一个 package.json
文件:
npm init
npm
将询问您有关项目的各种详细信息。 如果您需要有关完成这些提示的指导,您可以在 如何使用带有 npm 和 package.json 的 Node.js 模块 中阅读它们。
您现在将安装用于与 Discord API 交互的 discord.js
包。 您可以使用以下命令通过 npm 安装 discord.js
:
npm install discord.js
现在您已经设置了配置文件并安装了必要的依赖项,您就可以开始构建您的机器人了。 在现实世界的应用程序中,大型机器人将被拆分为多个文件,但出于本教程的目的,机器人的代码将位于一个文件中。
首先,在 discord-bot
文件夹中创建一个名为 index.js
的文件用于代码:
nano index.js
通过要求 discord.js
依赖项和带有机器人令牌的配置文件开始对机器人进行编码:
不和谐机器人/index.js
const Discord = require("discord.js"); const config = require("./config.json");
在此之后,添加接下来的两行代码:
不和谐机器人/index.js
... const client = new Discord.Client({intents: ["GUILDS", "GUILD_MESSAGES"]}); client.login(config.BOT_TOKEN);
保存并退出您的文件。
第一行代码创建一个新的 Discord.Client
并将其分配给常量 client
。 这个客户端部分是你将如何与 Discord API 交互以及 Discord 将如何通知你诸如新消息之类的事件的方式。 客户端实际上代表了 Discord 机器人。 传递给 Client
构造函数的对象指定您的机器人的 网关意图 。 这定义了您的机器人将侦听的 WebSocket 事件。 在这里,您已指定 GUILDS
和 GUILD_MESSAGES
以使机器人能够接收公会中的消息事件。
第二行代码使用 client
上的 login
方法登录到您创建的 Discord bot,使用 config.json
文件中的令牌作为密码。 该令牌让 Discord API 知道该程序适用于哪个机器人,并且您已通过身份验证使用该机器人。
现在,使用 Node 执行 index.js
文件:
node index.js
您的机器人在您添加到的 Discord 服务器中的状态将变为在线。
您已成功设置编码环境并创建了用于登录 Discord 机器人的基本代码。 在下一步中,您将处理用户命令并让您的机器人执行操作,例如发送消息。
第三步——处理你的第一个用户命令
在此步骤中,您将创建一个可以处理用户命令的机器人。 您将执行您的第一个命令 ping
,它将以 "pong"
和响应命令所需的时间进行响应。
首先,您需要检测并接收用户发送的任何消息,以便您可以处理任何命令。 使用 Discord 客户端上的 on
方法,Discord 将向您发送有关新事件的通知。 on
方法有两个参数:要等待的事件的名称和每次发生该事件时要运行的函数。 使用此方法,您可以等待事件 message
— 每次将消息发送到机器人有权查看消息的公会时都会发生这种情况。 因此,您将创建一个在每次发送消息以处理命令时运行的函数。
首先打开你的文件:
nano index.js
将以下代码添加到您的文件中:
不和谐机器人/index.js
... const client = new Discord.Client({intents: ["GUILDS", "GUILD_MESSAGES"]}); client.on("messageCreate", function(message) { }); client.login(config.BOT_TOKEN);
此函数在 messageCreate
事件上运行,将 message
作为参数。 message
将具有 Discord.js 消息 实例的值,其中包含有关已发送消息的信息和帮助机器人响应的方法。
现在将以下代码行添加到您的命令处理函数中:
不和谐机器人/index.js
... client.on("messageCreate", function(message) { if (message.author.bot) return; }); ...
此行检查消息的作者是否是机器人,如果是,则停止处理命令。 这很重要,因为您通常不想处理或响应机器人的消息。 机器人通常不需要使用来自其他机器人的信息,因此忽略它们的消息可以节省处理能力并有助于防止意外回复。
现在您将编写一个命令处理程序。 要做到这一点,最好了解 Discord 命令的常用格式。 通常,Discord 命令的结构按以下顺序包含三个部分:前缀、命令名称和(有时)命令参数。
- 前缀:前缀可以是任何东西,但通常是一段标点符号或抽象短语,通常不会出现在消息的开头。 这意味着当您在消息的开头包含前缀时,机器人将知道此命令的目的是让机器人处理它。
- 命令名称:用户要使用的命令的名称。 这意味着机器人可以支持具有不同功能的多个命令,并允许用户通过提供不同的命令名称来在它们之间进行选择。
- 参数:有时如果命令需要或使用来自用户的额外信息,用户可以在命令名称后提供参数,每个参数用空格分隔。
注意: 没有强制的命令结构,机器人可以按照他们喜欢的方式处理命令,但这里介绍的结构是绝大多数机器人使用的有效结构。
要开始创建处理此格式的命令解析器,请将以下代码行添加到消息处理函数中:
不和谐机器人/index.js
... const prefix = "!"; client.on("messageCreate", function(message) { if (message.author.bot) return; if (!message.content.startsWith(prefix)) return; }); ...
您添加第一行代码以将值 "!"
分配给常量 prefix
,您将使用它作为机器人的前缀。
您添加的第二行代码检查机器人正在处理的消息内容是否以您设置的前缀开头,如果不是,则停止消息继续处理。
现在您必须将消息的其余部分转换为命令名称和消息中可能存在的任何参数。 添加以下突出显示的行:
不和谐机器人/index.js
... client.on("messageCreate", function(message) { if (message.author.bot) return; if (!message.content.startsWith(prefix)) return; const commandBody = message.content.slice(prefix.length); const args = commandBody.split(' '); const command = args.shift().toLowerCase(); }); ...
您在此处使用第一行从消息内容中删除前缀并将结果分配给常量 commandBody
。 这是必要的,因为您不想在解析的命令名称中包含前缀。
第二行接受去掉前缀的消息,并在其上使用split方法,以空格作为分隔符。 这会将其拆分为一个子字符串数组,在有空格的地方进行拆分。 这将产生一个包含命令名称的数组,然后,如果包含在消息中,则包含任何参数。 将此数组分配给常量 args
。
第三行从 args
数组中删除第一个元素(这将是提供的命令名称),将其转换为小写,然后将其分配给常量 command
。 这允许您隔离命令名称并仅在数组中保留参数。 您还可以使用 toLowerCase
方法,因为 Discord 机器人中的命令通常不区分大小写。
您已完成构建命令解析器、实现所需前缀以及从消息中获取命令名称和任何参数。 您现在将为特定命令实现和创建代码。
添加以下代码以开始执行 ping
命令:
不和谐机器人/index.js
... const args = commandBody.split(' '); const command = args.shift().toLowerCase(); if (command === "ping") { } }); ...
此 if 语句 检查您解析的命令名称(分配给常量 command
)是否与 "ping"
匹配。 如果是,则表明用户想要使用 "ping"
命令。 您将在 if
语句块内嵌套特定命令的代码。 您将对要实现的其他命令重复此模式。
现在,您可以实现 "ping"
命令的代码:
不和谐机器人/index.js
... if (command === "ping") { const timeTaken = Date.now() - message.createdTimestamp; message.reply(`Pong! This message had a latency of ${timeTaken}ms.`); } ...
保存并退出您的文件。
添加 "ping"
命令块,计算当前时间(使用 Date
对象上的 now 方法 找到)与创建消息时的时间戳之间的差异毫秒。 这会计算消息处理所需的时间以及机器人的 "ping"
。
第二行使用 message
常量上的 reply
方法响应用户命令。 回复方法 ping(通知用户并突出显示指定用户的消息)调用命令的用户,然后是作为该方法的第一个参数提供的内容。 您提供一个 模板文字 包含一条消息和计算的 ping 作为 reply
方法将使用的响应。
"ping"
命令的实现到此结束。
使用以下命令运行您的机器人(在与 index.js
相同的文件夹中):
node index.js
您现在可以在机器人可以查看和发送消息的任何频道中使用命令 "!ping"
,从而产生响应。
您已经成功创建了一个可以处理用户命令的机器人,并且您已经实现了您的第一个命令。 在下一步中,您将通过实施 sum 命令继续开发您的机器人。
第 4 步 — 实现 Sum 命令
现在您将通过执行 "!sum"
命令来扩展您的程序。 该命令将采用任意数量的参数并将它们相加,然后将所有参数的总和返回给用户。
如果您的 Discord 机器人仍在运行,您可以使用 CTRL + C
停止其进程。
再次打开您的 index.js
文件:
nano index.js
要开始执行 "!sum"
命令,您将使用 else-if
块。 在检查 ping 命令名称后,它将检查命令名称是否等于 "sum"
。 您将使用 else-if
块,因为一次只处理一个命令,因此如果程序与命令名称 "ping"
匹配,则不必检查 [X170X ] 命令。 将以下突出显示的行添加到您的文件中:
不和谐机器人/index.js
... if (command === "ping") { const timeTaken = Date.now() - message.createdTimestamp; message.reply(`Ping! This message had a latency of ${timeTaken}ms.`); } else if (command === "sum") { } }); ...
您可以开始实现 "sum"
命令的代码。 "sum"
命令的代码将进入您刚刚创建的 else-if
块中。 现在,添加以下代码:
不和谐机器人/index.js
... else if (command === "sum") { const numArgs = args.map(x => parseFloat(x)); const sum = numArgs.reduce((counter, x) => counter += x); message.reply(`The sum of all the arguments you provided is ${sum}!`); } ...
您在参数列表上使用 map 方法 通过对 args
数组中的每个项目使用 parseFloat 函数来创建新列表。 这将创建一个新数组(分配给常量 numArgs
),其中所有项目都是数字而不是字符串。 这意味着稍后您可以通过将它们加在一起来成功找到数字的总和。
第二行使用常量 numArgs
上的 reduce 方法 提供了一个函数,该函数将列表中的所有元素相加。 您将 numArgs
中所有元素的总和分配给常数 sum
。
然后,您可以在消息对象上使用 reply
方法,使用 模板文字 回复用户的命令,其中包含用户发送给机器人的所有参数的总和。
"sum"
命令的实现到此结束。 现在使用以下命令运行机器人(在与 index.js
相同的文件夹中):
node index.js
您现在可以在机器人可以查看和发送消息的任何频道中使用 "!sum"
命令。
以下是 index.js
bot 脚本的完整版本:
不和谐机器人/index.js
const Discord = require("discord.js"); const config = require("./config.json"); const client = new Discord.Client({intents: ["GUILDS", "GUILD_MESSAGES"]}); const prefix = "!"; client.on("messageCreate", function(message) { if (message.author.bot) return; if (!message.content.startsWith(prefix)) return; const commandBody = message.content.slice(prefix.length); const args = commandBody.split(' '); const command = args.shift().toLowerCase(); if (command === "ping") { const timeTaken = Date.now() - message.createdTimestamp; message.reply(`Pong! This message had a latency of ${timeTaken}ms.`); } else if (command === "sum") { const numArgs = args.map(x => parseFloat(x)); const sum = numArgs.reduce((counter, x) => counter += x); message.reply(`The sum of all the arguments you provided is ${sum}!`); } }); client.login(config.BOT_TOKEN);
在这一步中,您通过实施 sum
命令进一步开发了 Discord 机器人。
结论
您已经成功实现了一个 Discord 机器人,它可以处理多个不同的用户命令和命令参数。 如果您想扩展您的机器人,您可以实现更多命令或尝试使用 Discord API 的更多部分来制作功能强大的 Discord 机器人。 您可以查看 Discord.js 文档 或 Discord API 文档 以扩展您对 Discord API 的了解。 特别是,您可以将机器人命令转换为 斜杠命令 ,这是 Discord.js v13 的最佳实践。
在创建 Discord 机器人时,您必须始终牢记 Discord API 服务条款 ,其中概述了开发人员必须如何使用 Discord API。 如果您想了解有关 Node.js 的更多信息,请查看我们的 如何在 Node.js 中编写代码系列 。