DEV Community

Cover image for Using aoi.js to build a bot on Discord
Megan Lee for LogRocket

Posted on • Originally published at blog.logrocket.com

Using aoi.js to build a bot on Discord

Written by Rahul Padalkar✏️

Discord is a popular application used for managing online communities. Bots play a huge role in managing these communities. They can entertain members of the Discord server by sending memes, making announcements in public channels, reminding people of upcoming birthdays, and so on.

As web developers, we can use the power of Discord bots to make the development process more efficient. For example, we could build systems for monitoring, data retrieval, and notifications.

Using Discord bots to build such systems can have many advantages:

  • No need to invest a lot of time in building such systems — we can use open source libraries to build our bot quickly
  • Discord roles make it possible to restrict access to the bot
  • Limiting the bot to certain channels in the server helps control data access
  • If Discord is used as your team’s primary means of communication, then the team can get all the updates in a single application — for example, a notification when an incident happens, like a build failure or a spike in memory usage
  • Using the bot to get relevant information from the database for the team might reduce the risk of leaking database credentials

In this blog post, we will see how we can build a Discord bot using the aoi.js library and use it to retrieve data from the database. We will also see how we can use the bot as a notification system.

Let’s dive in.

Why use aoi.js?

aoi.js is a string-based package for creating Discord bots. This means bot developers can use strings to trigger functions in response to a command. For example:

client.command({
  name: "ping",
  code: `
  $sendMessage[pong]
  `
});
Enter fullscreen mode Exit fullscreen mode

In the above code, when the user gives a ping command, the bot responds with a message pong.

Here, we are using the pre-built $sendMessage function from aoi.js to send the message pong. aoi.js has over 600 pre-built functions that bot developers can use, so you don’t necessarily need to know how to code to develop a simple bot with this package.

For more advanced use cases, aoi.js provides developers with an option to create custom functions. This package also comes with a database and a music extension. Developers can store simple data — like key-value pairs — in the database, while the music extension makes it possible to develop bots with music capabilities.

aoi.js has an active community of over four thousand members on Discord. If you ever need help while developing a bot, they can reach out to folks.

The ability to build bots using just strings, along with its rich library of over 600 pre-built functions, sets aoi.js apart from other libraries in the same space. Using this library greatly reduces the time and effort required to build bots is reduced greatly.

Creating a Discord application

To create a Discord bot, we first need to create a Discord application. The only prerequisite for this step is having a Discord account.

Head over to the Discord developer portal to create a new Discord application. Give your application a name and hit Create. Once the application is successfully created, you will be automatically redirected to the application configuration screen.

On the left sidebar, click on Bot. Here, you should be able to change the bot’s username. For this tutorial, we’ll change it to FeedbackBot.

One more important thing on the Bot page is the TOKEN under the username. We will use this token — referred to as a Bot Token — to connect to Discord servers and make API calls. To get the token, click on Reset Token and copy the token once it’s generated: Demonstrating How To Retrieve A Bot Token In Discord

Remember, never share this token with anyone. Also, the token is visible only once, so in case you lose the token, your only option is to reset the token. This action invalidates the older token, so any API calls made using the old token will be invalid.

Additional steps you can take for your own bot include adding a description to the application, adding an icon for the bot, and controlling how it looks via the Rich Presence options.

Adding the Discord bot to our server

Now that we have created a bot, let’s try to add it to our server. To do so, we need to generate a bot invite link. The bot invite link is formatted like so:

https://discord.com/api/oauth2/authorize?client_id=client_id_goes_here&permissions=bot_permission_integer_goes_here&scope=bot
Enter fullscreen mode Exit fullscreen mode

There are two things that we need to make the above URL work:

  • client_id: This can be obtained from the OAuth2 configuration
  • permission_integer: This can be obtained by checking the required bot permissions in the Bot configuration screen that we visited earlier. To keep things simple, we’ll use the Administrator option in the permissions list. Remember, giving admin access to a bot can be risky; please only provide permissions that are absolutely necessary for the bot to function

To easily generate a bot invite link, you can use this permission calculator website. Once the invite link is generated, navigate to that link and add the bot to your server. Once added, the bot will join the general channel in your server.

Configuring and pinging the Discord bot

Now that we have added our bot to our server, let’s configure it using the aoi.js library, then ping it and see if it responds.

First, create a Node.js project:

mkdir discrod-bot
cd discord-bot
npm init
Enter fullscreen mode Exit fullscreen mode

Then, let’s install aoi.js:

npm i aoi.js
Enter fullscreen mode Exit fullscreen mode

aoi.js is a simple and fast JavaScript package for developing Discord bots. It’s free and open source, and it provides a simple interface to interact with the Discord API. As discussed, aoi.js has over 600 built-in functions that developers can use to quickly build their bots. It also comes with a built-in database that makes storing data a lot easier.

This library only works with newer versions of Node.js, so make sure you have Node v18.19.0 or above. You can either upgrade to this version or use nvm to manage and install multiple Node versions.

Now that we have everything in place, let’s create a bot.js file in our project root:

const { AoiClient } = require("aoi.js");
require("dotenv").config();

const client = new AoiClient({
  token: process.env.BOT_TOKEN || "",
  prefix: "FeedbackBot",
  intents: ["MessageContent", "Guilds", "GuildMessages"],
  events: ["onMessage", "onInteractionCreate"],
});

client.command({
  name: "ping",
  code: `Pong! $pingms`,
});
Enter fullscreen mode Exit fullscreen mode

Here, we create a AoiClient and pass in the BOT_TOKEN, and prefix, intents, and events arrays. Let’s take a closer look at the intents and events arrays.

Intents are WebSocket events sent by Discord to the bot. There are various types of intents. It’s important to pass only those intents that are absolutely necessary for the bot to function; otherwise, the bot will receive data that is irrelevant to it.

In our example above, we use a privileged intent, MessageContent. For this to work, we need to enable MESSAGE CONTENT INTENT in Privileged Gateway Intents. You can toggle this setting in the Bot section of our app in the Discord developer portal: Enabling Message Content Intent Option Under Privileged Gateway Intents Settings In Discord

We then define events in the events array. This tells the client to listen for these events. We created a command called ping and told the bot to respond with pong followed by bot latency in ms.

Since aoi.js is a string-based package for developing Discord bots, it offers a lot of string-based functions out of the box for this purpose. $pingms is one such function that we used in the code above. For a full list of string functions, check out the aoi.js docs.

We’re not quite done yet. Create a .env file in the project root and add the bot token that we generated before:

BOT_TOKEN=bot_token_goes_here
Enter fullscreen mode Exit fullscreen mode

To make development a bit easier, let’s install Nodemon:

npm i -g nodemon
Enter fullscreen mode Exit fullscreen mode

Optionally, we can also add a command in the package.json file for running the bot:

{
  "name": "aoijs-bot",
  "version": "1.0.0",
  "description": "Building bot in aoijs",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start-bot": "nodemon ./bot.js",
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "aoi.js": "^6.7.1",
    "dotenv": "^16.4.1",
  },
  "devDependencies": {}
}
Enter fullscreen mode Exit fullscreen mode

Now, to start the bot, run the following command:

npm run start-bot
Enter fullscreen mode Exit fullscreen mode

This will start the bot. If you type FeedbackBotping in the general channel, the bot should reply with a message that says Pong! and provides the latency in ms: Discord Chat Open With Test Message To Ping Bot With Bot Response Of Pong Yes, it works! 🤯

Getting feedback from a user using our bot

This is already cool, but now, let’s make the bot more useful. We’ll start with the first use case for our bot, which is to retrieve useful data on demand.

Let’s say we have a web application where users enter feedback. The feedback may be about the products or services our web app offers, the user’s experience using our application, or some glitches or issues a user experienced while using the web application.

We’ll use a fake example of user feedback regarding glitches or technical issues faced while using our web app. The feedback is stored in a feedback table in a Postgres database. Our bot retrieves that feedback on demand and sends it to a channel.

There are three different systems working together here — the frontend application containing the feedback form, the server (which communicates with our Postgres database), and the Discord bot: Graphic Showing Three Coordinating Systems And How They Work Together: The Frontend With The Form, The Server, And The Discord Bot

Let’s start with the frontend application part. Let’s quickly create a React application using Vite:

npm create vite@latest
Enter fullscreen mode Exit fullscreen mode

Follow the prompts, and Vite will generate a new React application for you. Let’s use aoijs-feedback-form as the name of application. Now, we’ll create a simple feedback form:

