为Slack开发可操作的应用程序



译者的话:我们为您发布村村友美的文章,内容涉及如何开发与Slack集成的应用程序

通过Actions,Slack用户可以使用消息与您的应用程序进行交互:报告错误问题,向服务台发送请求或执行其他操作。 此功能类似于注释或共享之类的内置功能。

本教程将指导您完成创建实时应用程序的整个过程。

Skillbox建议:两年实践课程“我是PRO Web开发人员”

我们提醒您: 对于所有“哈勃”读者来说,使用“哈勃”促销代码注册任何Skillbox课程时均可享受10,000卢布的折扣。

本教程对任何想学习Slack API的人都非常有用。 在开发应用程序时,将使用Node.js,因此,如果要重复对话的内容,请安装它。

可以在GitHub上找到完成的项目,并在Glitch找到简化版本。

ClipIt! 松弛

我们将为虚构的ClipIt应用程序开发Slack-app! 假设我们正在管理一个Web服务,该服务允许您通过将网页的一部分存储在数据库中来“放置”网页的一部分。 用户可以从移动设备或PC访问存储的内容,该服务是多平台的。 还有ClipIt! 允许您使用操作在Slack消息环境中附加文本。

这是一个gif,演示了该应用程序的工作方式。



这是ClipIt的用户交互算法! 来自Slack:

  • 用户将鼠标悬停在消息上方,然后在下拉菜单中选择“剪切消息”。
  • 对话框打开,这提供了更多机会。
  • 用户确认操作。
  • ClipIt! for Slack将消息导出到ClipIt!数据库。
  • ClipIt! for Slack将DM发送给用户并进行确认。

定制应用


登录到您的Slack帐户并使用此链接创建应用程序。 输入其名称和范围。



单击创建应用程序按钮,然后单击基本信息,滚动到应用程序凭据。



之后,打开Signing Secret,然后将代码复制为根节点中.env文件中的环境变量SLACK_SIGNING_SECRET。 我将在“请求验证”部分中稍稍解释一下它的含义和用法。

SLACK_SIGNING_SECRET = 15770a ...

向下滚动一点,以在显示信息中填写您的应用程序图标和说明。

现在,在“交互式组件”中启用“交互性”。 这样,您将在页面上看到更多字段。



是时候输入Request URL了-这是Slack在用户开始操作时将相应数据发送到的地址。

这应该是运行应用程序代码的服务器的URL。 例如,如果您将所有这些都发布在Glitch中,则您的URL将类似于example.glitch.me/actions 。 如果在使用ngrok之类的服务时使用隧道,请使用服务URL(例如example.ngrok.io ,然后添加/操作)。

输入请求URL后,向下滚动到“操作”,然后单击“创建新操作”。 填写表格:



单击创建,然后单击保存更改。

接下来,转到Bot用户。 单击添加Bot用户,然后将其命名为应用程序机器人。



现在单击添加Bot用户并保存。

下一步是转到OAuth&Permissions,然后单击Install App to Workspace。 安装完成后,页面将使您返回带有访问令牌的OAuth&Permission。 复制机器人令牌并将其全部保存在.env文件中。

SLACK_ACCESS_TOKEN = xoxb-214 ...

此外,范围必须在同一页面上激活。 完成此操作后,请确保同时突出显示bot和command。

现在所有的设置都准备好了,我们开始创建-我们正在编写一个应用程序。

应用程式建立


如上所述,Node.js和ExpressJS用于创建应用程序。 为了使用所有这些功能,请安装ExpressJS依赖项,bodyParser和其他工具。 因此,我将axios HTTP请求客户端与qs一起使用。

$ npm install express正文解析器axios qs dotenv --save

让我们从最重要的开始。 当我们添加更多功能时,我们将在以后更改代码。 首先,创建index.js文件。 在此文件中,我们将服务器设置为侦听相应的端口:

/* Snippet 1 */ require('dotenv').config(); // To grab env vers from the .env file const express = require('express'); const bodyParser = require('body-parser'); const axios = require('axios'); const qs = require('qs'); const app = express(); // The next two lines will be modified later app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); const server = app.listen(5000); // port 

在继续之前,让我们看一下描述我们所讨论的一切操作原理的图。



当用户执行消息菜单中的操作时,将初始化每个线程。 一旦message_action事件触发,Slack就将有效负载应用程序发送到先前注册的请求URL。



端点可以编写如下:

 /* Snippet 2 */ app.post('/actions', (req, res) => { const payload = JSON.parse(req.body.payload); const {type, user, submission} = payload; // Verifying the request. I'll explain this later in this tutorial! if (!signature.isVerified(req)) { res.sendStatus(404); return; } if(type === 'message_action') { // open a dialog! } else if (type === 'dialog_submission') { // dialog is submitted } }); 

如果事件类型为message_action,则应用程序将打开一个对话框。

然后,我们使用dialog.open方法添加定义对话内容结构的代码,并在Slack客户端中将其打开:

 /* Snippet 2.1 */ const dialogData = { token: process.env.SLACK_ACCESS_TOKEN, trigger_id: payload.trigger_id, dialog: JSON.stringify({ title: 'Save it to ClipIt!', callback_id: 'clipit', submit_label: 'ClipIt', elements: [ { label: 'Message Text', type: 'textarea', name: 'message', value: payload.message.text }, { label: 'Importance', type: 'select', name: 'importance', value: 'Medium ', options: [ { label: 'High', value: 'High ' }, { label: 'Medium', value: 'Medium ' }, { label: 'Low', value: 'Low ️' } ], }, ] }) }; // open the dialog by calling the dialogs.open method and sending the payload axios.post('https://slack.com/api/dialog.open', qs.stringify(dialogData)) .then((result) => { if(result.data.error) { res.sendStatus(500); } else { res.sendStatus(200); } }) .catch((err) => { res.sendStatus(500); }); 

在这里,我们使用axios模块执行对Slack的POST请求; 之后,dialog.open方法通过发送HTTP状态200来打开对话框。



如果对话是由用户发起的,则端点也被激活。 在代码片段2中,您需要使用一个空的HTTP 200请求进行响应,以便Slack知道已接收到该视图。

最后,我们使用chat.postMessage方法向用户发送确认消息。

 /* Snippet 2.2 */ else if (type === 'dialog_submission') { res.send(''); // Save the data in DB db.set(user.id, submission); // this is a pseudo-code! // DM the user a confirmation message const attachments = [ { title: 'Message clipped!', title_link: `http://example.com/${user.id}/clip`, fields: [ { title: 'Message', value: submission.message }, { title: 'Importance', value: submission.importance, short: true }, ], }, ]; const message = { token: process.env.SLACK_ACCESS_TOKEN, channel: user.id, as_user: true, // DM will be sent by the bot attachments: JSON.stringify(attachments) }; } 

现在,让我们运行代码,看看应用程序如何与Slack集成在一起。 如果一切顺利,请执行最后一步。

要求验证


现在,让我们注意应用程序的安全性并添加请求验证。 始终先验证来自Slack的任何请求,然后再进行处理。

为此,请返回最顶部的代码段1。 替换有评论的地方// //稍后将修改以下两行,如下所示:

 /* Snippet 3 */ const rawBodyBuffer = (req, res, buf, encoding) => { if (buf && buf.length) { req.rawBody = buf.toString(encoding || 'utf8'); } }; app.use(bodyParser.urlencoded({verify: rawBodyBuffer, extended: true })); app.use(bodyParser.json({ verify: rawBodyBuffer })); 

我已经在verifySignature.js中启用了加密,因此只需在index.js的开头添加一个函数即可:

 const signature = require('./verifySignature'); 

现在我们执行验证:

 if(!signature.isVerified(req)) { // when the request is NOT coming from Slack! res.sendStatus(404); // a good idea to just make it “not found” to the potential attacker! return; } 

我建议您的应用程序每次从Slack收到请求时都进行验证。

我们再次运行代码,如果一切正常,您可以庆祝成功! 恭喜你!

Source: https://habr.com/ru/post/zh-CN431346/


All Articles