Рубрики
Без рубрики

Как создать своего первого Slack-бота с помощью Python

Узнайте, как создать простого Slack-бота на Python без предварительного опыта работы с ботами.

Автор оригинала: Matt Makai.

Боты – полезный способ взаимодействия с чат-сервисами, такими как Slack . Если вы никогда раньше не создавали бота, это сообщение представляет собой простое руководство по объединению Slack API с Python для создания вашего первого бота.

Мы рассмотрим настройку вашей среды разработки, получив Токен бота Slack API и кодирование нашего простого бота на Python.

Инструменты, которые нам нужны

Нашему боту, который мы назовем StarterBot, требуется Python и Slack API. Для запуска нашего кода Python нам потребуется:

  • Либо Python 2, либо 3
  • pip и
  • virtualenv для обработки Python
  • зависимости приложений
  • Бесплатная учетная запись Slack – вам необходимо войти в
  • хотя бы одно рабочее пространство, где у вас есть доступ к созданию приложений.

Также полезно иметь под рукой документацию по Slack API . пока вы создаете это руководство.

Весь код для этого руководства доступен с открытым исходным кодом по лицензии MIT. в общедоступном slack-starterbot репозиторий.

Создание нашей окружающей среды

Теперь мы знаем, какие инструменты нам нужны для нашего проекта, поэтому приступим к разработке. среда настроена. Перейдите в терминал (или командную строку в Windows) и перейдите в каталог, в котором вы хотите сохранить этот проект. В пределах этот каталог, создайте новый virtualenv, чтобы изолировать наше приложение зависимости от других проектов Python.

virtualenv starterbot

Активируйте virtualenv:

source starterbot/bin/activate

Теперь ваше приглашение должно выглядеть так, как на этом скриншоте.

Командная строка с активированным virtualenv стартер-бота.

Официальная вспомогательная библиотека API slackclient , созданная Slack, может отправлять и получать сообщения из канала Slack. Установите библиотеку slackclient с помощью команда pip :

pip install slackclient==1.3.2

Когда pip завершится, вы должны увидеть такой вывод, и вы будете обратно в подсказку.

Результат использования команды pip install slackclient с активированным virtualenv.

Нам также необходимо создать приложение Slack , чтобы получать токен API для вашего бота. Используйте «Starter Bot» в качестве имени вашего приложения. Если вы подписаны в более чем одну рабочую область, выберите из раскрывающегося списка рабочую область разработки.

Создать заполненную форму приложения Slack

После отправки формы оставьте страницу конфигурации приложения открытой.

API-интерфейсы Slack и конфигурация приложений

Мы хотим, чтобы наш стартовый бот выглядел как любой другой пользователь в вашей команде – он будет участвовать в беседах внутри каналов, групп и прямых переписок. В слабом Приложение, это называется пользователем-ботом , который мы настраиваем, выбрав «Пользователи-боты» в разделе «Функции». После нажав «Добавить пользователя-бота», вы должны выбрать отображаемое имя, выбрать имя пользователя по умолчанию и сохраните свой выбор, нажав «Добавить пользователя-бота». Ты будешь в итоге получится страница, которая выглядит следующим образом:

Добавлен пользователь-бот в приложение Slack

Библиотека slackclient упрощает использование Slack RTM API и веб-API . Мы будем использовать оба варианта для реализации Starter Bot, и каждый из них требует аутентификации. Удобно, что созданный нами ранее бот-пользователь может использоваться для аутентификации для оба API.

Нажмите «Установить приложение» в разделе «Настройки». Кнопка на этой странице установит приложение в нашу рабочую область разработки. После установки приложения он отображает токен доступа oauth пользователя-бота для аутентификации в качестве пользователя-бота.

После установки в рабочую область разработки вы можете скопировать токен доступа oauth пользователя бота

Обычной практикой для разработчиков Python является экспорт секретных токенов как переменные среды. Вернувшись в свой терминал, экспортируйте токен Slack с имя SLACK_BOT_TOKEN :

export SLACK_BOT_TOKEN='your bot user access token here'

Хорошо, теперь мы уполномочены использовать Slack RTM и веб-API в качестве пользователя-бота.

Кодирование нашего стартового бота

У нас есть все необходимое для написания кода Starter Bot. Создать новый файл с именем starterbot.py и включите в него следующий код.

import os
import time
import re
from slackclient import SlackClient

С нашими импортированными зависимостями мы можем использовать их для получения среды значения переменных, а затем создайте экземпляр клиента Slack.

