Photo by palesa on Unsplash

How to Make a Slackbot Using Google Scripts

Automatic, scheduled Slack notifications without the heavy lifting

Our team has a daily reviewer whose responsibility is powering through any newly opened pull requests to our code base each day. We also have a daily releaser, who pushes whatever was on stage yesterday to production today. We like how this process flattens the team and ensures a sort of frigid fairness. We also like automation (because we’re developers) and transparency (because we’re humans… mostly). As a result, we wanted an automated way to communicate the assignment of daily chores out to the team. Thus began our long and tumultuous relationship with Slackbots.

Tried and Failed Slackbot Solutions

Lots of Slackbots exist and chances are good you’ve already decked out your Slack with more notifications than you can shake a ShackBurger at. We thought our ask was simple. We needed…

  • Daily notification (Monday-Friday)
  • Ability to set a rotation of 4–6 reviewers
  • Ability to skip a reviewer when they are out
  • Ability to edit reviewer list
  • Ability to share ownership/editing capabilities

We dug through the Slack apps. We Googled our options. We found surprisingly little.

Google Calendar + Slack

Daily events posted from Google Calendar

Our first attempt was a Google Calendar with a repeating daily event and the Google Calendar Slack app configured to post that day’s events each morning. Suppose we had an event called “Today’s reviewer is Hermione”. When we had five reviewers, we could repeat “Today’s reviewer is Hermione” weekly on Mondays. However, when we gained a sixth reviewer, our options were “Repeat every 6 days” (with no option to skip weekends) or maintain 6 x 5 = 30 unique events. No one wants to maintain 30 unique events.

Scorecard

  • Daily notification (Monday-Friday): 10/10
  • Ability to set a rotation of 4–6 reviewers: 5/10
  • Ability to skip a reviewer when they are out: 1/10
  • Ability to edit reviewer list: 1/10
  • Ability to share ownership/editing capabilities: 10/10
  • Total: 27/50

Custom Slackbot Using AWS Lambda

When we saw our calendar solution going awry, one of our teammates spent an otherwise perfectly good weekend writing code which he hosted as an AWS lambda, creating some triggers and voila! We had a Slackbot. It worked perfectly. It looked super professional. It featured a robot cowboy. You could run commands straight from Slack to add or skip reviewers. You could search for it in Slack apps. Our lives were pretty great.

Robot cowboy enforcer

Then that coworker left and everything fell apart. We didn’t have a user-agnostic way to host and run the code in AWS. Complications with AWS privileges and credit cards and passwords was going to make it a nigh impossible to maintain. Eventually the app disappeared from the Slack apps directory, and with it our last vestiges of hope. Womp, womp.

Scorecard

  • Daily notification (Monday-Friday): 10/10
  • Ability to set a rotation of 4–6 reviewers: 10/10
  • Ability to skip a reviewer when they are out: 10/10
  • Ability to edit reviewer list: 10/10
  • Ability to share ownership/editing capabilities: 0/10
  • Total: 40/50

A Stupidly Simple Serverless Solution: Google Apps Script

Finally, out of desperation, we decided to try something kinda hacky I’d read about once. And that kinda hacky solution is still going strong. That kinda hacky solution is why I’m here today.

Slack message posted daily from our Google Script

Google Apps Script is natively included in Google Suite and gives you the ability to write and run code straight from your browser. You can read and write to Google docs and spreadsheets. You can also save your code as a web app or executable API. It’s pretty cool and I can’t figure out why more people don’t know about it.

Getting started is super easy. Today, I’m going to walk you through creating a Slackbot in three parts:

  • Part 1: Write a script that posts a simple message to Slack
  • Part 2: Add data persistence and post a message using data from your data store
  • Part 3: Schedule your script to run on a schedule

Posting a Message to Slack

  • First, we need to create an incoming webhook in Slack.
  • Go to Slack custom integrations directory > Search for “Incoming WebHooks” > Click “Add configuration”.
  • Fill out the details for the Slack channel to which your Slackbot will post, a description of your Slackbot, etc. (Don’t worry, we can override all of this in our script. However, we cannot jog the memory of future you when you forget what this app is and why you made it. For that reason, I suggest writing a basic description at least.)
  • Copy and save the webhook url for use later.
  • Now, go to Google Apps Script and create a new script.
  • In your new script, let’s create a variable for our webhook url saved in a previous step.
var webhookUrl = “https://hooks.slack.com/services/XXXXX/YYYYY";
  • Now, let’s create a function called postToSlack.
function postToSlack() {
var payload = {
“channel” : “#slackbot-test”,
“username” : “My Test Slackbot”,
“icon_url” : “https://puu.sh/BQqA9/408cadc2b3.png",
“text” : “Here’s an inspirational quote”,
“attachments”: [{
“text”: “:bearded_person: Today’s reviewer is *Hagrid*”,
“footer”: “<http://www.linktoyourscript.com|edit script>”,
“mrkdwn_in”: [“text”]
}]
}

var options = {
“method” : “post”,
“contentType” : “application/json”,
“payload” : JSON.stringify(payload)
};

return UrlFetchApp.fetch(webhookUrl, options)
}
  • Replace “channel”, “username”, “icon_url”, and any other fields to suit your needs. Or don’t. It’s your life. It’s up to you.
  • Run your script by going to Run > Run function > postToSlack().
  • Voila! Check the Slack channel specified in your payload to see your message come through.

In the (very unlikely) chance you run into issues, you can use Logger.log(thingToLog); to log out some value. Then run your function and go to View > Logs.

Adding Data Persistence

In order to log out the daily reviewer, we need a way to keep track of our list of reviewers and whose turn it is to review. Enter the great, the timeless, the indomitable, the irreplaceable… the spreadsheet.

  • Create a spreadsheet with a list of names of everyone who will be in the reviewer rotation. The current reviewer will be the name at the top of the list. When we rotate reviewers, we will move the top name to the bottom and shift all the names up.
  • Note and save the Google sheet id, which is the long string of nonsense in the url after /d/ and before /edit. We’ll use it later in our script.
  • Select the column containing your content and go to Data > Named ranges > Give your range a name.
  • Note the name of your range for later use. In my case I’ve named my range teammembers.
  • Now, back in your Google script, let’s create variables for the Google sheet id and named range. We’ll add an additional variable called sheets which just abstracts a call used throughout the script.
var googleSheetId = ‘XXXXXXXXXXXXXXXXXXXXXXXXXXXXX’
var namedRange = ‘teammembers’;
var sheets = SpreadsheetApp.openById(googleSheetId);
  • Next, create functions for getReviewer and rotateReviewer. We’ll also use a helper function called getLastRow to find the first empty cell in our range.
function getReviewer() {
var currReviewer = sheets.getRangeByName(namedRange).getCell(1,1).getValue();
return currReviewer;
}
function getLastRow() {
var nameList = sheets.getRangeByName(namedRange).getValues();
for (i in nameList) {
if (nameList[i][0] == “”) {
return Number(i);
break;
}
}
}
function rotateReviewer() {
var nextRow = getLastRow() + 1;
var currReviewer = getReviewer();
sheets.getRangeByName(namedRange).getCell(nextRow,1).setValue(currReviewer);
sheets.deleteRows(1, 1);
}
  • Finally, let’s create the function that we’ll run daily called rotateReviewerAndPost.
function rotateReviewerAndPost() {
rotateReviewer();
postToSlack();
}
  • Before we post to Slack, we need to update the postToSlack function to post the current reviewer’s name instead of the static text we used previously. First add a reviewer variable that looks like:
var reviewer = getReviewer();
  • And then update the “text” json to use that variable in place of the static text.
“text”: “Today’s reviewer is *” + reviewer + “*”
  • Finally, run your script by going to Run > Run function > rotateReviewerAndPost(). Run it repeatedly to see the reviewer update with each run. Check Slack to verify everything is coming through as expected.

Scheduling your Script to Run Automatically

To set up your Slackbot to run on a schedule, we need to add a trigger. On our team, we run a function called runDailyJob. Within that function, we get today’s date, check to see if it’s a holiday or weekend, and if it is, abandon ship. If it’s not a holiday or weekend, we run our script to advance the reviewer and post to Slack.

  • To add a trigger, go to Edit > Current project triggers > Add trigger.
  • Select the name of the function you want to run and the frequency with which you want to run it. To post the daily reviewer script we just wrote, we would run rotateReviewerAndPost daily between, say, 2am and 3am.

Scorecard

In all, this solution has met our needs and provided the right amount of flexibility and adaptability for our team to be able to use Slack more effectively.

As for our original acceptance criteria, I rate the Google Apps Script solution as follows.

  • Daily notification (Monday-Friday): 10/10
  • Ability to set a rotation of 4–6 reviewers: 9/10
  • Ability to skip a reviewer when they are out: 8/10
  • Ability to edit reviewer list: 10/10
  • Ability to share ownership/editing capabilities: 10/10
  • Total: 47/50

Significant pros have been:

  • Easy for anyone on the team to edit the script and spreadsheet
  • Easy to manage sharing permissions
  • No extra passwords, credit cards, or external dependencies

Opportunities for further enhancements include:

  • Google Scripts can integrate with just about any product in the Google suite. The possibilities are endless.
  • Google Scripts also supports incoming triggers such as commands posted from Slack to a script. To use this functionality, a script has to be published as a web app and access given to “anyone, even anonymous” which may or may not be supported in your account. You can learn more about posting to Google scripts in Victor Viruete’s article which is linked at the end of this post.

A few gotchas to watch out for:

  • Technically, there’s a quota on size and number of calls you can make. I do not anticipate hitting that quota.
  • Scheduling is only accurate within one hour.
  • Slack has character limits on certain fields. For example, if your links aren’t being formatted correctly, try using a url shortener.

Further reading

As you embark on your Slackbot journey, you may want to call on these resources I’ve found helpful: