2014-03-21 16:38:48 +01:00
< ? php
/**
* PHP Server Monitor
* Monitor your servers and websites .
*
* This file is part of PHP Server Monitor .
* PHP Server Monitor is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* PHP Server Monitor is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with PHP Server Monitor . If not , see < http :// www . gnu . org / licenses />.
*
* @ package phpservermon
2017-04-15 21:34:49 +02:00
* @ author Pepijn Over < pep @ mailbox . org >
* @ copyright Copyright ( c ) 2008 - 2017 Pepijn Over < pep @ mailbox . org >
2014-03-21 16:38:48 +01:00
* @ license http :// www . gnu . org / licenses / gpl . txt GNU GPL v3
* @ version Release : @ package_version @
* @ link http :// www . phpservermonitor . org /
**/
/**
* The status updater is for sending notifications to the users .
*
2014-08-06 13:14:41 +02:00
* @ see \psm\Util\Server\Updater\StatusUpdater
* @ see \psm\Util\Server\Updater\Autorun
2014-03-21 16:38:48 +01:00
*/
2014-08-06 13:14:41 +02:00
namespace psm\Util\Server\Updater ;
2014-03-21 16:38:48 +01:00
use psm\Service\Database ;
class StatusNotifier {
/**
* Database service
* @ var \psm\Service\Database $db
*/
protected $db ;
/**
* Send emails ?
* @ var boolean $send_emails
*/
protected $send_emails = false ;
/**
* Send sms ?
* @ var boolean $send_sms
*/
protected $send_sms = false ;
2014-06-13 17:34:09 +02:00
/**
2018-02-25 17:06:18 +01:00
* Send Pushover notification ?
2014-06-13 17:34:09 +02:00
* @ var boolean $send_pushover
*/
protected $send_pushover = false ;
2018-02-26 23:23:50 +01:00
/**
* Send telegram ?
* @ var boolean $send_telegram
*/
protected $send_telegram = false ;
2014-03-21 16:38:48 +01:00
/**
* Save log records ?
* @ var boolean $save_log
*/
protected $save_logs = false ;
2018-09-05 23:03:29 +02:00
/**
* 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 ()
);
2014-03-21 16:38:48 +01:00
/**
* Server id
* @ var int $server_id
*/
protected $server_id ;
/**
* Server information
* @ var array $server
*/
protected $server ;
/**
* Old status
* @ var boolean $status_old
*/
protected $status_old ;
/**
* New status
* @ var boolean $status_new
*/
protected $status_new ;
function __construct ( Database $db ) {
$this -> db = $db ;
$this -> send_emails = psm_get_conf ( 'email_status' );
$this -> send_sms = psm_get_conf ( 'sms_status' );
2014-06-13 17:34:09 +02:00
$this -> send_pushover = psm_get_conf ( 'pushover_status' );
2018-02-26 23:23:50 +01:00
$this -> send_telegram = psm_get_conf ( 'telegram_status' );
2014-03-21 16:38:48 +01:00
$this -> save_logs = psm_get_conf ( 'log_status' );
2018-09-05 23:03:29 +02:00
$this -> combine = psm_get_conf ( 'combine_notifications' );
2014-03-21 16:38:48 +01:00
}
2018-09-05 23:03:29 +02:00
/**
* This function initializes the sending ( text msg , email , Pushover and Telegram ) and logging
*
* @ param int $server_id
* @ param boolean $status_old
* @ param boolean $status_new
* @ return boolean
* @ throws \PHPMailer\PHPMailer\Exception
*/
2014-03-21 16:38:48 +01:00
public function notify ( $server_id , $status_old , $status_new ) {
2018-09-05 23:03:29 +02:00
if (
! $this -> send_emails &&
! $this -> send_sms &&
! $this -> send_pushover &&
! $this -> send_telegram &&
! $this -> save_logs
) {
2014-03-21 16:38:48 +01:00
// seems like we have nothing to do. skip the rest
return false ;
}
$this -> server_id = $server_id ;
$this -> status_old = $status_old ;
$this -> status_new = $status_new ;
// get server info from db
2018-09-05 23:03:29 +02:00
// only get info that will be put into the notification
// or is needed to check if a notification need to be send
2018-07-05 19:59:57 +02:00
$this -> server = $this -> db -> selectRow ( PSM_DB_PREFIX . 'servers' , array (
2014-03-21 16:38:48 +01:00
'server_id' => $server_id ,
), array (
2018-09-05 23:03:29 +02:00
'server_id' , 'ip' , 'port' , 'label' , 'error' , 'email' , 'sms' , 'pushover' , 'telegram' , 'last_online' , 'last_offline' , 'last_offline_duration' ,
2014-03-21 16:38:48 +01:00
));
2018-07-05 19:59:57 +02:00
if ( empty ( $this -> server )) {
2014-03-21 16:38:48 +01:00
return false ;
}
$notify = false ;
// check which type of alert the user wants
2018-07-05 19:59:57 +02:00
switch ( psm_get_conf ( 'alert_type' )) {
2014-03-21 16:38:48 +01:00
case 'always' :
2018-07-05 19:59:57 +02:00
if ( $status_new == false ) {
2014-03-21 16:38:48 +01:00
// server is offline. we are in error state.
$notify = true ;
}
break ;
case 'offline' :
// only send a notification if the server goes down for the first time!
2018-07-05 19:59:57 +02:00
if ( $status_new == false && $status_old == true ) {
2014-03-21 16:38:48 +01:00
$notify = true ;
}
break ;
case 'status' :
2018-07-05 19:59:57 +02:00
if ( $status_new != $status_old ) {
2014-03-21 16:38:48 +01:00
// status has been changed!
$notify = true ;
}
break ;
}
2018-07-05 19:59:57 +02:00
if ( ! $notify ) {
2014-03-24 20:15:53 +01:00
return false ;
}
2014-03-21 16:38:48 +01:00
// first add to log (we use the same text as the SMS message because its short..)
2018-07-05 19:59:57 +02:00
if ( $this -> save_logs ) {
2014-03-21 16:38:48 +01:00
psm_add_log (
$this -> server_id ,
'status' ,
psm_parse_msg ( $status_new , 'sms' , $this -> server )
);
}
2014-07-31 12:11:32 +02:00
$users = $this -> getUsers ( $this -> server_id );
2018-07-05 19:59:57 +02:00
if ( empty ( $users )) {
2014-07-31 12:11:32 +02:00
return $notify ;
}
2018-09-05 23:03:29 +02:00
if ( $this -> combine ){
$this -> setCombi ( 'init' , $users );
}
2014-03-21 16:38:48 +01:00
// check if email is enabled for this server
2018-07-05 19:59:57 +02:00
if ( $this -> send_emails && $this -> server [ 'email' ] == 'yes' ) {
2014-03-21 16:38:48 +01:00
// send email
2018-09-05 23:03:29 +02:00
$this -> combine ? $this -> setCombi ( 'email' ) : $this -> notifyByEmail ( $users );
2014-03-21 16:38:48 +01:00
}
// check if sms is enabled for this server
2018-07-05 19:59:57 +02:00
if ( $this -> send_sms && $this -> server [ 'sms' ] == 'yes' ) {
2018-09-05 23:03:29 +02:00
// sms will not be send combined as some gateways don't support long sms / charge extra
2014-03-21 16:38:48 +01:00
// yay lets wake those nerds up!
2014-07-31 12:11:32 +02:00
$this -> notifyByTxtMsg ( $users );
2014-03-21 16:38:48 +01:00
}
2014-06-13 17:34:09 +02:00
// check if pushover is enabled for this server
2018-07-05 19:59:57 +02:00
if ( $this -> send_pushover && $this -> server [ 'pushover' ] == 'yes' ) {
2014-06-13 17:34:09 +02:00
// yay lets wake those nerds up!
2018-09-05 23:03:29 +02:00
$this -> combine ? $this -> setCombi ( 'pushover' ) : $this -> notifyByPushover ( $users );
2014-06-13 17:34:09 +02:00
}
2018-02-26 23:23:50 +01:00
// check if telegram is enabled for this server
2018-07-05 19:59:57 +02:00
if ( $this -> send_telegram && $this -> server [ 'telegram' ] == 'yes' ) {
2018-09-05 23:03:29 +02:00
$this -> combine ? $this -> setCombi ( 'telegram' ) : $this -> notifyByTelegram ( $users );
2018-02-26 23:23:50 +01:00
}
2014-03-21 16:38:48 +01:00
return $notify ;
}
2018-09-05 23:03:29 +02:00
/**
* This functions collects all of the notifications
*
* @ param string $method notification method
* @ param array $users Users
* @ return void
*/
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 ){
$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 ()) {
2014-03-21 16:38:48 +01:00
// build mail object with some default values
$mail = psm_build_mail ();
2018-09-05 23:03:29 +02:00
$mail -> Subject = key_exists ( 'subject' , $combi ) ?
$combi [ 'subject' ] :
psm_parse_msg ( $this -> status_new , 'email_subject' , $this -> server );
2018-07-05 19:59:57 +02:00
$mail -> Priority = 1 ;
2014-03-21 16:38:48 +01:00
2018-09-05 23:03:29 +02:00
$body = key_exists ( 'message' , $combi ) ?
$combi [ 'message' ] :
psm_parse_msg ( $this -> status_new , 'email_body' , $this -> server );
2018-02-25 01:17:27 +01:00
$mail -> Body = $body ;
$mail -> AltBody = str_replace ( '<br/>' , " \n " , $body );
2014-03-21 16:38:48 +01:00
2018-07-05 19:59:57 +02:00
if ( psm_get_conf ( 'log_email' )) {
$log_id = psm_add_log ( $this -> server_id , 'email' , $body );
}
2014-10-01 20:50:37 +02:00
2014-03-21 16:38:48 +01:00
// go through empl
2018-07-05 19:59:57 +02:00
foreach ( $users as $user ) {
if ( ! empty ( $log_id )) {
psm_add_log_user ( $log_id , $user [ 'user_id' ]);
}
2018-09-05 23:03:29 +02:00
// we sent a separate email to every single user.
2018-07-05 19:59:57 +02:00
$mail -> AddAddress ( $user [ 'email' ], $user [ 'name' ]);
$mail -> Send ();
$mail -> ClearAddresses ();
}
2018-09-05 23:03:29 +02:00
return ;
2014-03-21 16:38:48 +01:00
}
2014-06-13 17:34:09 +02:00
/**
* This functions performs the pushover notifications
*
2018-09-05 23:03:29 +02:00
* @ param \PDOStatement $users
* @ param array $combi contains message and subject ( optional )
* @ return void
2014-06-13 17:34:09 +02:00
*/
2018-09-05 23:03:29 +02:00
protected function notifyByPushover ( $users , $combi = array ()) {
2018-07-05 19:59:57 +02:00
// Remove users that have no pushover_key
foreach ( $users as $k => $user ) {
if ( trim ( $user [ 'pushover_key' ]) == '' ) {
unset ( $users [ $k ]);
}
}
// Validation
if ( empty ( $users )) {
return ;
}
// Pushover
2018-09-05 23:03:29 +02:00
$message = key_exists ( 'message' , $combi ) ?
$combi [ 'message' ] :
psm_parse_msg ( $this -> status_new , 'pushover_message' , $this -> server );
2018-07-05 19:59:57 +02:00
$pushover = psm_build_pushover ();
if ( $this -> status_new === true ) {
$pushover -> setPriority ( 0 );
} else {
$pushover -> setPriority ( 2 );
$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.
}
2018-09-05 23:03:29 +02:00
$title = key_exists ( 'subject' , $combi ) ?
$combi [ 'subject' ] :
psm_parse_msg ( $this -> status_new , 'pushover_title' , $this -> server );
$pushover -> setHtml ( 1 );
$pushover -> setTitle ( $title );
2014-06-13 17:34:09 +02:00
$pushover -> setMessage ( str_replace ( '<br/>' , " \n " , $message ));
2014-09-12 01:08:04 +02:00
$pushover -> setUrl ( psm_build_url ());
$pushover -> setUrlTitle ( psm_get_lang ( 'system' , 'title' ));
2014-07-31 12:11:32 +02:00
2018-07-05 19:59:57 +02:00
// Log
if ( psm_get_conf ( 'log_pushover' )) {
$log_id = psm_add_log ( $this -> server_id , 'pushover' , $message );
}
2014-10-01 20:50:37 +02:00
2018-07-05 19:59:57 +02:00
foreach ( $users as $user ) {
// Log
if ( ! empty ( $log_id )) {
psm_add_log_user ( $log_id , $user [ 'user_id' ]);
}
2014-10-01 20:50:37 +02:00
2018-07-05 19:59:57 +02:00
// Set recipient + send
2014-06-13 17:34:09 +02:00
$pushover -> setUser ( $user [ 'pushover_key' ]);
2018-07-05 19:59:57 +02:00
if ( $user [ 'pushover_device' ] != '' ) {
2014-07-31 12:11:32 +02:00
$pushover -> setDevice ( $user [ 'pushover_device' ]);
}
2014-06-13 17:34:09 +02:00
$pushover -> send ();
2018-07-05 19:59:57 +02:00
}
2014-06-13 17:34:09 +02:00
}
2014-03-21 16:38:48 +01:00
/**
* This functions performs the text message notifications
*
2018-09-05 23:03:29 +02:00
* @ param \PDOStatement $users
2014-07-31 12:11:32 +02:00
* @ return boolean
2014-03-21 16:38:48 +01:00
*/
2014-07-31 12:11:32 +02:00
protected function notifyByTxtMsg ( $users ) {
2014-04-23 16:09:45 +02:00
$sms = psm_build_sms ();
2018-07-05 19:59:57 +02:00
if ( ! $sms ) {
2014-04-23 16:09:45 +02:00
return false ;
}
2014-03-21 16:38:48 +01:00
2018-07-05 19:59:57 +02:00
$message = psm_parse_msg ( $this -> status_new , 'sms' , $this -> server );
2014-10-01 20:50:37 +02:00
2018-07-05 19:59:57 +02:00
// Log
if ( psm_get_conf ( 'log_sms' )) {
$log_id = psm_add_log ( $this -> server_id , 'sms' , $message );
2014-10-01 20:50:37 +02:00
}
2014-03-21 16:38:48 +01:00
// add all users to the recipients list
foreach ( $users as $user ) {
2018-07-05 19:59:57 +02:00
// Log
if ( ! empty ( $log_id )) {
psm_add_log_user ( $log_id , $user [ 'user_id' ]);
}
2014-10-01 20:50:37 +02:00
2014-03-21 16:38:48 +01:00
$sms -> addRecipients ( $user [ 'mobile' ]);
}
// Send sms
$result = $sms -> sendSMS ( $message );
return $result ;
}
2018-02-26 23:23:50 +01:00
/**
* This functions performs the telegram notifications
*
2018-09-05 23:03:29 +02:00
* @ param \PDOStatement $users
* @ param array $combi contains message and subject ( optional )
* @ return void
2018-02-26 23:23:50 +01:00
*/
2018-09-05 23:03:29 +02:00
protected function notifyByTelegram ( $users , $combi = array ()) {
// Remove users that have no telegram_id
foreach ( $users as $k => $user ) {
if ( trim ( $user [ 'telegram_id' ]) == '' ) {
unset ( $users [ $k ]);
}
}
// Validation
if ( empty ( $users )) {
return ;
}
// Telegram
$message = key_exists ( 'message' , $combi ) ?
$combi [ 'message' ] :
psm_parse_msg ( $this -> status_new , 'telegram_message' , $this -> server );
$telegram = psm_build_telegram ();
$telegram -> setMessage ( $message );
// Log
if ( psm_get_conf ( 'log_telegram' )) {
$log_id = psm_add_log ( $this -> server_id , 'telegram' , $message );
2018-07-05 19:59:57 +02:00
}
2018-09-05 23:03:29 +02:00
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 ();
}
}
2018-02-26 23:23:50 +01:00
2014-03-21 16:38:48 +01:00
/**
* Get all users for the provided server id
* @ param int $server_id
2018-07-11 00:27:06 +02:00
* @ return \PDOStatement array
2014-03-21 16:38:48 +01:00
*/
public function getUsers ( $server_id ) {
// find all the users with this server listed
$users = $this -> db -> query ( "
2018-02-26 23:23:50 +01:00
SELECT `u` . `user_id` , `u` . `name` , `u` . `email` , `u` . `mobile` , `u` . `pushover_key` , `u` . `pushover_device` , `u` . `telegram_id`
2014-03-21 16:38:48 +01:00
FROM `".PSM_DB_PREFIX."users` AS `u`
JOIN `".PSM_DB_PREFIX."users_servers` AS `us` ON (
`us` . `user_id` = `u` . `user_id`
AND `us` . `server_id` = { $server_id }
)
" );
return $users ;
}
2018-02-25 01:17:27 +01:00
}