Slack for Kirby!

Are you lonely? Do you wish your Kirby sites would send you messages in slack?

Well, now you can have that happen! With new shiny Kirby-slack.

Just install the plugin, configure it minimally, and add a few slack()->send() calls here and there,

We use it on our default template to send us 404 alerts.

if ($page->intendedTemplate() === 'error') {
    header::missing();
    if (function_exists('slack')) {
        slack()->attach([
        'fallback' => 'Error Page Shown for ' . kirby()->request()->url(),
        'text'     => 'Error Page Shown',
        'color'    => 'warning',
        'fields'   => [
            [
               'title' => 'URL',
                'value' => kirby()->request()->url(),
            ],
            [
                'title' => 'User Agent',
                'value' => $_SERVER['HTTP_USER_AGENT'] ?? '',
            ],
        ]
     ])->send('Error Page Shown');
   }
}

7 Likes

Fantastic! I can see using this a lot. Thanks for building this!

Could be nice with register_shutdown_function to intercept all fatal PHP errors and uncaught exceptions.
Or maybe a try/catch in your index.php is enough.

(If you’re using Whoops, which is the default in Kirby, it might also be catching most exceptions before that.)

That was a good suggestion, especially since I had to remove the code above. (With redirectty, the page gets rendered first, before the redirect happens, so we were getting notifications even through the page was successfully redirected. Not very useful.)…

In any case, I ended up adding a handler to Whoops in order to generate info on the error any time there is an exception. Note that it only runs if debug is turned off and slack is working.

if (!c::get('debug') && c::get('slack.endpoint', false)) {
    $run = new \Whoops\Run;
    $run->pushHandler(function ($exception, $inspector, $run) {
        sendSlackOnError($exception, $inspector, $run);

        return \Whoops\Handler\Handler::DONE;
    });
    $run->register();
}

function sendSlackOnError($exception, $inspector, $run)
{
    if (function_exists('slack')) {
        $trace      = $exception->getTrace();
        $stackTrace = [];
        foreach ($trace as $call) {
            $out['title'] = $call['file'] . ':' . $call['line'];
            $out['value'] = $call['class'] . $call['type'] . $call['function'] . '(';
            $args         = '';
            foreach ($call['args'] as $arg) {
                if (in_array(gettype($arg), ['boolean', 'integer', 'double', 'string', 'NULL'])) {
                    $args .= $arg . ',';
                } else {
                    $args .= is_object($arg) ? get_class($arg) . ',' : gettype($arg) . ',';
                }
            }
            $args         = rtrim($args, ',');
            $out['value'] .= $args . ')';
            $stackTrace[] = $out;
        }
        $fields = array_merge([
            [
                'title' => 'Message',
                'value' => html($exception->getMessage()),
            ],
            [
                'title' => 'File',
                'value' => html($exception->getFile()),
            ],
            [
                'title' => 'Line',
                'value' => html($exception->getLine()),
            ],
            [
                'title' => 'URL',
                'value' => html(kirby()->request()->url()),
            ],
            [
                'title' => 'User Agent',
                'value' => $_SERVER['HTTP_USER_AGENT'] ?? '',
            ],
            [
                'title' => 'Stack Trace',
                'value' => $stackTrace,
            ],
        ], $stackTrace);
        slack()->attach([
            'fallback' => 'Exception occurred, file: ' . html($exception->getFile() . ' line:' . $exception->getLine()) .
                          'URL: ' . html(kirby()->request()->url()),
            'text'     => 'Exception Occurred',
            'color'    => 'red',
            'fields'   => $fields,
        ])->send('Unhandled Exception in Kirby Site!');
    }
}