How to send scheduled messages to Slack with the Google Calendar API
I work for the tech consultancy HeadFWD and we are a group of about 25 awesome and talented but slightly unorganised developers. We have a shared calendar but checking it often is not a priority for most of us, so we were looking for a way to send reminders of events and birthdays via Slack.
The result is an extension to our existing slack bot. We can schedule Slack messages by creating an event in the calendar. The event summary is used to target a specific channel, the event description is posted as the message. See it in in action here:
We decided to use a polling solution to integrate both platforms. We already have a chat bot set up as a slack app so it was most convenient to add the feature there. Next, we created a dedicated calendar which we now use to schedule messages (events, recurrent reminders, birthdays, etc).
For each event, we use the description as a way to store the message and put the desired channel in the event summary. We can use mentions and slack formatting (including smileys) as expected, but can not use the formatting options provided by Google Calendar as that will transform the description to HTML, which is not supported by Slack.
Our slack bot is created using NestJS and TypeScript. We choose nest-schedule to allow setting up of an interval job, in this case polling the calendar with the Google API to check for events to process. This is not required though, a simple Node script as a Cron job should do the job. We use the google-api-nodejs-client to retrieve and update calendar events, you can find the API docs here.
Connecting to the Google Calendar was not so trivial since OAuth is the only supported protocol and it requires an authenticated user (the bot is an app, not a google user). We have a G Suite and the magic trick is to set up a google service account with domain-wide delegation of authority to allow the service to impersonate a user.
Polling happens every 5 seconds and looks for events in the surrounding range so that messages are processed at the scheduled time. Recurrent calendar events are collapsed into single events by the API to make processing a whole lot easier.
In order to keep track of which events have been processed — to prevent duplicate postings — we needed a way to mark the events as handled. Since the calendar itself is a database, we decided to update the event summary with a symbol to mark it as either ‘sent’ (!) or indicate any issues with ‘problem’ (?).
That’s about all there is to it! The full implementation of our calendar service is available here. Thanks for reading!