З мовою програмування Go я почав працювати відносно недавно і тепер розширюю площину її застосування. Традиційно, я почав з розробки мікросервісів, наступним етапом були децентралізовані програми та блокчейн на основі бібліотеки IPFS. Тепер я спробував написати свого простого бота для меседжера Slack. Результатом став цей простий тюторіал. Сподіваюсь, він допоможе комусь із вас написати свого власного бота.
Ідея виникла, коли я випадково натрапив на проект Пятиминутка PHP - бот для Радио-Т на GitHub. Цей бот працює так. Якщо в чаті згадується PHP, то бот повідомляє якийсь цікавий факт про цю мову програмування. Я трохи розширив функціонал: наш Slack бот буде шукати в нових повідомленнях заданий набір ключових слів і, якщо знайде відповідність, у відповідь надішле один з цікавих фактів, який відновиться до цих ключових слів. Таким чином ми не будемо прив’язуватись до PHP і зробимо бота більш гнучким в конфігурації.
Для зручності, я виділив частину функціоналу в окрему бібліотеку, яка буде “знати” факти та вміти шукати їх. При її ініціалізації потрібно вказати де саме зберігаються файли з фактами і все. Далі користуючись методами GetFact(keyword) чи FindFact(message) можна отримувати випадкові факти, відповідно до переданих параметрів. Формат файлів з фактами можна знайти в README файлі самої бібліотеки. Там же описано як приєднати її до вашого проекту.
Slack API достатньо великий і містить безліч способів інтеграції вашого додатку в Slack. Ми будемо використовувати тільки невелику його частину для роботи з історією повідомлень в каналі. Для комунікації нашого боту з API будемо використовувати бібліотеку Slack API in Go, яка підтримує більшість, якщо не всі, функції із Slack API.
Що таке Slack-бот можна прочитати тут. Якщо коротко, то це спеціальний тип користувача, який має більшість атрибутів звичайного користувача і може бути доданим в будь-який канал. Головна відмінність бота від користувача це те, що замість взаємодії з командою він буде користуватись не мобільним додатком, а Slack API в автоматичному режимі, також він не може залогінитись і не має паролю.
Замість пароля користувач-бот має токен. Для його отримання потрібно перейти на сторінку створення боту і залогінитись в Slack. Після цього ви побачите форму реєстрації бота:
Введіть в поле ім’я вашого боту і натисніть кнопку Add bot integration. Після цього ви потрапите на сторінку, де зможете додати інші параметри, наприклад, іконку або повне ім’я. На цій же сторінці буде токен, з допомогою якого наш бот буде авторизуватись в системі.
Тепер можемо перейти безпосередньо до реалізацій боту. Тут теж все просто. Наш проект буде побудований на базі інструменту збірки gb (перед початком роботи необхідно встановити gb у ваш $GOPATH), тому структура проекту буде продиктована ним. Вона буде мати приблизно такий вигляд як на малюнку. Теки src/* є обов’язковими:
Для простоти можна проігнорувати створення файлу конфігурації config.xml і вичитування його в момент запуску додатку. Роботу з ним можна подивитись в репозиторій проекту. В прикладах цього проекту ми будемо всі параметри “хардкодити”. Також весь код може бути написаний в методі main() проекту, а не розкиданим по пакетах як в репозиторії.
Спочатку ініціюємо бібліотеку з фактами:
package main
import (
facts "github.com/sheremetat/randfacts-lib"
)
func main() {
factLib, err := facts.Init("./facts")
if err != nil {
log.Errorf("Error in main(): %v", err)
panic("Error in main(): " + err.Error())
}
...
Тепер напишемо самого бота. Доповнюємо main(). У фрагменті коду є коментарі, які описують, що саме там відбувається:
...
// Initialization of Slack Bot
api := slack.New("[Your Slack Bot Token]")
api.SetDebug(true)
// Open web socket connection
rtm := api.NewRTM()
go rtm.ManageConnection()
// Reading events from Slack
for msg := range rtm.IncomingEvents {
log.Print("Event Received: ")
switch ev := msg.Data.(type) {
case *slack.HelloEvent:
// Ignore hello
case *slack.ConnectedEvent:
// Ignore connection event
case *slack.MessageEvent:
// Processing message in channel
fact, err := factLib.FindFact(ev.Msg.Text)
// Check if fact for message found
if err == nil && len(fact) > 0 {
// Send message back to channel with fact
outMsg := rtm.NewOutgoingMessage(fact, ev.Channel)
outMsg.Channel = ev.Channel
rtm.SendMessage(outMsg)
}
default:
// Ignore other events..
}
}
}
Залишилось зібрати та запустити нашого простого бота. Для цього в корені виконаємо дві команди з консолі:
~$ gb build
~$ bin/factsbot
Якщо все запустилось без проблем (а я сподіваюсь, що так і було) то в вашому Slack новий користувач @[ім’я бота] змінить стан на “в мережі”. Напишіть йому повідомлення з вашими словами для пошуку і отримаєте цікавий факт у відповідь.
Код бібліотеки та моєї реалізації бота доступні на Github.com.
Програмуйте із задоволенням!