← Вернуться к списку тем

Бот для вывода информации из гугл таблицы по запросу

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

Авторизуйтесь через Telegram, чтобы оставить комментарий.
Откройте по ссылке или QR бот @iMakeBot, нажмите кнопку Старт/Start.
Следуйте инструкциям бота.

  • iMakeBots [3 недели назад]

    Добрый.

    Искать значение по конкретному столбцу?

  • Alex Quiett [3 недели назад → iMakeBots]

    Да, скажем есть столбец телефон. По нему бот ищет совпадения, если находит - передает информацию из 3-4 столбцов соседних, если нет пишет - нет совпадений.

  • iMakeBots [3 недели назад → Alex Quiett]

    Вот этот бот отлично подойдет 

  • Alex Quiett [3 недели назад → iMakeBots]

    Вроде сделал все как там описано, но бот никак не реагирует. И после выполнения в гугле "description":"Webhook is already set"

  • iMakeBots [3 недели назад → Alex Quiett]

    закиньте в бот команду /add

  • iMakeBots [3 недели назад → Alex Quiett]

    После запуска бота направить текстом один из номеров из таблицы, например 89732134578, результат будет

    [{"phone":89732134578,"param_1":"str_2_col_1","param_2":"str_2_col_2","key_row":2}]

    Данные в таблице

    phone	        param_1	        param_2
    89731239823	str_1_col_1	str_1_col_2
    89732134578	str_2_col_1	str_2_col_2

    Код бота

    const config = {
      // токен бота
      token: "", 
      // id файла в инструкции ранее назывался sheet
      file: "",
      // название таблицы
      table: "pages",
      // Телеграм api
      apiUrl: "https://api.telegram.org/bot",
    };
    
    // получим объект таблицы
    const file = SpreadsheetApp.openById(config.file);
    
    /**
     * Обрабатываем POST 
     */
    function doPost(request) {
      // парсим данные
      let update = JSON.parse(request.postData.contents);
      // запускаем обработку
      try {
        // передаем в роутер
        route(update);
      } 
      // перехватываем ошибку
      catch(e) {
        // логируем ошибку
        logger(e.message);
      }
    }
    
    /**
     * Набор команд
     */
    const routers = [
      {
        template: /^\/start$/,
        method: 'start'
      },
    ];
    
    /**
     * Порверим вхождение команды в текстовое значение из телеграма
     */
    function checkRouters(text) {
      // если есть команды
      if (routers.length) {
        // переберем
        for (let router of routers) {
          // если шаблон проходит тест
          if (router.template.test(text)) {
            // ставим флаг проверки в true 
            router.result = true;
            // вернем роутер
            return router;
          }
        }
      }
      // по умолчанию вернем объект с флагом false
      return {
        result: false
      };
    }
    
    /**
     * Роутер
     */
    function route(data) {
      // если это объект сообщения из телеграмма
      if('message' in data) {
        // если это текстовое сообщение
        if('text' in data.message) {
          // получим результат проверки на команду
          const router = checkRouters(data.message.text);
          // если команда 
          if(router.result) {
            // получим параметры
            let params = data.message.text.split("_");
            // удалим первый элемент
            params.shift();
            // вызовем функцию из параметра метод
            (new Function(["data", "params"], "return " + router.method + "(data, params);"))(data, params);
          } else {
            find_by_phone(data)
          }
        }
      } 
    }
    
    /**
     * Выборка данные из таблицы по условию
     * table  таблица выборки
     * params   объект данных для условия, где ключ == заголовку в таблице
     */
    function getRows(table_, params = {}) {
      // получим объект таблицы
      const table = file.getSheetByName(table_);
      // получим все данные из таблицы
      const rows = table.getDataRange().getValues();
      // запомним названия столбцов
      const headers = rows.shift();
      // получим все ключи условий
      const paramsKeys = Object.keys(params);
      // отфильтруем по условию если условия есть
      const data = paramsKeys.length 
        ? rows.filter((line, idx, arr) => {
          // добавим в конец элемента - ключ элемента в массиве строк таблицы
          // далее в объекте он будет под ключем key_row
          arr[idx].push(idx + 1);
          // вернем результат проверки условий
          return (paramsKeys.filter(key => line[headers.findIndex(header => header == key)] == params[key])).length == paramsKeys.length;
        }) 
        : rows;
      // вернем результат массивом объектов
      return setObjects(headers, data);
    }
    
    /**
     * Преобразуем в объекты
     */
    function setObjects(headers, data) {
      // проверим
      if(data.length) {
        // пройдем по массиву и преобразуем элементы в объекты
        return data.map((item) => {
          // создадим новый объект
          let object = {};
          // переберем заголовки и заполним объект данными
          headers.forEach((head, key) => object[head] = item[key]);
          // добавим номер строки - нужен для редактирования или удаления из таблицы
          object.key_row = item.at(-1);
          // вернем объект
          return object;
        });
      }
      // вернем результат
      return data;
    }
    
    /**
     * Старт бота
     */
    function start(data, params) {
        // направим текстовое сообщение пользователю
        sendMessage(data.message.from.id, 'Направьте номер телефона');
    }
    
    /**
     * Найдем результат по телефону
     */
    function find_by_phone(data) {
      // получим результат
      const result = getRows(config.table, {phone: data.message.text});
      // подготовим текст
      const text = result.length 
        ? JSON.stringify(result) 
        : 'Не найдены результаты';
      // выведем пользователю
      sendMessage(data.message.from.id, text);
    }
    
    /**
     * Отправим текстовое сообщение
     */
    function sendMessage(chat_id, text) {
      // подготовим набор данных
      let payload = {
        method: "sendMessage",
        chat_id: String(chat_id),
        text: text,
        parse_mode: "HTML"
      };
      // вернем результат отправки
      return query(payload);
    }
    
    /**
     * Направляем запрос в Телеграм
     */
    function query(payload) {
      let data = {
        method: "post",
        payload: payload
      };
      return JSON.parse(UrlFetchApp.fetch(config.apiUrl + config.token + "/", data).getContentText());
    }
    
    /**
     * Логгирование
     */
    function logger(message, table = "Logs") {
      try {
        // если таблице в файле нет
        if (file.getSheetByName(table) === null) {
          // добавляем таблицу
          file.insertSheet(table);
        }
        // записываем
        file.getSheetByName(table).appendRow([message]);
      } catch (e) {}
    }
  • Alex Quiett [2 недели назад → iMakeBots]

    Не могу понять, у меня почему-то не работает... Вроде все сделал как вы описали. При попытке выполнить getRows, ругается на const rows = table.getDataRange().getValues();