Skip to content
← Back to Community
Making a Discord bot in Ruby
Profile icon
h
has Hacker Plan
InvisibleOne

#Discord bot in Ruby!

Most people know that you can create a discord bot in Python or Javascript, maybe some of you even know how to do it in Java or another lang.
You can also do it in ruby, and it isn’t as completemicated (Meaning: Complicated) as you might think.
Ruby is sort of like a mix of a bunch of languages, its syntax is similar to python and Lua, but also quirky and different, it’s actually really fun to write.

Step 1

The first thing that you need to do to make a Discord bot in ruby is make a new application in the discord developer portal and getting the secret token.
Use secrets to hide this and access it in the code with ENV["TOKEN_NAME"] which is quite simple.

Step 2

Next, we need to get the modules to use, which is discordrb

We can require that at the top of the code, and then use the replit package manager to add it so it is added to our bundle.

require "discordrb"

Then we can make a global variable to hold our prefix and token… which I think is like this:

$prefix = "$" # set the prefix to whatever you like $token = ENV["TOKEN"] # this doesn't have to be global

And finally we can actually initiate the discord bot.

@bot = Discordrb::Commands::CommandBot.new token: token, prefix: $prefix

This creates a new instance of a command bot, using our token and prefix. You can also add a client id but I didn’t and it worked just fine for this little bot, it’s probably important for bigger projects.

And then to run the bot we just do

@bot.run

Step 3

Setting commands for a ruby bot is pretty simple, sort of like doing it in python.

@bot.command(:ping) do |event| event.respond "Pong!" end

What this does is create a command ping . By default it takes event as the first argument, similar to ctx in a python discord bot command.
We can then use the event to get access to the users data or respond to them, we don’t have to await it in ruby.

Using event we can access stuff like author which then gives us access to the users name, id and so on.

@bot.command(:hello) do |event| event.respond "Hello there #{event.author.mention}" end

Step 4

To include arguments into our commands, all we have to do is add more args after event.

@bot.command(:say) do |event, text| event.respond text end

Now if we send a message in the discord channel: $say hello we should get the bot saying hello

This only works if the user includes the argument, if they don’t, then the command won’t work.
To force them to include an argument, we can add min_args: 1 inside out @bot.command() line.

@bot.command(:say, min_args: 1) do |event, text| event.respond text end

Now if the user does not include at least one arg, they will get a message telling them they have to include an argument and the command won’t try and run.

Step 5

Hopefully you know get the general idea behind the commands, so let’s start making out bot do some stuff.
I decided to make it tell some jokes, so I included a gem called dad_jokes

First you need to add it with the replit package manager, then require it at the top of the code

require "dad_jokes"

Then we’ll make a command joke that can take an argument, but it isn’t required. If the argument is required, we will search for a joke including that keyword, but if it isn’t, then we will just return a random joke.

@bot.command(:joke) do |event, arg| if arg result = DadJokes.search(term: arg, limit: 100) # limit it to a list of 100 jokes if result != [] event.respond result.sample # if there are results, return a random one else event.respond "Could not find a joke with keyword #{arg}" # else tell the user we didn't find a joke with that keyword end else event.respond DadJokes.random # give them a random joke if there is no argument end end

Testing it in our discord, we can see that we don’t have to include an argument, but if we do it will search by that argument.

Screen Shot 2021-07-10 at 11.56.27 AM

Now let’s make a command to do something that requires some arguments. Since we want the bot to be smart, we’ll give him the ability to do math.

The basic input should be $math 10 + 5 and the result should be the answer. This means we’ll need a minimum of three arguments, but also a maximum of three arguments.

We can force this by adding these to arguments when we create the command:
min_args: 3 and max_args: 3

This way if three arguments are not included, we will get this result:

Screen Shot 2021-07-10 at 11.59.19 AM

Or if we include too many arguments:

Screen Shot 2021-07-10 at 12.00.36 PM

The command looks like this:

@bot.command(:math, min_args: 3, max_args: 3) do |event, arg1, operator, arg2| result = 0 # defualt result if operator == '+' # check which operation we are doing result = arg1.to_i + arg2.to_i # to_i converts the string to an integer for calculations elsif operator == '-' result = arg1.to_i - arg2.to_i elsif operator == '*' or operator == 'x' or operator == 'X' result = arg1.to_i * arg2.to_i elsif operator == '/' result = arg1.to_i / arg2.to_i else result = '???' end event.respond "#{arg1} #{operator} #{arg2} = #{result}" # respond with the result end

What this does is include three arguments, arg1, arg2 and the operator

We then check what kind of operation we want to do and return the results accordingly. It’s simple but get’s the job done, although it won’t do floats, only integers.
The result:

Screen Shot 2021-07-10 at 12.04.17 PM

Step 6

I sort of janked this, as I’m not really sure what I’m doing, but to keep the robot alive, I added a file called keepalive.rb and wrote this code:

require "socket" def keepalive() t = Thread.new() { server = TCPServer.new 80 loop do puts "Server Alive" client = server.accept client.puts "I'm alive" client.close end } end

It’s supposed to imitate what this does in python:

from flask import Flask from threading import Thread web = Flask('') @web.route('/') def home(): return "I am alive!" def run(): web.run(host='0.0.0.0',port=8080) def keep_alive(): run_thread = Thread(target=run) run_thread.start()

But does so pretty badly. I set up UptimeRobot to ping it but I’m pretty sure it isn’t going to work, although surprisingly the repl has stayed alive for a while and hasn’t stopped running yet.

The real way to solve this issue without using the hacker plan’s “always on” repl would be to use Ruby on Rails, but since I was too lazy to set up a rails server and figure out how to get everything running, I just did this and I’m hoping that it sort of works… we’ll see.

Too use my code, I just load the file at the top of the code:

load "keepalive.rb"

And then put this just above my @bot.run line of code.

keepalive() @bot.run

And so there you have it, a very basic introduction to making Discord Bots in ruby. I’m assuming that I’m not the first person to write a tutorial on this so if you need to learn more, you can try searching for another tutorial, or look at the discordrb docs.

File: README — Documentation for discordrb (3.4.0)

And here’s the repl if you want to take a look at it:

https://replit.com/@InvisibleOne/Ruby-Bot#main.rb

Voters
Profile icon
Scorpiii
Profile icon
Hitor1
Profile icon
EpicGamer007
Profile icon
VulcanWM
Profile icon
ch1ck3n
Profile icon
InvisibleOne
Comments
hotnewtop
Profile icon
devynbrett

This is amazing.
friday night funkin

Profile icon
AndiDuferense

A couple of years ago I also wanted to create my own discord bot for my channel with my gaming friends. I figured out how to make the bot was able to send video, but there was no autoconverter, and my bot could only send mp4 files and so I spent a couple of evenings and through third-party services came up with the bot itself to determine the format and using one of the best DVD-to-MP4 converters automatically convert all video and sent already mp4.

Profile icon
VulcanWM

Woah this is amazing!

Profile icon
InvisibleOne

Thanks, ruby is actually quite fun for discord bots @VulcanWM

Profile icon
VulcanWM

np, I can see that @InvisibleOne