# instantiate Slack client
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
# starterbot's user ID in Slack: value is assigned after the bot starts up
starterbot_id = None

# constants
RTM_READ_DELAY = 1 # 1 second delay between reading from RTM
EXAMPLE_COMMAND = "do"
MENTION_REGEX = "^<@(|[WU].+?)>(.*)"

Код создает экземпляр клиента SlackClient с нашим SLACK_BOT_TOKEN экспортируется как переменная среды. Он также объявляет переменную, которую мы можем использовать для сохранить идентификатор пользователя Slack нашего стартового бота. Также объявлено несколько констант, и каждый из них будет объяснен, поскольку они используются в следующем коде.

if __name__ == "__main__":
    if slack_client.rtm_connect(with_team_state=False):
        print("Starter Bot connected and running!")
        # Read bot's user ID by calling Web API method `auth.test`
        starterbot_id = slack_client.api_call("auth.test")["user_id"]
        while True:
            command, channel = parse_bot_commands(slack_client.rtm_read())
            if command:
                handle_command(command, channel)
            time.sleep(RTM_READ_DELAY)
    else:
        print("Connection failed. Exception traceback printed above.")

Клиент Slack подключается к Slack RTM API. После подключения он вызывает Метод веб-API ( auth.test ) для поиска ID пользователя Starter Bot.

У каждого пользователя-бота есть идентификатор пользователя для каждой рабочей области, в которой установлено приложение Slack. в пределах. Сохранение этого идентификатора пользователя поможет программе понять, есть ли у кого-то упомянул бота в сообщении.

Затем программа входит в бесконечный цикл, где каждый раз, когда цикл запускает клиент получает любые события, которые поступают от Slack RTM API. Заметить, что перед завершением цикла программа останавливается на одну секунду, чтобы не зацикливаться слишком быстро и тратите время процессора.

Для каждого прочитанного события функция parse_bot_commands () определяет, событие содержит команду для Starter Bot. Если это так, то command будет содержат значение, а функция handle_command () определяет, что делать с командой.

Мы заложили основу для обработки событий Slack и вызова методов Slack. в программе. Затем добавьте три новые функции над предыдущим фрагментом в полные команды обработки:

def parse_bot_commands(slack_events):
    """
        Parses a list of events coming from the Slack RTM API to find bot commands.
        If a bot command is found, this function returns a tuple of command and channel.
        If its not found, then this function returns None, None.
    """
    for event in slack_events:
        if event["type"] == "message" and not "subtype" in event:
            user_id, message = parse_direct_mention(event["text"])
            if user_id == starterbot_id:
                return message, event["channel"]
    return None, None

def parse_direct_mention(message_text):
    """
        Finds a direct mention (a mention that is at the beginning) in message text
        and returns the user ID which was mentioned. If there is no direct mention, returns None
    """
    matches = re.search(MENTION_REGEX, message_text)
    # the first group contains the username, the second group contains the remaining message
    return (matches.group(1), matches.group(2).strip()) if matches else (None, None)

def handle_command(command, channel):
    """
        Executes bot command if the command is known
    """
    # Default response is help text for the user
    default_response = "Not sure what you mean. Try *{}*.".format(EXAMPLE_COMMAND)

    # Finds and executes the given command, filling in response
    response = None
    # This is where you start to implement more commands!
    if command.startswith(EXAMPLE_COMMAND):
        response = "Sure...write some more code then I can do that!"

    # Sends the response back to the channel
    slack_client.api_call(
        "chat.postMessage",
        channel=channel,
        text=response or default_response
    )

Функция parse_bot_commands () принимает события из Slack и определяет если это команды, адресованные Starter Bot. Много типы событий , с которыми может столкнуться наш бот, но найти команды, которые мы только хотим рассмотреть события сообщений . События сообщений также имеют подтипы, но для команд, которые мы хотим найти, не будет определенного подтипа. В функция отфильтровывает неинтересные события, проверяя эти свойства. Теперь мы знайте, что событие представляет собой сообщение с некоторым текстом, но мы хотим узнать если Starter Bot упоминается в тексте. parse_direct_mention () функция определит, что текст сообщения начинается с упоминания, а затем мы сравниваем это с идентификатором пользователя, который мы сохранили ранее для Starter Bot. Если они то же самое, тогда мы знаем, что это команда бота, и возвращаем текст команды с идентификатор канала.

Функция parse_direct_mentions () использует регулярное выражение для определения если пользователь упоминается в начале сообщения. Он возвращается идентификатор пользователя и оставшееся сообщение (и None, None , если не было упоминания найденный).

