Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] Add telegram notification webhook when new messages are detected #1056

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
86 changes: 86 additions & 0 deletions lib/telegram_webhook.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

/**
* Webhook
* @package framework
* @subpackage webhook
*/

class Hm_Telegram_Webhook {

const PREFIX_URI = 'https://api.telegram.org/';

/**
* send telegram notiofication using curl
* @param int $msg_count
* @param string $email_to
* @param string $webhook_token
*/
public static function send($msg_count, $email_to, $webhook_token) {
self::delete_webhook($webhook_token);
// Get the chat ID
$chatId = self::get_chat_id($webhook_token);
if (!empty($chatId)) {
$text = "You have received: $msg_count unread email.s\nTo: $email_to";
$curl_handle = Hm_Functions::c_init();
Hm_Functions::c_setopt($curl_handle, CURLOPT_URL, static::PREFIX_URI.'bot'.$webhook_token.'/sendMessage');
Hm_Functions::c_setopt($curl_handle, CURLOPT_POST, true);
Hm_Functions::c_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
Hm_Functions::c_setopt($curl_handle, CURLOPT_POSTFIELDS, http_build_query(['chat_id' => $chatId, 'text' => $text]));
Hm_Functions::c_setopt($curl_handle, CURLOPT_HTTPHEADER, ["Content-Type: application/x-www-form-urlencoded"]);
$curl_result = Hm_Functions::c_exec($curl_handle);
if (trim($curl_result)) {
$response_data = json_decode($curl_result, true);
if (!$response_data['ok']) {
Hm_Debug::add("ERRMessage not sent: ".$response_data['description']);
}
}
}else{
Hm_Debug::add('No chat found, please check your token.');
}
}

/**
* get the chat ID using webhook_token
* @param string $webhook_token
*/
public static function get_chat_id($webhook_token) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, static::PREFIX_URI . 'bot' . $webhook_token . '/getUpdates');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$curl_result = curl_exec($ch);

if ($curl_result === false) {
Hm_Msgs::add('cURL Error: ' . curl_error($ch) . '<br>');
curl_close($ch);
return '';
}

curl_close($ch);
if (trim($curl_result)) {
$response_data = json_decode($curl_result, true);
// Log the decoded response data for debugging
if (isset($response_data['result'][0]['message']['chat']['id']) && !empty($response_data['result'][0]['message']['chat']['id'])) {
$chatId = $response_data['result'][0]['message']['chat']['id'];
return $chatId;
} else {
Hm_Debug::add('ERRNo messages found. Please send a message to your bot first.<br>');
return '';
}
}
}

/**
* This function is usefull when trying to resend, we need to delete old webhook before we send a new one
* delete the webhook using webhook_token if there is one
* sometimes the webhook is not deleted, so we need to delete it manually
* and sometines we are gettiting not found error
* @param string $webhook_token
*/
public static function delete_webhook($webhook_token) {
$curl_handle = Hm_Functions::c_init();
Hm_Functions::c_setopt($curl_handle, CURLOPT_URL, static::PREFIX_URI.'bot'.$webhook_token.'/delete_webhook');
Hm_Functions::c_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
Hm_Functions::c_exec($curl_handle);
}
}
14 changes: 14 additions & 0 deletions modules/core/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,20 @@ function max_source_setting_callback($val) {
return $val;
}}

/**
* Sanitize a default value for interval webhook notifications
* @subpackage core/functions
* @param int $val request interval
* @return sanitized interval
*/
if (!hm_exists('interval_webhook_notification_setting_callback')) {
function interval_webhook_notification_setting_callback($val) {
if ($val < 1) {
return DEFAULT_INTERVAL_WEBHOOK_NOTIFICATION;
}
return $val;
}}

