В последнее время сервис для командного общения стал очень популярен.
Слабый .
«Из коробки» имеет немалое количество интеграций.
с различными услугами + довольно удобное внешнее API. Но при всем этом на бесплатных аккаунтах действует ограничение в 5 интеграций.
Прикрепили github, newrelic + пару плат с trello и всё, они закончились.
Можно использовать универсальный Входящий вебхук , но он естественно имеет свой формат и никак не совместим с другими сервисами.
Но программист не был бы программистом, если бы не решил эту задачу.
Решение простое, как молоток.
Мы сами принимаем хуки от сервисов, обрабатываем их и отправляем в Slack в нужном нам виде.
Помимо интеграций в список вошли: гамак , который написан на PHP и имеет некоторые набор плагинов , но мне это решение не особо понравилось.
Хоть и есть готовые интеграции, но нужных, увы, нет, а так как я знаком с PHP на уровне чтения кода и «исправления чего-то из справочника», писать свою у меня не возникло желания.
Вот почему я решил написать свой собственный сервис.
Я решил построить его полностью по модульному принципу: ядро и отдельные модули «ввода» и «выхода».
В качестве языка я использовал Ruby; его динамичный характер очень помог в реализации моих планов.
Итак, знакомьтесь
Хукслер!
Позволяет создать сервис получения уведомлений и их дальнейшей отправки с минимумом кода.Для настройки используйте собственный DSL:
Вначале объявляются точки ввода/вывода, каждая имеет свое имя и тип, а также может содержать дополнительные параметры для инициализации.require 'hooksler/slack' require 'hooksler/newrelic' require 'hooksler/trello' require 'dotenv' Dotenv.load Hooksler::Router.config do secret_code 'very_secret_code' host_name ' http://example.com ' endpoints do input 'simple', type: :simple input 'newrelic', type: :newrelic input 'trello', type: :trello, create: false, public_key: ENV['TRELLO_KEY'], member_token: ENV['TRELLO_TOKEN'], board_id: ENV['TRELLO_ID1'] output 'black_hole', type: :dummy output 'slack_out', type: :slack, url: ENV['SLACK_WEBHOOK_URL'], channel: '#test' end route 'simple' => 'slack_out' route 'trello' => ['black_hole', 'slack_out'] route 'newrelic' => ['black_hole', 'slack_out'] end
Ниже приведены маршруты.
Его можно указывать в разных формах: один к одному, один ко многим и наоборот. Вы также можете прикрепить к каждому маршруту фильтры, которые могут как модифицировать сообщение, так и фильтровать его.
Таким образом мы получаем достаточно гибкое ядро для маршрутизации сообщений из точки А в точку Б.
Сообщения внутри передаются во внутреннем представлении, и известно от какого сервиса (его типа) оно было получено + исходное сообщение.
При получении заполняются типовые поля: пользователь, текст, заголовок, ссылка, уровень.
В будущем их можно будет использовать для генерации уведомлений.
На данный момент ядро полностью реализовано, протестировано и покрыто тестами.
Также реализовано несколько интеграций: trello, newrelic, slack. Очень легко написать свою собственную интеграцию.
Немного практики
Получение сообщений
Например, мы создадим модуль, который позволит вам разместить тело POST-запроса в поле сообщения.
class DummyInput
extend Hooksler::Channel::Input
register :dummy
def initialize(params)
@params = params
end
def load(request)
build_message({}) do |msg|
msg.message = request.body.read
end
end
end
Давайте объявим класс и расширим его соответствующим модулем.
Тогда мы зарегистрируем его имя.
Все, после этого мы готовы принимать и обрабатывать входящие данные.
Обработка запроса осуществляется в методе нагрузка , который принимает только один параметр — объект класса Стойка::Запрос .
Какая-то сложная обработка нам не нужна, поэтому сразу создаем сообщение и заполняем поле.
После этого он пойдет дальше по маршрутам, описанным в конфигурации.
Для отправки можно создать сразу несколько сообщений, т.е.
метод нагрузка вернет массив.
В дальнейшем каждый объект обрабатывается отдельно.
Отправка сообщений
Столь же просто создать модуль отправки, который позволит нам видеть полученные сообщения в консоли: class DummyOutput
extend Hooksler::Channel::Output
register :dummy
def initialize(params)
@params = params
end
def dump(message)
puts "-- #{message.title} : #{message.level} --"
puts message.user
puts message.message
puts message.url
end
end
Проделываем те же действия, что и для входящего, только выбираем соответствующий модуль расширения.
Отправка, в нашем случае вывод на консоль, осуществляется в методе свалка .
Название метода спорное, но send уже был занят и переопределять его не хотелось.
Теперь соберем все это и опишем маршруты:
Hooksler::Router.config do
secret_code 'very_secret_code'
host_name ' http://example.com '
endpoints do
input 'in', type: :dummy
output 'out', type: :dummy
end
route 'in' => 'out'
end
Указываем код, который используется для генерации путей и хост, на котором будет висеть наш сервис.
Запустим и все готово.
Конечные пути вы можете просмотреть, обратившись http://example.com/_endpoints_ , ответ будет в формате JSON. Более подробный пример можно найти в ДЕМО-приложении: github.com/hooksler/hooksler-demo Таким образом, без особых усилий вы можете настроить пересылку сообщений одновременно в разные точки: получать изменения из Trello, пересылать их в Slack или отправлять особо важные (например, содержащие ключевые слова или теги) push-уведомлением на телефон.
Схем можно придумать кучу, благо основа гибкая.
Более практичный пример
На днях передо мной встала задача автоматизировать процесс приглашения пользователей в Slack. Добавлять всех вручную долго и нудно, а открытую регистрацию из коробки не создать.В интернете есть готовая форма на nodejs. А потому что у меня уже есть рабочий хукслер и я решил на нем сделать.
Во-первых, вам нужно как-то получить правильную почту, для этого вы воспользовались возможностью Mandrill оборачивать входящие сообщения в Webhook (именно то, что доктор прописал).
Далее создаем почтовый ящик, настраиваем Webhook и пишем наш получатель: require 'hashie'
module Hooksler
module Mandrill
class Input
extend Hooksler::Channel::Input
register :mandrill
def initialize(params)
@params = Hashie::Mash.new(params)
end
def load(request)
return unless request.content_type == 'application/x-www-form-urlencoded'
action, payload = request.POST.first
return unless action == 'mandrill_events'
payload = MultiJson.load(payload)
payload.map do |event|
build_message(event) do |msg|
begin
method_name = "for_#{event['event']}"
self.send method_name, msg, event if respond_to? method_name
rescue
end
end
end
end
def for_inbound(msg, event)
msg.message = event['msg']['text'] || event['msg']['html']
msg.title = event['msg']['subject']
msg.user = event['msg']['headers']['From']
end
end
end
end
Принимаем события, оборачиваем их в Message и идем дальше.
Теперь нам нужен код, который будет приглашать пользователей: class SlackInviteOutbound
extend Hooksler::Channel::Output
register :slack_invite
def initialize(params)
@params = params
end
def dump(message)
return unless message.source == :mandrill
email = message.raw['msg']['from_email']
url = " https://#{@params[:team]}.
slack.com/api/users.admin.invite "
HTTParty.post url, body: { email: email, token: @params[:token], set_active: true }
end
end
Принимаем сообщение, проверяем, что оно пришло от Mandrill, получаем письмо, запрос и пользователя приглашают. При этом мы абсолютно уверены, что коробка действительна.
В качестве последнего штриха настройте маршрутизацию: endpoints do
input 'slack_invite', type: :mandrill
output 'slack_invite', type: :slack_invite, team: 'myteam', token: 'mysupersecrettoken'
end
route 'slack_invite' => 'slack_invite'
Запускаем и наслаждаемся процессом.
Окончательно
Я уже некоторое время пользуюсь этим решением, пока никаких проблем не возникло - все работает гладко.Единственное, не все дела обрабатываются в Trello; у них слишком много разных типов уведомлений.
Также мы сделали свои модули форматирования для Slack, кому интересно может посмотреть пример здесь .
В будущем мы планируем расширить количество адаптеров как для приема, так и для отправки сообщений.
Я надеюсь, что это решение будет полезно кому-то еще.
Критика и предложения приветствуются, об ошибках в тексте пишите мне.
Сам Hooksler и адаптеры доступны на Github: github.com/hooksler Теги: #hooksler #ruby #Slack #Trello #agile #notifications #ruby
-
Лучшее Ftp-Приложение Для Mac
19 Oct, 24 -
Гномику 15 Лет!
19 Oct, 24 -
+10 К Интеллекту
19 Oct, 24 -
P2P-Медиа
19 Oct, 24