Build A Bot (DiscordJS) — A Bot Factory and Revealing Module Design Pattern

Last time we made our commands more flexible and improved the structure of our code for better readability and scalability. This time we will turn our simple bot into a bot factory, allowing us to use it to spawn multiple bots with different configs, using the well-established Factory and Revealing Module design patterns.

SERIES: Build A Bot (DiscordJS)
1) Javascript Chatbots made easy
2) A scalable setup with command modules
3) => you are here <=
4) Better Logging And A Persistent Bot Config

Things you should know for this part include scope and closure of Javascript functions as well as es6 basics (const, let and fat arrow functions)

Transformation

Then we will wrap all of our remaining code in our factory function and call it createBot but if we were to simply return the bot object, which we used until now, this would mean that everything within this function will be bundled together and publicly available. We don't want that, do we?

To make sure we control what is visible and accessible from the outside, we won’t return the bot object itself but only the functions that need to be usable. In our case right now this is only the bot.load() function. Thanks to the closure, the bot object will still be there and remember all that we need for our bot to run but access is limited to what we pass to the return function. This is often referred to as the Reveal Module Pattern.

Add a return {} to the createBot function and only define one attribute as start() that will call the load function.

The last thing to add now is the module.export with our createBot function.

You might have noticed that I did not use the correct indentation here. To show you a better screenshot, I simply kept the indentation (even though I wrapped the code in a function) so that the diff would show exactly what I changed in each line.

I will correct this before we move on.

GitHub Commit (changes)

Adjustments

The new load() will expect a config object with mandatory (token) and optional (name, prefix and later other) attributes and attempt to merge them with our configSchema in loadConfig(). Our old code will be passed into loadConfig() as a callback here.

In loadConfig() we will check if our initial config is there and contains a token. If either check fails, we will throw an error. Otherwise, we will merge the initial config with our configSchema and attach it to our bot before we execute the callback code.

We need to make a small adjustment to grab our prefix from the new config and then we’re done here.

With our factory in place, it’s time to add the bots. For this part to work properly, you would need to head over to my first instalment of this series and create a second bot via developers portal but you might as well just make an array of 1 bot and go with it.

Create a new index.js at the root of the project. This is where we will import our factory, load our .env variables containing our tokens and add the configs for our bots. Without an array of bots to start, this would be the way to start a single bot with the factory.

If you have only one bot, it’s super easy to start it. Create the bot using the factory with your config and run the start() that is publicly available.

You are done!

If you want to define a group of bots to run from your project, you can simply do so in the config file.

If you name your tokens in your .env file accordingly, you can map them in your config file like this.

Running our new index.js file will now start as many bots as you have entered in your config file.

If you have given them different prefixes, you can now interact with them as if they were fully independent bots. Should you use the same prefix for both bots, both would react to the same command.

With one final adjustment to our package.json to switch to the new index.js file we are now done and can spawn as many bots as we like (and have registered with Discord)

One word of advice though.

If you are running bots on your own server, this way of creating multiple bots is ok. If you plan on hosting this bot on many servers to be used by many people, grouping more than one bot together is not advisable because it can lead to performance issues.

In that case, it would be better to reuse the code for the factory (for example by submitting it to and loading/importing it from npm).

Bonus

Git Commit (tagged logging)Link to the finished code / tag v0.0.3 on GitHub

Wrapping up

Next time I will guide you through the process of writing a scaleable and self-updating help command as well as adding our first user management/administration commands to make the bot a bit more useful.

Some words about me:

I’m also currently working on other series covering complex React Native Setups using Typescript and scalable apps with Redux, where I’ll go into details about how and why I do stuff the way I do as well as some articles on my experience in building games for web and mobile with React.

Here are some of my recent topics:
- React Quick Start with Typescript, Redux and Router
- Linting/Prettier with Typescript
- Redux + Toolkit with Typescript
- Spread & Rest Syntax in Javascript
- clean and simple Redux, explained
- Game Theory behind Incremental Games
- Custom and flexible UI Frames in React Native

And if you feel really supportive right now, you can always support me on patreon, thus allowing me to continue to write tutorials and offer support in the comments section.

I’m a Web / App Developer & father 👨‍👩‍👧 doing freelance and part-time agency work since 2003, 💻 building stuff on the side 🕹 and attending conferences 🎟