Как отправить сообщение в Telegram из Google Apps Script?

Google Apps Script (GAS) предоставляет мощную платформу для автоматизации задач в экосистеме Google Workspace. Интеграция с Telegram позволяет расширить возможности GAS, добавляя уведомления, оповещения и даже интерактивные элементы через популярный мессенджер.

Зачем отправлять сообщения в Telegram из Google Apps Script?

Интеграция GAS и Telegram открывает множество сценариев:

Мониторинг и оповещения: Мгновенные уведомления о критических изменениях в Google Sheets, новых событиях в Google Calendar, результатах выполнения скриптов.

Отчетность: Автоматическая отправка ежедневных/еженедельных отчетов (например, по данным из Google Analytics, Google Ads, загруженным в Sheets) в指定된 чаты или каналы.

Автоматизация маркетинга: Отправка уведомлений о новых лидах из Google Forms, статусах заказов.

Управление процессами: Инициирование или подтверждение действий (например, запуск другого скрипта) через команды боту.

Необходимые условия: Google Apps Script и Telegram Bot

Для реализации интеграции вам понадобятся:

Аккаунт Google: Для доступа к Google Apps Script.

Базовые знания Google Apps Script: Понимание основ синтаксиса, работы с API и триггерами.

Аккаунт Telegram: Для создания бота и получения сообщений.

Telegram Bot: Необходимо создать специального бота, который будет выступать посредником для отправки сообщений.

Создание и настройка Telegram-бота

Процесс создания и настройки бота осуществляется непосредственно в Telegram с помощью специального бота BotFather.

Создание нового бота через BotFather

Найдите в Telegram бота @BotFather и начните с ним диалог.

Отправьте команду /newbot.

BotFather запросит имя для вашего бота (отображаемое имя).

Затем он запросит username для бота. Username должен быть уникальным и заканчиваться на bot (например, MyGoogleSheetsNotifierBot).

Получение токена бота (API Token)

После успешного создания бота BotFather предоставит вам токен доступа (API Token). Этот токен выглядит как длинная строка символов (например, 1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij).

Важно: Храните токен в секрете. Он предоставляет полный контроль над вашим ботом. Рекомендуется использовать PropertiesService в GAS для безопасного хранения токена, а не хранить его прямо в коде.

/**
 * Сохраняет токен Telegram бота в свойствах скрипта.
 * @param {string} token Токен, полученный от BotFather.
 */
function saveBotToken(token: string): void {
  PropertiesService.getScriptProperties().setProperty('TELEGRAM_BOT_TOKEN', token);
  Logger.log('Токен бота сохранен.');
}

/**
 * Получает сохраненный токен Telegram бота.
 * @returns {string | null} Сохраненный токен или null, если он не найден.
 */
function getBotToken(): string | null {
  return PropertiesService.getScriptProperties().getProperty('TELEGRAM_BOT_TOKEN');
}

Получение Chat ID пользователя или группы

Чтобы бот знал, куда отправлять сообщение, ему нужен идентификатор чата (Chat ID).

Личный чат: Самый простой способ узнать свой Chat ID — найти бота @userinfobot, начать с ним диалог, и он немедленно сообщит ваш ID.

Групповой чат:

Добавьте вашего бота в нужную группу.

Отправьте любое сообщение в группу.

Обратитесь к API Telegram через браузер или curl, используя ваш токен:
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates

В полученном JSON-ответе найдите объект message, затем chat, и в нем поле id. Это и будет Chat ID группы (обычно отрицательное число).

Канал: Аналогично группе, но сначала нужно добавить бота в администраторы канала. ID канала также можно найти через getUpdates (он будет в формате @channelusername или отрицательным числом, если канал приватный и бот добавлен).

Написание кода Google Apps Script для отправки сообщений

Теперь перейдем к написанию кода в среде Google Apps Script.

Создание нового проекта Google Apps Script

Откройте Google Drive.

Создайте новый проект: Создать -> Еще -> Google Apps Script.

Дайте проекту осмысленное имя (например, "Telegram Notifier").

Функция отправки сообщений в Telegram (sendMessage)

