Бот для Алисы и Телеграма одновременно: одна кодовая база на umbot

Как поддерживать навык Алисы, smartapp сбер салют и чат-бота Telegram одним приложением на TypeScript: мультиплатформенный фреймворк umbot, пример кода и запуск за 10 минут.

Бот для Алисы и Телеграма одновременно: одна кодовая база на umbot

26 Сентября, 2026 Автор: Максим М

Бот для Алисы и Телеграма одновременно: одна кодовая база на umbot

Разбираемся, как поддерживать навык Алисы, smartApp сбер Салют и бота в Telegram одним приложением на TypeScript.

Ситуация, знакомая каждому, кто делал навык для Алисы на заказ: проект сдан, работает, и через месяц приходит просьба «сделайте такого же бота в Телеграме». Если логика написана вплотную к протоколу одной платформы — это не копипаста, а второй проект. Следом появляется «а ещё в smartApp сбер Салют» — и одна и та же логика правится уже в третьем месте. В статье разберём, почему так происходит, чем отличаются платформы на уровне протокола и как вынести эти различия из кода, чтобы бот для Алисы и Телеграма жил в одной кодовой базе.

Почему «просто скопировать» не работает

Даже при одинаковой бизнес-логике платформы требуют разного. Коротко — в таблице:

Алиса / smartApp сбер Салют Telegram
Как уходит ответ JSON в теле ответа на вебхук Отдельный запрос к Bot API (sendMessage и т.п.)
Лимит текста 1024 символа 4096 символов
Кнопки Массив с title и payload Вложенные массивы клавиатуры, callback_data до 64 байт
Состояние пользователя Есть хранилище платформы, приходит в каждом запросе Нет — нужна своя сессия или БД
Проверка подлинности вебхука Подписи нет Секретный заголовок
Время на ответ Несколько секунд, потом ошибка на стороне платформы Жёсткого лимита на ответ пользователю нет
Устройство без экрана Есть (колонка): кнопки и картинки не видны Нет

Если поддерживать два-три таких проекта параллельно, каждая новая функция делается два-три раза, тестируется два-три раза — и всё равно версии постепенно расходятся: в одной навык уже умеет галереи, в другой — нет; в Алисе исправили текст fallback-ответа, в Telegram забыли.

Типичные ошибки при ручном дублировании

  • Рассинхрон сценариев. Новую ветку диалога добавили в одну платформу и забыли в другую — пользователи разных каналов получают разный продукт.
  • Разные тексты ошибок и «не поняла». Мелочь, которую замечают первой: бот отвечает по-разному на одну и ту же фразу.
  • Кнопки, которые работают только в одной платформе. Длинный payload, который Алиса принимает, не влезает в 64 байта callback_data Telegram — кнопка молча перестаёт работать.
  • Двойные тесты — или ни одних. Обычно тестируется «основная» платформа, а вторая узнаёт о багах от пользователей.

Единая логика + адаптеры: что это значит на практике

Мультиплатформенный фреймворк umbot переворачивает расклад: вы пишете бизнес-логику один раз на TypeScript, а перевод ответа в формат конкретной платформы берут на себя адаптеры. Фреймворк сам определяет платформу по входящему запросу, наполняет контроллер данными пользователя и после выполнения вашей логики собирает ответ — JSON для Алисы и smartApp сбер Салют, API-вызовы для Telegram, VK, MAX и Viber. Поддерживаются семь платформ: Яндекс.Алиса, smartApp сбер Салют, Сбер SmartApp, Telegram, VK, MAX и Viber.

Пример: один навык — Алиса, smartApp сбер Салют и Telegram

Минимальное приложение по мотивам документации быстрого старта:

import { Bot, WELCOME_INTENT_NAME, FALLBACK_COMMAND } from 'umbot';
import { fullPlatforms } from 'umbot/plugins';

const bot = new Bot()
    .use(fullPlatforms) // все платформы одним вызовом
    .setAppConfig({ isLocalStorage: true });

bot.addCommand(WELCOME_INTENT_NAME, ['привет', '/start'], (_, bc) => { // /start — Telegram
    bc.text = 'Привет! Я работаю и в Алисе, и в Телеграме.';
    bc.buttons.addBtn('Помощь');
});

bot.addCommand(FALLBACK_COMMAND, [], (userCommand, bc) => {
    // пустая команда — пользователь только что запустил навык
    bc.text = userCommand ? `Вы сказали: ${userCommand}` : 'Привет! Скажите «помощь».';
});

bot.start('localhost', 3000);

Вся «мультиплатформенность» — в строке .use(fullPlatforms). Тот же вызов bc.buttons.addBtn('Помощь') для Алисы станет её нативной кнопкой, для Telegram — кнопкой клавиатуры, для MAX — элементом клавиатуры с его лимитами. Хотите начать с одной платформы — подключите одиночный адаптер, например bot.use(new AlisaAdapter()), и добавьте остальные позже: меняется строка подключения, логика остаётся той же.

Навык для Алисы и smartApp сбер Салют: только голосовые платформы

Частый сценарий — навык нужен сразу в Алисе и smartApp сбер Салют, а мессенджеры не нужны. Протоколы двух голосовых ассистентов похожи, но не идентичны, и поддерживать два отдельных навыка всё равно неудобно. Для этого случая есть набор voicePlatforms — Алиса, smartApp сбер Салют и Сбер SmartApp:

import { Bot } from 'umbot';
import { voicePlatforms } from 'umbot/plugins';

const bot = new Bot().use(voicePlatforms);

Один сервер, один вебхук-адрес для обеих платформ: фреймворк различает их по формату запроса. Для обратного случая — только чат-боты без голосовых платформ — есть botPlatforms.

Когда платформам всё же нужна разная логика

Бывает, что различие не техническое, а продуктовое: например, в голосовом навыке длинный адрес сайта лучше не зачитывать, а в мессенджере его удобно дать ссылкой. Для таких мест не нужно дробить проект — достаточно проверки платформы в обработчике через поле bc.appType:

bot.addCommand('contacts', ['контакты', 'как связаться'], (_, bc) => {
    if (bc.appType === 'alisa' || bc.appType === 'marusia') {
        bc.text = 'Позвоните нам: 8 800 000-00-00.';
        return;
    }
    bc.text = 'Пишите в поддержку: https://example.ru/support или звоните 8 800 000-00-00.';
});

Лимиты при этом писать руками не нужно: добавили 15 кнопок — Алисе уйдёт столько, сколько она принимает, Telegram получит все; слишком длинный текст обрежется до лимита платформы. Поэтому развилки по платформе в реальном проекте — редкие точечные места, а не параллельный код.

Дублирование кода против адаптеров: итог

Отдельный проект под каждую платформу Одна логика + адаптеры
Точек входа По одной на платформу Одна
Новая функция Правка в каждом проекте Одна правка
Состояние пользователя Свой механизм под каждую платформу Единый userData
Тесты Набор на каждую платформу Один набор
Новая платформа Новый проект Строка подключения адаптера

Цена абстракции небольшая: обработка запроса внутри фреймворка — менее 30 мс даже при 1000 зарегистрированных командах (замеры — в документации по производительности), так что почти весь бюджет времени голосовых платформ остаётся бизнес-логике.

Что фреймворк берёт на себя

  • Кнопки и карточки в едином API: buttons.addBtn(), галереи и BigImage — адаптеры сами переводят их в форматы платформ и обрезают по лимитам.
  • Состояние пользователя: встроенное userData с хранением в хранилище платформы (где оно есть) или в БД — файловой, MongoDB или своей.
  • Кэширование медиа: изображения и звуки загружаются на платформу один раз, идентификаторы сохраняются — повторные ответы не тратят время на загрузку.
  • Безопасность: проверка регулярных выражений на ReDoS, проверка подписи вебхука для платформ, где она есть.
  • Отладка без публикации: класс BotTest запускает диалог с ботом прямо в консоли, а метод simulate() позволяет прогнать одну и ту же фразу через разные платформы в автотестах.

Как запустить

Готовый проект генерируется одной командой CLI:

npx umbot create my-bot
cd my-bot
npm install
npm run build
npm start

Шаблон содержит структуру проекта, конфигурацию и .gitignore, в который заранее внесён .env под токены (сам файл создаётся командой npx umbot add env). Дальше: зарегистрируйте навык в Яндекс.Диалогах, бота — у @BotFather, пропишите токены и вебхуки. Подробно каждый шаг описан в getting-started, а сценарий удобно сначала проверить в консоли — см. статью про тестирование навыка без публикации.

Частые вопросы

Можно ли сделать бота для Алисы и Телеграма одновременно без фреймворка? Да: вынесите бизнес-логику в отдельный слой и напишите по тонкому адаптеру на каждую платформу. Фактически это и есть собственный фреймворк — вопрос в том, хотите ли вы его поддерживать.

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

Что, если у меня уже есть навык Алисы на другом стеке? Бизнес-логика обычно переносится командами addCommand почти один к одному; переписывать приходится только работу с форматом запроса и ответа — ту часть, которую и заменяют адаптеры.

Куда дальше

Рекомендую к прочтению следующие статьи:

Навык Алисы на TypeScript: создание с нуля на Node.js и umbot

Навык Алисы на TypeScript: создание с нуля на Node.js и umbot

Пошаговая разработка навыка для Яндекс.Алисы на TypeScript и Node.js: команды, шаги диалога, формы, кнопки, TTS, отладка в консоли и частые ошибки новичка.

Читать статью

Telegraf или grammY — что выбрать для Telegram-бота в 2026?

Telegraf или grammY — что выбрать для Telegram-бота в 2026?

Честное сравнение Telegraf и grammY с примерами кода и таблицей: типы, плагины, вебхуки — и когда вместо библиотеки нужен мультиплатформенный фреймворк.

Читать статью

Сколько стоит разработка навыка для Алисы в 2026 году

Сколько стоит разработка навыка для Алисы в 2026 году

Сколько стоит навык для Алисы: цены от 5 000 ₽, что влияет на стоимость, три уровня сложности, доли бюджета по этапам и как сэкономить без потери качества.

Читать статью

Конструктор навыков Алисы или разработка на фреймворке: что выбрать

Конструктор навыков Алисы или разработка на фреймворке: что выбрать

Когда хватит конструктора навыков для Алисы без программирования, а когда нужны фреймворк и разработчик: потолок конструкторов, логика и владение продуктом.

Читать статью

Навык для Алисы без своего сервера: serverless на Yandex Cloud

Навык для Алисы без своего сервера: serverless на Yandex Cloud

Как запустить навык Алисы в Yandex Cloud Functions без своего сервера: генерация serverless-проекта через CLI umbot, деплой, публичный вызов и лимиты.

Читать статью

Комментарии

Оставить комментарий

Как со мной связаться?

Свяжитесь со мной по любому поводу!
Я с радостью отвечу на все вопросы!

Телефон:

+7(909) 281 35-20

Дополнительная почта:

info@maxim-m.ru

Я в социальных сетях:

ВверхВверх 👆