Последняя функция, handle_command () – это то место, куда в будущем вы добавите все интересные команды, юмор и индивидуальность для Starter Bot. На данный момент у него есть всего один пример команды: do . Если команда начинается с известной команды, она будет соответствующий ответ. Если нет, используется ответ по умолчанию. В ответ отправляется обратно в Slack путем вызова chat.postMessage Веб-API метод с каналом.

Вот как должна выглядеть вся программа в собранном виде (вы также можете просмотрите файл в GitHub ):

import os
import time
import re
from slackclient import SlackClient


# instantiate Slack client
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
# starterbot's user ID in Slack: value is assigned after the bot starts up
starterbot_id = None

# constants
RTM_READ_DELAY = 1 # 1 second delay between reading from RTM
EXAMPLE_COMMAND = "do"
MENTION_REGEX = "^<@(|[WU].+?)>(.*)"

def parse_bot_commands(slack_events):
    """
        Parses a list of events coming from the Slack RTM API to find bot commands.
        If a bot command is found, this function returns a tuple of command and channel.
        If its not found, then this function returns None, None.
    """
    for event in slack_events:
        if event["type"] == "message" and not "subtype" in event:
            user_id, message = parse_direct_mention(event["text"])
            if user_id == starterbot_id:
                return message, event["channel"]
    return None, None

def parse_direct_mention(message_text):
    """
        Finds a direct mention (a mention that is at the beginning) in message text
        and returns the user ID which was mentioned. If there is no direct mention, returns None
    """
    matches = re.search(MENTION_REGEX, message_text)
    # the first group contains the username, the second group contains the remaining message
    return (matches.group(1), matches.group(2).strip()) if matches else (None, None)

def handle_command(command, channel):
    """
        Executes bot command if the command is known
    """
    # Default response is help text for the user
    default_response = "Not sure what you mean. Try *{}*.".format(EXAMPLE_COMMAND)

    # Finds and executes the given command, filling in response
    response = None
    # This is where you start to implement more commands!
    if command.startswith(EXAMPLE_COMMAND):
        response = "Sure...write some more code then I can do that!"

    # Sends the response back to the channel
    slack_client.api_call(
        "chat.postMessage",
        channel=channel,
        text=response or default_response
    )

if __name__ == "__main__":
    if slack_client.rtm_connect(with_team_state=False):
        print("Starter Bot connected and running!")
        # Read bot's user ID by calling Web API method `auth.test`
        starterbot_id = slack_client.api_call("auth.test")["user_id"]
        while True:
            command, channel = parse_bot_commands(slack_client.rtm_read())
            if command:
                handle_command(command, channel)
            time.sleep(RTM_READ_DELAY)
    else:
        print("Connection failed. Exception traceback printed above.")

Теперь, когда весь наш код готов, мы можем запустить нашего стартового бота на командную строку с помощью команды python starterbot.py .

Вывод в консоль, когда StarterBot работает и подключен к API.

В Slack создайте новый канал и пригласите Starter Bot или пригласите его на существующий канал.

В пользовательском интерфейсе Slack создайте новый канал и пригласите StarterBot.

Теперь начните давать команды Starter Bot на своем канале.

Дайте команды StarterBot в вашем канале Slack.

Дополнительное примечание . В настоящее время существует проблема с пакет websocket и сертификат CA, который он использует, поэтому, если вы столкнетесь с такой ошибкой, как:

...
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)
...
slackclient.server.SlackConnectionError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)
Connection failed. Exception traceback printed above.

Вот что можно сделать: 1. Понижение версии библиотеки websocket-client до 0.47.0 2. Или загрузите сертификат ( wget https://www.tbs-certificats.com/issuerdata/DigiCertGlobalRootCA.crt ), затем установите переменную среды export WEBSOCKET_CLIENT_CA_BUNDLE = DigiCertGlobalRootCA.crt

Заключение

Хорошо, теперь у вас есть простой стартовый бот с кучей мест в код, вы можете добавить любые функции, которые хотите создать.

С помощью Slack RTM API и Python можно сделать гораздо больше. Прочтите эти сообщения, чтобы узнать, что вы могли бы сделать:

Вопросов? Свяжитесь со мной через Twitter @fullstackpython или @mattmakai . Я также на GitHub с имя пользователя mattmakai .

Что-то не так в этом посте? Вилка исходный код этой страницы на GitHub и отправьте запрос на перенос.