Центральным элементом будет функция, инкапсулирующая логику вызова Telegram Bot API.

/**
 * Отправляет текстовое сообщение в указанный чат Telegram.
 *
 * @param {string} chatId Идентификатор чата назначения.
 * @param {string} text Текст сообщения.
 * @param {string | null} [parseMode=null] Режим форматирования ('MarkdownV2', 'HTML').
 * @param {boolean} [disableNotification=false] Отправить сообщение без звукового уведомления.
 * @returns {GoogleAppsScript.URL_Fetch.HTTPResponse | null} Ответ от API Telegram или null в случае ошибки.
 */
function sendMessage(chatId: string, text: string, parseMode: string | null = null, disableNotification: boolean = false): GoogleAppsScript.URL_Fetch.HTTPResponse | null {
  const token: string | null = getBotToken();
  if (!token) {
    Logger.log('Ошибка: Токен бота не найден в ScriptProperties.');
    return null;
  }

  const telegramApiUrl: string = `https://api.telegram.org/bot${token}/sendMessage`;

  const payload: { [key: string]: any } = {
    chat_id: chatId,
    text: text,
    disable_notification: disableNotification
  };

  // Добавляем parse_mode только если он указан
  if (parseMode && (parseMode === 'MarkdownV2' || parseMode === 'HTML')) {
    payload.parse_mode = parseMode;
  }

  const options: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions = {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify(payload),
    muteHttpExceptions: true // Важно для обработки ошибок API
  };

  try {
    const response: GoogleAppsScript.URL_Fetch.HTTPResponse = UrlFetchApp.fetch(telegramApiUrl, options);
    Logger.log(`Ответ API Telegram: ${response.getResponseCode()} ${response.getContentText()}`);
    return response;
  } catch (error) {
    if (error instanceof Error) {
        Logger.log(`Ошибка при вызове UrlFetchApp: ${error.message}`);
    } else {
        Logger.log(`Неизвестная ошибка при вызове UrlFetchApp: ${error}`);
    }
    return null;
  }
}

Пример кода: отправка простого текстового сообщения

Используем созданную функцию sendMessage для отправки уведомления.

/**
 * Пример отправки простого уведомления.
 */
function sendTestNotification(): void {
  // Замените на ваш реальный Chat ID
  const targetChatId: string = 'YOUR_CHAT_ID'; 
  // Убедитесь, что токен сохранен через saveBotToken()
  // saveBotToken('YOUR_BOT_TOKEN'); 

  if (!targetChatId || targetChatId === 'YOUR_CHAT_ID') {
      Logger.log('Ошибка: Укажите корректный Chat ID в переменной targetChatId.');
      return;
  }

  const messageText: string = 'Тестовое сообщение из Google Apps Script!';
  const response = sendMessage(targetChatId, messageText);

  if (response && response.getResponseCode() === 200) {
    Logger.log('Сообщение успешно отправлено.');
  } else {
    Logger.log('Не удалось отправить сообщение.');
  }
}

Обработка ошибок и логирование

Ключевой момент — параметр muteHttpExceptions: true в UrlFetchApp.fetch. Он позволяет скрипту не прерываться при ошибках API (например, неверный chat_id, слишком длинное сообщение), а получить ответ с кодом ошибки от Telegram.

Всегда проверяйте response.getResponseCode(). Код 200 означает успех. Другие коды (например, 400, 401, 403) указывают на проблему. Содержимое ответа (response.getContentText()) часто содержит описание ошибки от Telegram API.

Реклама

Используйте Logger.log() для отладки и мониторинга работы скрипта.

Продвинутые возможности: форматирование и отправка разных типов сообщений

Telegram Bot API позволяет не только отправлять простой текст.

Форматирование текста сообщений (Markdown, HTML)

Передайте параметр parseMode в функцию sendMessage со значением 'MarkdownV2' или 'HTML', чтобы использовать соответствующую разметку.