/**
* Save user settings from the session to permanent storage
* @subpackage core/functions
Expand Down
1 change: 1 addition & 0 deletions modules/core/handler_modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ public function process() {
}
$this->out('mailto_handler', $this->user_config->get('mailto_handler_setting', false));
$this->out('warn_for_unsaved_changes', $this->user_config->get('warn_for_unsaved_changes_setting', false));
$this->out('telegram_webhook_interval', $this->user_config->get('interval_webhook_notification_setting', false));
$this->out('no_password_save', $this->user_config->get('no_password_save_setting', false));
if (!strstr($this->request->server['REQUEST_URI'], 'page=') && $this->page == 'home') {
$start_page = $this->user_config->get('start_page_setting', false);
Expand Down
1 change: 1 addition & 0 deletions modules/core/modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
define('MAX_PER_SOURCE', 1000);
define('DEFAULT_PER_SOURCE', 20);
define('DEFAULT_MAX_GOOGLE_CONTACTS_NUMBER', 500);
define('DEFAULT_INTERVAL_WEBHOOK_NOTIFICATION', 5);
define('DEFAULT_SINCE', '-1 week');
define('DEFAULT_SEARCH_FLD', 'TEXT');

Expand Down
1 change: 1 addition & 0 deletions modules/core/output_modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ protected function output() {
'var hm_web_root_path = function() { return "'.WEB_ROOT.'"; };'.
'var hm_flag_image_src = function() { return "<i class=\"bi bi-star-half\"></i>"; };'.
'var hm_check_dirty_flag = function() { return '.($this->get('warn_for_unsaved_changes', '') ? '1' : '0').'; };'.
'var hm_telegram_webhook_interval = function() { return '.$this->get('telegram_webhook_interval', '').'; };'.
format_data_sources($this->get('data_sources', array()), $this);

if (!$this->get('disable_delete_prompt')) {
Expand Down
48 changes: 47 additions & 1 deletion modules/core/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -1799,6 +1799,24 @@ var reset_default_value_checkbox = function() {
}
};

var reset_default_value_input_webhook_token = function() {
let field = this.parentElement.parentElement.querySelector('input[type="text"]');
const defaultValue = field.getAttribute("data-default-value");

if (field.disabled == false) {
this.style.transform = "scaleX(1)";
this.parentElement.setAttribute("restore_aria_label", hm_trans("Restore current value"));
field.setAttribute("current_value", field.value);
field.value = defaultValue; // Use the default value (which is now an empty string)
field.disabled = true;
} else {
this.style.transform = "scaleX(-1)";
this.parentElement.setAttribute("restore_aria_label", hm_trans("Restore default value"));
field.value = field.getAttribute("current_value");
field.disabled = false;
}
};

var reset_default_value_select = function() {
let field = this.parentElement.parentElement.firstChild;
let tab_static_default_value = {"inline_message_style" : 0, "smtp_compose_type" : 0, "theme_setting" : 0,
Expand Down Expand Up @@ -1860,6 +1878,32 @@ var reset_default_value_input = function() {
}
};

var reset_default_value_input_interval_webhook_notification = function() {
let field = this.parentElement.parentElement.firstChild;
const defaultValue = this.getAttribute("default-value");

if (this.style.transform == "scaleX(1)") {
this.style.transform = "scaleX(-1)";
this.parentElement.setAttribute("restore_aria_label",hm_trans("Restore default value"))
field.value = field.getAttribute("current_value");
field.style.backgroundColor = "#fff";
field.style.pointerEvents = "auto";
field.style.touchAction = "auto";
}
else {
this.style.transform = "scaleX(1)";
this.parentElement.setAttribute("restore_aria_label",hm_trans("Restore current value"));
field.setAttribute("current_value", field.value);
field.value = 5;
if(defaultValue) {
field.value = defaultValue;
}
field.style.backgroundColor = "#eee";
field.style.pointerEvents = "none";
field.style.touchAction = "none";
}
};

var decrease_servers = function(section) {
const element = document.querySelector(`.server_count .${section}_server_count`);
const value = parseInt(element.textContent);
Expand Down Expand Up @@ -1942,6 +1986,8 @@ $(function() {
$('.reset_default_value_checkbox').on("click", reset_default_value_checkbox);
$('.reset_default_value_select').on("click", reset_default_value_select);
$('.reset_default_value_input').on("click", reset_default_value_input);
$('.reset_default_value_input_webhook_token').on("click", reset_default_value_input_webhook_token);
$('.reset_default_value_input_interval_webhook_notification').on("click", reset_default_value_input_interval_webhook_notification);
}

if (hm_check_dirty_flag()) {
Expand Down Expand Up @@ -2602,7 +2648,7 @@ const observeMessageTextMutationAndHandleExternalResources = (inline) => {
if (mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach(function (node) {
if (node.classList.contains('msg_text_inner')) {
handleExternalResources(inline);
handleExternalResources(inline);
}
});
}
Expand Down
2 changes: 1 addition & 1 deletion modules/feeds/hm-feed.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ function get_feed_data($url) {
}
switch ($type) {
case 'curl':
$curl_handle=curl_init();
$curl_handle = curl_init();
curl_setopt($curl_handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36");
curl_setopt($curl_handle, CURLOPT_URL, $url);
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT,15);
Expand Down
42 changes: 41 additions & 1 deletion modules/imap/handler_modules.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<?php

/**
* IMAP modules
* @package modules
Expand All @@ -8,6 +7,7 @@

if (!defined('DEBUG_MODE')) { die(); }

require_once APP_PATH .'lib/telegram_webhook.php';

/**
* Check for attachments when forwarding a message
Expand Down Expand Up @@ -93,6 +93,33 @@ public function process() {
}
}

/**
* Process input from the interval webhook notification setting in the settings page
* @subpackage imap/handler
*/
class Hm_Handler_process_interval_webhook_notification_setting extends Hm_Handler_Module {
/**
* Allowed values are greater than zero
*/
public function process() {
process_site_setting('interval_webhook_notification', $this, 'interval_webhook_notification_setting_callback', DEFAULT_INTERVAL_WEBHOOK_NOTIFICATION);
}
}

