用NodeJS创建交互式Discord机器人的教程

1,767 阅读7分钟

在一个小时内建立你的第一个Discord机器人

了解如何用NodeJS创建交互式Discord机器人

在不到60分钟的时间里用NodeJS构建你的第一个Discord机器人

Discord是一个超过1亿用户依赖的聊天应用程序,通过文本、语音和视频对话建立在线社区。利用Discord为开发者提供的大量API,我们可以建立机器人,在Discord上执行重复的、平凡的、甚至是有趣的任务。管理社区、向社区发送信息、给用户发私信,只是我们可以使用 Discord 机器人自动完成的几项工作。

在今天的教程中,我们将建立一个简单(和有趣)的机器人,在用户要求下向社区发送随机的爸爸笑话。使用Node.js和discord.js模块,我们可以在60分钟内创建、开发和部署这个Discord机器人,而且没有任何麻烦。现在开始倒计时了。


在我们开始之前...

在这里,我们列出了在开始学习教程之前需要设置的所有东西:

  • 在你的机器上安装Node.js。
  • 在 Discord 上创建一个账户。你可以下载桌面应用程序或使用浏览器访问它。
  • 创建一个新的社区(或者用Discord语言创建一个新的 "服务器")来测试该应用程序。

一旦所有这些都设置好了,你就可以继续学习教程了。

最后一件事,你可以在GitHub上找到项目的代码


创建一个新的Discord机器人

在这第一步,你应该在Discord上创建和配置一个新的机器人。以下是你的操作方法

登录你的Discord账户,进入其开发者门户网站的应用页面。

Discord Dev Portal

Discord 开发者门户网站

点击 "新应用程序"。它会生成一个弹出窗口,提供新机器人的名字。

Discord new application form

Discord新申请表格

添加完名字后,点击创建按钮,你会被导航到一个包含申请信息的新页面。进入 "机器人 "标签,点击 "添加机器人 "按钮,将机器人添加到申请中。同样,在弹出的对话框中确认该操作。

Discord bot application

Discord机器人应用程序

这就把新的机器人添加到了 Discord。现在,我们可以开始配置它了。

Discord register bot

Discord注册机器人

第一步,复制机器人令牌,并将其存放在某个私人地方。记住:这个令牌只能给你看,千万不要与其他人分享。

保持 "授权流程 "部分的默认选择。

Discord authorization flow

Discord授权流程

接下来,你应该在 "特权网关意图 "下打开 "服务器成员意图 "选项。我们的机器人需要这个意图的权限来检测新成员加入服务器的时间。

Discord set up bot intents

Discord设置的机器人意图


将机器人添加到Discord服务器上

我们应该生成一个邀请链接,反映机器人应该拥有的权限级别,以便将其添加到Discord服务器。要做到这一点,在同一页上的 "OAuth2 "标签,选择 "机器人 "作为应用程序的范围。然后,选择机器人在与服务器互动时应该有的一组权限。我们的机器人只需要在服务器频道中读取和发送消息的权限。

Discord set bot permissions

Discord设置机器人的权限

选择所有必要的权限后,复制范围部分下生成的URL,并在新的浏览器标签中打开它。然后,选择机器人应该加入的服务器,并在出现提示时授权该行动。

Connect bot to Discord server

将机器人连接到 Discord 服务器

现在,如果你进入Discord服务器,你就能看到新的机器人在右侧面板上被列为成员。


实现机器人的行为

我们现在可以开始添加代码来定义机器人在服务器中的行为。正如我们在文章开头提到的,我们将使用Node.js和discord.js来完成这个任务。

作为实施的第一步,建立一个新的Node.js项目,用npm初始化它。然后,我们应该用npm安装discord.js、axios和dotenv模块。

npm install discord.js axios dotenv

接下来,我们创建一个.env文件,并添加我们之前复制的令牌作为环境变量。

//.env

TOKEN=<your token>

登录并开始监听事件

现在我们可以导入discord.js,设置机器人来监听服务器事件并作出相应的反应。创建一个名为index.js的新文件,并在其中添加以下代码:

//index.js

require("dotenv").config();
const Discord = require("discord.js");
const client = new Discord.Client();

//Listen to the event that signals the bot is ready to start working
client.on("ready", () => {
  console.log(`logged in as ${client.user.tag}`);
});

//Listen to new messages on the server
client.on("message", async (message) => {
  if (message.content === "ping") {
    message.reply("pong");
  }
});

//Login to the server using bot token
client.login(process.env.TOKEN);

这段代码中发生了几件重要的事情。首先,我们导入discord.js模块,并创建一个新的客户端对象,在这个方案中代表Discord机器人。然后,client.login 方法允许机器人使用我们添加到.env文件中的令牌登录到 Discord。dotenv模块负责把它作为一个环境变量添加到进程中。

我们的机器人监听两个Discord事件:ready和message。当机器人准备好被使用时,就会触发ready事件。而消息事件是在每次用户向频道发送消息时触发的。在这里,我们将机器人设置为用 "pong "来回复每条发送 "ping "的消息。

当我们使用node index 命令运行这个Node脚本时,到目前为止一直处于离线状态的Bot就会上线并开始工作。

See your bot online

看到你的机器人在线

你可以向一个频道发送ping信息,测试它是否正常工作。

Test your basic bot

测试你的基本机器人


应用户要求用随机的爸爸笑话回复用户