MarkdownV2: Использует синтаксис, похожий на Markdown. Специальные символы (_, *, [, ], (, ), ~, `, >, #, +, -, =, |, {, }, ., !) должны быть экранированы символом \.

HTML: Поддерживает ограниченный набор HTML-тегов: <b>, <i>, <u>, <s>, <tg-spoiler>, <a href="...">, <code>, <pre>.

/**
 * Пример отправки отформатированного сообщения (статистика кампании).
 */
function sendFormattedReport(): void {
  const targetChatId: string = 'YOUR_CHAT_ID'; 
  const campaignName: string = 'Весенняя распродажа 2024';
  const clicks: number = 1520;
  const conversions: number = 85;
  const cost: number = 540.75;

  // Формируем сообщение с использованием HTML
  const messageText: string = 
    `Отчет по кампании: ${campaignName}\n\n` +
    `Клики: ${clicks}\n` +
    `Конверсии: ${conversions}\n` +
    `Расход: ${cost.toFixed(2)} USD\n\n` +
    `Перейти в Google Ads`;

  sendMessage(targetChatId, messageText, 'HTML');
}

Отправка изображений и документов

Для отправки файлов используются другие методы API Telegram (sendPhoto, sendDocument). Это требует формирования multipart/form-data запроса, что несколько усложняет код по сравнению с sendMessage.

/**
 * Отправляет изображение в указанный чат Telegram.
 *
 * @param {string} chatId Идентификатор чата назначения.
 * @param {GoogleAppsScript.Base.BlobSource} imageBlob Blob изображения для отправки.
 * @param {string}  Подпись к изображению.
 * @returns {GoogleAppsScript.URL_Fetch.HTTPResponse | null} Ответ от API Telegram или null в случае ошибки.
 */
function sendPhoto(chatId: string, imageBlob: GoogleAppsScript.Base.BlobSource, caption?: string): GoogleAppsScript.URL_Fetch.HTTPResponse | null {
  const token: string | null = getBotToken();
  if (!token) {
    Logger.log('Ошибка: Токен бота не найден.');
    return null;
  }
  const telegramApiUrl: string = `https://api.telegram.org/bot${token}/sendPhoto`;

  const payload: { [key: string]: any } = {
    chat_id: chatId,
    photo: imageBlob // Передаем Blob напрямую
  };
  if (caption) {
      payload.caption = caption;
  }

  const options: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions = {
    method: 'post',
    payload: payload, // GAS сам формирует multipart/form-data
    muteHttpExceptions: true
  };

  try {
    const response: GoogleAppsScript.URL_Fetch.HTTPResponse = UrlFetchApp.fetch(telegramApiUrl, options);
    Logger.log(`Ответ API Telegram (sendPhoto): ${response.getResponseCode()} ${response.getContentText()}`);
    return response;
  } catch (error) {
     if (error instanceof Error) {
        Logger.log(`Ошибка при вызове UrlFetchApp (sendPhoto): ${error.message}`);
    } else {
        Logger.log(`Неизвестная ошибка при вызове UrlFetchApp (sendPhoto): ${error}`);
    }
    return null;
  }
}

/**
 * Пример отправки изображения из Google Drive.
 */
function sendImageFromDrive(): void {
  const targetChatId: string = 'YOUR_CHAT_ID';
  const fileId: string = 'YOUR_DRIVE_FILE_ID'; // ID файла изображения в Google Drive

  try {
      const file = DriveApp.getFileById(fileId);
      const imageBlob = file.getBlob();
      sendPhoto(targetChatId, imageBlob, 'График конверсий за неделю');
  } catch (e) {
      Logger.log(`Не удалось получить файл из Drive: ${e}`);
      sendMessage(targetChatId, 'Не удалось отправить изображение: ошибка доступа к файлу.');
  }
}

Использование клавиатур (InlineKeyboardMarkup)

Клавиатуры (InlineKeyboardMarkup) позволяют добавлять кнопки к сообщениям, делая взаимодействие интерактивным. Кнопки могут содержать ссылки, callback-данные (для обработки ботом) и т.д.

Добавление клавиатуры осуществляется через параметр reply_markup в sendMessage или других методах отправки.

