When we started using Slack in our small team I was sold on the spot, and I particularly enjoy being able to build integrations which, well, integrate seamlessly into Slack: type a command into a Slack channel, and get a response right there, without leaving Slack.
I was thinking about how to go about getting a bit of our OwnTracks into Slack. Wouldn’t it be neat if you could tell with a single command where a team mate is? Sure, we could glance at a map or use one of the other utilities that the OwnTracks project provides, but let’s see if we can do better.
If you’ve been following a bit of what we do with OwnTracks, you’ll know privacy is a big word for us, and as such we recommend you use your own MQTT broker for OwnTracks. I have a dozen friends and family members using my broker with carefully designed ACLs so that only consenting parties can see each others’ location. I don’t want to open up MQTT publishes from my broker to the rest of the world, but I want my Slack team to be able to determine where I am so they know if I can be disturbed. (I trust these guys.)
What I’m going to show you is how we can use a combination of OwnTracks, mqttwarn (which I introduced here), and a Slack slash command to produce a useful utility you can use in Slack as well. (If you’re more of an IRC user, I’m sure you can use some of these techniques to write a bot which will do similarly, and do tell me about how you solved it!) The difference between a slash command in Slack and other integrations such as Webhooks is that only the person who issued the command sees the response, so it doesn’t clutter the channel.
My smart phone publishes a location update via MQTT to my broker, from which mqttwarn picks it up, reformats the payload, and performs a HTTP POST to an external system on which a Slack integration can obtain the data.
The payload published by OwnTracks over MQTT is JSON which contains the latitude, longitude, altitude, etc. of the smart phone, as well as a time stamp, and a tracker-ID called TID which I configure on the device itself. The payload looks like this (I’ve removed some of the elements to keep the example brief):
mqttwarn subscribes to MQTT messages published at the topic used by my phone, and determines whether the message qualifies to be handled. The
filter function can drop messages I’m not interested in handling even though they’re published to the same topic (e.g.
lwt messages when the broker detects the device has temporarily gone offline).
So, if OwnTracks publishes the JSON shown above to the topic
owntracks/jjolie/nex, say, mqttwarn, which is subscribed to that topic, will receive and handle the message and, via the slack_whereis() function, will add a
geo element which mqttwarn can use in format when finally sending the message to the configured target.
In this case, I use the http target to POST data to a remote endpoint where the association (Jane is at this place) is stored.
The HTTP endpoint is a small Bottle app which accepts these location update POSTs on the one hand, and which is an endpoint for a Slack command on the other.
Slack slash commands
There’s pretty little that the guys over at SlackHQ forgot to implement, and one of my favorites is
Slack allows me to add my own custom slash commands which I configure in Slack integrations. What I’m going to do here is to create a
/whereis command so that my mates can see where I am (and maybe I can see where they are).
Adding a custom command requires two steps:
- add the Slack integration for the custom command
- create the code which will actually run the command
Adding the command integration is easy: choose the name of the command (
/whereis), the HTTP endpoint, and a usage hint for the user. I make a note of the token which I can use in my code to ensure only clients which know the token can query my service.
When I invoke a custom command, Slack fires off a POST (or optional GET) request to the endpoint we configure. The example I show you here implements a simple solution for the task: use the value passed to
/whereis to find information about a particular user and return a one-line text result which Slack displays au-lieu of the command I entered. (I run this particular app under nginx and UWSGI.)
If I’m very concerned about privacy, I can add a bit of haversine magic or use the OwnTracks waypoints feature on the location reported by OwnTracks to keep things anonymous even from trusted team mates:
For example, I can hide at which
restaurant customer I am, etc.