Build a Discord Bot With AWS Lambda + API Gateway | by jakjus | Apr, 2022

Picture by Alexander Kovacs on Unsplash

Lately, Discord has launched Interactions and Slash Instructions to ease customers’ expertise with bots. Partially, the explanation was to safe customers’ privateness — bots at the moment are barely compelled to desert flags for studying messages in Discord Servers — which was beforehand a degree of concern concerning illegal knowledge processing by bot builders.

These are essentially the most identified options, however on prime of that, the replace has added a chance to work together with talked about Interactions by the Interactions Endpoint URL.

Developer Dashboard’s Area for Interactions Endpoint URL.

This enables us to maneuver from a standard listener app hosted on a server to a serverless app *applause*, that runs a Lambda Perform on every Interplay invocation.

In the course of the coding, we’ll bounce between “AWS”, “Code” and “Discord Developer Portal”.

AWS

We are going to use AWS API Gateway and AWS Lambda for our process. It’s a base toolset for serverless structure on AWS. Features will likely be written in Node.js.

  1. Create an account and log in at https://aws.amazon.com
  2. Go to API Lambda service through the use of top-bar navigation
  3. Select “Features” part within the sidebar (if not but chosen)
  4. Click on “Create operate”
AWS Lambda Principal Web page.

In the event you had been courageous sufficient to click on it instantly with plugged in bank card — you’ve most likely used AWS or AWS Lambda earlier than.

In the event you hesitated — it’s a second to calm you down: The AWS Lambda free tier consists of a million free requests per 30 days and 400,000 GB-seconds of compute time per 30 days. Far more than you will want for sake of this tutorial and doubtless ever after (although I want you exceeding the restrict!).

5. Select your Perform title, choose Node.js 14.x and Click on “Create operate”

Create operate panel.

After creation, it’s best to see the dashboard beneath.

Preliminary Lambda dashboard. Yeah, we will likely be clicking like that. Not a time limit to implement IaC.

Nice! We now have our lambda with a boilerplate code. Now add an API Set off — we’d like some URI to move to Discord Portal, proper?

Set off configuration.

Allow CORS to permit Discord’s host origin. Some day sooner or later, you could wish to change the openness of API endpoint and CORS allowed domains in order that you don’t get bot-spammed (it’s not widespread for AWS sources although).

The end result:

Set off created.

Go to the API endpoint by clicking on its URL: it’s best to see “Howdy from Lambda!”

Code

Create mission listing serverless_discord/. Inside, create a subdirectory lambda_bot/ and index.js inside. Use the next code:

Within the code above, we observe the construction you could already see in AWS Lambda boilerplate code (exports.handler operate).

Subsequent, we fulfill endpoint necessities (payload verification and ping reply) set by Discord within the documentation. Verification is finished with tweetnacl package deal, that we shouldn’t have but. Let’s set up it!

Finest case could be in case your node --version is near the Lambda runtime’s model (we selected 14.x ) — ideally, if it’s the identical. If it’s too far aside — together with npm — the packed modules might not work in Lambda.

npm i tweetnacl

Good. Now, let’s zip all of that (with node_modules!) and put again into our Lambda. Whereas nonetheless being inside your listing, sort:

zip -r ../lambda_bot.zip *

AWS

Add the zip in Lambda dashboard — part “Code”.

Lambda dashboard.

or by CLI as an alternative, if in case you have AWS CLI put in and configured:

aws lambda update-function-code 
--function-name discord
--zip-file fileb://../lambda_bot.zip

All the pieces seems to be nice. Fast app creation at Discord in 3, 2, 1, go!

Discord Developer Portal

Go to Discord Developer Portal, select New Utility and choose a reputation. Copy beforehand created API endpoint to Interactions Endpoint URL subject in bot’s configuration beneath.

My actual AWS API Gateway URL.

and click on Save!

Saving performs Discord-side test of their necessities — they ship a set of POST requests to your endpoint.

Scroll to the highest of the web page for notification and — there you could have it! Large Inexperienced Success bar — your Bot is stay! You made it!

Huh? What? You’ve acquired some error? Umm, what’s the error message?

You despatched me this unhelpful screenshot.

How can I repair the endpoint, when all I do know is that “one thing” is flawed? At most, we might assume, that certainly one of their two necessities is just not fulfilled.

AWS

To debug it from AWS aspect, you may make some take a look at snippets and run them in opposition to your code. Sadly, it’s not simple to seek out a precise name instance from Discord to mock this.

You too can debug it rapidly by working the code by yourself pc (simply strip the code in index.js from handler operate), however you then you definately’d want exterior area redirecting to your native IP, which has its personal dangers.

Let’s add console logs to have any concept, if the request is coming and if we interpret it appropriately.

Add logging in very first strains of index.js

const nacl = require('tweetnacl');exports.handler = async (occasion) => {
console.log(occasion)
// Checking signature (requirement 1.)
...

and click on “Deploy”.

In Discord Developer Portal, “Save” Discord Utility settings (as a reminder — it’ll rerun Discord’s POST request to our Lambda). With the occasion (hopefully) logged, test it in CloudWatch.

Lambda dashboard — navigating to CloudWatch.

I discovered this error message:

Error message.

(the occasion itself was logged in a single subject greater, which can be useful)

The error factors to Line 15 in index.js , which states:

Buffer.from(PUBLIC_KEY, 'hex')

and factors rightfully so. We didn’t move PUBLIC_KEY atmosphere variable, which is assigned to variable PUBLIC_KEY beforehand.

const PUBLIC_KEY = course of.env.PUBLIC_KEY;

Get the Public Key of your app from Discord Developer Portal and insert in AWS Lambda’s: Configuration → Atmosphere Variables → Edit… → Add… (do NOT use citation marks for env variables)

Key: PUBLIC_KEY, Worth: 55ff1c234...

Run “Save Modifications” now!

All of your edits have been fastidiously recorded.

On the finish of index.js , add handler for a command, that we are going to quickly register.

I desire a Slash Command /foo that replies “bar” (okay, not too mind-blowing).

Copy and paste the up to date code to AWS Lambda code editor or zip it and add it just like the final time. Click on “Deploy”.

Registering /foo command

Create a second subdirectory in serverless_discord/ , referred to as register_commands/ , and navigate into it.

➜  serverless_discord mkdir register_commands && cd register_commands

Create a brand new file register.js with:

So as to add lacking modules, run:

npm i axios dotenv

However, why do we have now two completely different packages (folders) now?

Properly, this one won’t be on AWS Lambda and doesn’t should be wherever distant, really. Ideally, registering instructions, ought to occur throughout CI/CD Pipeline, when there are instructions modifications. With out CI/CD, it’s completely OK to run the script manually out of your native PC after you develop one thing new.

Create .env file and alter values to yours:

ForGUILD_ID, go to Discord App, create a Discord Guild (colloquially Discord Server). In your Person Settings → Superior → Developer Mode ON. Return to major discord display, proper click on in your Guild and click on Copy ID.

Then, go to Discord Developer Portal, select your app → Bot → Add Bot → Reset Token → Copy — it’s your BOT_TOKEN.

Discover APP_ID in Basic Data part.

Go to OAuth2 part → URL Generator. Select Scopes: bot, utility.instructions. Bot permissions: Use Slash Instructions.

Copy URL generated beneath and go to it — select Guild, that you’ve simply made.

Generated URL.

You’re proper, we restrict the scope to only one guild (yours). Slash instructions will NOT seem in different guilds, that you’ll invite bot into. When creating Slash Instructions with Guild Scope, it applies modifications instantly — that’s why it’s all the time used within the growth course of till the bot could be very prepared. Creating or altering International Instructions is rolled out for every guild in 0–60 minutes.

Altering scope to International in a while, ought to take you round 5 minutes with the official documentation.

Sufficient speaking, let’s deploy the command!

➜  register_commands node register.js➜  register_commands

No error means success! Go rapidly to your Discord Guild chat, begin typing /foo and press Enter.

Drumroll…
BAR!

Congratulations! 🏆

Your serverless bot is now u̶p̶ ̶a̶n̶d̶ ̶r̶u̶n̶n̶i̶n̶g̶ ready for occasions 🙂

Upsides:

  1. Low value
  2. Straightforward to implement
  3. Very effectively scalable — no want for sharding (with solely linear value improve!)

Downsides:

  1. Locked to AWS (vendor-lock) (this explicit answer)
  2. Could require CI/CD implementation greater than “serverful” choices — in any other case, altering AWS sources could also be tedious
  3. This structure wants correct logging and debug messages on consumer and server-side in an effort to be efficient.

On this article you could have discovered:

  1. Fundamental serverless toolkit on AWS
  2. The present state of Discord Bot programming
  3. Challenges with AWS Lambda — growth, deployment, debugging
  4. Payload verification with nacl and making requests with axios

Further sources:

As your newly made operate says, it’s time to rejoice on the bar!

(Now the article intro image doesn’t really feel so odd, proper?)

More Posts