Блог переїхав на HUGO . Нова адреса сайту https://sheremetat.dev
З мовою програмування Go я почав працювати відносно недавно і тепер розширюю площину її застосування. Традиційно, я почав з розробки мікросервісів, наступним етапом були децентралізовані додатки на основі бібліотеки IPFS. Тепер я спробував написати свого простого бота для меседжера Slack. Результатом став цей простий тюторіал. Сподіваюсь, він допоможе комусь із вас написати свого власного бота.
Ідея виникла, коли я випадково натрапив на проект Пятиминутка PHP - бот для Радио-Т на GitHub. Цей бот працює так. Якщо в чаті згадується PHP, то бот повідомляє якийсь цікавий факт про цю мову програмування. Я трохи розширив функціонал: наш Slack бот буде шукати в нових повідомленнях заданий набір ключових слів і, якщо знайде відповідність, у відповідь надішле один з цікавих фактів, який відновиться до цих ключових слів. Таким чином ми не будемо прив'язуватись до PHP і зробимо бота більш гнучким в конфігурації.
Для зручності, я виділив частину функціоналу в окрему бібліотеку, яка буде "знати" факти та вміти шукати їх. При її ініціалізації потрібно вказати де саме зберігаються файли з фактами і все. Далі користуючись методами GetFact(keyword) чи FindFact(message) можна отримувати випадкові факти, відповідно до переданих параметрів. Формат файлів з фактами можна знайти в README файлі самої бібліотеки. Там же описано як приєднати її до вашого проекту.
Замість пароля користувач-бот має токен. Для його отримання потрібно перейти на сторінку https://my.slack.com/services/new/bot і залогінитись в Slack. Після цього ви побачите форму реєстрації бота:
Введіть в поле ім'я вашого боту і натисніть кнопку "Add bot integration". Після цього ви потрапите на сторінку, де зможете додати інші параметри, наприклад, іконку або повне ім'я. На цій же сторінці буде токен, з допомогою якого наш бот буде авторизуватись в системі.
Для простоти можна проігнорувати створення файлу конфігурації config.xml і вичитування його в момент запуску додатку. Роботу з ним можна подивитись в репозиторій проекту. В прикладах цього проекту ми будемо всі параметри "хардкодити". Також весь код може бути написаний в методі main() проекту, а не розкиданим по пакетах як в репозиторії.
Спочатку ініціюємо бібліотеку з фактами:
Тепер напишемо самого бота. Доповнюємо main(). У фрагменті коду є коментарі, які описують, що саме там відбувається:
Ідея виникла, коли я випадково натрапив на проект Пятиминутка PHP - бот для Радио-Т на GitHub. Цей бот працює так. Якщо в чаті згадується PHP, то бот повідомляє якийсь цікавий факт про цю мову програмування. Я трохи розширив функціонал: наш Slack бот буде шукати в нових повідомленнях заданий набір ключових слів і, якщо знайде відповідність, у відповідь надішле один з цікавих фактів, який відновиться до цих ключових слів. Таким чином ми не будемо прив'язуватись до PHP і зробимо бота більш гнучким в конфігурації.
Для зручності, я виділив частину функціоналу в окрему бібліотеку, яка буде "знати" факти та вміти шукати їх. При її ініціалізації потрібно вказати де саме зберігаються файли з фактами і все. Далі користуючись методами GetFact(keyword) чи FindFact(message) можна отримувати випадкові факти, відповідно до переданих параметрів. Формат файлів з фактами можна знайти в README файлі самої бібліотеки. Там же описано як приєднати її до вашого проекту.
Slack API
Slack API достатньо великий і містить безліч способів інтеграції вашого додатку в Slack. Ми будемо використовувати тільки невелику його частину для роботи з історією повідомлень в каналі. Для комунікації нашого боту з API будемо використовувати бібліотеку Slack API in Go, яка підтримує більшість, якщо не всі, функції із Slack API.Реєстрація бота
Що таке Slack-бот можна прочитати тут. Якщо коротко, то це спеціальний тип користувача, який має більшість атрибутів звичайного користувача і може бути доданим в будь-який канал. Головна відмінність бота від користувача це те, що замість взаємодії з командою він буде користуватись не мобільним додатком, а Slack API в автоматичному режимі, також він не може залогінитись і не має паролю.Замість пароля користувач-бот має токен. Для його отримання потрібно перейти на сторінку https://my.slack.com/services/new/bot і залогінитись в 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.. } } }
Залишилось зібрати та запустити нашого простого бота. Для цього в корені виконаємо дві команди з консолі:
Якщо все запустилось без проблем (а я сподіваюсь, що так і було) то в вашому Slack новий користувач @[ім'я бота] змінить стан на "в мережі". Напишіть йому повідомлення з вашими словами для пошуку і отримаєте цікавий факт у відповідь.
Код бібліотеки та моєї реалізації бота доступні на Github.com.
Програмуйте із задоволенням!
~$ gb build ~$ bin/factsbot
Якщо все запустилось без проблем (а я сподіваюсь, що так і було) то в вашому Slack новий користувач @[ім'я бота] змінить стан на "в мережі". Напишіть йому повідомлення з вашими словами для пошуку і отримаєте цікавий факт у відповідь.
Код бібліотеки та моєї реалізації бота доступні на Github.com.
Програмуйте із задоволенням!