Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Expand
titleНажмите здесь, чтобы развернуть пример сценария
Image RemovedImage Added
Code Block
// Сценарий отправляет на указанный адрес текст переписки с пользователем.
// Дополнительно к письму прикладываются файлы, выбранные оператором.
// Сценарий может быть использован как для отправки переписки самому пользователю так и для отправки письма в сторонний сервис. 
//
// Настройки сценария
// 
// Формат текста письма. Установите true для HTML и false для обычного текста.
установитьПеременную("formated_text", "true") +
// Максимальный размер файлов для отправки в качестве вложения. Сценарий сообщит о пропущенных файлах и оператору и получателю письма.
установитьПеременную("useUserEmail", "true") +
// Адрес отправителя 
установитьПеременную("from_email", "noreply@autofaq.ai") +
// Предустановленная тема письма. Оператор сможет сменить тему перед отправкой письма.
установитьПеременную("subject", "Переписка с пользователем {userFullName}")+
//
// Адрес сервиса по отправке писем, встроенного в AutoFAQ
установитьПеременную("host", "http://porter/api/postman/mail") +
//дополнительные переменные
установитьПеременную("t1","false")+
установитьПеременную("t2","false")+
установитьПеременную("t3","false")+
установитьПеременную("t4","false")+
установитьПеременную("t5","false")+
//
// Основной код сценария
//
// Сценарий проверяет файлы в переписке
выполнитьJs("""
try {
  var parsedExtFiles = JSON.parse(externalFiles);
} catch(e) {
  var parsedExtFiles = [];
}
var numOfFiles = parsedExtFiles.length;
var filesUrl_01 = ''; var filesUrl_name_01 = '';var filesUrl_size_01 = '';
var filesUrl_02 = ''; var filesUrl_name_02 = '';var filesUrl_size_02 = '';
var filesUrl_03 = ''; var filesUrl_name_03 = '';var filesUrl_size_03 = '';
var filesUrl_04 = ''; var filesUrl_name_04 = '';var filesUrl_size_04 = '';
var filesUrl_05 = ''; var filesUrl_name_05 = '';var filesUrl_size_05 = '';
var idx = 0;
var contentIndex = 0;
if (numOfFiles > 5) {
  numOfFiles = 5;
}
if (numOfFiles > 0) {
  for (var i = 0; i < numOfFiles; i++) {
      idx = idx + 1;
      if (idx == 1) {filesUrl_01 = 'http://bot-platform-back:8090/api/files/' + JSON.parse(parsedExtFiles[i])['id'];filesUrl_name_01 =JSON.parse(parsedExtFiles[i])['name'];contentIndex = 1;filesUrl_size_01 = JSON.parse(parsedExtFiles[i])['size'];}
      if (idx == 2) {filesUrl_02 = 'http://bot-platform-back:8090/api/files/' + JSON.parse(parsedExtFiles[i])['id'];filesUrl_name_02 =JSON.parse(parsedExtFiles[i])['name'];contentIndex = 2;filesUrl_size_02 = JSON.parse(parsedExtFiles[i])['size'];}
      if (idx == 3) {filesUrl_03 = 'http://bot-platform-back:8090/api/files/' + JSON.parse(parsedExtFiles[i])['id'];filesUrl_name_03 =JSON.parse(parsedExtFiles[i])['name'];contentIndex = 3;filesUrl_size_03 = JSON.parse(parsedExtFiles[i])['size'];}
      if (idx == 4) {filesUrl_04 = 'http://bot-platform-back:8090/api/files/' + JSON.parse(parsedExtFiles[i])['id'];filesUrl_name_04 =JSON.parse(parsedExtFiles[i])['name'];contentIndex = 4;filesUrl_size_04 = JSON.parse(parsedExtFiles[i])['size'];}
      if (idx == 5) {filesUrl_05 = 'http://bot-platform-back:8090/api/files/' + JSON.parse(parsedExtFiles[i])['id'];filesUrl_name_05 =JSON.parse(parsedExtFiles[i])['name'];contentIndex = 5;filesUrl_size_05 = JSON.parse(parsedExtFiles[i])['size'];}
    }
}
var exit = {'contentIndex': contentIndex, 'filesUrl_01':filesUrl_01, 'filesUrl_02':filesUrl_02, 'filesUrl_03':filesUrl_03, 'filesUrl_04':filesUrl_04, 'filesUrl_05':filesUrl_05, 'filesUrl_name_01':filesUrl_name_01, 'filesUrl_name_02':filesUrl_name_02, 'filesUrl_name_03':filesUrl_name_03, 'filesUrl_name_04':filesUrl_name_04, 'filesUrl_name_05':filesUrl_name_05, 'filesUrl_size_01': filesUrl_size_01, 'filesUrl_size_02':filesUrl_size_02,'filesUrl_size_03':filesUrl_size_03,'filesUrl_size_04':filesUrl_size_04,'filesUrl_size_05':filesUrl_size_05};
exit;
""") +
//отображаем список файлов для выбора
если("{contentIndex} > 0").то(
  добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "t1_txt",
  значение = "{filesUrl_name_01} размер {filesUrl_size_01} b",
  название = "",
  тип = "Однострочный нередактируемый текст",
  обязательное = false
) +
  добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "t1",
  название = "",
  тип = "Переключатель",
  описание = "",
  обязательное = false
)
)+
если("{contentIndex} > 1").то(
  
  добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "t2_txt",
  значение = "{filesUrl_name_02} размер {filesUrl_size_02} b",
  название = "",
  тип = "Однострочный нередактируемый текст",
  обязательное = false
) +
  добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "t2",
  название = "",
  тип = "Переключатель",
  описание = "",
  обязательное = false
)
)+
если("{contentIndex} > 2").то(
  добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "t3_txt",
  значение = "{filesUrl_name_03} размер {filesUrl_size_03} b",
  название = "",
  тип = "Однострочный нередактируемый текст",
  обязательное = false
) +
  добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "t3",
  название = "",
  тип = "Переключатель",
  описание = "",
  обязательное = false
)
)+
если("{contentIndex} > 3").то(
  добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "t4_txt",
  значение = "{filesUrl_name_04} размер {filesUrl_size_04} b",
  название = "",
  тип = "Однострочный нередактируемый текст",
  обязательное = false
) +
  добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "t4",
  название = "",
  тип = "Переключатель",
  описание = "",
  обязательное = false
)
)+
если("{contentIndex} == 5").то(
  добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "t5_txt",
  значение = "{filesUrl_name_05} размер {filesUrl_size_05} b",
  название = "",
  тип = "Однострочный нередактируемый текст",
  обязательное = false
) +
  добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "t5",
  название = "",
  тип = "Переключатель",
  описание = "",
  обязательное = false
)
)+
// Сценарий предустанавливает адрес получателя из данных пользователя или оставляет поле пустым
если("{useUserEmail} == true").то(
  установитьПеременную("_email", "{userEmail}") 
)+
// Сценарий собирает форму для сбора данных у пользователя - адрес и комментарий к письму
добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "formName",
  название = "",
  значение = "Сценарий отправит электронное письмо с текстом переписки на указанный адрес. Выбранные файлы в переписке будут приложены к письму.",
  тип = "Нередактируемый текст",
  описание = "",
  обязательное = false
) +
добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "email",
  значение = "{_email}",
  название = "Укажите адрес email",
  тип = "Однострочный редактируемый текст",
  обязательное = true
) +
добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "subject",
  значение = "{subject}",
  название = "Укажите тему письма",
  тип = "Однострочный редактируемый текст",
  обязательное = true
) +
добавитьПолеВФормуОператора(
  форма = "Отправка текста переписки на электронную почт",
  переменная = "comment",
  значение = "",
  название = "Комментарий к письму",
  тип = "Многострочный редактируемый текст",
  обязательное = false
) +
//  
// Сценарий отображает форму для опроса оператора
показатьФормуОператору(имя = "Отправка текста переписки на электронную почт") +
//
//собирает выбранные вложения для отправки в письме
комментарий("{filesUrl_01}")+
выполнитьJs("""
var filesUrls = [];
if (t1 == 'true'){
filesUrls.push(filesUrl_01);
}
if (t2 == 'true'){
filesUrls.push(filesUrl_02);
}
if (t3 == 'true'){
filesUrls.push(filesUrl_03);
}
if (t4 == 'true'){
filesUrls.push(filesUrl_04);
}
if (t5 == 'true'){
filesUrls.push(filesUrl_05);
}
var exit = {'filesUrls' : filesUrls};
exit;
""")+
//
// Сценарий получает историю сообщений и формирует запрос на отправку письма
выполнитьJs("""
var rawText = '';

var msgTypes = ['Question', 'AnswerOperator', 'AnswerChatterbox','AnswerOperatorWithBot','AnswerOperator', 'AnswerBot']; 
var labelMap = {
    'Question': 'Пользователь:',
    'AnswerOperator': 'Оператор:',
    'AnswerBot': 'Бот:',
    'AnswerChatterbox': 'Бот:',
    'AnswerOperatorWithBot': 'Оператор:'
  }

if (conversation.channelUser.fullName) {
  if (conversation.channelUser.email) {
    var line_1 = '<div>Переписка с пользователем <b>' + conversation.channelUser.fullName + '</b> (' + conversation.channelUser.email + ')</div>';
  } else {
    var line_1 = '<div>Переписка с пользователем <b>' + conversation.channelUser.fullName + '</b> (адрес EMAIL не зарегистрирован)</div>';
  }
} else {
  if (conversation.channelUser.email) {
    var line_1 = '<div>Переписка с пользователем ' + conversation.channelUser.email + ' (ФИО не указано)</div>';
  } else {
    var line_1 = '<div>Переписка с неизвестным пользователем</div>'
  }
}

if (conversation.messages.length > 0) {
  var first_event = conversation.messages[0];
  var line_2 = '<div>Дата начала диалога ' + first_event.ts.slice(8,10) + '.' + first_event.ts.slice(5,7) + '.' + first_event.ts.slice(0,4);
  line_2 = line_2 + ' ' + first_event.ts.slice(11,13) + ':' + first_event.ts.slice(14,16) + '</div><br>';
} else {
  var line_2 = '<div>Дата начала диалога не указана</div><br>';
}

if (comment == '' || comment == 'NaN') {
  var line_3 = '<div>Оператор не оставил комментарий к переписке.</div>';  
} else {
  var line_3 = '<div><b>Комментарий оператора к переписке:</b> ' + comment + '</div>';
}
line_3 = line_3 + '<br>';

var messages = conversation.messages.filter(function (str) {return  msgTypes.indexOf(str.tpe) > -1;});
for (var i = 0; i < messages.length; i++) {
  var message = messages[i];
  var label = labelMap[message.tpe] || '';
  if (label) {
    if (formated_text != 'true') {
      clean_txt = message.txt.replace(/<a[^>]*href="([^"]+)"[^>]*>(?:.*?<\/a>)?/g, '$1').replace(/<\/?[^>]+(>|$)/g, "").replace(/(\r\n|\n|\r)/gm, '\n');
      rawText = rawText + '\n' + message.ts.slice(11,16) + ' ' + label + '\n' + clean_txt;
    } else {
      clean_txt = message.txt.replace(/(\r\n|\n|\r)/gm, '');
      rawText = rawText + '<div>' + message.ts.slice(11,16) + ' ' + label + '</div><div>' + clean_txt + '</div>';
    }
    
  }
}
if (rawText == '') {
  var line_4 = '<div><b>Содержание переписки недоступно.</b></div>'
} else {
  var line_4 = '<div><b>Содержание переписки</b></div>';
}

if (formated_text == 'true') {
  var final_text = '<html><head></head><body>' + line_1 + line_2 + line_3 + line_4 + rawText + '</body></html>';
} else {
  var final_text = line_1 + '\n' + line_2 + '\n' + line_3 + '\n\n' + line_4;
  final_text = final_text.replace(/<\/?[^>]+(>|$)/g, "") + '\n' + rawText;
}

var request = {
  from: from_email,
  to: email,
  subject: subject,
  body: final_text,
  files: JSON.parse(filesUrls)
}

var exit = {'request': JSON.stringify(request)};
exit;
""")+
// 
// Сценарий отправляет запрос на формирование письма
вызвать.внешнийСервис("{host}", "POST").сЗаголовками(("Content-Type","application/json")).сТеломСообщения("{request}").сохранитьРезультатКакСтроку("answer")+
// 
// Если сервис по отправке писем ответил ошибкой сценарий сообщает об этом пользователю и завершает работу
если("{http_code} > 202").то(
  //если запрос завершен с ошибкой сценарий помещает в диалог соответствующий комментарий и завершает свою работу
  комментарий("При отправке письма возникла ошибка {http_code} - {answer}")+
  завершить
)+
//
// Если сервис по отправке писем успешно отправляет письмо то сценарий сообщает об отправке и завершает свою работу
комментарий("Письмо с перепиской отправлено на адрес {email}") + 
завершить