最后,我们来到了这个项目的有趣部分。在这一步中,我们将设置我们的机器人回复任何直接提到它的用户,并给他一个随机的爸爸笑话。为此,我们将使用这个很棒的API:icanhazdadjoke.com。它有一个伟大的有趣(和尴尬)的爸爸笑话集合,我们可以免费检索。

这个实现的基本逻辑是这样的。当用户提到我们的机器人时,它使用axios向爸爸笑话API发送一个请求,并检索一个随机的爸爸笑话。然后,它将笑话回复给用户。相当简单。

这里需要注意的是,我们需要将GET请求的接受头设置为application/json,以便以JSON格式从API检索结果。

require("dotenv").config();
const axios = require("axios");
const Discord = require("discord.js");
const client = new Discord.Client();

const dadJokeURL = "https://icanhazdadjoke.com";
const headers = { "Accept": "application/json" };

async function getRandomDadJoke() {
  const response = await axios.get(dadJokeURL, { headers: headers });
  return response.data;
}

//Listen to the event that signals bot is ready to start working
client.on("ready", () => {
  console.log(`logged in as ${client.user.tag}`);
});

//Listen to new messages on the server
client.on("message", async (message) => {
    //"Ignore the message if the bot authored it"
    if (message.author.bot) return;

    //If the doesn't specifically mention the bot, return
    if (text.includes("@here") || text.includes("@everyone")) return;

    //Return if the message doesn't mention the bot
    if (!message.mentions.has(client.user.id)) return;

    try {  
        //Reply with a random joke
        const result = await getRandomDadJoke();
        message.reply(result.joke);
    }
    catch (error) {
      message.reply("Sorry, an error occured");
    }
});

//Login to the server using bot token
client.login(process.env.TOKEN);

getRandomDadJoke 方法发送axios请求,并返回带有随机笑话的检索数据。在消息处理程序中,机器人监听消息事件并决定它应该回复哪些消息。它消除了三种类型的消息:

  • 由机器人自己编写的消息。
  • 提及服务器上的每个人,而不仅仅是机器人的消息。
  • 没有提到机器人的信息。

如果一个用户直接提到机器人,它就会用一个使用getRandomDadJoke 方法检索的随机笑话进行回复。

你可以停止和启动Node脚本,让修改后的机器人在服务器上运行。

Now the bot can reply information from the API

现在机器人可以从API中回复信息了


用用户提供的搜索词来搜索爸爸的笑话

这个实现与上一个没有太大区别。但在这里,用户可以提交一个搜索词,以获得一个特定主题的爸爸笑话。

为了实现这一点,我们添加了一个名为searchDadJokes 的新函数,该函数将请求发送到/search API端点,并将搜索词作为一个查询参数。我们还设置了limit=1 ,以便在一个给定的主题上只检索一个笑话。

async function searchDadJokes(term) {
    const params = { term: term, limit: 1 }
    const response = await axios.get(`${dadJokeURL}/search`, { params: params, headers: headers });
    return response.data.results[0];
}

然后,我们必须修改消息事件处理程序,以考虑用户提交搜索词的情况。下面是我们如何做的。

//Listen to new messages on the server
client.on("message", async (message) => {

    //"Ignore the message if the bot authored it"
    if (message.author.bot) return;

    const text = message.content.toLowerCase();

    //If the doesn't specifically mention, bot return
    if (text.includes("@here") || text.includes("@everyone")) return;

    //Return if the message doesn't mention the bot
    if (!message.mentions.has(client.user.id)) return;

    let result;
    try {
        const term = text.replace(/<@!\d+>/, "").trim();

        //If there is a search term
        if (term !== "") {
            //Search a joke containing the term
            result = await searchDadJokes(term);
            if (!result) {
                message.reply(`Sorry, got no dad jokes about ${term}. But how about a random dad joke?`);
            }
        }

        //Reply with a random joke
        if (!result) {
            result = await getRandomDadJoke();
        }

        message.reply(result.joke);
    }
    catch (error) {
        message.reply("Sorry, an error occured")
    }
});

在这段代码中,为了检查用户是否提交了一个搜索词,我们需要从文本中删除机器人的ID。当用户提到机器人的时候,它就会被添加到文本中。一个被提及的ID在文本中以如下格式出现。

<@!1223344342859688930>

我们使用regex模式<@!\d+> ,检测文本中的ID,并将其替换为一个空字符串。在修剪了修改后的文本后,机器人可以检索到用户提交的搜索词。然后,机器人使用searchDadJokes 方法找到一个相关的笑话。

但是,如果API数据库中没有关于某个特定主题的笑话,机器人就会回复用户,解释这种情况以及一个随机笑话。如果用户没有提交搜索词,它就会默认回复一个随机笑话。

代码的其余部分保持与上一个场景相似。所以,我们现在可以运行和测试我们机器人的这个新功能。


欢迎新成员

我们可以设置我们的机器人来欢迎每个加入Discord服务器的新用户。当机器人检测到一个新的 "guildMemberAdd "事件,也就是一个新用户加入的信号,它会向 "General "频道发送一条消息,欢迎新用户。

//Listen to new member joining event
client.on("guildMemberAdd", member => {
//Find the general channel in the user's channel list to send the welcome message
const channel = member.guild.channels.cache.find(ch => ch.name === "general");

    //If the channel is not in the server, exit
    if (!channel) return;

    channel.send(`Welcome, ${member}! I'm at your service if you want to hear dad jokes`);
});

至此,我们已经完成了我们的Discord机器人的开发。你现在可以把机器人添加到任何你有 "管理服务器 "权限的服务器上,并享受阅读随机爸爸笑话的乐趣。