Daniel Azuma

Building a Discord Command in Ruby on Google Cloud Functions

I recently spent a weekend experimenting with Discord integration. My church had decided to move our online services from Zoom to Discord, and, being a software geek, I thought it would be fun to try to build some things for the community.

So far I’ve built a simple command that does Scripture lookups. You can type a command in one of our Discord channels:

Invoking the command: /bible John 1:1-5

…and the bot will look up the passage using an API, and display it in the channel:

The command output, displaying a passage

“Slash” commands such as this, are a relatively recent adition to the Discord API. They’re easy for users to interact with, and convenient to deploy as a webhook.

Following will be a short series of articles describing how to write a Discord command such as this “scripture-bot” in Ruby, along with how to deploy it to the cloud. Along the way, we’ll cover a lot of the issues you may encounter with a real-world application, including:

  • Deploying to a “serverless” environment. Specifically, we’ll use Cloud Functions, a functions-as-a-service offering from Google.
  • Verifying request signatures using Ruby libraries, in this case using the ed25519 gem.
  • Good practices for handling secrets, such as API keys, in production. For this project, we’ll demonstrate the use of Google Secret Manager.
  • Techniques for reducing cold start time, including lazy initialization.
  • Using an event-driven architecture to schedule and run background tasks. In this project we’ll use Google Pub/Sub.

Contents

Because there’s a lot to cover, I’ll be splitting this article into four parts:

In part 1, we’ll cover setting up a Discord bot, deploying a webhook to Google Cloud Functions, and validating webhook requests from Discord using the Ruby ed25519 library. At the end of this part, we’ll have a working webhook that Discord recognizes, but that doesn’t yet actually implement a command.

In part 2, we’ll add our bot to a Discord server, and use the Discord API to register a command with the server. At the end of this part, we’ll know how to authenticate with the Discord API, and we’ll have a command set up, but it won’t yet be implemented.

In part 3, we’ll implement the command, calling an external API to get the actual Scripture text to display on the Discord channel. We’ll also learn how to use Google’s Secret Manager to access the API key securely in production. At the end of this part, our command will be working, with a few caveats.

In part 4, we’ll deal with one of the main issues with our implementation so far, which is that Discord doesn’t let you display more than 2000 characters in a chat message. To display a longer Scripture passage, we’ll need to send follow-up messages using the Discord API, and we’ll do that by scheduling a follow-up task using Google Pub/Sub.

All the code will be included, so at the end, if you follow along, you’ll have your own fully-functional Discord bot. (Note: I do work at Google in my day job, so the sample code is Copyright 2021 Google LLC, and licensed under the Apache 2.0 License.)

Ready? On to part 1

Dialogue & Discussion