Back in April, Slack released a cool new feature that allows you to set a status message on your account. Some of the examples they provide are:

  • In a meeting
  • Commuting
  • Out sick
  • Vacationing
  • Working remotely

“This is awesome!,” I thought. “Now I can do what did on AIM in 1997!”

Slack did sprinkle this status in various places in the UI, but it’s still a pain to go searching for it, especially if you haven’t chatted with a person in a while. Plus, there doesn’t seem to be an easy way to see a compiled status for a group (e.g. @engineering-team).

Enter: Staatus

I built Staatus on a PHP framework called Silex. It’s a microframework based on Symfony that provides the guts for building simple single-file apps. Here’s an example:

require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

$app->get('/hello/{name}', function($name) use($app) {
    return 'Hello '.$app->escape($name);
});

$app->run();

Staatus allows you to see a compiled status of an individual, a particular team, or everyone in a channel. The code is over on our Github.

I have to hand it to the devs at Slack. The API was super-easy to work with. I made use of these REST commands:

With that, I was able to display both status emojis/messages, but also a blue diamond if the person is online:

The Code

Coding this up was very straightforward. I’d say the only quirk I ran into is that the calls take too long, and Slack does not like that. If your plugin doesn’t return within a few seconds, you get an error message. My plugin is hosted on Heroku, so between the lag of Heroku waking up instances and the time it takes to run all the API calls (which can amount to many, especially when Staatus is run against a team name), I needed to figure out a way to return a delayed response. Normally, in a single-threaded language like PHP, that’s not easy. Most frameworks follow a very “serial” manner of generating a response:

  1. A request comes in (possibly with parameters).
  2. A response is generated.
  3. The response is returned and the request dies.

So if step 2 was taking too long, how was I going to work around Slack’s request time limits? The answer comes in Silex’s $app->finish() method. It is documented as:

A finish application middleware allows you to execute tasks after the Response has been sent to the client (like sending emails or logging)

Here’s how I used it:

$process = function(Request $request) use($app) {

// first, validate token
 $token = $request->get('token');
 if (empty($token) || $token !== VERIFY_TOKEN) {
 $app->abort(403, "Invalid token.");
 }

$response = [
 'response_type' => 'ephemeral',
 'text' => 'Gathering staatus...'];

// just return; the rest of the processing will happen in finish()

return $app->json($response);
};

$app->get('/', $process); // for testing
$app->post('/', $process);

$app->finish(function (Request $request, Response $response) use($app) {
...
}

As you can see, my $process method returns immediately and I do the rest of the processing in a finish() method. This allows me to take as long as I’d like (give or take) to return a response back to Slack using a one-time response URL they provide. (Technically, you can’t take as long as you’d like to respond. Slack has a hard limit of “up to 5 times within 30 minutes”):

$response = [
 'response_type' => 'ephemeral',
 'text' => $text];

$client2 = new Client(['base_uri' => $responseUrl]);
 $response2 = $client2->post('', [
 'json' => $response,
 'verify' => false
 ]);

And that’s all, folks. So, go ahead and download Staatus, deploy it on Heroku, and you’ll be partying like it’s 1997 all over again. BOOYAH!


Also published on Medium.