Готовые скрипты для AppScript

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

Если у вас не получается самостоятельно с помощью бота создать нужный скрипт, напишите в группу https://t.me/+KQ6mUbTAtFQ4YWEy и мы поможем. 

Еще больше скриптов собраны здесь: https://buildin.ai/share/89fa3fc7-02c2-46b1-822b-159eb9bcc2e4?code=S6VZ8D

Комбайн для массовых задач

Этот скрипт превращает Google Таблицу в мощный инструмент для массовой автоматизации задач с ботами ProTalk.  

📌 Ключевые особенности: 
✔ Массовая обработка — отправка множества задач одновременно.  
✔ Асинхронность — каждая задача выполняется независимо, без ограничений по времени.  
✔ Многошаговые сценарии — поддержка цепочек сообщений (разделитель ##).  
✔ Автоматический контроль статусов — отслеживание выполнения задач (Sent, Waiting, Completed, Error).  
✔ Работа с API ProTalk — интеграция через вебхуки и запросы статусов.  

🔹 Преимущества 
🚀 Масштабируемость — можно запускать сотни задач одновременно.  
⏳ Неограниченное время выполнения — задачи выполняются асинхронно, без таймаутов.  
🔄 Многошаговые сценарии — поддержка сложных диалогов с ботами.  
📊 Контроль через таблицу — все статусы и ответы видны в реальном времени.  

🔹 Технические детали 
- Использует API ProTalk (replica_webhook_mass и replica_get_reply).  
- Работает в Google Apps Script (триггеры или ручной запуск).  
- Оптимизирован для массовых запросов (пакетная отправка + задержки между проверками).  

📌 Итог 
Этот инструмент превращает Google Таблицу в мощный комбайн для автоматизации любых задач с ботами ProTalk — от рассылок до сложных диалоговых сценариев.  

🚀 Просто добавь задачи в таблицу — остальное сделает скрипт!

Этот пример скрипта будет запускать задачи по вторникам: 

function addGoOnTuesdays() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const range = sheet.getRange("A1:C3");
  const today = new Date();
  if (today.getDay() === 2) {
    range.setValue("go");
  }
}
function processTasks() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const configSheet = ss.getSheetByName("Боты ProTalk");
  const taskSheet = ss.getSheetByName("Задачи");
  
  const taskData = taskSheet.getDataRange().getValues();
  const botConfigs = getBotConfigs(configSheet);
  
  const COLUMNS = {
    EMPLOYEE_ID: 0,
    MESSAGES: 1,
    RESPONSES: 2,
    FLAG: 3,
    STATUS: 4,
    TASK_ID: 5,
    STEP_INDEX: 6,
    CHAT_ID: 7
  };
  
  const tasksToSend = {};
  const repliesToCheck = [];

  for (let i = 1; i < taskData.length; i++) {
    try {
      const row = i + 1;
      const employeeId = taskData[i][COLUMNS.EMPLOYEE_ID];
      const fullMessage = taskData[i][COLUMNS.MESSAGES];
      const currentResponse = taskData[i][COLUMNS.RESPONSES];
      const flag = taskData[i][COLUMNS.FLAG];
      const currentStatus = taskData[i][COLUMNS.STATUS];
      const taskId = taskData[i][COLUMNS.TASK_ID];
      const stepIndex = taskData[i][COLUMNS.STEP_INDEX];
      const chatId = taskData[i][COLUMNS.CHAT_ID];
      
      if (!employeeId || !flag || currentStatus === 'Completed') continue;
      
      const botConfig = botConfigs[employeeId];
      if (!botConfig) continue;
      
      const messages = fullMessage ? fullMessage.split('##').map(m => m.trim()).filter(m => m) : [];
      if (messages.length === 0) continue;
      
      if (!currentStatus || currentStatus.startsWith('Error')) {
        const timestamp = Math.floor(new Date().getTime() / 1).toString();
        const uuid = Utilities.getUuid().split('-')[0];
        const newChatId = `long_task_api_${timestamp}_${employeeId}`;
        const newTaskId = Utilities.getUuid();
        Utilities.sleep(200);
        if (!tasksToSend[employeeId]) {
          tasksToSend[employeeId] = {
            botConfig: botConfig,
            requests: []
          };
        }
        
        tasksToSend[employeeId].requests.push({
          row: row,
          chatId: newChatId,
          taskId: newTaskId,
          message: messages[0],
          stepIndex: 1,
          updates: {
            STATUS: 'Sent',
            TASK_ID: newTaskId,
            STEP_INDEX: 1,
            RESPONSES: '',
            CHAT_ID: newChatId,
            FLAG: 'Task started'
          }
        });
      } 
      else if (currentStatus === 'Sent' || currentStatus === 'Waiting') {
        repliesToCheck.push({
          row: row,
          employeeId: employeeId,
          chatId: chatId,
          taskId: taskId,
          currentResponse: currentResponse,
          stepIndex: stepIndex,
          messages: messages,
          botConfig: botConfig
        });
      }
      
    } catch (error) {
      taskSheet.getRange(i + 1, COLUMNS.STATUS + 1).setValue(`Error: ${error.message}`);
    }
  }
  
  sendBatchMessages(tasksToSend, taskSheet, COLUMNS);
  checkIndividualReplies(repliesToCheck, taskSheet, COLUMNS);
}

