#!/usr/bin/env php
<?php
/*

  notify-by-webhook for NEMS Linux

  (c) 2024 By Robbie Ferguson https://nemslinux.com/

  License: https://www.gnu.org/licenses/gpl-3.0.txt

  Version History:

    - 2024-06-03 - 1.1
      Log webhook errors to /var/log/nems/webhook.log

    - 2024-05-13 - 1.0
      Initial numbered release. Includes improvements to "Acknowledged" notification.
      Truncate long usernames for Discord webhook.

*/

/* Arguments containing Nagios Alert/Notification Info */
array_shift($argv);
$f_notify_type =array_shift($argv);  /*1*/
$f_name =array_shift($argv);  /*2*/
$f_alias =array_shift($argv);  /*3*/
$f_state =array_shift($argv);  /*4*/
$f_address =array_shift($argv);  /*5*/
$f_output =array_shift($argv);  /*6*/
$f_long_date =array_shift($argv);  /*7*/
$f_to  =array_shift($argv);  /*8*/
$f_totalup  =array_shift($argv);  /*9*/
$f_totaldown=array_shift($argv);  /*10*/
$f_ackauthor= array_shift($argv);  /*11*/
$f_ackcomment= array_shift($argv);  /*12*/
$f_long_datetime= array_shift($argv);  /*13*/
$f_duration= array_shift($argv);  /*14*/
$f_duration_sec= array_shift($argv);  /*15*/
$f_last_state_check= array_shift($argv);  /*16*/
$f_last_state_change= array_shift($argv);  /*17*/
$f_notification_escalation_state= array_shift($argv);  /*18*/
$f_attempt_state= array_shift($argv);  /*19*/
$f_max_host_attempt_state= array_shift($argv);  /*20*/
$f_all_recipients= array_shift($argv);  /*21*/

$f_date_year = date("Y");

if (strlen($f_notify_type) == 0) exit('Please see the documentation.' . PHP_EOL);

/* Load from NEMS Config */
$nems['alias'] = trim(shell_exec('/usr/local/bin/nems-info alias'));
$resource = file('/usr/local/nagios/etc/resource.cfg');
if (is_array($resource)) {
  foreach ($resource as $line) {
    if (strstr($line,'$=')) {
      $tmp = explode('$=',$line);
      if (substr(trim($tmp[0]),0,1) == '$') { // omit comments (eg., starts with # instead of $)
        $variable_name = str_replace('$','',trim($tmp[0]));
        $nems['resource'][$variable_name] = trim($tmp[1]);
      }
    }
  }
}
$nems['HOSTADDRESS'] = trim(shell_exec('/usr/local/bin/nems-info ip'));
$nems['HOSTNAME'] = trim(shell_exec('hostname'));
$nems['WEBHOOK'] = trim(shell_exec('/usr/local/bin/nems-info webhook'));

$LONGDATETIME = date('r');

