План статьи:
- Вступление
- Немного о slackclient 1.0
- Что нового в slackclient 2.0
- Как изменения 2.0 сделают жизнь разработчика легче.
Вступление
Часто, когда начинаешь пользоваться библиотеками, понимаешь, что без недостатков никак. Конечно, в этом может быть замешан быстрый старт, когда не особо задумываются о том, что людям как-то нужно будет тестировать свой софт, который использует эту библиотеку. Естественно, тут и нехватка времени у разработчиков и много других факторов. Ведь опенсоурс — это не всегда основное время разработчиков, скорее это больше свободное время. Но я очень благодарен все тем, кто вкладывает свое время в опенсоурс — без вас ребята, прогресс невозможен. Без вас, миром будет править небольшая часть людей (во главе корпораций), с закрытыми наглухо технологиями.
Но как говорится, не важно сколько ошибок ты совершил, важно то, что ты их решал или хотя бы пытался решить. И приятно осознавать что библиотека растет и развивается и вот уже в ней есть все то малое и необходимое, для написания интеграционных или e2e тестов в отрыве от сервисов развернутых в интернете.
Немного о slackclient 1.0
Ничего более подходящего для написания бота, в тот момент как мы его задумали написать на python, не было.
На дворе был апрель 2019 года, когда я нашел вот эту библиотеку https://github.com/slackapi/python-slackclient, на тот момент была доступна официально версия 1.X.X она и ставилась, по умолчанию. Я сразу решил, что буду использовать RTMClient, а не веб-хуки. Почему так, да потому что проще всего тестировать, можно запускать бота из локалки и не использовать дополнительные средства туннелирования трафика на локалку из вне. Клиент через протокол веб-сокетов, коннектится к серверу после получения настроек wss сервера и в реальном времени может получать все данные, приходящие из чатов слака.
Тут было несколько моментов:
- Цикл чтения сообщений нужно реализовывать самому
- В ходе длительного тестирования обнаружилось, что не посылаются Heartbeat пакеты типа ping-pong для удержания живого ws/wss соединения, по умолчанию (ну хотя бы с каким либо зашитым интервалом).
- Heartbeat пакеты нужно слать самому, но это не проблемка.
- Вся работа по распознаванию нужного, для вас типа сообщения, лежит целиком на вас. Так как кроме обычных сообщений есть и всякие другие типы.
И вот так собственно производится запуск бота
- Инстанс сервера, через который, можно было отправлять сообщения, находился внутри инстанса клиента и создавается внутри неявным образом и как такового разделения веб части от реалтайм мессенджинга не было. Для веб части нет необходимости держать постоянное соединение. Для RTM — необходимо.
- И самое печальное, я не нашел как можно изменить URL для RTM соединения, легитимным и удобным способом
Что нового в slackclient 2.0
Ну тут ребята полностью все переписали и убрали все выше-перечисленные моменты. 30 апреля 2019 года ребята выкатили версию 2.0, что собственно показало понимание проблем разработчиков и открыла новые возможности, в использовании и тестировании.
Теперь полноценная поддержка Python 3.6 и выше с использованием всех возможных плюшек асинхронности. Python 2.7 остался поддерживаться в 1.X.X версии.
Ребята разделили RTMClient и WebClient. Очень хорошее правило:
“Лучше пусть модуль/функция/класс, выполняет одну единственную функцию, но выполняет ее - хорошо”!.
Добавили функции обертки @slack.RTMClient.run_on(event=’name_of_event’) для обработчиков для следующих событий:
- message — событие для приходящего сообщения с типом “message”. Теперь именно сообщения будут попадать в обработку и не нужно самому их вылавливать.
- open — событие возникающее при успешном открытии соединения RTM (а тут можно запустить какие либо фоновые таски, получить данные о пользователе бота и его идентификаторе и так далее. Это теперь входная точка)
- close — событие возникающее при закрытии соединения (соответственно тут можно произвести необходимые меры по очистки ресурсов, остановки асинхронных тасков в фоне и так далее)
- error — событие при возникновении ошибки
Но самое главное и нужное обновление — это возможность изменить базовый URL до апи слака, с обращению к которому и начинается работа RTM.
Более детально об изменениях вы можете почитать по ссылке https://github.com/slackapi/python-slackclient/wiki/Migrating-to-2.x
Как изменения 2.0 сделают жизнь разработчика легче.
Ну а теперь, о самом главном, что собственно и сподвигло меня пройти непростой, хоть и короткий путь для обновления до версии 2.0 — это конечно же возможность указать свой базовый урл. А вместе с этим и создание Фейк-Слака, что дало возможность без внешнего сервера слака тестировать RTM версию бота вместе с WEB частью.
Теперь код бота выглядит вот так:
Есть некоторые моменты, с вызовами синхронного кода внутри асинхронного и наоборот. Но легко преодолеть эти моменты, мне помогла библиотека от команды Django https://github.com/django/asgiref/, с ее обертками для функций
В общем, не секрет, если у проекта хорошая документация по API, то и разобраться как она работает можно без проблем. За это спасибо Slack инженерам.
Фейк-слак был затеян мной, чтобы облегчить и уменьшить время запуска девелоперовской версии проекта. Ведь при этом не нужно создавать воркспейс слака и не нужно добавлять туда приложение, не нужно хранить секреты, каким то образом их передавать разработчику. Конечно для финальной версии, перед выпуском в продакшн, по-любому нужно будет запустить бота на каком либо тестовом чате и указать реальные настройки, но это нужно будет позже, а для тестирования локального функционала, подойдет и Фейк-Слак.
К примеру, после его создания, я нашел проблему при отправки оповещений “о наборе сообщения пользователем” (typing), почему-то они приходили скопом, вместе с сообщением. Проблема оказалась в синхронном коде, что блокировал асинхронный луп. Решение запуска такого кода в отдельной асинхронной таске — сработало отлично. А так как мой Фейк-Слак, отображает приходящие через веб-апи сообщения в RAW JSON виде, то и заметить что-то неладное проще, чем наблюдать за реальным интерфейсом Cлака.
Фейк-Слак написан на Node.js + express + express-ws, чтобы как говорится не особо заморачиваться.
И имеет следующий интерфейс:
Возможности Фейк-слака пока скудные (но все еще впереди!)
- Возможность отдачи настроек RTM по веб запросу rtm.connect
- Отдача списка каналов channels.list
- Ответ на запрос auth.test c выдачей информации о команде и пользователе
- Обработка сообщений посылаемых через chat.postMessage
- Отсылка через веб-сокетное соединение простого сообщения боту (без всякого форматирования)
Он очень хорошо помогает в тестировании, а также его можно будет в будущем адаптировать для написания e2e и интеграционных тестов. Думаю что должно получиться хорошо.
Теперь указав base_url=http://domain:9001, для инстансов RTM и Web клиентов, могу проверять базовый функционал бота. Без танцев и бубна.
Дисклеймер
Код Фейк-слака еще не хочется показывать, но после вынесения его в отдельное репо и приведения в порядок, думаю что можно будет опубликовать его код. Надеюсь он многим облегчит жизнь.
Всем кто дочитал до этого предложения — огромный респект и уважуха! В эту статью я вложил 99% пота )))
Список ссылок
- https://github.com/django/asgiref/ — библиотека оберток функций для возможности вызова синхронного кода в асинхронном и наоборот
- https://github.com/jpr5/ngrep — отличный инструмент, что помог мне подглядеть коммуникацию и последовательность запросов.
- https://github.com/slackapi/python-slackclient/ — библиотека для написания Slack бота (в мастере уже версия 2.0.1)
Ранее статья была опубликована тут.