Главная » Хабрахабр » Разработка Action-able приложения для Slack

Разработка Action-able приложения для Slack

От переводчика: публикуем для вас статью Томоми Имуры о том, как разработать приложение, интегрированное со Slack

Эта функция похожа на встроенные возможности вроде комментирования или шеринга. Actions — то, что позволяет пользователям Slack взаимодействовать с вашим приложением при помощи сообщений: сообщить о проблеме с багом, отправить запрос в хелпдеск или сделать что-то еще.

Этот туториал проведет вас через весь процесс создания действующего приложения.

Skillbox рекомендует: Двухлетний практический курс «Я – Веб-разработчик PRO».

Напоминаем: для всех читателей «Хабра» — скидка 10 000 рублей при записи на любой курс Skillbox по промокоду «Хабр».

Туториал будет полезен для всех, кто хотел бы изучить API Slack. При разработке приложения используется Node.js, так что, если вы хотите повторить то, о чем пойдет разговор, — установите его.

С готовым проектом можно ознакомиться на GitHub, с упрощенной его версией — на Glitch.

for Slack ClipIt!

Давайте представим, что мы управляем веб-сервисом, который позволяет «заложить» часть веб-страницы, сохранив ее в базу данных. Мы займемся разработкой Slack-app для воображаемого приложения ClipIt! А еще ClipIt! Пользователи могут получать доступ к сохраненному контенту с мобильного устройства или ПК, сервис является мультиплатформенным. позволяет прикреплять текст в среде сообщений Slack, используя Action.

Вот гифка, демонстрирующая принцип действия приложения.

из Slack: А вот алгоритм взаимодействия пользователя с ClipIt!

  • Пользователь наводит курсор на сообщение и выбирает Clip the message в выпадающем меню.
  • Открывается диалог, который дает больше возможностей.
  • Пользователь подтверждает действие.
  • ClipIt! для Slack экспортирует сообщение в базу данных ClipIt!.
  • ClipIt! для Slack отправляет пользователю DM с подтверждением.

Настраиваем приложение

Зайдите в свой аккаунт Slack и создайте приложение при помощи этой ссылки. Введите его название и область применения.

Нажмите кнопку Create App, затем — Basic Information, прокрутите до App Credentials.

Я объясню, что это и как все это использовать, в разделе «Верификация запросов» чуть ниже. После этого откройте Signing Secret и скопируйте код для использования в качестве переменной окружения SLACK_SIGNING_SECRET в вашем .env-файле в root Node.

SLACK_SIGNING_SECRET=15770a…

Прокрутите еще немного ниже для заполнения Display Information с иконкой вашего приложения и описанием.

Сделав это, вы увидите больше полей на странице. Теперь включите Interactivity в Interactive Components.

Пора ввести Request URL — это адрес, на который Slack отсылает соответствующие данные, когда пользователь запускает действие.

Например, если вы разместили все это в Glitch, ваш URL будет выглядеть примерно так example.glitch.me/actions. Это должен быть URL вашего сервера, на котором выполняется код приложения. Если вы используете туннелирование, работая с сервисами вроде ngrok, то используйте URL сервиса (например example.ngrok.io, а затем добавляйте /actions).

Заполните форму: Как только вы ввели Request URL, прокрутите вниз до Actions и нажмите Create New Action.

Нажмите Create, затем Save Changes.

Нажмите Add a Bot User и назовите бота приложения. Далее идем к Bot Users.

Теперь кликаем по Add Bot User и сохраняемся.

После завершения установки страница вернет вас к OAuth & Permission с токенами доступа. Следующий шаг — идем в OAuth & Permissions и нажимаем Install App to Workspace. Скопируйте токен бота и сохраните все это в файле .env.

SLACK_ACCESS_TOKEN=xoxb-214…

Сделав это, удостоверьтесь, что и bot, и command выделены. Кроме того, на той же странице нужно будет активировать Scopes.

Теперь, когда все настройки готовы, начинаем творить — пишем приложение.

Создание приложения

Как говорилось выше, при создании приложения используются Node.js и ExpressJS. Для того чтобы работать со всем этим, устанавливаем зависимости ExpressJS, bodyParser и еще кое-что. Так, я используют клиент HTTP-запросов axios вместе с qs.

$ npm install express body-parser 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()); const server = app.listen(5000); // port

Прежде чем продолжить, давайте взглянем на диаграмму с описанием принципов работы всего, о чем мы сейчас говорим.

Как только срабатывает событие message_action, Slack отправляет приложению payload по URL-адресу запроса, который был прописан ранее. Каждый поток инициализируется, когда пользователь выполняет actions, расположенные в меню сообщений.

Эндпоинт можно прописать следующим образом:

/* 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, приложение открывает диалог.

Потом добавляем код, определяющий структуру контента диалога, с открытием его в клиенте Slack, используя метод dialog.open:

/* 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 для выполнения запроса POST к Slack; после этого метод dialog.open открывает диалог, отправляя HTTP статус 200.

В коде snippet 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, перед тем как принимать их в работу.

Заменяем то место, где есть комментарий //The next two lines will be modified later, на вот это: Для этого возвращаемся в snippet 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.

Поздравляю! Запускаем код снова, и, если все работает, как нужно, можно праздновать успех!


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Перевезти дата-центр за 14 400 секунд

Всем знакома пословица «Один переезд равен двум пожарам». Смысл этой народной мудрости в том, что процесс переезда сопряжен со стрессами, суетой, переживаниями и, конечно, беготней, которые бывают и при пожаре, а подчас и с утратами ценного имущества. К тому же, ...

Дорожная карта математических дисциплин для машинного обучения, часть 1

Вместо предисловия Допустим, сидя вечерком в теплом кресле вам вдруг пришла в голову шальная мысль: «Хм, а почему бы мне вместо случайного подбора гиперпараметров модели не узнать, а почему оно всё работает?»Это скользкий путь — вы думаете, что достаточно пары ...