One of my closest collaborators is a teammate far away — I'm in New York and Emily Withrow is in Chicago.
We stay connected chatting on Slack. But recently Emily asked if I could regularly update my Slack status to indicate what I was doing at the moment, like coding, meeting, eating. It's the kind of thing colleagues in New York know just by glancing toward my desk.
Changing my Slack status isn't hard; remembering do it is. So I built a bot to change it for me.
From the outset, I figured the best approach would be to link my status to my Google calendar. Googling for solutions led me to this wonderful post by Dan Chilton at Vox Media. If you want to do this quickly and easily, go with his approach.
But I wanted more control over the emoji and text displayed in my status. Also Dan's method involves giving IFTTT access to my Google account so it can watch my calendar. While I love (and use) IFTTT, I try not to give out my work credentials to services I don't absolutely need.
Instead I wrote some code that lives in Amazon's serverless Lambda system and used the "Secret address in iCal format" from my Google Calendar settings:
This URL gives the Lambda function read-only access to the contents of my calendar without using any credentials.
How it works
- Twice and hour, at 2 minutes and 32 minutes past, Amazon's Cloudwatch service pokes my Amazon Lambda function.
- The Lambda function wakes up and grabs my current calendar data using the "secret link."
- The function then loops through all of the events and checks whether the current time falls between each event's start and end times.
- If it finds an event happening now, it looks in the event title for words I tend to use like, like "lunch" or "in transit." It also checks the description field to see if I added a special line that looks like
jkstat :plane: Flying to LA. Here,
:plane:means "✈️" in Slack. If it finds none of these things, it assumes I'm "In a meeting."
- Event in hand, the Lambda function uses the Slack API to update my Slack status with an emoji, some text, and an expiration time (the end time of the event).
Unfortunately, using Lambda functions isn't super straightforward, and certainly not as easy as the one-button deploy Dan set up. (I have some starter code here, tho I really need to write a true tutorial.)
Once I got it up and running, it worked beautifully — with one glaring exception.
Simple, one-time events show up as you might expect in the "iCal" file I get from Google Calendar: Title, start time, end time, description, and so on. Determining whether an event is happening now is pretty straightforward. As I loop through all of the events in the calendar, I can essentially ask, "Hey, does the current time fall between the start time and end time of this event?"
Buuuut repeating events are quite a different story, I learned. The "iCal" file stores these events with the start and end times of the original event and then tacks on a rule that describes when subsequent events take place. Like, every other Wednesday or the first Tuesday of every month or every October 31st. This is called the "RRULE."
Here's the beginning of the iCal code for a demo session the Quartz product team does every Friday at 5 pm, including just last week. Note that the original event is back in July (201807...):
So as I loop through the events in my calendar, the question to the computer becomes more complicated: "Hey, for this event, is there an RRULE? If so, take a look at the start and end times of the original event. Now apply the repetition rule to create a bunch of subsequent events up until today, because I don't care about the future. Cool? Okay, does the current time fall between the start and end times of the latest one of those events?"
As you might imagine, that "now apply the repetition rule" part is not at all trivial. Just think about how you need to handle all of the possible repetition formulas. Fortunately, others have solved this problem, so I used existing code to make it work. (Whew.)
The reaction has been excellent.
Of course, now she'd like to use it, and others likely will as well. I have a plan for how to make the same code work for multiple people, and I'll update this post if/when I pull that off.
I'm also noodling on how to interpret emoji characters into Slack codes, like
:plane:. I might implement something like that, too.
If you find this useful, or find a way to improve on it, definitely let me know!