• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

使用Node.js构建Slack机器人

Slack正迅速成为团队沟通的新行业标准。事实上,它是如此受欢迎,以至于当我在谷歌中输入 slack 时,正如我所期望的那样,第一个结果是字典中单词的定义。紧随其后的是 Slack 的网站! 

对于英语词典中最常见的单词,这几乎是闻所未闻的。通常,谷歌的定义后面有几个顶级词典网站的链接。

什么是松弛?

最基本的,Slack 是一个消息传递系统。它允许直接向团队成员发送消息,并创建允许轻松实时团队沟通和协作的渠道(私人或公共)。有关 Slack 的更多信息,您可以查看Slack 的功能

在这一点上,您可能想知道 node.js 的用武之地。正如我所提到的,在最基本的情况下,Slack 是一个消息传递系统;但是,它可以无限扩展和定制。Slack 提供了一个非常灵活的系统来定制您的团队的集成,包括:

  • 创建自定义欢迎消息

  • 创建自定义表情符号

  • 安装第三方应用程序

  • 创建自己的应用程序

  • 创建自定义 Slack 机器人

在本文中,我将演示如何使用 Node.js 创建一个可添加到团队的 Slack 配置中的 Slack 机器人。

定义的 Slack 机器人

Slack Bot 的工作是接收Slack 发送的事件并进行处理。有大量事件将发送到您的 Bot,这就是 Node.js 的用武之地。我们不仅要决定要处理哪些事件,还要决定如何处理每个单独的事件。

例如,机器人将处理的一些常见事件是:

  • member_joined_channel

  • member_left_channel

  • message

在本文中,我将创建一个 Node.js 应用程序和一个 Slack Bot,可以将它们添加到您的团队项目中,以根据它接收到的事件执行特定操作。

首先,我需要在 Slack 上创建一个机器人。可以创建两种类型的机器人:

  • 自定义机器人

  • 创建应用程序并添加机器人用户

本文将创建一个自定义机器人,因为如果您打算在 Slack 上编写和发布应用程序,应用程序机器人用户会更合适。鉴于我希望这个机器人对我的团队来说是私有的,一个自定义机器人就足够了。

创建自定义 Slack 机器人

可以在此处创建自定义机器人:  https ://my.slack.com/apps/A0F7YS25R-bots 。如果您已经登录到您的 Slack 帐户,请在左侧选择 添加配置按钮;否则,请先登录您的 Slack 帐户,然后再继续。如果您没有 Slack 帐户,您可以免费注册

这会将您带到一个新页面,该页面要求您为您的机器人提供用户名。现在输入您的用户名,确保您遵循 Slack 的命名准则。一旦您选择了一个很棒的机器人名称,请按 Add bot configuration

成功创建机器人后,Slack 会将您重定向到允许进一步自定义机器人的页面。我会把这部分留给你有创造力的自己。此页面唯一需要 是以 xoxb-我要么将此令牌复制到一个安全的地方供以后使用,要么只是让此页面保持打开状态,直到我们需要 Node.js 应用程序的令牌。

配置

在继续编写代码之前,还需要两个 Slack 配置:

  1. 创建或选择您的机器人将与之交互的现有频道。在测试我的新机器人时,我选择创建一个新频道。请务必记住通道名称,因为您很快就会在应用程序中使用它。

  2. 将您的机器人添加/邀请到频道,以便它可以与之交互。

现在我已经配置了我的 Slack Bot,是时候转到 Node.js 应用程序了。如果您已经安装了 Node.js,则可以继续下一步。如果您没有安装 Node.js,我建议您首先访问Node.js 下载页面并为您的系统选择安装程序。

对于我的 Slack Bot,我将通过运行该npm init过程来创建一个新的 Node.js 应用程序。使用设置为您希望安装应用程序的位置的命令提示符,您可以运行以下命令:

mkdir slackbot
cd slackbot
npm init