/**
* Process input from the webhook token setting in the settings page
* @subpackage imap/handler
*/
class Hm_Handler_process_webhook_token_setting extends Hm_Handler_Module {
/**
* Allowed values for webhook token
*/
public function process() {
function webhook_token_callback($val) { return $val; }
process_site_setting('webhook_token', $this, 'webhook_token_callback', false, true);
}
}

/**
* Process input from the max google contacts input in the settings page
* @subpackage imap/handler
Expand Down Expand Up @@ -1304,6 +1331,19 @@ public function process() {
$this->out('folder_status', $status);
$this->out('imap_unread_data', $msg_list);
$this->out('imap_server_ids', $form['imap_server_ids']);

}
}
}

class Hm_Handler_send_telegram_webhook extends Hm_Handler_Module {
public function process() {
list($success, $form) = $this->process_form(array('unread_message_count'));
if ($success) {
$webhook_token = $this->user_config->get('webhook_token_setting');
if ($form['unread_message_count'] && !empty($webhook_token)) {
Hm_Telegram_Webhook::send($form['unread_message_count'], $this->config->get('app_name'), $webhook_token);
}
}
}
}
Expand Down
42 changes: 42 additions & 0 deletions modules/imap/output_modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,48 @@ protected function output() {
}
}

/**
* Option to set the interval webhook notification for the settings page
* @subpackage imap/output
*/
class Hm_Output_interval_webhook_notification_setting extends Hm_Output_Module {
protected function output() {
$settings = $this->get('user_settings', array());
$per_page = 5;
$reset = '';
if (array_key_exists('interval_webhook_notification', $settings)) {
$per_page = $settings['interval_webhook_notification'];
}
if ($per_page != 5) {
$reset = '<span class="tooltip_restore" restore_aria_label="Restore default value"><i class="bi bi-arrow-repeat refresh_list reset_default_value_input_interval_webhook_notification"></i></span>';
}
return '<tr class="general_setting"><td><label for="interval_webhook_notification">'.
$this->trans('Interval webhook notification(minutes)').'</label></td><td><input class="form-control form-control-sm w-auto" type="text" id="interval_webhook_notification" '.
'name="interval_webhook_notification" value="'.$this->html_safe($per_page).'" />'.$reset.'</td></tr>';
}
}

