Creating A Discord Bot With Lua



Many people want to create a discord bot but they are not familiar with the languages that are commonly used to do so such as JavaScript, Python etc… The thing is that there is no reason for discord bots to be constrained in one language as what you are doing when you are programming your own discord bot is just communicating with your bot through Discord’s API. So in this tutorial, I will be showing you how to create your own discord bot with Lua, as most of the people in this forum are familiar with it.

First of all to create a discord bot, we will need to install Luvit and Discordia. Here is a simple guide on how to do that: Installing Discordia · SinisterRectus/Discordia Wiki · GitHub.

EDIT: There has recently been a problem with Luvit installation, it errors when installing it, so I am also linking a .ZIP file containing all of the files you need to have (containing discordia).

Once we are done with that, put everything installed in 1 directory. Your directory should look something like this:

So now we are pretty much done with the installation! Simple as that. Time to program the bot!

So to learn how to program the bot by yourself you need to read Discordia’s wiki which covers everything about it and everything you should know about it. For the sake of this tutorial I will be showing you how you should organize your discord bot and how to make a simple command.

First of all you must create a discord bot before programming it (obviously). So go to Discord Developer Portal and make a new application. After you are done with that go to the Bot tab and get the token of the bot. Once you get it do not share it with anyone. Anyone who has access to your discord bot’s token can do anything to the bot with it! For now save that token somewhere, we will need it later.

Now create a new .lua file. Call it whatever you want. I will call it bot.lua. Once you are done with that open your .lua file with a code editor. I personally use Brackets.

Now lets create a simple command! Lets make the bot respond with pong every time we say (prefix)ping. First of all lets require discordia and define the client:

local discordia = require('discordia')
local client = discordia.Client()

Once we are done with that lets add a prefix variable and also lets add a variable for our bot’s token:

local discordia = require('discordia')
local client = discordia.Client()
local prefix = "!"
local token = --your own bot's token here

Lets start writing our bot! So here is the code I wrote to make the bot respond with pong when we say ping!:

client:on('messageCreate', function(message) 
	if message.content == prefix..'ping' then'pong')

If you are confused by this then I will explain what we are basically doing. So every time a message is being sent, we check if the message’s content is equal to prefix..'ping'. If so we respond with pong!. Simple as that. Now lets run our bot! Before we do that tho we must add this code to the bottom of our script:

client:run("Bot "..token)

Basically this just runs our bot. Now to actually run our bot and make it work we need to type cmd at the file’s location directory. Like this:
That is the first step, now type there luvit (Your Lua File Name Here). So my Lua file is called bot.lua, so I will type luvit bot.
Now our bot is ready! Lets test!
It worked! I suggest you make a .bat file which automatically runs the bot for you when testing because opening the cmd program and typing luvit bot every time is really time consuming. So lets do that. Make a new .txt file and type: luvit bot. Save it as something.bat and make sure you save it as All Files or else it won’t work. Lets test it out!
Worked! If you run the bot through a .bat file, if an error occurs the program with shut down. Every error is logged in a the discordia.log file.

Now lets take a look at our code and try to make it better:

local discordia = require('discordia')
local client = discordia.Client()
local prefix = "!"
local token = --token here

client:on('messageCreate', function(message)
	if message.content == prefix..'ping' then'pong')

client:run("Bot "..token)

So you are probably thinking the code looks good, there is nothing wrong with it, and you are right, but what if we have like 10 commands? Our functions will be spammed with code and if statements. To prevent that we can organize the code by making a dictionary which holds all of the commands. This is not useful for just organizing the code, but lets suppose you are going to make a help command. You would need to display a description for every command, and it would be better if we just looped on our command dictionary. That is just a suggestion, it is OK if you stick to the current method. So we are pretty much done programming our first bot! You can do different harder stuff with the bot, this was just an easy example for the sake of the tutorial, you can make the bot play audio (it is a bit complicated), you can make the bot kick, ban, mute people, you can make the bot do pretty much everything! Here is the wiki once more Home · SinisterRectus/Discordia Wiki · GitHub, you can learn everything about discordia there!

(P.S You will need to host your bot if you want it to always be active and run, you can self host it or you can use a VPS to host your bot such as DigitalOcean, Heroku, Glitch etc…)


I actually host a Discord bot that runs on Discordia on my PC! It has very little overhead and as long as you don’t put it into a lot of servers you should be fine; I have mine in a server with 400 people in it and it doesn’t cause a noticeable issue with my internet or PC.

Discordia uses a basic event system similiar to Roblox/Node.js, and they use (modified) coroutines by design so you don’t need to worry about an event completing before a new one begins. They run in sync.

Luvit is essentially a Lua equivalent to node.js so it changes the way a few things work. Specifically, it comes pre-packaged with things like a json manipulator and a file system similiar to node’s, but they can only be required from the main script because it was launched with Luvit. Thus require("json") will work in the main script but not in a module.

Luvit runs with LuaJIT, which extends Lua 5.1 with a lot of the API from Lua 5.2, meaning it has a few things that Roblox users may not be used to. As it uses LuaJIT, performance is a non-issue in most cases. To give you an idea, I have a loop that runs every second in my bot that performs multiple pieces of logic (It’s to increment timers and to unmute people) and it’s not caused any problems thus far.

The main changes between Lua 5.1 and 5.2 can be found here. I would strongly encourage anyone who uses this tutorial to look into them because it will make the experience a lot less painful. The big ones that will affect most people is that the environment system has changed completely (getfenv/setfenv have been killed in favor of a _ENV variable in every scope), unpack was moved into table.unpack, and loadstring is deprecated in favor of load. EDIT: This is not true. I was making an assumption. My apologies.

A thing to look out for that bamboozled me personally the first time it happened was DMs from users. If you’re relying upon messages having a guild attached to them, DMs to the bot will cause them to throw errors. You can fix that by just putting a if not message.guild then return end at the top of your message receiving function.

Overall, nice tutorial. Lua is a language that everyone here knows and it’s always nice when tutorials are written in it because it opens them up to more people. :slightly_smiling_face:


I’m a bot developer myself and I personally still think that Discord.JS above all other languages but thanks to your tutorial, I think that I’ll be trying to play around with Discordia some time soon :slight_smile:


I’m not sure if it’s the same on Windows, but to get around this you should be able to pipe the output of the command to a log file such that luvit bot > my_log.txt, which would contain all the output from the bot after it’s died off, including the error message.

This is a bug. You can fix this by adding getfenv(0).require = require to the first line of your main script.

It’s just LuaJIT, iirc.


Luvit uses LuaJIT, which is based on Lua 5.1 and implements some features from Lua 5.2:


I did not know that! Thank you for the tip.

It might just be LuaJIT, but it running with an API similiar to 5.2 is still important for the sake of API reference as most Roblox devs are used to 5.1.


It also seems like the 5.2 changes you mentioned are not present in LuaJIT, since it’s a 5.1 fork.

Here are the LuaJIT and 5.1 differences: (Wow thanks @bunny_hop ninja’d me)


waits for Roblox to allow bots

This is nice, going to link it on my own bot tutorial in case anyone has an easier time than learning JavaScript.


Thank you for this, now I can develop my bot at a much faster rate than I would have learning the finer nuances of JS.


Awesome share and tutorial! I used to code chat bots years ago when I got into PHP. I coded a couple of discord bots not too long ago but never finished them. I might pick this one up and give it a try :grinning:


i wanna try this
but idk what I want my bot to do :frowning:


Thanks and cool! By the way my tutorial isn’t really a good one. English isn’t my native language and due to that I might’ve not expressed myself the way I wanted to. Not only that but I was in a rush.


There are some examples found in the deps folder! They might give you some inspiration. Also it is not that hard to come up with ideas really.

1 Like

Good to hear that! As I said, discord bots have no reason to be constrained in one language!

1 Like

What am I supposed to do here? It’s not working…


No problem! Everyone has his own preferences so I can’t argue on that. I am sure you can do everything with Discordia that discord.js does.

1 Like

That is strange. Try this: I am going to update my thread with the .ZIP files that appear when downloading luvit, not rn tho as I am not on my PC. Probably in a couple of hours. I had another same incident report.

Thank you for your feedback and information given! I feel like updating the tutorial as I made it in a rush. I can also give more and better command examples and explain more stuff related to Discordia, not only that but for some people luvit is not properly installing for them so I should also update the thread with more available download options.


i have a hard time thinking of ideas :frowning:

but thanks anyway, ill check out that deps folder!

@vamik64 Put these on your thread.

Zip File: [File doesn’t exist anymore]

Code for an Auto Rebooting Batch file to Launch:

@echo off
echo Rebooting Bot

You can run a bot with the batch file from a single folder which you can then take around with you and move around your computer. You can also replace PATH-TO-FOLDER\luvit.exe "PATH-TO-FOLDER\LUA-FILE.lua" with luvit FILE.lua if the batch file is in that folder.