Реализация мультиканального бота (Telegram + WhatsApp + Viber) в мобильном приложении
Интегрировать бота в одном мессенджере несложно. Сложность начинается, когда нужно покрыть Telegram, WhatsApp и Viber одновременно — и при этом не превратить кодовую базу в три независимых кипы логики. Главная архитектурная задача: единый слой бизнес-логики, а специфику каждой платформы изолировать за интерфейсом адаптера.
Почему три бота — это не три раза больше работы, а три раза больше ошибок
Каждая платформа живёт по своим правилам. Telegram Bot API отдаёт вебхук синхронно и ожидает ответ 200 OK в течение 5 секунд — если бэкенд задумался, платформа начнёт повторять запросы, и бот получит дубли. WhatsApp Business API (Meta Cloud API) работает иначе: вебхук для верификации приходит GET-запросом с hub.challenge, и если не ответить правильным значением, вебхук просто не зарегистрируется — тихая ошибка, которую легко пропустить.
Viber отличается форматом rich media: тип rich_media с кнопками работает только при отправке через send_message, а не через reply API. Разработчики, переносящие логику с Telegram (где inline keyboard вешается прямо на любое сообщение), натыкаются на это в первый же день.
Отдельная история — формат вложений. Telegram принимает multipart/form-data при отправке файла напрямую, WhatsApp требует сначала загрузить медиа через POST /v1/media и получить media_id, и только потом слать его в сообщении. Viber ограничивает размер файла 200 МБ и поддерживает строго определённые MIME-типы.
Если вся эта логика размазана по одному сервису без чёткой абстракции, сопровождать это через полгода невозможно.
Архитектура: один канал обмена, три адаптера
Правильный подход — ввести интерфейс BotAdapter с методами sendMessage, sendFile, parseIncoming. Каждая платформа — своя реализация.
// Android (Kotlin) — пример адаптерного слоя
interface BotAdapter {
suspend fun sendMessage(chatId: String, text: String, buttons: List<BotButton>? = null)
suspend fun sendFile(chatId: String, fileUrl: String, mimeType: String)
fun parseIncoming(payload: String): BotMessage
}
class TelegramAdapter(private val token: String) : BotAdapter {
private val client = OkHttpClient()
override suspend fun sendMessage(chatId: String, text: String, buttons: List<BotButton>?) {
val body = buildTelegramPayload(chatId, text, buttons)
client.newCall(Request.Builder()
.url("https://api.telegram.org/bot$token/sendMessage")
.post(body).build()).execute()
}
// ...
}
На iOS паттерн тот же — протокол BotAdapter и три struct-реализации через URLSession. В Flutter удобно использовать абстрактный класс с dio под капотом.
Бизнес-логика (распознавание команд, FSM диалога, работа с базой) живёт выше — она не знает, откуда пришло сообщение.
Управление состоянием диалога
Для любого нетривиального бота нужен конечный автомат состояний. Хранить userState в памяти — антипаттерн: при рестарте сервиса все диалоги сбрасываются. На практике используем Redis с TTL (например, 30 минут неактивности сбрасывают сессию) или таблицу в PostgreSQL с updated_at.
Ключ состояния — {platform}:{chatId}, это позволяет одному пользователю иметь независимые диалоги в разных мессенджерах, что иногда нужно по бизнес-логике.
Специфика мобильного приложения
Если бот встраивается не в серверный сервис, а непосредственно в мобильное приложение — нужна WebSocket-подписка или polling. Для Telegram в мобильном контексте это getUpdates с long polling через BackgroundFetch (iOS) или WorkManager (Android). Держать постоянный WebSocket для бота в фоне iOS не даст — система убьёт процесс. Правильный паттерн: push-уведомление от сервера будит приложение, оно делает один getUpdates, обрабатывает очередь и засыпает.
WhatsApp Cloud API в мобильном приложении потребует серверного прокси — напрямую из мобильного клиента обращаться к Meta API нельзя (нужен верифицированный бизнес-аккаунт на стороне сервера). Это часто удивляет команды, которые хотят «лёгкую» интеграцию.
Процесс работы
Сначала — аудит сценариев: какие команды, нужны ли кнопки/карусели, есть ли файловый обмен, нужна ли оплата (Telegram Payments vs WhatsApp Pay). Это определяет сложность адаптеров.
Далее: проектирование FSM, реализация адаптеров по очереди (Telegram первым — самый зрелый API), интеграция с основной логикой, нагрузочное тестирование вебхуков.
Отдельный этап — мониторинг: логирование входящих payload с маскировкой персональных данных, алерты на delivery_failed в Viber и неудачные верификации вебхуков.
Ориентиры по срокам
Бот в одном мессенджере с базовыми командами — 3–5 дней. Мультиканальная реализация с FSM, файлами, кнопками и серверной частью — 2–4 недели. Если нужна интеграция с CRM или платёжными системами — отдельная оценка после анализа требований.







