Writing a Ban Command - SinisterRectus/Discordia GitHub Wiki
This tutorial is will give you a basic understanding of some frequently used Discordia features, such as Events. Before starting this tutorial, if you haven't already, please do the previous tutorials before starting this one, as they provide essentials that this tutorial does not cover.
Events are a class of emitter. Without going into the nitty-gritty, events are emitted when something happens, such as when a new member joins, someone, sends a message, or when someone adds a reaction. To start listening to those events and their respective arguments, you assign a listener to the said event. A listener is a callback (a function). Then using those listeners, you execute some logic, such as sending a message, or in this case, banning a member.
For this tutorial, we'll be using the messageCreate
event to detect when someone wants to use the command.
To detect this, we'll require the Discordia module and its client class. We assign this class to the variable 'client'. This variable represents the bot on the client-side and allows us to listen to any events from the client-side.
local discordia = require('discordia')
local client = discordia.Client()
Then we'll use the on
method to assign a listener to the messageCreate
event. Doing this will allow us to know when someone sends a message, such as hello
or !ban @member
. We'll also add a check to determine whether the member who sent the message is a bot or not because we do not want bots to interact with our bot!
client:on('messageCreate', function(message) -- Once a message is sent, this function will be executed.
if message.author.bot then return end -- Make sure a bot cannot execute this command.
-- We still need to implement more logic here!
end)
Now that we have our listener set up, we need to detect if the message is a command, so it ignores any other messages such as hello
. We also need to check if the text starts with !ban
. To do this, we perform a variety of checks.
Does the message begin with our prefix? (We'll assume it's !
for this tutorial.)
Is the command ban
?
We do this by using Lua's string
library. In this case, we'll be using string.sub
. string.sub
extracts a piece of the string. In this case, the first four characters to see if it matches our requirements above.
This code is the same as the last, just with our checks added.
client:on('messageCreate', function(message)
if message.author.bot then return end
if message.content:sub(1, 4) == '!ban' then
-- If our message contains our command, we'll execute some logic here.
end
end)
Now that we indeed do know that the user wants to execute the ban command, we need to check several things, such as does the executor have enough permissions? Are there any mentioned members?
client:on('messageCreate', function(message)
if message.author.bot then return end
if message.content:sub(1, 4) == '!ban' then
local author = message.guild:getMember(message.author.id)
local member = message.mentionedUsers.first
if not member then
-- The user have not mentioned any member to be banned
message:reply("Please mention a member to ban!")
return
elseif not author:hasPermission("banMembers") then
-- The user does not have enough permissions
message:reply("You do not have `banMembers` permissions!")
return
end
-- We still have to implement the actual banning logic here
end
end)
Now that we have our checks in place, it's time to do the actual banning. To do this, we'll take our message and check it's content for user mentions. Before every ban we will make sure the user who executed the command have a higher role than the banned member.
--[[
DISCLAIMER: Due to current incorrect handling of message.mentionedUsers
we will be using string patterns to detect mentioned users.
]]
-- Loads some helpful string functions such as string.startswith
discordia.extensions.string()
client:on('messageCreate', function(message)
if message.author.bot then
return -- Ignore messages sent by bots
end
if not message.guild then
return -- Ignore messages not sent in a guild
end
--[[
string.startswith returns true if the first argument startts with the second argument
string.startswith('Hello World!', 'Hello') -> true
]]
if message.content:startswith('!ban ') then
-- Get the member object of the user calling the command
local caller = message.guild:getMember(message.author)
-- Confirm the caller has permissions to ban users before we do anything else
if not caller:hasPermission('banMembers') then
message:reply('You are missing the `banMembers` permission')
return
end
-- Confirm the bot is actually able to ban users
if not message.guild.me:hasPermission('banMembers') then
message:reply('I am missing the `banMembers` permission')
return
end
--[[
Strip the command from the message
string.sub('!ban @user#0000', 6) -> @user#0000
]]
local argument = message.content:sub(6)
--[[
Check if the message contains a mention
Read https://www.lua.org/manual/5.2/manual.html#6.4.1 if you'd like to learn what this pattern does
]]
local id = argument:match('^<@!?(%d+)>$')
if not id then
-- The caller did not mention anyone.
message:reply('Please mention a user to ban')
return
end
-- Confirm the caller mentioned a valid user.
local user = client:getUser(id)
if not user then
message:reply('Please mention a valid user')
return
end
-- Try to get the member object of the mentioned user (if it exists)
local member = message.guild:getMember(user)
if member then
-- Prevent the caller from banning members with a higher role
if caller.highestRole.position < member.highestRole.position then
message:reply('You are unable to ban '..member.mentionString..' as they have a higher role than you')
return
end
-- Confirm the bot is able to ban the mentioned member
if message.guild.me.highestRole.position < member.highestRole.position then
message:reply('I am unable to ban '..member.mentionString..' as they have a higher role than me')
return
end
-- Finally ban the member
member:ban()
else
-- The mentioned user is not a member of the server so no need to check role positions
message.guild:banUser(user)
end
message:reply('Banned '..member.mentionString)
end
end)
Now that setting up is finished, we have to add the run
method to tell the client to start authentication and the bot.
To do this, add this line to the very end of your code.
client:run("Bot BOT_TOKEN")
Make sure to replace BOT_TOKEN
with your actual bot token. Your code should look something like this now:
local discordia = require('discordia')
local client = discordia.Client()
client:on('messageCreate', function(message)
if message.author.bot then return end
if message.content:sub(1, 4) == '!ban' then
local author = message.guild:getMember(message.author.id)
local member = message.mentionedUsers.first
if not member then
-- The user have not mentioned any member to be banned
message:reply("Please mention someone to ban!")
return
elseif not author:hasPermission("banMembers") then
-- The user does not have enough permissions
message:reply("You do not have the `banMembers` permissions!")
return
end
for user in message.mentionedUsers:iter() do
-- Check if mention isn't a reply
if string.find(message.content, "<@[!]?" .. user.id .. ">") then
member = message.guild:getMember(user.id)
if author.highestRole.position > member.highestRole.position then
member:ban()
end
end
end
end
end)
client:run("Bot BOT_TOKEN")
Prev: Writing Your First Bot