[OUTDATED] Discord JS - Slash Commands (2021) [Episode #82]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone alex here from wornoffkeys.com and in this discord.js tutorial we're going to be covering slash commands which is a new feature that discord has recently implemented here i'm inside of a new server and discord has always had these things where you could do a forward slash and there's a number of different commands such as a table flip which would then send this in the chat however as i'm sure you know most bots have some type of prefix where you would send a message such as exclamation point ping or question mark ping or something like that but discord has recently added it so we can add in our own custom commands inside of this right here so within this video i'm going to show you how you can create your own custom commands how you can delete your own custom commands how you can list all of your custom commands as well as how to use the one off keys commands npm package to make this very simple and if you want to skip to a certain section in the video go ahead and use the youtube chapters at the bottom of the video player and you can skip ahead to a certain section that you're interested in and real quick before we continue if you do help with anything throughout this video feel free to join the warnoff keys discord server and ask your questions within the discord js and discord js2 channels and i'm sure someone will be able to help you out so one thing to move forward with is that your bot will have to be invited to your servers with the applications.commandscope and not just the boss scope so just ensure both of these are checked and then here's your new invite url i've now invited my tutorial bot and we're going to go ahead and set up a new project if you already have a project established then you can go ahead and skip to the next section using the youtube player so here i'm within vs code i have an empty project and i'm going to start off by making a new node project by using npm init dash y i'm then going to create a couple new files the first one will be index.js as well as dot env now back to the console i'm going to install some dependencies that we need using npm install discord.js as well as dot env we'll install warnoff keys commands later on in the video for now we're just going to use the basic discord.js and we're going to add in the token into our env file so if your token was abc123 then you would add it into this file like this of course i'll paste in my own token and we also want to make sure that this dot env file is inside of a get ignore so if we create a new file called dot get ignore and within here we just simply say dot env this will now prevent the dot env file from being pushed to github repositories which is important because we do not want our token to be exposed to the outside world so with that said we can now go inside of our index.js file and actually work on our bot so i'm going to start off by just importing discord.js we could say const discord.js equals require discord.js we can also ensure that we have access to all of the things within our env file by requiring dot env which is one thing that we installed and we can call the config method for that we can then create a new client which is essentially an instance of your bot by saying const client equals new discord.js dot client and now we can listen for whenever this client is ready by saying client.on ready whenever this event is fired it will then invoke this callback function here and within here we can just simply say console.log the bot is ready and then now we can actually log into the bot by using client.login and we can pass in the actual token using process dot inv dot token we can then save this and i can try running this using node index.js and now it says the bot is ready and within discord we see it online however with node index.js we'll have to restart the bot every time our source code changes instead i'm going to run this by using nodemon if you don't have access to nodemon you can install it by simply doing npm install g nodemon and then to run it you can just simply type in nodemon now whenever our source code is changed it will automatically restart the bot which is a lot more convenient for us so the first thing we're going to do is list all of the current slash commands registered to that specific guild at the start this will just be an empty array but as we add more commands to it we'll see some of them populated within that array so we first need to make sure that this function is asynchronous and then we can create a constant called commands and set it equal to await client dot api dot applications and then we can pass in client.user.id and now within here we want to specify a guild id so i'm going to go back into discord and i'm going to right click on my guild and then copy the id if you don't see this make sure to enable developer mode on your discord account i can go back and then make a new variable here so const guild id equals this now after our applications we now want to specify a guild there are global commands and there are guild based commands the guild based commands are ideal for testing because they are registered instantly where the global commands will be used for every single guild that your server is in and those will take up to one hour to be visible so when developing it is highly encouraged to use the guild based command and to specify that we're looking to list all of the guild based commands we can now say dot guilds and pass in the guild id afterwards we could say dot commands dot get and so this is going to return all of the commands we can then add in a console log of commands and i can save this and we are now going to get an empty array however as the bot restarts once we add in our own commands to the guild then we're going to see something within that array but for now we will keep this here and underneath we're going to create our very first command which is going to be a very simple ping command where if you type ping in chat it should reply with pong so in order to do this we can say await client dot api dot applications we can then pass in client.user.id and at this stage you might notice we have some repeat code so let's go ahead and improve this so i'll go ahead and create a new function we can say const git app this will be a function that will have one parameter which will be the guild id this will be optional and then within here we can first get access to our app so we can say const app equals client api dot applications we can then pass in client.user.id and then here we can say if guild id actually is a thing we can specify by using app.guilds and pass in guild id then after that we can say return app so going down here we can replace all of this code with git app and passing in the guild id so if i save this we still get our empty array that's fine however moving forward this will be a lot cleaner code rather than writing similar code every single time so now we'll move forward with creating the actual ping pong command to do this we can say await git app and pass in the guild id we can then say dot commands dot post and then here we're gonna pass in an object if you're familiar with apis you know that there are different types of endpoints that you can access using different types of methods one is git which is typically used to retrieve things another one is post which is used to typically create things and so here we're actually retrieving all of the commands and here we are posting to the commands which means that we are creating them and this object is going to contain some information the first property will be data and that will be its own object where we actually describe the command both a name and a description are required so our name can be ping and our description can be a simple ping pong command now i'm going to go ahead and save this in our bot where we start and we're currently listing all of the commands before we actually create this so it's still an empty array in the console however if i save this one more time we are now going to get this object here we have an id that's our command id we have our application id the name description version and guild id and if we go inside of our actual guild and if we do forward slash we now see some other commands that i use for testing as well as our ping command and if i try this nothing currently will happen and it'll actually look like an error in here but only we see this and no one else sees the our actual command so we can go ahead and dismiss this message and then we can go back into our code and now the goal is to listen for whenever the actual interaction occurs and we can do this by using websockets however discord.js clients give us a very simple way to do this we can say client.ws which stands for websockets dot on we can then pass in a string which will be interaction underscore create we can then pass in an asynchronous function callback which will have an interaction as a parameter and within here is where we can handle each individual command's interaction the first thing we can gain access to is the actual command as a string so i can say const command equals interaction dot data dot name dot 2 lower case now within here i'm going to simply console log the command so we can have a full understanding of when this occurs i can save this or bot restarts i could then run xmission point ping and we now see ping in the console however our interaction still fails because we have to actually respond with something so i'm going to dismiss this and going back we can now use a switch statement or a chain of if statements to actually listen for each individual command and then handle those accordingly so we could say if command is exactly equal to ping again this is lowercase because we are using two lowercase right here so within here we can then respond with the actual pong apply and to do this it isn't as simple as just saying message.reply that you might do typically we have to say client.api dot interactions and pass in interaction.id as well as the interaction.token from here we can access the callback and then we can send a post request similar to whenever we are creating a command right here this will actually send a post request back and so this is actually our response and how to handle this specific interaction now as i'm sure you can tell this isn't very intuitive and not the easiest code to work with compared to the rest of discord.js that's because discord.js doesn't natively handle this yet they might do that in version 13 or future versions and so this is what we have to currently do however as i previously mentioned ward off keys commands does a lot of this for you and we'll look at that later on in the video so for now we're going to actually use a post request we can have data and within here the type will be four we can also have it our own data here where the content will be pong and this is the actual reply so if i save this and going back if i type expression point ping when i'll say pong in the chat here and it'll also say that i use slash ping within tutorial so this is our first slash command actually working if we do forward slash you will then see it right there now if i were to run forward slash test nothing's actually going to happen because that's not registered as a real command so that's one thing to keep in mind as well now i'm sure you would imagine that when adding more and more commands this will be very annoying to actually duplicate all this code so we can go ahead and create a reply method which will then automatically use this and reply with whatever the given string is we can say cost reply equals a function here we can then pass in an interaction and then a response within here i'm going to essentially cut this code here and paste it in here we already have access to our interaction correctly however the pong string right here can now be replaced with response now within here we can simply say reply pass in our interaction and then the string pong let's make sure that this works i can save this i could do forward slash ping and we're now going to see pong so that works and moving forward this will be a lot easier for us to actually reply with things now one thing that you'll likely want to do is reply with an embed and how you do that is going to be slightly different than just saying message.apply and passing in an embed we can use something similar to this reply method but we have one additional step as well so i'm going to create a new method here or a new slash command i mean that is going to be creating an embed i can say await git app pass in the guild id dot commands dot post and within this object we're going to have a data object as well with a name being embed and a description being displays and embed and now every single option that's passed in or every single argument is going to be its own field and with that said here's another demonstration of how to use arguments or what's known as options within slash commands we can pass in options which is going to be an array and within here we can have an object with a name for example this could be name as in the user's name and then we can add in a description which is required for every single option this will be your name we can also have required as a boolean in this case i'll say true and then we can have a type which will be three and in the case of options three represents a string so now we can add in a couple more of these we can say name will be age the description will be your age required can be false for this one alternatively you can just not have the required property here type will be 4 which is an integer and now these options will be displayed within the actual interaction create callback but how do we gain access to them well we can destructure them so we can say const options equals interaction.data and of course with this said we can move this line above here and we can also destructure the actual name so here we can just say name.2 lowercase we also have access to options and for now i'm going to just simply console log options so we can actually see what's inside we obviously don't have a handler for embed that's fine so it will act like it doesn't exist however we will still see our console log if i save this i go back i do slash embed we now have a name in this case alex i can then press tab and now at this stage we're kind of typing as nothing if we press tab again we're now focused on the age parameter so that's one thing i'm not 100 sure on if this is intentional or not it's kind of weird that you have to press tab twice to first exit the first parameter and then press it again to go into the next parameter so here we're selected on age and i can enter 27. if i run this this is not going to work of course as i mentioned however we do see this array here with a value and a name we also have the types as well now i find this format not the most user friendly so i'm going to actually change this and put it inside of our own args object so we can say constructs equals an object and then we can say if options because options will be undefined if we don't actually specify anything here for example with a ping command so we want to ensure that options actually exist we can then loop through the options so for const option of options and now we can destructure the name and the value so cost name and value equals option we can then say args index of name equals value and now after all of this i'm going to console.log args i can now save this and i can do embed alex and 27. if i run this we now have this object here which might be more user friendly for you to use depending on your use case of course you will have access to both of these at this stage so it's up to you which one you prefer i can dismiss this and going back we can now add in a handler so i can say else if command is exactly equal to embed and then here we can actually create our embed so i can say const embed equals new message embed dot set title we'll call this example embed of course add in whatever title you want and then here i'm wanting to loop through all of the arguments and add in a field for each one so i could say four const arg in args this will give us access to each individual key we can then say const value equals args index of arg and then we can say embed dot add field the first argument is going to be the actual name of the field so this will be arg and the second argument is going to be value we now want to be able to actually send this embed however if we just do reply interaction embed this won't actually work so if i save this and i go back and i do slash embed we can say alex and then 27 we now get an exception scrolling up it's going to say invalid form body because we cannot just directly send an embed here it's going to say data.content could not interpret this actual json string here and so we need to actually create our own api message to send this correctly and if you've had to work with the direct api in ways like this before you may have had to do this before so a common way to do this is const create api message this is going to be an asynchronous function that has two parameters the first one will be an interaction the second one will be the actual content in this case it'll be embed now within here we're going to say const and we're going to these structures and pieces information that'll be from await which is why this function is asynchronous we can now say api message dot create and within here we have to pass in an actual channel and we can do that by getting access to the channel id from the interaction so we can say client dot channels dot resolve we can then pass an interaction dot channel underscore id the second argument will be the actual content which in this case is just our parameter and then we have to resolve the data and resolve the files this will give us access to the actual embed as well as any other files that this method might use in the future so we can say dot resolve data and dot resolve files now we have access to data and files which is what we want to actually destructure so we have data and files and now we're wanting to return an object and this object is going to contain the actual properties of the data object itself so we can spread that object into here and then we can also just have our own files property which will contain the files object so now what we can do is within our reply we can actually change the response to be an api message from the create api message method that is then going to actually return the embed so one thing wants to change is how this data object is structured we can say let data equals an object where content equals response which is the exact same thing right here so i can now remove this because this was in reference itself and so this is basically the same exact code however if type of response is exactly equal to object which means that this is an embed i can add in a comment here check for embeds we could then say data equals await which means that this function needs to be asynchronous so await create api message we can then pass in the interaction and the response which is the embed so this will actually return this object here which will then contain all the necessary information for us to respond using this code right here so if it's a normal string everything will act the same way however if it's an embed where they're going to change the data should be the correct response so i can save this the bot will restart i can then do forward slash ping to make sure that this still works and it does i can then do embed the name will be alex the age will be 27 and we actually get an example in bed with the name being alex and the age being 27. so now the reply method is the only thing we need to do in order to respond with an embed or a string which is very convenient for us moving forward so we've talked about how to list the commands how to create the commands but let's say we want to actually delete the embed command so i'm going to comment out this section of code here and when i save this we're still going to have it created here here we have the command id as well as the guild id which we also have defined in our code of course right up here so we have git and post and if you're familiar with apis we also have a delete method so i'm going to go ahead and delete the embed command i can do this with a wait git app passing in the guild id dot commands and then here i can pass in the actual command id so i can copy this and then i can say dot delete so i will save this our bot will restart we still see it here because this is going to console log this before we actually delete it however if i comment this out save it we are now only going to see one command and if i go back to the discord server and do slash embed we don't actually see it here now if you're using global commands which basically means that the guild id in this exact code doesn't exist then it might take up to an hour to see this change but if you're using guild based commands like we are here not only will the change only be visible within this specific guild but it also is instant which like i previously mentioned is ideal for development now i'm going to go over how the one off keys commands package makes this a lot simpler where you don't have to go through and check every single command individually and how if you're already using the one off keys package it does a lot of the heavy lifting for you so you can simply change a few properties and it will automatically create slash commands from your existing commands so i'm going to go ahead and comment out most of this code our git app all the way down to our login will be commented out so right here we're just logging in and above we're doing our standard imports and creating our clients and defining our guild id from here we can go into the console and we can install one off keys commands using npm install wok commands go ahead and run that we can then use nodemon to run our bot again and now within here we're looking to import one of key's commands so const wok commands equals require worn off keys commands we can then listen for whenever the bot is ready with client.on ready and within this callback we can now create a new instance of one off keys commands new wlk commands we can pass in the client and then an object here we're just going to specify the different directories and other options that we have for example we can say commands dir and this will just be commands which is a folder that we then have to create as we did right here we also want to pass in an array of strings for the different test server ids this is very important because when one of keys commands notices that you want a slash command and you don't specify a test server it will create a global command which as previously mentioned might take up to an hour to be displayed so we can say test servers as an array and we can just simply pass in the guild id so whenever we specify a command as a test only command it will then look to this array to know which guilds to actually register that command in so we can go ahead and save this and we get a couple warnings which we can simply ignore by just saying show warns is false some of these should not be here and depending on when you're watching this video those may or may not be there so show warns is false and now we have less warnings so that's good to go so now we're going to create the simple ping pong command i can then say ping.js has a new file name and we can say module.exports is an object we can specify slash is true we can specify test only is true and this will make it so this command will only be registered in guilds that are specified within the test servers array so going back into our file we can now add in a description which is required for all slash commands this would be a simple ping pong command now if we go back into the discord and i do forward slash ping we see the same exact description so to make sure that this is going to be a different we can add an exclamation point so at the end we can just add in a couple exclamation points so it's very clearly different we can add in a callback and if you're used to one off keys commands the actual properties within this object are slightly different the message and prefix will not exist and there is a new channel property which you will then have access to as well for normal commands and slash commands however we don't need access to any of those here so we'll just basically have an object there and a difference within slash commands is that we have to now return the actual information so whether that be a string or an embed we don't have to return that so we can now say return pong and i'm also going to add in a couple exclamation points so this is obviously different from the previous pawn command i can then save this we now see one of keys commands loaded with one command and going back into discord i can do four slash ping and select the one with a bunch of exclamation points and it now says pong so one of keys commands does a lot of heavy lifting for you and you just have to specify a few certain things here and also a slightly different system when it comes to the actual contents but what happens if you're wanting to transition into slash commands but not just have a complete switch all at once we can actually specify the string both in all lower case here and this will register as a slash command and a normal command so within our callback let's say we have access to a message and again message will be undefined if this is ran as a slash command so we can't say if message to ensure it actually exists we're going to say message.reply pong i can then save this and going back into the discord server i can run forward slash ping and it says pong and now i can run x mission point ping and it also replies as pawn so this is now used as both a slash command and a normal command now what happens if i want to reply with an embed well it's simple you just create the embed and then return it so for example i can say const embed equals new message embed dot set title example dot set description pong and then here we can reply with the embed and then also we can return the embed so i can save this i can go into discord forward slash ping is now going to respond with the actual embed and we don't have to go through and create the api message or anything like that one of keys commands will do that for us then also exclamation point ping will now reply with the same exact embed so the last thing i wanted to show you is how arguments are used so let's say hypothetically we're wanting to pass in the name and age of the user into this ping command doesn't make too much sense but it's just a basic example so we can say minimum arguments is two and expected args will now be a string where the first one is name the second one is age keep in mind that the minimum number of arguments will tell one of key's commands how many of these arguments you want to be required if i were to and then add in a country this would then be an optional argument because the minimum argus is 2 which would encompass these two right here and so i may want to specify the actual square brackets here instead of the arrow brackets in order to specify this command here now this syntax isn't exactly required you could use the less than and greater than sign however having it like this makes it more clear what is optional so we have access to args which is just like the normal commands it's an array we also have access to text if we want that which is all of them joined together but for now we just need access to args and we're going to go ahead and add in the name and the age and the country to this embed so i can now destructure these so const name age country equals args and then i can say embed.add field name is name i can then copy this a couple times i can then add in the age and then i can add in the country which would then be country or none because again this is optional and so this is a fallback string so now i can save this going back into discord forward slash ping when i hover over the one with x mission points we now see the different arguments clicking on this we're wanting our name which is alex or age27 and then if i press tab again here we have the country which is the usa if i run this now we see the actual things within the embed we also see pong here which was the description previously and so this is how you're going to handle the arguments it's very similar to how you previously would it's going to interpret all of these as three different arguments and then also understand which ones are required based off the minimum number of arguments so the goal i had for this system was to make it so you had to change as little things as possible in order to implement slash commands into your bot now a final note is that this system was just published to one of key's commands and there could be changes in the future obviously i can't update this video once it's actually live but i can update the pinned comment so please check the pin comment for any updates possibly a new video or any mention of breaking changes to the system thanks for watching this discord discord.js tutorial if you want to learn more about discord.js consider clicking on the playlist you see on your screen now if you need help feel free to leave a comment or ask in the worn off keys discord which can be found in the video description
Info
Channel: Worn Off Keys
Views: 49,645
Rating: undefined out of 5
Keywords: slash commands, discord bot, creating a discord bot, v12, worn off keys
Id: -YxuSSG_O6g
Channel Id: undefined
Length: 31min 3sec (1863 seconds)
Published: Sat Mar 06 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.