/**
* Option to set the webhook token for the settings page
* @subpackage imap/output
*/
class Hm_Output_webhook_token_setting extends Hm_Output_Module {
protected function output() {
$settings = $this->get('user_settings', array());
$webhook_token = '';
$reset = '';
if (array_key_exists('webhook_token', $settings)) {
$webhook_token = $settings['webhook_token'];
}
if (!empty($webhook_token)) {
$reset = '<span class="tooltip_restore" restore_aria_label="Restore default value"><i class="bi bi-arrow-repeat refresh_list reset_default_value_input_webhook_token"></i></span>';
}
return '<tr class="general_setting"><td><label for="webhook_token">'.
$this->trans('Webhook telegram token').'</label></td><td><input class="form-control form-control-sm w-auto" type="text" id="webhook_token" '.
'name="webhook_token" value="'.$this->html_safe($webhook_token).'" data-default-value="" />'.$reset.'</td></tr>';
}
}

/**
* Option to set number of google contacts
* @subpackage imap/output
Expand Down
13 changes: 12 additions & 1 deletion modules/imap/setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
add_handler('settings', 'process_enable_simple_download_options', true, 'imap', 'date', 'after');
add_handler('settings', 'process_unread_on_open', true, 'imap', 'date', 'after');
add_handler('settings', 'process_imap_per_page_setting', true, 'imap', 'date', 'after');
add_handler('settings', 'process_webhook_token_setting', true, 'imap', 'save_user_settings', 'before');
add_handler('settings', 'process_interval_webhook_notification_setting', true, 'imap', 'date', 'after');
add_handler('settings', 'process_max_google_contacts_number', true, 'imap', 'date', 'after');
add_handler('settings', 'process_review_sent_email_setting', true, 'imap', 'date', 'after');
add_handler('settings', 'process_auto_advance_email_setting', true, 'imap', 'date', 'after');
Expand All @@ -51,6 +53,8 @@
add_output('settings', 'imap_pagination_links', true, 'imap', 'imap_msg_icons_setting', 'after');
add_output('settings', 'imap_unread_on_open', true, 'imap', 'imap_msg_icons_setting', 'after');
add_output('settings', 'imap_per_page_setting', true, 'imap', 'imap_pagination_links', 'after');
add_output('settings', 'webhook_token_setting', true, 'imap', 'imap_per_page_setting', 'after');
add_output('settings', 'interval_webhook_notification_setting', true, 'imap', 'webhook_token_setting', 'after');
add_output('settings', 'enable_simple_download_options', true, 'imap', 'imap_per_page_setting', 'after');
add_output('settings', 'max_google_contacts_number', true, 'imap', 'imap_per_page_setting', 'after');
add_output('settings', 'review_sent_email', true, 'imap', 'imap_pagination_links', 'after');
Expand Down Expand Up @@ -172,6 +176,9 @@
add_handler('ajax_imap_unread', 'save_imap_cache', true);
add_output('ajax_imap_unread', 'filter_unread_data', true);

setup_base_ajax_page('ajax_send_telegram_webhook', 'core');
add_handler('ajax_send_telegram_webhook', 'send_telegram_webhook', true, 'imap');

/* ajax add/remove to combined view */
setup_base_ajax_page('ajax_imap_update_combined_source', 'core');
add_handler('ajax_imap_update_combined_source', 'load_imap_servers_from_config', true);
Expand Down Expand Up @@ -331,6 +338,7 @@
'ajax_imap_unsnooze',
'ajax_imap_junk',
'message_source',
'ajax_send_telegram_webhook',
),

'allowed_output' => array(
Expand Down Expand Up @@ -416,6 +424,9 @@
'review_sent_email' => FILTER_VALIDATE_BOOLEAN,
'imap_snooze_ids' => FILTER_DEFAULT,
'imap_snooze_until' => FILTER_DEFAULT,
'auto_advance_email' => FILTER_VALIDATE_BOOLEAN
'auto_advance_email' => FILTER_VALIDATE_BOOLEAN,
'webhook_token' => FILTER_DEFAULT,
'interval_webhook_notification' => FILTER_VALIDATE_INT,
'unread_message_count' => FILTER_VALIDATE_INT,
)
);
Loading