如果您不熟悉npm init,这将启动一个实用程序来帮助您配置新项目。它要求的第一件事是名称。它默认我的slackbot,我很满意。如果您想更改您的应用程序名称,现在是机会;否则,按 Enter继续下一个配置步骤。下一个选项是版本和描述。我将两者都保留为默认设置,只需按 Enter 键即可继续使用这两个选项。

入口点

接下来要求的是 入口点这默认为index.js但是,很多人喜欢使用app.js我不想参加这场辩论,并且鉴于我的申请不需要密集的项目结构,我将把我的默认设置为index.js.

在您从可能与制表符与空格一样激烈的辩论中恢复过来后,配置继续进行,并提出了几个问题:

  • 测试命令

  • git仓库

  • 关键词

  • 作者

  • 执照

出于本文的目的,我将所有选项都保留为默认选项。最后,一旦配置了所有选项,在创建文件之前会显示文件的确认package.json按 Enter 键完成配置。

进入SDK

为了使与 Slack 的交互更容易,我还将安装Slack Developer Kit 包,如下所示:

npm install @slack/client --save

你终于准备好使用一些代码了吗?我当然是。首先,我将使用 Slack Developer Kit 网站上的示例代码,该代码使用实时消息传递 api (RTM)发布一条 Slack 消息, 并进行一些调整。

鉴于 我选择的入口点index.js是,是时候创建这个文件了。Slack Developer Kit 网站上的示例大约有 20 行代码。我将一次将其分解为几行,只是为了解释这些行的作用。但请注意,所有这些行都应包含在您的index.js文件中。 

代码首先包含 Slack Developer Kit 中的两个模块:

var RtmClient = require('@slack/client').RtmClient;
var CLIENT_eventS = require('@slack/client').CLIENT_EVENTS;

实例化RtmClient后,将成为我们引用 RTM API 的机器人对象。这些CLIENT_EVENTS 是机器人将要监听的事件。

包含这些模块后,就可以实例化并启动机器人了:

var rtm = new RtmClient('xoxb-******************************************');rtm.start();

请务必将上面混淆的 API 令牌替换为您在创建 Slack Bot 期间获得的令牌。

调用startmy 上的函数RtmClient将初始化机器人的会话。这将尝试验证我的机器人。当我的机器人成功连接到 Slack 时,将发送事件以允许我的应用程序继续。这些事件将立即显示。

实例化客户端后,将channel创建一个变量以在其中一个CLIENT_EVENTS事件中临时填充。

let channel;

channel变量将用于执行特定操作,例如向机器人连接的通道发送消息。

当 RTM 会话启动 ( ) 并为机器人rtm.start();提供有效的 API 令牌RTM.AUTHENTICATED时,将发送一条消息。接下来的几行监听这个事件:

rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, (rtmStartdata) => {
  for (const c of rtmStartData.channels) {
      if (c.is_member && c.name ==='jamiestestchannel') { channel = c.id }
  }
  console.log(`Logged in as ${rtmStartData.self.name} of team ${rtmStartData.team.name}`);
});

当 RTM.AUTHENTICATED 收到事件时,前面的代码会在 Slack 团队频道列表中执行for 循环。就我而言,我专门寻找 jamiestestchannel并确保我的机器人是该频道的成员。当满足该条件时,通道 ID 将存储在channel变量中。

调试

为了帮助调试,会记录一条控制台消息,其中显示一条消息,表明机器人已通过显示其名称 ( ) 和它所属${rtmStartData.self.name}的团队名称 ( ) 成功进行身份验证。${rtmStartData.team.name}

机器人通过身份验证后,会触发另一个事件 ( RTM.RTM_CONNECTION_OPENED),这表示机器人已完全连接并可以开始与 Slack 交互。接下来的代码行创建事件监听器;成功后, 您好!消息被发送到频道(在我的例子中是 jamiestestchannel)。

rtm.on(CLIENT_EVENTS.RTM.RTM_CONNECTION_OPENED, function () {
  rtm.sendMessage("Hello!", channel);
});

此时,我现在可以运行我的 Node 应用程序并观察我的机器人自动向我的频道发布一条新消息:

node index.js

运行此命令(成功时)的结果是双重的:

  1. 我收到调试消息,表明我的机器人已成功登录。这源于RTM.AUTHENTICATED 启动 RTM 客户端后被触发。

  2. 我收到一个 你好!我的 Slack 频道中的消息。这发生在 RTM.RTM_CONNECTION_OPENED 应用程序接收和处理事件消息时。

在继续并进一步增强我的应用程序之前,现在是回顾一下我为实现这一目标所做的工作的好时机:

  1. 创建了一个自定义 Slack Bot。

  2. 创建了一个自定义 Slack 频道并邀请我的机器人加入其中。

  3. 创建了一个名为slackbot的新 Node.js 应用程序 

  4. 将 Slack Developer Kit 包安装到我的应用程序中。

  5. 创建了我的index.js文件,该文件RtmClient使用我的自定义机器人中的API 令牌创建了一个文件。

  6. 创建了一个事件***器,用于RTM.AUTHENTICATED查找我的机器人所属的 Slack 频道。

  7. RTM.RTM_CONNECTION_OPENED为发送 Hello!创建了一个事件***器。消息到我的 Slack 频道。

  8. 调用 RTM Start Session 方法以开始由我的事件***器处理的身份验证过程。

构建机器人

现在是时候开始真正的乐趣了。Slack 提供(我没有计算在内)至少50 种不同的事件可供我的自定义机器人监听和选择性处理。从 Slack Events 列表中可以看出,一些事件是 RTM API(我们正在使用)自定义的,而其他事件是Events API自定义的。在写这篇文章的时候,我的理解是 Node.js SDK 只支持 RTM。

为了完成我的机器人,我将处理message事件;当然,这可能是最复杂的事件之一,因为它支持大量子类型,我稍后将探讨。

message以下是Slack中最基本事件的示例:

{
    "type": "message", 
    "channel": "C2147483705", 
    "user": "U2147483697", 
    "text": "Hello world", 
    "ts": "1355517523.000005" 
}

在这个基本对象中,我最关心的三件事是:

  1. channel我将要确保此消息属于我的机器人所属的频道。

  2. user这将允许我直接与用户交互或根据用户身份执行特定操作。

  3. text这可能是最重要的部分,因为它包含消息的内容。我的机器人将只想响应某些类型的消息。

有些消息更复杂。它们可以包含许多子属性,例如:

  • edited: 一个子对象,描述了哪个用户编辑了消息以及它何时发生。

  • subtype: 定义多种不同类型之一的字符串,例如 channel_join、channel_leave 等。

  • is_starred: 一个布尔值,指示此消息是否已加星标。

  • pinned_to:已固定此消息的频道数组。

  • reactions:一组反应对象,定义了反应是什么(例如,facepalm)、发生了多少次,以及以这种方式对消息做出反应的用户数组。

我将扩展我之前创建index.js的监听message事件。为了减少代码冗余,以下示例将仅包含与message事件增强相关的部分代码。

必须做的第一件事是为RTM_EVENTS我将要收听的新模块添加一个新模块。我把它放在我之前的两个模块下面,包括:

var RTM_EVENTS = require('@slack/client').RTM_EVENTS;

message我将放置在文件底部的用于处理事件的代码。为了测试message事件是否正常工作,我创建了一个新的事件***器,将 message对象记录到控制台,如下所示:

rtm.on(RTM_EVENTS.MESSAGE, function(message) {
    console.log(message);
});

我现在可以重新运行我的 Node 应用程序 ( node index.js)。当我在频道中输入消息时,控制台会记录以下内容:

{ 
    type: 'message',
    channel: 'C6TBHCSA3',
    user: 'U17JRET09',
    text: 'hi',
    ts: '1503519368.000364',
    source_team: 'T15TBNKNW',
    team: 'T15TBNKNW' 
}

到目前为止,一切都很好。我的机器人正在成功接收消息。下一个增量步骤是确保消息属于我的机器人所在的频道:

rtm.on(RTM_EVENTS.MESSAGE, function(message) {
    if (message.channel === channel)
        console.log(message);
});

现在,当我运行我的应用程序时,如果message事件是针对channel我的机器人所属的事件,我只会看到我的调试消息。

我现在将扩展应用程序以向通道发送自定义消息,以演示如何在消息中标记用户:

rtm.on(RTM_EVENTS.MESSAGE, function(message) {
    if (message.channel === channel)
        rtm.sendMessage("Stop, everybody listen, <@" + message.user + "> has something important to say!", message.channel);
});

现在,当有人在频道中键入消息时,我的机器人会发送自己的消息,类似于:“停止,每个人都听着,@endyourif 有重要的事情要说!”

好的,不是很有用。相反,我将通过增强message事件***器以响应特定命令来完成我的机器人。这将通过执行以下操作来完成:

  1. 根据空格text将 a 的部分拆分为数组。message

  2. 检查第一个索引是否与我的机器人的用户名匹配。

  3. 如果是这样,我将查看第二个索引(如果存在)并将其视为 我的机器人应该执行的命令。

为了便于检测是否提到了我的机器人,我需要创建一个新变量来存储我的机器人用户 ID。下面是更新的代码部分,我之前在其中设置了channel变量。它现在还将我的机器人的用户 ID 存储在一个名为bot.

let channel;
let bot;

rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, (rtmStartData) => {
  for (const c of rtmStartData.channels) {
      if (c.is_member && c.name ==='jamiestestchannel') { channel = c.id }
  }
  console.log(`Logged in as ${rtmStartData.self.name} of team ${rtmStartData.team.name}`);
  
  bot = '<@' + rtmStartData.self.id + '>';
});

使用我的bot变量集,我通过充实先前创建的 message事件***器来完成我的机器人,如下所示:

rtm.on(RTM_EVENTS.MESSAGE, function(message) {
    if (message.channel === channel) {
		if (message.text !== null) {
			var pieces = message.text.split(' ');
			
			if (pieces.length > 1) {
				if (pieces[0] === bot) {
					var response = '<@' + message.user + '>';
					
					switch (pieces[1].toLowerCase()) {
						case "jump":
							response += '"Kris Kross will make you jump jump"';
							break;
						case "help":
							response += ', currently I support the following commands: jump';
							break;
						default:
							response += ', sorry I do not understand the command "' + pieces[1] + '". For a list of supported commands, type: ' + bot + ' help';
							break;
					}
					
					rtm.sendMessage(response, message.channel);
				}
			}
		}
	}
});

以下代码基于空格text将对象的属性拆分为数组。message接下来,我确保数组中至少有两个元素,理想情况下是我的机器人和要执行的命令。

当数组中的第一个元素与我的机器人匹配时,我对数组中switch的第二个元素执行语句:命令。当前支持的命令是 jump和 help当一条消息发送到看起来像“@jamiestest jump”的频道时,我的机器人将向原始用户发送一条特殊消息。 

如果无法识别该命令,它将属于我的默认 case 语句,switch并以如下所示的通用命令响应:“@endyourif,对不起,我不理解命令“hi”。有关支持的命令列表,输入:@jamiestest 帮助”。

结论

至此,我的机器人就完成了!如果您有兴趣进一步增强您的机器人,这里有一个想法列表:

  • 通过收听 team_join事件来处理新的团队成员加入。当新团队成员加入时,向他们发送各种入职信息和/或文档以欢迎他们加入您的团队是一个好主意。

  • 增强我已启动的受支持命令列表。

  • 通过搜索数据库、Google、YouTube 等使命令具有交互性。

  • 在应用程序上创建机器人用户并创建您自己的自定义斜杠命令


文章目录
  • 什么是松弛?
  • 定义的 Slack 机器人
  • 创建自定义 Slack 机器人
    • 配置
    • 入口点
    • 进入SDK
    • 调试
    • 构建机器人
  • 结论