Allow classic commands in DMs even when disabled, add channel name to music end message, better check for API_TYPE, update docs
This commit is contained in:
		
							parent
							
								
									50bff306c0
								
							
						
					
					
						commit
						e474d838b0
					
				
					 11 changed files with 94 additions and 35 deletions
				
			
		
							
								
								
									
										8
									
								
								app.js
									
										
									
									
									
								
							
							
						
						
									
										8
									
								
								app.js
									
										
									
									
									
								
							| 
						 | 
					@ -71,12 +71,14 @@ const services = [
 | 
				
			||||||
if (process.env.METRICS && process.env.METRICS !== "") services.push({ name: "prometheus", ServiceWorker: PrometheusWorker });
 | 
					if (process.env.METRICS && process.env.METRICS !== "") services.push({ name: "prometheus", ServiceWorker: PrometheusWorker });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const intents = [
 | 
					const intents = [
 | 
				
			||||||
  "guilds",
 | 
					 | 
				
			||||||
  "guildVoiceStates",
 | 
					  "guildVoiceStates",
 | 
				
			||||||
  "guildMessages",
 | 
					 | 
				
			||||||
  "directMessages"
 | 
					  "directMessages"
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
if (types.classic) intents.push("messageContent");
 | 
					if (types.classic) {
 | 
				
			||||||
 | 
					  intents.push("guilds");
 | 
				
			||||||
 | 
					  intents.push("guildMessages");
 | 
				
			||||||
 | 
					  intents.push("messageContent");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Admiral = new Fleet({
 | 
					const Admiral = new Fleet({
 | 
				
			||||||
  BotWorker: Shard,
 | 
					  BotWorker: Shard,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,7 @@ class StopCommand extends MusicCommand {
 | 
				
			||||||
    players.delete(this.channel.guild.id);
 | 
					    players.delete(this.channel.guild.id);
 | 
				
			||||||
    queues.delete(this.channel.guild.id);
 | 
					    queues.delete(this.channel.guild.id);
 | 
				
			||||||
    this.success = true;
 | 
					    this.success = true;
 | 
				
			||||||
    return "🔊 The current voice channel session has ended.";
 | 
					    return `🔊 The voice channel session in \`${this.connection.voiceChannel.name}\` has ended.`;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static description = "Stops the music";
 | 
					  static description = "Stops the music";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,18 @@
 | 
				
			||||||
# Config
 | 
					# Config
 | 
				
			||||||
esmBot uses environment variables for configuration. To make managing them easier, a `.env` file is included with the bot and can be used to load the variables on bot startup.
 | 
					esmBot uses a mix of environment variables and JSON for configuration.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Here's an overview of the environment variables required to run the bot:
 | 
					## Environment Variables (.env)
 | 
				
			||||||
 | 
					To make managing environment variables easier, an example `.env` file is included with the bot at `.env.example` and can be used to load the variables on startup.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Required
 | 
				
			||||||
- `NODE_ENV`: Used for tuning the bot to different environments. If you don't know what to set it to, leave it as is.
 | 
					- `NODE_ENV`: Used for tuning the bot to different environments. If you don't know what to set it to, leave it as is.
 | 
				
			||||||
- `TOKEN`: Your bot's token. You can find this [here](https://discord.com/developers/applications) under your application's Bot tab.
 | 
					- `TOKEN`: Your bot's token. You can find this [here](https://discord.com/developers/applications) under your application's Bot tab.
 | 
				
			||||||
- `DB`: The database connection string. By default the `sqlite` and `postgresql` protocols are available, but this can be expanded by putting proper DB driver scripts into `utils/database/`. You can also set this to `dummy` to make the bot not use a database at all.
 | 
					- `DB`: The database connection string. By default the `sqlite` and `postgresql` protocols are available, but this can be expanded by putting proper DB driver scripts into `utils/database/`. You can also set this to `dummy` to make the bot not use a database at all.
 | 
				
			||||||
- `OWNER`: Your Discord user ID. This is used for granting yourself access to certain management commands. Adding multiple users is supported by separating the IDs with a comma; however, this is not recommended for security purposes.
 | 
					- `OWNER`: Your Discord user ID. This is used for granting yourself access to certain management commands. Adding multiple users is supported by separating the IDs with a comma; however, this is not recommended for security purposes.
 | 
				
			||||||
- `PREFIX`: The bot's default command prefix. Note that servers can set their own individual prefixes via the `prefix` command.
 | 
					- `PREFIX`: The bot's default command prefix for classic commands. Note that servers can set their own individual prefixes via the `prefix` command.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Here's an overview of the variables that are not necessarily required for the bot to run, but can greatly enhance its functionality:
 | 
					### Optional
 | 
				
			||||||
 | 
					These variables that are not necessarily required for the bot to run, but can greatly enhance its functionality:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- `STAYVC`: Set this to true if you want the bot to stay in voice chat after playing music/a sound effect. You can make it leave by using the stop command.
 | 
					- `STAYVC`: Set this to true if you want the bot to stay in voice chat after playing music/a sound effect. You can make it leave by using the stop command.
 | 
				
			||||||
- `DBL`: An API token from [Top.gg](https://top.gg/). Unnecessary for most users since Top.gg tends to ban forks of bots like esmBot from their list.
 | 
					- `DBL`: An API token from [Top.gg](https://top.gg/). Unnecessary for most users since Top.gg tends to ban forks of bots like esmBot from their list.
 | 
				
			||||||
| 
						 | 
					@ -19,7 +22,60 @@ Here's an overview of the variables that are not necessarily required for the bo
 | 
				
			||||||
- `TMP_DOMAIN`: The root domain/directory that the images larger than 8MB are stored at. Example: `https://projectlounge.pw/tmp`
 | 
					- `TMP_DOMAIN`: The root domain/directory that the images larger than 8MB are stored at. Example: `https://projectlounge.pw/tmp`
 | 
				
			||||||
- `THRESHOLD`: A filesize threshold that the bot will start deleting old files in `TEMPDIR` at.
 | 
					- `THRESHOLD`: A filesize threshold that the bot will start deleting old files in `TEMPDIR` at.
 | 
				
			||||||
- `METRICS`: The HTTP port to serve [Prometheus](https://prometheus.io/)-compatible metrics on.
 | 
					- `METRICS`: The HTTP port to serve [Prometheus](https://prometheus.io/)-compatible metrics on.
 | 
				
			||||||
- `API`: Set this to "none" if you want to process all images locally. Alternatively, set it to "ws" to use an image API server specified in the `image` block of `servers.json`, or "azure" to use the Azure Functions-based API.
 | 
					- `API_TYPE`: Set this to "none" if you want to process all images locally. Alternatively, set it to "ws" to use an image API server specified in the `image` block of `config/servers.json`, or "azure" to use the Azure Functions-based API.
 | 
				
			||||||
- `AZURE_URL`: Your Azure webhook URL. Only applies if `API` is set to "azure".
 | 
					- `AZURE_URL`: Your Azure webhook URL. Only applies if `API` is set to "azure".
 | 
				
			||||||
- `AZURE_PASS`: An optional password used for Azure requests. Only applies if `API` is set to "azure".
 | 
					- `AZURE_PASS`: An optional password used for Azure requests. Only applies if `API` is set to "azure".
 | 
				
			||||||
- `ADMIN_SERVER`: A server to limit owner-only commands to.
 | 
					- `ADMIN_SERVER`: A Discord server/guild ID to limit owner-only commands such as eval to.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## JSON
 | 
				
			||||||
 | 
					The JSON-based configuration files are located in `config/`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### commands.json
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "types": {
 | 
				
			||||||
 | 
					    "classic": false, // Enable/disable "classic" (prefixed) commands, note that classic commands in direct messages will still work
 | 
				
			||||||
 | 
					    "application": true // Enable/disable application commands (slash and context menu commands)
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "blacklist": [
 | 
				
			||||||
 | 
					    // Names of commands that you don't want the bot to load
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### messages.json
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "emotes": [
 | 
				
			||||||
 | 
					    // Discord emote strings to use in the "Processing... this may take a while" messages, e.g. "<a:processing:818243325891051581>" or "⚙️"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "messages": [
 | 
				
			||||||
 | 
					    // Strings to use in the bot's activity message/playing status
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### servers.json
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "lava": [ // Objects containing info for connecting to Lavalink audio server(s)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "name": "test", // A human-friendly name for the server
 | 
				
			||||||
 | 
					      "url": "localhost:2333", // IP address/domain name and port for the server
 | 
				
			||||||
 | 
					      "auth": "youshallnotpass", // Password/authorization code for the server
 | 
				
			||||||
 | 
					      "local": false // Whether or not the esmBot "assets" folder is located next to the Lavalink jar file
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "image": [ // Objects containing info for connecting to WS image server(s)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "server": "localhost", // IP address or domain name for the server
 | 
				
			||||||
 | 
					      "auth": "verycoolpass100", // Password/authorization code for the server
 | 
				
			||||||
 | 
					      "tls": false // Whether or not this is a secure TLS/wss connection
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "searx": [
 | 
				
			||||||
 | 
					    // URLs for Searx/SearXNG instances used for image/YouTube searches, e.g. "https://searx.projectlounge.pw"
 | 
				
			||||||
 | 
					    // Note: instances must support getting results over JSON
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
# Custom Commands
 | 
					# Custom Commands
 | 
				
			||||||
esmBot has a flexible command handler, allowing you to create new commands and categories simply by creating new files. This page will provide a reference for creating new commands.
 | 
					esmBot has a powerful and flexible command handler, allowing you to create new commands and categories simply by creating new files. This page will provide a reference for creating new commands.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Directory Structure
 | 
					## Directory Structure
 | 
				
			||||||
The bot loads commands from subdirectories inside of the `commands` directory, which looks something like this by default:
 | 
					The bot loads commands from subdirectories inside of the `commands` directory, which looks something like this by default:
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,9 @@ commands/
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
As you can see, each command is grouped into categories, which are represented by subdirectories. To create a new category, you can simply create a new directory inside of the `commands` directory, and to create a new command, you can create a new JS file under one of those subdirectories.
 | 
					As you can see, each command is grouped into categories, which are represented by subdirectories. To create a new category, you can simply create a new directory inside of the `commands` directory, and to create a new command, you can create a new JS file under one of those subdirectories.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					!!! tip
 | 
				
			||||||
 | 
					    The `message` category is special; commands in here act as right-click context menu message commands instead of "classic" or slash commands.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Commnand Structure
 | 
					## Commnand Structure
 | 
				
			||||||
It's recommended to use the `Command` class located in `classes/command.js` to create a new command in most cases. This class provides various parameters and fields that will likely be useful when creating a command. Here is a simple example of a working command file:
 | 
					It's recommended to use the `Command` class located in `classes/command.js` to create a new command in most cases. This class provides various parameters and fields that will likely be useful when creating a command. Here is a simple example of a working command file:
 | 
				
			||||||
```js
 | 
					```js
 | 
				
			||||||
| 
						 | 
					@ -46,7 +49,7 @@ The parameters available to your command consist of the following:
 | 
				
			||||||
- `this.worker`: The ID of the current eris-fleet worker. This should be a number greater than or equal to 0.
 | 
					- `this.worker`: The ID of the current eris-fleet worker. This should be a number greater than or equal to 0.
 | 
				
			||||||
- `this.ipc`: An eris-fleet [`IPC`](https://danclay.github.io/eris-fleet/classes/IPC.html) instance, useful for communication between worker processes.
 | 
					- `this.ipc`: An eris-fleet [`IPC`](https://danclay.github.io/eris-fleet/classes/IPC.html) instance, useful for communication between worker processes.
 | 
				
			||||||
- `this.origOptions`: The raw options object provided to the command by the command handler.
 | 
					- `this.origOptions`: The raw options object provided to the command by the command handler.
 | 
				
			||||||
- `this.type`: The type of message that activated the command. Can be "classic" (a regular message) or "application" (slash commands).
 | 
					- `this.type`: The type of message that activated the command. Can be "classic" (a regular message) or "application" (slash/context menu commands).
 | 
				
			||||||
- `this.channel`: An Eris [`TextChannel`](https://abal.moe/Eris/docs/TextChannel) object of the channel that the command was run in, useful for getting info about a server and how to respond to a message.
 | 
					- `this.channel`: An Eris [`TextChannel`](https://abal.moe/Eris/docs/TextChannel) object of the channel that the command was run in, useful for getting info about a server and how to respond to a message.
 | 
				
			||||||
- `this.author`: An Eris [`User`](https://abal.moe/Eris/docs/User) object of the user who ran the command, or a [`Member`](https://abal.moe/Eris/docs/Member) object identical to `this.member` if run in a server as a slash command.
 | 
					- `this.author`: An Eris [`User`](https://abal.moe/Eris/docs/User) object of the user who ran the command, or a [`Member`](https://abal.moe/Eris/docs/Member) object identical to `this.member` if run in a server as a slash command.
 | 
				
			||||||
- `this.member`: An Eris [`Member`](https://abal.moe/Eris/docs/Member) object of the server member who ran the command. When running the command outside of a server, this parameter is undefined when run as a "classic" command or a [`User`](https://abal.moe/Eris/docs/User) object identical to `this.author` when run as a slash command.
 | 
					- `this.member`: An Eris [`Member`](https://abal.moe/Eris/docs/Member) object of the server member who ran the command. When running the command outside of a server, this parameter is undefined when run as a "classic" command or a [`User`](https://abal.moe/Eris/docs/User) object identical to `this.author` when run as a slash command.
 | 
				
			||||||
| 
						 | 
					@ -59,10 +62,11 @@ Some options are only available depending on the context/original message type,
 | 
				
			||||||
- `this.content`: A string of the raw content of the command message, excluding the prefix and command name.
 | 
					- `this.content`: A string of the raw content of the command message, excluding the prefix and command name.
 | 
				
			||||||
- `this.reference`: An object that's useful if you ever decide to reply to a user inside the command. You can use [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) to combine your message content with this parameter.
 | 
					- `this.reference`: An object that's useful if you ever decide to reply to a user inside the command. You can use [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) to combine your message content with this parameter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The options only available with "application"/slash commands are listed below:
 | 
					The options only available with application (slash and context menu) commands are listed below:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- `this.interaction`: An Eris [`CommandInteraction`](https://abal.moe/Eris/docs/CommandInteraction) object of the incoming slash command data. 
 | 
					- `this.interaction`: An Eris [`CommandInteraction`](https://abal.moe/Eris/docs/CommandInteraction) object of the incoming slash command data. 
 | 
				
			||||||
- `this.optionsArray`: A raw array of command options. Should rarely be used.
 | 
					- `this.optionsArray`: A raw array of command options. Should rarely be used.
 | 
				
			||||||
 | 
					- `this.success`: A boolean value that causes the bot to respond with a normal message when `true`, or an "ephemeral" message (a message that's only visible to the person who ran the command) when `false`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Some static fields are also available and can be set depending on your command. These fields are listed below:
 | 
					Some static fields are also available and can be set depending on your command. These fields are listed below:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,6 +84,7 @@ static flags = [{
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
- `slashAllowed`: Specifies whether or not the command is available via slash commands.
 | 
					- `slashAllowed`: Specifies whether or not the command is available via slash commands.
 | 
				
			||||||
- `directAllowed`: Specifies whether or not a command is available in direct messages.
 | 
					- `directAllowed`: Specifies whether or not a command is available in direct messages.
 | 
				
			||||||
 | 
					- `adminOnly`: Specifies whether or not a command should be limited to the bot owner(s).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## The `run` Function
 | 
					## The `run` Function
 | 
				
			||||||
The main JS code of your command is specified in the `run` function. This function should return a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) of your command output, which is why the `run` function [is an async function by default](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). The return value inside the `Promise` should be either a string or an object; you should return a string whenever you intend to reply with plain text, or an object if you intend to reply with something else, such as an embed or attachment.
 | 
					The main JS code of your command is specified in the `run` function. This function should return a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) of your command output, which is why the `run` function [is an async function by default](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). The return value inside the `Promise` should be either a string or an object; you should return a string whenever you intend to reply with plain text, or an object if you intend to reply with something else, such as an embed or attachment.
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ You should then modify the `config/servers.json` file to change the IP addresses
 | 
				
			||||||
```json
 | 
					```json
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  "lava": [
 | 
					  "lava": [
 | 
				
			||||||
    { "name": "localhost", "url": "localhost:2333", "auth": "youshallnotpass", "local": true }
 | 
					    { "name": "localhost", "url": "lavalink:2333", "auth": "youshallnotpass", "local": true }
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "image": [
 | 
					  "image": [
 | 
				
			||||||
    { "server": "api", "auth": "verycoolpass100", "tls": false }
 | 
					    { "server": "api", "auth": "verycoolpass100", "tls": false }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,7 @@ Choose the distro you're using below for insallation instructions.
 | 
				
			||||||
    ```sh
 | 
					    ```sh
 | 
				
			||||||
    sudo pacman -S git curl cmake pango ffmpeg npm imagemagick libvips sqlite3 libltdl noto-fonts-emoji gobject-introspection libcgif libimagequant meson
 | 
					    sudo pacman -S git curl cmake pango ffmpeg npm imagemagick libvips sqlite3 libltdl noto-fonts-emoji gobject-introspection libcgif libimagequant meson
 | 
				
			||||||
    ```
 | 
					    ```
 | 
				
			||||||
    You'll also need to install [`ttf-ms-fonts`](https://aur.archlinux.org/packages/ttf-ms-fonts/) from the AUR.
 | 
					    You'll also need to install [`ttf-ms-win10-auto`](https://aur.archlinux.org/packages/ttf-ms-win10-auto/) from the AUR.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
***
 | 
					***
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ export default async (client, cluster, worker, ipc, member, oldChannel) => {
 | 
				
			||||||
          players.delete(connection.originalChannel.guild.id);
 | 
					          players.delete(connection.originalChannel.guild.id);
 | 
				
			||||||
          queues.delete(connection.originalChannel.guild.id);
 | 
					          queues.delete(connection.originalChannel.guild.id);
 | 
				
			||||||
          skipVotes.delete(connection.originalChannel.guild.id);
 | 
					          skipVotes.delete(connection.originalChannel.guild.id);
 | 
				
			||||||
          client.createMessage(connection.originalChannel.id, "🔊 The current voice channel session has ended.");
 | 
					          client.createMessage(connection.originalChannel.id, `🔊 The voice channel session in \`${connection.originalChannel.name}\` has ended.`);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    } else if (member.id === connection.host) {
 | 
					    } else if (member.id === connection.host) {
 | 
				
			||||||
| 
						 | 
					@ -74,7 +74,7 @@ export default async (client, cluster, worker, ipc, member, oldChannel) => {
 | 
				
			||||||
            players.delete(connection.originalChannel.guild.id);
 | 
					            players.delete(connection.originalChannel.guild.id);
 | 
				
			||||||
            queues.delete(connection.originalChannel.guild.id);
 | 
					            queues.delete(connection.originalChannel.guild.id);
 | 
				
			||||||
            skipVotes.delete(connection.originalChannel.guild.id);
 | 
					            skipVotes.delete(connection.originalChannel.guild.id);
 | 
				
			||||||
            client.createMessage(connection.originalChannel.id, "🔊 The current voice channel session has ended.");
 | 
					            client.createMessage(connection.originalChannel.id, `🔊 The voice channel session in \`${connection.originalChannel.name}\` has ended.`);
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            const randomMember = random(members);
 | 
					            const randomMember = random(members);
 | 
				
			||||||
            players.set(connection.voiceChannel.guild.id, { player: connection.player, type: connection.type, host: randomMember.id, voiceChannel: connection.voiceChannel, originalChannel: connection.originalChannel, loop: connection.loop, shuffle: connection.shuffle, playMessage: connection.playMessage });
 | 
					            players.set(connection.voiceChannel.guild.id, { player: connection.player, type: connection.type, host: randomMember.id, voiceChannel: connection.voiceChannel, originalChannel: connection.originalChannel, loop: connection.loop, shuffle: connection.shuffle, playMessage: connection.playMessage });
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ export default async (client, cluster, worker, ipc, member, oldChannel) => {
 | 
				
			||||||
      players.delete(connection.originalChannel.guild.id);
 | 
					      players.delete(connection.originalChannel.guild.id);
 | 
				
			||||||
      queues.delete(connection.originalChannel.guild.id);
 | 
					      queues.delete(connection.originalChannel.guild.id);
 | 
				
			||||||
      skipVotes.delete(connection.originalChannel.guild.id);
 | 
					      skipVotes.delete(connection.originalChannel.guild.id);
 | 
				
			||||||
      await client.createMessage(connection.originalChannel.id, "🔊 The current voice channel session has ended.");
 | 
					      await client.createMessage(connection.originalChannel.id, `🔊 The voice channel session in \`${connection.originalChannel.name}\` has ended.`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										5
									
								
								shard.js
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								shard.js
									
										
									
									
									
								
							| 
						 | 
					@ -78,10 +78,7 @@ class Shard extends BaseClusterWorker {
 | 
				
			||||||
      log("log", `Loading event from ${file}...`);
 | 
					      log("log", `Loading event from ${file}...`);
 | 
				
			||||||
      const eventArray = file.split("/");
 | 
					      const eventArray = file.split("/");
 | 
				
			||||||
      const eventName = eventArray[eventArray.length - 1].split(".")[0];
 | 
					      const eventName = eventArray[eventArray.length - 1].split(".")[0];
 | 
				
			||||||
      if (eventName === "messageCreate" && !types.classic) {
 | 
					      if (eventName === "interactionCreate" && !types.application) {
 | 
				
			||||||
        log("warn", `Skipped loading event from ${file} because classic commands are disabled...`);
 | 
					 | 
				
			||||||
        continue;
 | 
					 | 
				
			||||||
      } else if (eventName === "interactionCreate" && !types.application) {
 | 
					 | 
				
			||||||
        log("warn", `Skipped loading event from ${file} because application commands are disabled`);
 | 
					        log("warn", `Skipped loading event from ${file} because application commands are disabled`);
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,17 +14,19 @@ class AwaitRejoin extends EventEmitter {
 | 
				
			||||||
    this.listener = (member, newChannel) => this.verify(member, newChannel);
 | 
					    this.listener = (member, newChannel) => this.verify(member, newChannel);
 | 
				
			||||||
    this.bot.on("voiceChannelJoin", this.listener);
 | 
					    this.bot.on("voiceChannelJoin", this.listener);
 | 
				
			||||||
    this.bot.on("voiceChannelSwitch", this.listener);
 | 
					    this.bot.on("voiceChannelSwitch", this.listener);
 | 
				
			||||||
    setTimeout(() => this.stop(), 10000);
 | 
					    this.stopTimeout = setTimeout(() => this.stop(), 10000);
 | 
				
			||||||
    this.checkInterval = setInterval(() => this.verify({ id: memberID }, channel, true), 1000);
 | 
					    this.checkInterval = setInterval(() => this.verify({ id: memberID }, channel, true), 1000);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  verify(member, channel, checked) {
 | 
					  verify(member, channel, checked) {
 | 
				
			||||||
    if (this.channel.id === channel.id) {
 | 
					    if (this.channel.id === channel.id) {
 | 
				
			||||||
      if ((this.member === member.id && this.channel.voiceMembers.has(member.id)) || (this.anyone && !checked)) {
 | 
					      if ((this.member === member.id && this.channel.voiceMembers.has(member.id)) || (this.anyone && !checked)) {
 | 
				
			||||||
 | 
					        clearTimeout(this.stopTimeout);
 | 
				
			||||||
        this.rejoined = true;
 | 
					        this.rejoined = true;
 | 
				
			||||||
        this.stop(member);
 | 
					        this.stop(member);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      } else if (this.anyone && (!checked || this.channel.voiceMembers.size > 1)) {
 | 
					      } else if (this.anyone && (!checked || this.channel.voiceMembers.size > 1)) {
 | 
				
			||||||
 | 
					        clearTimeout(this.stopTimeout);
 | 
				
			||||||
        this.rejoined = true;
 | 
					        this.rejoined = true;
 | 
				
			||||||
        this.stop(random(this.channel.voiceMembers.filter((i) => i.id !== this.bot.user.id && !i.bot)));
 | 
					        this.stop(random(this.channel.voiceMembers.filter((i) => i.id !== this.bot.user.id && !i.bot)));
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ import EventEmitter from "events";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// only requiring this to work around an issue regarding worker threads
 | 
					// only requiring this to work around an issue regarding worker threads
 | 
				
			||||||
const nodeRequire = createRequire(import.meta.url);
 | 
					const nodeRequire = createRequire(import.meta.url);
 | 
				
			||||||
if (process.env.API_TYPE === "none") {
 | 
					if (!process.env.API_TYPE || process.env.API_TYPE === "none") {
 | 
				
			||||||
  nodeRequire(`../../build/${process.env.DEBUG && process.env.DEBUG === "true" ? "Debug" : "Release"}/image.node`);
 | 
					  nodeRequire(`../../build/${process.env.DEBUG && process.env.DEBUG === "true" ? "Debug" : "Release"}/image.node`);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ export async function checkStatus() {
 | 
				
			||||||
      const response = await request(`http://${node.url}/version`, { headers: { authorization: node.auth } }).then(res => res.body.text());
 | 
					      const response = await request(`http://${node.url}/version`, { headers: { authorization: node.auth } }).then(res => res.body.text());
 | 
				
			||||||
      if (response) newNodes.push(node);
 | 
					      if (response) newNodes.push(node);
 | 
				
			||||||
    } catch {
 | 
					    } catch {
 | 
				
			||||||
      logger.error(`Failed to get status of Lavalink node ${node.host}.`);
 | 
					      logger.error(`Failed to get status of Lavalink node ${node.url}.`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  nodes = newNodes;
 | 
					  nodes = newNodes;
 | 
				
			||||||
| 
						 | 
					@ -230,8 +230,10 @@ export async function nextSong(client, options, connection, track, info, music,
 | 
				
			||||||
      const newTrack = await connection.node.rest.decode(newQueue[0]);
 | 
					      const newTrack = await connection.node.rest.decode(newQueue[0]);
 | 
				
			||||||
      nextSong(client, options, connection, newQueue[0], newTrack, music, voiceChannel, host, player.loop, player.shuffle, track);
 | 
					      nextSong(client, options, connection, newQueue[0], newTrack, music, voiceChannel, host, player.loop, player.shuffle, track);
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
 | 
					        if (options.type === "classic") {
 | 
				
			||||||
          if (newQueue[0] !== track && playingMessage.channel.messages.has(playingMessage.id)) await playingMessage.delete();
 | 
					          if (newQueue[0] !== track && playingMessage.channel.messages.has(playingMessage.id)) await playingMessage.delete();
 | 
				
			||||||
          if (newQueue[0] !== track && player.playMessage.channel.messages.has(player.playMessage.id)) await player.playMessage.delete();
 | 
					          if (newQueue[0] !== track && player.playMessage.channel.messages.has(player.playMessage.id)) await player.playMessage.delete();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      } catch {
 | 
					      } catch {
 | 
				
			||||||
        // no-op
 | 
					        // no-op
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -241,19 +243,14 @@ export async function nextSong(client, options, connection, track, info, music,
 | 
				
			||||||
      players.delete(voiceChannel.guild.id);
 | 
					      players.delete(voiceChannel.guild.id);
 | 
				
			||||||
      queues.delete(voiceChannel.guild.id);
 | 
					      queues.delete(voiceChannel.guild.id);
 | 
				
			||||||
      skipVotes.delete(voiceChannel.guild.id);
 | 
					      skipVotes.delete(voiceChannel.guild.id);
 | 
				
			||||||
      const content = "🔊 The current voice channel session has ended.";
 | 
					      const content = `🔊 The voice channel session in \`${voiceChannel.name}\` has ended.`;
 | 
				
			||||||
      if (options.type === "classic") {
 | 
					      if (options.type === "classic") {
 | 
				
			||||||
        await client.createMessage(options.channel.id, content);
 | 
					        await client.createMessage(options.channel.id, content);
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        await options.interaction.createMessage(content);
 | 
					        await options.interaction.createMessage(content);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      try {
 | 
					 | 
				
			||||||
        if (playingMessage.channel.messages.has(playingMessage.id)) await playingMessage.delete();
 | 
					 | 
				
			||||||
        if (player?.playMessage.channel.messages.has(player.playMessage.id)) await player.playMessage.delete();
 | 
					 | 
				
			||||||
      } catch {
 | 
					 | 
				
			||||||
        // no-op
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    } else {
 | 
					    if (options.type === "classic") {
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        if (playingMessage.channel.messages.has(playingMessage.id)) await playingMessage.delete();
 | 
					        if (playingMessage.channel.messages.has(playingMessage.id)) await playingMessage.delete();
 | 
				
			||||||
        if (player?.playMessage.channel.messages.has(player.playMessage.id)) await player.playMessage.delete();
 | 
					        if (player?.playMessage.channel.messages.has(player.playMessage.id)) await player.playMessage.delete();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue