Slack — это популярный инструмент для улучшения общения между членами команды. Он поставляется с множеством полезных функций и услуг, включая сторонние интеграции и поддержку webhook. Вялые веб-зацепки могут быть веселыми и полезными, и их легко настроить. В этом руководстве мы создадим простой сервер с использованием Node.js и Heroku, который будет отвечать на сообщения вашей команды из Slack как «бот». Знакомство с JavaScript и Git будет полезным. Если вы раньше не использовали Git, взгляните на Git для начинающих, чтобы начать. Доступ к учетной записи Slack также предполагается, но не волнуйтесь — они бесплатны!
Создание новой слабой интеграции
В веб-интерфейсе Slack откройте меню в верхнем левом углу рядом с названием вашей команды и выберите « Настроить интеграции» . Здесь вы можете увидеть панель инструментов со всеми доступными вам интеграциями. Прокрутите до самого низа в разделе « Сделай сам» и добавьте исходящий веб-крючок . Прочитайте краткое описание и затем нажмите Add Outgoing WebHooks Integration .
Вы увидите конфигурацию Outgoing WebHook и пример того, как должны выглядеть данные запроса и ответа. Наш первый бот просто приветствует пользователя при вызове. Для этого мы позволим хуку прослушивать слово «привет» на любом канале. Мы еще не знаем URL, по которому он будет публиковаться, поэтому мы вернемся к этой странице позже.
Создание веб-сервера
Мы будем использовать Express 4 на Node.js для создания простого веб-сервера.
Создайте новый каталог для вашего приложения и запустите npm init
чтобы сгенерировать файл package.json
. В ваших зависимостях package.json
"express": "^4.xx"
и "body-parser": "^1.xx"
. Пакет body-parser
будет использоваться для анализа содержимого, отправленного из Slack. Создайте файл сервера с именем app.js
Здесь нам require
необходимые модули, добавлено промежуточное программное обеспечение анализатора тела, обработчик ошибок и маршрут тестирования. Затем мы говорим серверу начать прослушивание.
var express = require('express'); var bodyParser = require('body-parser'); var app = express(); var port = process.env.PORT || 3000; // body parser middleware app.use(bodyParser.urlencoded({ extended: true })); // test route app.get('/', function (req, res) { res.status(200).send('Hello world!') }); // error handler app.use(function (err, req, res, next) { console.error(err.stack); res.status(400).send(err.message); }); app.listen(port, function () { console.log('Slack bot listening on port ' + port); });
Запустите сервер с node app
и убедитесь, что посещение http://localhost:3000
отвечает «Hello world!».
Написание логики бота
Создайте файл с именем hellobot.js
Этот модуль будет там, где живет логика нашего бота. Он будет включать одну экспортированную функцию, которая возвращает сообщение Slack с кодом состояния 200
. Мы начнем с анализа данных, которые Slack отправляет на наш сервер, а затем ответим правильно отформатированными собственными данными. Чтобы сделать это, давайте вернемся к нашему Исходящему WebHook под Настроенными Интеграциями . Пример исходящих данных показывает нам всю информацию, которую Slack отправляет, когда запускается Outoing WebHook.
Вы можете видеть, что некоторые данные могут быть полезны для аутентификации или маршрутизации, но сейчас мы просто сосредоточимся на свойстве user_name
. Используя это значение, мы можем отправить персональное приветствие обратно пользователю.
module.exports = function (req, res, next) { var userName = req.body.user_name; var botPayload = { text : 'Hello, ' + userName + '!' }; // avoid infinite loop if (userName !== 'slackbot') { return res.status(200).json(botPayload); } else { return res.status(200).end(); } }
Здесь мы создаем наш объект botPayload
. Единственное необходимое свойство — это botPayload.text
, которое определяет, что будет отображать наш бот, когда мы ответим. Добавьте text
свойство с приветствием для пользователя и ответьте JSON и кодом состояния 200
. Обратите внимание, что ответ нашего бота является триггерным словом нашего Исходящего WebHook! Чтобы избежать бесконечного цикла, мы можем проверить user_name
тела. Все перехваты публикуются как «slackbot», даже если имя в чате выглядит по-другому. Мы можем использовать этот факт, чтобы наш хук не реагировал сам на себя.
Вернувшись в app.js
, вам потребуется модуль бота вверху.
var hellobot = require('./hellobot');
Затем добавьте маршрут, который прослушивает POST
для /hello
.
app.post('/hello', hellobot);
Давайте сделаем быстрый тест. Запустите приложение снова, используя node app
, и в другом окне терминала используйте curl
чтобы убедиться, что приложение отвечает так, как мы ожидаем. (Примечание: поскольку наш бот ищет здесь только одно значение, нет необходимости включать всю полезную нагрузку Slack в наш тест).
curl -X POST --data "user_name=foobar" http://localhost:3000/hello
Если наше приложение работает, мы должны увидеть ответ, который выглядит следующим образом:
{"text":"Hello, foobar!"}
Теперь пришло время разместить нашего бота в сети.
Развертывание приложения на Heroku
Heroku — это удобный сервис, который поможет вам бесплатно получить веб-сервер онлайн за очень короткое время. Развертывания выполняются путем отправки вашего кода на их git-сервер, где он автоматически развертывается и запускается. Создайте аккаунт на Heroku или войдите, если у вас уже есть аккаунт.
После того, как вы войдете в систему, вы увидите свою панель управления Heroku. Нажмите +
в правом верхнем углу, чтобы создать новое приложение. Следуйте инструкциям, чтобы войти в Heroku на вашем компьютере. Развертывание очень просто, но при первом развертывании приложения нужно знать много нового. При настройке приложения обязательно следуйте этому руководству . По пути мы сделаем несколько двойных проверок, но там есть много полезной информации, которая выходит за рамки этой статьи.
Прежде чем мы сможем развернуть нашего бота, нам нужно рассказать Heroku, как запустить приложение. Это делается путем создания Procfile . Вашему Procfile нужна только одна строка:
web: node app
Как только вы это сделали, вы можете зафиксировать свои изменения и нажать на heroku
. Heroku автоматически установит модули узлов, и вы увидите результаты своего развертывания. Если все прошло гладко, вы увидите ссылку на ваше приложение внизу. Скопируйте этот URL, а затем снова посетите страницу конфигурации вашего Outgoing WebHook. Добавьте скопированный URL-адрес в поле ввода URL-адресов с добавленным /hello
route и измените имя и значок ловушки, если хотите.
Есть еще один шаг, чтобы вывести бота в онлайн: нам нужно дать ему Dyno . В терминале введите:
heroku ps:scale web=1
Это говорит Heroku дать вашему приложению одного веб-работника. Осторожный; Ваше приложение получает только один бесплатный динамо в месяц!
Ваш бот должен быть в сети сейчас, так что вернитесь в Slack и протестируйте его!
Если вы не получили ответ, вернитесь и проверьте свой код. Вы можете использовать heroku logs
команды heroku logs
терминала, чтобы увидеть подробную информацию о запросах, а также любые операторы console.log()
вы добавили.
Не слишком сложно, правда? Мы успешно создали веб-крючок в Slack, развернули наше приложение в Heroku и заставили их поговорить друг с другом! Немного больше работы, чем простая программа «Здравствуй, мир», но гораздо полезнее. Теперь, когда наш сервер запущен, мы можем легко добавить больше хуков и ответов. Hellobot довольно дружелюбный, но не очень полезный. В следующем разделе мы будем использовать другие типы Slack для подключения к чату.
DiceBot — использование слабых команд и входящих веб-крючков
В последнем разделе мы использовали Outgoing WebHook, который прослушивал чат для слова триггера, отправлял сообщение на наш сервер и отображал ответ. В этом разделе мы будем использовать два других инструмента для создания пользовательских интеграций: Slash Commands и Incoming WebHooks . Посетите страницу « Настройка интеграций» и ознакомьтесь с другими вариантами в разделе « Интеграции и настройки DIY» . Давайте начнем с добавления интеграции команд Slash . Прочитайте краткое описание, установите команду «/ roll» и добавьте интеграцию. На следующей странице показана конфигурация. Вы можете видеть, что исходящие данные похожи на исходящий веб-крючок, который мы настроили ранее. Мы будем использовать приложение, которое мы создали в последнем разделе для этого раздела, поэтому мы можем использовать тот же URL, но на этот раз мы отправим POST
к маршруту /roll
.
Обратите внимание, что интеграция Slash Command может отвечать пользователю, но только в частном порядке. Какая польза от броска костей, если только вы можете видеть кости? Slack предлагает использовать Incoming WebHook совместно с Slash Commands для отправки сообщений в чат. Вернитесь на страницу Configure Integrations и добавьте входящий WebHook . Прочитайте описание, выберите канал и добавьте хук. Не беспокойтесь о том, какой канал вы выбрали; мы можем указать канал в ответе нашего бота. Поскольку мы можем выбрать канал в нашем приложении, это означает, что мы также можем использовать эту интеграцию для любых других созданных нами ботов. Входящий WebHook не имеет особых возможностей для настройки, но в нем есть много важной информации для построения полезных нагрузок нашего бота. Наиболее важной частью является URL-адрес Webhook . Мы будем размещать сообщения из нашего приложения для отправки сообщений в Slack.
Ответ на команды косой черты с сервера
Поскольку мы указали нашу команду Slash на маршрут /roll
, мы можем добавить этот маршрут на наш сервер вместе с hellobot. Мы будем использовать секретный URL-адрес для нашего входящего хука, поэтому рекомендуется скрыть его на случай, если вы захотите сделать свой код общедоступным. Хороший способ сделать это — использовать конфигурационные переменные Heroku.
Также добавим request
в наш пакет для использования с входящим хуком:
npm install --save request
Теперь мы добавим dicebot.js
. Dicebot экспортирует одну функцию, но нам понадобятся две дополнительные функции: одна для POST
для входящего WebHook и одна для броска костей.
var request = require('request'); module.exports = function (req, res, next) { }; function roll () { } function send () { }
Как известно многим настольным геймерам, существует гораздо больше видов игральных костей, чем просто шестигранные. Другие кости имеют четыре стороны, восемь сторон, десять сторон, двадцать сторон и многое другое! При броске этих костей используются специальные обозначения: <number of dice>d<sides of dice>
. Итак, бросание двух шестигранных кубиков обозначается как «2d6». Мы можем позволить пользователям бросать несколько кубиков, используя эту нотацию, но нам нужно будет проверить правильность ввода от пользователя.
Давайте начнем с инициализации некоторых переменных и анализа входных данных. Мы установим некоторые значения по умолчанию на случай, если пользователь захочет пропустить ввод.
module.exports = function (req, res, next) { // default roll is 2d6 var matches; var times = 2; var die = 6; var rolls = []; var total = 0; var botPayload = {}; if (req.body.text) { // parse roll type if specified matches = req.body.text.match(/^(\d{1,2})d(\d{1,2})$/); if (matches && matches[1] && matches[2]) { times = matches[1]; die = matches[2]; } else { // send error message back to user if input is bad return res.status(200).send('<number>d<sides>'); } } }
Приведенное выше регулярное выражение достаточно надежно для разбора бросков кубиков и ограничивает значения только двузначными числами, чтобы пользователь не мог сходить с ума. Если пользователь испортил свой синтаксис, мы отправим подсказку.
Бросать кости с пользовательским вводом достаточно легко. Смотрите эту ветку для объяснения того, как работает случайный бросок. Для действительно случайных бросков вы можете обратиться к API random.org . Давайте напишем функцию крена.
function roll (min, max) { return Math.floor(Math.random() * (max - min + 1) + min); }
Затем в нашей основной функции мы сделаем несколько бросков и создадим сообщение для ответа. Давайте включим название ролика, чтобы другие пользователи могли видеть, кто использовал команду /roll
.
// roll dice and sum for (var i = 0; i < times; i++) { var currentRoll = roll(1, die); rolls.push(currentRoll); total += currentRoll; } // write response message and add to payload botPayload.text = req.body.user_name + ' rolled ' + times + 'd' + die + ':\n' + rolls.join(' + ') + ' = *' + total + '*';
Мы добавили сообщение в свойство botPayload.text
с небольшим форматированием Slack, чтобы сделать его жирным. Мы также можем настроить имя, значок и канал, используя полезную нагрузку ответа. Мы установим канал на основе канала, с которого пользователь выдает команду roll. Слэк предлагает использовать название канала в полезной нагрузке, но это означает, что мы должны добавить его к «#». Вместо этого мы можем использовать идентификатор канала, который позволит нам публиковать в общедоступных каналах, а также в частных группах. Для иконки существует удобный эмодзи, хотя вы могли бы обеспечить лучшее изображение, используя icon_url
.
botPayload.username = 'dicebot'; botPayload.channel = req.body.channel_id; botPayload.icon_emoji = ':game_die:';
Полезная нагрузка выглядит хорошо. Давайте напишем функцию send
. Я решил хранить только токены пути в конфигурационных переменных Heroku. Обязательно отправьте тело в виде строки JSON.
function send (payload, callback) { var path = process.env.INCOMING_WEBHOOK_PATH; var uri = 'https://hooks.slack.com/services' + path; request({ uri: uri, method: 'POST', body: JSON.stringify(payload) }, function (error, response, body) { if (error) { return callback(error); } callback(null, response.statusCode, body); }); }
В нашей основной функции мы инициируем запрос на отправку. Если это работает, мы можем ответить на команду Slash с пустыми 200
. Если нет, мы можем использовать значения из нашего обратного вызова send()
для создания ошибки. Это вызовет обработчик ошибок в app.js
и отправит обратно 400
, который уведомит пользователя об ошибке.
// send dice roll send(botPayload, function (error, status, body) { if (error) { return next(error); } else if (status !== 200) { // inform user that our Incoming WebHook failed return next(new Error('Incoming WebHook: ' + status + ' ' + body)); } else { return res.status(200).end(); } });
Давайте запустим наш сервер и curl
его снова. На этот раз нам нужно будет включить channel_id
. Вы можете использовать тестер Slack API, чтобы найти правильный channel_id
. Поскольку Incoming WebHook уже настроен, он должен услышать, как наш сервер вызывает его. Нам также нужно будет включить путь Incoming WebHook в нашу среду, поскольку приложение еще не доступно в Heroku.
INCOMING_WEBHOOK_PATH=/your/path/tokens node app
curl -X POST --data "user_name=foobar&channel_id=C0123ABCD&text=4d6" http://localhost:3000/roll`
Выглядит хорошо! Давайте развернем это.
Перевод в Heroku
Поскольку мы использовали конфигурационные переменные Heroku для хранения токена нашего webhook, не забудьте установить его в меню « Настройки» приложения.
Затем с помощью git добавьте новые файлы, heroku
изменения и heroku
на свой пульт heroku
. Heroku установит модули узлов и запустит сервер. Прежде чем мы протестируем это, давайте начнем смотреть логи в режиме реального времени:
heroku logs -t
После того, как все наши крюки настроены, наша команда крена должна быть готова к работе. Попробуйте несколько рулонов! Если что-то не работает, вы можете использовать журналы Heroku для отладки. Чтобы увидеть законченное приложение в полном объеме, посмотрите репозиторий GitHub .
Продолжение развития
Эти два бота демонстрируют все инструменты, необходимые для написания собственных чатов и интеграций. Вы можете интегрировать множество сервисов в ботов или попытаться найти убедительного партнера по общению. Для достижения обеих целей существуют API-интерфейсы и модули узлов.
Некоторые другие идеи для ботов:
- бот, который использует GitHub API, чтобы показать вам открытые запросы
- бот, который использует Yelp API, чтобы помочь вашей команде выбрать обед
- бот, который ищет вас в Google
- бот, который разговаривает с вами только с умными словами и жаргоном
Если у вас появятся хорошие идеи, поделитесь своим кодом! Ботов делать весело, и их никогда не было так просто создать.