if (isset($f_state) && strlen($nems['WEBHOOK']) > 0) {

$alias = trim(shell_exec('/usr/local/bin/nems-info alias'));
$nemsver = trim(shell_exec('/usr/local/bin/nems-info nemsver'));

$light_cdn = 'https://cdn.zecheriah.com/nems/img/lights/';
$stateup = strtoupper($f_state);

switch ($stateup) {
  case 'OK':
  case 'UP':
    $color='green';
    $colorHex='#33ff33';
    $stateText = '<b><font color="#' . $colorHex . '">OK</font></b>';
    break;

  case 'WARNING':
    $color='yellow';
    $colorHex='#ffff33';
    $stateText = 'in a <b><font color="#' . $colorHex . '">WARNING</font></b> state';
    break;

  case 'CRITICAL':
  case 'DOWN':
    $color='red';
    $colorHex='ff3333';
    $stateText = 'in a <b><font color="#' . $colorHex . '">CRITICAL</font></b> state';
    break;

  case 'UNKNOWN':
  case 'UNREACHABLE':
  default:
    $color='yellow';
    $colorHex='#ffff33';
    $stateText = 'in an <b><font color="#' . $colorHex . '">UNKNOWN</font></b> state';
    break;

}

switch ($f_notify_type) {

  case 'FLAPPINGSTART':
    $statetype = 'Started Flapping';
    break;

  case 'FLAPPINGSTOP':
    $statetype = 'Stopped Flapping';
    break;

  case 'PROBLEM':
    $statetype = 'Problem';
    break;

  case 'RECOVERY':
    $statetype = 'Recovered';
    break;

  case 'ACKNOWLEDGEMENT':
    $statetype = 'Acknowledged';
    if (strlen(trim($f_ackcomment)) > 0) $currentissues .= '<br /><br /><b>Comment:</b> ' . $f_ackcomment;
    if (strlen(trim($f_ackauthor)) > 0 && $f_ackauthor != 'anonymous') $currentissues .= ' - <i>' . $f_ackauthor . '</i>';
    break;

  case 'FLAPPINGDISABLED':
    $statetype = 'Flapping Disabled';
    break;

  case 'DOWNTIMESTART':
    $statetype = 'Entered Scheduled Downtime';
    break;

  case 'DOWNTIMESTOP':
    $statetype = 'Scheduled Downtime has Ended';
    break;

  case 'DOWNTIMECANCELLED':
  case 'DOWNTIMECANCELED':
    $statetype = 'Scheduled Downtime has been Canceled';
    break;

  default:
    $statetype = $f_notify_type;
    break;

}

$currentissueshead = '<b><font color="#' . $colorHex . '">' . trim(strtoupper($statetype)) . '</font></b><br /><br /><b>' . trim($f_name) . '</b> is ' . trim($stateText) . '.';
$currentissues = trim($f_output);


if (!isset($fieldsarray)) {
  $fieldsarray[] = array(
    'name' => 'No Info',
    'value' => 'Something is up.',
    'inline' => false
  );
}

if (!class_exists('RemoteResult')) {
  class RemoteResult {
    public $name;
    public $value;
    public $inline;

    public function __construct($name, $value, $inline) {
        $this->name = $name;
        $this->value = $value;
        $this->inline = $inline;
    }

    public function toJson() {
        return [
            'name' => $this->name,
            'value' => $this->value,
            'inline' => $this->inline,
        ];
    }
  }
}

$output = [];

foreach ($fieldsarray as $input) {
    array_push($output, new RemoteResult($input['name'], $input['value'], $input['inline']));
}

// Create the webhook object
$hookObject = new stdClass();

if (strstr($nems['WEBHOOK'],'office.com')) { // MS Office 365 / Teams: https://docs.microsoft.com/en-us/outlook/actionable-messages/send-via-connectors
  $nemsstate = trim($currentissueshead);
  $hookObject = [
    "@type" => "MessageCard",
    "@context" => "http://schema.org/extensions",
    "themeColor" => $colorHex,
    "summary" => $nemsstate,
    "sections" => [
        [
            "activitySubtitle" => "Reported by $alias | <a href=\"https://nemslinux.com/\" target=\"_blank\">NEMS Linux $nemsver</a>",
            "activityImage" => $light_cdn . $color . '.png',
            "markdown" => true,
        ]
    ],
    "text" => trim($nemsstate) . '<br /><br />' . trim($currentissues) . '<hr />'

];

} elseif (strstr($nems['WEBHOOK'],'slack.com')) { // Slack

  $nemsstate = trim('NEMS ' . $currentissueshead);
  $hookObject->username = 'NEMS ' . strtoupper($f_state);
  $hookObject->icon_url = $light_cdn . $color . '.png';
  $hookObject->text = "*$nemsstate*\n\n" . str_replace(PHP_EOL,"\n\n",$currentissues) . "\n\n*Reporting Server:* $alias\n\n*Timestamp:* " . date('c') . "\n\nPowered by <https://nemslinux.com/|NEMS Linux $nemsver>";

} elseif ( strstr($nems['WEBHOOK'],'discord.com') || strstr($nems['WEBHOOK'],'discordapp.com') )  { // Discord
  $hookObject->content = strtoupper($f_state);
  $hookObject->username = mb_strimwidth('NEMS ' . strtoupper($f_state), 0,77, '...');
  $hookObject->avatar_url = $light_cdn . $color . '.png';
  $hookObject->tts = false;

  $hookObject->embeds = array();
  $hookObject->embeds[0] = array();
  $hookObject->embeds[0]['title'] = $currentissueshead;
  $hookObject->embeds[0]['type'] = 'rich';
  $hookObject->embeds[0]['description'] = '';
  $hookObject->embeds[0]['timestamp'] = date('c');
  $hookObject->embeds[0]['color'] = hexdec('FFFFFF');

  $hookObject->embeds[0]['author'] = new stdClass();
  $hookObject->embeds[0]['author']->name = 'Reporting Server: ' . $alias;

  $hookObject->embeds[0]['footer'] = new stdClass();
  $hookObject->embeds[0]['footer']->text = 'Powered by NEMS Linux ' . $nemsver;

  $hookObject->embeds[0]['fields'] = $output;
} else {
  echo 'Unsupported Webhook.';
  exit();
}



$ch = curl_init();

$hookObjectJSON = json_encode($hookObject, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );

curl_setopt_array( $ch, [
    CURLOPT_URL => $nems['WEBHOOK'],
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $hookObjectJSON,
    CURLOPT_HTTPHEADER => [
        "Length: " . strlen( $hookObjectJSON ) . ',',
        "Content-Type: application/json"
    ]
]);

$response = curl_exec( $ch );

if (curl_errno($ch)) {
  $error = curl_error($ch);
  $error_msg = date('r') . ' | Webhook Error | Payload: ' . $hookObjectJSON . ' | Error: ' . $error_msg;
  file_put_contents('/var/log/nems/webhook.log', $error_msg, FILE_APPEND | LOCK_EX);
}

curl_close( $ch );
}
