Added combined notifications (#639)

If multiple servers go up or down together, you don't get spammed with notifications if you have this option enabled. It will send one combined notification.
This commit is contained in:
Tim 2018-09-05 23:03:29 +02:00 committed by TimZ99
parent d33c891be2
commit cf6f30adfc
No known key found for this signature in database
GPG Key ID: 4D8268DC68E8339D
8 changed files with 570 additions and 343 deletions

View File

@ -5,6 +5,7 @@ Changelog
Not yet released Not yet released
---------------- ----------------
* #639: Added combined notifications.
* #626: Added redirect check. * #626: Added redirect check.
* #627: Latest server output, error and output during a failure will be saved and are shown on the server page. * #627: Latest server output, error and output during a failure will be saved and are shown on the server page.
* #631: Added option to specify the request method. * #631: Added option to specify the request method.

View File

@ -33,8 +33,9 @@
/** /**
* Retrieve language settings from the selected language file * Retrieve language settings from the selected language file
* Return false if arg is not found
* *
* @return string * @return string|bool
* @see psm_load_lang() * @see psm_load_lang()
*/ */
function psm_get_lang() { function psm_get_lang() {
@ -62,7 +63,7 @@ function psm_get_lang() {
$lang = $GLOBALS['sm_lang_default']; $lang = $GLOBALS['sm_lang_default'];
foreach ($args as $translation) { foreach ($args as $translation) {
$lang = $lang[$translation]; $lang = $lang[$translation];
} }
return $lang; return $lang;
} }
@ -311,15 +312,20 @@ function psm_log_uptime($server_id, $status, $latency) {
/** /**
* Parses a string from the language file with the correct variables replaced in the message * Parses a string from the language file with the correct variables replaced in the message
* *
* @param boolean $status * @param boolean|null $status
* @param string $type is either 'sms', 'email', 'pushover_title', 'pushover_message' or 'telegram_message' * @param string $type is either 'sms', 'email', 'pushover_title', 'pushover_message' or 'telegram_message'
* @param array $server information about the server which may be placed in a message: %KEY% will be replaced by your value * @param array $vars server information about the server which may be placed in a message: %KEY% will be replaced by your value
* @param boolean $combi parse other message if notifications need to be send combined
* @return string parsed message * @return string parsed message
*/ */
function psm_parse_msg($status, $type, $vars) { function psm_parse_msg($status, $type, $vars, $combi = false) {
$status = ($status === true) ? 'on' : 'off'; if(is_bool($status)) {
$status = ($status === true) ? 'on_' : 'off_';
}
$message = psm_get_lang('notifications', $status.'_'.$type); $combi = ($combi === true) ? 'combi_' : '';
$message = psm_get_lang('notifications', $combi.$status.$type);
if (!$message) { if (!$message) {
return $message; return $message;
@ -817,6 +823,12 @@ class telegram
$this->_user = (string) $user; $this->_user = (string) $user;
} }
public function setMessage($message) { public function setMessage($message) {
$message = str_replace("<ul>","",$message);
$message = str_replace("</ul>","\n",$message);
$message = str_replace("<li>","- ",$message);
$message = str_replace("</li>","\n",$message);
$message = str_replace("<br>","\n",$message);
$message = str_replace("<br/>","\n",$message);
$this->_message = (string) $message; $this->_message = (string) $message;
} }
public function sendurl() { public function sendurl() {
@ -830,7 +842,9 @@ class telegram
} }
public function send() { public function send() {
if (!Empty($this->_token) && !Empty($this->_user) && !Empty($this->_message)) { if (!Empty($this->_token) && !Empty($this->_user) && !Empty($this->_message)) {
$this->_url = 'https://api.telegram.org/bot'.urlencode($this->_token).'/sendMessage?chat_id='.urlencode($this->_user).'&text='.urlencode($this->_message); $this->_url = 'https://api.telegram.org/bot'.urlencode($this->_token).
'/sendMessage?chat_id='.urlencode($this->_user).'&text='.
urlencode($this->_message).'&parse_mode=HTML';
} }
return $this->sendurl(); return $this->sendurl();
} }

View File

@ -272,16 +272,18 @@ $sm_lang = array(
'telegram_api_token_description' => 'Before you can use Telegram, you need to get a API token. Visit the <a href="http://docs.phpservermonitor.org/">documentation</a> for help.', 'telegram_api_token_description' => 'Before you can use Telegram, you need to get a API token. Visit the <a href="http://docs.phpservermonitor.org/">documentation</a> for help.',
'alert_type' => 'Select when you\'d like to be notified.', 'alert_type' => 'Select when you\'d like to be notified.',
'alert_type_description' => '<b>Status change:</b> '. 'alert_type_description' => '<b>Status change:</b> '.
'You will receive a notifcation when a server has a change in status. So from online -> offline or offline -> online.<br/>'. 'You will receive a notification when a server has a change in status. So from online -> offline or offline -> online.<br/>'.
'<br /><b>Offline:</b> '. '<br /><b>Offline:</b> '.
'You will receive a notification when a server goes offline for the *FIRST TIME ONLY*. For example, '. 'You will receive a notification when a server goes offline for the *FIRST TIME ONLY*. For example, '.
'your cronjob is every 15 mins and your server goes down at 1 am and stays down till 6 am. '. 'your cronjob is every 15 minutes and your server goes down at 1 am and stays down till 6 am. '.
'You will get 1 notification at 1 am and thats it.<br/>'. 'You will get 1 notification at 1 am and that\'s it.<br/>'.
'<br><b>Always:</b> '. '<br><b>Always:</b> '.
'You will receive a notification every time the script runs and a site is down, even if the site has been offline for hours.', 'You will receive a notification every time the script runs and a site is down, even if the site has been offline for hours.',
'alert_type_status' => 'Status change', 'alert_type_status' => 'Status change',
'alert_type_offline' => 'Offline', 'alert_type_offline' => 'Offline',
'alert_type_always' => 'Always', 'alert_type_always' => 'Always',
'combine_notifications' => 'Combine notifications',
'combine_notifications_description' => 'Reduces the amount of notification by combining the notifications into 1 single notification. (This does not affect SMS notifications.)',
'alert_proxy' => 'Even if enabled, proxy is never used for services', 'alert_proxy' => 'Even if enabled, proxy is never used for services',
'alert_proxy_url' => '<b>Format:</b> Host:Port', 'alert_proxy_url' => '<b>Format:</b> Host:Port',
'log_status' => 'Log status', 'log_status' => 'Log status',
@ -347,7 +349,18 @@ $sm_lang = array(
'on_email_body' => "Server '%LABEL%' is running again, it was down for %LAST_OFFLINE_DURATION%:<br/><br/>Server: %LABEL%<br/>IP: %IP%<br/>Port: %PORT%<br/>Date: %DATE%", 'on_email_body' => "Server '%LABEL%' is running again, it was down for %LAST_OFFLINE_DURATION%:<br/><br/>Server: %LABEL%<br/>IP: %IP%<br/>Port: %PORT%<br/>Date: %DATE%",
'on_pushover_title' => 'Server \'%LABEL%\' is RUNNING', 'on_pushover_title' => 'Server \'%LABEL%\' is RUNNING',
'on_pushover_message' => 'Server \'%LABEL%\' is running again, it was down for %LAST_OFFLINE_DURATION%:<br/><br/>Server: %LABEL%<br/>IP: %IP%<br/>Port: %PORT%<br/>Date: %DATE%', 'on_pushover_message' => 'Server \'%LABEL%\' is running again, it was down for %LAST_OFFLINE_DURATION%:<br/><br/>Server: %LABEL%<br/>IP: %IP%<br/>Port: %PORT%<br/>Date: %DATE%',
'on_telegram_message' => 'Server \'%LABEL%\' is running again, it was down for %LAST_OFFLINE_DURATION%:<br/><br/>Server: %LABEL%<br/>IP: %IP%<br/>Port: %PORT%<br/>Date: %DATE%', 'on_telegram_message' => 'Server \'%LABEL%\' is running again, it was down for :<br/><br/>Server: %LABEL%<br/>IP: %IP%<br/>Port: %PORT%<br/>Downtime: %LAST_OFFLINE_DURATION%<br/>Date: %DATE%',
'combi_off_email_message' => "<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port: %PORT%</li><li>Error: %ERROR%</li><li>Date: %DATE%</li></ul>",
'combi_off_pushover_message' => "<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port: %PORT%</li><li>Error: %ERROR%</li><li>Date: %DATE%</li></ul>",
'combi_off_telegram_message' => "- Server: %LABEL%<br/>- IP: %IP%<br/>- Port: %PORT%<br/>- Error: %ERROR%<br/>- Date: %DATE%<br/><br/>",
'combi_on_email_message' => "<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port: %PORT%</li><li>Downtime: %LAST_OFFLINE_DURATION%</li><li>Date: %DATE%</li></ul>",
'combi_on_pushover_message' => '<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port: %PORT%</li><li>Downtime: %LAST_OFFLINE_DURATION%</li><li>Date: %DATE%</li></ul>',
'combi_on_telegram_message' => '- Server: %LABEL%<br/>- IP: %IP%<br/>- Port: %PORT%<br/>- Downtime: %LAST_OFFLINE_DURATION%<br/>- Date: %DATE%<br/><br/>',
'combi_email_subject' => 'IMPORTANT: \'%UP%\' servers UP again, \'%DOWN%\' servers DOWN',
'combi_pushover_subject' => '\'%UP%\' servers UP again, \'%DOWN%\' servers DOWN',
'combi_email_message' => '<b>The following servers went down:</b><br/>%DOWN_SERVERS%<br/><b>The following servers are up again:</b><br/>%UP_SERVERS%',
'combi_pushover_message' => '<b>The following servers went down:</b><br/>%DOWN_SERVERS%<br/><b>The following servers are up again:</b><br/>%UP_SERVERS%',
'combi_telegram_message' => '<b>The following servers went down:</b><br/>%DOWN_SERVERS%<br/><b>The following servers are up again:</b><br/>%UP_SERVERS%',
), ),
'login' => array( 'login' => array(
'welcome_usermenu' => 'Welcome, %user_name%', 'welcome_usermenu' => 'Welcome, %user_name%',

View File

@ -48,6 +48,7 @@ class ConfigController extends AbstractController {
'log_pushover', 'log_pushover',
'log_telegram', 'log_telegram',
'show_update', 'show_update',
'combine_notifications',
); );
/** /**
@ -395,6 +396,8 @@ class ConfigController extends AbstractController {
'label_alert_type_status' => psm_get_lang('config', 'alert_type_status'), 'label_alert_type_status' => psm_get_lang('config', 'alert_type_status'),
'label_alert_type_offline' => psm_get_lang('config', 'alert_type_offline'), 'label_alert_type_offline' => psm_get_lang('config', 'alert_type_offline'),
'label_alert_type_always' => psm_get_lang('config', 'alert_type_always'), 'label_alert_type_always' => psm_get_lang('config', 'alert_type_always'),
'label_combine_notifications' => psm_get_lang('config', 'combine_notifications'),
'label_combine_notifications_description' => psm_get_lang('config', 'combine_notifications_description'),
'label_log_status' => psm_get_lang('config', 'log_status'), 'label_log_status' => psm_get_lang('config', 'log_status'),
'label_log_status_description' => psm_get_lang('config', 'log_status_description'), 'label_log_status_description' => psm_get_lang('config', 'log_status_description'),
'label_log_email' => psm_get_lang('config', 'log_email'), 'label_log_email' => psm_get_lang('config', 'log_email'),

View File

@ -560,13 +560,15 @@ class Installer {
* If you have a lot of server that are redirecting, * If you have a lot of server that are redirecting,
* this will make sure you're servers stay online. * this will make sure you're servers stay online.
*/ */
$queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` ADD COLUMN `allow_http_status` VARCHAR(255) NOT NULL DEFAULT '' AFTER `pattern_online`;"; $queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` ADD COLUMN `allow_http_status` VARCHAR(255) NOT NULL DEFAULT '' AFTER `pattern_online`;";
$queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` ADD `redirect_check` ENUM( 'ok','bad' ) NOT NULL DEFAULT 'ok' AFTER `allow_http_status`;"; $queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` ADD `redirect_check` ENUM( 'ok','bad' ) NOT NULL DEFAULT 'ok' AFTER `allow_http_status`;";
$queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` CHANGE `redirect_check` `redirect_check` ENUM('ok','bad') NOT NULL DEFAULT 'bad';"; $queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` CHANGE `redirect_check` `redirect_check` ENUM('ok','bad') NOT NULL DEFAULT 'bad';";
$queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` ADD COLUMN `last_error` VARCHAR(255) NULL AFTER `website_password`;"; $queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` ADD COLUMN `last_error` VARCHAR(255) NULL AFTER `website_password`;";
$queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` ADD COLUMN `last_error_output` TEXT NULL AFTER `last_error`;"; $queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` ADD COLUMN `last_error_output` TEXT NULL AFTER `last_error`;";
$queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` ADD COLUMN `last_output` TEXT NULL AFTER `last_error_output`;"; $queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` ADD COLUMN `last_output` TEXT NULL AFTER `last_error_output`;";
$queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` ADD COLUMN `request_method` varchar(50) NULL AFTER `port`;"; $queries[] = "ALTER TABLE `".PSM_DB_PREFIX."servers` ADD COLUMN `request_method` varchar(50) NULL AFTER `port`;";
$this->execSQL($queries); $queries[] = "INSERT INTO `".PSM_DB_PREFIX."config` (`key`, `value`) VALUES ('combine_notifications', '1');";
$this->execSQL($queries);
$this->log('Combined notifications enabled. Check out the config page for more info.');
} }
} }

View File

@ -79,5 +79,8 @@ class UpdateManager implements ContainerAwareInterface {
$archive->archive($server['server_id']); $archive->archive($server['server_id']);
$archive->cleanup($server['server_id']); $archive->cleanup($server['server_id']);
} }
if($notifier->combine){
$notifier->notifyCombined();
}
} }
} }

View File

@ -72,6 +72,23 @@ class StatusNotifier {
*/ */
protected $save_logs = false; protected $save_logs = false;
/**
* Send multiple notifications as one?
* @var boolean $combine
*/
public $combine = false;
/**
* Notification list
* @var array $combiNotification
*/
protected $combiNotification = array(
'count' => array(),
'users' => array(),
'notifications' => array(),
'userNotifications' => array()
);
/** /**
* Server id * Server id
* @var int $server_id * @var int $server_id
@ -104,18 +121,26 @@ class StatusNotifier {
$this->send_pushover = psm_get_conf('pushover_status'); $this->send_pushover = psm_get_conf('pushover_status');
$this->send_telegram = psm_get_conf('telegram_status'); $this->send_telegram = psm_get_conf('telegram_status');
$this->save_logs = psm_get_conf('log_status'); $this->save_logs = psm_get_conf('log_status');
$this->combine = psm_get_conf('combine_notifications');
} }
/** /**
* This function initializes the sending (text msg & email) and logging * This function initializes the sending (text msg, email, Pushover and Telegram) and logging
* *
* @param int $server_id * @param int $server_id
* @param boolean $status_old * @param boolean $status_old
* @param boolean $status_new * @param boolean $status_new
* @return boolean * @return boolean
*/ * @throws \PHPMailer\PHPMailer\Exception
*/
public function notify($server_id, $status_old, $status_new) { public function notify($server_id, $status_old, $status_new) {
if (!$this->send_emails && !$this->send_sms && !$this->save_logs) { if (
!$this->send_emails &&
!$this->send_sms &&
!$this->send_pushover &&
!$this->send_telegram &&
!$this->save_logs
) {
// seems like we have nothing to do. skip the rest // seems like we have nothing to do. skip the rest
return false; return false;
} }
@ -125,10 +150,12 @@ class StatusNotifier {
$this->status_new = $status_new; $this->status_new = $status_new;
// get server info from db // get server info from db
// only get info that will be put into the notification
// or is needed to check if a notification need to be send
$this->server = $this->db->selectRow(PSM_DB_PREFIX.'servers', array( $this->server = $this->db->selectRow(PSM_DB_PREFIX.'servers', array(
'server_id' => $server_id, 'server_id' => $server_id,
), array( ), array(
'server_id', 'ip', 'port', 'label', 'type', 'pattern', 'status', 'header_name', 'header_value', 'error', 'active', 'email', 'sms', 'pushover', 'telegram', 'last_online', 'last_offline', 'last_offline_duration', 'server_id', 'ip', 'port', 'label', 'error', 'email', 'sms', 'pushover', 'telegram', 'last_online', 'last_offline', 'last_offline_duration',
)); ));
if (empty($this->server)) { if (empty($this->server)) {
return false; return false;
@ -177,14 +204,19 @@ class StatusNotifier {
return $notify; return $notify;
} }
if($this->combine){
$this->setCombi('init', $users);
}
// check if email is enabled for this server // check if email is enabled for this server
if ($this->send_emails && $this->server['email'] == 'yes') { if ($this->send_emails && $this->server['email'] == 'yes') {
// send email // send email
$this->notifyByEmail($users); $this->combine ? $this->setCombi('email') : $this->notifyByEmail($users);
} }
// check if sms is enabled for this server // check if sms is enabled for this server
if ($this->send_sms && $this->server['sms'] == 'yes') { if ($this->send_sms && $this->server['sms'] == 'yes') {
// sms will not be send combined as some gateways don't support long sms / charge extra
// yay lets wake those nerds up! // yay lets wake those nerds up!
$this->notifyByTxtMsg($users); $this->notifyByTxtMsg($users);
} }
@ -192,31 +224,143 @@ class StatusNotifier {
// check if pushover is enabled for this server // check if pushover is enabled for this server
if ($this->send_pushover && $this->server['pushover'] == 'yes') { if ($this->send_pushover && $this->server['pushover'] == 'yes') {
// yay lets wake those nerds up! // yay lets wake those nerds up!
$this->notifyByPushover($users); $this->combine ? $this->setCombi('pushover') : $this->notifyByPushover($users);
} }
// check if telegram is enabled for this server // check if telegram is enabled for this server
if ($this->send_telegram && $this->server['telegram'] == 'yes') { if ($this->send_telegram && $this->server['telegram'] == 'yes') {
// yay lets wake those nerds up! $this->combine ? $this->setCombi('telegram') : $this->notifyByTelegram($users);
$this->notifyByTelegram($users);
} }
return $notify; return $notify;
} }
/** /**
* This functions performs the email notifications * This functions collects all of the notifications
* *
* @param array $users * @param string $method notification method
* @return boolean * @param array $users Users
*/ * @return void
protected function notifyByEmail($users) { */
public function setCombi($method, $users = array()) {
$status = $this->status_new ? 'on' : 'off';
if ($method == 'init' && !empty($users)){
foreach($users as $user) {
if(!isset($this->combiNotification['count'][$user['user_id']])){
$this->combiNotification['count'][$user['user_id']] = array('on' => 0, 'off' => 0);
}
$this->combiNotification['userNotifications'][$user['user_id']][] = $this->server_id;
$this->combiNotification['users'][$user['user_id']] = $user;
$this->combiNotification['count'][$user['user_id']][$status] += 1;
}
return;
}
$this->combiNotification['notifications'][$method][$status][$this->server_id] =
psm_parse_msg($this->status_new, $method.'_message', $this->server, true);
return;
}
/**
* This functions returns the subject for a combined notification
*
* @return void
*/
public function notifyCombined() {
if(empty($this->combiNotification['userNotifications'])){
return;
}
// Get the servers the user will get notified of
$this->status_new = true;
foreach ($this->combiNotification['userNotifications'] as $user => $servers) {
$notifications = array();
// Combine all of the messages belonging to the server the user will get notification of
foreach ($servers as $server) {
foreach ($this->combiNotification['notifications'] as $method => $status){
foreach ($status as $the_status => $value) {
if(!key_exists($method, $notifications)){
$notifications[$method] = array('on' => '', 'off' => '');
}
if(key_exists($server, $status[$the_status])){
$notifications[$method][$the_status] .= $status[$the_status][$server];
}
// Set $this->status_new to false if a server is down.
// This is used by Pushover to determine the priority.
if(!empty($notifications[$method]['off'])){
$this->status_new = false;
}
}
}
}
// Send combined notification per user
foreach ($notifications as $method => $notification){
$finalNotification['message'] = $this->createCombiMessage($method, $notification);
$subject = $this->createCombiSubject($method, $user);
if(!is_null($subject)){
$finalNotification['subject'] = $subject;
}
$this->{'notifyBy' . ucwords($method)}
(array($this->combiNotification['users'][$user]), $finalNotification);
}
}
unset($notifications);
return;
}
/**
* This functions returns the message for a combined notification
*
* @param string $method Notification method
* @param array $notification Notification
* @return string
*/
protected function createCombiMessage($method, $notification){
if(empty($notification['off'])){
$notification['off'] = "<ul><li>".psm_get_lang('system', 'none')."</li></ul>";
}
if(empty($notification['on'])){
$notification['on'] = "<ul><li>".psm_get_lang('system', 'none')."</li></ul>";
}
$vars = array('DOWN_SERVERS' => $notification['off'], 'UP_SERVERS' => $notification['on']);
return psm_parse_msg(null, $method.'_message', $vars, true);
}
/**
* This functions returns the subject for a combined notification
*
* @param string $method Notification method
* @param integer $user_id User id
* @return string|null
*/
protected function createCombiSubject($method, $user_id){
//die(var_dump($GLOBALS['sm_lang_default']['notifications']['combi_'.$method.'_subject']));
$vars = array('DOWN' => $this->combiNotification['count'][$user_id]['off'], 'UP' => $this->combiNotification['count'][$user_id]['on']);
$translation = isset($GLOBALS['sm_lang_default']['notifications']['combi_'.$method.'_subject']) ?
psm_parse_msg(null, $method.'_subject', $vars, true) :
null;
return $translation;
}
/**
* This functions performs the email notifications
*
* @param \PDOStatement $users
* @param array $combi contains message and subject (optional)
* @return void
* @throws \PHPMailer\PHPMailer\Exception
*/
protected function notifyByEmail($users, $combi = array()) {
// build mail object with some default values // build mail object with some default values
$mail = psm_build_mail(); $mail = psm_build_mail();
$mail->Subject = psm_parse_msg($this->status_new, 'email_subject', $this->server); $mail->Subject = key_exists('subject', $combi) ?
$combi['subject'] :
psm_parse_msg($this->status_new, 'email_subject', $this->server);
$mail->Priority = 1; $mail->Priority = 1;
$body = psm_parse_msg($this->status_new, 'email_body', $this->server); $body = key_exists('message', $combi) ?
$combi['message'] :
psm_parse_msg($this->status_new, 'email_body', $this->server);
$mail->Body = $body; $mail->Body = $body;
$mail->AltBody = str_replace('<br/>', "\n", $body); $mail->AltBody = str_replace('<br/>', "\n", $body);
@ -230,20 +374,22 @@ class StatusNotifier {
psm_add_log_user($log_id, $user['user_id']); psm_add_log_user($log_id, $user['user_id']);
} }
// we sent a seperate email to every single user. // we sent a separate email to every single user.
$mail->AddAddress($user['email'], $user['name']); $mail->AddAddress($user['email'], $user['name']);
$mail->Send(); $mail->Send();
$mail->ClearAddresses(); $mail->ClearAddresses();
} }
return;
} }
/** /**
* This functions performs the pushover notifications * This functions performs the pushover notifications
* *
* @param array $users * @param \PDOStatement $users
* @return boolean * @param array $combi contains message and subject (optional)
* @return void
*/ */
protected function notifyByPushover($users) { protected function notifyByPushover($users, $combi = array()) {
// Remove users that have no pushover_key // Remove users that have no pushover_key
foreach ($users as $k => $user) { foreach ($users as $k => $user) {
if (trim($user['pushover_key']) == '') { if (trim($user['pushover_key']) == '') {
@ -257,7 +403,10 @@ class StatusNotifier {
} }
// Pushover // Pushover
$message = psm_parse_msg($this->status_new, 'pushover_message', $this->server); $message = key_exists('message', $combi) ?
$combi['message'] :
psm_parse_msg($this->status_new, 'pushover_message', $this->server);
$pushover = psm_build_pushover(); $pushover = psm_build_pushover();
if ($this->status_new === true) { if ($this->status_new === true) {
$pushover->setPriority(0); $pushover->setPriority(0);
@ -266,7 +415,11 @@ class StatusNotifier {
$pushover->setRetry(300); //Used with Priority = 2; Pushover will resend the notification every 60 seconds until the user accepts. $pushover->setRetry(300); //Used with Priority = 2; Pushover will resend the notification every 60 seconds until the user accepts.
$pushover->setExpire(3600); //Used with Priority = 2; Pushover will resend the notification every 60 seconds for 3600 seconds. After that point, it stops sending notifications. $pushover->setExpire(3600); //Used with Priority = 2; Pushover will resend the notification every 60 seconds for 3600 seconds. After that point, it stops sending notifications.
} }
$pushover->setTitle(psm_parse_msg($this->status_new, 'pushover_title', $this->server)); $title = key_exists('subject', $combi) ?
$combi['subject'] :
psm_parse_msg($this->status_new, 'pushover_title', $this->server);
$pushover->setHtml(1);
$pushover->setTitle($title);
$pushover->setMessage(str_replace('<br/>', "\n", $message)); $pushover->setMessage(str_replace('<br/>', "\n", $message));
$pushover->setUrl(psm_build_url()); $pushover->setUrl(psm_build_url());
$pushover->setUrlTitle(psm_get_lang('system', 'title')); $pushover->setUrlTitle(psm_get_lang('system', 'title'));
@ -294,7 +447,7 @@ class StatusNotifier {
/** /**
* This functions performs the text message notifications * This functions performs the text message notifications
* *
* @param array $users * @param \PDOStatement $users
* @return boolean * @return boolean
*/ */
protected function notifyByTxtMsg($users) { protected function notifyByTxtMsg($users) {
@ -329,39 +482,44 @@ class StatusNotifier {
/** /**
* This functions performs the telegram notifications * This functions performs the telegram notifications
* *
* @param array $users * @param \PDOStatement $users
* @return boolean * @param array $combi contains message and subject (optional)
* @return void
*/ */
protected function notifyByTelegram($users) { protected function notifyByTelegram($users, $combi = array()) {
// Remove users that have no telegram_id // Remove users that have no telegram_id
foreach ($users as $k => $user) { foreach ($users as $k => $user) {
if (trim($user['telegram_id']) == '') { if (trim($user['telegram_id']) == '') {
unset($users[$k]); unset($users[$k]);
} }
} }
// Validation // Validation
if (empty($users)) { if (empty($users)) {
return; return;
} }
// Telegram // Telegram
$message = psm_parse_msg($this->status_new, 'telegram_message', $this->server); $message = key_exists('message', $combi) ?
$telegram = psm_build_telegram(); $combi['message'] :
$telegram->setMessage(str_replace('<br/>', "\n", $message)); psm_parse_msg($this->status_new, 'telegram_message', $this->server);
// Log $telegram = psm_build_telegram();
if (psm_get_conf('log_telegram')) { $telegram->setMessage($message);
$log_id = psm_add_log($this->server_id, 'telegram', $message);
} // Log
foreach ($users as $user) { if (psm_get_conf('log_telegram')) {
// Log $log_id = psm_add_log($this->server_id, 'telegram', $message);
if (!empty($log_id)) {
psm_add_log_user($log_id, $user['user_id']);
} }
$telegram->setUser($user['telegram_id']);
$telegram->send(); foreach ($users as $user) {
} // Log
} if (!empty($log_id)) {
psm_add_log_user($log_id, $user['user_id']);
}
$telegram->setUser($user['telegram_id']);
$telegram->send();
}
}
/** /**
* Get all users for the provided server id * Get all users for the provided server id

View File

@ -1,293 +1,326 @@
{% import 'main/macros.tpl.html' as macro %} {% import 'main/macros.tpl.html' as macro %}
<form class="form-horizontal" name="edit_config" action="index.php?mod=config&amp;action=save" id="edit_config" method="post"> <form class="form-horizontal" name="edit_config" action="index.php?mod=config&amp;action=save" id="edit_config" method="post">
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li class="{{ general_active }}"><a href="#config-general" data-toggle="tab">{{ label_general }}</a></li> <li class="{{ general_active }}"><a href="#config-general" data-toggle="tab">{{ label_general }}</a></li>
<li class="{{ email_active }}"><a href="#config-email" data-toggle="tab">{{ label_tab_email }}</a></li> <li class="{{ email_active }}"><a href="#config-email" data-toggle="tab">{{ label_tab_email }}</a></li>
<li class="{{ sms_active }}"><a href="#config-sms" data-toggle="tab">{{ label_tab_sms }}</a></li> <li class="{{ sms_active }}"><a href="#config-sms" data-toggle="tab">{{ label_tab_sms }}</a></li>
<li class="{{ pushover_active }}"><a href="#config-pushover" data-toggle="tab">{{ label_tab_pushover }}</a></li> <li class="{{ pushover_active }}"><a href="#config-pushover" data-toggle="tab">{{ label_tab_pushover }}</a></li>
<li class="{{ telegram_active }}"><a href="#config-telegram" data-toggle="tab">{{ label_tab_telegram }}</a></li> <li class="{{ telegram_active }}"><a href="#config-telegram" data-toggle="tab">{{ label_tab_telegram }}</a></li>
</ul> </ul>
<div class="tab-content well"> <div class="tab-content well">
<div id="config-general" class="tab-pane {{ general_active }}"> <div id="config-general" class="tab-pane {{ general_active }}">
<fieldset> <fieldset>
<legend>{{ label_general }}</legend> <legend>{{ label_general }}</legend>
<div class="control-group"> <div class="control-group">
<label class="control-label" for="language">{{ label_language }}</label> <label class="control-label" for="language">{{ label_language }}</label>
<div class="controls"> <div class="controls">
<select id="language" name="language"> <select id="language" name="language">
{% for language in languages %} {% for language in languages %}
<option value="{{ language.value }}" {% if language.value == language_current %} selected="selected" {% endif %}>{{ language.label }}</option> <option value="{{ language.value }}" {% if language.value == language_current %} selected="selected" {% endif %}>{{
{% endfor %} language.label }}</option>
</select> {% endfor %}
</select>
</div>
</div> </div>
</div> <div class="control-group">
<div class="control-group"> <div class="controls">
<div class="controls"> <label class="checkbox" for="show_update"><input type="checkbox" id="show_update" name="show_update[]"
<label class="checkbox" for="show_update"><input type="checkbox" id="show_update" name="show_update[]" {{ show_update_checked|raw }} /> {{ label_show_update }}</label> {{ show_update_checked|raw }} /> {{ label_show_update }}</label>
</div>
</div> </div>
</div> <div class="control-group">
<div class="control-group"> <label class="control-label" for="auto_refresh_servers">{{ label_auto_refresh }}</label>
<label class="control-label" for="auto_refresh_servers">{{ label_auto_refresh }}</label> <div class="controls">
<div class="controls"> <input type="text" class="input-mini" id="auto_refresh_servers" name="auto_refresh_servers" value="{{ auto_refresh_servers }}"
<input type="text" class="input-mini" id="auto_refresh_servers" name="auto_refresh_servers" value="{{ auto_refresh_servers }}" maxlength="10" data-toggle="tooltip" title="{{ label_auto_refresh_servers }}" />&nbsp;{{ label_seconds }} maxlength="10" data-toggle="tooltip" title="{{ label_auto_refresh_servers }}" />&nbsp;{{
label_seconds }}
</div>
</div> </div>
</div> <div class="control-group">
<div class="control-group"> <label class="control-label" for="password_encrypt_key">
<label class="control-label" for="password_encrypt_key"> {{ label_password_encrypt_key }}
{{ label_password_encrypt_key }} </label>
</label> <div class="controls">
<div class="controls"> <input type="text" class="input-xxlarge" id="password_encrypt_key" name="password_encrypt_key" value="{{ password_encrypt_key }}"
<input type="text" class="input-xxlarge" id="password_encrypt_key" name="password_encrypt_key" maxlength="40" data-toggle="tooltip" title="{{ label_password_encrypt_key_note }}" />
value="{{ password_encrypt_key }}" maxlength="40" data-toggle="tooltip" </div>
title="{{ label_password_encrypt_key_note }}"/>
</div>
</div>
</fieldset>
<fieldset>
<legend>{{ label_settings_notification }}</legend>
<div class="control-group">
<label class="control-label" for="alert_type">{{ label_alert_type }}</label>
<div class="controls">
<select id="alert_type" name="alert_type">
<option value="status" {{ alert_type_selected_status|raw }}>{{ label_alert_type_status }}</option>
<option value="offline" {{ alert_type_selected_offline|raw }}>{{ label_alert_type_offline }}</option>
<option value="always" {{ alert_type_selected_always|raw }}>{{ label_alert_type_always }}</option>
</select>
<p class="help-block">{{ label_alert_type_description|raw }}</p>
</div> </div>
</div> </fieldset>
</fieldset> <fieldset>
<fieldset> <legend>{{ label_settings_notification }}</legend>
<legend>{{ label_settings_log }}</legend> <div class="control-group">
<div class="control-group"> <div class="controls">
<div class="controls"> <label class="checkbox"><input type="checkbox" id="combine_notifications" name="combine_notifications[]" {{ combine_notifications_checked|raw }} data-toggle="tooltip" /> {{ label_combine_notifications }}</label>
<label class="checkbox"><input type="checkbox" id="log_status" name="log_status[]" {{ log_status_checked|raw }} data-toggle="tooltip" title="{{ label_log_status_description }}" /> {{ label_log_status }}</label> <p class="help-block">{{ label_combine_notifications_description }}</p>
</div> </div>
</div>
<div class="control-group">
<label class="control-label" for="log_retention_period">{{ label_log_retention_period }}</label>
<div class="controls">
<input type="text" class="input-mini" id="log_retention_period" name="log_retention_period" value="{{ log_retention_period }}" data-toggle="tooltip" title="{{ label_log_retention_period_description }}" />&nbsp;{{ label_log_retention_days }}
</div> </div>
</div> <div class="control-group">
<legend>{{ label_settings_proxy }}</legend> <label class="control-label" for="alert_type">{{ label_alert_type }}</label>
<div class="control-group"> <div class="controls">
<div class="controls"> <select id="alert_type" name="alert_type">
<label class="checkbox" for="proxy"><input type="checkbox" id="proxy" name="proxy[]" {{ proxy_checked|raw }} />{{ label_proxy }}</label> <option value="status" {{ alert_type_selected_status|raw }}>{{ label_alert_type_status }}</option>
<p class="help-block">{{ label_alert_proxy|raw }}</p> <option value="offline" {{ alert_type_selected_offline|raw }}>{{ label_alert_type_offline }}</option>
<option value="always" {{ alert_type_selected_always|raw }}>{{ label_alert_type_always }}</option>
</select>
<p class="help-block">{{ label_alert_type_description|raw }}</p>
</div>
</div> </div>
</div> </fieldset>
<div class="control-group"> <fieldset>
<label class="control-label" for="proxy_url">{{ label_proxy_url }}</label> <legend>{{ label_settings_log }}</legend>
<div class="controls"> <div class="control-group">
<input type="text" id="proxy_url" name="proxy_url" value="{{ proxy_url }}" maxlength="100" placeholder="{{ label_proxy_url }}" /> <div class="controls">
<p class="help-block">{{ label_alert_proxy_url|raw }}</p> <label class="checkbox"><input type="checkbox" id="log_status" name="log_status[]" {{ log_status_checked|raw
}} data-toggle="tooltip" title="{{ label_log_status_description }}" /> {{ label_log_status }}</label>
</div>
</div> </div>
</div> <div class="control-group">
<div class="control-group"> <label class="control-label" for="log_retention_period">{{ label_log_retention_period }}</label>
<label class="control-label" for="proxy_user">{{ label_proxy_user }}</label> <div class="controls">
<div class="controls"> <input type="text" class="input-mini" id="log_retention_period" name="log_retention_period" value="{{ log_retention_period }}"
<input type="text" id="proxy_user" name="proxy_user" value="{{ proxy_user }}" maxlength="100" placeholder="{{ label_proxy_user }}" /> data-toggle="tooltip" title="{{ label_log_retention_period_description }}" />&nbsp;{{
label_log_retention_days }}
</div>
</div> </div>
</div> <legend>{{ label_settings_proxy }}</legend>
<div class="control-group"> <div class="control-group">
<label class="control-label" for="proxy_password">{{ label_proxy_password }}</label> <div class="controls">
<div class="controls"> <label class="checkbox" for="proxy"><input type="checkbox" id="proxy" name="proxy[]" {{ proxy_checked|raw
<input type="password" id="proxy_password" name="proxy_password" value="{{ proxy_password }}" maxlength="100" placeholder="{{ label_proxy_password }}" /> }} />{{ label_proxy }}</label>
<p class="help-block">{{ label_alert_proxy|raw }}</p>
</div>
</div> </div>
</div> <div class="control-group">
<div class="form-actions"> <label class="control-label" for="proxy_url">{{ label_proxy_url }}</label>
<button class="btn btn-success" type="submit" name="general_submit">{{ label_save }}</button> <div class="controls">
</div> <input type="text" id="proxy_url" name="proxy_url" value="{{ proxy_url }}" maxlength="100" placeholder="{{ label_proxy_url }}"
</fieldset> />
</div> <p class="help-block">{{ label_alert_proxy_url|raw }}</p>
<div id="config-email" class="tab-pane {{ email_active }}"> </div>
<fieldset>
<legend>{{ label_settings_email }}</legend>
<div class="control-group">
<div class="controls">
<label class="checkbox" for="email_status"><input type="checkbox" id="email_status" name="email_status[]" {{ email_status_checked|raw }} /> {{ label_email_status }}</label>
</div> </div>
</div> <div class="control-group">
<div class="control-group"> <label class="control-label" for="proxy_user">{{ label_proxy_user }}</label>
<div class="controls"> <div class="controls">
<label class="checkbox"><input type="checkbox" id="log_email" name="log_email[]" {{ log_email_checked|raw }} /> {{ label_log_email }}</label> <input type="text" id="proxy_user" name="proxy_user" value="{{ proxy_user }}" maxlength="100" placeholder="{{ label_proxy_user }}"
</div> />
</div> </div>
<div class="control-group">
<label class="control-label" for="email_from_name">{{ label_email_from_name }}</label>
<div class="controls">
<input type="text" id="email_from_name" name="email_from_name" value="{{ email_from_name }}" maxlength="255" />
</div> </div>
</div> <div class="control-group">
<div class="control-group"> <label class="control-label" for="proxy_password">{{ label_proxy_password }}</label>
<label class="control-label" for="email_from_email">{{ label_email_from_email }}</label> <div class="controls">
<div class="controls"> <input type="password" id="proxy_password" name="proxy_password" value="{{ proxy_password }}" maxlength="100" placeholder="{{ label_proxy_password }}"
<input type="text" id="email_from_email" name="email_from_email" value="{{ email_from_email }}" maxlength="255" /> />
</div>
</div> </div>
</div> <div class="form-actions">
<div class="control-group"> <button class="btn btn-success" type="submit" name="general_submit">{{ label_save }}</button>
<div class="controls">
<label class="checkbox" for="email_smtp"><input type="checkbox" id="email_smtp" name="email_smtp[]" {{ email_smtp_checked|raw }} />{{ label_email_smtp }}</label>
</div> </div>
</div> </fieldset>
<div class="control-group">
<label class="control-label" for="email_smtp_host">{{ label_email_smtp_host }}</label>
<div class="controls">
<input type="text" id="email_smtp_host" name="email_smtp_host" value="{{ email_smtp_host }}" maxlength="100" placeholder="{{ label_email_smtp_host }}" />
<input type="text" class="input-small" id="email_smtp_port" name="email_smtp_port" value="{{ email_smtp_port }}" maxlength="10" placeholder="{{ label_email_smtp_port }}" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="email_smtp_security">{{ label_email_smtp_security }}</label>
<div class="controls">
<select id="email_smtp_security" name="email_smtp_security">
<option value="" {{ email_smtp_security_selected_|raw }}>{{ label_email_smtp_security_none }}</option>
<option value="ssl" {{ email_smtp_security_selected_ssl|raw }}>SSL</option>
<option value="tls" {{ email_smtp_security_selected_tls|raw }}>TLS</option>
</select>
</div>
</div>
<div class="control-group">
<label class="control-label" for="email_smtp_username">{{ label_email_smtp_username }}</label>
<div class="controls">
<input type="text" id="email_smtp_username" name="email_smtp_username" value="{{ email_smtp_username }}" maxlength="100" placeholder="{{ label_email_smtp_noauth }}" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="email_smtp_password">{{ label_email_smtp_password }}</label>
<div class="controls">
<input type="password" id="email_smtp_password" name="email_smtp_password" value="{{ email_smtp_password }}" maxlength="100" placeholder="{{ label_email_smtp_noauth }}" />
</div>
</div>
<div class="control-group">
<div class="controls">
<button class="btn btn-primary show-modal" data-modal-id="testEmail">{{ label_test }}</button>
<input type="hidden" name="test_email" value="0" />
</div>
</div>
<div class="form-actions">
<button class="btn btn-success" type="submit" name="email_submit" >{{ label_save }}</button>
</div>
</fieldset>
</div>
<div id="config-sms" class="tab-pane {{ sms_active }}">
<fieldset>
<legend>{{ label_settings_sms }}</legend>
<div class="control-group">
<div class="controls">
<label class="checkbox" for="sms_status"><input type="checkbox" id="sms_status" name="sms_status[]" {{ sms_status_checked|raw }} /> {{ label_sms_status }}</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox"><input type="checkbox" id="log_sms" name="log_sms[]" {{ log_sms_checked|raw }} /> {{ label_log_sms }}</label>
</div>
</div>
<div class="control-group">
<label class="control-label" for="sms_gateway">{{ label_sms_gateway }}</label>
<div class="controls">
<select id="sms_gateway" name="sms_gateway">
{% for sms_gateway in sms_gateways %}
<option value="{{ sms_gateway.value }}" {% if sms_gateway.value == sms_gateway_current %} selected="selected" {% endif %}>{{ sms_gateway.label }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="control-group">
<label class="control-label" for="sms_gateway_username">{{ label_sms_gateway_username }}</label>
<div class="controls">
<input type="text" id="sms_gateway_username" name="sms_gateway_username" value="{{ sms_gateway_username }}" maxlength="255" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="sms_gateway_password">{{ label_sms_gateway_password }}</label>
<div class="controls">
<input type="password" id="sms_gateway_password" name="sms_gateway_password" value="{{ sms_gateway_password }}" maxlength="255" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="sms_from">{{ label_sms_from }}</label>
<div class="controls">
<input type="text" id="sms_from" name="sms_from" value="{{ sms_from }}" maxlength="255" />
</div>
</div>
<div class="control-group">
<div class="controls">
<button class="btn btn-primary show-modal" data-modal-id="testSms">{{ label_test }}</button>
<input type="hidden" name="test_sms" value="0" />
</div>
</div>
<div class="form-actions">
<button class="btn btn-success" type="submit" name="sms_submit">{{ label_save }}</button>
</div>
</fieldset>
</div>
<div id="config-pushover" class="tab-pane {{ pushover_active }}">
<fieldset>
<legend>{{ label_settings_pushover }}</legend>
<div class="control-group">
<div class="controls">
<label class="checkbox" for="pushover_status"><input type="checkbox" id="pushover_status" name="pushover_status[]" {{ pushover_status_checked|raw }} /> {{ label_pushover_status }}</label>
<p class="help-block">{{ label_pushover_description|raw }}</p>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox"><input type="checkbox" id="log_pushover" name="log_pushover[]" {{ log_pushover_checked|raw }} /> {{ label_log_pushover }}</label>
</div>
</div>
<div class="control-group">
<label class="control-label" for="pushover_api_token">{{ label_pushover_api_token }}</label>
<div class="controls">
<p><button class="btn btn-primary" onclick="window.open('{{ pushover_clone_url }}');return false;">{{ label_pushover_clone_app }}</button></p>
<input type="text" id="pushover_api_token" name="pushover_api_token" value="{{ pushover_api_token }}" maxlength="255" />
<p class="help-block">{{ label_pushover_api_token_description|raw }}</p>
</div>
</div>
<div class="control-group">
<div class="controls">
<button class="btn btn-primary show-modal" data-modal-id="testPushover">{{ label_test }}</button>
<input type="hidden" name="test_pushover" value="0" />
</div>
</div>
<div class="form-actions">
<button class="btn btn-success" type="submit" name="pushover_submit">{{ label_save }}</button>
</div>
</fieldset>
</div>
<div id="config-telegram" class="tab-pane {{ telegram_active }}">
<fieldset>
<legend>{{ label_settings_telegram }}</legend>
<div class="control-group">
<div class="controls">
<label class="checkbox" for="telegram_status"><input type="checkbox" id="telegram_status" name="telegram_status[]" {{ telegram_status_checked|raw }} /> {{ label_telegram_status }}</label>
<p class="help-block">{{ label_telegram_description|raw }}</p>
</div>
</div> </div>
<div class="control-group"> <div id="config-email" class="tab-pane {{ email_active }}">
<div class="controls"> <fieldset>
<label class="checkbox"><input type="checkbox" id="log_telegram" name="log_telegram[]" {{ log_telegram_checked|raw }} /> {{ label_log_telegram }}</label> <legend>{{ label_settings_email }}</legend>
</div> <div class="control-group">
<div class="controls">
<label class="checkbox" for="email_status"><input type="checkbox" id="email_status" name="email_status[]"
{{ email_status_checked|raw }} /> {{ label_email_status }}</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox"><input type="checkbox" id="log_email" name="log_email[]" {{ log_email_checked|raw
}} /> {{ label_log_email }}</label>
</div>
</div>
<div class="control-group">
<label class="control-label" for="email_from_name">{{ label_email_from_name }}</label>
<div class="controls">
<input type="text" id="email_from_name" name="email_from_name" value="{{ email_from_name }}" maxlength="255" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="email_from_email">{{ label_email_from_email }}</label>
<div class="controls">
<input type="text" id="email_from_email" name="email_from_email" value="{{ email_from_email }}" maxlength="255" />
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox" for="email_smtp"><input type="checkbox" id="email_smtp" name="email_smtp[]"
{{ email_smtp_checked|raw }} />{{ label_email_smtp }}</label>
</div>
</div>
<div class="control-group">
<label class="control-label" for="email_smtp_host">{{ label_email_smtp_host }}</label>
<div class="controls">
<input type="text" id="email_smtp_host" name="email_smtp_host" value="{{ email_smtp_host }}" maxlength="100" placeholder="{{ label_email_smtp_host }}"
/>
<input type="text" class="input-small" id="email_smtp_port" name="email_smtp_port" value="{{ email_smtp_port }}" maxlength="10"
placeholder="{{ label_email_smtp_port }}" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="email_smtp_security">{{ label_email_smtp_security }}</label>
<div class="controls">
<select id="email_smtp_security" name="email_smtp_security">
<option value="" {{ email_smtp_security_selected_|raw }}>{{ label_email_smtp_security_none }}</option>
<option value="ssl" {{ email_smtp_security_selected_ssl|raw }}>SSL</option>
<option value="tls" {{ email_smtp_security_selected_tls|raw }}>TLS</option>
</select>
</div>
</div>
<div class="control-group">
<label class="control-label" for="email_smtp_username">{{ label_email_smtp_username }}</label>
<div class="controls">
<input type="text" id="email_smtp_username" name="email_smtp_username" value="{{ email_smtp_username }}" maxlength="100"
placeholder="{{ label_email_smtp_noauth }}" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="email_smtp_password">{{ label_email_smtp_password }}</label>
<div class="controls">
<input type="password" id="email_smtp_password" name="email_smtp_password" value="{{ email_smtp_password }}" maxlength="100"
placeholder="{{ label_email_smtp_noauth }}" />
</div>
</div>
<div class="control-group">
<div class="controls">
<button class="btn btn-primary show-modal" data-modal-id="testEmail">{{ label_test }}</button>
<input type="hidden" name="test_email" value="0" />
</div>
</div>
<div class="form-actions">
<button class="btn btn-success" type="submit" name="email_submit">{{ label_save }}</button>
</div>
</fieldset>
</div> </div>
<div class="control-group"> <div id="config-sms" class="tab-pane {{ sms_active }}">
<label class="control-label" for="telegram_api_token">{{ label_telegram_api_token }}</label> <fieldset>
<div class="controls"> <legend>{{ label_settings_sms }}</legend>
<input type="text" id="telegram_api_token" name="telegram_api_token" value="{{ telegram_api_token }}" maxlength="255" /> <div class="control-group">
<p class="help-block">{{ label_telegram_api_token_description|raw }}</p> <div class="controls">
</div> <label class="checkbox" for="sms_status"><input type="checkbox" id="sms_status" name="sms_status[]"
{{ sms_status_checked|raw }} /> {{ label_sms_status }}</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox"><input type="checkbox" id="log_sms" name="log_sms[]" {{ log_sms_checked|raw
}} /> {{ label_log_sms }}</label>
</div>
</div>
<div class="control-group">
<label class="control-label" for="sms_gateway">{{ label_sms_gateway }}</label>
<div class="controls">
<select id="sms_gateway" name="sms_gateway">
{% for sms_gateway in sms_gateways %}
<option value="{{ sms_gateway.value }}" {% if sms_gateway.value==sms_gateway_current %} selected="selected" {% endif %}>{{
sms_gateway.label }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="control-group">
<label class="control-label" for="sms_gateway_username">{{ label_sms_gateway_username }}</label>
<div class="controls">
<input type="text" id="sms_gateway_username" name="sms_gateway_username" value="{{ sms_gateway_username }}" maxlength="255"
/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="sms_gateway_password">{{ label_sms_gateway_password }}</label>
<div class="controls">
<input type="password" id="sms_gateway_password" name="sms_gateway_password" value="{{ sms_gateway_password }}" maxlength="255"
/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="sms_from">{{ label_sms_from }}</label>
<div class="controls">
<input type="text" id="sms_from" name="sms_from" value="{{ sms_from }}" maxlength="255" />
</div>
</div>
<div class="control-group">
<div class="controls">
<button class="btn btn-primary show-modal" data-modal-id="testSms">{{ label_test }}</button>
<input type="hidden" name="test_sms" value="0" />
</div>
</div>
<div class="form-actions">
<button class="btn btn-success" type="submit" name="sms_submit">{{ label_save }}</button>
</div>
</fieldset>
</div> </div>
<div class="control-group"> <div id="config-pushover" class="tab-pane {{ pushover_active }}">
<div class="controls"> <fieldset>
<button class="btn btn-primary show-modal" data-modal-id="testTelegram">{{ label_test }}</button> <legend>{{ label_settings_pushover }}</legend>
<input type="hidden" name="test_telegram" value="0" /> <div class="control-group">
</div> <div class="controls">
<label class="checkbox" for="pushover_status"><input type="checkbox" id="pushover_status" name="pushover_status[]"
{{ pushover_status_checked|raw }} /> {{ label_pushover_status }}</label>
<p class="help-block">{{ label_pushover_description|raw }}</p>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox"><input type="checkbox" id="log_pushover" name="log_pushover[]" {{ log_pushover_checked|raw
}} /> {{ label_log_pushover }}</label>
</div>
</div>
<div class="control-group">
<label class="control-label" for="pushover_api_token">{{ label_pushover_api_token }}</label>
<div class="controls">
<p><button class="btn btn-primary" onclick="window.open('{{ pushover_clone_url }}');return false;">{{
label_pushover_clone_app }}</button></p>
<input type="text" id="pushover_api_token" name="pushover_api_token" value="{{ pushover_api_token }}" maxlength="255" />
<p class="help-block">{{ label_pushover_api_token_description|raw }}</p>
</div>
</div>
<div class="control-group">
<div class="controls">
<button class="btn btn-primary show-modal" data-modal-id="testPushover">{{ label_test }}</button>
<input type="hidden" name="test_pushover" value="0" />
</div>
</div>
<div class="form-actions">
<button class="btn btn-success" type="submit" name="pushover_submit">{{ label_save }}</button>
</div>
</fieldset>
</div> </div>
<div class="form-actions"> <div id="config-telegram" class="tab-pane {{ telegram_active }}">
<button class="btn btn-success" type="submit" name="telegram_submit">{{ label_save }}</button> <fieldset>
<legend>{{ label_settings_telegram }}</legend>
<div class="control-group">
<div class="controls">
<label class="checkbox" for="telegram_status"><input type="checkbox" id="telegram_status" name="telegram_status[]"
{{ telegram_status_checked|raw }} /> {{ label_telegram_status }}</label>
<p class="help-block">{{ label_telegram_description|raw }}</p>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox"><input type="checkbox" id="log_telegram" name="log_telegram[]" {{ log_telegram_checked|raw
}} /> {{ label_log_telegram }}</label>
</div>
</div>
<div class="control-group">
<label class="control-label" for="telegram_api_token">{{ label_telegram_api_token }}</label>
<div class="controls">
<input type="text" id="telegram_api_token" name="telegram_api_token" value="{{ telegram_api_token }}" maxlength="255" />
<p class="help-block">{{ label_telegram_api_token_description|raw }}</p>
</div>
</div>
<div class="control-group">
<div class="controls">
<button class="btn btn-primary show-modal" data-modal-id="testTelegram">{{ label_test }}</button>
<input type="hidden" name="test_telegram" value="0" />
</div>
</div>
<div class="form-actions">
<button class="btn btn-success" type="submit" name="telegram_submit">{{ label_save }}</button>
</div>
</fieldset>
</div> </div>
</fieldset>
</div> </div>
</div> {{ macro.csrf_input() }}
{{ macro.csrf_input() }} </form>
</form>