57 |
58 | - ErelaClient was renamed to Manager
59 | - You no longer need to pass the client
60 | - Most of the node options can be omitted
61 | - You no longer need to provide a node if you're using completely default lavalink options
62 | - You ***need*** provide a `send` function to send voice data to Discord
63 |
64 | ## Player
65 |
66 | ## Creating players
67 |
68 | Before you had to get the PlayerStore and use the `spawn` method to create a Player, now PlayerStore was removed as it's completely useless and bloated the package.
69 |
70 | You can still create players using a similar method named `create` like so:
71 |
72 | ```javascript
73 | const player = manager.create(options);
74 | ```
75 |
76 | Or directly off the Player class:
77 |
78 | ```javascript
79 | const player = new Player(options);
80 | ```
81 |
82 | In both these examples the [`options`](/docs/typedefs/ManagerOptions.html) is same as before.
83 |
84 | ## Destroying players
85 |
86 | In v1 you had to destroy players using the PlayerStore `destroy` method, now you use it off of the Manager class or directly on the Player class.
87 |
88 | ```javascript
89 | const player = manager.get("guildId")
90 |
91 | manager.destroy("guildId");
92 |
93 | // Or
94 |
95 | player.destroy();
96 | ```
97 |
98 | ## Setting equalizer
99 |
100 | Before v2 you had to provide an array of objects to set the equalizer, now you just have to put each object on their own.
101 | If your band objects are in an array you can use the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) to *spread* the objects out.
102 |
103 | ```javascript
104 | // Before
105 | player.setEQ([{ band: 0, gain: .25}, { band: 2, gain: .25}])
106 |
107 | // After
108 | player.setEQ({ band: 0, gain: .25}, { band: 1, gain: .25})
109 | ```
110 |
111 | ## Connecting to voice
112 |
113 | Before Erela.js would automatically connect to the voice channel. Now you must use the Player#connect() method.
114 |
115 | ```javascript
116 | const player = new Player(options);
117 | player.connect();
118 | ```
119 |
120 | ## Queue
121 |
122 | The Queue class had some changed regarding the current song, before it was the first element in the array but was changed to the `current` property.
123 |
124 | ## Utils
125 |
126 | The utils was removed as it bloated the package and didn't offer as much flexibility. There are some packages below to parse and format times.
127 |
128 | ## Format time
129 |
130 | - [https://www.npmjs.com/package/humanize-duration](https://www.npmjs.com/package/humanize-duration)
131 |
132 | ## Parse time
133 |
134 | - [https://www.npmjs.com/package/timestring](https://www.npmjs.com/package/timestring)
135 |
--------------------------------------------------------------------------------
/guide/topics/erelajs/basics.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Basics
3 | displayHeaders: true
4 | sidebarDepth: 1
5 | ---
6 |
7 | ## Installation
8 |
9 | ::: tip
10 | This guide assumes you already have knowledge about JavaScript and a Discord API library installed, for this guide Discord.JS will be used.
11 | :::
12 |
13 | To start using Erela.js you first have to install it using NPM or Yarn.
14 |
15 | :::: tabs type:border-card stretch:true
16 |
17 | ::: tab NPM
18 | ```bash
19 | npm install erela.js
20 | ```
21 | :::
22 |
23 | ::: tab Yarn
24 | ```bash
25 | yarn add erela.js
26 | ```
27 | :::
28 | ::::
29 |
30 | ## First start
31 |
32 | The first place to start with Erela.js is the Manager class with some [options](/docs/typedefs/ManagerOptions.html).
33 |
34 | ```javascript
35 | // Require both libraries
36 | const { Client } = require("discord.js");
37 | const { Manager } = require("erela.js");
38 |
39 | // Initiate both main classes
40 | const client = new Client();
41 |
42 | // Define some options for the node
43 | const nodes = [
44 | {
45 | host: "localhost",
46 | password: "youshallnotpass",
47 | port: 2333,
48 | }
49 | ];
50 |
51 | // Assign Manager to the client variable
52 | client.manager = new Manager({
53 | // The nodes to connect to, optional if using default lavalink options
54 | nodes,
55 | // Method to send voice data to Discord
56 | send: (id, payload) => {
57 | const guild = client.guilds.cache.get(id);
58 | // NOTE: FOR ERIS YOU NEED JSON.stringify() THE PAYLOAD
59 | if (guild) guild.shard.send(payload);
60 | }
61 | });
62 |
63 | // Emitted whenever a node connects
64 | client.manager.on("nodeConnect", node => {
65 | console.log(`Node "${node.options.identifier}" connected.`)
66 | })
67 |
68 | // Emitted whenever a node encountered an error
69 | client.manager.on("nodeError", (node, error) => {
70 | console.log(`Node "${node.options.identifier}" encountered an error: ${error.message}.`)
71 | })
72 |
73 | // Listen for when the client becomes ready
74 | client.once("ready", () => {
75 | // Initiates the manager and connects to all the nodes
76 | client.manager.init(client.user.id);
77 | console.log(`Logged in as ${client.user.tag}`);
78 | });
79 |
80 | // THIS IS REQUIRED. Send raw events to Erela.js
81 | client.on("raw", d => client.manager.updateVoiceState(d));
82 |
83 | // Finally login at the END of your code
84 | client.login("your bot token here");
85 | ```
86 |
87 | ## The play command
88 |
89 | The whole idea of a music bot is to play music right? So let's write a command to play songs.
90 |
91 | First you want to listen to the message event.
92 |
93 | ```javascript
94 | // Add the previous code block to this
95 |
96 | client.on("message", async message => {
97 | // Some checks to see if it's a valid message
98 | if (!message.content.startsWith("!") || !message.guild || message.author.bot) return;
99 |
100 | // Get the command name and arguments
101 | const [command, ...args] = message.content.slice(1).split(/\s+/g);
102 |
103 | // Check if it's the play command
104 | if (command === "play") {
105 | if (!message.member.voice.channel) return message.reply("you need to join a voice channel.");
106 | if (!args.length) return message.reply("you need to give me a URL or a search term.");
107 |
108 | const search = args.join(" ");
109 | let res;
110 |
111 | try {
112 | // Search for tracks using a query or url, using a query searches youtube automatically and the track requester object
113 | res = await client.manager.search(search, message.author);
114 | // Check the load type as this command is not that advanced for basics
115 | if (res.loadType === "LOAD_FAILED") throw res.exception;
116 | else if (res.loadType === "PLAYLIST_LOADED") throw { message: "Playlists are not supported with this command." };
117 | } catch (err) {
118 | return message.reply(`there was an error while searching: ${err.message}`);
119 | }
120 |
121 | if (res.loadType === "NO_MATCHES") return message.reply("there was no tracks found with that query.");
122 |
123 | // Create the player
124 | const player = client.manager.create({
125 | guild: message.guild.id,
126 | voiceChannel: message.member.voice.channel.id,
127 | textChannel: message.channel.id,
128 | });
129 |
130 | // Connect to the voice channel and add the track to the queue
131 | player.connect();
132 | player.queue.add(res.tracks[0]);
133 |
134 | // Checks if the client should play the track if it's the first one added
135 | if (!player.playing && !player.paused && !player.queue.size) player.play()
136 |
137 | return message.reply(`enqueuing ${res.tracks[0].title}.`);
138 | }
139 | });
140 | ```
141 |
142 | ## Events
143 |
144 | You can play songs but what about knowing when a song starts or end? Those are events that the Manager class emits.
145 |
146 | ```javascript
147 | client.manager = new Manager(/* options above */)
148 | // Chain it off of the Manager instance
149 | // Emitted when a node connects
150 | .on("nodeConnect", node => console.log(`Node "${node.options.identifier}" connected.`));
151 |
152 | // Or each listener on their own
153 | // Emitted when a track starts
154 | client.manager.on("trackStart", (player, track) => {
155 | const channel = client.channels.cache.get(player.textChannel);
156 | // Send a message when the track starts playing with the track name and the requester's Discord tag, e.g. username#discriminator
157 | channel.send(`Now playing: \`${track.title}\`, requested by \`${track.requester.tag}\`.`);
158 | });
159 |
160 | // Emitted the player queue ends
161 | client.manager.on("queueEnd", player => {
162 | const channel = client.channels.cache.get(player.textChannel);
163 | channel.send("Queue has ended.");
164 | player.destroy();
165 | });
166 | ```
167 |
--------------------------------------------------------------------------------
/guide/topics/discordjs/gettingStarted.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Getting Started
3 | ---
4 |
5 | ## Creating a bot
6 |
7 | Before you start programming a Discord bot you need to create a bot application first. If you would like to visually see this you can follow the video down below, but if you prefer reading you can look below for a quick and easy guide on making your bot.
8 |
9 |
11 |
18 |
19 |
20 | TODO: show how to make a bot account
21 |
22 | ## Project setup
23 |
24 | Now that you have your bot application you need to program and run it.
25 |
26 | First you will need to download and install [Node.JS](https://nodejs.org/en/download/). You might notice two different versions, LTS and Current. LTS means Long Term Support, it'll be supported for as long as the developers can. Current is the most stable version. There is also nightly builds which are previews of whats to come, these shouldn't be used as there's no guarantee it will function normally.
27 |
28 | Secondly you will need either a code editor or a IDE to edit the code. You can find some editors and IDEs [here](/topics/discordjs/#editors-and-ides). Some might require a add-on for syntax or linting support with JavaScript, if it does not it should prompt you to add it or you can search how to add it. Personally I use Visual Studio Code Insiders and **_will be throughout this guide_** but you're free to use any you like.
29 |
30 | Once you have both installed you can start setting up the project files by creating a new folder or use a existing one for the bot files to reside, you can name it anything you like. Next is to open the folder in your editor, usually this can be done by right-clicking the folder and selecting `Open with ` or clicking `File` at the top left in the editor and selecting `Open Folder`.
31 |
32 | After you have the editor open it's time to do the first step for any Node.JS project, creating a `package.json` and installing Node modules through the command line. If your editor has a integrated terminal you can open that, it does not or you prefer to use your OS terminal then you can open that. For Windows you can open the folder and click the path URL and write `cmd` and hit enter to open a Command Prompt. For Linux you usually can open the terminal from a dropdown button in the folder or right click in the empty space (TODO: improve this).
33 |
34 | Once you have a terminal open you can run your first command.
35 |
36 | ```shell
37 | npm init
38 | ```
39 |
40 | What is `npm` though? NPM is **N**ode.JS **P**ackage **M**anager that you can use to manage your projects packages or "dependencies" as it's called when your project "depends" on another. Here we are using the main command `npm` with a sub-command `init` which will run through a few questions and create a `package.json` file once complete. This file will store some basic information and dependencies. When you get a question it will look like `package name: (discordjs-tutorial)`, for some it will show parentheses and some content inside them, that is the default answer if you do not give one. Some wont have parentheses such as `description:` because it does not have a default answer, it's optional and can be left blank. You can edit any of this in the `package.json` later on.
41 |
42 | If you are curious about the other sub-commands you can look at [NPM's command line documentation](https://docs.npmjs.com/cli-documentation/cli) but we will only cover a few throughout this guide.
43 |
44 | After that process is finished you can now install a package.
45 |
46 | ```shell
47 | npm install discord.js
48 | ```
49 |
50 | As said before we are using the main command `npm` with a sub-command `install` and a package to install which is `discord.js`. You'll see the terminal fly through some lines and a new folder called `node_modules`, this is where your dependencies are stored to be used in your code.
51 |
52 | Next you can create a file named `index.js`, it must end in `.js` for two reasons, one for your editor to properly highlight the syntax, and two for Node.JS to know it's a JavaScript file.
53 |
54 | Congratulations, you've completed the first steps to making a Discord bot!
55 |
56 | ## Writing your first program
57 |
58 | Now that you have your project setup you can start coding. By being at this section you know at least the basics of [JavaScript and Node.JS](/topics/discordjs/#javascript-and-node-js), if not then I highly suggest you follow that hyperlink and read one of those resources. In this beginning part of this guide I will be explaining all the code I provide.
59 |
60 | Copy and paste this into your editor.
61 |
62 | ```javascript
63 | const { Client } = require("discord.js");
64 |
65 | const client = new Client();
66 |
67 | client.once("ready", () => console.log("I am ready!"));
68 |
69 | client.login("token");
70 | ```
71 |
72 | Replace `token` with your bot token found in the Discord Applications page when you created your bot and save the file. Next in your open terminal run this command.
73 |
74 | ```shell
75 | node index.js
76 | ```
77 |
78 | You should see the terminal show `I am ready!`. Congratulations, you just programmed your first Discord bot. But what does all of that do and what command is `node`?
79 |
80 | First I'll explain what the `node` command is. Every application on your computer has a main command, for Node.JS it's `node`, running this command with a JavaScript file will execute the code inside of it. If you do not like typing the command every time you can do two things, one is use `node .` which will use the `entry point` set in the `package.json`, by default it is `index.js`, if you named your file something else or it is in a sub directory you can rename that value accordingly. The other thing you can do is press the up arrow on your keyboard, this usually scrolls through the terminal history, you can use it to quickly get the command back and run it. There are other options like using `nodemon` to restart your program every time a file is saved but we'll get to that later on.
81 |
82 | Now what does all of that code do? If you know the basics of [JavaScript and Node.JS](/topics/discordjs/#javascript-and-node-js) you should understand some, if not most of it.
83 |
84 | The first line requires the `discord.js` module and assigns the deconstructed value `Client` by its name as a constant. `require` is only available in Node.JS and it can import files, [directories](https://stackoverflow.com/a/5365577/13257043) or modules. A constant is a variable that cannot be re-declared and must have a value assigned to it. Deconstructing is taking a value by name from a object and using it by itself, an is example below.
85 |
86 | ```javascript
87 | // Define a constant with a object as the value that has it's own property and value.
88 | const foo = { bar: "bar" };
89 |
90 | // Extract the foo variable and define it as its own.
91 | const { bar } = foo;
92 |
93 | // Print the variable to the terminal without doing "console.log(foo.bar)".
94 | console.log(bar) // bar
95 | ```
96 |
97 | I know that was big explanation so let's move to the second line. There you initiate the `Client` class and assign it to the `client` variable as a constant.
98 |
99 | The third line is a bit special, since you have to know when the bot is ready you need an event listener, thats what this line does. The `Client` class extends `EventEmitter` and lets you listen to events using `on` and `once` methods. Here we listen to the `ready` event which is sent every time your bot becomes ready, but since we don't want our terminal being spammed with messages so we'll use `once` so it only runs `once`. The second parameter is an inline [arrow function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) that prints a message to the console letting us know the bot is ready.
100 |
101 | The last line is a method that logins into the Discord WebSocket with your bot token to receive events and to make HTTP requests for sending message, adding roles, etc.
102 |
103 | Now that you understand what that snippet of code we can dive into more.
104 |
--------------------------------------------------------------------------------
/guide/topics/discordjs/firstCommand.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Creating your first command
3 | authors:
4 | - NorteX-dev
5 | - MenuDocs
6 | tags:
7 | - Discord.js
8 | - Bot Developement
9 | - Basics
10 | ---
11 |
12 | Disclaimer: this tutorial assumes you've followed the [Getting Started](gettingStarted.md) tutorial. It also uses the `stable` branch of Discord.js, so double check if you are using it, or anything older.
13 |
14 | ## Setup
15 | In the previous tutorial ([Getting Started](gettingStarted.md)) you learned how to install Node with npm, your programming environment (IDE) and initialized the project.
16 |
17 | Just to remind us, this is the code we had set up in the end:
18 | ```javascript
19 | // Import the "[Client](https://discord.js.org/#/docs/main/stable/class/Client)" class from discord.js library
20 | const { Client } = require("discord.js");
21 | // Initialize the client and assign it to a constant variable "client"
22 | const client = new Client();
23 | // Listen to the "ready" event and print "I am ready!" whenever the bot is ready.
24 | client.once("ready", () => console.log("I am ready!"));
25 | // Authenticate the bot with your token from the Discord Developer Page
26 | client.login("-- Your Token --");
27 | ```
28 | This code tells the bot to listen to the "ready" event and print "I am ready!" whenever the bot is connected to the Discord API.
29 |
30 | Now, that we are up to date with the previous tutorial, we can start writing more code.
31 |
32 | ## Creating the event
33 | First off, you have to understand that commands are in fact just messages with a specific prefix.
34 | That being said, to create commands for your bot, you'll have to listen to the `message` event.
35 |
36 | Listening to the `message` event is very similar to listening to the `ready` event and is as follows:
37 | ```javascript
38 | client.on("message", (message) => {
39 | console.log("Hello!");
40 | });
41 | ```
42 | Let's break this code down. As with the `ready` event, we are accessing the `client` variable. Then, we are using `.on()` which is a method that creates an _event listener_ on our Discord bot client. Events are the Node.js way of launching code when a certain thing happens, for example in our case, the bot connects to the Discord API or a message gets sent. You can read more about events in the [Node.js Events Documentation](https://nodejs.org/api/events.html).
43 |
44 | But wait! We can notice, that in the `ready` event, the method is `.once`, not `.on`!
45 |
46 | The difference between these two, is `once` - as the name suggests - only invokes once per execution and cannot be run again. `on` on the other hand can execute however many times the event happens. For our `message` event, we want to use the `on` method, as the command is sent more than one time - unlike `ready`, which should only execute once.
47 |
48 | Now with the `once` and `on` difference out of the way, we can look at the arguments - for both methods, it will always be two:
49 | - Event name
50 | - A callback function
51 |
52 | The event name is obviously the name of the event that we want to listen to. There are many events, e.g. these which we have learnt already: `ready` and `message`, but also `guildCreate`, `guildMemberAdd`, `messageDelete`, `roleCreate` and many, many more. You can see all of them in this handy [Discord events cheatsheet by koad](https://gist.github.com/koad/316b265a91d933fd1b62dddfcc3ff584).
53 |
54 | The second parameter is a callback. This will be executed once the event is triggered. Oftentimes, it takes in parameters specific for that type of event. Our `message` event, only returns 1 parameter: a message object which we will be able to utilize later in the guide.
55 |
56 | You can place the event anywhere between the client initialization and the logging in of the client. The best place for it, would be after the `ready` event to keep the code understandable and clean.
57 |
58 | ## Responding to the message
59 | If you set up the code correctly, now, when the code is being run, and a message on any server with your bot is sent, a log should appear in our console.
60 |
61 | Next up, we will discuss how we can use the `message` object returned from the event to send a response in the channel that the message has been sent.
62 |
63 | `message` object has the following properties in it:
64 | - author - returns the [User](https://discord.js.org/#/docs/main/stable/class/User) that has sent the message.
65 | - channel - returns the [TextChannel](https://discord.js.org/#/docs/main/stable/class/TextChannel) that the message has been sent in.
66 | - content - returns the content of the message
67 | - guild - returns the [Guild](https://discord.js.org/#/docs/main/stable/class/Guild) (server) of where the message was sent in
68 | - id - returns the ID of the message - this is especially useful when saving a reference to the message
69 |
70 | And a few functions, too:
71 | - delete() - deletes the message
72 | - pin() - pins the message to the channel
73 | - react(emoji) - reacts to the message with an emoji object
74 |
75 | There are many more properties in the `message` class, however these are the most used ones. If you'd like to get to know each one of them, you can view it here: [Message Class on discord.js.org](https://discord.js.org/#/docs/main/stable/class/Message)
76 |
77 | Having these in mind, we can construct the following code:
78 | ```javascript
79 | client.on("message", (message) => {
80 | if(message.author.bot) return;
81 | if(!message.guild) return;
82 |
83 | message.channel.send(`Hello, ${message.author.username}!`);
84 | });
85 | ```
86 |
87 | To make sure that the bot will not fall in a loop responding to it's own messages, we have to add two `if` statements. First one is to check if the author is a bot. If so, `return` - stop - the code. That is to prevent any bots, including the one we are making, from (self-)firing commands. The second check (on line 3) sees if the guild is present in the message object, as we don't want to listen to DM messages. Now, that we are sure that the bot will not fall into a loop and that guild is present on the object, we can move on. In the first bit of the last line, we are looking at `message` and then accessing the `channel` property of it. That returns the channel that the message was sent in. Channels have a method [`.send(content)`](https://discord.js.org/#/docs/main/stable/class/TextChannel?scrollTo=send) that sends a message to them - and it requires a parameter of what the content of that message should be.
88 |
89 | With this code, we can `send` a message in `channel` that the original `message` was sent. Inside the `.send()` function, we can find a template string - indicated with backticks as opposed to the normal quotes. This allowes us to embed some code in the message: `${message.author.username}`. Here, again, we are looking at `message`, but this time not the `channel`, but instead the `author` of that message. That returns a user that sent that message. Then, we are getting the username from it. Easy!
90 |
91 | With this, the bot should respond "Hello, [username]!", for example "Hello, NorteX!" if it sees any message on any channel.
92 |
93 | ## Making a command
94 | In the first sentence of creating the event, I said that all commands are prefixed messages. So, let's try and make a very simple command handler.
95 | ```javascript
96 | client.on("message", (message) => {
97 | if(message.author.bot) return;
98 | if(!message.guild) return;
99 |
100 | // What do we split on?
101 | // We split on spaces. The text inside the slashes indicates it's a RegExp.
102 | // A RegExp is a way to match values in a string.
103 | // How this RegExp works, is that we match on " " (space).
104 | // Then the `+` indicates that we wish to match as many spaces in a row as possible.
105 | // That way the amount of spaces between your args doesn't matter.
106 |
107 | const [command, ...args] = message.content.split(/ +/g);
108 | });
109 | ```
110 |
111 | Before going any further, let's quickly discuss this code. Again, we are listening to the `message` event, nothing different here. In the next line, we are creating a variable named `split` which is assigned to the message content *split with spaces*.
112 |
113 | Take this example for example:
114 |
115 | The message content is: "!ban user reason", a very simple ban command.
116 |
117 | So, in the code above, we're declaring 2 variables - command and args - from message.content.split(" ") via a "destructuring assignment". Each variable represents an index in the array. So const command = `message.content.split(" ")[0];` is the same as the command variable, and the args variable will be filled with the rest - meaning, it would equal to something like `message.content.split(" ").slice(1)`.
118 |
119 | For more information on destructuring assignment, check out the [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment).
120 |
121 | Ok. Now, for example `user` or `reason` in our command are going to be stored in the `args` array, so we can access it later.
122 |
123 | Ok, moving on with the code!
124 | ```javascript
125 | client.on("message", (message) => {
126 | if(message.author.bot) return;
127 | if(!message.guild) return;
128 |
129 | const [command, ...args] = message.content.split(/ +/g);
130 |
131 | if(command.toLowerCase() === "!ping") {
132 | message.channel.send("Pong!");
133 | }
134 | });
135 | ```
136 |
137 | Now, a very straightforward `if` statement checks if the `command` string is equal to `!ping`. We make this comparison before sending the response to ensure the right command is ran. We also force it to lowercase to allow running commands without worrying about case sensitivity.
138 |
139 | ## Conclusion
140 |
141 | This is the basics of how you can make your own commands. You can of course add much more code to your command. Be creative!
142 |
143 | This is the final code that we made to add our simple "ping" command and set up code for further commands:
144 |
145 | ```javascript
146 | const { Client } = require("discord.js");
147 |
148 | const client = new Client();
149 |
150 | client.once("ready", () => console.log("I am ready!"));
151 | client.on("message", (message) => {
152 | if(message.author.bot) return;
153 | if(!message.guild) return;
154 |
155 | const [command, ...args] = message.content.split(/ +/g);
156 |
157 | if(command.toLowerCase() === "!ping") {
158 | message.channel.send("Pong!");
159 | }
160 | });
161 |
162 | client.login("-- Your Token --");
163 | ```
164 |
--------------------------------------------------------------------------------