Slackbot: Rebus Leaderboard

June 30, 2021

Virtual team building is tough. If the event is too long, people may find it a chore to join. Too infrequent, and people may not participate at all. So how do you strike a balance and find something that everyone will love? The answer is: daily rebuses

A rebus is a puzzle in which words are represented by combinations of pictures and/or letters. The picture below is an example of a rebus and you can find the answer at the end of this post! 

I post a rebus in Slack every day at 11 am. Basically, I’ve conditioned everyone at Tome to stare at our #watercooler channel at 10:59 am, fingers ready to hit that ‘Reply to Thread’ button. 

I reward the winner of each rebus with a 💯 emoji on their answer. However, the problem I faced was keeping track of the winners. Of course I could manually update an excel spreadsheet with each day’s winner to get a running leaderboard but who wants to do anything manually nowadays? Therefore, the solution to my problem lies in a Slackbot. 

There are two main things I needed this Slackbot to do: 

  1. Evaluate threads for all rebus posts in the #watercooler channel for the correct answer
  2. Post the Rebus leaderboard when someone uses the Slack Slash command /leaderboard

For my solution, I decided to connect an AWS Lambda function to a POST command in API Gateway that will be triggered when a user types /leaderboard in Slack. 

There were some initial steps I took to set up the workflow: 

  1. Create a Hello World app in an AWS Lambda function
  2. Connect the Lambda function to a POST command in API Gateway so it can be triggered from a public URL 
  3. Create, configure, and install the Rebus Leaderboard app in Slack and ensure the /leaderboard command triggers the Lambda function via API Gateway 
  4. Update the Lambda function code to post a message in Slack as the Rebus Leaderboard Bot

Now that I had all the necessary pieces in place, it was time to build the core functionality. 

The first step was to get a list of all messages in the #watercooler channel. I used Slack’s conversations.history API to fetch a conversation’s history of messages and events. A conversation can be a public channel, private channel, or a direct message. In my case, I was fetching the message history of a public channel. The only required arguments for this API are an authentication token and a channel or conversation ID. You can find a channel’s ID in the Slack app at the end of the information section for that channel or in the URL.

Now that I have a list of all the messages in the #watercooler channel, I have to filter it down to only rebus posts. So I filtered the list by messages that contain the word rebus, messages that were posted by my user ID, and messages that have a thread. 

Below is a sample response from the conversations.history API. It shows a message that meets all three filter criteria mentioned above. 

The last step that I completed on this Lab Day was to grab the thread timestamps from each rebus post from the filtered list. The conversations.history API does not provide you with the thread replies on a message and that’s where the rebus answers lie for us. So I would need to call another Slack API, conversations.replies, to fetch all the replies of each message. This API requires three arguments: an authentication token, a channel ID, and a timestamp. The timestamp is a unique identifier of either a thread’s parent message or a message in the thread. So I need these timestamps in order to call the conversations.replies API. 

That was as far as I got during this Lab Day but I do plan on finishing this Slackbot during the next one. 

The next steps would be to:  

  1. Call the conversations.replies API to get the thread replies of each rebus message 
  2. Search each thread reply per rebus post for the 💯 emoji reaction posted by my user and grab the user ID of the thread reply message and add a point to their score 
  3. Identify the top 3 winners and post a message in Slack with the leaderboard

Are there more performant ways to craft this solution? Of course. But that’s a problem for another Lab Day! 

Rebus Answer: Neighbourhood Watch