Таблица в телеграмм как сделать
Очень нравится работать с Мажордомо через Телеграм. Спасибо Eraser’у за чудесный модуль, один из моих любимых, не вызывающий никаких нареканий.
Давно хотелось получать сводную инфу о состоянии всего дома разом, а не продираться через систему многоуровневых меню до нужного элемента.
Тут и статейка Удобный просмотр данных сенсоров через телеграмм от directmann подоспела с нужными решениями.
Но отображение всех датчиков по-строчно в виде клавиатуры как-то не зашло((
Решил сделать лист отчета с выводом инфы по комнатам. Внешний вид — на картинке к блогу.
По-моему, наглядно.
Итак, скрипт:
//SendTeleStatus //Картинки (как их получить, см Примечание и есть отдельный блог и на форуме ) $drop = hex2bin('F09F92A7'); //капля $tmp = hex2bin('F09F8CA1'); //термометр $walk = json_decode('"'.'\ud83d\ude42'.'"'); //ходют $nomove = json_decode('"'.'\ud83d\udeb7'.'"'); //не ходют $green = json_decode('"'.'\ud83d\udc9a'.'"'); //зеленое сердце $yellow = json_decode('"'.'\ud83d\udc9b'.'"');// и т.д. $red = json_decode('"'.'\ud83d\udc94'.'"'); $subj = ''; $subj .= gg('timeNow').''.PHP_EOL.''.gg('somebodyHomeText').PHP_EOL.'. '.PHP_EOL; $subj .= gg('lastSayMessage').PHP_EOL; $subj .='. '.''.PHP_EOL; $subj .= 'Статусы:'.PHP_EOL; $subj .=''; $subj .='Система: ';//.gg('system.stateTitle').PHP_EOL; if(gg('System.stateColor')=='green')< $subj .= $green.PHP_EOL; >else < if(gg('System.stateColor')=='yellow') $subj .= $yellow; if(gg('System.stateColor')=='red') $subj .= $red; $subj .= gg('System.stateDetails').PHP_EOL; >$subj .='Связь : ';//.gg('Communication.stateTitle').PHP_EOL; if(gg('Communication.stateColor')=='green')< $subj .= $green.PHP_EOL; >else < if(gg('Communication.stateColor')=='yellow') $subj .= $yellow; if(gg('Communication.stateColor')=='red') $subj .= $red; $subj .= gg('Communication.stateDetails').PHP_EOL; >$subj .='. '.PHP_EOL.''; $subj .='комнаты '.$tmp.'°С '.$drop.'% '.$walk.PHP_EOL;//заголовок статуса (я подгонял под свой телефон(( $objects = getObjectsByClass("Rooms"); foreach($objects as $obj) < $room = mb_substr(gg($obj['TITLE'].".title")." ",0,12); // тут основная фишка! $room .= mb_substr(gg($obj['TITLE'].".Temperature")." ",0,7); $room .= mb_substr(gg($obj['TITLE'].".Humidity")." ",0,5); if(gg($obj['TITLE'].".SomebodyHere"))< $room .= $walk.gg($obj['TITLE'].".LatestActivityTime"); >else < $room .= $nomove.substr(gg($obj['TITLE'].".LatestActivityTime"),0,5); >$subj .= $room.PHP_EOL; > $subj .= ''; //echo($subj); runScript('SendTelegram', array("message"=>$subj));
Основная фишка статьи — получение псевдотаблицы ограниченными средствами форматирования телеграма.
Это сделано с помощью имитации табуляции моноширинного шрифта телеграма:
$room = mb_substr(gg($obj['TITLE'].".title")." ",0,12);
эта строка делает первую колонку с именами комнат шириной в 12 символов, чтобы следующая колонка выводилась ровненьким столбиком, так же фоматируется температура и влажность.
строка
runScript('SendTelegram', array("message"=>$subj));
отправляет в телегу текст — абсолютно стандартный:
//SendTelegram // params $message = $params['message']; $img = $params['img']; $video = $params['video']; $album = $params['album']; $descr = $params['description']; include_once(DIR_MODULES . 'telegram/telegram.class.php'); $telegram_module = new telegram(); //Если текст if ($message)< $telegram_module->sendMessageToAll($message); > //Если картинка if ($img) < $telegram_module->sendAction($chat_id,"upload_photo"); $telegram_module->sendImageToAll($img,$descr); > //Если кино if ($video) < $telegram_module->sendVideoToAll($video); > //Если альбом if ($album) < $telegram_module->sendAlbumToAll($album,$descr); >
Примечание:
Бот — отправляешь ему смайл, он в ответ его код. @getemojicodebot
Передача данных из «Google Таблиц» в Telegram – это просто!
Вы думаете, что настроить передачу данных из Google Sheets в Telegram – это сложно? На самом деле, всё гораздо проще, чем можно себе представить!
Настройка передачи информации из «Гугл Таблиц» в «Телеграмм» открывает бизнесу, фрилансерам и обычным пользователям массу возможностей и может избавить их от необходимости выполнят рутинные задачи. Зачем тратить время на ручную отправку сообщения о добавлении новых строк в таблицу, когда можно сделать так, чтобы соответствующие уведомления отправлялись автоматически.
Кому могут понадобиться такие возможности и как их реализовать — об этом и пойдет речь ниже.
Кому и зачем нужна интеграция «Телеграмма» с «Гугл Таблицами»?
Рассмотрим только две ситуации, хотя на самом деле их огромное множество. Допустим, у вас есть интернет-магазин, вы пока не используете CRM и фиксируете информацию о заказах и клиентах в «Гугл Таблице». Вам может понадобиться распределить поступающие заказы между ответственными менеджерами. Часто при этом передача данных осуществляется вручную. Если заказов 10-20, то справиться можно, хотя это и потребует дополнительных временных затрат. Но как быть, если в день поступает 50, 100 и больше заказов и идут они из разных источников? Трудно ничего не пропустить и не допустить ошибку.
Другой пример, вы работаете на фрилансе и получаете задачи от клиента в «Гугл Таблицах», чтобы ничего не пропустить нужно постоянно заглядывать в файл или ждать, когда о новых задачах сообщит заказчик. Если оба замотались — пропущена задача и снова потеряно время.
Получается, в обоих случаях ручная рутинная работа и мониторинг отнимают время, которое могло быть потрачено на более важные задачи, и приводит к ошибкам, а это уже упущенная прибыль, репутационные риски.
После настройки автоматизации уведомления об изменениях в таблице будут сразу же приходить в мессенджер ответственному менеджеру или фрилансеру, как в примерах выше. К тому же можно сделать так, чтобы вы могли указать, какие именно данные будут передаваться в мессенджер и при каких условиях.
Но сначала давайте разберемся, как настроить связь таблицы с Telegram с помощью ApiX-Drive на примере упомянутого выше интернет-магазина.
Как связать работу «Google Таблиц» и Telegram с помощью ApiX-Drive?
Не будем останавливаться подробно на регистрации в сервисе, делается это очень просто и быстро, тут сможет разобраться каждый.

После того, как процедура регистрации успешно завершена, заходим в личный кабинет и нажимаем «Создать связь».
Настраиваем Google Sheets
Дальше нужно выбрать систему, из которой будут экспортироваться данные, в нашем случае «Гугл Таблицы».

Указываем, о каком действии будут отправляться уведомления в «Телеграмм». Нам нужно, чтобы приходила информация о новых заказах, поэтому выбираем «Загрузить строки (новые)».

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

Выбираем файл, с которым будем связывать Telegram. ApiX-Drive подгрузит все таблицы с вашего «Гугл Диска», указываем нужную. Если в ней много листов — понадобится указать конкретный лист, с которого системе нужно брать данные.

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

Затем ApiX-Drive предлагает настроить фильтры, если это необходимо. Допустим, нам не интересны заказы с суммой меньше 200 долларов. Их будут обрабатывать в обычном режиме, а менеджеры получат оповещения в «Телеграмм» только о тех, которые равны или больше этой цифры. Так они смогут проследить лично за исполнением крупных заказов.
Как создать бота в телеграм с помощью Google таблицы бесплатно
Основное назначение. Дать возможность любому пользователю быстро запустить телеграм бота со своими данными, размещенными в google таблице. Первый шаг – бот информационный, содержит только текст/кнопки(инлайн) и лонгриды, как ответ на нажатие кнопки. Нажатие на кнопку пробрасывает на лист screen_2…256, который содержит картинку, текст(лонгрид) и кнопку назад.
Порядок работы
1. Создайте бот с помощью @BotFather
2. Создайте копию таблицы https://docs.google.com/spreadsheets/d/1un8_usklBqEPlHbGHSlRcSIXgzinIRL1pLQ2FovXFr0/edit в свой google disk. При создании – поставьте галочку Скопировать настройки доступа
3. Подставьте в таблицу свои данные
4. Для подключения вашей таблице к сервису(активизации бота) – перейдите на лист data, вставьте токен вашего бота в ячейку С2 скопируйте id таблицы в ячейку A2 и перейдите по ссылке в ячейке B2. При успешном подключении вы получите страницу с текстом
——
Table
1un8_usklBqEPlHbGHSlRcSIXgzinIRL1pLQ2FovXFr0
connected successfully.
5. Каждое меню/подменю с сопровождающим текстом создается на отдельном листе
6. Каждый лист (screen_. ) имеет 4 колонки
a. Data – текст сообщения / ссылка на картинку / название кнопки
b. Type – тип сообщения которое посылается пользователю text/img/button
c. Time – сейчас не используется
d. Step – номер листа, на который должна вести кнопка
7. Для переключения между листами используется колонка step. Например, после нажатия пользователя на кнопку HTML step=6 пользователь увидит текст/кнопки с листа screen _6
8. Для ускорения работы бота – все данные из таблицы, кроме страницы log хранятся на сервере сервиса. После изменения данных на любом листе – необходимо обновить данные – для этого перейдите по ссылке из ячейки «data!B2»
9. TODO На странице log ведется база подписчиков бота, с последней активностью(что написал, на что нажал) и номером step на текущий момент. Планируется использование для определения, на каком шаге анкетирования пользователь находится и в дальнейшем – рассылка сообщений, мотивирующих закончить анкетирование.
Замечания по заполнению данных screen_.
1. Все данные из ячеек читаются последовательно A2…A100
2. Желательно меню из кнопок располагать внизу / например А98…А100 — button
3. Inline кнопки должны располагаться после ячейки с текстом / например А2 – text, A3 – button, A4 – button …
4. Количество кнопок любое
Гугл таблица как БД для телеграм бота (запись в таблицу)
Всем привет! Спасибо за интерес к предыдущим постам (раз и два), а сегодня продолжаем дополнять нашего бота функционалом. Сохраним ответы из телеграма от пользователей в гугл таблицу.
Полезное отступление
Сначала я бы хотела сделать пол шага назад и показать, в каком виде мы получаем информацию из телеграма, когда мы кликаем по кнопке, отправляем сообщение боту или любое другое действие. Любая активность пользователя возвращается в виде json пакета.
Например, мое сообщение /start отправляет HTTP POST запрос к веб-приложению (веб-приложение это наш скрипт). Скрипт, в свою очередь, с помощью Simple trigger doPost(e) вернет пакет как в снипете ниже.
< update_id=2.96528127E8, message=< text=/start, entities=[Ljava.lang.Object;@73afdadb, message_id=116.0, from=< first_name=Nadya, language_code=ru, is_bot=false, username=brainwashed_from_rock, >, date=1.680698505E9, chat= < username=brainwashed_from_rock, first_name=Nadya, type=private, >> >
e в doPost(e) означает event. Далее обращаемся к документации и изучаем методы для event. Находим e.postData.contents и используем его для парсинга json-пакета. Функция парсинга у нас уже есть:
function doPost(e) < const update = JSON.parse(e.postData.contents); let msgData = <>if (update.hasOwnProperty('message')) < msgData = < id : update.message.message_id, chat_id : update.message.chat.id, user_name : update.message.from.username, text : update.message.text, is_msg : true >; > sendQuestions(msgData.chat_id); >
В функции я объявляю переменную update, в которую записываю содержание пакета. Далее объявляю объект msgData, проверяю есть ли у переменной update свойство ‘message‘ и записываю в msgData нужные мне значения.
Помимо свойства message могут быть callback_data, edited_message, forwarded_message и так далее. При этом возвращаемый пакет будет содержать разные ключи и вложенность и, соответственно, в парсинге необходимо предусматривать все кейсы, которые нас интересуют.
У нас есть кейс с кнопками, нажатие на какую-либо из них возвращает пакет вида
< update_id=2.96528133E8, callback_query=< chat_instance=-2700514822492676651, message=< text=Say my name. chat=< type=private, username=brainwashed_from_rock, first_name=Nadya >, message_id=121.0, date=1.680698507E9, from=< is_bot=true, username=Testforpost_Bot, first_name=Test for post >, reply_markup= < inline_keyboard=[Ljava.lang.Object;@39c491d8 >>, data=Финн парнишка, from= < username=brainwashed_from_rock, language_code=ru, first_name=Nadya, is_bot=false, >> >
Очевидно, что пакеты различаются и порядок парсинга тоже изменится. Дополним функцию doPost(e) обработкой нажатия кнопки:
function doPost(e) < const update = JSON.parse(e.postData.contents); let msgData = <>if (update.hasOwnProperty('message')) < msgData = < id : update.message.message_id, chat_id : update.message.chat.id, user_name : update.message.from.username, text : update.message.text, date : (update.message.date/86400)+25569.125, is_msg : true >; > else if (update.hasOwnProperty('callback_query')) < msgData = < id : update.callback_query.message.message_id, chat_id : update.callback_query.message.chat.id, user_name : update.callback_query.from.username, first_name : update.callback_query.from.first_name, text : update.callback_query.message.text, date : (update.callback_query.message.date/86400)+25569.125, data : update.callback_query.data, is_button : true >//sendQuestions(msgData.chat_id); >
Сам объект msgData можно дополнять любыми необходимыми вам значениями. В моем примере, помимо некоторых данных из пакета, я добавила идентификаторы is_msg и is_button.
Надеюсь, что в этой части я привела достаточные вводные как работать с пакетами и парсингом.
План минимум
Функцию doPost(e) я оставлю только для парсинга и вызову в ней в последней строке новую функцию dataHandler(msgData). Обозначим ее пока приблизительно, проверив какое событие (event) вернулось — сообщение или кнопка.
function dataHandler(msgData) < if (msgData.is_msg) < sendQuestions(msgData.chat_id); >else if (msgData.is_button) < saveData(msgData) >>
Если бот получил сообщение, отправляем вопросы, если кнопку, сохраняем ответы. Структура таблицы для сохранения ответов следующая:

Функция сохранения ответов saveData(msgData):
function saveData(msgData)
В переменную vals я записываю сохраняемые данные в том порядке, в котором они будут выведены в таблице. На лист usersSheet вставляю новую строку с помощью метода appendRow() и указанием вставляемого массива. Результат выполнения функции приведен на скрине выше во второй строке таблицы.
Далее будем проверять правильность ответов и возвращать пользователю результат. Здесь нам нужно сопоставить сообщение с вопросом из таблицы, затем вопрос из таблицы — с ответами из таблицы Answers и проверить выбранный из 4 вариантов ответ на корректность.
Здесь я бы хотела использовать не текст вопроса, а его ид. Поменяю текст вопроса так, что в начале вопроса будет его ид.

В функции sendQuestions(chat_id) вместо строки send(e[1], chat_id, keyboard) напишу две следующие:
const question = e[0]+'/'+questionsArr.length+': '+e[1] send(question, chat_id, keyboard)
Таким образом, в объекте msgData после нажатия кнопки мы можем спарсить ид вопроса и записать его в таблицу с ответами, изменив функцию saveData(msgData):
function saveData(msgData)
В данном случае, из текста сообщения мы сохраняем только первый символ, что соответствует ид вопроса. Как это выглядит в таблице.

*Если дата записана в виде магических чисел, измените формат ячеек в соответствующей колонке.

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

После ответа бот показывает правильность ответов в тексте кнопок, а в тексте сообщения выводит ответ пользователя и корректность данного ответа.
Для начала обозначим функцию, которая редактирует уже отправленное сообщение:
function editMsg(msg, chat_id, msg_id, keyboard) < const payload = < 'method': 'editMessageText', 'chat_id': String(chat_id), 'message_id': String(msg_id), 'text': msg, 'parse_mode': 'HTML' >if (keyboard) payload.reply_markup = JSON.stringify(keyboard) const data = < 'method': 'post', 'payload': payload, 'muteHttpExceptions': true >UrlFetchApp.fetch('https://api.telegram.org/bot' + token + '/', data); >
Функция использует метод editMessageText, обязательными параметрами являются text, chat_id и message_id. Дополнительно мы можем указать другие параметры, в том числе клавиатуру.
*Чтобы не запутаться, храните функции в разных файлах, разделив их по предназначению. Например, функции для отправки данных в телеграм, глобальные переменные и функция парсинга расположены у меня в разных файлах.

Далее создам еще одну функцию editMessage(msgData), в которой нам нужно сравнить ответ пользователя с вариантами ответов из таблицы, и в зависимости от правильности ответа внести соответствующие правки в текст.
Начнем с ответов из таблицы, записав их в переменную answersArr, что мы уже делали в функции отправки вопросов.
function editMessage(msgData)
Воспользуюсь методом массива .filter(), оставив варианты ответа только для текущего вопроса:
const answersArr = answersSheet.getDataRange().getValues().filter(e => e[0] == msgData.text[0]);
В данном случае я сравниваю первый элемент массива answersArr с первым символом в строке текста сообщения, то есть сопоставляю ид вопроса из таблицы с ответами с ид вопроса из текста сообщения.
Сохраним в переменную curAnswerArr строку из таблицы с ответами, которая соответствует данному пользователем ответу:
const curAnswerArr = answersArr.find(e => e[1] == msgData.data);
Здесь в уже отфильтрованном массиве из 4х вариантов ответов я выбираю один, текст которого равен тексту в кнопке.
Далее отредактирую сам текст сообщения в зависимости от того, правильный был ответ или нет:
let newText = new String(); if (curAnswerArr[2]) newText = msgData.text + '\n\n✅Wow\nТвой ответ: '+msgData.data; else newText = msgData.text + '\n\n❌Nope\nТвой ответ: '+msgData.data;
Если данный пользователем ответ имеет плашку TRUE, то в текст добавляю галочку, или крестик в обратном случае.
И наконец прописываем строку с вызовом функции editMsg() и передаем новый текст сообщения, ид чата, ид сообщения и null для клавиатуры.
editMsg(newText,msgData.chat_id,msgData.id,null);
Вся функция saveData(msgData) представлена ниже:
function editMessage(msgData) < const answersArr = answersSheet.getDataRange().getValues().filter(e =>e[0] == msgData.text[0]); const curAnswerArr = answersArr.find(e => e[1] == msgData.data); let newText = new String(); if (curAnswerArr[2]) newText = msgData.text + '\n\n✅Wow\nТвой ответ: '+msgData.data; else newText = msgData.text + '\n\n❌Nope\nТвой ответ: '+msgData.data; editMsg(newText,msgData.chat_id,msgData.id, null); >
На этом этапе деплоим и проверяем, что все работает:

Клавиатура под сообщением пропала, т.к. в editMsg вместо клавиатуры мы передали null.
Редактирование клавиатуры оставлю читателю для самостоятельного изучения. Может один из моих старых постов поможет
План максимум (advanced)
Перейдем к вопросам в комментах:
- как отправлять вопросы последовательно (следующий вопрос после ответа на предыдущий);
- как отправить свой ответ.
Вопросы, кстати, взаимосвязаны, и добавление любой из логик сопровождается тем, что мы должны отслеживать прогресс прохождения квиза. Го!
*Я не буду погружаться в детали, как делала до этого, иначе чтиво затянется на часы. Прошу понять и принять, что эта часть скорее про дополнительные фичи.
До сих пор мы записывали все клики в таблицу, и моя таблица после нескольких ответов выглядит так:

Сделаем так, чтобы каждое прохождение квиза по-прежнему отражалось в таблице, но каждая попытка конкретного пользователя была в одной строке.
Тогда можно вынести ид вопросов в отдельные колонки. Изменю таблицу Users так, чтобы колонка C стала колонкой progress, что отражает на каком этапе квиза данный пользователь. Названия колонок E-H соответствуют ид вопросов.
*Используйте функцию Transpose для быстрого добавления названий колонок.

Отправка вопросов последовательно
Вернемся к функции отправки вопросов, скопируем ее и переименуем копию в sendQuestion, оригинальная функция вам еще может пригодиться. Также я вынесу формирование клавиатуры в отдельную функцию createKeyboard() и получу следующее:
function sendQuestion(msgData) < const questionsArr = questionsSheet.getDataRange().getValues(); const questionArr = questionsArr.find(e =>e[0] == 'ид вопроса').flat(); const question = questionArr[0]+'/'+questionsArr.length+': ' +questionArr[1]; const keyboard = createKeyboard(questionArr); send(question, msgData.chat_id, keyboard) //const vals = [msgData.chat_id, msgData.user_name, 1, msgData.date] //usersSheet.appendRow(vals); > function createKeyboard(questionArr) < const answersArr = answersSheet.getDataRange().getValues(); let arr = answersArr.filter(el =>el[0] == questionArr[0]) arr = arr.map(el => []) const keyboard = < "inline_keyboard": arr >return keyboard >
Определим, какой именно вопрос является следующим для пользователя на основании его текущей попытки. Передадим nextState (пока обозначим переменную условно) в функцию sendQuestion(msgData, nextState) и проверим последний ли это вопрос из всех возможных или нет
function sendQuestion(msgData, nextState) < const questionsArr = questionsSheet.getDataRange().getValues(); if (nextState e[0] == nextState).flat(); const question = questionArr[0]+'/'+questionsArr.length+': ' +questionArr[1]; const keyboard = createKeyboard(questionArr); send(question, msgData.chat_id, keyboard) > else < const msg = 'Поздравляю! Квиз пройден' send(msg, msgData.chat_id, null) >>
Если вопрос был последним, отправляем поздравительное сообщение.
Разбираемся с этим nextState. Так как все ид просто увеличиваются на 1, то следующий вопрос это последний отправленный ид + 1. А текущее состояние или progress, нужно забрать из таблицы, если пользователь нажал на кнопку.
Добавлю функцию getRow(chat_id), которая по чат ид находит последнюю попытку на вкладке usersSheet.
function getRow(chat_id) < const usersArr = usersSheet.getDataRange().getValues(); const ind = usersArr.findIndex(e =>e[0] == chat_id); if (ind < 0) return null else < const rowArr = usersArr[ind] const rowMap = new Map(); rowMap.set('ind', rowInd) return rowMap; >>
Я решила создать объект Map и внести туда данные о пользователе в виде ключ — значение, что также позволяет сохранить определенную последовательность этих пар.
В rowMap я внесу все ключи и присвою им соответствующие значения. Также нам нужно просматривать массив всех пользователей не с начала, а с конца, т.к. самый «свежий» старт квиза записывается в конец таблицы, поэтому воспользуюсь методом массива .reverse().
function getRow(chat_id) < const usersArr = usersSheet.getDataRange().getValues(); const headerUsersArr = usersArr.shift().flat(); usersArr.reverse(); const ind = usersArr.findIndex(e =>e[0] == chat_id); if (ind < 0) return null else < const rowInd = usersArr.length - ind; const rowArr = usersArr[ind] const rowMap = new Map(); rowMap.set('ind', rowInd) rowArr.forEach((e,i) =>rowMap.set(headerUsersArr[i], e)); return rowMap; > >
headerUsersArr это шапка таблицы, то есть названия колонок. В rowMap при этом запишутся значения в условном виде: . Теперь из этого объекта можно достать текущий прогресс:
function getNextState(rowMap)
Функция для обновления строки в таблице. Я записываю юзернейм (т.к. может менятся), ответ на текущий вопрос, ид следующего вопроса, дату.
function setChatsVals(msgData, progress, rowMap) < rowMap.set("username", msgData.user_name); rowMap.set(rowMap.get("progress"), msgData.data); rowMap.set("progress", progress); rowMap.set("date", msgData.date); const rowArr = new Array(); const iterator = rowMap.values(); rowMap.forEach(() =>rowArr.push(iterator.next().value)); const ind = rowArr.shift(); usersSheet.getRange(ind+1,1,1,rowArr.length).setValues([rowArr]); >
И наконец записываю в нужную строку измененный и трансформированный в массив объект Map.
Теперь изменим dataHandler(msgData) под новую логику:
function dataHandler(msgData) < if (msgData.is_msg) < if (msgData.text == '/start') < saveData(msgData); sendQuestion(msgData,nextState=1); >> else if (msgData.is_button) < editMessage(msgData) const rowMap = getRow(msgData.chat_id); const nextState = getNextState(msgData, rowMap); sendQuestion(msgData, nextState); setChatsVals(msgData, nextState, rowMap); >>
Бот будет реагировать только на сообщения с командой /start или кнопки. Если это старт, то создаем новую строку с данными пользователя и отправляем первый вопрос.
И если кнопка, редактируем текст сообщения, забираем актуальную строку из таблицы Users, определяем следующий вопрос для пользователя и отправляем его. И конечно сохраняем ответ в таблицу.
Отправить свой вариант ответа
Теперь мы можем добавить возможность давать свободный ответ. Пример чата и таблицы ниже.

Изменим setChatsVals(msgData, progress, rowMap, flag):
function setChatsVals(msgData, progress, rowMap, flag) < flag == 'is_button' ? rowMap.set(rowMap.get("progress"), msgData.data) : rowMap.set(rowMap.get("progress"), msgData.text); rowMap.set("username", msgData.user_name); rowMap.set("progress", progress); rowMap.set("date", msgData.date); const rowArr = new Array() const iterator = rowMap.values() rowMap.forEach(() =>rowArr.push(iterator.next().value)) const ind = rowArr.shift(); usersSheet.getRange(ind+1,1,1,rowArr.length).setValues([rowArr]) >
В первую строку я добавила проверку флага на is_button. Если да, записываем в таблицу значение кнопки, если нет, то текст сообщения.
И немного отредактируем dataHandler(msgData):
function dataHandler(msgData) < const rowMap = getRow(msgData.chat_id); if (msgData.is_msg) < if (msgData.text == '/start') < saveData(msgData); sendQuestion(msgData,nextState=1); >else < const nextState = getNextState(rowMap); sendQuestion(msgData, nextState); setChatsVals(msgData, nextState, rowMap, 'is_msg'); >> else if (msgData.is_button) < editMessage(msgData) const nextState = getNextState(rowMap); sendQuestion(msgData, nextState); setChatsVals(msgData, nextState, rowMap, 'is_button'); >>
Здесь в условии is_msg я прописала исключение и включила туда ту же самую логику, как и для кнопки. На этом все!
Заключение
Основная задача, которую я ставила в самом первом посте, а именно «Гугл таблица как база данных», на мой взгляд, выполнена. Мы можем перекидавать данные из гугл таблицы в телеграм чат и из чата в гугл таблицу.
Доработать можно еще много чего на ваш вкус и цвет, внести всякие проверки и прочее. Ссылка на мой бот, для прохождения квиза. Через некоторое время выложу весь код с редактированием кнопок.
