umbot
    Preparing search index...

    Class BotController<TUserData, TPlatformState>Abstract

    Контроллер приложения – главный класс для реализации единой бизнес-логики вашего приложения. Именно в этом классе обрабатывается вся логика вашего приложения, которая потом передается в саму платформу, будь то голосовой навык для Алисы, либо чат-бот для VK.

    Этот класс связывает входящие запросы от пользователя с вашей бизнес‑логикой. Вы наследуетесь от BotController, переопределяете метод action и получаете доступ ко всем инструментам: кнопкам, карточкам, состоянию диалога, пользовательским данным, NLU и многому другому.

    Адаптеры платформ (например, AlisaAdapter) автоматически наполняют контроллер данными, вызывают внутренний метод {@link run} (он вызывает ваш action()), а затем формируют ответ на основе заполненных вами полей (text, buttons, card и т.д.).

    Ключевая особенность: вся логика вашего голосового навыка или бота описывается в одном месте – в методе action(). Фреймворк сам позаботится о маршрутизации: команды, интенты, шаги диалога – всё придёт в action с соответствующим флагом.

    Основные возможности:

    • Обработка пользовательских команд и интентов
    • Управление состоянием диалога
    • Работа с UI компонентами (кнопки, карточки)
    • Управление пользовательскими данными
    import { BotController } from 'umbot';
    // Определение пользовательских данных
    interface MyUserData extends IUserData {
    score: number;
    level: number;
    preferences: {
    language: string;
    theme: string;
    };
    }

    class MyController extends BotController<MyUserData> {
    public action(intentName: string | null): void {
    try {
    // Обработка приветствия
    if (intentName === WELCOME_INTENT_NAME) {
    // Текстовый ответ
    this.text = 'Привет! Чем могу помочь?';

    // Добавление кнопок
    this.buttons
    .addBtn('Помощь')
    .addBtn('Выход');

    // Добавление карточки
    this.card
    .addImage('xxx', 'Добро пожаловать!', 'Выберите действие:')
    .addButton('Начать игру')

    // Установка пользовательских данных
    this.userData = {
    score: 0,
    level: 1,
    preferences: {
    language: 'ru',
    theme: 'light'
    }
    };
    return;
    }

    // Обработка команды помощи
    if (intentName === HELP_INTENT_NAME) {
    this.text = 'Я могу помочь вам с...';
    this.buttons.addBtn('Назад');
    return;
    }

    // Обработка пользовательских событий
    if (this.userEvents?.auth?.status) {
    this.text = 'Вы успешно авторизовались!';
    }

    // Обработка оценки
    if (this.userEvents?.rating?.status) {
    const rating = this.userEvents.rating.value;
    this.text = `Спасибо за оценку ${rating}!`;
    }

    } catch (error) {
    // Обработка ошибки
    this.text = 'Произошла ошибка. Попробуйте позже.';
    }
    }
    }
    • action – переопределите этот метод, чтобы добавить свою логику.
    • Bot – основной класс приложения, управляющий адаптерами и контроллерами.

    Type Parameters

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    appContext: AppContext

    Контекст приложения.

    appeal: "official" | "no_official" | null = null

    Стиль обращения к пользователю. Определяет формальность общения, используется для платформ, которые поддерживают данное поведение.

    Возможные значения:

    • 'official': официальное обращение
    • 'no_official': неофициальное обращение
    • null: стиль не определен
    this.appeal = 'official'; // официальное обращение
    
    appType: string | null = null

    Платформа от которой был получен запрос.

    emotion: string | null = null

    Эмоция для голосового ответа. Используется для платформ, которые поддерживают данное поведение.

    this.emotion = 'good';
    
    isAuth: boolean = false

    Флаг необходимости авторизации. Определяет, требуется ли авторизация пользователя или нет.

    this.isAuth = true; // требуется авторизация
    
    isEnd: boolean = false

    Флаг, определяющий необходимость завершения диалога. Актуально когда необходимо принудительно завершить диалог с пользователем. Поддержка работы флага зависит от платформы.

    this.isEnd = true; // завершить диалог
    
    isScreen: boolean = false

    Определяет, с колонки пользователь запустил приложение или с устройства с экраном.

    this.isScreen = true; // экран доступен
    
    isSendRating: boolean = false

    Флаг отправки запроса на оценку. Определяет, нужно ли запросить оценку у пользователя. Используется для платформ, которые поддерживают данное поведение.

    this.isSendRating = true; // запросить оценку
    
    messageId: string | number | null = null

    ID сообщения. Используется для определения начала нового диалога.

    this.messageId = 12345;
    
    oldIntentName: string | null = null

    Название предыдущего интента/команды, полученное из userData.oldIntentName. Используется для отслеживания контекста диалога.

    КАК ЭТО РАБОТАЕТ:

    1. В конце обработки каждого запроса, this.thisIntentName сохраняется в userData.oldIntentName
    2. При следующем запросе это значение копируется в this.oldIntentName
    3. Используется для определения, с какого шага продолжить диалог

    ТИПИЧНОЕ ИСПОЛЬЗОВАНИЕ:

    • Возврат к предыдущему шагу
    • Многошаговые формы ("вернуться назад")
    • Диалоги с контекстом
    • Использование в шагах bot.addStep()
    // Пример: Многошаговая регистрация
    class RegistrationBot extends BotController {
    public action(intentName: string | null): void {
    // Определяем на каком шаге находимся
    const previousStep = this.oldIntentName;

    if (previousStep === 'enter_name') {
    // Пользователь только что ввел имя, спрашиваем email
    this.userData.name = this.userCommand;
    this.text = 'Отлично! Теперь введите ваш email:';
    this.thisIntentName = 'enter_email'; // Сохранится для следующего шага
    } else if (previousStep === 'enter_email') {
    // Пользователь ввел email, завершаем регистрацию
    this.userData.email = this.userCommand;
    this.text = 'Регистрация завершена!';
    }
    }
    }

    // Пример: Кнопка "Назад"
    if (intentName === 'back') {
    // Возвращаемся к предыдущему шагу
    switch(this.oldIntentName) {
    case 'product_list':
    this.text = 'Выберите категорию:';
    break;
    case 'category_list':
    this.text = 'Добро пожаловать!';
    break;
    }
    }
    originalUserCommand: string | null = null

    Оригинальный запрос пользователя. Текст запроса без изменений, включая регистр и знаки препинания.

    this.originalUserCommand = 'Привет, мир!';
    
    payload: string | Record<string, unknown> | null | undefined = null

    Дополнительные параметры запроса. Может содержать любые дополнительные данные полученные от платформы.

    this.payload = {
    source: 'mobile',
    version: '1.0'
    };
    platformOptions: IPlatformOptions = {}

    Дополнительные опции платформы. ⚠️ Внутреннее свойство. Заполняется адаптером платформы. Не предназначено для прямого использования в пользовательском коде.

    requestObject: unknown = null

    Полученный запрос от платформы. Содержит оригинальный объект запроса.

    this.requestObject = {
    command: 'start',
    payload: { source: 'mobile' }
    };
    skipAutoReply: boolean = false

    Флаг, указывающий, что ответ уже отправлен через API и не требуется автоматическая отправка. Как правило, данный флаг стоит использовать для платформ, которые не ждут ответ в виде возвращаемого содержимого, а ожидают что к самой платформе будет отправлен запрос. Например, чат-бот для Telegram, для отображения результата пользователю, отправляется запрос к платформе с нужным содержимым.

    Если указано true, значит все необходимые запросы уже отправлены в логике приложения, и дополнительно пользователю ничего отправлять не нужно.

    this.skipAutoReply = true; // запросы уже отправлены
    
    state: TPlatformState | null = null

    Пользовательское локальное хранилище. Используется для временного хранения данных, специфичных для текущего диалога. Работает только при включённой опции isLocalStorage: true в конфигурации. bot.setAppConfig({ isLocalStorage: true, });

    Правила синхронизации с базой данных (если подключена):

    • Если заполнены и userData, и state:
      • userData сохраняется в БД,
      • state сохраняется в локальное хранилище платформы.
    • Если заполнен только userDatastate пуст или равен userData):
      • данные сохраняются только в БД (состояние платформы не обновляется).
    • Если заполнен только state:
      • данные сохраняются только в локальное хранилище.

    При загрузке данных:

    1. Если есть данные из локального хранилища и из БД, они попадают соответственно в state и userData.
    2. Если есть только данные из хранилища, они копируются и в userData, и в state (для удобства).
    3. Если есть только данные из БД, они записываются в userData.

    userData — для постоянного хранения данных пользователя.

    this.state = {
    lastIntent: 'greeting',
    step: 1
    };
    text: string = ''

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

    this.text = 'Привет! Чем могу помочь?';
    
    thisIntentName: string | null = null

    Название текущего интента. Определяет следующий шаг диалога.

    this.thisIntentName = 'help';
    
    tts: string | null = null

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

    this.tts = 'Привет! Я голосовой ассистент.';
    
    userCommand: string | null = null

    Запрос пользователя в нижнем регистре.

    this.userCommand = 'привет мир';
    
    userData: TUserData = ...

    Пользовательские данные, который были сохранены.

    this.userData = {
    name: 'John',
    preferences: {
    language: 'ru'
    }
    };
    userEvents: IUserEvent | null = null

    Пользовательские событий. Содержит информацию об авторизации или оценке.

    IUserEvent

    this.userEvents = {
    auth: { status: true },
    rating: { status: true, value: 5 }
    };
    userId: string | number | null = null

    Уникальный идентификатор пользователя.

    this.userId = 'user_123';    // Telegram (string)
    this.userId = 123456789; // VK (number)
    this.userId = null; // не удалось получить информацию
    userMeta: unknown = null

    Дополнительная информация о пользователе.

    this.userMeta = {
    timezone: 'Europe/Moscow',
    locale: 'ru-RU'
    };
    userToken: string | null = null

    Пользовательский токен авторизации. Используется для авторизованных запросов (например, в Алисе).

    this.userToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
    

    Accessors

    • get buttons(): Buttons

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

      Returns Buttons

      • Навигация по меню
      • Быстрые ответы (Да/Нет)
      • Выбор из вариантов
      • Быстрое действие/команда

      Buttons

      this.buttons
      .addBtn('Помощь')
      .addBtn('Выход');
    • get card(): Card

      Компонент для отображения карточек пользователю. Позволяет создавать визуальные элементы с изображениями и текстом. Также при указании нескольких изображений, они автоматически преобразуются в карточку.

      Returns Card

      • Каталог товаров/услуг
      • Галерея изображений
      • Карточки статей/новостей
      • Навигация

      Card

      // КАТАЛОГ ТОВАРОВ (интернет-магазин):
      this.text = 'Популярные товары:';
      this.card
      .addImage(
      'http://localhost/iphone.jpg',
      'iPhone 15 Pro',
      '99 990 ₽\nЭкран 6.1", процессор A17 Pro'
      )
      .addButton('Купить')

      .addImage(
      'http://localhost/macbook.jpg',
      'MacBook Air M2',
      '124 990 ₽\n13.6", 8ГБ RAM, 256ГБ SSD'
      )
      .addButton('Купить');

      // ГАЛЕРЕЯ ФОТОГРАФИЙ:
      this.text = 'Наши работы:';
      this.card
      .addImage('photo1.jpg', 'Свадьба', 'Иван и Мария')
      .addImage('photo2.jpg', 'Выпускной', 'Школа №123')
      .addImage('photo3.jpg', 'Корпоратив', 'Компания "Рога и копыта"');

      // КАРТОЧКИ НОВОСТЕЙ:
      this.card
      .addImage(
      'news1.jpg',
      'Новое обновление',
      'Добавлена оплата картой и доставка',
      {
      title: 'Перейти',
      url: 'http://localhost/news/1'
      }
      )
    • get nlu(): Nlu

      Обработанный NLU (Natural Language Understanding). Содержит результаты обработки естественного языка, как правило, данные заполняются самой платформой.

      Returns Nlu

      Nlu

    • get sound(): Sound

      Компонент для работы со звуками. Позволяет добавлять звуковые эффекты и музыку. Используется вместе с tts.

      Returns Sound

      Sound

    Methods

    • Запуск обработки пользовательских команд с учетом метрик.

      Parameters

      • commandName: string | null
      • isCommand: boolean = false
      • isStep: boolean = false

      Returns void

    • Извлекает нужную команду из запроса.

      Returns void | Promise<void> | null

      найденная команда или null если не удалось найти команду

    • Находит нужный интент по тексту запроса.

      Parameters

      • text: string | null

        Текст запроса

      Returns string | null

      Название интента или null

    • Основной метод, в котором вы реализуете логику вашего голосового навыка или бота.

      Этот метод вызывается фреймворком автоматически после того, как запрос пользователя был распознан как команда, интент или шаг диалога. В параметр intentName передаётся имя команды. Флаги isCommand и isStep позволяют различить источник вызова. Используется для более глубокой логики приложения, например можно использовать в качестве логирования, если все обработчики реализованы через команды. Либо использовать в качестве обработки команд, что не рекомендуется, так как из-за подобного подхода, размер метода может быть большим.

      Метод необходимо обязательно реализовать в дочерних классах.

      Parameters

      • intentName: string | null

        Название интента или команды

      • OptionalisCommand: boolean

        Флаг, указывающий что это команда

      • OptionalisStep: boolean

        Флаг, указывающий что это шаг

      Returns void

      // Пример с обработкой интентов
      class MyController extends BotController {
      public action(intentName: string | null): void {
      if (intentName === 'greeting') {
      this.text = 'Привет!';
      } else if (intentName === 'help') {
      this.text = 'Помощь:';
      this.buttons.addBtn('Назад');
      }
      }
      }

      // Пример с логированием
      class MyController extends BotController {
      public action(intentName: string | null, isCommand?: boolean, isStep?: boolean): void {
      console.log(`Прошли по ${isCommand ? 'команде' : isStep ? 'шагу' : 'интенту'} с именем: ${intentName}`);
      }
      }
    • Очищает все временные данные необходимые для отправки ответа.

      Returns void

    • Флаг возвращающий информацию о том, были ли инициализированы кнопки или нет

      Returns boolean

    • Флаг возвращающий информацию о том, были ли инициализированы карточки или нет

      Returns boolean

    • Флаг возвращающий информацию о том, были ли инициализирован nlu или нет

      Returns boolean

    • Флаг возвращающий информацию о том, были ли инициализированы звуки или нет

      Returns boolean

    • Основной метод обработки запроса, вызываемый автоматически фреймворком.

      Returns void | Promise<void>

      Может быть асинхронным

      КРАТКИЙ ОБЗОР РАБОТЫ:

      1. Пользователь отправляет сообщение → платформа → Bot.run()
      2. run() определяет тип запроса (команда/интент/шаг)
      3. Вызывается ваш метод action() с результатом
      4. Вы заполняете поля ответа (text, buttons, card)
      5. Bot отправляет ответ пользователю

      ЧТО НЕ НУЖНО ДЕЛАТЬ:

      • ❌ Не вызывайте run() вручную в своем коде
      • ❌ Не переопределяйте этот метод
      • ✅ Переопределяйте только метод action() для своей логики

      ПОСЛЕДОВАТЕЛЬНОСТЬ ОБРАБОТКИ ВНУТРИ run():

      run()
      ├── Шаг 1: Проверяет есть ли активный шаг
      │ → Если естьвызывает action(stepName, false, true)
      ├── Шаг 2: Ищет команду
      │ → Если нашелвызывает action(commandName, true, false)
      ├── Шаг 3: Ищет интент
      │ → Если нашелвызывает action(intentName, false, false)
      └── Шаг 4: Если ничего не нашелFallback команда
      // ВАШ КОД (контроллер):
      class MyController extends BotController {
      public action(intentName: string | null): void {
      // Ваша логика здесь
      this.text = "Ответ пользователю";
      }
      }

      // КОД ФРЕЙМВОРКА (не ваш):
      // Когда приходит запрос от пользователя:
      const controller = new MyController();
      {...}; // Наполняет контроллер данными. Как правило, этим занимается адаптер платформы
      await controller.run(); // Автоматически вызывает ваш action()
      const response = ...; // Адаптер формирует ответ в зависимости от состояния контроллера