// ./App.jsx
import { useState } from "react";
import "./App.css";
import api from "./api";
function App() {
  const [feedback, setFeedback] = useState("");
  const onSubmit = async () => {
    const res = await api.post("/feedback", {
      feedback,
    });
    if (res.success) {
      console.log("Submitted");
    }
  };
  return (
    <>
      <div>Feedback Form</div>
      <textarea
        rows="20"
        cols="100"
        onChange={(e) => {
          setFeedback(e.target.value);
        }}
      />
      <div>
        <button onClick={onSubmit}>Submit</button>
      </div>
    </>
  );
}
export default App;
Enter fullscreen mode Exit fullscreen mode

We hooked up the feedback form with an API that we will build next:

// ./api.js
import axios from "axios";
const api = axios.create({
  baseURL: import.meta.env.VITE_API_URL,
});
export default api;
Enter fullscreen mode Exit fullscreen mode

To finish creating our simple API, we’ll head back to our bot Node.js project and install Express:

npm i express pg
Enter fullscreen mode Exit fullscreen mode

Now, let’s create a server.js file in the root of our project:

// db.js
const { Client } = require("pg");
require("dotenv").config();
let client;
module.exports = {
  connectToDB: async () => {
    client = new Client({ connectionString: process.env.DB_URL });
    await client.connect();
    console.log(`Connected to DB successfully!`);
  },
  executeQuery: async (query, values) => {
    return await client.query(query, values);
  },
};
Enter fullscreen mode Exit fullscreen mode

Copy and paste the following code into your server.js file:

// server.js
import express from "express";
import { connectToDB, executeQuery } from "./db";
const app = express();
app.use(express.json());

app.post("/feedback", async (req, res) => {
  const { feedback } = req.body;
  await executeQuery("INSERT INTO feedback(feedback) VALUES($1)", [feedback]);
  res.send({ success: true });
});

app.listen(4600, async () => {
  await connectToDB();
  console.log(`API started on port 4600`);
});
Enter fullscreen mode Exit fullscreen mode

Here, we create an endpoint called POST /feedback. When the user clicks on the Submit button in the feedback form, it sends a POST request to our server. We then insert that feedback in our Postgres database.

We will add another command in package.json to run our server:

{
  "name": "aoijs-bot",
  "version": "1.0.0",
  "description": "Building bot in aoijs",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start-bot": "nodemon ./bot.js",
    "start-server": "nodemon ./server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "aoi.js": "^6.7.1",
    "dotenv": "^16.4.1",
    "express": "^4.18.2"
  },
  "devDependencies": {
    "@types/pg": "^8.11.0",
    "pg": "^8.11.3",
  }
}
Enter fullscreen mode Exit fullscreen mode

To run our server, we need to run this command:

npm run start-server
Enter fullscreen mode Exit fullscreen mode

Now, let’s modify our bot code, finish the final piece of our system, and test it out:

const { AoiClient, CustomEvent } = require("aoi.js");
require("dotenv").config();
const { connectToDB, executeQuery } = require("./db");

connectToDB();
const client = new AoiClient({
  token: process.env.BOT_TOKEN || "",
  prefix: "FeedbackBot",
  intents: ["MessageContent", "Guilds", "GuildMessages"],
  events: ["onMessage", "onInteractionCreate"],
});

client.command({
  name: "ping",
  code: `Pong! $pingms`,
});

client.functionManager.createFunction({
  name: "$getFeedback",
  type: "djs",
  code: async (d) => {
    const data = d.util.aoiFunc(d);
    const { rows } = await executeQuery("SELECT * FROM feedback");
    const feedback = rows.map(({ feedback }) => feedback);
    const msg = await d.message.channel.send(`${feedback.join("\n")}`);
    data.result = msg;
    return { code: "" };
  },
});

client.command({
  name: "getFeedback",
  code: "$getFeedback",
  nonPrefixed: true,
});
Enter fullscreen mode Exit fullscreen mode

Here, we use the createFunction utility provided by aoi.js to create a custom function that connects to our Postgres database and returns data stored in the feedback table. We then create a getFeedback command and call the function we created above.

Now to test this, let’s run everything:

npm run dev // to start react app
npm run start-bot // to start bot application
npm run server // to start the api
Enter fullscreen mode Exit fullscreen mode

We’ll submit some dummy feedback in the form: Simple Feedback Form In Frontend App with Dummy Content After submitting the feedback form, you should receive a message from the FeedbackBot: Discord Chat Open To Show User Testing The Feedback Bot's Notification Feature With Dummy Feedback Yeah, it works!!!

