Создание бота для Viber
Боты для социальных сетей и мессенджеров в последние годы все больше и больше набирают популярность. Мобильные приложения для большинства популярных социальных сетей есть почти у каждого в смарфоне, что облегчает использование ботов.
Существует два типа ботов:
- сложные, которые могут самообучаться, вести диалог, как человек;
- специализированные боты для выполнения конкретных задач. Например, узнать где в данный момент находится ваша посылка, посмотреть актуальные скидки в магазине, узнать историю автомобиля по vin-номеру и многие другие. Кроме того, бот может сам автоматически оповещать о статусе вашей посылке, о появлении новых акций в магазине и о многом другом. И поэтому, многие компании разработали своих ботов, с помощью которых они могут оказывать услуги более удобным и быстрым способом.
Рассмотрим создание бота для получения списка вакансий нашей компании. Для работы с ботом будем использовать кнопки ответов, чтобы упростить взаимодействие с ботом.
Работу начнем с изучения официальной документации Viber, она находится тут:
https://developers.viber.com/docs/.
В компании Viber позаботились о разработчиках, которые захотят создать новых viber-ботов, и создали для популярных языков программирования уже готовые библиотеки, в которые инкапсулированы сложные операции по работе с сервисом Viber, что значительно упрощает разработку ботов.
В данный момент имеются библиотеки для Python и Node.JS.
Для разработки будем использовать язык программирования Python3.
Процесс создания бота разделим на несколько шагов:
- Создание бота в сервисе Viber.
- Создание каркаса бота на Python.
- Настройка бота под конкретные сообщения.
- Использование ngrok для локальной разработки.
- Пример работы.
Создание бота в сервисе Viber
Для это требуется перейти по ссылке: https://partners.viber.com/account/create-bot-account и заполнить все необходимые поля формы. После успешного заполнения данных, будет создан бот и автоматически сгенерируется токен (обязательно сохраните его - он будет использоваться для аутентификации).
Создание каркаса бота на Python
Установим библиотеку для бота от viber:
pip install viberbot
Версия python для этой библиотеки должна быть выше 2.7.
В качестве фреймворка для python возьмем легковесный Flask:
pip install Flask
Создадим и сконфигурируем нашего бота:
viber = Api(BotConfiguration(
name='Smyt Career\'s Bot',
avatar='',
auth_token='your auth token'
))
Создадим каркас для обработки сообщений пользователя:
if not viber.verify_signature(request.get_data(), request.headers.get('X-Viber-Content-Signature')):
return Response(status=403)
# this library supplies a simple way to receive a request object
viber_request = viber.parse_request(request.get_data())
if isinstance(viber_request, ViberMessageRequest):
message = viber_request.message
viber.send_messages(viber_request.sender.id, [
message
])
elif isinstance(viber_request, ViberSubscribedRequest):
viber.send_messages(viber_request.user.id, [
TextMessage(text="thanks for subscribing!")
])
elif isinstance(viber_request, ViberFailedRequest):
logger.warn("client failed receiving message. failure: {0}".format(viber_request))
return Response(status=200)
Для каждого сообщения пользователя выполняется проверка на подлинность с помощью токена. Также определяется тип сообщения пользователя:
- простое сообщение пользователя;
- запрос на подписку;
- ошибка в запросе.
В зависимости от типа сообщения система реагирует.
В нашем примере пользователю, в ответ на его сообщение, отправляется то же самое сообщение.
Создание http-сервера
Для работы бота ваш http-сервер обязательно должен быть защищен ssl-шифрованием.
Так выглядит запуск сервиса у меня:
from flask import Flask, request, Response
app = Flask(__name__)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8443, debug=True)
Обращаю внимание, что это только ознакомительный пример и бота я запускал на локальном компьютере, поэтому не заполнил данные для ssl. Имеется возможность указать ssl-сертификат через параметр ssl_context.
Установим веб-хуку
После того, как сервер запущен, нужно указать сервису Viber куда ему нужно посылать сообщения пользователей для бота. Можно сделать разными способами.
Первый - через python:
viber.set_webhook('https://mybot.com/')
Второй - отправить запрос на установку веб-хука вручную; например, используя программу Postman.
Установим заголовки:
где X-Viber-Auth-Token – токен, полученный ранее.
Текст сообщения:
В переменной event_types мы можем указать на какие типы событий наш бот будет реагировать.
После этого бот уже будет рабочим и вы сможете отправлять сообщения через приложение viber, а он будет вам отвечать.
Настройка бота под конкретные сообщения
Сначала немного теории. Как я уже писал выше, я не считаю нужным нагружать пользователей набором сообщений для работы с ботом, поэтому было решено использовать keyboard. По сути - это hotkeys для определенных сообщений, выполненных в виде кнопок. Пример, как это выглядит, можно найти чуть ниже.
Например, у нас должна быть кнопка поиска вакансий, для этого добавим следующий код:
{
"DefaultHeight": True,
"BgColor": "#FFFFFF",
"Type": "keyboard",
"Buttons": [
{
"Columns": 6,
"Rows": 1,
"BgColor": "#e6f5ff",
"BgLoop": True,
"ActionType": "reply",
"ActionBody": "search_vacancies",
"ReplyType": "message",
"Text": "Поиск вакансий"
}
]
}
Если нужно добавить несколько кнопок, то их нужно перечислить в списке Buttons.
Область для кнопок имеет сетку в 6 колонок. В параметрах кнопки указаны следующие характеристики:
- она будет занимать 6 колонок и 1 строку;
- иметь определенный цвет фона;
- какой вид действия используется при нажатии;
- задано сообщение, которое будет посылаться на сервер при нажатии;
- задан тип сообщения;
- указан заголовок кнопки.
Так как в ActionBody указывается сообщение, которое будет отправлено на сервер при нажатии пользователем соответствующей кнопки, я решил использовать ActionBody для определения типа ответа от пользователя и самого ответа. Для этого использовал такую структуру:
ActionBody: action_type|value или просто action_type.
Рабочие примеры:
ActionBody: select_country|Russia
ActionBody: search_vacancies
ActionBody: select_level|’’
Также хочу отметить, что нам необходимо запоминать ответы, которые дает пользователь. Это можно сделать несколькими способами. Я решил эти данные сохранять в параметр сообщения tracking_data.
Это поле может содержать только строковые значения, поэтому сохраним данные в json, а передавать их пользователю будем через параметр tracking_data в виде строки, путем преобразования json.dumps() и обратно через json.loads().
Вот пример работы с сообщениями пользователя:
keyboard = {
"DefaultHeight": True,
"BgColor": "#FFFFFF",
"Type": "keyboard",
"Buttons": [
{
"Columns": 6,
"Rows": 1,
"BgColor": "#e6f5ff",
"BgLoop": True,
"ActionType": "reply",
"ActionBody": "search_vacancies",
"ReplyType": "message",
"Text": "Поиск вакансий"
}
]
}
is_finished = False
buttons = {}
if text_type == 'search_vacancies':
tracking_data = {}
countries = [country[1] for country in COUNTRIES]
text_message = 'Доступны вакансии в следующих странах: {countries}. Пожалуйста, выберите одну из них.'\
.format(countries=', '.join(countries))
buttons = get_buttons('select_country', COUNTRIES)
elif text_type == 'select_country':
tracking_data['country'] = text[1]
items = [item[1] for item in PROFILES]
text_message = 'Доступны вакансии по следующим профилям: {profiles}. Пожалуйста, выберите один из них.'\
.format(profiles=', '.join(items))
buttons = get_buttons('select_profile', PROFILES)
elif text_type == 'select_profile':
tracking_data['profile'] = text[1]
items = [item[1] for item in LEVELS]
text_message = 'Укажите пожалуйста какой у вас опыт в этой области: {items}. Пожалуйста, выберите один из них.'\
.format(
items=', '.join(items))
buttons = get_buttons('select_level', LEVELS)
elif text_type == 'select_level':
is_finished = True
tracking_data['level'] = text[1]
else:
text_message = "Выберите опцию"
messages = []
if is_finished:
response = requests.get(VACANCIES_URL, params=tracking_data)
json_response = response.json()
items = json_response.get('results', [])
for item in items:
messages.append(URLMessage(media=item.get('url'),
keyboard=keyboard,
tracking_data={}))
if not messages:
messages.append(TextMessage(text='Извините, по выбранным критериям, вакансий не найдено.',
keyboard=keyboard,
tracking_data={}))
else:
keyboard_buttons = keyboard.get('Buttons', [])
keyboard_buttons.extend(buttons)
keyboard['Buttons'] = keyboard_buttons
keyboard = keyboard if keyboard.get('Buttons') else None
tracking_data = json.dumps(tracking_data)
messages.append(TextMessage(text=text_message,
keyboard=keyboard,
tracking_data=tracking_data))
viber.send_messages(viber_request.sender.id, messages)
В вышеприведенном фрагменте кода происходит следующее: определяется тип отправленного сообщения пользователем, к примеру 'search_vacancies' - значит запустить процедуру выбора параметров для поиска вакансий; следующим шагом нужно показать выбор страны в виде кнопок и таким же способом далее выбирается профиль и опыт, как только все параметры выбраны, то посылается запрос на сервер и результаты с вакансиями отображаются ботом.
Также, хочется отметить, что Бот может отправлять следующие сообщения:
- Обычное текстовое – TextMessage(text=’some text’).
- Сообщение-ссылка – URLMessage(media=’http://mysite.com’).
- Контактное сообщение – ContactMessage(contact=contact), где contact объект вида Contact c параметрами name, phone_number, avatar.
- Сообщение-картинка – PictureMessage(media=’http://picture.url.com’).
- Видео сообщение – VideoMessage(media=’http://video.url.com’, size=1234).
- Сообщение о местоположении – LocationMessage(location=location), где location – объект вида Location с указанием координат широты и долготы.
- Стикер – StickerMessage(sticker_id=123), где sticker_id это ид конкретного стикера.
- Файл – FileMessage(media=’http://path/to/file’, size=123, file_name=’file name’).
- Сложное медиа-сообщение – RichMediaMessage(rich_media=json_object), более подробно можно посмотреть в документации, можно вывести несколько объектов вида: картинку с текстом и ссылкой, таким образом организовать некую «карусель» объектов.
- Hotkeys для пользователя – KeyboardMessage – это такие кнопки которые мы делали для ответа пользователям.
Использование ngrok для локальной разработки
Как я отмечал выше, чтобы ваш сервис работал с Viber, он должен быть запущен через ssl (самоподписанные сертификаты работать не будут, нужен хотя бы let’s encrypt).
У меня не было задачи размещать сервис с ботом на каком-либо сервере, я ограничился только локальной разработкой, но мне нужно было, чтобы мой сервис был доступен извне, для этого я взял замечательную утилиту ngrok.
Установка ее очень простая: достаточно посетить сайт https://ngrok.com/.
С помощью нее вы можете пробросить свой локальный порт наружу даже с защищенным туннелем. Мой сервис локально был развернут на 8443 порту, поэтому я запустил ngrok cо следующими параметрами:
./ngrok http 8443
После это получаем такую информацию:
Тут видно что по адресу https://4c4b93d5.ngrok.io доступен мой сервис с ботом.
Этот адрес сервера нужно отправлять при установке хука инициализации бота.
Пример работы
После нажатия кнопки (Поиск вакансий):
После выбора страны (Россия):
После выбора профиля деятельности (Разработка):
После указания опыта работы(Неважно) получаем такие результаты:
По нашему запросу нашлась одна вакансия.
К сожалению, мы самостоятельно не можем добавить нашего бота в общий список всех доступных ботов и даже не можем дать на него прямую ссылку, а все потому, что у компании Viber строгие требования к чат-ботам и нужно обращаться в компанию Viber с просьбой о подтверждении (судя по статьям в интернете, такое подтверждение удается получить только крупным компаниям).
Полный код бота доступен по адресу: