Bring the cuteness of r/aww straight to your discord server

Related tags

Video/Audio awwbotcf
Overview

awwbot

Bring the cuteness of r/aww straight to your discord server. Now on Cloudflare workers.

awwbot in action

How it works

When you create a bot on Discord, you can receive common events from the client as webhooks. Discord will call a pre-configured HTTPS endpoint, and send details on the event in a JSON payload.

This guide walks through creating a webhook-based bot which:

Creating bot on Discord

To start, we'll create the bot through the Discord Developer Dashboard:

awwbot-ids

  • Click on the Bot tab, and create a bot! Choose the same name as your app.
  • Grab the token for your bot, and store it somewhere safe (I like to put these tokens in a password manager like 1password or lastpass).

πŸ” For security reasons, you can only view your bot token once. If you misplace your token, you'll have to generate a new one.

Adding bot permissions

Now we'll configure the bot with permissions required to create and use slash commands, as well as send messages in channels.

  • Click on the OAuth2 tab, and choose the URL Generator. Click the bot and applications.commands scopes.
  • Check the boxes next to Send Messages and Use Slash Commands, then copy the Generated URL.

awwbot permissions

  • Paste the URL into the browser and follow the OAuth flow, selecting the server where you'd like to develop and test your bot.

Creating your Cloudflare worker

Cloudflare Workers are a convenient way to host Discord bots due to the free tier, simple development model, and automatically managed environment (no VMs!).

Storing secrets

The production service needs access to some of the information we saved earlier. To set those variables, run:

$ wrangler secret put DISCORD_TOKEN
$ wrangler secret put DISCORD_PUBLIC_KEY
$ wrangler secret put DISCORD_APPLICATION_ID

You'll also need the Guild ID for the server where your app is installed. This can be found in the URL when you visit any channel in that server.

For example, if my URL was https://discord.com/channels/123456/789101112, the Guild ID is the first numberβ€”in this case 123456.

Once you know your Guild ID, set that variable as well:

$ wrangler secret put DISCORD_TEST_GUILD_ID

Running locally

‼️ This depends on the beta version of the wrangler package, which better supports ESM on Cloudflare Workers.

Let's start by cloning the repository and installing dependencies. This requires at least v16 of Node.js:

$ npm install

Before testing our bot, we need to register our desired slash commands. For this bot, we'll have a /awwww command, and a /invite command. The name and description for these are kept separate in commands.js:

export const AWW_COMMAND = {
  name: 'awwww',
  description: 'Drop some cuteness on this channel.',
};

export const INVITE_COMMAND = {
  name: 'invite',
  description: 'Get an invite link to add the bot to your server',
};

The code to register commands lives in register.js. Commands can be registered globally, making them available for all servers with the bot installed, or they can be registered on a single server.

In this example - we'll just focus on global commands:

import { AWW_COMMAND, INVITE_COMMAND } from './commands.js';
import fetch from 'node-fetch';

/**
 * This file is meant to be run from the command line, and is not used by the
 * application server.  It's allowed to use node.js primitives, and only needs
 * to be run once.
 */

const token = process.env.DISCORD_TOKEN;
const applicationId = process.env.DISCORD_APPLICATION_ID;

if (!token) {
  throw new Error('The DISCORD_TOKEN environment variable is required.');
}
if (!applicationId) {
  throw new Error(
    'The DISCORD_APPLICATION_ID environment variable is required.'
  );
}

/**
 * Register all commands globally.  This can take o(minutes), so wait until
 * you're sure these are the commands you want.
 */
async function registerGlobalCommands() {
  const url = `https://discord.com/api/v10/applications/${applicationId}/commands`;
  await registerCommands(url);
}

async function registerCommands(url) {
  const response = await fetch(url, {
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bot ${token}`,
    },
    method: 'PUT',
    body: JSON.stringify([AWW_COMMAND, INVITE_COMMAND]),
  });

  if (response.ok) {
    console.log('Registered all commands');
  } else {
    console.error('Error registering commands');
    const text = await response.text();
    console.error(text);
  }
  return response;
}

await registerGlobalCommands();

This command needs to be run locally, once before getting started:

$ DISCORD_TOKEN=**** DISCORD_APPLICATION_ID=**** node src/register.js

We're finally ready to run this code locally! Let's start by running our local development server:

$ npm run dev

When a user types a slash command, Discord will send an HTTP request to a public endpoint. During local development this can be a little challenging, so we're going to use a tool called ngrok to create an HTTP tunnel.

$ npm run ngrok

forwardin

This is going to bounce requests off of an external endpoint, and foward them to your machine. Copy the HTTPS link provided by the tool. It should look something like https://8098-24-22-245-250.ngrok.io.

Now head back to the Discord Developer Dashboard, and update the Interactions Endpoint URL for your bot:

interactions-endpoint

This is the process we'll use for local testing and development. When you've published your bot to Cloudflare, you will want to update this field to use your Cloudflare Worker URL.

Deployment

This repository is set up to automatically deploy to Cloudflare Workers when new changes land on the main branch. To deploy manually, run npm run publish, which uses the wrangler publish command under the hood.

Publishing via a GitHub Action requires obtaining an API Token and your Account ID from Cloudflare. These are stored as secrets in the GitHub repository, making them available to GitHub Actions.

The following configuration in .github/workflows/ci.yaml demonstrates how to tie it all together:

release:
  if: github.ref == 'refs/heads/main'
  runs-on: ubuntu-latest
  needs: [test, lint]
  steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v2
      with:
        node-version: 16
    - run: npm install
    - run: npm run publish
      env:
        CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
        CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}

Code deep dive

Most of the interesting code in this bot lives in src/server.js. Cloudflare Workers require exposing a fetch function, which is called as the entry point for each request. This code will largely do two things for us: validate the request is valid and actually came from Discord, and hand the request over to a router to help give us a little more control over execution.

export default {
  /**
   * Every request to a worker will start in the `fetch` method.
   * Verify the signature with the request, and dispatch to the router.
   * @param {*} request A Fetch Request object
   * @param {*} env A map of key/value pairs with env vars and secrets from the cloudflare env.
   * @returns
   */
  async fetch(request, env) {
    if (request.method === 'POST') {
      // Using the incoming headers, verify this request actually came from discord.
      const signature = request.headers.get('x-signature-ed25519');
      const timestamp = request.headers.get('x-signature-timestamp');
      const body = await request.clone().arrayBuffer();
      const isValidRequest = verifyKey(
        body,
        signature,
        timestamp,
        env.DISCORD_PUBLIC_KEY
      );
      if (!isValidRequest) {
        console.error('Invalid Request');
        return new Response('Bad request signature.', { status: 401 });
      }
    }

    // Dispatch the request to the appropriate route
    return router.handle(request, env);
  },
};

All of the API calls from Discord in this example will be POSTed to /. From here, we will use the discord-interactions npm module to help us interpret the event, and to send results.

/**
 * Main route for all requests sent from Discord.  All incoming messages will
 * include a JSON payload described here:
 * https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object
 */
router.post('/', async (request, env) => {
  const message = await request.json();
  console.log(message);
  if (message.type === InteractionType.PING) {
    // The `PING` message is used during the initial webhook handshake, and is
    // required to configure the webhook in the developer portal.
    console.log('Handling Ping request');
    return new JsonResponse({
      type: InteractionResponseType.PONG,
    });
  }

  if (message.type === InteractionType.APPLICATION_COMMAND) {
    // Most user commands will come as `APPLICATION_COMMAND`.
    switch (message.data.name.toLowerCase()) {
      case AWW_COMMAND.name.toLowerCase(): {
        console.log('handling cute request');
        const cuteUrl = await getCuteUrl();
        return new JsonResponse({
          type: 4,
          data: {
            content: cuteUrl,
          },
        });
      }
      case INVITE_COMMAND.name.toLowerCase(): {
        const applicationId = env.DISCORD_APPLICATION_ID;
        const INVITE_URL = `https://discord.com/oauth2/authorize?client_id=${applicationId}&scope=applications.commands`;
        return new JsonResponse({
          type: 4,
          data: {
            content: INVITE_URL,
            flags: 64,
          },
        });
      }
      default:
        console.error('Unknown Command');
        return new JsonResponse({ error: 'Unknown Type' }, { status: 400 });
    }
  }

  console.error('Unknown Type');
  return new JsonResponse({ error: 'Unknown Type' }, { status: 400 });
});

Questions?

Feel free to post an issue here, or reach out to @justinbeckwith!

You might also like...

A discord bot made using discord.js and discord-player

A discord bot made using discord.js and discord-player

Musx A custom discord bot that can play music in your server 🎯 Add the bot to your server If you are looking for a music bot for your Discord server

Mar 28, 2022

Meet Muffin - a multipurpose, customizable and open source Discord bot with bunch of useful features for your server!

Meet Muffin - a multipurpose, customizable and open source Discord bot with bunch of useful features for your server!

Meet Muffin - a multipurpose, highly customizable and open source Discord bot with bunch of useful features for your server! Self-hosting notice While

Oct 21, 2021

πŸ”Š first auto join discord selfbot - just with one command join it to your server πŸ”₯

πŸ”Š first auto join discord selfbot - just with one command join it to your server πŸ”₯

πŸ€– Messi (Discord Self Bot) first auto join discord selfbot - just with one command join it to your server discord.js-selfbot πŸ”§ Requirements Discord

Dec 12, 2022

Link your position on a mcbe server to a discord voice. The sound changes according to the distance to the nearest players.