...

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

Для работы сценария необходимо получить данные для подключения к Google Sheets и подготовить переменные сервиса. Детальное описание подключения доступно по ссылке - Подключение сценария к Google Sheets

Expand
titleНажмите здесь, чтобы развернуть пример сценария
Code Block
//
// Сценарий ищетопроса текстпользователя ви таблице Google Sheets по значениюсохранения результатов в любойтаблице колонке и возвращает сообщение "Да" если текст найден или "Нет" если не найден
//
// Укажите логин сервисного аккаунта Google
установитьПеременную("email", "account_name@project_name.iam.gserviceaccount.com") +Google Sheet 
// 
// Укажите идентификаторИдентификатор таблицы Google Sheet
установитьПеременную("sheetId", "ХХХХХХ1UyTG1ag6kb-ХХХХХХХХХХХХХtKCD0Wc5nD21zE38TvYSiMMQ_vzwxWbs")+
// Укажите названиеНазвание листа в таблице Google Sheet
установитьПеременную("sheetName", "Sheet1")+
//
// Опрос Основнойпользователя
код сценария 
//
//
// Получение временного токена для работы с гугл таблицей
вызвать.внешнийСервис("https://denisk.autofaq.ai/gtoken","GET").сЗаголовками(("Content-Type", "application/json"),("charset", "utf-8")).сПараметрами(("email","{email}")).сохранитьРезультат(("message","message"),("token","token"),("status","status")//
установитьПеременную("sendFio", "{userFullName}")+
если("{sendFio} == ").то(
    задатьПользователюВопрос("Укажите как вас зовут, пожалуйста").сохранитьРезультат("sendFio")
)+
установитьПеременную("sendEmail", "{userEmail}")+
если("{sendEmail} == ").то(
    задатьПользователюВопрос("Укажите адрес вашей электронной почты").сохранитьРезультат("sendEmail")
)+
задатьПользователюВопрос("Пожалуйста назовите ваш отдел").сохранитьРезультат("sendOtdel") +
задатьПользователюВопрос("Пожалуйста назовите вашу должность").сохранитьРезультат("sendDolznost") +
задатьПользователюВопрос("Уточните, пожалуйста, что для Вас является приоритетным?").сВариантамиОтвета("Получение максимальной суммы","Простота получения").сохранитьРезультат("sendPriority")+
задатьПользователюВопрос("Укажите, на какие цели предназначается займ?").сохранитьРезультат("sendGoal")+
//
// Проверка результатовОтправка запроса, в случаегугл
ошибки// сценарий
сообщит// обПопытка ошибкеполучения исохраненного завершитсяранее 
если("{http_code} > 210").то(
	комментарий("Сценарий не смог получить токен для работы с таблицей. {message}")+
	сообщениеПользователю.сШаблоном("Спасибо за участие, но что-то сломалось и я не могу связаться с Гугл.")+
	завершить
)+
если("{status} == error").то(
	комментарий("Сценарий не смог получить токен для работы с таблицей. {message}")+
	сообщениеПользователю.сШаблоном("Спасибо за опрос, но что-то сломалось и я не смог сохранить результаты.")+
	завершить
)+
//
// Получение адреса электронной почты
установитьПеременную("enteredEmail", "{userEmail}") +
если("{enteredEmail} == ").то(
	задатьПользователюВопрос("Укажите адрес вашей электронной почты").сохранитьРезультат("enteredEmail") +
	установитьПеременнуюПользователю("userEmail", "{enteredEmail}")
) +
//
// Отправка запроса на поиск адреса в гугл таблицу
вызвать.внешнийСервис("https://sheets.googleapis.com/v4/spreadsheets/{sheetId}/values/{sheetName}","GET").сПараметрами(("majorDimension","COLUMNS")).сЗаголовками(("Authorization", "Bearer {token}"),("Content-Type","application/json")).сохранитьРезультатКакСтроку("checkLoginResult") +
//
// Проверка результатов запроса, в случае ошибки сценарий сообщит об ошибке и завершится 
если("{http_code} > 210").то(
	комментарий("Сценарий не смог отправить запрос на поиск в гугл таблице. Код ответа {http_code}, ответ {checkLoginResult}")+
	сообщениеПользователю.сШаблоном("Спасибо за участие, но что-то сломалось и я не могу связаться с центром.")+    
    завершить
)+
выполнитьJs("""
var checkLoginResultParsed = JSON.parse(checkLoginResult);
if ("values" in checkLoginResultParsed) {
	if (checkLoginResultParsed['values'][0].indexOf(userLogin) != -1) {
		var checkLoginResultData = 1;
	} else {
		var checkLoginResultData = 0;
	}
} else {
	var checkLoginResultData = 0;
}
var exit = {'checkLoginResultData':checkLoginResultData};
exit;
""") +
//
// Если адрес почты пользователя найден в таблице то сценарий сообщает об этом пользователю и завершается
если("{checkLoginResultData} == 1").то(
	комментарий("Логин пользователя {userLogin} уже найден в таблице, поэтому опрос останавливаю")+	
	сообщениеПользователю.сШаблоном("Вы уже проходили этот опрос. Второй раз спрашивать нет необходимости")+	
	завершить
)+
//
// Сценарий начинает опрос пользователя
задатьПользователюВопрос("Пожалуйста назовите ваше ФИО").сохранитьРезультат("fio") +
задатьПользователюВопрос("Пожалуйста назовите ваш отдел").сохранитьРезультат("otdel") +
задатьПользователюВопрос("Пожалуйста назовите вашу должность").сохранитьРезультат("dolznost") +
задатьПользователюВопрос("Оцените удобство нашего сервиса").сВариантамиОтвета("Все устраивает", "Возникают трудности", "Комментарий").сохранитьРезультат("udobstvo_main") +
установитьПеременную("udobstvo_add", " ")+
если("{udobstvo_main} == Возникают трудности").то(задатьПользователюВопрос("Какие у вас трудности?").сохранитьРезультат("udobstvo_add")) +
если("{udobstvo_main} == Комментарий").то(задатьПользователюВопрос("Напишите ваш комментарий").сохранитьРезультат("udobstvo_add")) +
// Открытые вопросы
задатьПользователюВопрос("Напишите какие дополнительные сервисы Вы хотели бы видеть").сохранитьРезультат("new_services") +
задатьПользователюВопрос("Напишите Ваши предложения и пожелания").сохранитьРезультат("suggestions") +
// 
выполнитьJs("""
var now = new Date();
var login = enteredEmail;
var udobstvo = udobstvo_main + udobstvo_add;

var requestBody = {"range": sheetName+"!A1:O1", "majorDimension": "ROWS", "values":[[now, login, fio, otdel, dolznost, udobstvo, new_services, suggestions]]};
var requestBodyJSON = JSON.stringify(requestBody);

var exit = {'requestBodyJSON':requestBodyJSONтокена для запросов в google из переменных сервиса
получитьПеременнуюСервиса("google_token", "g_token")+
// Разбор сохраненного токена
выполнитьJs("""
try {
    var doc = JSON.parse(g_token);
} catch(e) {
    var doc = {'token': '', 'ts': 0};
}

var token = '';
var now_ts =  parseInt(Date.now() / 1000);

if (now_ts > doc.ts) {
    var error = 1;    
} else if (doc.ts == 0) {
    var error = 2;
} else if (doc.token == '') {
    var error = 3;
} else {
    var error = 0;
    var token = doc.token;
}

var exit = {'error':error, 'token':token, 'expired':doc.ts, 'now_ts':now_ts};
exit;
""") +
комментарий("Получил сохраненный токен, статус токена {error}")+ 
// Проверка актуальности сохраненного токена
если("{error} == 0").то(
    // Токен записан и его время жизни не истекло 
    // Сценарий переходит непосредственно к запросу на добавление данных в таблицу
    комментарий("Токен еще валиден, используем его")+
    перейтиНаМетку("google_query")
)+
// Токен или не сохранен или его время жизни истекло
// Сценарий получает новый токен
комментарий("Токен не валиден, получаем новый токен")+
// Сценарий получает из переменных сервиса секретный ключ и адрес аккаунта гугл 
получитьПеременнуюСервиса("google_private_key", "g_private_key") +
получитьПеременнуюСервиса("goggle_account_email", "goggle_account_email") +
// Проверка полученных данных
если("{g_private_key} == ").то(
    комментарий("Нет приватного ключа от аккаунта, не могу получить токен.")+
    завершить
)+
если("{goggle_account_email} == ").то(
    комментарий("Нет адреса аккаунта гугл, не могу получить токен.")+
    завершить
)+
// Сценарий формирует тело запроса на получение токена 
выполнитьJs("""
var header = {
        "alg": "RS256",
        "typ": "JWT"
    };
var data = {
        "iss": goggle_account_email,
        "scope": "https://www.googleapis.com/auth/spreadsheets",
        "aud": "https://oauth2.googleapis.com/token",
        "exp": parseInt(Date.now() / 1000) + 3600,
        "iat": parseInt(Date.now() / 1000)
    };

var sHeader = JSON.stringify(header);
var sPayload = JSON.stringify(data);
var s_g_private_key = g_private_key.replace(/\\n/g,'');
var signature = KJUR.jws.JWS.sign(header.alg, sHeader, sPayload, s_g_private_key);

var exit = {'signature':signature};
exit;
""") +
// //Сценарий Получениезапрашивает временного токенагугла для работы с гугл таблицейполучения токена
вызвать.внешнийСервис("https://deniskoauth2.autofaqgoogleapis.aicom/gtokentoken", "GETPOST").сЗаголовками(("Content-Type", "application/json"),("charset", "utf-8")).сПараметрами(("email","{email}")).сохранитьРезультат(("message","message"),("token","token"),("status","status"))+
//
// Проверка результатов запроса, в случае ошибки сценарий сообщит об ошибке и завершится 
если("{http_code} > 210").то(
	комментарий("Сценарий не смог получить токен для работы с таблицей. {message}")+
	).сТеломСообщения("{'grant_type':'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion':'{signature}'}").сохранитьРезультатКакСтроку("result")+
если("{http_code} > 210").то(
    комментарий("Сценарий не смог получить токен для записи в таблицу. Код ошибки {http_code}, ответ {result}")+
    сообщениеПользователю.сШаблоном("Спасибо за участие, но что-то сломалось и я не могу связаться с центромGoogle.")+    
    завершить
)+
если("{status} == error").то(
	комментарий("Сценарий не смог получить токен для работы с таблицей. {message}")+
	сообщениеПользователю.сШаблоном("Спасибо за опрос, но что-то сломалось и я не смог сохранить результаты.")+    
    завершить
)
// Сценарий разбирает ответ от гугл на получения токена
выполнитьJs("""
try {
    var resultParced = JSON.parse(result)
} catch(e) {
    var resultParced = {'access_token':'','expires_in':0};
}
var token = resultParced.access_token;
var expires = resultParced.expires_in;
var g_token = {'token': token, 'ts': parseInt(Date.now() / 1000) + 3599};

var exit = {'token':token, 'expires':expires, 'g_token':JSON.stringify(g_token)};
exit;
""") +
// Сценарий разбирает ответ гугла
если("{token} == ").то(
    комментарий("Сценарий не смог распознать токен в ответе от гугла. Ответ {result}")+
    сообщениеПользователю.сШаблоном("Спасибо за участие, но что-то сломалось и я не могу связаться с Google.")+    
    завершить
)+
// Сценарий сохраняет полученный токен для будущего использования
изменитьПеременнуюСервиса("google_token", "{g_token}")
комментарий("Обновил сохраненный токен для запросов в гугл")+
// 
// Метка для запроса на запись данных в таблицу
установитьМетку("google_query") +
//
// Формирование тела запроса на добавление 1 строки в конец таблицы, количество столбцов не более 25
выполнитьJs("""
    // Дата добавления
    var sendDate = new Date();
    // Список добавляемых значений
    var addValues = [sendDate, sendEmail, sendFio, sendOtdel, sendDolznost, sendPriority, sendGoal];

    var sheetsNames = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','R','S','T','U','V','W','X','Y','Z'];
    var sheetEnd = sheetsNames[addValues.length];
    var requestBody = {"range": sheetName+"!A1:"+sheetEnd+"1", "majorDimension": "ROWS", "values":[addValues,]};

    var exit = {'requestBodyJSON':JSON.stringify(requestBody), 'sheetEnd':sheetEnd};
exit;
""") +
//
// Сценарий Отправкаотправляет запросазапрос на добавлениеотправку строкиданных в таблицутабличку
вызвать.внешнийСервис("https://sheets.googleapis.com/v4/spreadsheets/{sheetId}/values/Sheet1{sheetName}!A1:O1{sheetEnd}1:append","POST").сПараметрами(("valueInputOption","USER_ENTERED")).сЗаголовками(("Authorization", "Bearer {token}"),("Content-Type","application/json")).сТеломСообщения("{requestBodyJSON}").сохранитьРезультатКакСтроку("result")+
// //Сценарий Проверкаразбирает результатоврезультаты запроса, в случае ошибки сценарий сообщит об ошибке и завершится 
если("{http_code} > 210").то(
   	 комментарий("Сценарий не смог отправить запрос на добавление строчки в гугл таблице. Код ответа {http_code}, ответ {result}")+
    	сообщениеПользователю.сШаблоном("Спасибо за участие, но что-то сломалось и я не могу связаться с центромGoogle.")+    
    завершить
)+
// Запрос на добавление записи завершен успешно
комментарий("Добавил строчку в гугл таблицу.") +
сообщениеПользователю.сШаблоном("Все записал. Большое спасибо за участие!") +
завершить

Интеграционные сценарии

...