Bryan Berger
/ Bryan Berger

My Custom Discord bot, with a Hint of Ventrilo

Back when I was in high school I used to game [A LOT] with a group of guys. We gathered together, virtually, from different parts of the world to play some of the best titles of that era (CS 1.5, COD1, COD2, COD4, etc.)

Before tools like Discord popped onto the scene we used Ventrilo to communicate in and out of game. We hosted our own server, a place where we got together to hang out and play competitively.

Screenshot of the old ventrilo client on Windows

Fast forward 10-15 years, we've all grown up and one-by-one began to gather once again.

Two of the original members (myself included) started a private Discord server, a few years later, we have ~60 active members at any given time.

Ventrilo's best feature

We quickly realized Discord was missing 1 major feature we loved from Ventrilo, that of the Channel Announcer. We would typically run Ventrilo in the background while we gamed in the foreground. When someone would join or leave a channel you were in, Ventrilo would announce that person's name, this way you could tell who it was (duh).

Discord has an in-game overlay that visually shows you who's in the channel, but, we typically disable it (in order to improve in-game performance).

Discord has an awesome API, so I decided to build a bot to replicate that old channel announcing feature we loved from Ventrilo. I wrote the bot in Javascript/Node and it works great!

Here's a bit of the code that listens for voiceStatusUpdates:

1client.on('voiceStateUpdate', (oldMember, newMember) => {
2 // ...
3 if (
4 newMember.voiceChannel &&
5 client.voiceConnections.find(
6 (item) => item.channel === newMember.voiceChannel,
7 )
8 ) {
9 announce.sayJoin(newMember)
10 } else if (
11 oldMember.voiceChannel &&
12 client.voiceConnections.find(
13 (item) => item.channel === oldMember.voiceChannel,
14 )
15 ) {
16 announce.sayLeave(oldMember)
17 }
18})

The announce module has sayJoin and sayLeave methods that synthesize the member's name + their phrases using a text to speech service. The bot then caches the resulting .wav file for future events.

I took it a step further and allow users to modify their join/leave phrase in order to introduce some personalization.

Ventrilo Inspired Commands

1// Add a join phrase for a specific user (by that user or admin)
2!phrase-join <user> <phrase>
3
4// Add a leave phrase for a specific user (by that user or admin)
5!phrase-leave <user> <phrase>
6
7// List of join and leave phrases for all users added to the database
8!phrase-list
9
10// Create random teams from a group of users (for pugs)
11!teams <number_of_teams> <list of users>

Additional Miscellaneous Commands

1// Lookup the Apex Legends stats of an Origin user
2!apex <origin-user>
3
4// Lookup server stats on our COD 2 Server
5!cod2
6
7// Lookup server stats on our CS:GO Server
8!csgo
9
10// Flip a coin. Heads or tails. Solves many disputes :)
11!flip
12
13// Command to show what this bot can respond to.'
14!help
15
16// Rejoin the current VoiceChannel
17!rejoin
18
19// Tell the bot to say something in the user's current voice channel (custom tts).
20!say <words>
21
22// Convert fahrenheit to celsius and vice-versa (because we have UK/US based friends)
23!temp <int> <f|c>
24
25// How long the bot process has been running.
26!uptime

Admin Commands

1// This command bulk deletes n messages from a channel
2!clear <number>
3
4// Forces the bot to disconnect and reconnect to discord
5!restart
6
7// Adds a specific user to the database, allows them to set their phrase
8!user-add <user>

What Next?

Currently the bot is private, but i've been getting requests from others who want to add it to their server as well (awesome!).

I've got some refactoring to do (ideally a re-write in Typescript) and enable sharding so it can scale to hundreds of servers.

I'll most likely open-source it as well. Stay tuned!

Edit 2020:

I've submitted this bot to top.gg (a Discord bot search directory). You can install it on your server for free.