DiscordLink Link your position on a mcbe server to a discord voice. The sound changes according to the distance to the nearest players. Credits - No I

May 28, 2022

πŸ€–A small, robust Discord bot to support and manage a daily word game in your server. (soonβ„’)

Wordable πŸ€– Wordable is a small, robust Discord bot to support and manage a daily word game in your server! Commands /ping - Replies with pong! /guess

Feb 11, 2022

QBCore - Create codes using discord bot to redeem items & cash in your server!

Things you should know: The code was built for Old QBCore, you can of course change it to new if you want. (If you need help feel free to ask) When yo

Dec 10, 2022

Talking Ben on your Discord Server? Sure!

Talking Ben on your Discord Server? Sure!

Talking Ben Discord Bot Talking Ben is my opensource Discord Bot inspired by a game Talking Ben. Bot is running on discord.js v13 version. Tutorial Cr

Mar 25, 2022

A multi-purpose assistant bot for Discord to make your server a better place.

A multi-purpose assistant bot for Discord to make your server a better place.

━━━━━━ ❖ ━━━━━━ Rieko 🎁 FEATURES To be filled. πŸ’Έ TIP JAR If you enjoyed it and would like to show your appreciation, you may want to tip me here. It

May 23, 2022

Manoj Bajpayee Bot offers funny interactions on your discord server.

Manoj Bajpayee Discord Bot Invite Link : https://discord.com/api/oauth2/authorize?client_id=986232247680118814&permissions=534857121088&scope=bot Inst

Jul 17, 2022
Comments
  • docs: Minor README revisions

    docs: Minor README revisions

    • Adds section + image focused on permissions to add a bit of clarity
    • Add description of how to find Guild ID
    • Minor formatting and consistency edits throughout

    See https://github.com/shaydewael/awwbotcf/tree/README-suggestions for preview

    opened by shaydewael 0
Owner
Justin Beckwith
Building bots @discord
Justin Beckwith
Co-Pilot is a discord Bot designed to be the all-in-one, open-source Discord bot that handles all your server needs.

Welcome to Co-Pilot Bot repo! ?? ?? Co-Pilot (All-in-one Discord Bot) Co-Pilot is a discord Bot designed to be the all-in-one, open-source Discord bot

YMafalha 19 Nov 11, 2022
Aeona is a multi-purpose discord bot ready to skill up and boost up your Discord server! It has an State of the Art AI chatbot to make sure you never feel bored!

Aeona | Chatbot Aeona is an ever-growing multipurpose bot; primarily a fun chatbot you can converse with, but also showcases a wide range of fun comma

null 29 Jan 9, 2023
About Discord bot draft that does not contain ready-made commands, compatible with discord.js v14. Create your own discord bot with this command handler.

discordJS-V14 About Discord bot draft that does not contain ready-made commands, compatible with discord.js v14. Create your own discord bot with this

Umut Bayraktar 36 Dec 28, 2022
Discord Bot of the NCS's Discord server.

Installation Install dependencies npm install Start the server npm start Usage/Examples Create .env file touch .env Add this to the file TOKEN=y

NextCitizens 10 Sep 3, 2022
Mabicord AIO is a Discord bot that handles MMORPG Mabinogi's bugle messages, designed to serve a single Discord server.

Welcome to NamVr Discord Bot Template ?? An open source discord.js bot template which is based on official discord.js guide to get started on making y

Shane Lx 2 Jul 13, 2022
The Discord Bot for the AvdanOS Community Discord server.

Tinan The Discord Bot for the AvdanOS Community Discord server, made using discord.js v13.8. How to contribute Forking Step 1: Make a contribution for

AvdanOS 11 Dec 1, 2022
A simple & easy2use API for obtaining information about a discord user, discord bot or discord guild and their use for some purpose on websites!

discord-web-api A simple & easy2use API for obtaining information about a discord user, discord bot or discord guild and their use for some purpose on

InvalidLenni 2 Jun 28, 2022
Discord-Bot - You can use the discord bot codes that are updated in every video of the codes I use in the discord bot making series that I have published on my youtube channel.

Discord-Bot You can use the discord bot codes that are updated in every video of the codes I use in the discord bot making series that I have publishe

Umut Bayraktar 114 Jan 3, 2023
Discord Neura - a Discord bot framework built on discord.js

Discord Neura Description Discord Neura is a Discord bot framework built on discord.js. Features Command Handler, Arguments, Preconditions and Listene

Discord Neura 3 Mar 23, 2022
Gitlift Discord Bot is a discord bot which is listening Discord Messages to reply with user gitlift profile and total contributions.

Remoklify - Gitlift Discord Bot Gitlift Discord Bot is a discord bot which is listening Discord Messages to reply with user gitlift profile and total

Remoklify 3 Mar 20, 2022