Перейти к содержанию

Введение в скрипты

Возможности

Скрипты предназначены для решения задач, для которых не предусмотрены возможности готовых блоков в конструкторе ELMA Bot. Скрипты пишутся на языке TypeScript.

Скрипт — это блок кода, который запускается в определенный момент. Скрипт может читать и менять значения переменных бота, а также влиять на его поведение.

image

Есть два типа скриптов:

  • элемент сценария;

  • обработчик событий.

Элемент сценария

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

image

Типичный алгоритм такого скрипта:

  • прочитать значения переменных бота;

  • выполнить вычисление;

  • записать данные в переменные бота.

Рассмотрим, как с помощью скрипта отправить SMS с кодом для подтверждения номера телефона пользователя:

TypeScript
// Отправка

const axios = require('axios');

const systemEmail = 'mr.cat@elma-bpm.com';
const apiKey = 'bIgSeCreT';

// Перед запуском скрипта бот спросил у пользователя номер телефона и записал его в переменную
// Читаем номер телефона из переменной
const userPhone = context.input.variables.user_phone;

// Генерируем код для отправки в SMS
const systemCode = Math.floor(Math.random() * (999999 - 100000) + 100000);

// Записываем код в переменную, чтобы использовать его далее в сценарии с текстом, который введет пользователь
context.output.variables.system_code = systemCode;

const response = await axios.get(
  'https://' +
    systemEmail +
   ':' +
   apiKey +
   '@gate.smsaero.ru/v2/sms/send?number=' + 
   userPhone + 
   '&text=' + 
   systemCode + 
   '&sign=SMS%20Aero'
;

Обработка ошибок в сценарии

Элемент «Скрипт» имеет два выхода:

  • успешный;

  • переход в случае ошибки.

image

Если скрипт отработал успешно, то сценарий бота продолжает работу, переходя к следующему шагу. Выход «Ошибка отправки» используется, чтобы определить поведение бота, если во время выполнения скрипта возникла ошибка.

Настройка запуска

image

Настройки запуска скрипта:

  • Максимальное время выполнения скрипта в секундах. Если скрипт выполняется дольше, чем указано в данном поле, то выполнение прерывается. Скрипт выполняется как шаг сценария, и пока сценарий не будет завершен, бот не переходит к следующим шагам. В это время пользователь ждет нового сообщения от бота, а при долгом ожидании может возникнуть ощущение, что бот «завис».

  • Количество повторных попыток выполннения скрипта. Если скрипт не удалось успешно выполнить с первой попытки, то будет предпринято столько попыток, сколько указано в этом поле.

  • Задержка времени в секундах между повторными попытками. Пауза между повторами скрипта.

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

Обработчик событий

С помощью скрипта обработчика событий можно решать следующие задачи:

  • добавление нового формата ввода данных;

  • кастомные правила валидации ввода;

  • автоматическое заполнение переменных (slot filling);

  • динамический набор кнопок;

  • определение условий прерывания сценариев.

Скрипт обработчика событий задается один на бот в разделе «Настройки бота». В одном скрипте размещается множество обработчиков, каждый квалифицируется типом события и дополнительными параметрами.

В примере скрипт загружает список ФИО через REST API и при при вводе переменной fio добавляет кнопки с именами сотрудников.

TypeScript
const axios = require("axios");

const baseUrl = 'http://localhost:5020/api/v1/info/application/';
const personsEndpointRoute = 'test-fio';

onInputDialogBegin('fio', async () => {
    const searchOptions = {
        method: 'GET',
        url: baseUrl + personsEndpointRoute,
    };

    try {
        const response = await axios.request(searchOptions);
        if (response.data.filter(p => p.position == 'hr').length) {
            console.log('more than 0 hr');
            context.output.result.promptText = 'Выберите сотрудника. Например, вы можете обратиться к кому-то из HR:';
            context.output.result.suggestedActions =
                response.data
                    .filter(p => p.position == 'hr')
                    .map((person) => {
                        return {
                            value: person.lastName + ' ' + person.firstName + ' ' + person.middleName,
                            text: person.lastName + ' ' + person.firstName,
                        }
                    });
        }
    }
    catch (ex) {
        console.log(ex);
        context.output.result.recognized = false;
        context.output.result.promptText = 'Какая-то ошибка';
        context.output.result.suggestedActions = [];
    }
});