July 5, 2023

Создаём телеграм бота для подсчета расходов

Друзья, сегодня статья-урок. Попробуем считать наши расходы лучше, экономить больше. Ну либо просто научимся соединять Телеграм бота и Google Таблицу :)

Концепция такая — мы создаём приватный Телеграм канал, чтобы отправлять в него расходы. Помимо вас, расходы смогут отправлять любые люди, которых вы добавите к каналу.

А причём тут Таблицы, спросите вы? А мы добавим в этот канал Телеграм бота и пусть все расходы отправляет в Таблицу, добавляя к ним дату и время.

Сообщение в канал будем отправлять одним сообщением [сумма] / [на что пошли кровные], а наш бот в канале будет ловить это сообщение и делить его по / и число помещать в одну колонку, а предмет расхода в другую.

масло дешёвое нашел, маргарин, наверное, а вот хлеб дорогой, видимо с семечками :)

Поехали делать.

1) Создавайте Телеграм бота в t.me/botfather и получайте его токен

2) Создавайте канал в Телеграм и добавляйте бота в него как администратора

если сделаете канал "приватным" то его никто не сможет найти через поиск в Телеграм

3) Копируйте нашу Таблицу с кодом и открывайте в копии редактор скриптов.

4) Вставьте в переменную botToken токен вашего Телеграм бота, который вы получили от @botfather

Собственно весь наш код с комментариями (их лучше читать в вашей Таблице)

/*
1) вставляем токен бота
2) публикуем код как веб-приложение (начать развертывание > новое развертывание > веб-приложение > от моего имени (ваш аккаунт) > доступ для всех пользователей)
3) получаем ссылку приложения, вставляем её в webAppUrl
4) запускаем скрипт setWebhook()
5) при любом изменении кода публикуем веб-приложение под новой версией, setWebhook() повторно запускать не надо 
*/

const botToken = '';
const webAppUrl = '';
const telegramUrl = 'https://api.telegram.org/bot' + botToken;

/*
setWebhook просто соединяет 'https://api.telegram.org/bot', токен вашего бота, '/setWebhook?url=' и адрес вашего развернутого приложения в одну ссылку и запрашивает её, тем самым регистрируя отправку всего от вашего бота в адрес вашего приложения
*/
function setWebhook() {
  var response = UrlFetchApp.fetch(telegramUrl + '/setWebhook?url=' + webAppUrl);
  Logger.log(response.getContentText());
};

/*
doPost будет принимать сообщение от телеграм и либо логировать на листе "расходы", либо падать с какой-нибудь ошибкой на листе "ошибки"
*/
function doPost(e) {
  try {
    log(e);
  } catch (err) {
    error(err);
  }
};

/*
LOG принимает объект от doPost, парсит, достаёт сообщение и автора далее делит сообщение на две части по '/', собирает это всё, добавляет дату и вставляет на лист "расходы" в новую строку, если листа с таким названием нет - скрипт его создаст
*/
function log(r) {
  r = JSON.parse(r.postData.contents);
  const message = r.channel_post.text;
  const author_signature = r.channel_post.author_signature;
  const values = [[new Date, author_signature, message, message.split('/')[0], message.split('/')?.[1]]];

  const ss = SpreadsheetApp.getActive();
  const sheet = ss.getSheetByName("расходы") || ss.insertSheet("расходы");

  sheet.insertRowBefore(2)
    .getRange(2, 1, 1, values[0].length)
    .setValues(values);
};

/*
если при попытке распарсить и вставить сообщение происходит что-то не то, то вы увидите эту ошибку на листе "ошибки"
*/
function error(err) {
  const ss = SpreadsheetApp.getActive();
  const sheet = ss.getSheetByName("ошибки") || ss.insertSheet("ошибки");
  const data = [[new Date(), err.message]];
  sheet.getRange(sheet.getLastRow() + 1, 1, data.length, data[0].length).setValues(values);
};

5) Разворачиваем наш код как веб-приложение и вставляем ссылку в webAppUrl

Если не знаете как развернуть код как приложение, вот короткая гифка со звуком.

doPost будет принимать сообщение от вашего Телеграм бота и отправлять либо на лист 'расходы', либо на лист 'ошибки'. Чтобы doPost работал, мы должны развернуть наш скрипт в Таблице как веб-приложение.

6) Запускаем скрипт setWebhook, этот скрипт свяжет адрес нашего веб-приложения и токен бота и Телеграм будет отправлять все, что получит бот в адрес нашего приложения.

Если все ок, то увидите что-то такое:

Объект с сообщением, который будет приходить от Телеграм выглядит как-то так:

{
    channel_post:
    {
        date: 1.688566918E9,
        author_signature: 'Eugeny Namokonov',
        chat:
        {
            type: channel,
            title: speedsheets,
            id: -1.0019,
            username: ''
        },
        sender_chat:
        {
            title: speedsheets,
            type: channel,
            id: -1.001933,
            username: ''
        },
        text: '134 / хлебушек',
        message_id: 7.0
    },
    update_id: 6.64
}

Мы берём из него в функции log только имя автора и само сообщение, но вы можете брать и другие поля.


Всё, теперь пишем в канал сообщения и видим их в Таблице, которую вы развернули как веб-приложение. За это отвечают скрипты doPost + log.

Либо, если что-то пошло не так, то видим в Таблице ошибку на листе "ошибки", за это отвечает doPost + error :)

PS Чтобы увидеть автора сообщения - в настройках Телеграм канала выберите "Sign Messages".

PPS Ну и как обычно - при любом изменении уже опубликованного кода, чтобы новый код попал в веб-приложение и начал работать - приложение надо публиковать под новой (следующей) версией, вебхук при этом пересоздавать не надо.


МЫ:

Канал “Google Таблицы” в Телеграме

Оглавление канала — все статьи

Наш чат в Телеграме

Заказать работу