---
# System prepended metadata

title: Інтеграція чат-бот API
tags: [External API, Bot Editor]

---

# Інтеграція чат-бот API

###### tags: `Bot Editor`, `External API`

__Суть завдання__

Потрібно реалізувати абстракцію, яка буде опрацьовувати вхідні запити з чату, звертатися до потрібного чат-бота і в ньому шукати потрібну відповідь. Формувати її в залежності від типу повідомлення та відправляти у чат користувачу.


__Основні типи відповідей__

- Повідомлення
- Зображення
- Чат-поле

Додаткові елементи повідомлення
- Кнопки-крок
- Кнопки-посилання

Кнопки можуть бути прикріплені до будь-якого типу відповіді


__Структура даних__

Bot (bot_id) є основною сутністю, від якої відштовхується логіка.

До бота може бути прив'язано кілька API месендлжерів одночасно (FB, Telegram...), всі вони мають працювати коректно з тими даними, які лежать в нас в базі, не залежно від своїх особливостей і обмежень.

## Алгоритм роботи
1. На веб-хук приходить реквест від месенджера
2. Система опрацьовує запит, визначає, якому месенджеру належить запит (який драйвер підключати)
3. Визначає, до якого бота відбувається звернення
4. Опрацьовує запит
5. Формує відповідь
6. Відправляє відповідь користувачу і записує її у базу даних, щоб власник бота (оператор) міг відслідкувати історію взаємодії
7. Робить розсилку про подію, якщо є підписники.


## Вимоги

__Підписка на події__

Підписка на події використовується для того, щоб платформа могла сповістити підписаних операторів про те, що хтось виконав цільову дію.

Список цільових дій
- Хтось написав повідомення в чат, а онлайн нікого немає - надсилати посилання на ChatRoom в телеграм (зарза реалізовано)
- Хтось зайшов на певний крок в чаті (зарза реалізовано)

Необхідні роботи:
- Врахувати це при реалізації нової логіки
- Додати в редактор поле "Підписані оператори" в налаштування кроку 
??? можливо варто винести в окреме завдання


__Taxonomy__

Дана технологія реалізована на даний момент і використовується для сигментації бази контактів.

Алгоритм роботи:
- `Крок 1` позначений категорією `taxonomy_1`
- Коли користувач переходить в цей крок, даному користувачу має присвоїтись категорія `taxonomy_1`

Необхідні роботи:
- Врахувати це при реалізації нової логіки
 

__Розсилки__

В кабінеті можна запланувати розсилки по наявних контактах.
Для FB можна вказати тег/тип повідомення (вимога самої платформи)
Реалізовано на даний момент. 

Необхідні роботи:
- Відрефакторити код після того, як буде інтегровано нову логіку
- Додати можливість вказати команду кроку, щоб розсилка відправила якийсь конкретний крок користувачам (по аналогії з ChatRoom > пп 2.)
- Актуалізувати теги/типи повідомлень FB відповідно до документації - https://developers.facebook.com/docs/messenger-platform/send-messages/#messaging_types


__ChatRoom__

Це вікно чату, через яке оператор може переписуватися з користувачем чат-бота.

На даний момент чат-рум взаємодіє з чат-ботом наступним чином:
1. Відправка текстових повідомлень оператора у чат-бот
2. Ініціація команд в чат-боті - оператор відправляє команду (наприклад `/start` ) і користувач отримує повідомлення, яке прив'язане до даної команди (крок)
3. Додавання користувача до категорій - оператор відправляє хеш тег в чат (наприклад `#taxonomy_1`) і даний користувач автоматично відноситься до даної категорії. Щоб відправити кілька категорії зразу, достатньо їх вказати з нового рядка:
```
#taxonomy_1
#taxonomy_2
#taxonomy_3
```

Необхідні роботи:
- Відрефакторити код після того, як буде інтегровано нову логіку


# Екскурс по коду і класах

## Те, що є зараз

__Поточна інтеграція апі__

На даний момент логіка реалізована за допомогою:

класу
`Common\ChatBot::class`, 

двох драйверів 
`Common\ChatBotServises\FaceBook::class`
`Common\ChatBotServises\Telegram::class` 

та двох контролерів 
`applications/FrontSide/API/Method/ChatBot.php`
`applications/FrontSide/API/Method/ChatBotFacebook.php`