function sendBatchMessages(tasksToSend, taskSheet, COLUMNS) {
  for (const [employeeId, data] of Object.entries(tasksToSend)) {
    if (data.requests.length === 0) continue;

    const { botConfig, requests } = data;
    const { apiToken, apiHost } = botConfig;

    const url = `https://${apiHost}/api/v1.0/replica_webhook_mass?` +
      `promt_id=${encodeURIComponent(employeeId)}&` +
      `api_token=${encodeURIComponent(apiToken)}`;

    const payload = requests.map(req => ({
      message: {
        message_id: req.taskId,
        chat: { id: req.chatId },
        text: req.message
      }
    }));

    const options = {
      method: 'post',
      contentType: 'application/json',
      payload: JSON.stringify(payload),
      muteHttpExceptions: true,
      timeout: 1
    };

    try {
      UrlFetchApp.fetch(url, options);
    } catch (error) {}

    data.requests.forEach(req => {
      updateTaskRow(taskSheet, req.row, COLUMNS, req.updates);
    });

    Utilities.sleep(200);
  }
}

function checkIndividualReplies(repliesToCheck, taskSheet, COLUMNS) {
  for (const task of repliesToCheck) {
    try {
      const { botConfig, employeeId, chatId, taskId } = task;
      const reply = getReply(botConfig.apiToken, employeeId, chatId, taskId, botConfig.apiHost);
      
      processReply(
        taskSheet, 
        task.row, 
        COLUMNS, 
        botConfig, 
        employeeId, 
        {
          currentResponse: task.currentResponse,
          stepIndex: task.stepIndex,
          messages: task.messages,
          chatId: chatId,
          taskId: taskId
        }, 
        reply
      );
      
      Utilities.sleep(500);
    } catch (error) {
      taskSheet.getRange(task.row, COLUMNS.STATUS + 1)
        .setValue(`Error checking reply: ${error.message}`);
    }
  }
}

function getReply(apiToken, employeeId, chatId, messageId, apiHost) {
  const url = `https://${apiHost}/api/v1.0/replica_get_reply?` +
    `promt_id=${encodeURIComponent(employeeId)}&` +
    `api_token=${encodeURIComponent(apiToken)}`;
  
  const options = {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify({
      message: {
        message_id: messageId,
        chat: {id: chatId}
      }
    }),
    muteHttpExceptions: true,
    timeout: 5000
  };
  
  const response = UrlFetchApp.fetch(url, options);
  if (response.getResponseCode() === 200) {
    const responseData = JSON.parse(response.getContentText());
    return responseData.message || '';
  } else {
    throw new Error(`API error: ${response.getResponseCode()} - ${response.getContentText()}`);
  }
}

function processReply(taskSheet, row, COLUMNS, botConfig, employeeId, req, reply) {
  if (reply && reply !== '' && !reply.includes('/restart')) {
    const updatedResponse = req.currentResponse ? req.currentResponse + '\n\n---\n\n' + reply : reply;
    taskSheet.getRange(row, COLUMNS.RESPONSES + 1).setValue(updatedResponse);
    
    if (req.stepIndex < req.messages.length) {
      const nextTaskId = Utilities.getUuid();
      const newChatId = req.chatId;
      
      const updates = {
        STATUS: 'Sent',
        TASK_ID: nextTaskId,
        STEP_INDEX: req.stepIndex + 1
      };
      updateTaskRow(taskSheet, row, COLUMNS, updates);
      
      const sendUrl = `https://${botConfig.apiHost}/api/v1.0/replica_webhook?` +
        `promt_id=${encodeURIComponent(employeeId)}&` +
        `api_token=${encodeURIComponent(botConfig.apiToken)}`;
      
      const sendOptions = {
        method: 'post',
        contentType: 'application/json',
        payload: JSON.stringify({
          message: {
            message_id: nextTaskId,
            chat: { id: newChatId },
            text: req.messages[req.stepIndex]
          }
        }),
        muteHttpExceptions: true,
        timeout: 2000
      };
      
      UrlFetchApp.fetch(sendUrl, sendOptions);
    } else {
      taskSheet.getRange(row, COLUMNS.STATUS + 1).setValue('Completed');
    }
  } else {
    const waitingMessage = reply === '' ? 'Waiting for response...' : reply;
    taskSheet.getRange(row, COLUMNS.STATUS + 1).setValue('Waiting');
    taskSheet.getRange(row, COLUMNS.RESPONSES + 1).setValue(waitingMessage);
  }
}

function updateTaskRow(taskSheet, row, COLUMNS, updates) {
  const sheet = taskSheet;
  for (const [colName, value] of Object.entries(updates)) {
    const colIndex = COLUMNS[colName];
    sheet.getRange(row, colIndex + 1).setValue(value);
  }
}

function getBotConfigs(configSheet) {
  const data = configSheet.getDataRange().getValues();
  const botConfigs = {};
  
  for (let i = 1; i < data.length; i++) {
    const employeeId = data[i][0];
    if (employeeId) {
      botConfigs[employeeId] = {
        apiToken: data[i][1],
        apiHost: data[i][2] || 'us1.api.pro-talk.ru'
      };
    }
  }
  
  return botConfigs;
}