Learn to Code via Tutorials on Repl.it!

← Back to all posts
Making a Discord bot in Ruby
h
InvisibleOne (3206)

#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.

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:

Or if we include too many arguments:

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:

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

Comments
hotnewtop
VulcanWM (2886)

Woah this is amazing!

InvisibleOne (3206)

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