Skip to content

Instantly share code, notes, and snippets.

@gtchakama
Created November 15, 2024 06:48
Show Gist options
  • Save gtchakama/822fd0d8efc90b369a8f33000d28fd08 to your computer and use it in GitHub Desktop.
Save gtchakama/822fd0d8efc90b369a8f33000d28fd08 to your computer and use it in GitHub Desktop.
Google App Script - Telegram Notifications
// Configuration
const CONFIG = {
BOT_TOKEN: ':',
CHAT_ID: '',
IMPORTANT_SENDERS: [
'[email protected]', '[email protected]',
],
KEYWORDS: ['urgent', 'important', 'deadline'],
CHECK_INTERVAL_MINUTES: 5,
REMINDER_INTERVALS: [3, 10, 30, 60, 180, 300, 600] // in minutes
};
// Properties to store information about sent notifications
const SCRIPT_PROPERTIES = PropertiesService.getScriptProperties();
function sendToTelegram(message) {
const telegramUrl = `https://api.telegram.org/bot${CONFIG.BOT_TOKEN}/sendMessage`;
if (!message || message.trim() === '') {
Logger.log('Error: Message is empty');
return;
}
const payload = {
'chat_id': CONFIG.CHAT_ID,
'text': message,
'parse_mode': 'HTML'
};
const options = {
'method': 'post',
'contentType': 'application/json',
'payload': JSON.stringify(payload),
'muteHttpExceptions': true
};
try {
const response = UrlFetchApp.fetch(telegramUrl, options);
Logger.log('Telegram API response: ' + response.getContentText());
} catch (error) {
Logger.log('Error sending message to Telegram: ' + error);
}
}
function checkEmails() {
const threads = GmailApp.getInboxThreads(0, 20); // Check the latest 20 threads
if (threads.length === 0) {
Logger.log('No email threads found');
return;
}
const currentTime = new Date().getTime();
let newEmailFound = false;
threads.forEach(thread => {
const messages = thread.getMessages();
const latestMessage = messages[messages.length - 1];
if (latestMessage.isUnread()) {
const subject = latestMessage.getSubject() || '(No Subject)';
const sender = latestMessage.getFrom() || '(Unknown Sender)';
const snippet = latestMessage.getPlainBody()?.substring(0, 100) + '...' || '(No Body)';
const attachments = latestMessage.getAttachments();
if (isImportantEmail(sender, subject, snippet)) {
const messageId = latestMessage.getId();
const storedNotification = SCRIPT_PROPERTIES.getProperty(messageId);
if (!storedNotification) {
newEmailFound = true;
const telegramMessage = formatTelegramMessage(sender, subject, snippet, attachments);
sendToTelegram(telegramMessage);
// Store the notification time and message details
SCRIPT_PROPERTIES.setProperty(messageId, JSON.stringify({
notificationTime: currentTime,
sender: sender,
subject: subject,
snippet: snippet,
reminderIndex: 0
}));
}
}
}
});
sendReminders(currentTime);
}
function sendReminders(currentTime) {
const properties = SCRIPT_PROPERTIES.getProperties();
for (let messageId in properties) {
const storedData = JSON.parse(properties[messageId]);
const timeSinceNotification = currentTime - storedData.notificationTime;
const reminderIndex = storedData.reminderIndex || 0;
if (reminderIndex < CONFIG.REMINDER_INTERVALS.length) {
const nextReminderInterval = CONFIG.REMINDER_INTERVALS[reminderIndex] * 60 * 1000; // Convert to milliseconds
if (timeSinceNotification >= nextReminderInterval) {
const reminderMessage = formatReminderMessage(storedData.sender, storedData.subject, storedData.snippet, reminderIndex);
sendToTelegram(reminderMessage);
// Update the notification time and increment the reminder index
storedData.notificationTime = currentTime;
storedData.reminderIndex = reminderIndex + 1;
SCRIPT_PROPERTIES.setProperty(messageId, JSON.stringify(storedData));
}
}
}
}
function formatReminderMessage(sender, subject, snippet, reminderIndex) {
let message = `<b>Reminder ${reminderIndex + 1}: Unopened Important Email</b>\n\n`;
message += `<b>From:</b> ${escapeHtml(sender)}\n`;
message += `<b>Subject:</b> ${escapeHtml(subject)}\n\n`;
message += `<b>Preview:</b> ${escapeHtml(snippet)}\n\n`;
message += `<i>This email is still unopened. Please check your inbox.</i>`;
return message;
}
function isImportantEmail(sender, subject, body) {
// Check if sender is in the important senders list
if (CONFIG.IMPORTANT_SENDERS.some(s => sender.includes(s))) {
return true;
}
// Check if any keywords are in the subject or body
const fullText = (subject + ' ' + body).toLowerCase();
if (CONFIG.KEYWORDS.some(keyword => fullText.includes(keyword.toLowerCase()))) {
return true;
}
return false;
}
function formatTelegramMessage(sender, subject, snippet, attachments) {
let message = `<b>New Important Email</b>\n\n`;
message += `<b>From:</b> ${escapeHtml(sender)}\n`;
message += `<b>Subject:</b> ${escapeHtml(subject)}\n\n`;
message += `<b>Preview:</b> ${escapeHtml(snippet)}\n\n`;
if (attachments.length > 0) {
message += `<b>Attachments:</b>\n`;
attachments.forEach(attachment => {
message += `- ${escapeHtml(attachment.getName())} (${formatBytes(attachment.getSize())})\n`;
});
}
return message;
}
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
function formatBytes(bytes, decimals = 2) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
function setupTrigger() {
// Delete existing triggers
const triggers = ScriptApp.getProjectTriggers();
triggers.forEach(trigger => ScriptApp.deleteTrigger(trigger));
// Create a new trigger
ScriptApp.newTrigger('checkEmails')
.timeBased()
.everyMinutes(CONFIG.CHECK_INTERVAL_MINUTES)
.create();
Logger.log(`Trigger set to run every ${CONFIG.CHECK_INTERVAL_MINUTES} minutes`);
}
// Test function
function testTelegramIntegration() {
sendToTelegram('This is a test message from your enhanced Google Apps Script.');
}
// Function to clear all stored properties (use cautiously)
function clearAllProperties() {
SCRIPT_PROPERTIES.deleteAllProperties();
Logger.log('All stored properties have been cleared.');
}
@gtchakama
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment