From 14f6e491cf304995265d188ee06fc2f049d0d2fe Mon Sep 17 00:00:00 2001 From: Malte Grosse Date: Wed, 12 Aug 2020 19:27:13 +0200 Subject: [PATCH] webhook support (#951) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added webhook support * Added missing upgrade lines * Removed todo * Removed linebreak * Moved webhook below Jabber * Fixed description not showing * Moved webhook below jabber * Indentation and table name fix * Bumped version * Fixed “header already sent” error Co-authored-by: TimZ99 --- src/includes/functions.inc.php | 620 +++++++++++------- src/includes/psmconfig.inc.php | 2 +- src/lang/en_US.lang.php | 40 ++ .../Config/Controller/ConfigController.php | 47 +- .../Install/Controller/InstallController.php | 2 + .../Controller/AbstractServerController.php | 1 + .../Server/Controller/LogController.php | 3 +- .../Server/Controller/ServerController.php | 8 +- .../User/Controller/ProfileController.php | 8 +- .../Module/User/Controller/UserController.php | 10 + src/psm/Util/Install/Installer.php | 45 +- src/psm/Util/Server/UpdateManager.php | 2 +- .../Util/Server/Updater/StatusNotifier.php | 58 +- .../default/module/config/config.tpl.html | 25 +- .../module/server/server/list.tpl.html | 5 +- .../module/server/server/update.tpl.html | 4 +- .../module/server/server/view.tpl.html | 15 +- .../default/module/user/profile.tpl.html | 19 +- .../default/module/user/user/update.tpl.html | 4 + 19 files changed, 651 insertions(+), 267 deletions(-) diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index 960c04ba..73128915 100644 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -34,21 +34,21 @@ namespace { # ############################################### -/** - * Retrieve language settings from the selected language file - * Return false if arg is not found - * - * @return string|bool - * @see psm_load_lang() - */ + /** + * Retrieve language settings from the selected language file + * Return false if arg is not found + * + * @return string|bool + * @see psm_load_lang() + */ function psm_get_lang() { $args = func_get_args(); - + if (empty($args)) { return isset($GLOBALS['sm_lang']) ? $GLOBALS['sm_lang'] : $GLOBALS['sm_lang_default']; } - + if (isset($GLOBALS['sm_lang'])) { $lang = $GLOBALS['sm_lang']; $not_found = false; @@ -72,13 +72,13 @@ namespace { return $lang; } -/** - * Load default language from the English (en_US) language file to the $GLOBALS['sm_lang_default'] variable - * Load language from the language file to the $GLOBALS['sm_lang'] variable if language is different from default - * - * @param string $lang language - * @see psm_get_lang() - */ + /** + * Load default language from the English (en_US) language file to the $GLOBALS['sm_lang_default'] variable + * Load language from the language file to the $GLOBALS['sm_lang'] variable if language is different from default + * + * @param string $lang language + * @see psm_get_lang() + */ function psm_load_lang($lang) { // load default language - English (en_US) @@ -86,29 +86,29 @@ namespace { $default_lang_file = PSM_PATH_LANG . 'en_US.lang.php'; file_exists($default_lang_file) ? require $default_lang_file : - trigger_error("English translation needs to be installed at all time!", E_USER_ERROR); + trigger_error("English translation needs to be installed at all time!", E_USER_ERROR); isset($sm_lang) ? $GLOBALS['sm_lang_default'] = $sm_lang : - trigger_error("\$sm_lang not found in English translation!", E_USER_ERROR); + trigger_error("\$sm_lang not found in English translation!", E_USER_ERROR); unset($sm_lang); // load translation is the selected language is not English (en_US) if ($lang != "en_US") { $lang_file = PSM_PATH_LANG . $lang . '.lang.php'; file_exists($lang_file) ? require $lang_file : - trigger_error("Translation file could not be found! Default language will be used.", E_USER_WARNING); - + trigger_error("Translation file could not be found! Default language will be used.", E_USER_WARNING); + isset($sm_lang) ? $GLOBALS['sm_lang'] = $sm_lang : - trigger_error("\$sm_lang not found in translation file! Default language will be used.", E_USER_WARNING); + trigger_error("\$sm_lang not found in translation file! Default language will be used.", E_USER_WARNING); isset($sm_lang['locale']) ? setlocale(LC_TIME, $sm_lang['locale']) : - trigger_error("locale could not ben found in translation file.", E_USER_WARNING); + trigger_error("locale could not ben found in translation file.", E_USER_WARNING); } } -/** - * Retrieve a list with keys of the available languages - * - * @return array - * @see psm_load_lang() - */ + /** + * Retrieve a list with keys of the available languages + * + * @return array + * @see psm_load_lang() + */ function psm_get_langs() { $fn_ext = '.lang.php'; @@ -133,11 +133,11 @@ namespace { return $langs; } -/** - * Retrieve a list with available sms gateways - * - * @return array - */ + /** + * Retrieve a list with available sms gateways + * + * @return array + */ function psm_get_sms_gateways() { $sms_gateway_files = glob(PSM_PATH_SMS_GATEWAY . '*.php'); @@ -155,14 +155,14 @@ namespace { return $sms_gateways; } -/** - * Get a setting from the config. - * - * @param string $key - * @param mixed $alt if not set, return this alternative - * @return string - * @see psm_load_conf() - */ + /** + * Get a setting from the config. + * + * @param string $key + * @param mixed $alt if not set, return this alternative + * @return string + * @see psm_load_conf() + */ function psm_get_conf($key, $alt = null) { if (!isset($GLOBALS['sm_config'])) { @@ -173,13 +173,13 @@ namespace { return $result; } -/** - * Load config from the database to the $GLOBALS['sm_config'] variable - * - * @global object $db - * @return boolean - * @see psm_get_conf() - */ + /** + * Load config from the database to the $GLOBALS['sm_config'] variable + * + * @return boolean + * @global object $db + * @see psm_get_conf() + */ function psm_load_conf() { global $db; @@ -204,14 +204,14 @@ namespace { } } -/** - * Update a config setting. - * - * If the key does not exist yet it will be created. - * @global \psm\Service\Database $db - * @param string $key - * @param string $value - */ + /** + * Update a config setting. + * + * If the key does not exist yet it will be created. + * @param string $key + * @param string $value + * @global \psm\Service\Database $db + */ function psm_update_conf($key, $value) { global $db; @@ -223,8 +223,8 @@ namespace { $db->save( PSM_DB_PREFIX . 'config', array( - 'key' => $key, - 'value' => $value, + 'key' => $key, + 'value' => $value, ) ); } else { @@ -243,16 +243,16 @@ namespace { # ############################################### -/** - * This function merely adds the message to the log table. It does not perform any checks, - * everything should have been handled when calling this function - * - * @param string $server_id - * @param string $type - * @param string $message - * - * @return int log_id - */ + /** + * This function merely adds the message to the log table. It does not perform any checks, + * everything should have been handled when calling this function + * + * @param string $server_id + * @param string $type + * @param string $message + * + * @return int log_id + */ function psm_add_log($server_id, $type, $message) { global $db; @@ -260,19 +260,19 @@ namespace { return $db->save( PSM_DB_PREFIX . 'log', array( - 'server_id' => $server_id, - 'type' => $type, - 'message' => $message, + 'server_id' => $server_id, + 'type' => $type, + 'message' => $message, ) ); } -/** - * This function just adds a user to the log_users table. - * - * @param $log_id - * @param $user_id - */ + /** + * This function just adds a user to the log_users table. + * + * @param $log_id + * @param $user_id + */ function psm_add_log_user($log_id, $user_id) { global $db; @@ -280,19 +280,19 @@ namespace { $db->save( PSM_DB_PREFIX . 'log_users', array( - 'log_id' => $log_id, - 'user_id' => $user_id, + 'log_id' => $log_id, + 'user_id' => $user_id, ) ); } -/** - * This function adds the result of a check to the uptime table for logging purposes. - * - * @param int $server_id - * @param int $status - * @param string $latency - */ + /** + * This function adds the result of a check to the uptime table for logging purposes. + * + * @param int $server_id + * @param int $status + * @param string $latency + */ function psm_log_uptime($server_id, $status, $latency) { global $db; @@ -300,62 +300,62 @@ namespace { $db->save( PSM_DB_PREFIX . 'servers_uptime', array( - 'server_id' => $server_id, - 'date' => date('Y-m-d H:i:s'), - 'status' => $status, - 'latency' => $latency, + 'server_id' => $server_id, + 'date' => date('Y-m-d H:i:s'), + 'status' => $status, + 'latency' => $latency, ) ); } -/** - * Converts an interval into a string - * - * @param DateInterval $interval - * @return string - */ + /** + * Converts an interval into a string + * + * @param DateInterval $interval + * @return string + */ function psm_format_interval(DateInterval $interval) { $result = ""; if ($interval->y) { $result .= $interval->format("%y ") . (($interval->y == 1) ? - psm_get_lang('system', 'year') : psm_get_lang('system', 'years')) . " "; + psm_get_lang('system', 'year') : psm_get_lang('system', 'years')) . " "; } if ($interval->m) { $result .= $interval->format("%m ") . (($interval->m == 1) ? - psm_get_lang('system', 'month') : psm_get_lang('system', 'months')) . " "; + psm_get_lang('system', 'month') : psm_get_lang('system', 'months')) . " "; } if ($interval->d) { $result .= $interval->format("%d ") . (($interval->d == 1) ? - psm_get_lang('system', 'day') : psm_get_lang('system', 'days')) . " "; + psm_get_lang('system', 'day') : psm_get_lang('system', 'days')) . " "; } if ($interval->h) { $result .= $interval->format("%h ") . (($interval->h == 1) ? - psm_get_lang('system', 'hour') : psm_get_lang('system', 'hours')) . " "; + psm_get_lang('system', 'hour') : psm_get_lang('system', 'hours')) . " "; } if ($interval->i) { $result .= $interval->format("%i ") . (($interval->i == 1) ? - psm_get_lang('system', 'minute') : psm_get_lang('system', 'minutes')) . " "; + psm_get_lang('system', 'minute') : psm_get_lang('system', 'minutes')) . " "; } if ($interval->s) { $result .= $interval->format("%s ") . (($interval->s == 1) ? - psm_get_lang('system', 'second') : psm_get_lang('system', 'seconds')) . " "; + psm_get_lang('system', 'second') : psm_get_lang('system', 'seconds')) . " "; } return $result; } -/** - * Parses a string from the language file with the correct variables replaced in the message - * - * @param boolean|null $status - * @param string $type is either 'sms', 'email', 'pushover_title', 'pushover_message' or 'telegram_message' - * @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 - */ + /** + * Parses a string from the language file with the correct variables replaced in the message + * + * @param boolean|null $status + * @param string $type is either 'sms', 'email', 'pushover_title', 'pushover_message', 'webhook_title', 'webhook_message' or 'telegram_message' + * @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 + */ function psm_parse_msg($status, $type, $vars, $combi = false) { if (is_bool($status)) { @@ -378,20 +378,20 @@ namespace { return $message; } -/** - * Shortcut to curl_init(), curl_exec and curl_close() - * - * @param string $href - * @param boolean $header return headers? - * @param boolean $body return body? - * @param int|null $timeout connection timeout in seconds. defaults to PSM_CURL_TIMEOUT (10 secs). - * @param boolean $add_agent add user agent? - * @param string|bool $website_username Username website - * @param string|bool $website_password Password website - * @param string|null $request_method Request method like GET, POST etc. - * @param string|null $post_field POST data - * @return array cURL result - */ + /** + * Shortcut to curl_init(), curl_exec and curl_close() + * + * @param string $href + * @param boolean $header return headers? + * @param boolean $body return body? + * @param int|null $timeout connection timeout in seconds. defaults to PSM_CURL_TIMEOUT (10 secs). + * @param boolean $add_agent add user agent? + * @param string|bool $website_username Username website + * @param string|bool $website_password Password website + * @param string|null $request_method Request method like GET, POST etc. + * @param string|null $post_field POST data + * @return array cURL result + */ function psm_curl_get( $href, $header = false, @@ -419,7 +419,7 @@ namespace { curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_ENCODING, ''); curl_setopt($ch, CURLOPT_CERTINFO, 1); - + if (!empty($request_method)) { curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request_method); } @@ -453,32 +453,32 @@ namespace { if ($add_agent) { curl_setopt($ch, CURLOPT_USERAGENT, psm_get_conf('user_agent', 'Mozilla/5.0 (compatible; phpservermon/' . - PSM_VERSION . '; +https://github.com/phpservermon/phpservermon)')); + PSM_VERSION . '; +https://github.com/phpservermon/phpservermon)')); } $result['exec'] = curl_exec($ch); $result['info'] = curl_getinfo($ch); curl_close($ch); - + if (defined('PSM_DEBUG') && PSM_DEBUG === true && psm_is_cli()) { echo PHP_EOL . - '==============cURL Result for: ' . $href . '===========================================' . PHP_EOL; + '==============cURL Result for: ' . $href . '===========================================' . PHP_EOL; print_r($result); echo PHP_EOL . - '==============END cURL Resul for: ' . $href . '===========================================' . PHP_EOL; + '==============END cURL Resul for: ' . $href . '===========================================' . PHP_EOL; } return $result; } -/** - * Get a "nice" timespan message - * - * Source: http://www.interactivetools.com/forum/forum-posts.php?postNum=2208966 - * @param string $time - * @return string - */ + /** + * Get a "nice" timespan message + * + * Source: http://www.interactivetools.com/forum/forum-posts.php?postNum=2208966 + * @param string $time + * @return string + */ function psm_timespan($time) { if (empty($time) || $time == '0000-00-00 00:00:00') { @@ -489,7 +489,7 @@ namespace { } if ($time < strtotime(date('Y-m-d 00:00:00')) - 60 * 60 * 24 * 3) { $format = psm_get_lang('system', (date('Y') !== date('Y', $time)) ? - 'long_day_format' : 'short_day_format'); + 'long_day_format' : 'short_day_format'); // Check for Windows to find and replace the %e // modifier correctly if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { @@ -500,7 +500,7 @@ namespace { $d = time() - $time; if ($d >= 60 * 60 * 24) { $format = psm_get_lang('system', (date('l', time() - 60 * 60 * 24) == date('l', $time)) ? - 'yesterday_format' : 'other_day_format'); + 'yesterday_format' : 'other_day_format'); return strftime($format, $time); } if ($d >= 60 * 60 * 2) { @@ -522,11 +522,11 @@ namespace { return psm_get_lang('system', 'a_second_ago'); } -/** - * Get a localised date from MySQL date format - * @param string $time - * @return string - */ + /** + * Get a localised date from MySQL date format + * @param string $time + * @return string + */ function psm_date($time) { if (empty($time) || $time == '0000-00-00 00:00:00') { @@ -535,12 +535,12 @@ namespace { return strftime('%x %X', strtotime($time)); } -/** - * Check if an update is available for PHP Server Monitor. - * - * Will only check for new version if user turned updates on in config. - * @return boolean - */ + /** + * Check if an update is available for PHP Server Monitor. + * + * Will only check for new version if user turned updates on in config. + * @return boolean + */ function psm_update_available() { if (!psm_get_conf('show_update')) { @@ -582,14 +582,14 @@ namespace { return version_compare($latestVersion, $current, '>'); } -/** - * Prepare a new phpmailer instance. - * - * If the from name and email are left blank they will be prefilled from the config. - * @param string $from_name - * @param string $from_email - * @return \PHPMailer\PHPMailer\PHPMailer - */ + /** + * Prepare a new phpmailer instance. + * + * If the from name and email are left blank they will be prefilled from the config. + * @param string $from_name + * @param string $from_email + * @return \PHPMailer\PHPMailer\PHPMailer + */ function psm_build_mail($from_name = null, $from_email = null) { $phpmailer = new \PHPMailer\PHPMailer\PHPMailer(); @@ -600,7 +600,7 @@ namespace { if (psm_get_conf('email_smtp') == '1') { $phpmailer->IsSMTP(); $phpmailer->Host = psm_get_conf('email_smtp_host'); - $phpmailer->Port = (int) psm_get_conf('email_smtp_port'); + $phpmailer->Port = (int)psm_get_conf('email_smtp_port'); $phpmailer->SMTPSecure = psm_get_conf('email_smtp_security'); $smtp_user = psm_get_conf('email_smtp_username'); @@ -628,11 +628,11 @@ namespace { return $phpmailer; } -/** - * Prepare a new Pushover util. - * - * @return \Pushover - */ + /** + * Prepare a new Pushover util. + * + * @return \Pushover + */ function psm_build_pushover() { $pushover = new \Pushover(); @@ -641,10 +641,22 @@ namespace { return $pushover; } -/** - * - * @return \Telegram - */ + /** + * Prepare a new Webhook util. + * + * @return Webhook + */ + function psm_build_webhook() + { + $webhook = new Webhook(); + + return $webhook; + } + + /** + * + * @return \Telegram + */ function psm_build_telegram() { $telegram = new \Telegram(); @@ -656,12 +668,12 @@ namespace { /** * Send message via XMPP. * - * @param string $host - * @param string $username - * @param string $password - * @param array $receivers - * @param string $message - * @param int|null $port + * @param string $host + * @param string $username + * @param string $password + * @param array $receivers + * @param string $message + * @param int|null $port * @param string|null $domain */ function psm_jabber_send_message($host, $username, $password, $receivers, $message, $port = null, $domain = null) @@ -707,11 +719,11 @@ namespace { } } -/** - * Prepare a new SMS util. - * - * @return \psm\Txtmsg\TxtmsgInterface - */ + /** + * Prepare a new SMS util. + * + * @return \psm\Txtmsg\TxtmsgInterface + */ function psm_build_sms() { $sms = null; @@ -796,20 +808,20 @@ namespace { return $sms; } -/** - * Generate a new link to the current monitor - * @param array|string $params key value pairs or pre-formatted string - * @param boolean $urlencode urlencode all params? - * @param boolean $htmlentities use entities in url? - * @return string - */ + /** + * Generate a new link to the current monitor + * @param array|string $params key value pairs or pre-formatted string + * @param boolean $urlencode urlencode all params? + * @param boolean $htmlentities use entities in url? + * @return string + */ function psm_build_url($params = array(), $urlencode = true, $htmlentities = true) { if (defined('PSM_BASE_URL') && PSM_BASE_URL !== null) { $url = PSM_BASE_URL; } else { $url = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || - $_SERVER['SERVER_PORT'] == 443 ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST']; + $_SERVER['SERVER_PORT'] == 443 ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST']; // on Windows, dirname() adds both back- and forward slashes (http://php.net/dirname). // for urls, we only want the forward slashes. $url .= dirname($_SERVER['SCRIPT_NAME']); @@ -836,12 +848,12 @@ namespace { return $url; } -/** - * Try existence of a GET var, if not return the alternative - * @param string $key - * @param string $alt - * @return mixed - */ + /** + * Try existence of a GET var, if not return the alternative + * @param string $key + * @param string $alt + * @return mixed + */ function psm_GET($key, $alt = null) { if (isset($_GET[$key])) { @@ -851,12 +863,12 @@ namespace { } } -/** - * Try existence of a POST var, if not return the alternative - * @param string $key - * @param string|array|bool $alt - * @return mixed - */ + /** + * Try existence of a POST var, if not return the alternative + * @param string $key + * @param string|array|bool $alt + * @return mixed + */ function psm_POST($key, $alt = null) { if (isset($_POST[$key])) { @@ -866,12 +878,12 @@ namespace { } } -/** - * Check if we are in CLI mode - * - * Note, php_sapi cannot be used because cgi-fcgi returns both for web and cli. - * @return boolean - */ + /** + * Check if we are in CLI mode + * + * Note, php_sapi cannot be used because cgi-fcgi returns both for web and cli. + * @return boolean + */ function psm_is_cli() { return (!isset($_SERVER['SERVER_SOFTWARE']) || php_sapi_name() == 'cli'); @@ -883,11 +895,11 @@ namespace { # ############################################### -/** - * Only used for debugging and testing - * - * @param mixed $arr - */ + /** + * Only used for debugging and testing + * + * @param mixed $arr + */ function pre($arr = null) { echo "
";
@@ -898,9 +910,9 @@ namespace {
         echo "
"; } -/** - * Send headers to the browser to avoid caching - */ + /** + * Send headers to the browser to avoid caching + */ function psm_no_cache() { header("Expires: Mon, 20 Dec 1998 01:00:00 GMT"); @@ -909,14 +921,14 @@ namespace { header("Pragma: no-cache"); } -/** - * Encrypts the password for storage in the database - * - * @param string $key - * @param string $password - * @return string - * @author Pavel Laupe Dvorak - */ + /** + * Encrypts the password for storage in the database + * + * @param string $key + * @param string $password + * @return string + * @author Pavel Laupe Dvorak + */ function psm_password_encrypt($key, $password) { if (empty($password)) { @@ -945,14 +957,14 @@ namespace { return $encrypted; } -/** - * Decrypts password stored in the database for future use - * - * @param string $key - * @param string $encryptedString - * @return string - * @author Pavel Laupe Dvorak - */ + /** + * Decrypts password stored in the database for future use + * + * @param string $key + * @param string $encryptedString + * @return string + * @author Pavel Laupe Dvorak + */ function psm_password_decrypt($key, $encryptedString) { if (empty($encryptedString)) { @@ -960,7 +972,7 @@ namespace { } if (empty($key)) { - throw new \InvalidArgumentException('invalid_encryption_key'); + throw new \InvalidArgumentException('invalid_encryption_key'); } // using open ssl @@ -975,16 +987,16 @@ namespace { OPENSSL_RAW_DATA, $iv ); - + return $decrypted; } -/** -* Send notification to Telegram -* -* @return string -* @author Tim Zandbergen -*/ + /** + * Send notification to Telegram + * + * @return string + * @author Tim Zandbergen + */ class Telegram { private $token; @@ -994,12 +1006,14 @@ namespace { public function setToken($token) { - $this->token = (string) $token; + $this->token = (string)$token; } + public function setUser($user) { - $this->user = (string) $user; + $this->user = (string)$user; } + public function setMessage($message) { $message = str_replace("
    ", "", $message); @@ -1008,8 +1022,9 @@ namespace { $message = str_replace("", "\n", $message); $message = str_replace("
    ", "\n", $message); $message = str_replace("
    ", "\n", $message); - $this->message = (string) $message; + $this->message = (string)$message; } + public function sendurl() { $con = curl_init($this->url); @@ -1020,15 +1035,17 @@ namespace { $response = json_decode($response, true); return $response; } + public function send() { 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) . '&parse_mode=HTML&disable_web_page_preview=True'; + '/sendMessage?chat_id=' . urlencode($this->user) . '&text=' . + urlencode($this->message) . '&parse_mode=HTML&disable_web_page_preview=True'; } return $this->sendurl(); } + // Get the bots username public function getBotUsername() { @@ -1038,4 +1055,121 @@ namespace { return $this->sendurl(); } } + + /** + * Send notification via webhooks + * + * @return string + * @author Malte Grosse + */ + class Webhook + { + protected $url; + protected $json; + protected $message; + + /** + * Send Webhook + * + * @return bool|string + * @var string $message + * + */ + + public function sendWebhook($message) + { + $error = ""; + $success = 1; + + $this->setMessage($message); + $jsonMessage = strtr($this->json, array('#message' => $this->message)); + + $curl = curl_init($this->url); + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $jsonMessage); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5); + curl_setopt($curl, CURLOPT_TIMEOUT, 60); + curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); + $result = curl_exec($curl); + + $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $err = curl_errno($curl); + + if ($err != 0 || $httpcode < 200 || $httpcode >= 300) { + $success = 0; + $error = "HTTP_code: " . $httpcode . ".\ncURL error (" . $err . "): " . $err . ". \nResult: " . $result; + } + + curl_close($curl); + + if ($success) { + return 1; + } + return $error; + } + + /** + * setUrl + * + * @var string $url + * + */ + public function setUrl($url) + { + $this->url = $url; + } + + /** + * getUrl + * + * @return string + */ + public function getUrl() + { + return $this->url; + } + + /** + * setJson + * + * @var string $json + * + */ + public function setJson($json) + { + $this->json = $json; + } + + /** + * getJson + * + * @return string + */ + public function getJson() + { + return $this->json; + } + + /** + * Set message + * + * @return string + * @var string $message + * + */ + public function setMessage($message) + { + $message = str_replace("
      ", "", $message); + $message = str_replace("
    ", "\n", $message); + $message = str_replace("
  • ", "- ", $message); + $message = str_replace("
  • ", "\n", $message); + $message = str_replace("
    ", "\n", $message); + $message = str_replace("
    ", "\n", $message); + $message = str_replace("", "", $message); + $message = str_replace("", "", $message); + $message = strip_tags($message); + $this->message = (string)$message; + } + } } diff --git a/src/includes/psmconfig.inc.php b/src/includes/psmconfig.inc.php index 601cd3c3..25d33fb8 100644 --- a/src/includes/psmconfig.inc.php +++ b/src/includes/psmconfig.inc.php @@ -30,7 +30,7 @@ /** * Current PSM version */ -define('PSM_VERSION', '3.5.2'); +define('PSM_VERSION', '3.6.0.beta1'); /** * URL to check for updates. Will not be checked if turned off on config page. diff --git a/src/lang/en_US.lang.php b/src/lang/en_US.lang.php index fc6cf710..acec4425 100644 --- a/src/lang/en_US.lang.php +++ b/src/lang/en_US.lang.php @@ -138,6 +138,13 @@ $sm_lang = array( 'jabber' => 'Jabber', 'jabber_label' => 'Jabber', 'jabber_description' => 'You Jabber account', + 'webhook' => 'Webhook', + 'webhook_description' => 'Send a json webhook to a certain endpoint.
    The json can be customized, e.g. { +"text":"servermon: #message"}', + 'webhook_url' => 'Webhook Url', + 'webhook_url_description' => 'Webhook public endpoint url, should start with https://.', + 'webhook_json' => 'Webhook JSON', + 'webhook_json_description' => 'Define a custom json, use #message as message variable.', 'delete_title' => 'Delete User', 'delete_message' => 'Are you sure you want to delete user \'%1\'?', 'deleted' => 'User deleted.', @@ -164,6 +171,7 @@ $sm_lang = array( 'email' => 'Email', 'sms' => 'SMS', 'pushover' => 'Pushover', + 'webhook' => 'Webhook', 'telegram' => 'Telegram', 'jabber' => 'Jabber', 'no_logs' => 'No logs', @@ -229,6 +237,8 @@ $sm_lang = array( 'send_email' => 'Send Email', 'sms' => 'SMS', 'send_sms' => 'Send SMS', + 'webhook' => 'Webhook', + 'send_webhook' => 'Send Webhook notification', 'pushover' => 'Pushover', 'send_pushover' => 'Send Pushover notification', 'telegram' => 'Telegram', @@ -268,6 +278,7 @@ $sm_lang = array( 'chart_short_time_format' => '%H:%M', 'warning_notifications_disabled_sms' => 'SMS notifications are disabled.', 'warning_notifications_disabled_email' => 'Email notifications are disabled.', + 'warning_notifications_disabled_webhook' => 'Webhook notifications are disabled.', 'warning_notifications_disabled_pushover' => 'Pushover notifications are disabled.', 'warning_notifications_disabled_telegram' => 'Telegram notifications are disabled.', 'warning_notifications_disabled_jabber' => 'Jabber notifications are disabled.', @@ -309,6 +320,12 @@ $sm_lang = array( 'sms_gateway_username' => 'Gateway username', 'sms_gateway_password' => 'Gateway password', 'sms_from' => 'Sender\'s phone number', + 'webhook_status' => 'Allow sending webhooks', + 'webhook_description' => 'Allow sending webhooks to services like slack. The message payload end endpoint are defined in the profile settings.', + 'webhook_url' => 'Webhook Url', + 'webhook_url_description' => 'Url to webhook endpoint', + 'webhook_json' => 'Webhook Json', + 'webhook_json_description' => 'Customized Json, use #message as message variable.', 'pushover_status' => 'Allow sending Pushover messages', 'pushover_description' => 'Pushover is a service that makes it easy to get real-time notifications. See their website for more info.', @@ -363,17 +380,20 @@ $sm_lang = array( 'log_email' => 'Log emails sent by the script', 'log_sms' => 'Log text messages sent by the script', 'log_pushover' => 'Log pushover messages sent by the script', + 'log_webhook' => 'Log webhook messages sent by the script', 'log_telegram' => 'Log Telegram messages sent by the script', 'log_jabber' => 'Log Jabber messages sent by the script', 'updated' => 'The configuration has been updated.', 'tab_email' => 'Email', 'tab_sms' => 'SMS', 'tab_pushover' => 'Pushover', + 'tab_webhook' => 'Webhook', 'tab_telegram' => 'Telegram', 'tab_jabber' => 'Jabber', 'settings_email' => 'Email settings', 'settings_sms' => 'Text message settings', 'settings_pushover' => 'Pushover settings', + 'settings_webhook' => 'Webhook settings', 'settings_telegram' => 'Telegram settings', 'settings_jabber' => 'Jabber settings', 'settings_notification' => 'Notification settings', @@ -387,6 +407,7 @@ $sm_lang = array( 'test_sms' => 'An SMS will be sent to the phone number specified in your user profile.', 'test_pushover' => 'A Pushover notification will be sent to the user key/device specified in your user profile.', + 'test_webhook' => 'A webhook notification will be sent to the given url endpoint.', 'test_telegram' => 'A Telegram notification will be sent to the chat id specified in your user profile.', 'test_jabber' => 'A Jabber notification will be sent to the jabber account specified in your user profile.', 'send' => 'Send', @@ -397,6 +418,10 @@ $sm_lang = array( 'sms_sent' => 'SMS sent', 'sms_error' => 'An error has occurred while sending the SMS: %s', 'sms_error_nomobile' => 'Unable to send test SMS: no valid phone number found in your profile.', + 'webhook_sent' => 'Webhook notification sent', + 'webhook_error' => 'An error has occurred while sending the webhook notification: %s', + 'webhook_error_nourl' => 'Unable to send test notification: no url found in user profile.', + 'webhook_error_nojson' => 'Unable to send test notification: no json found in user profile.', 'pushover_sent' => 'Pushover notification sent', 'pushover_error' => 'An error has occurred while sending the Pushover notification: %s', 'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global @@ -424,6 +449,9 @@ $sm_lang = array( 'off_email_subject' => 'IMPORTANT: Server \'%LABEL%\' is DOWN', 'off_email_body' => 'Failed to connect to the following server:

    Server: %LABEL%
    IP: %IP%
    Port: %PORT%
    Error: %ERROR%
    Date: %DATE%', + 'off_webhook_title' => 'Server \'%LABEL%\' is DOWN', + 'off_webhook_message' => 'Failed to connect to the following server:

    Server: %LABEL%
    IP: + %IP%
    Port: %PORT%
    Error: %ERROR%
    Date: %DATE%', 'off_pushover_title' => 'Server \'%LABEL%\' is DOWN', 'off_pushover_message' => 'Failed to connect to the following server:

    Server: %LABEL%
    IP: %IP%
    Port: %PORT%
    Error: %ERROR%
    Date: %DATE%', @@ -435,6 +463,10 @@ $sm_lang = array( 'on_email_subject' => 'IMPORTANT: Server \'%LABEL%\' is RUNNING', 'on_email_body' => 'Server \'%LABEL%\' is running again, it was down for %LAST_OFFLINE_DURATION%:

    Server: %LABEL%
    IP: %IP%
    Port: %PORT%
    Date: + %DATE%', + 'on_webhook_title' => 'Server \'%LABEL%\' is RUNNING', + 'on_webhook_message' => 'Server \'%LABEL%\' is running again, it was down for + %LAST_OFFLINE_DURATION%:

    Server: %LABEL%
    IP: %IP%
    Port: %PORT%
    Date: %DATE%', 'on_pushover_title' => 'Server \'%LABEL%\' is RUNNING', 'on_pushover_message' => 'Server \'%LABEL%\' is running again, it was down for @@ -447,6 +479,8 @@ $sm_lang = array( %LAST_OFFLINE_DURATION%

    Server: %LABEL%
    IP: %IP%
    Port: %PORT%
    Date: %DATE%', 'combi_off_email_message' => '
    • Server: %LABEL%
    • IP: %IP%
    • Port: %PORT%
    • Error: + %ERROR%
    • Date: %DATE%
    ', + 'combi_off_webhook_message' => '
    • Server: %LABEL%
    • IP: %IP%
    • Port: %PORT%
    • Error: %ERROR%
    • Date: %DATE%
    ', 'combi_off_pushover_message' => '
    • Server: %LABEL%
    • IP: %IP%
    • Port: %PORT%
    • Error: %ERROR%
    • Date: %DATE%
    ', @@ -456,6 +490,9 @@ $sm_lang = array( Date: %DATE%

    ', 'combi_on_email_message' => '
    • Server: %LABEL%
    • IP: %IP%
    • Port: %PORT%
    • Downtime: %LAST_OFFLINE_DURATION%
    • Date: %DATE%
    ', + 'combi_on_webhook_message' => '
    • Server: %LABEL%
    • IP: %IP%
    • Port: + %PORT%
    • Downtime: %LAST_OFFLINE_DURATION%
    • Date: + %DATE%
    ', 'combi_on_pushover_message' => '
    • Server: %LABEL%
    • IP: %IP%
    • Port: %PORT%
    • Downtime: %LAST_OFFLINE_DURATION%
    • Date: %DATE%
    ', @@ -464,8 +501,11 @@ $sm_lang = array( 'combi_on_jabber_message' => '- Server: %LABEL%
    - IP: %IP%
    - Port: %PORT%
    - Downtime: %LAST_OFFLINE_DURATION%
    - Date: %DATE%

    ', 'combi_email_subject' => 'IMPORTANT: \'%UP%\' servers UP again, \'%DOWN%\' servers DOWN', + 'combi_webhook_subject' => '\'%UP%\' servers UP again, \'%DOWN%\' servers DOWN', 'combi_pushover_subject' => '\'%UP%\' servers UP again, \'%DOWN%\' servers DOWN', 'combi_email_message' => 'The following servers went down:
    %DOWN_SERVERS%
    The following + servers are up again:
    %UP_SERVERS%', + 'combi_webhook_message' => 'The following servers went down:
    %DOWN_SERVERS%
    The following servers are up again:
    %UP_SERVERS%', 'combi_pushover_message' => 'The following servers went down:
    %DOWN_SERVERS%
    The following servers are up again:
    %UP_SERVERS%', diff --git a/src/psm/Module/Config/Controller/ConfigController.php b/src/psm/Module/Config/Controller/ConfigController.php index 7bb78e65..8cf996e3 100644 --- a/src/psm/Module/Config/Controller/ConfigController.php +++ b/src/psm/Module/Config/Controller/ConfigController.php @@ -44,12 +44,14 @@ class ConfigController extends AbstractController 'email_smtp', 'sms_status', 'pushover_status', + 'webhook_status', 'telegram_status', 'jabber_status', 'log_status', 'log_email', 'log_sms', 'log_pushover', + 'log_webhook', 'log_telegram', 'log_jabber', 'show_update', @@ -72,6 +74,8 @@ class ConfigController extends AbstractController 'sms_gateway_username', 'sms_gateway_password', 'sms_from', + 'webhook_url', + 'webhook_json', 'pushover_api_token', 'telegram_api_token', 'jabber_host', @@ -208,7 +212,7 @@ class ConfigController extends AbstractController $tpl_data[$this->default_tab . '_active'] = 'active'; - $testmodals = array('email', 'sms', 'pushover', 'telegram', 'jabber'); + $testmodals = array('email', 'sms', 'pushover','webhook', 'telegram', 'jabber'); foreach ($testmodals as $modal_id) { $modal = new \psm\Util\Module\Modal( $this->twig, @@ -272,6 +276,8 @@ class ConfigController extends AbstractController $this->testSMS(); } elseif (!empty($_POST['test_pushover'])) { $this->testPushover(); + }elseif (!empty($_POST['test_webhook'])) { + $this->testWebhook(); } elseif (!empty($_POST['test_telegram'])) { $this->testTelegram(); } elseif (!empty($_POST['test_jabber'])) { @@ -291,6 +297,8 @@ class ConfigController extends AbstractController $this->default_tab = 'sms'; } elseif (isset($_POST['pushover_submit']) || !empty($_POST['test_pushover'])) { $this->default_tab = 'pushover'; + } elseif (isset($_POST['webhook_submit']) || !empty($_POST['test_webhook'])) { + $this->default_tab = 'webhook'; } elseif (isset($_POST['telegram_submit']) || !empty($_POST['test_telegram'])) { $this->default_tab = 'telegram'; } elseif (isset($_POST['jabber_submit']) || !empty($_POST['test_jabber'])) { @@ -346,6 +354,34 @@ class ConfigController extends AbstractController } } + /** + * Execute webhook test + * + * @todo move test to separate class + */ + protected function testWebhook() + { + + $user = $this->getUser()->getUser(); + + + if (empty($user->webhook_url)) { + $this->addMessage(psm_get_lang('config', 'webhook_error_nourl'), 'error'); + } elseif (empty($user->webhook_json)) { + $this->addMessage(psm_get_lang('config', 'webhook_error_nojson'), 'error'); + } else { + $webhook = psm_build_webhook(); + $webhook->setUrl($user->webhook_url); + $webhook->setJson($user->webhook_json); + $message = (psm_get_lang('config', 'test_message')); + $result = $webhook->sendWebhook($message); + if ($result==1) { + $this->addMessage(psm_get_lang('config', 'webhook_sent'), 'success'); + } else { + $this->addMessage(sprintf(psm_get_lang('config', 'webhook_error'), $result), 'error'); + } + } + } /** * Execute pushover test * @@ -445,10 +481,12 @@ class ConfigController extends AbstractController 'label_tab_email' => psm_get_lang('config', 'tab_email'), 'label_tab_sms' => psm_get_lang('config', 'tab_sms'), 'label_tab_pushover' => psm_get_lang('config', 'tab_pushover'), + 'label_tab_webhook' => psm_get_lang('config', 'tab_webhook'), 'label_tab_telegram' => psm_get_lang('config', 'tab_telegram'), 'label_tab_jabber' => psm_get_lang('config', 'tab_jabber'), 'label_settings_email' => psm_get_lang('config', 'settings_email'), 'label_settings_sms' => psm_get_lang('config', 'settings_sms'), + 'label_settings_webhook' => psm_get_lang('config', 'settings_webhook'), 'label_settings_pushover' => psm_get_lang('config', 'settings_pushover'), 'label_settings_telegram' => psm_get_lang('config', 'settings_telegram'), 'label_settings_jabber' => psm_get_lang('config', 'settings_jabber'), @@ -479,6 +517,12 @@ class ConfigController extends AbstractController 'label_sms_gateway_username' => psm_get_lang('config', 'sms_gateway_username'), 'label_sms_gateway_password' => psm_get_lang('config', 'sms_gateway_password'), 'label_sms_from' => psm_get_lang('config', 'sms_from'), + 'label_webhook_description' => psm_get_lang('config', 'webhook_description'), + 'label_webhook_status' => psm_get_lang('config', 'webhook_status'), + 'label_webhook_url' => psm_get_lang('config', 'webhook_url'), + 'label_webhook_url_description' => psm_get_lang('config', 'webhook_url_description'), + 'label_webhook_json' => psm_get_lang('config', 'webhook_json'), + 'label_webhook_json_description' => psm_get_lang('config', 'webhook_json_description'), 'label_pushover_description' => psm_get_lang('config', 'pushover_description'), 'label_pushover_status' => psm_get_lang('config', 'pushover_status'), 'label_pushover_clone_app' => psm_get_lang('config', 'pushover_clone_app'), @@ -513,6 +557,7 @@ class ConfigController extends AbstractController 'label_log_email' => psm_get_lang('config', 'log_email'), 'label_log_sms' => psm_get_lang('config', 'log_sms'), 'label_log_pushover' => psm_get_lang('config', 'log_pushover'), + 'label_log_webhook' => psm_get_lang('config', 'log_webhook'), 'label_log_telegram' => psm_get_lang('config', 'log_telegram'), 'label_log_jabber' => psm_get_lang('config', 'log_jabber'), 'label_alert_proxy' => psm_get_lang('config', 'alert_proxy'), diff --git a/src/psm/Module/Install/Controller/InstallController.php b/src/psm/Module/Install/Controller/InstallController.php index f51de403..b1b9bc0b 100644 --- a/src/psm/Module/Install/Controller/InstallController.php +++ b/src/psm/Module/Install/Controller/InstallController.php @@ -303,6 +303,8 @@ class InstallController extends AbstractController 'level' => PSM_USER_ADMIN, 'pushover_key' => '', 'pushover_device' => '', + 'webhook_url' => '', + 'webhook_json' => '', 'telegram_id' => '', 'jabber' => '' ); diff --git a/src/psm/Module/Server/Controller/AbstractServerController.php b/src/psm/Module/Server/Controller/AbstractServerController.php index 26ed2c9d..5d191fe3 100644 --- a/src/psm/Module/Server/Controller/AbstractServerController.php +++ b/src/psm/Module/Server/Controller/AbstractServerController.php @@ -81,6 +81,7 @@ abstract class AbstractServerController extends AbstractController `s`.`active`, `s`.`email`, `s`.`sms`, + `s`.`webhook`, `s`.`pushover`, `s`.`telegram`, `s`.`jabber`, diff --git a/src/psm/Module/Server/Controller/LogController.php b/src/psm/Module/Server/Controller/LogController.php index 8046af99..05f26c0d 100644 --- a/src/psm/Module/Server/Controller/LogController.php +++ b/src/psm/Module/Server/Controller/LogController.php @@ -56,6 +56,7 @@ class LogController extends AbstractServerController 'label_email' => psm_get_lang('log', 'email'), 'label_sms' => psm_get_lang('log', 'sms'), 'label_pushover' => psm_get_lang('log', 'pushover'), + 'label_webhook' => psm_get_lang('log', 'webhook'), 'label_telegram' => psm_get_lang('log', 'telegram'), 'label_jabber' => psm_get_lang('log', 'jabber'), 'label_title' => psm_get_lang('log', 'title'), @@ -89,7 +90,7 @@ class LogController extends AbstractServerController ); } - $log_types = array('status', 'email', 'sms', 'pushover', 'telegram', 'jabber'); + $log_types = array('status', 'email', 'sms', 'pushover', 'webhook','telegram', 'jabber'); foreach ($log_types as $key) { $records = $this->getEntries($key); diff --git a/src/psm/Module/Server/Controller/ServerController.php b/src/psm/Module/Server/Controller/ServerController.php index 47e24d9e..1a8ea05f 100644 --- a/src/psm/Module/Server/Controller/ServerController.php +++ b/src/psm/Module/Server/Controller/ServerController.php @@ -101,6 +101,7 @@ class ServerController extends AbstractServerController 'email' => 'icon-envelope', 'sms' => 'icon-mobile', 'pushover' => 'icon-pushover', + 'webhook' => 'icon-webhook', 'telegram' => 'icon-telegram', 'jabber' => 'icon-jabber' ); @@ -130,6 +131,7 @@ class ServerController extends AbstractServerController $tpl_data['config']['email'] = psm_get_conf('email_status'); $tpl_data['config']['sms'] = psm_get_conf('sms_status'); + $tpl_data['config']['webhook'] = psm_get_conf('webhook_status'); $tpl_data['config']['pushover'] = psm_get_conf('pushover_status'); $tpl_data['config']['telegram'] = psm_get_conf('telegram_status'); @@ -237,13 +239,14 @@ class ServerController extends AbstractServerController 'edit_active_selected' => $edit_server['active'], 'edit_email_selected' => $edit_server['email'], 'edit_sms_selected' => $edit_server['sms'], + 'edit_webhook_selected' => $edit_server['webhook'], 'edit_pushover_selected' => $edit_server['pushover'], 'edit_telegram_selected' => $edit_server['telegram'], 'edit_jabber_selected' => $edit_server['jabber'], )); } - $notifications = array('email', 'sms', 'pushover', 'telegram', 'jabber'); + $notifications = array('email', 'sms', 'pushover','webhook', 'telegram', 'jabber'); foreach ($notifications as $notification) { if (psm_get_conf($notification . '_status') == 0) { $tpl_data['warning_' . $notification] = true; @@ -312,6 +315,7 @@ class ServerController extends AbstractServerController 'email' => in_array($_POST['email'], array('yes', 'no')) ? $_POST['email'] : 'no', 'sms' => in_array($_POST['sms'], array('yes', 'no')) ? $_POST['sms'] : 'no', 'pushover' => in_array($_POST['pushover'], array('yes', 'no')) ? $_POST['pushover'] : 'no', + 'webhook' => in_array($_POST['webhook'], array('yes', 'no')) ? $_POST['webhook'] : 'no', 'telegram' => in_array($_POST['telegram'], array('yes', 'no')) ? $_POST['telegram'] : 'no', 'jabber' => in_array($_POST['jabber'], array('yes', 'no')) ? $_POST['jabber'] : 'no', ); @@ -590,8 +594,10 @@ class ServerController extends AbstractServerController 'label_sms' => psm_get_lang('servers', 'sms'), 'label_send_sms' => psm_get_lang('servers', 'send_sms'), 'label_send_pushover' => psm_get_lang('servers', 'send_pushover'), + 'label_send_webhook' => psm_get_lang('servers', 'send_webhook'), 'label_telegram' => psm_get_lang('servers', 'telegram'), 'label_jabber' => psm_get_lang('servers', 'jabber'), + 'label_webhook' => psm_get_lang('servers', 'webhook'), 'label_pushover' => psm_get_lang('servers', 'pushover'), 'label_send_telegram' => psm_get_lang('servers', 'send_telegram'), 'label_send_jabber' => psm_get_lang('servers', 'send_jabber'), diff --git a/src/psm/Module/User/Controller/ProfileController.php b/src/psm/Module/User/Controller/ProfileController.php index 47efc335..74aeec9d 100644 --- a/src/psm/Module/User/Controller/ProfileController.php +++ b/src/psm/Module/User/Controller/ProfileController.php @@ -39,7 +39,7 @@ class ProfileController extends AbstractController * @var array $profile_fields */ protected $profile_fields = - array('name', 'user_name', 'email', 'mobile', 'pushover_key', 'pushover_device', 'telegram_id', 'jabber'); + array('name', 'user_name', 'email', 'mobile', 'pushover_key', 'pushover_device','webhook_url', 'webhook_json', 'telegram_id', 'jabber'); public function __construct(Database $db, \Twig_Environment $twig) { @@ -78,6 +78,12 @@ class ProfileController extends AbstractController 'label_password_repeat' => psm_get_lang('users', 'password_repeat'), 'label_level' => psm_get_lang('users', 'level'), 'label_mobile' => psm_get_lang('users', 'mobile'), + 'label_webhook' => psm_get_lang('users', 'webhook'), + 'label_webhook_description' => psm_get_lang('users', 'webhook_description'), + 'label_webhook_url' => psm_get_lang('users', 'webhook_url'), + 'label_webhook_url_description' => psm_get_lang('users', 'webhook_url_description'), + 'label_webhook_json' => psm_get_lang('users', 'webhook_json'), + 'label_webhook_json_description' => psm_get_lang('users', 'webhook_json_description'), 'label_pushover' => psm_get_lang('users', 'pushover'), 'label_pushover_description' => psm_get_lang('users', 'pushover_description'), 'label_pushover_key' => psm_get_lang('users', 'pushover_key'), diff --git a/src/psm/Module/User/Controller/UserController.php b/src/psm/Module/User/Controller/UserController.php index 1104a4d0..a648ee68 100644 --- a/src/psm/Module/User/Controller/UserController.php +++ b/src/psm/Module/User/Controller/UserController.php @@ -158,6 +158,8 @@ class UserController extends AbstractController 'name', 'user_name', 'mobile', + 'webhook_url', + 'webhook_json', 'pushover_key', 'pushover_device', 'telegram_id', @@ -255,6 +257,8 @@ class UserController extends AbstractController 'password_repeat', 'level', 'mobile', + 'webhook_url', + 'webhook_json', 'pushover_key', 'pushover_device', 'telegram_id', @@ -392,6 +396,12 @@ class UserController extends AbstractController 'label_level' => psm_get_lang('users', 'level'), 'label_level_description' => psm_get_lang('users', 'level_description'), 'label_mobile' => psm_get_lang('users', 'mobile'), + 'label_webhook' => psm_get_lang('users', 'webhook'), + 'label_webhook_description' => psm_get_lang('users', 'webhook_description'), + 'label_webhook_url' => psm_get_lang('users', 'webhook_url'), + 'label_webhook_url_description' => psm_get_lang('users', 'webhook_url_description'), + 'label_webhook_json' => psm_get_lang('users', 'webhook_json'), + 'label_webhook_json_description' => psm_get_lang('users', 'webhook_json_description'), 'label_pushover' => psm_get_lang('users', 'pushover'), 'label_pushover_description' => psm_get_lang('users', 'pushover_description'), 'label_pushover_key' => psm_get_lang('users', 'pushover_key'), diff --git a/src/psm/Util/Install/Installer.php b/src/psm/Util/Install/Installer.php index 888af309..a1476467 100644 --- a/src/psm/Util/Install/Installer.php +++ b/src/psm/Util/Install/Installer.php @@ -134,11 +134,11 @@ class Installer $queries = array(); $queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "servers` ( `ip`, `port`, `label`, `type`, `pattern`, `pattern_online`, `redirect_check`, - `status`, `rtime`, `active`, `email`, `sms`, `pushover`, `telegram`, `jabber`) + `status`, `rtime`, `active`, `email`, `sms`, `pushover`,`webhook`, `telegram`, `jabber`) VALUES ('http://sourceforge.net/index.php', 80, 'SourceForge', 'website', '', - 'yes', 'bad', 'on', '0.0000000', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes'), + 'yes', 'bad', 'on', '0.0000000', 'yes', 'yes', 'yes', 'yes','yes', 'yes', 'yes'), ('smtp.gmail.com', 465, 'Gmail SMTP', 'service', '', - 'yes', 'bad','on', '0.0000000', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes')"; + 'yes', 'bad','on', '0.0000000', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes')"; $queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "users_servers` (`user_id`,`server_id`) VALUES (1, 1), (1, 2);"; $queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "config` (`key`, `value`) VALUE ('language', 'en_US'), @@ -160,6 +160,7 @@ class Installer ('sms_gateway_username', 'username'), ('sms_gateway_password', 'password'), ('sms_from', '1234567890'), + ('webhook_status', '0'), ('pushover_status', '0'), ('pushover_api_token', ''), ('telegram_status', '0'), @@ -176,6 +177,7 @@ class Installer ('log_email', '1'), ('log_sms', '1'), ('log_pushover', '1'), + ('log_webhook', '1'), ('log_telegram', '1'), ('log_jabber', '1'), ('log_retention_period', '365'), @@ -214,7 +216,9 @@ class Installer `mobile` varchar(15) NOT NULL, `pushover_key` varchar(255) NOT NULL, `pushover_device` varchar(255) NOT NULL, - `telegram_id` varchar(255) NOT NULL, + `webhook_url` varchar(255) NOT NULL, + `webhook_json` varchar(255) NOT NULL DEFAULT '{\"text\":\"servermon: #message\"}', + `telegram_id` varchar(255) NOT NULL , `jabber` varchar(255) NOT NULL, `email` varchar(255) NOT NULL, PRIMARY KEY (`user_id`), @@ -235,7 +239,7 @@ class Installer PSM_DB_PREFIX . 'log' => "CREATE TABLE `" . PSM_DB_PREFIX . "log` ( `log_id` int(11) unsigned NOT NULL AUTO_INCREMENT, `server_id` int(11) unsigned NOT NULL, - `type` enum('status','email','sms','pushover','telegram', 'jabber') NOT NULL, + `type` enum('status','email','sms','pushover','webhook','telegram', 'jabber') NOT NULL, `message` TEXT NOT NULL, `datetime` timestamp NOT NULL default CURRENT_TIMESTAMP, PRIMARY KEY (`log_id`) @@ -270,6 +274,7 @@ class Installer `email` enum('yes','no') NOT NULL default 'yes', `sms` enum('yes','no') NOT NULL default 'no', `pushover` enum('yes','no') NOT NULL default 'yes', + `webhook` enum('yes','no') NOT NULL default 'yes', `telegram` enum('yes','no') NOT NULL default 'yes', `jabber` enum('yes','no') NOT NULL default 'yes', `warning_threshold` mediumint(1) unsigned NOT NULL DEFAULT '1', @@ -357,6 +362,9 @@ class Installer if (version_compare($version_from, '3.5.0', '<')) { $this->upgrade350(); } + if (version_compare($version_from, '3.6.0', '<')) { + $this->upgrade360(); + } psm_update_conf('version', $version_to); } @@ -553,7 +561,7 @@ class Installer $this->execSQL($queries); - // Create log_users table + // Create log_users table $this->execSQL("CREATE TABLE `" . PSM_DB_PREFIX . "log_users` ( `log_id` int(11) UNSIGNED NOT NULL , `user_id` int(11) UNSIGNED NOT NULL , @@ -659,7 +667,7 @@ class Installer $this->execSQL($queries); $this->log('Combined notifications enabled. Check out the config page for more info.'); } - + /** * Patch for v3.4.2 release * Version_compare was forgotten in v3.4.1 and query failed. @@ -715,4 +723,27 @@ class Installer $this->execSQL($queries); } + + /** + * Upgrade for v3.6.0 release + */ + protected function upgrade360() + { + $queries = array(); + + $queries[] = 'ALTER TABLE `' . PSM_DB_PREFIX . 'users` + ADD `webhook_url` VARCHAR( 255 ) NOT NULL AFTER `telegram_id`;'; + $queries[] = 'ALTER TABLE `' . PSM_DB_PREFIX . 'users` + ADD `webhook_json` VARCHAR( 255 ) NOT NULL AFTER `telegram_id`;'; + $queries[] = "ALTER TABLE `' . PSM_DB_PREFIX . 'log` + CHANGE `type` `type` ENUM('status','email','sms','webhook','pushover','telegram','jabber') + CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;"; + $queries[] = "ALTER TABLE `' . PSM_DB_PREFIX . 'servers` + ADD `webhook` ENUM( 'yes','no' ) NOT NULL DEFAULT 'yes' AFTER `telegram`;"; + $queries[] = "INSERT INTO `' . PSM_DB_PREFIX . 'config` (`key`, `value`) VALUE + ('webhook_status', '0'), + ('log_webhook', '1')"; + + $this->execSQL($queries); + } } diff --git a/src/psm/Util/Server/UpdateManager.php b/src/psm/Util/Server/UpdateManager.php index e5429df6..2ba6ff0a 100644 --- a/src/psm/Util/Server/UpdateManager.php +++ b/src/psm/Util/Server/UpdateManager.php @@ -69,7 +69,7 @@ class UpdateManager implements ContainerAwareInterface } $sql = "SELECT `s`.`server_id`,`s`.`ip`,`s`.`port`,`s`.`label`,`s`.`type`,`s`.`pattern`,`s`.`header_name`, - `s`.`header_value`,`s`.`status`,`s`.`active`,`s`.`email`,`s`.`sms`,`s`.`pushover`,`s`.`telegram`, + `s`.`header_value`,`s`.`status`,`s`.`active`,`s`.`email`,`s`.`sms`,`s`.`pushover`,`s`.`webhook`,`s`.`telegram`, `s`.`jabber` FROM `" . PSM_DB_PREFIX . "servers` AS `s` {$sql_join} diff --git a/src/psm/Util/Server/Updater/StatusNotifier.php b/src/psm/Util/Server/Updater/StatusNotifier.php index 080f0fbc..263bfdf1 100644 --- a/src/psm/Util/Server/Updater/StatusNotifier.php +++ b/src/psm/Util/Server/Updater/StatusNotifier.php @@ -63,6 +63,12 @@ class StatusNotifier */ protected $send_pushover = false; + /** + * Send webhook notification? + * @var boolean $send_webhook + */ + protected $send_webhook = false; + /** * Send telegram? * @var boolean $send_telegram @@ -128,6 +134,7 @@ class StatusNotifier $this->send_emails = (bool)psm_get_conf('email_status'); $this->send_sms = (bool)psm_get_conf('sms_status'); + $this->send_webhook = (bool)psm_get_conf('webhook_status'); $this->send_pushover = (bool)psm_get_conf('pushover_status'); $this->send_telegram = (bool)psm_get_conf('telegram_status'); $this->send_jabber = (bool)psm_get_conf('jabber_status'); @@ -149,6 +156,7 @@ class StatusNotifier if ( !$this->send_emails && !$this->send_sms && + !$this->send_webhook && !$this->send_pushover && !$this->send_telegram && !$this->send_jabber && @@ -175,6 +183,7 @@ class StatusNotifier 'error', 'email', 'sms', + 'webhook', 'pushover', 'telegram', 'jabber', @@ -245,7 +254,11 @@ class StatusNotifier // yay lets wake those nerds up! $this->notifyByTxtMsg($users); } - + // check if webhook is enabled for this server + if ($this->send_webhook && $this->server['webhook'] == 'yes') { + // yay lets wake those nerds up! + $this->combine ? $this->setCombi('webhook') : $this->notifyByWebhook($users); + } // check if pushover is enabled for this server if ($this->send_pushover && $this->server['pushover'] == 'yes') { // yay lets wake those nerds up! @@ -482,7 +495,48 @@ class StatusNotifier $pushover->send(); } } + /** + * This functions performs the webhook notifications + * + * @param \PDOStatement $users + * @param array $combi contains message and subject (optional) + * @return void + */ + protected function notifyByWebhook($users, $combi = array()) + { + foreach ($users as $k => $user) { + if (trim($user['webhook_url']) == '') { + unset($users[$k]); + } + } + $webhook = psm_build_webhook(); + + $message = key_exists('message', $combi) ? + $combi['message'] : + psm_parse_msg($this->status_new, 'webhook_message', $this->server); + $message = str_replace('
    ', "\n", $message); + $message = str_replace('
    ', "\n", $message); + $title = key_exists('subject', $combi) ? + $combi['subject'] : + psm_parse_msg($this->status_new, 'webhook_title', $this->server); + + // Log + if (psm_get_conf('log_webhook')) { + $log_id = psm_add_log($this->server_id, 'webhook', $message); + } + + // send notifications to all users + foreach ($users as $user) { + // Log + if (!empty($log_id)) { + psm_add_log_user($log_id, $user['user_id']); + } + $webhook->setUrl($user['webhook_url']); + $webhook->setJson($user['webhook_json']); + $webhook->sendWebhook($message); + } + } /** * This functions performs the text message notifications * @@ -619,7 +673,7 @@ class StatusNotifier { // find all the users with this server listed $users = $this->db->query(' - SELECT `u`.`user_id`, `u`.`name`,`u`.`email`, `u`.`mobile`, `u`.`pushover_key`, + SELECT `u`.`user_id`, `u`.`name`,`u`.`email`, `u`.`mobile`, `u`.`pushover_key`, `u`.`webhook_url`,`u`.`webhook_json`, `u`.`pushover_device`, `u`.`telegram_id`, `u`.`jabber` FROM `' . PSM_DB_PREFIX . 'users` AS `u` diff --git a/src/templates/default/module/config/config.tpl.html b/src/templates/default/module/config/config.tpl.html index 1472bc61..a9c4f6c0 100644 --- a/src/templates/default/module/config/config.tpl.html +++ b/src/templates/default/module/config/config.tpl.html @@ -30,7 +30,12 @@ +
@@ -183,6 +188,24 @@ {{ macro.button_save("jabber_submit", label_save) }} +
+
+ {{ label_settings_webhook }} +

{{ label_webhook_description|raw }}

+ + {{ macro.input_checkbox("webhook_status", "webhook_status", label_webhook_status, webhook_status_checked) }} + + {{ macro.input_checkbox("log_webhook", "log_webhook", label_log_webhook, log_webhook_checked) }} + + + + + + {{ macro.button_test("testWebhook", label_test) }} + {{ macro.input_hidden("test_webhook", "0") }} + {{ macro.button_save("webhook_submit", label_save) }} +
+
{{ macro.input_csrf() }} diff --git a/src/templates/default/module/server/server/list.tpl.html b/src/templates/default/module/server/server/list.tpl.html index 8fd94464..c32c86b1 100644 --- a/src/templates/default/module/server/server/list.tpl.html +++ b/src/templates/default/module/server/server/list.tpl.html @@ -73,7 +73,10 @@ J - {% endif %} + {% endif %} + {% if server.webhook|lower == 'yes' and config.webhook|lower %} + + {% endif %} {% if user_level == 10 %} diff --git a/src/templates/default/module/server/server/update.tpl.html b/src/templates/default/module/server/server/update.tpl.html index 38292434..0cefdd98 100644 --- a/src/templates/default/module/server/server/update.tpl.html +++ b/src/templates/default/module/server/server/update.tpl.html @@ -143,7 +143,9 @@ {{ macro.input_select_monitoring("telegram", "telegram", label_send_telegram, edit_telegram_selected, label_yes, label_no, warning_telegram, label_warning_telegram) }} - {{ macro.input_select_monitoring("jabber", "jabber", label_send_jabber, edit_jabber_selected, label_yes, label_no, warning_jabber, label_warning_jabber) }} + {{ macro.input_select_monitoring("jabber", "jabber", label_send_jabber, edit_jabber_selected, label_yes, label_no, warning_jabber, label_warning_jabber) }} + + {{ macro.input_select_monitoring("webhook", "webhook", label_send_webhook, edit_webhook_selected, label_yes, label_no, warning_webhook, label_warning_webhook) }}
diff --git a/src/templates/default/module/server/server/view.tpl.html b/src/templates/default/module/server/server/view.tpl.html index be5906f4..154ea26c 100644 --- a/src/templates/default/module/server/server/view.tpl.html +++ b/src/templates/default/module/server/server/view.tpl.html @@ -347,7 +347,20 @@ {% endif %} - + +
  • + {{ label_webhook }}: + {% if webhook|lower == 'yes' %} + + + {% elseif webhook|lower == 'no' %} + + + {% else %} + + + {% endif %} +
  • diff --git a/src/templates/default/module/user/profile.tpl.html b/src/templates/default/module/user/profile.tpl.html index 93caa951..abed8ad7 100644 --- a/src/templates/default/module/user/profile.tpl.html +++ b/src/templates/default/module/user/profile.tpl.html @@ -24,9 +24,9 @@ {{ label_pushover }}

    {{ label_pushover_description|raw }}

    - {{ macro.input_field("text", "pushover_key", null, "pushover_key", label_pushover_key, pushover_key, label_pushover_key, "255", "pushover_key_help", pushover_key_description) }} + {{ macro.input_field("text", "pushover_key", null, "pushover_key", label_pushover_key, pushover_key, label_pushover_key, "255", "pushover_key_help", label_pushover_key_description) }} - {{ macro.input_field("text", "pushover_device", null, "pushover_device", label_pushover_device, pushover_device, label_pushover_device, "255", "pushover_device_help", pushover_device_description) }} + {{ macro.input_field("text", "pushover_device", null, "pushover_device", label_pushover_device, pushover_device, label_pushover_device, "255", "pushover_device_help", label_pushover_device_description) }}
    @@ -36,7 +36,7 @@ - {{ macro.input_field("text", "telegram_id", null, "telegram_id", label_telegram_chat_id, telegram_id, label_telegram_chat_id, "255", "telegram_id_help", telegram_id_description) }} + {{ macro.input_field("text", "telegram_id", null, "telegram_id", label_telegram_chat_id, telegram_id, label_telegram_chat_id, "255", "telegram_id_help", label_telegram_id_description) }} {{ macro.input_hidden("activate_telegram", "0") }}
    @@ -44,7 +44,16 @@
    {{ label_jabber }} - {{ macro.input_field("text", "jabber", null, "jabber", label_jabber, jabber, label_jabber, "255", "jabber_help", jabber_description) }} -
    + {{ macro.input_field("text", "jabber", null, "jabber", label_jabber, jabber, label_jabber, "255", "jabber_help", label_jabber_description) }} + + +
    + {{ label_webhook }} +

    {{ label_webhook_description|raw }}

    + + {{ macro.input_field("text", "webhook_url", null, "webhook_url", label_webhook_url, webhook_url, "https://test.com/api/abcde", "255", "webhook_url_help", label_webhook_url_description) }} + + {{ macro.input_field("text", "webhook_json", null, "webhook_json", label_webhook_json, webhook_json, "{\"text\":\"servermon: #message\"}", "255", "webhook_json_help", label_webhook_json_description) }} +
    {{ macro.button_save(null, label_save) }} \ No newline at end of file diff --git a/src/templates/default/module/user/user/update.tpl.html b/src/templates/default/module/user/user/update.tpl.html index 0e86d617..bde98390 100644 --- a/src/templates/default/module/user/user/update.tpl.html +++ b/src/templates/default/module/user/user/update.tpl.html @@ -17,6 +17,10 @@ {{ macro.input_field("email", "email", null, "email", label_email, edit_value_email, null, "255") }} {{ macro.input_field("tel", "mobile", null, "mobile", label_mobile, edit_value_mobile, null, "20") }} + + {{ macro.input_field("text", "webhook_url", null, "webhook_url", label_webhook_url, edit_value_webhook_url, null, "255") }} + + {{ macro.input_field("text", "webhook_json", null, "webhook_json", label_webhook_json, edit_value_webhook_json, null, "255") }} {{ macro.input_field("text", "pushover_key", null, "pushover_key", label_pushover_key, edit_value_pushover_key, null, "255") }}