// ... внутри функции sendMessage или аналогичной ...

  const keyboard = {
    inline_keyboard: [
      [
        { text: 'Подробнее...', url: 'https://example.com/report' },
        { text: 'Архивировать', callback_data: 'archive_report_123' } 
      ]
    ]
  };

  payload.reply_markup = JSON.stringify(keyboard);

// ... остальной код отправки запроса ...

Примечание: Обработка callback_data требует настройки вебхука для бота, что выходит за рамки данной статьи.

Автоматизация отправки сообщений: триггеры и расписания

Сила GAS заключается в возможности автоматического выполнения скриптов по расписанию или в ответ на события.

Использование триггеров Google Apps Script для автоматической отправки

Триггеры настраиваются в редакторе скриптов (Редактировать -> Триггеры текущего проекта):

Триггеры по времени (Time-driven): Запускают функцию через определенные интервалы (минуты, часы, дни, недели).

Триггеры на события (Event-driven):

onOpen(e): При открытии документа/таблицы.

onEdit(e): При редактировании ячейки в Google Sheets.

onInstall(e): При установке дополнения.

Триггеры Google Forms (onSubmit): При отправке формы.

Триггеры Google Calendar: При обновлении событий.

Примеры: отправка уведомлений о событиях в Google Sheets, Google Calendar

Ежедневный отчет из Google Sheets: Создайте функцию, которая собирает данные из таблицы (например, сводку по рекламным расходам за вчерашний день), форматирует их и отправляет через sendMessage. Настройте триггер по времени на ежедневный запуск этой функции.

/**
 * Собирает данные из Google Sheets и отправляет отчет в Telegram.
 */
function sendDailySheetReport(): void {
  const targetChatId: string = 'YOUR_CHAT_ID';
  // Предполагается, что таблица с ID 'YOUR_SHEET_ID' существует
  // и на листе 'DailyStats' есть данные в A1:B5
  try {
    const ss = SpreadsheetApp.getActiveSpreadsheet(); // Или SpreadsheetApp.openById('YOUR_SHEET_ID');
    const sheet = ss.getSheetByName('DailyStats');
    if (!sheet) {
        Logger.log('Лист DailyStats не найден.');
        sendMessage(targetChatId, 'Ошибка: Не найден лист DailyStats для отчета.');
        return;
    }
    const dataRange = sheet.getRange('A1:B5');
    const values = dataRange.getDisplayValues();

    let reportText = 'Ежедневный отчет:\n';
    values.forEach(row => {
      reportText += `${row[0]}: ${row[1]}\n`;
    });

    sendMessage(targetChatId, reportText, 'HTML');

  } catch (e) {
    Logger.log(`Ошибка при формировании отчета из Sheets: ${e}`);
    sendMessage(targetChatId, `Ошибка при создании отчета: ${e.message}`);
  }
}

// Далее настройте Time-driven триггер для вызова sendDailySheetReport()

Уведомление о событии Google Calendar: Создайте триггер на обновление календаря, который вызывает функцию, проверяющую новые/измененные события и отправляющую уведомление в Telegram.

Лучшие практики по управлению триггерами и квотами

Квоты Google Apps Script: Помните об ограничениях GAS (время выполнения скрипта, количество вызовов UrlFetchApp, частота триггеров). Ознакомьтесь с актуальными квотами в документации Google.

Оптимизация: Минимизируйте количество вызовов внешних сервисов (включая Telegram API) внутри циклов. Используйте CacheService для кэширования часто запрашиваемых данных.

Обработка ошибок триггеров: Настройте уведомления об ошибках выполнения триггеров (в настройках триггера), чтобы оперативно узнавать о сбоях.

Безопасность: Не храните токены и Chat ID непосредственно в коде. Используйте PropertiesService.

Telegram API Limits: Учитывайте лимиты Telegram на частоту отправки сообщений ботом, особенно в группы.

Интеграция Google Apps Script и Telegram — это гибкий инструмент для автоматизации уведомлений и рабочих процессов. Следуя приведенным шагам и рекомендациям, вы сможете эффективно использовать возможности обеих платформ.


Добавить комментарий