Sending a notification in a Discord channel after an incident

In the previous section, we saw how we can use Discord bot to retrieve information on demand from a data source — in our case, a Postgres database. However, Discord bots can also be used for sending out notifications in a channel when an event happens in the system.

For example, you could set up your bot to notify you when a dev on your team opens a new pull request. You could also send notifications if the CI/CD pipeline fails, the memory or CPU usage of an instance spikes, or pretty much any other situation you need.

Let’s see how we can send a message in a Discord channel when such an event occurs. In our bot code, we will create a custom incident event and trigger it using a setInterval function to simulate an incident:

const { AoiClient, CustomEvent } = require("aoi.js");
require("dotenv").config();
const { connectToDB, executeQuery } = require("./db");

connectToDB();

const client = new AoiClient({
  token: process.env.BOT_TOKEN || "",
  prefix: "FeedbackBot",
  intents: ["MessageContent", "Guilds", "GuildMessages"],
  events: ["onMessage", "onInteractionCreate"],
});

client.command({
  name: "ping",
  code: `Pong! $pingms`,
});

client.functionManager.createFunction({
  name: "$getFeedback",
  type: "djs",
  code: async (d) => {
    const data = d.util.aoiFunc(d);
    const { rows } = await executeQuery("SELECT * FROM feedback");
    const feedback = rows.map(({ feedback }) => feedback);
    const msg = await d.message.channel.send(`${feedback.join("\n")}`);
    data.result = msg;
    return { code: "" };
  },
});

client.command({
  name: "getFeedback",
  code: "$getFeedback",
  nonPrefixed: true,
});

client.functionManager.createFunction({
  name: "$notifyDevs",
  type: "djs",
  code: async (d) => {
    const data = d.util.aoiFunc(d);
    const channel = await d.client.channels.fetch("channel_id_goes_here");
    const msg = channel.send("Incident detected!");
    data.result = msg;
    return { code: "" };
  },
});

const event = new CustomEvent(client);
event.command({
  listen: "incident",
  code: `$notifyDevs`,
});

event.listen("incident");

setInterval(() => {
   event.emit("incident");
}, 6000); 
Enter fullscreen mode Exit fullscreen mode

In the code above, we created:

  • An incident event using a CustomEvent from aoi.js that we passed to the client object we created earlier. Next, we assigned the $notifyDevs function to execute when the event occurs. Then, we start the listener for the incident event
  • A custom $notifyDevs function that sends a message that reads Incident detected in a channel with the given channel ID

Note that to get a channel‘s ID, you simply open the Discord server and the target channel in your web browser. The last number in the URL bar is the channel ID: Discord Channel Id Shown Anonymized In Example Url As mentioned, to simulate an event, we use a setInterval function that periodically emits the event incident every 6 seconds. In the real world, many services — like Circle CI and GitHub — provide webhook events that our bot can listen to and trigger the incident event if necessary.

To run the bot, execute the following command:

npm run start-bot
Enter fullscreen mode Exit fullscreen mode

Every 6 seconds, you should see a message sent by the bot in the channel: Discord Chat Open Showing User Testing Incident Notification Bot With Dummy Incidents That Send A Notification Through The Bot Every Six Seconds

Conclusion

Discord bots can be very powerful. They are easy to build and run and don’t require a lot of deep knowledge of the Discord API. You can use them in creative ways to work more efficiently.

There are a ton of packages you can use to quickly build a Discord bot. Some examples include discord.js, aoi.js, js-cord, and Eris. You can also read this tutorial on building a Rust Discord bot to see another option in action, step by step.

Among these, aoi.js stands out for its user-friendly, string-based bot development approach and rich, extensive library of pre-built functions. In this tutorial, we explored how to use the aoi.js library to build our bot.

Thank you for reading!


Get set up with LogRocket's modern error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID.
  2. Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.

NPM:

$ npm i --save logrocket 

// Code:

import LogRocket from 'logrocket'; 
LogRocket.init('app/id');
Enter fullscreen mode Exit fullscreen mode

Script Tag:

Add to your HTML:

<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
Enter fullscreen mode Exit fullscreen mode

3.(Optional) Install plugins for deeper integrations with your stack:

  • Redux middleware
  • ngrx middleware
  • Vuex plugin

Get started now

Top comments (0)