Драйвер Телеграму реалізований трохи краще ніж FB. У фб не дотриманий інтерфейс, що викликало критичну помилку рекурсії при опрацюванні деяких запитів, вирішити її вдалося лише через костиль - рефакторити не було часу + там клубок ниток розмотувати...


__Кастомна логіка чат-бота__

В системі інтергований алгоритм для реалізації індивідуальної логіки для компанії через абстракцію `Common\Company\Bot\Response::class`. ЇЇ порібно повторити, але з прив'язкою до бота, а не до компанії.


__Моделі для роботи з даними чатбота__

Дані моделі використвуються для збереження даних з редактора

`Common\ChatBot\Bot::class`
`Common\ChatBot\Step::class`
`Common\ChatBot\Step\Node::class`


## Потрібно реалізувати

### 1. Контроллер

Потрібно реалізувати окремі контролери в файлі
`applications/API/Internal/Webhook/ChatBotController.php`

Роути лежать в файлі `configs/routing/front_side.yml`
- `telegram_webhook`
- `facebook_webhook`

URI Роутів мають лишитися такими як зараз, але їх потрібно зробити нормально (без спроб універсалізувати роути - 1 роут, 1 контролер)


### 2. Клас `Common\ChatBotService::class`

Це аналог класу `Common\ChatBot::class`

__Інтерфейс__

```
{
	// Білдить об'єкт з ініційоманим драйвером месенджера
	statuc build(ChatBotService::TELEGRAM, $bot_id);
	
	// Приймає на вхід дані, які можуть прийти від месенджера
	readRequest($request);
	
	// Відправляє відповідь в чат
	send(Pilot $responser);
	
	// Має вертати https посилання на чат в месенджері
	getBotUrl();
	
	// Відправляє в месенджер необхідні дані, які мають виводитися при початку роботи з ботом в месенджері
	saveStartMessage();
	
}

```

### 3. Клас `Common\Company\Bot\Pilot::class`

Це аналог класу `Common\Company\Bot\Response::class`.

Його завдання формувати відповідь для відправки в месенджер.

На вхід приймає об'єкт `Common\ChatRoom::class` - цей клас відповідає за роботу з чатом в середині нашої платформи.

`Pilot` є моделлю, яка має свою таблицю в базі. В цій таблиці зберігаються дані про те, в якому місці чат-бота зараз знаходиться користувач. Це потрібно наприклад для реалізації чат-форм, коли користувач має отримати повідомення, вказати якісь дані, а тоді піти далі по алгоритму.


__Інтерфейс__

```
{
	static factory(ChatRoom $chat_room);

	/**
	 * @param string|Command $message_to_user
	 */
	setAnswer($message_to_user);
	
	/**
	 * Формує відповідь на основі того, де зараз знаходиться користувач або того, що він відправив
	 * 
	 * @return string|Pilot\Response[]
	 */
	renderAnswer();
	
	#region Actions
	
	// Calls before save User message and send any response
	beforeSaveUserMessage();
	
	// Calls after save User message and send any response
	afterSaveUserMessage();
	
	// Calls before response will sends to User
	// e.g. $driver_id == ChatBotService::TELEGRAM
	beforeSend($driver_id);
	
	// Calls after response was sent to User
	// e.g. $driver_id == ChatBotService::TELEGRAM
	afterSend($driver_id);
	
	#endregion
}

```


### 4. Клас `Pilot\Response::class`

Це клас, який відповідає за формування одного повідомлення в чат
```
{
	extands Core\AbstractClass\Collection
	
	#region Getters
	
	// Повертає список кнопок, які прив'язані до повідомлення
	getButtons();
	
	// Повертає повідомлення, яке буде відправлене у месенджер
	getUserMessage();
	
	// Повертає повідомлення, яке буде відправлене оператору	
	getOperatorMessage();
	
	// Повертає тип повідомлення. Наприклад зображення, форма, текстове повідомлення тощо.
	getResponseType();
	
	#endregion
	
	#region Is Condition methods
	
	hasButtons();

	hasMessageForUser();
	
	hasMessageForOperator();
	
	#endregion

}
```

---

> !!! Пропозиції щодо зміни інтерфейсу, списку необхідних класів, оптимізації тощо - вітаються.