diff --git a/.gitignore b/.gitignore
index cf92c76..44c00d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@ secrets*
deploycommands.json
data/existingGames/*.json
data/gameApplications/*.json
-data/archivedGames/*.json
\ No newline at end of file
+data/archivedGames/*.json
+node_modules/*
\ No newline at end of file
diff --git a/commands/init.js b/commands/init.js
index 26df44d..e03a1e7 100644
--- a/commands/init.js
+++ b/commands/init.js
@@ -4,17 +4,29 @@ module.exports = {
//command definition for discord API
data: new SlashCommandBuilder()
.setName('init')
- .setDescription('what could this be?'),
+ .setDescription('what could this be?')
+ .addStringOption(option =>
+ option
+ .setName("type")
+ .setDescription("gaming")),
//the funciton to be run
- async execute(interaction){
- if(interaction.user.id != '122065561428426755'){
- await interaction.reply({content: "Permission Denied", ephemeral: true});
+ async execute(interaction) {
+ if (interaction.user.id != '122065561428426755') {
+ await interaction.reply({ content: "Permission Denied", ephemeral: true });
return;
}
- await initGmAndReportForm(interaction);
- interaction.reply({content:"Done", ephemeral:"true"})
+ const choice = interaction.options.getString("type");
+ switch (choice) {
+ case "music":
+ await initMusicButtons(interaction);
+ break;
+ default:
+ await initGmAndReportForm(interaction);
+ break;
+ }
+ await interaction.reply({ content: "Done", ephemeral: "true" })
}
}
@@ -27,14 +39,115 @@ async function initGmAndReportForm(interaction) {
const actionRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
- .setCustomId("pushGmForm")
- .setLabel("GM Form")
- .setStyle(ButtonStyle.Primary),
+ .setCustomId("pushGmForm")
+ .setLabel("GM Form")
+ .setStyle(ButtonStyle.Primary),
new ButtonBuilder()
- .setCustomId("pushReportForm")
- .setLabel("Report Form")
- .setStyle(ButtonStyle.Danger)
+ .setCustomId("pushReportForm")
+ .setLabel("Report Form")
+ .setStyle(ButtonStyle.Danger)
);
await interaction.channel.send({ embeds: [embed], components: [actionRow] });
+}
+
+async function initMusicButtons(interaction) {
+ //row 1
+ //join(green), leave(red),
+
+ const row1 = new ActionRowBuilder()
+ .addComponents(
+ new ButtonBuilder()
+ .setCustomId("join")
+ .setEmoji('π»')
+ .setLabel("Join")
+ .setStyle(ButtonStyle.Success),
+ new ButtonBuilder()
+ .setCustomId("leave")
+ .setEmoji('π')
+ .setLabel("Leave")
+ .setStyle(ButtonStyle.Danger),
+ /*
+ new ButtonBuilder()
+ .setCustomId("squelch")
+ .setEmoji('π')
+ .setLabel("Disable Replies")
+ .setStyle(ButtonStyle.Secondary)
+ */
+ );
+
+ //row 2
+ //enqueue(modal??), clear, queue, nowplaying
+ const row2 = new ActionRowBuilder()
+ .addComponents(
+ new ButtonBuilder()
+ .setCustomId("enqueueModal")
+ //.setEmoji('')
+ .setLabel("Add Song")
+ .setStyle(ButtonStyle.Primary),
+ new ButtonBuilder()
+ .setCustomId("clearQueue")
+ //.setEmoji('')
+ .setLabel("Clear Queue")
+ .setStyle(ButtonStyle.Danger),
+ new ButtonBuilder()
+ .setCustomId("showQueue")
+ //.setEmoji('')
+ .setLabel("Show Queue")
+ .setStyle(ButtonStyle.Secondary),
+ new ButtonBuilder()
+ .setCustomId("nowPlaying")
+ //.setEmoji('')
+ .setLabel("Now Playing")
+ .setStyle(ButtonStyle.Secondary)
+ );
+
+ //row 3
+ //loop, loopOne, shuffle
+ const row3 = new ActionRowBuilder()
+ .addComponents(
+ new ButtonBuilder()
+ .setCustomId("loop")
+ .setEmoji('π')
+ //.setLabel("")
+ .setStyle(ButtonStyle.Primary),
+ new ButtonBuilder()
+ .setCustomId("loopOne")
+ .setEmoji('π')
+ //.setLabel("")
+ .setStyle(ButtonStyle.Primary),
+ new ButtonBuilder()
+ .setCustomId("shuffleQueue")
+ .setEmoji('π')
+ //.setLabel("")
+ .setStyle(ButtonStyle.Secondary)
+ );
+
+ //row 4
+ //resume, pause, skip,
+ const row4 = new ActionRowBuilder()
+ .addComponents(
+ new ButtonBuilder()
+ .setCustomId("resumePlayback")
+ .setEmoji('βΆοΈ')
+ //.setLabel("")
+ .setStyle(ButtonStyle.Primary),
+ new ButtonBuilder()
+ .setCustomId("pause")
+ .setEmoji('βΈοΈ')
+ //.setLabel("")
+ .setStyle(ButtonStyle.Primary),
+ new ButtonBuilder()
+ .setCustomId("skip")
+ .setEmoji('βοΈ')
+ //.setLabel("")
+ .setStyle(ButtonStyle.Secondary),
+ );
+
+ //send rows as messages
+ const channel = interaction.channel;
+ await channel.send({ components: [row1] });
+ await channel.send({ components: [row2] });
+ await channel.send({ components: [row3] });
+ await channel.send({ components: [row4] });
}
\ No newline at end of file
diff --git a/commands/music commands/clear.js b/commands/music commands/clear.js
new file mode 100644
index 0000000..b176a16
--- /dev/null
+++ b/commands/music commands/clear.js
@@ -0,0 +1,16 @@
+const { SlashCommandBuilder } = require('discord.js');
+
+module.exports = {
+ data: new SlashCommandBuilder()
+ .setName("clear")
+ .setDescription("Clears the playlist.")
+ .addBooleanOption(option =>
+ option
+ .setName("clearcurrentlyplaying")
+ .setDescription("Should the current song also be removed and skipped?")
+ .setRequired(false)),
+
+ async execute(interaction) {
+ await interaction.client.functions.get("clearQueue").execute(interaction);
+ }
+}
\ No newline at end of file
diff --git a/commands/music commands/enqueue.js b/commands/music commands/enqueue.js
new file mode 100644
index 0000000..56154a4
--- /dev/null
+++ b/commands/music commands/enqueue.js
@@ -0,0 +1,17 @@
+const { SlashCommandBuilder } = require('discord.js');
+
+module.exports = {
+ data: new SlashCommandBuilder()
+ .setName("enqueue")
+ .setDescription("Adds a song to the playlist.")
+ .addStringOption(option =>
+ option
+ .setName("query")
+ .setDescription("Enter a Youtube video or playlist URL, or enter a search query.")
+ .setRequired(true)
+ ),
+
+ async execute(interaction) {
+ await interaction.client.functions.get("enqueue").execute(interaction);
+ }
+}
\ No newline at end of file
diff --git a/commands/music commands/join.js b/commands/music commands/join.js
new file mode 100644
index 0000000..68e0d13
--- /dev/null
+++ b/commands/music commands/join.js
@@ -0,0 +1,12 @@
+const { SlashCommandBuilder } = require('discord.js')
+
+module.exports = {
+ //command definition for discord API
+ data: new SlashCommandBuilder()
+ .setName('join')
+ .setDescription('Assigns a loudspeaker to your channel.'),
+
+ async execute(interaction) {
+ await interaction.client.functions.get("join").execute(interaction);
+ }
+}
\ No newline at end of file
diff --git a/commands/music commands/leave.js b/commands/music commands/leave.js
new file mode 100644
index 0000000..9c924dd
--- /dev/null
+++ b/commands/music commands/leave.js
@@ -0,0 +1,11 @@
+const { SlashCommandBuilder } = require('discord.js');
+
+module.exports = {
+ data: new SlashCommandBuilder()
+ .setName("leave")
+ .setDescription("Disconnects a loudspeaker from your channel."),
+
+ async execute(interaction) {
+ await interaction.client.functions.get("leave").execute(interaction);
+ }
+}
\ No newline at end of file
diff --git a/commands/music commands/loop.js b/commands/music commands/loop.js
new file mode 100644
index 0000000..9bfef02
--- /dev/null
+++ b/commands/music commands/loop.js
@@ -0,0 +1,15 @@
+const { SlashCommandBuilder } = require('discord.js');
+
+module.exports = {
+ data: new SlashCommandBuilder()
+ .setName("loop")
+ .setDescription("Sets the playlist on a loop. If not given a choice, on/off will be toggled.")
+ .addBooleanOption(option =>
+ option
+ .setName('on')
+ .setDescription("True turns loop on, False turns loop off.")),
+
+ async execute(interaction) {
+ await interaction.client.functions.get("loop").execute(interaction);
+ }
+}
\ No newline at end of file
diff --git a/commands/music commands/nowplaying.js b/commands/music commands/nowplaying.js
new file mode 100644
index 0000000..045fe3e
--- /dev/null
+++ b/commands/music commands/nowplaying.js
@@ -0,0 +1,11 @@
+const { SlashCommandBuilder } = require('discord.js');
+
+module.exports = {
+ data: new SlashCommandBuilder()
+ .setName("nowplaying")
+ .setDescription("Displays the current song."),
+
+ async execute(interaction) {
+ await interaction.client.functions.get("nowPlaying").execute(interaction);
+ }
+}
\ No newline at end of file
diff --git a/commands/music commands/pause.js b/commands/music commands/pause.js
new file mode 100644
index 0000000..383dd9d
--- /dev/null
+++ b/commands/music commands/pause.js
@@ -0,0 +1,11 @@
+const { SlashCommandBuilder } = require('discord.js');
+
+module.exports = {
+ data: new SlashCommandBuilder()
+ .setName("pause")
+ .setDescription("Pauses playback."),
+
+ async execute(interaction) {
+ await interaction.client.functions.get("pause").execute(interaction);
+ }
+}
\ No newline at end of file
diff --git a/commands/music commands/play.js b/commands/music commands/play.js
new file mode 100644
index 0000000..555c83b
--- /dev/null
+++ b/commands/music commands/play.js
@@ -0,0 +1,52 @@
+const { SlashCommandBuilder } = require('discord.js')
+
+module.exports = {
+ data: new SlashCommandBuilder()
+ .setName("play")
+ .setDescription("Plays a Youtube video or playlist given a URL or search query.")
+ .addStringOption(option =>
+ option
+ .setName("query")
+ .setDescription("Enter a Youtube video or playlist URL, or enter a search query.")
+ .setRequired(false)
+ ),
+
+ /**
+ * This function should:
+ * Assign a new vacant loudspeaker to the user's channel if there isn't one already already assigned and have it join the channel.
+ * If there is no queue, create a new one.
+ * Parse whether the query is a video link, playlist link, or search term and enqueue the found video(s).
+ * If there is no query, unpause the playback (call resume.js).
+ * If there is a query and the queue was previously empty, start playback.
+ */
+ async execute(interaction) {
+ if (!interaction.member.voice.channel) {
+ await interaction.reply({ content: "You need to be in a voice channel to use music commands.", ephemeral: true });
+ return;
+ }
+
+ await interaction.deferReply({ephemeral: true});
+
+ const result = await interaction.client.functions.get("connectLoudspeaker").execute(interaction);
+ let response = "";
+ //respond to the user
+ switch (result.status) {
+ case "no vacancies":
+ response = "Unfortunately there are no vacant loudspeakers at this time.\n";
+ break;
+ case "already assigned":
+ response = "";
+ break;
+ case "new assignment":
+ response = "Assigned a loudspeaker to your channel.\n"
+ break;
+ }
+
+ response += await interaction.client.functions.get("enqueue").execute(interaction) + "\n";
+
+ //TODO: resume/start playback
+ response += await interaction.client.functions.get("resumePlayback").execute(interaction);
+
+ await interaction.editReply(response);
+ }
+}
\ No newline at end of file
diff --git a/commands/music commands/queue.js b/commands/music commands/queue.js
new file mode 100644
index 0000000..33c85d9
--- /dev/null
+++ b/commands/music commands/queue.js
@@ -0,0 +1,11 @@
+const { SlashCommandBuilder } = require('discord.js');
+
+module.exports = {
+ data: new SlashCommandBuilder()
+ .setName("queue")
+ .setDescription("Shows the queue."),
+
+ async execute(interaction) {
+ await interaction.client.functions.get("showQueue").execute(interaction);
+ }
+}
\ No newline at end of file
diff --git a/commands/music commands/resume.js b/commands/music commands/resume.js
new file mode 100644
index 0000000..1f7a51d
--- /dev/null
+++ b/commands/music commands/resume.js
@@ -0,0 +1,11 @@
+const { SlashCommandBuilder } = require('discord.js');
+
+module.exports = {
+ data: new SlashCommandBuilder()
+ .setName("resume")
+ .setDescription("Resumes playback."),
+
+ async execute(interaction) {
+ await interaction.client.functions.get("resumePlayback").execute(interaction);
+ }
+}
\ No newline at end of file
diff --git a/commands/music commands/shuffle.js b/commands/music commands/shuffle.js
new file mode 100644
index 0000000..1dfa831
--- /dev/null
+++ b/commands/music commands/shuffle.js
@@ -0,0 +1,11 @@
+const { SlashCommandBuilder } = require('discord.js');
+
+module.exports = {
+ data: new SlashCommandBuilder()
+ .setName("shuffle")
+ .setDescription("Shuffles the playlist."),
+
+ async execute(interaction) {
+ await interaction.client.functions.get("shuffleQueue").execute(interaction);
+ }
+}
\ No newline at end of file
diff --git a/commands/music commands/skip.js b/commands/music commands/skip.js
new file mode 100644
index 0000000..5c54865
--- /dev/null
+++ b/commands/music commands/skip.js
@@ -0,0 +1,15 @@
+const { SlashCommandBuilder } = require('discord.js');
+
+module.exports = {
+ data: new SlashCommandBuilder()
+ .setName("skip")
+ .setDescription("Skips current song.")
+ .addBooleanOption(option =>
+ option
+ .setName('pause')
+ .setDescription("(Default is false/no) Should the next song be paused?")),
+
+ async execute(interaction) {
+ await interaction.client.functions.get("skip").execute(interaction);
+ }
+}
\ No newline at end of file
diff --git a/deploycommands.js b/deploycommands.js
index e2bbc8e..740a7c6 100644
--- a/deploycommands.js
+++ b/deploycommands.js
@@ -1,14 +1,18 @@
const { REST, Routes } = require('discord.js');
const { clientid, productionGuildId, token } = require('./secrets.json');
const fs = require('node:fs');
+const path = require('node:path');
+
const commands = [];
// Grab all the command files from the commands folder
-const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
+//const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
+const commandFiles = [];
+getAllNestedFiles('./commands', commandFiles);
// Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
for (const file of commandFiles) {
- const command = require(`./commands/${file}`);
+ const command = require(`./${file}`);
console.log(`requiring ${file}`);
commands.push(command.data.toJSON());
}
@@ -33,4 +37,16 @@ const rest = new REST({ version: '10' }).setToken(token);
// And of course, make sure you catch and log any errors!
console.error(error);
}
-})();
\ No newline at end of file
+})();
+
+function getAllNestedFiles(rootDirectory, fileList){
+ fs.readdirSync(rootDirectory).forEach(File => {
+ const filePath = path.join(rootDirectory, File);
+ if(fs.statSync(filePath).isDirectory()){
+ return getAllNestedFiles(filePath, fileList);
+ }
+ else{
+ return fileList.push(filePath);
+ }
+ });
+}
\ No newline at end of file
diff --git a/events/autoDestroyLoudspeaker.js b/events/autoDestroyLoudspeaker.js
new file mode 100644
index 0000000..1ebac17
--- /dev/null
+++ b/events/autoDestroyLoudspeaker.js
@@ -0,0 +1,30 @@
+const { Events } = require('discord.js');
+const { client } = require('../index');
+const { productionGuildId } = require('../secrets.json');
+
+module.exports = {
+ name: Events.VoiceStateUpdate,
+ /**
+ * This function will respond to people leaving VCs, seeing if there's a loudspeaker in there.
+ * If there is nobody else in that channel, the loudspeaker will be destroyed.
+ * @param {*} oldState
+ * @param {*} newState
+ * @returns
+ */
+ async execute(oldState, newState) {
+ //oldState is a VoiceState object
+
+ if (oldState.guild.id != productionGuildId || !oldState.channel)
+ return;
+
+ const channel = oldState.channel;
+ const assignLoudspeakerResult = await client.functions.get("assignLoudspeaker").execute(channel.id, client.loudspeakers);
+
+ //don't do anything if there's no loudspeaker in there or if there are still people other than the bot in there
+ if (assignLoudspeakerResult.status != "already assigned" || channel.members.size != 1)
+ return;
+
+ const loudspeakerClient = client.loudspeakers.get(assignLoudspeakerResult.loudspeakerId);
+ client.functions.get("destroyLoudspeaker").execute(loudspeakerClient);
+ }
+}
\ No newline at end of file
diff --git a/index.js b/index.js
index a3212b3..bb022cc 100644
--- a/index.js
+++ b/index.js
@@ -3,14 +3,24 @@ const fs = require('node:fs');
const path = require('node:path');
// Require the necessary discord.js classes
const { Client, Collection, Events, GatewayIntentBits } = require('discord.js');
-const { token } = require('./secrets.json');
+const { token, loudspeakerTokens } = require('./secrets.json');
-// Create a new client instance
-const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.DirectMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessages] });
+// Create a new client instance for CAROLINE
+const client = new Client({
+ intents: [GatewayIntentBits.Guilds,
+ GatewayIntentBits.GuildMembers,
+ GatewayIntentBits.DirectMessages,
+ GatewayIntentBits.MessageContent,
+ GatewayIntentBits.GuildMessages,
+ GatewayIntentBits.GuildVoiceStates]
+});
// Log in to Discord with your client's token
client.login(token);
-module.exports = {client};
+module.exports = { client };
+
+//create instances for loudspeakers
+const loudspeakerClients = loginLoudspeakerClients();
//commands collection
client.commands = new Collection();
@@ -18,16 +28,19 @@ client.commands = new Collection();
//load all commands and add them to the collection
const commandsPath = path.join(__dirname, 'commands');
//read all files in the commands folder and return an array
-const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
+//const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
+const commandFiles = [];
+getAllNestedFiles(commandsPath, commandFiles);
//put commands in the collection
for (const file of commandFiles) {
- const filePath = path.join(commandsPath, file);
- const command = require(filePath);
+ //const filePath = file;
+ //const filePath = path.join(commandsPath, file);
+ const command = require(file);
// Set a new item in the Collection with the key as the command name and the value as the exported module
if ('data' in command && 'execute' in command) {
client.commands.set(command.data.name, command);
} else {
- console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
+ console.log(`[WARNING] The command at ${file} is missing a required "data" or "execute" property.`);
}
}
@@ -50,13 +63,12 @@ client.functions = new Collection();
const functionsPath = path.join(__dirname, 'lib');
//const functionFiles = fs.readdirSync(functionsPath).filter(file => file.endsWith('.js'));
const functionFiles = [];
-getAllNestedFiles(functionsPath);
-console.log(`found files ${functionFiles}`);
-for(const file of functionFiles){
+getAllNestedFiles(functionsPath, functionFiles);
+for (const file of functionFiles) {
//const filePath = path.join(functionsPath, file);
- console.log(`including ${file}`);
+ //console.log(`including ${file}`);
const customFunction = require(file);
- if('name' in customFunction && 'execute' in customFunction)
+ if ('name' in customFunction && 'execute' in customFunction)
client.functions.set(customFunction.name, customFunction);
else
console.log(`The custom function ${file} is missing a name or executable.`);
@@ -65,15 +77,45 @@ for(const file of functionFiles){
//initialize cooldown collection for rate limiting, the rest is handled in interactioncreate.js
client.cooldowns = new Collection();
-function getAllNestedFiles(rootDirectory){
+//compile the collection of loudspeaker clients
+loudspeakerClients.then((loudspeakerClients) => {
+ client.loudspeakers = new Collection();
+ for (const loudspeaker of loudspeakerClients) {
+ client.loudspeakers.set(loudspeaker.user.id, loudspeaker);
+ loudspeaker.parentClient = client;
+ }
+ console.log(`${loudspeakerClients.length} Loudspeakers ready`);
+},
+ (error) => console.error(`Error while logging in loudspeakers:\n${error.stack}`));
+
+//functions below
+
+function getAllNestedFiles(rootDirectory, fileList) {
fs.readdirSync(rootDirectory).forEach(File => {
const filePath = path.join(rootDirectory, File);
- if(fs.statSync(filePath).isDirectory()){
- return getAllNestedFiles(filePath);
+ if (fs.statSync(filePath).isDirectory()) {
+ return getAllNestedFiles(filePath, fileList);
}
- else{
- return functionFiles.push(filePath);
+ else {
+ return fileList.push(filePath);
+ }
+ });
+}
+
+async function loginLoudspeakerClients() {
+ return new Promise(async (resolve) => {
+ const loudspeakerClients = [];
+ for (const token of loudspeakerTokens) {
+ const loudspeakerClient = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates] });
+ try {
+ await loudspeakerClient.login(token);
+ console.log(`Logged in loudspeaker ${loudspeakerClient.user.tag}`);
+ loudspeakerClients.push(loudspeakerClient);
+ }
+ catch (e) {
+ console.error(`Couldn't login a loudspeaker:\n${e.stack}`);
+ }
}
+ resolve(loudspeakerClients);
});
- return functionFiles;
}
\ No newline at end of file
diff --git a/lib/musicFunctions/assignLoudspeaker.js b/lib/musicFunctions/assignLoudspeaker.js
new file mode 100644
index 0000000..78f380e
--- /dev/null
+++ b/lib/musicFunctions/assignLoudspeaker.js
@@ -0,0 +1,39 @@
+
+module.exports = {
+ name: "assignLoudspeaker",
+ async execute(voiceChannelId, loudspeakerMap) {
+ /**
+ * This function should:
+ * Find out whether the user's vc needs a loudspeaker assigned to it. Return {status: "already assigned", loudspeakerid: loudspeakerid}
+ * If it does, search the client.loudspeakers collection and find one that is unassigned.
+ * If there are no vacancies, return {status: "no vacancies"}
+ * Return {status: "new assignment", loudspeakerid}
+ */
+
+ //search for both a vacant loudspeaker and a loudspeaker that is already occupying the user's vc
+ let vacantLoudspeakerList = [];
+ let vacantLoudspeakerClient;
+ let channelHasLoudspeakerAlready = false;
+ loudspeakerMap.each(loudspeakerClient => {
+ if (!loudspeakerClient.connection)
+ vacantLoudspeakerList.push(loudspeakerClient);
+ //vacantLoudspeakerClient = loudspeakerClient;
+ else if (loudspeakerClient.connection.joinConfig.channelId == voiceChannelId) {
+ channelHasLoudspeakerAlready = true;
+ vacantLoudspeakerClient = loudspeakerClient;
+ return;
+ }
+ });
+
+ if (channelHasLoudspeakerAlready)
+ return { status: "already assigned", loudspeakerId: vacantLoudspeakerClient.user.id };
+
+ if (vacantLoudspeakerList.length == 0)
+ return { status: "no vacancies" };
+
+ vacantLoudspeakerClient = vacantLoudspeakerList[Math.floor(Math.random() * vacantLoudspeakerList.length)];
+
+ return { status: "new assignment", loudspeakerId: vacantLoudspeakerClient.user.id };
+ }
+}
+
diff --git a/lib/musicFunctions/clearQueue.js b/lib/musicFunctions/clearQueue.js
new file mode 100644
index 0000000..a2ebd70
--- /dev/null
+++ b/lib/musicFunctions/clearQueue.js
@@ -0,0 +1,51 @@
+const latentFunctionPrecheck = require("./latentFunctionPrecheck");
+
+module.exports = {
+ name: "clearQueue",
+
+ /**
+ * Removes every song from the queue of the assigned loudspeaker except the one that's currently playing.
+ * If the interaction boolean option says to, it will also remove the first song by skipping it.
+ * @param {*} interaction
+ * @returns
+ */
+ async execute(interaction) {
+ const guardCheckResponse = await latentFunctionPrecheck.execute(interaction);
+ if (!guardCheckResponse.inVoiceChannel || !guardCheckResponse.loudspeakerClient)
+ return;
+
+ //collect loudspeaker
+ const loudspeakerClient = guardCheckResponse.loudspeakerClient;
+
+ //collect command option to skip current song
+ //ternary for music control button compatibility
+ const clearCurrentlyPlayingSong = interaction.options ? interaction.options.getBoolean('clearcurrentlyplaying') : undefined;
+
+ //do nothing if the queue is empty
+ if (loudspeakerClient.queue.length == 0) {
+ await interaction.followUp("The queue is already empty.");
+ return;
+ }
+
+ //do nothing if the queue only has one song and they don't want to clear it
+ if (loudspeakerClient.queue.length == 1 && !clearCurrentlyPlayingSong){
+ await interaction.followUp("There's only one song in the queue and it was not cleared.\nTry using /skip.");
+ return;
+ }
+
+ let skipResponse = "";
+ if (clearCurrentlyPlayingSong) {
+ //weird but it works: https://stackoverflow.com/a/1232046
+ loudspeakerClient.queue.length = 1;
+ skipResponse = await interaction.client.functions.get("skip").execute(interaction);
+ }
+ else { //don't clear current song
+ const temp = loudspeakerClient.queue[0];
+ loudspeakerClient.queue.length = 0;
+ loudspeakerClient.queue.push(temp);
+ }
+
+ await interaction.followUp(`Queue was cleared.\n${skipResponse}`);
+ return;
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/connectLoudspeaker.js b/lib/musicFunctions/connectLoudspeaker.js
new file mode 100644
index 0000000..e23cb47
--- /dev/null
+++ b/lib/musicFunctions/connectLoudspeaker.js
@@ -0,0 +1,124 @@
+const { AudioPlayerStatus } = require('@discordjs/voice');
+
+module.exports = {
+ name: "connectLoudspeaker",
+
+ async execute(interaction) {
+ const voiceChannelId = interaction.member.voice.channelId;
+ const loudspeakerList = interaction.client.loudspeakers;
+ const loudspeakerAssignmentResult = await interaction.client.functions.get("assignLoudspeaker").execute(voiceChannelId, loudspeakerList);
+
+ if (loudspeakerAssignmentResult.status == "new assignment") {
+ //assign a new loudspeaker and initialize it
+ const loudspeakerClient = loudspeakerList.get(loudspeakerAssignmentResult.loudspeakerId);
+ const voiceChannel = await loudspeakerClient.channels.fetch(interaction.member.voice.channel.id);
+ initLoudspeaker(loudspeakerClient, voiceChannel);
+ }
+
+ //If there were no vacant loudspeakers or one has already been assigned, do nothing
+ return loudspeakerAssignmentResult;
+ }
+}
+
+async function initLoudspeaker(loudspeakerClient, channel) {
+ //have the bot join the channel https://discordjs.guide/voice/voice-connections.html#cheat-sheet
+ //IMPORTANT! The client that instantiates the Guild object when
+ //creating the voice adapter will be the one who joins the channel!
+ //Source: https://discord.com/channels/222078108977594368/1090014703209693194/1090123144594980934
+ //IMPORTANT! The /voice will attempt to reuse connections from the same group,
+ //so use a different group identifier for every bot!
+ //Source: https://discord.com/channels/222078108977594368/1114539446629572668/1114558326341120142
+ const { joinVoiceChannel, createAudioPlayer, NoSubscriberBehavior } = require('@discordjs/voice');
+ loudspeakerClient.connection = joinVoiceChannel({
+ channelId: channel.id,
+ guildId: channel.guild.id,
+ adapterCreator: channel.guild.voiceAdapterCreator,
+ group: loudspeakerClient.id
+ });
+
+ //I have no idea what this does other than listen to the connection's state change.
+ //This fixes an issue where the playback would consistently stop around 1 minute but the player would not show any errors or state changes.
+ //https://github.com/umutxyp/MusicBot/issues/97#issuecomment-1452607414
+ //NEVERMIND this was patched; updating djs/voice fixed the issue and this is no longer necessary
+ /*
+ loudspeakerClient.connection.on('stateChange', (oldState, newState) => {
+ const oldNetworking = Reflect.get(oldState, 'networking');
+ const newNetworking = Reflect.get(newState, 'networking');
+ const networkStateChangeHandler = (oldNetworkState, newNetworkState) => {
+ const newUdp = Reflect.get(newNetworkState, 'udp');
+ clearInterval(newUdp?.keepAliveInterval);
+ }
+ oldNetworking?.off('stateChange', networkStateChangeHandler);
+ newNetworking?.on('stateChange', networkStateChangeHandler);
+ });
+ */
+
+ //init loudspeaker with empty queue
+ loudspeakerClient.queue = [];
+
+ //init player
+ loudspeakerClient.player = createAudioPlayer({
+ behaviors: {
+ noSubscriber: NoSubscriberBehavior.Play,
+ debug: true
+ }
+ });
+
+ //install event handlers (DEBUGGING)
+ loudspeakerClient.player.on(AudioPlayerStatus.Paused, () => {
+ });
+ loudspeakerClient.player.on(AudioPlayerStatus.Playing, () => {
+ //this is set in function music.js where the next song that starts playing may be paused.
+ if (loudspeakerClient.player.pauseOnNextPlay) {
+ loudspeakerClient.player.pause();
+ loudspeakerClient.player.pauseOnNextPlay = undefined;
+ }
+ });
+ loudspeakerClient.player.on(AudioPlayerStatus.Idle, () => {
+ autoplayNextSong(loudspeakerClient);
+ });
+ loudspeakerClient.player.on(AudioPlayerStatus.Buffering, () => {
+ });
+ loudspeakerClient.player.on(AudioPlayerStatus.AutoPaused, () => {
+ });
+ loudspeakerClient.player.on('error', error => {
+ console.log(`MUSIC - [WARN] ${loudspeakerClient.user.username} encountered an error:\n${error.stack}`);
+ });
+ loudspeakerClient.player.on('stateChange', (oldState, newState) => {
+ console.log(`MUSIC - [INFO] ${loudspeakerClient.user.username}: ${oldState.status} -> ${newState.status}`);
+ });
+ loudspeakerClient.connection.on('error', error => {
+ console.log(`MUSIC - [WARN] ${loudspeakerClient.user.username} connection error:\n${error.message}`);
+ });
+}
+
+function autoplayNextSong(loudspeakerClient) {
+ //if the player is about to be or is already destroyed, don't try to play the next song.
+ if (!loudspeakerClient.player || loudspeakerClient.player.markedForDeletion)
+ return;
+
+ console.log(`MUSIC - [INFO] ${loudspeakerClient.user.username} autoplaying next song in queue.`);
+ //remove the song that just finished
+ let removedItem = loudspeakerClient.queue.length != 0 ? loudspeakerClient.queue.shift() : undefined;
+
+ //if the first song should be looping (ifelse makes loopOne take precedence over just loop)
+ if (loudspeakerClient.player.loopOne) {
+ //in some cases (skip when there's only 1 song), loop should not readd the song
+ if (loudspeakerClient.player.loopNoReadd)
+ loudspeakerClient.player.loopNoReadd = undefined;
+ else
+ loudspeakerClient.queue.unshift(removedItem)
+ }
+ //if the queue should be looping, readd the item to the back of the list
+ else if (loudspeakerClient.player.loop) {
+ //in some cases (skip when there's only 1 song), loop should not readd the song
+ if (loudspeakerClient.player.loopNoReadd)
+ loudspeakerClient.player.loopNoReadd = undefined;
+ else
+ loudspeakerClient.queue.push(removedItem);
+ }
+
+ //start the next song
+ if (loudspeakerClient.queue.length != 0)
+ loudspeakerClient.parentClient.functions.get("startNextSong").execute(loudspeakerClient); //using interaction here might lead to some problems
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/destroyLoudspeaker.js b/lib/musicFunctions/destroyLoudspeaker.js
new file mode 100644
index 0000000..0d27503
--- /dev/null
+++ b/lib/musicFunctions/destroyLoudspeaker.js
@@ -0,0 +1,28 @@
+
+module.exports = {
+ name: "destroyLoudspeaker",
+ /**
+ * This function should:
+ * If there is no loudspeaker assigned to the VC, ignore the command
+ * Disconnect the loudspeaker from the VC
+ * Clear/delete the queue (not decided on the specification yet)
+ * Clear the connection status
+ */
+ async execute(loudspeakerClient) {
+ //notify the autoplayer to not play the next song because the player is about to be deleted.
+ loudspeakerClient.player.markedForDestroy = true;
+ //destroy player -> stop playback and avoid memory leaks
+ //https://discordjs.guide/voice/audio-player.html#deletion
+ loudspeakerClient.player.stop();
+ loudspeakerClient.player = undefined;
+ //destroying this is actually good because the player is created at connection time
+
+ //destroy connection -> disconnect
+ loudspeakerClient.connection.destroy();
+ loudspeakerClient.connection = undefined;
+
+ //destroy queue
+ loudspeakerClient.queue.length = 0;
+ loudspeakerClient.queue = undefined;
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/enqueue.js b/lib/musicFunctions/enqueue.js
new file mode 100644
index 0000000..0fd18b6
--- /dev/null
+++ b/lib/musicFunctions/enqueue.js
@@ -0,0 +1,77 @@
+const latentFunctionPrecheck = require("./latentFunctionPrecheck");
+
+module.exports = {
+ name: "enqueue",
+
+ /**
+ * This function enqueues a query using an interaction's option.getString('query').
+ * It WILL reply to the user with an ephemeral response and also return the response.
+ * Be sure to use interaction.editReply() in the function that called this.
+ * @param {*} interaction
+ * @returns
+ */
+ async execute(interaction) {
+ const guardCheckResponse = await latentFunctionPrecheck.execute(interaction);
+ if (!guardCheckResponse.inVoiceChannel || !guardCheckResponse.loudspeakerClient)
+ return;
+
+ //collect loudspeaker
+ const loudspeakerClient = guardCheckResponse.loudspeakerClient;
+
+ let response = "";
+ let query;
+
+ //check if the query is in a modal
+ if (interaction.fields) {
+ query = interaction.fields.getTextInputValue("query");
+ }
+
+ //if there's no query, don't do anything
+ /*
+ If there already is a query, skip this block.
+ If interaction was a command AND there's nothing supplied in the block, execute this block
+ */
+ if (!query && interaction.options && !interaction.options.getString('query')) {
+ response = "No query provided. Did not enqueue anything.";
+ if (!interaction.replied && !interaction.deferred)
+ await interaction.followUp(response);
+ return response;
+ }
+
+ //if query was not already set from a modal field, set it from the command
+ if (!query)
+ query = interaction.options.getString('query');
+
+ //start a response to the user
+ response = "Pondering your query...";
+ if (interaction.replied || interaction.deferred)
+ await interaction.editReply(response);
+ else
+ await interaction.followUp(response);
+
+ //enqueue query
+ const videosAdded = await interaction.client.functions.get("enqueueQuery").execute(query, loudspeakerClient);
+
+ //respond with all of the video titles enqueued
+ response = "";
+ if (videosAdded.length == 1)
+ response += `Added [${videosAdded[0].title}](<${videosAdded[0].url}>)`; //<> to remove embed
+
+ else {
+ response += "Added the following tracks:\n"
+ let numVideosListed = 0;
+ for (let video of videosAdded) {
+ response += `[${video.title}](<${video.url}>)\n`;
+ numVideosListed++;
+ //check if character limit is being approached
+ if (response.length >= 1600) {
+ response += `...and ${videosAdded.length - numVideosListed} more tracks.`
+ break;
+ }
+ }
+ }
+
+ await interaction.editReply(response);
+ return response;
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/enqueueModal.js b/lib/musicFunctions/enqueueModal.js
new file mode 100644
index 0000000..ccfac25
--- /dev/null
+++ b/lib/musicFunctions/enqueueModal.js
@@ -0,0 +1,37 @@
+const { ActionRowBuilder, TextInputBuilder, TextInputStyle, ModalBuilder } = require("discord.js");
+
+module.exports = {
+ name: "enqueueModal",
+ async execute(interaction) {
+ //custom latent check
+ if (!interaction.member.voice.channel) {
+ await interaction.reply({ content: "You need to be in a voice channel to use music commands.", ephemeral: true });
+ return;
+ }
+ //collect vc id for loudspeaker assignment test
+ const channelId = interaction.member.voice.channelId;
+ //don't do anything if there's no loudspeaker assigned
+ const loudspeakerAssignmentResult = await interaction.client.functions.get("assignLoudspeaker").execute(channelId, interaction.client.loudspeakers);
+ if (loudspeakerAssignmentResult.status != "already assigned") {
+ await interaction.reply({ content: "There is no loudspeaker in your channel! Please use /join first.", ephemeral: true });
+ return;
+ }
+
+ //user passed latent check
+ //init modal
+ const modal = new ModalBuilder()
+ .setCustomId('enqueue')
+ .setTitle('Enqueue a Song, Playlist, or Search Term');
+
+ //input row
+ const query = new TextInputBuilder()
+ .setRequired(true)
+ .setCustomId('query')
+ .setLabel("Video URL, Playlist URL, or Search")
+ .setStyle(TextInputStyle.Short);
+ const row1 = new ActionRowBuilder().addComponents(query);
+
+ modal.addComponents(row1);
+ await interaction.showModal(modal);
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/enqueueQuery.js b/lib/musicFunctions/enqueueQuery.js
new file mode 100644
index 0000000..13c4b96
--- /dev/null
+++ b/lib/musicFunctions/enqueueQuery.js
@@ -0,0 +1,85 @@
+// https://github.com/fent/node-ytdl-core#readme
+const ytdl = require('ytdl-core');
+// https://github.com/TimeForANinja/node-ytsr
+const ytsr = require('ytsr');
+// https://github.com/TimeForANinja/node-ytpl
+const ytpl = require('ytpl');
+
+module.exports = {
+ name: "enqueueQuery",
+
+ async execute(query, loudspeakerClient) {
+ //append queries to queue
+ const videos = await getQuery(query);
+ Array.prototype.push.apply(loudspeakerClient.queue, videos);
+
+ return videos;
+ }
+}
+
+async function getQuery(query) {
+ //result should be a list of {songName, songURL} that will later be turned into ytdl streams when playback happens
+ const result = [];
+
+ //Function for pushing video objects to the results list
+ const pushVideoInfo = async (url) => {
+ //There's a bug that prevents the below line from working in the base repo.
+ //Use `npm i ytdl-core@npm:@distube/ytdl-core` instead
+ const videoInfo = await ytdl.getInfo(url);
+ result.push({ title: videoInfo.videoDetails.title, url: videoInfo.videoDetails.video_url });
+ }
+
+ //Testing for playlist URL
+ let playlistID;
+ try {
+ playlistID = await ytpl.getPlaylistID(query);
+ }
+ catch (e) {
+ playlistID = null;
+ }
+
+ //if query is a video link
+ if (ytdl.validateURL(query)) {
+ //console.log("Query was video URL");
+ await pushVideoInfo(query);
+ }
+
+ //if query is a playlist link
+ else if (playlistID) {
+ //console.log("Query was playlist URL");
+ //playlist response https://github.com/timeforaninja/node-ytpl/blob/master/example/example_output.txt
+ /*
+ await ytpl(playlistID).then(async playlistResponse => {
+ playlistResponse.items.forEach(async item => {
+ //console.log(`Playlist adding ${item.shortUrl}`);
+ await pushVideoInfo(item.shortUrl);
+ })
+ });
+ */
+ //below boomer way adds them 1 at a time and is much slower but ensures they are in order
+ const response = await ytpl(playlistID);
+ for (item of response.items) {
+ await pushVideoInfo(item.shortUrl);
+ }
+ }
+
+ //query is not a link, seqrch
+ else {
+ //console.log("Query was a search");
+ //search response https://github.com/timeforaninja/node-ytsr/blob/master/example/example_search_output.txt
+ //get the first video in the results and ytdl it
+ //ytsr is very error-prone, try-catch it.
+ try {
+ await ytsr(query).then(async searchResult => {
+ await pushVideoInfo(searchResult.items.filter(item => item.type == 'video')[0].url);
+ });
+ }
+ catch(e){
+ console.log(`MUSIC - [WARN] ytsr for "${query}" encountered an error:\n${e.stack}`);
+ }
+ }
+
+ //result is now a list of {title, url}
+ //result.forEach(item => console.log(item));
+ return result;
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/join.js b/lib/musicFunctions/join.js
new file mode 100644
index 0000000..20b4990
--- /dev/null
+++ b/lib/musicFunctions/join.js
@@ -0,0 +1,40 @@
+
+module.exports = {
+ name: "join",
+
+ async execute(interaction) {
+ //this function does not use the latent loudspeaker check
+ if (!interaction.replied)
+ await interaction.deferReply({ ephemeral: true });
+
+ let response = "";
+
+ if (!interaction.member.voice.channel) {
+ response = "You need to be in a voice channel to use music commands.";
+ if (!interaction.replied)
+ await interaction.followUp(response);
+ return response;
+ }
+
+ //attempt to connect loudspeaker
+ const result = await interaction.client.functions.get("connectLoudspeaker").execute(interaction);
+
+ //respond to the user
+ switch (result.status) {
+ case "no vacancies":
+ response = "Unfortunately there are no vacant loudspeakers at this time.";
+ break;
+ case "already assigned":
+ response = "There is already a loudspeaker in your channel.";
+ break;
+ case "new assignment":
+ response = "Assigned a loudspeaker to your channel."
+ break;
+ }
+
+ if (!interaction.replied)
+ await interaction.followUp(response);
+
+ return response;
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/latentFunctionPrecheck.js b/lib/musicFunctions/latentFunctionPrecheck.js
new file mode 100644
index 0000000..94d1640
--- /dev/null
+++ b/lib/musicFunctions/latentFunctionPrecheck.js
@@ -0,0 +1,38 @@
+
+module.exports = {
+ /**
+ * This function WILL DEFER OR REPLY TO THE INTERACTION!
+ *
+ * This function should:
+ * Check if the user is in a VC
+ * If not, return {inVoiceChannel: false}
+ * Check if a loudspeaker is in the channel
+ * If not, return {inVoiceChannel: true, channelId: , loudspeakerClient: null}
+ * return {inVoiceChannel: true, channelId: , loudspeakerClient: }
+ * @param {*} interaaction
+ * @returns
+ */
+ async execute(interaction){
+ if(!interaction.replied && !interaction.deferred)
+ await interaction.deferReply({ephemeral: true});
+
+ if (!interaction.replied && !interaction.member.voice.channel) {
+ await interaction.followUp({ content: "You need to be in a voice channel to use music commands.", ephemeral: true });
+ return {inVoiceChannel: false};
+ }
+
+ //collect vc id for loudspeaker assignment test
+ const channelId = interaction.member.voice.channelId;
+
+ //don't do anything if there's no loudspeaker assigned
+ const loudspeakerAssignmentResult = await interaction.client.functions.get("assignLoudspeaker").execute(channelId, interaction.client.loudspeakers);
+ if (loudspeakerAssignmentResult.status != "already assigned") {
+ await interaction.followUp({ content: "There is no loudspeaker in your channel! Please use /join first.", ephemeral: true });
+ return {inVoiceChannel: true, channelId: channelId, loudspeakerClient: null};
+ }
+
+ //collect loudspeaker
+ const loudspeakerClient = interaction.client.loudspeakers.get(loudspeakerAssignmentResult.loudspeakerId);
+ return {inVoiceChannel: true, channelId, loudspeakerClient};
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/leave.js b/lib/musicFunctions/leave.js
new file mode 100644
index 0000000..d8286e8
--- /dev/null
+++ b/lib/musicFunctions/leave.js
@@ -0,0 +1,20 @@
+const latentFunctionPrecheck = require("./latentFunctionPrecheck");
+
+module.exports = {
+ name: "leave",
+
+ async execute(interaction) {
+ const guardCheckResponse = await latentFunctionPrecheck.execute(interaction);
+ if (!guardCheckResponse.inVoiceChannel || !guardCheckResponse.loudspeakerClient)
+ return;
+
+ //collect loudspeaker
+ const loudspeakerClient = guardCheckResponse.loudspeakerClient;
+
+ //disconnect the loudspeaker
+ await interaction.client.functions.get('destroyLoudspeaker').execute(loudspeakerClient);
+
+ //respond to the user
+ await interaction.followUp("Loudspeaker disconnected.");
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/loop.js b/lib/musicFunctions/loop.js
new file mode 100644
index 0000000..5b02b01
--- /dev/null
+++ b/lib/musicFunctions/loop.js
@@ -0,0 +1,32 @@
+const latentFunctionPrecheck = require("./latentFunctionPrecheck");
+
+module.exports = {
+ name: "loop",
+
+ async execute(interaction) {
+ const guardCheckResponse = await latentFunctionPrecheck.execute(interaction);
+ if (!guardCheckResponse.inVoiceChannel || !guardCheckResponse.loudspeakerClient)
+ return;
+
+ //collect loudspeaker
+ const loudspeakerClient = guardCheckResponse.loudspeakerClient;
+
+ //if an option is given, set it to that
+ //ternary is for compatibilitiy with button controls; they won't have int.options
+ let choice = interaction.options ? interaction.options.getBoolean('on') : undefined;
+ if (choice) {
+ //special message if loop was already set to that value
+ if (choice == loudspeakerClient.player.loop) {
+ await interaction.followUp(`Loop was already ${choice ? "on" : "off"}.`);
+ return;
+ }
+ loudspeakerClient.player.loop = choice;
+ }
+ //otherwise, toggle the loop
+ else
+ loudspeakerClient.player.loop = !loudspeakerClient.player.loop; //i'm going to hope that !undefined becomes true
+
+ await interaction.followUp(`Loop turned ${loudspeakerClient.player.loop ? "on" : "off"}.`);
+ return ;
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/loopOne.js b/lib/musicFunctions/loopOne.js
new file mode 100644
index 0000000..1c16442
--- /dev/null
+++ b/lib/musicFunctions/loopOne.js
@@ -0,0 +1,19 @@
+const latentFunctionPrecheck = require("./latentFunctionPrecheck");
+
+module.exports = {
+ name: "loopOne",
+
+ async execute(interaction) {
+ const guardCheckResponse = await latentFunctionPrecheck.execute(interaction);
+ if (!guardCheckResponse.inVoiceChannel || !guardCheckResponse.loudspeakerClient)
+ return;
+
+ //collect loudspeaker
+ const loudspeakerClient = guardCheckResponse.loudspeakerClient;
+
+ loudspeakerClient.player.loopOne = !loudspeakerClient.player.loopOne; //i'm going to hope that !undefined becomes true
+
+ await interaction.followUp(`Loop one turned ${loudspeakerClient.player.loopOne ? "on" : "off"}.`);
+ return ;
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/nowPlaying.js b/lib/musicFunctions/nowPlaying.js
new file mode 100644
index 0000000..75e254a
--- /dev/null
+++ b/lib/musicFunctions/nowPlaying.js
@@ -0,0 +1,23 @@
+const latentFunctionPrecheck = require("./latentFunctionPrecheck");
+
+module.exports = {
+ name: "nowPlaying",
+
+ async execute(interaction) {
+ const guardCheckResponse = await latentFunctionPrecheck.execute(interaction);
+ if (!guardCheckResponse.inVoiceChannel || !guardCheckResponse.loudspeakerClient)
+ return;
+
+ //collect queue
+ const queue = guardCheckResponse.loudspeakerClient.queue;
+
+ //special message if the queue is empty
+ if(queue.length == 0){
+ await interaction.followUp("Nothing is playing.");
+ return;
+ }
+
+ //respond with the first song and its link
+ await interaction.followUp(`Now playing: [${queue[0].title}](<${queue[0].url}>)`);
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/pause.js b/lib/musicFunctions/pause.js
new file mode 100644
index 0000000..dc022a1
--- /dev/null
+++ b/lib/musicFunctions/pause.js
@@ -0,0 +1,29 @@
+const latentFunctionPrecheck = require("./latentFunctionPrecheck");
+
+module.exports = {
+ name: "pause",
+
+ async execute(interaction) {
+ const guardCheckResponse = await latentFunctionPrecheck.execute(interaction);
+ if (!guardCheckResponse.inVoiceChannel || !guardCheckResponse.loudspeakerClient)
+ return;
+
+ //collect loudspeaker
+ const loudspeakerClient = guardCheckResponse.loudspeakerClient;
+
+ //do nothing if it's already paused or idle
+ switch (loudspeakerClient.player.state.status) {
+ case "paused":
+ case "autopaused":
+ await interaction.followUp("Already paused.");
+ break;
+ case "idle":
+ await interaction.followUp("Nothing is playing.");
+ break;
+ default:
+ loudspeakerClient.player.pause();
+ await interaction.followUp("Playback paused.");
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/resumePlayback.js b/lib/musicFunctions/resumePlayback.js
new file mode 100644
index 0000000..2586a49
--- /dev/null
+++ b/lib/musicFunctions/resumePlayback.js
@@ -0,0 +1,43 @@
+const latentFunctionPrecheck = require("./latentFunctionPrecheck");
+
+module.exports = {
+ name: "resumePlayback",
+
+ async execute(interaction) {
+ const guardCheckResponse = await latentFunctionPrecheck.execute(interaction);
+ if (!guardCheckResponse.inVoiceChannel || !guardCheckResponse.loudspeakerClient)
+ return;
+
+ //collect loudspeaker
+ const loudspeakerClient = guardCheckResponse.loudspeakerClient;
+
+ //start a response to the user
+ let response = "";
+
+ //don't do anything if the queue is empty
+ if (loudspeakerClient.queue.length == 0) {
+ response = "The queue is empty, playback not resumed.";
+ //if (!interaction.replied && !interaction.deferred)
+ //await interaction.followUp("The queue is empty, playback not resumed.");
+ await interaction.editReply("The queue is empty, playback not resumed.");
+ return response;
+ }
+
+ switch (loudspeakerClient.player.state.status) {
+ case "playing":
+ response = "Already playing.";
+ break;
+ case "idle":
+ interaction.client.functions.get("startNextSong").execute(loudspeakerClient);
+ response = "Beginning playback.";
+ break;
+ case "paused":
+ loudspeakerClient.player.unpause();
+ response = "Playback resumed.";
+ break;
+ }
+
+ await interaction.editReply(response);
+ return response;
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/showQueue.js b/lib/musicFunctions/showQueue.js
new file mode 100644
index 0000000..d1a5be6
--- /dev/null
+++ b/lib/musicFunctions/showQueue.js
@@ -0,0 +1,64 @@
+const latentFunctionPrecheck = require("./latentFunctionPrecheck");
+const { ButtonBuilder, ButtonStyle, ActionRowBuilder } = require("discord.js");
+
+module.exports = {
+ name: "showQueue",
+
+ async execute(interaction) {
+ const guardCheckResponse = await latentFunctionPrecheck.execute(interaction);
+ if (!guardCheckResponse.inVoiceChannel || !guardCheckResponse.loudspeakerClient)
+ return;
+
+ //collect queue
+ const queue = guardCheckResponse.loudspeakerClient.queue;
+
+ //special response if the queue is empty
+ if (queue.length == 0) {
+ await interaction.followUp("The queue is empty.");
+ return;
+ }
+
+ //collect starting point if there is one
+ const startingIndex = /\d+/.exec(interaction.customId) ? /\d+/.exec(interaction.customId) : 0;
+
+ //collect result of tostring and compile response
+ const result = queueToString(queue, startingIndex);
+ const response = `Queue for your channel:\n${result.text}`;
+
+ //show a button if there are still more to show
+ let buttonRow;
+ if(result.lastIndex < queue.length - 1)
+ buttonRow = buildButtonRow(result.lastIndex);
+
+ await interaction.followUp({content: response, components: buttonRow ? [buttonRow] : []});
+ return response;
+ }
+}
+
+function queueToString(queue, startingIndex) {
+ //compile items in the queue starting at 0 if a starting point is not given
+ //we can't show all of them at once because it may exceed the character limit.
+ let text = "";
+ let i;
+ for (i = startingIndex; i < queue.length; i++) {
+ if (text.length >= 1800) {
+ //off by one if this happens after adding the new item
+ text += `..and ${queue.length - i} more tracks.`
+ break;
+ }
+ text += `${i}. [${queue[i].title}](<${queue[i].url}>)\n`;
+ }
+ return { text: text, lastIndex: i };
+}
+
+function buildButtonRow(lastIndex){
+ const row = new ActionRowBuilder()
+ .addComponents(
+ new ButtonBuilder()
+ .setCustomId(`${lastIndex}_showQueue`)
+ .setLabel("Show More")
+ .setStyle(ButtonStyle.Primary)
+ );
+
+ return row;
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/shuffleQueue.js b/lib/musicFunctions/shuffleQueue.js
new file mode 100644
index 0000000..7e14144
--- /dev/null
+++ b/lib/musicFunctions/shuffleQueue.js
@@ -0,0 +1,41 @@
+const latentFunctionPrecheck = require("./latentFunctionPrecheck");
+
+module.exports = {
+ name: "shuffleQueue",
+
+ async execute(interaction) {
+ const guardCheckResponse = await latentFunctionPrecheck.execute(interaction);
+ if (!guardCheckResponse.inVoiceChannel || !guardCheckResponse.loudspeakerClient)
+ return;
+
+ //collect loudspeaker
+ const loudspeakerClient = guardCheckResponse.loudspeakerClient;
+
+ //do nothing if there is nothing to shuffle
+ //not shuffling the first item, so there needs to be at least 3 items
+ if (loudspeakerClient.queue.length <= 2) {
+ let response = "There are too few songs in the queue to shuffle.";
+ await interaction.followUp(response);
+ return response;
+ }
+
+ //shuffle all items except the first
+ //using this algorithm: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
+ const queue = loudspeakerClient.queue;
+ //save and remove the first item
+ const firstItem = queue.shift();
+ //perform shuffle
+ for (let i = queue.length - 1; i >= 0; i--) {
+ const rand = Math.floor(Math.random() * i);
+ const temp = queue[i];
+ queue[i] = queue[rand];
+ queue[rand] = temp;
+ }
+ //replace first item
+ queue.unshift(firstItem);
+
+ let response = "Queue shuffled.";
+ await interaction.followUp(response);
+ return response;
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/skip.js b/lib/musicFunctions/skip.js
new file mode 100644
index 0000000..57c9369
--- /dev/null
+++ b/lib/musicFunctions/skip.js
@@ -0,0 +1,54 @@
+const latentFunctionPrecheck = require("./latentFunctionPrecheck");
+
+module.exports = {
+ name: "skip",
+
+ /**
+ * Skips the current playing song by calling player.stop(). The autoplayer will immediately play the next song in the queue if there is one.
+ * If the playback is paused, it shoud also immediately pause the playback of the new song.
+ * @param {*} interaction
+ * @returns
+ */
+ async execute(interaction) {
+ const guardCheckResponse = await latentFunctionPrecheck.execute(interaction);
+ if (!guardCheckResponse.inVoiceChannel || !guardCheckResponse.loudspeakerClient)
+ return;
+
+ //collect loudspeaker
+ const loudspeakerClient = guardCheckResponse.loudspeakerClient;
+
+ //start a response to the user
+ let response = "";
+
+ //do nothing if the queue is empty
+ if(loudspeakerClient.queue.length == 0){
+ response = "The queue is empty; there is nothing to skip."
+ await interaction.followUp(response);
+ return response;
+ }
+
+ response = "Current song skipped.";
+ if(loudspeakerClient.queue.length > 1)
+ response += `\nNow playing [${loudspeakerClient.queue[1].title}](<${loudspeakerClient.queue[1].url}>).`;
+
+ //start playing the song really quick so that stop() sets the player to the idle state, triggering autoplay
+ loudspeakerClient.player.unpause();
+ //if the user wants the next song to be paused, set that now
+ //if there's no other song in the list, don't bother doing this
+ //ternary for compatibiltiy with music button controls
+ const pauseChoice = interaction.options ? interaction.options.getBoolean('pause') : undefined;
+ if(pauseChoice && loudspeakerClient.queue.length > 1){
+ loudspeakerClient.player.pauseOnNextPlay = true;
+ response += "\nThe next song will be paused.";
+ }
+ //edge case: if loop is on, queue has exactly 1 song, and skip is used, the song should not be readded to the queue
+ if(loudspeakerClient.queue.length == 1 && loudspeakerClient.player.loop)
+ loudspeakerClient.player.loopNoReadd = true;
+
+ //stop the player which will load the next song
+ await loudspeakerClient.player.stop();
+
+ await interaction.followUp(response);
+ return response;
+ }
+}
\ No newline at end of file
diff --git a/lib/musicFunctions/startNextSong.js b/lib/musicFunctions/startNextSong.js
new file mode 100644
index 0000000..886f93f
--- /dev/null
+++ b/lib/musicFunctions/startNextSong.js
@@ -0,0 +1,40 @@
+// https://github.com/fent/node-ytdl-core#readme
+const ytdl = require('ytdl-core');
+
+//ytdl causes an error with nodejs v16, use this instead
+//https://github.com/microlinkhq/youtube-dl-exec
+const youtubedl = require('youtube-dl-exec');
+
+const { createAudioResource } = require('@discordjs/voice')
+
+module.exports = {
+ name: "startNextSong",
+
+ async execute(loudspeakerClient) {
+ //the song at the front of the queue should be removed by the caller.
+ //collect song at queue front
+ const song = loudspeakerClient.queue[0];
+ //download stream
+ loudspeakerClient.songStream = ytdl(song.url, { filter: "audioonly" });
+ /*
+ loudspeakerClient.songStream = youtubedl(song.url, {
+ o: '-',
+ q: '',
+ f: 'bestaudio[ext=webm+acodec=opus+asr=48000]/bestaudio',
+ r: '100K',
+ },
+ {
+ stdio: ['ignore', 'pipe', 'ignore']
+ });
+ */
+
+ //https://discordjs.guide/voice/audio-player.html#playing-audio
+ //play audio
+ //create audio resource
+ const resource = createAudioResource(loudspeakerClient.songStream);
+ //play source
+ loudspeakerClient.player.play(resource);
+ //subscribe to player
+ loudspeakerClient.connection.subscribe(loudspeakerClient.player);
+ }
+}
\ No newline at end of file
diff --git a/node_modules/.bin/node-which b/node_modules/.bin/node-which
new file mode 100644
index 0000000..aece735
--- /dev/null
+++ b/node_modules/.bin/node-which
@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../which/bin/node-which" "$@"
+else
+ exec node "$basedir/../which/bin/node-which" "$@"
+fi
diff --git a/node_modules/.bin/node-which.cmd b/node_modules/.bin/node-which.cmd
new file mode 100644
index 0000000..8738aed
--- /dev/null
+++ b/node_modules/.bin/node-which.cmd
@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+ SET "_prog=%dp0%\node.exe"
+) ELSE (
+ SET "_prog=node"
+ SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\which\bin\node-which" %*
diff --git a/node_modules/.bin/node-which.ps1 b/node_modules/.bin/node-which.ps1
new file mode 100644
index 0000000..cfb09e8
--- /dev/null
+++ b/node_modules/.bin/node-which.ps1
@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+ # Fix case when both the Windows and Linux builds of Node
+ # are installed in the same directory
+ $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+ # Support pipeline input
+ if ($MyInvocation.ExpectingInput) {
+ $input | & "$basedir/node$exe" "$basedir/../which/bin/node-which" $args
+ } else {
+ & "$basedir/node$exe" "$basedir/../which/bin/node-which" $args
+ }
+ $ret=$LASTEXITCODE
+} else {
+ # Support pipeline input
+ if ($MyInvocation.ExpectingInput) {
+ $input | & "node$exe" "$basedir/../which/bin/node-which" $args
+ } else {
+ & "node$exe" "$basedir/../which/bin/node-which" $args
+ }
+ $ret=$LASTEXITCODE
+}
+exit $ret
diff --git a/node_modules/.bin/semver b/node_modules/.bin/semver
new file mode 100644
index 0000000..77443e7
--- /dev/null
+++ b/node_modules/.bin/semver
@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../semver/bin/semver.js" "$@"
+else
+ exec node "$basedir/../semver/bin/semver.js" "$@"
+fi
diff --git a/node_modules/.bin/semver.cmd b/node_modules/.bin/semver.cmd
new file mode 100644
index 0000000..9913fa9
--- /dev/null
+++ b/node_modules/.bin/semver.cmd
@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+ SET "_prog=%dp0%\node.exe"
+) ELSE (
+ SET "_prog=node"
+ SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver.js" %*
diff --git a/node_modules/.bin/semver.ps1 b/node_modules/.bin/semver.ps1
new file mode 100644
index 0000000..314717a
--- /dev/null
+++ b/node_modules/.bin/semver.ps1
@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+ # Fix case when both the Windows and Linux builds of Node
+ # are installed in the same directory
+ $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+ # Support pipeline input
+ if ($MyInvocation.ExpectingInput) {
+ $input | & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
+ } else {
+ & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
+ }
+ $ret=$LASTEXITCODE
+} else {
+ # Support pipeline input
+ if ($MyInvocation.ExpectingInput) {
+ $input | & "node$exe" "$basedir/../semver/bin/semver.js" $args
+ } else {
+ & "node$exe" "$basedir/../semver/bin/semver.js" $args
+ }
+ $ret=$LASTEXITCODE
+}
+exit $ret
diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
index c6ca8da..b737e71 100644
--- a/node_modules/.package-lock.json
+++ b/node_modules/.package-lock.json
@@ -1,83 +1,104 @@
{
"name": "caroline",
"version": "1.0.0",
- "lockfileVersion": 2,
+ "lockfileVersion": 3,
"requires": true,
"packages": {
- "node_modules/@discord-player/equalizer": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@discord-player/equalizer/-/equalizer-0.1.3.tgz",
- "integrity": "sha512-cfHFTW7DCZNgFeFKNlBtWK6DzCaOlxZ5KnnY7jdbm3xQreyJnEt8iuv6hyBRUSjSlP98DI8K4KIC5xr/zP57AQ=="
- },
"node_modules/@discordjs/builders": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.4.0.tgz",
- "integrity": "sha512-nEeTCheTTDw5kO93faM1j8ZJPonAX86qpq/QVoznnSa8WWcCgJpjlu6GylfINTDW6o7zZY0my2SYdxx2mfNwGA==",
- "dependencies": {
- "@discordjs/util": "^0.1.0",
- "@sapphire/shapeshift": "^3.7.1",
- "discord-api-types": "^0.37.20",
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.6.3.tgz",
+ "integrity": "sha512-CTCh8NqED3iecTNuiz49mwSsrc2iQb4d0MjMdmS/8pb69Y4IlzJ/DIy/p5GFlgOrFbNO2WzMHkWKQSiJ3VNXaw==",
+ "dependencies": {
+ "@discordjs/formatters": "^0.3.1",
+ "@discordjs/util": "^0.3.1",
+ "@sapphire/shapeshift": "^3.8.2",
+ "discord-api-types": "^0.37.41",
"fast-deep-equal": "^3.1.3",
- "ts-mixer": "^6.0.2",
- "tslib": "^2.4.1"
+ "ts-mixer": "^6.0.3",
+ "tslib": "^2.5.0"
},
"engines": {
"node": ">=16.9.0"
}
},
"node_modules/@discordjs/collection": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.3.0.tgz",
- "integrity": "sha512-ylt2NyZ77bJbRij4h9u/wVy7qYw/aDqQLWnadjvDqW/WoWCxrsX6M3CIw9GVP5xcGCDxsrKj5e0r5evuFYwrKg==",
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.1.tgz",
+ "integrity": "sha512-aWEc9DCf3TMDe9iaJoOnO2+JVAjeRNuRxPZQA6GVvBf+Z3gqUuWYBy2NWh4+5CLYq5uoc3MOvUQ5H5m8CJBqOA==",
+ "engines": {
+ "node": ">=16.9.0"
+ }
+ },
+ "node_modules/@discordjs/formatters": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.3.1.tgz",
+ "integrity": "sha512-M7X4IGiSeh4znwcRGcs+49B5tBkNDn4k5bmhxJDAUhRxRHTiFAOTVUNQ6yAKySu5jZTnCbSvTYHW3w0rAzV1MA==",
+ "dependencies": {
+ "discord-api-types": "^0.37.41"
+ },
"engines": {
"node": ">=16.9.0"
}
},
"node_modules/@discordjs/rest": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.5.0.tgz",
- "integrity": "sha512-lXgNFqHnbmzp5u81W0+frdXN6Etf4EUi8FAPcWpSykKd8hmlWh1xy6BmE0bsJypU1pxohaA8lQCgp70NUI3uzA==",
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.7.1.tgz",
+ "integrity": "sha512-Ofa9UqT0U45G/eX86cURQnX7gzOJLG2oC28VhIk/G6IliYgQF7jFByBJEykPSHE4MxPhqCleYvmsrtfKh1nYmQ==",
"dependencies": {
- "@discordjs/collection": "^1.3.0",
- "@discordjs/util": "^0.1.0",
+ "@discordjs/collection": "^1.5.1",
+ "@discordjs/util": "^0.3.0",
"@sapphire/async-queue": "^1.5.0",
- "@sapphire/snowflake": "^3.2.2",
- "discord-api-types": "^0.37.23",
- "file-type": "^18.0.0",
- "tslib": "^2.4.1",
- "undici": "^5.13.0"
+ "@sapphire/snowflake": "^3.4.2",
+ "discord-api-types": "^0.37.41",
+ "file-type": "^18.3.0",
+ "tslib": "^2.5.0",
+ "undici": "^5.22.0"
},
"engines": {
"node": ">=16.9.0"
}
},
"node_modules/@discordjs/util": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.1.0.tgz",
- "integrity": "sha512-e7d+PaTLVQav6rOc2tojh2y6FE8S7REkqLldq1XF4soCx74XB/DIjbVbVLtBemf0nLW77ntz0v+o5DytKwFNLQ==",
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.3.1.tgz",
+ "integrity": "sha512-HxXKYKg7vohx2/OupUN/4Sd02Ev3PBJ5q0gtjdcvXb0ErCva8jNHWfe/v5sU3UKjIB/uxOhc+TDOnhqffj9pRA==",
"engines": {
"node": ">=16.9.0"
}
},
"node_modules/@discordjs/voice": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.11.0.tgz",
- "integrity": "sha512-6+9cj1dxzBJm7WJ9qyG2XZZQ8rcLl6x2caW0C0OxuTtMLAaEDntpb6lqMTFiBg/rDc4Rd59g1w0gJmib33CuHw==",
+ "version": "0.16.0",
+ "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.16.0.tgz",
+ "integrity": "sha512-ToGCvHD1cBscuW3p+C7zOF5+L7MJmU4GjdOARfNk9mkHyFFZq4grK+Sxr3QXKbp27DtfDBc9uqD4GUOYgxngfA==",
"dependencies": {
- "@types/ws": "^8.5.3",
- "discord-api-types": "^0.36.2",
- "prism-media": "^1.3.4",
- "tslib": "^2.4.0",
- "ws": "^8.8.1"
+ "@types/ws": "^8.5.4",
+ "discord-api-types": "^0.37.37",
+ "prism-media": "^1.3.5",
+ "tslib": "^2.5.0",
+ "ws": "^8.13.0"
},
"engines": {
"node": ">=16.9.0"
}
},
- "node_modules/@discordjs/voice/node_modules/discord-api-types": {
- "version": "0.36.3",
- "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.36.3.tgz",
- "integrity": "sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg=="
+ "node_modules/@discordjs/ws": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-0.8.3.tgz",
+ "integrity": "sha512-hcYtppanjHecbdNyCKQNH2I4RP9UrphDgmRgLYrATEQF1oo4sYSve7ZmGsBEXSzH72MO2tBPdWSThunbxUVk0g==",
+ "dependencies": {
+ "@discordjs/collection": "^1.5.1",
+ "@discordjs/rest": "^1.7.1",
+ "@discordjs/util": "^0.3.1",
+ "@sapphire/async-queue": "^1.5.0",
+ "@types/ws": "^8.5.4",
+ "@vladfrangu/async_event_emitter": "^2.2.1",
+ "discord-api-types": "^0.37.41",
+ "tslib": "^2.5.0",
+ "ws": "^8.13.0"
+ },
+ "engines": {
+ "node": ">=16.9.0"
+ }
},
"node_modules/@sapphire/async-queue": {
"version": "1.5.0",
@@ -89,9 +110,9 @@
}
},
"node_modules/@sapphire/shapeshift": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.8.1.tgz",
- "integrity": "sha512-xG1oXXBhCjPKbxrRTlox9ddaZTvVpOhYLmKmApD/vIWOV1xEYXnpoFs68zHIZBGbqztq6FrUPNPerIrO1Hqeaw==",
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.0.tgz",
+ "integrity": "sha512-iJpHmjAdwX9aSL6MvFpVyo+tkokDtInmSjoJHbz/k4VJfnim3DjvG0hgGEKWtWZgCu45RaLgcoNgR1fCPdIz3w==",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"lodash": "^4.17.21"
@@ -102,9 +123,9 @@
}
},
"node_modules/@sapphire/snowflake": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.3.0.tgz",
- "integrity": "sha512-Hec5N6zEkZuZFLybVKyLFLlcSgYmR6C1/+9NkIhxPwOf6tgX52ndJCSz8ADejmbrNE0VuNCNkpzhRZzenEC9vA==",
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz",
+ "integrity": "sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==",
"engines": {
"node": ">=v14.0.0",
"npm": ">=7.0.0"
@@ -116,214 +137,153 @@
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="
},
"node_modules/@types/node": {
- "version": "18.11.16",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.16.tgz",
- "integrity": "sha512-6T7P5bDkRhqRxrQtwj7vru+bWTpelgtcETAZEUSdq0YISKz8WKdoBukQLYQQ6DFHvU9JRsbFq0JH5C51X2ZdnA=="
+ "version": "20.2.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.1.tgz",
+ "integrity": "sha512-DqJociPbZP1lbZ5SQPk4oag6W7AyaGMO6gSfRwq3PWl4PXTwJpRQJhDq4W0kzrg3w6tJ1SwlvGZ5uKFHY13LIg=="
},
"node_modules/@types/ws": {
- "version": "8.5.3",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
- "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==",
+ "version": "8.5.4",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz",
+ "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==",
"dependencies": {
"@types/node": "*"
}
},
- "node_modules/boolbase": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
- "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
- "peer": true
- },
- "node_modules/busboy": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
- "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
- "dependencies": {
- "streamsearch": "^1.1.0"
- },
+ "node_modules/@vladfrangu/async_event_emitter": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.2.tgz",
+ "integrity": "sha512-HIzRG7sy88UZjBJamssEczH5q7t5+axva19UbZLO6u0ySbYPrwzWiXBcC0WuHyhKKoeCyneH+FvYzKQq/zTtkQ==",
"engines": {
- "node": ">=10.16.0"
+ "node": ">=v14.0.0",
+ "npm": ">=7.0.0"
}
},
- "node_modules/cheerio": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
- "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==",
- "peer": true,
+ "node_modules/bin-version": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-6.0.0.tgz",
+ "integrity": "sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw==",
"dependencies": {
- "cheerio-select": "^2.1.0",
- "dom-serializer": "^2.0.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.0.1",
- "htmlparser2": "^8.0.1",
- "parse5": "^7.0.0",
- "parse5-htmlparser2-tree-adapter": "^7.0.0"
+ "execa": "^5.0.0",
+ "find-versions": "^5.0.0"
},
"engines": {
- "node": ">= 6"
+ "node": ">=12"
},
"funding": {
- "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/cheerio-select": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
- "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
- "peer": true,
+ "node_modules/bin-version-check": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-5.0.0.tgz",
+ "integrity": "sha512-Q3FMQnS5eZmrBGqmDXLs4dbAn/f+52voP6ykJYmweSA60t6DyH4UTSwZhtbK5UH+LBoWvDljILUQMLRUtsynsA==",
"dependencies": {
- "boolbase": "^1.0.0",
- "css-select": "^5.1.0",
- "css-what": "^6.1.0",
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.0.1"
+ "bin-version": "^6.0.0",
+ "semver": "^7.3.5",
+ "semver-truncate": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
},
"funding": {
- "url": "https://github.com/sponsors/fb55"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/css-select": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
- "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
- "peer": true,
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
"dependencies": {
- "boolbase": "^1.0.0",
- "css-what": "^6.1.0",
- "domhandler": "^5.0.2",
- "domutils": "^3.0.1",
- "nth-check": "^2.0.1"
+ "streamsearch": "^1.1.0"
},
- "funding": {
- "url": "https://github.com/sponsors/fb55"
- }
- },
- "node_modules/css-what": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
- "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
- "peer": true,
"engines": {
- "node": ">= 6"
- },
- "funding": {
- "url": "https://github.com/sponsors/fb55"
+ "node": ">=10.16.0"
}
},
- "node_modules/discord-api-types": {
- "version": "0.37.23",
- "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.23.tgz",
- "integrity": "sha512-IixodMf9PjOSrsPorbti5aGv6sJVSPJybAlFMYsYDQXFS7zJyhSmA/ofpPTR9ZYqL1KEDY+xU74oZgBQa52eSQ=="
- },
- "node_modules/discord-player": {
- "version": "5.4.0",
- "resolved": "https://registry.npmjs.org/discord-player/-/discord-player-5.4.0.tgz",
- "integrity": "sha512-Hrab+4aNCZCGJwsGkiQx+nfvJNqMEr9T+vEAzTOybWJ83InJOxUK7t6muVqHlkonmXBM/nVOczWs2qacDlRH6g==",
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dependencies": {
- "@discord-player/equalizer": "^0.1.2",
- "@discordjs/voice": "^0.11.0",
- "libsodium-wrappers": "^0.7.10",
- "tiny-typed-emitter": "^2.1.0",
- "tslib": "^2.4.0"
- },
- "funding": {
- "url": "https://github.com/Androz2091/discord-player?sponsor=1"
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
},
- "peerDependencies": {
- "soundcloud-scraper": "5.x",
- "spotify-url-info": "3.x",
- "youtube-sr": "4.x",
- "ytdl-core": "4.x"
+ "engines": {
+ "node": ">= 8"
}
},
- "node_modules/discord.js": {
- "version": "14.7.1",
- "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.7.1.tgz",
- "integrity": "sha512-1FECvqJJjjeYcjSm0IGMnPxLqja/pmG1B0W2l3lUY2Gi4KXiyTeQmU1IxWcbXHn2k+ytP587mMWqva2IA87EbA==",
- "dependencies": {
- "@discordjs/builders": "^1.4.0",
- "@discordjs/collection": "^1.3.0",
- "@discordjs/rest": "^1.4.0",
- "@discordjs/util": "^0.1.0",
- "@sapphire/snowflake": "^3.2.2",
- "@types/ws": "^8.5.3",
- "discord-api-types": "^0.37.20",
- "fast-deep-equal": "^3.1.3",
- "lodash.snakecase": "^4.1.1",
- "tslib": "^2.4.1",
- "undici": "^5.13.0",
- "ws": "^8.11.0"
- },
+ "node_modules/dargs": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
+ "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==",
"engines": {
- "node": ">=16.9.0"
+ "node": ">=8"
}
},
- "node_modules/dom-serializer": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
- "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
- "peer": true,
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
"dependencies": {
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.2",
- "entities": "^4.2.0"
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/domelementtype": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
- "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fb55"
- }
- ],
- "peer": true
+ "node_modules/discord-api-types": {
+ "version": "0.37.43",
+ "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.43.tgz",
+ "integrity": "sha512-bBhDWU3TF9KADxR/mHp1K4Bvu/LRtFQdGyBjADu4e66F3ZnD4kp12W/SJCttIaCcMXzPV3sfty6eDGRNRph51Q=="
},
- "node_modules/domhandler": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
- "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
- "peer": true,
- "dependencies": {
- "domelementtype": "^2.3.0"
+ "node_modules/discord.js": {
+ "version": "14.11.0",
+ "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.11.0.tgz",
+ "integrity": "sha512-CkueWYFQ28U38YPR8HgsBR/QT35oPpMbEsTNM30Fs8loBIhnA4s70AwQEoy6JvLcpWWJO7GY0y2BUzZmuBMepQ==",
+ "dependencies": {
+ "@discordjs/builders": "^1.6.3",
+ "@discordjs/collection": "^1.5.1",
+ "@discordjs/formatters": "^0.3.1",
+ "@discordjs/rest": "^1.7.1",
+ "@discordjs/util": "^0.3.1",
+ "@discordjs/ws": "^0.8.3",
+ "@sapphire/snowflake": "^3.4.2",
+ "@types/ws": "^8.5.4",
+ "discord-api-types": "^0.37.41",
+ "fast-deep-equal": "^3.1.3",
+ "lodash.snakecase": "^4.1.1",
+ "tslib": "^2.5.0",
+ "undici": "^5.22.0",
+ "ws": "^8.13.0"
},
"engines": {
- "node": ">= 4"
- },
- "funding": {
- "url": "https://github.com/fb55/domhandler?sponsor=1"
+ "node": ">=16.9.0"
}
},
- "node_modules/domutils": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
- "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
- "peer": true,
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
"dependencies": {
- "dom-serializer": "^2.0.0",
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.1"
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
},
- "funding": {
- "url": "https://github.com/fb55/domutils?sponsor=1"
- }
- },
- "node_modules/entities": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
- "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
- "peer": true,
"engines": {
- "node": ">=0.12"
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
"node_modules/fast-deep-equal": {
@@ -332,9 +292,9 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/file-type": {
- "version": "18.0.0",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.0.0.tgz",
- "integrity": "sha512-jjMwFpnW8PKofLE/4ohlhqwDk5k0NC6iy0UHAJFKoY1fQeGMN0GDdLgHQrvCbSpMwbqzoCZhRI5dETCZna5qVA==",
+ "version": "18.4.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.4.0.tgz",
+ "integrity": "sha512-o6MQrZKTAK6WpvmQk3jqTVUmqxYBxW5bloUfrdH1ZnRFDvvAPNr+l+rgOxM3nkqWT+3khaj3FRMDydWe0xhu+w==",
"dependencies": {
"readable-web-to-node-stream": "^3.0.2",
"strtok3": "^7.0.0",
@@ -347,29 +307,37 @@
"url": "https://github.com/sindresorhus/file-type?sponsor=1"
}
},
- "node_modules/himalaya": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/himalaya/-/himalaya-1.1.0.tgz",
- "integrity": "sha512-LLase1dHCRMel68/HZTFft0N0wti0epHr3nNY7ynpLbyZpmrKMQ8YIpiOV77TM97cNpC8Wb2n6f66IRggwdWPw==",
- "peer": true
- },
- "node_modules/htmlparser2": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz",
- "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==",
- "funding": [
- "https://github.com/fb55/htmlparser2?sponsor=1",
- {
- "type": "github",
- "url": "https://github.com/sponsors/fb55"
- }
- ],
- "peer": true,
+ "node_modules/find-versions": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz",
+ "integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==",
"dependencies": {
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.2",
- "domutils": "^3.0.1",
- "entities": "^4.3.0"
+ "semver-regex": "^4.0.5"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "engines": {
+ "node": ">=10.17.0"
}
},
"node_modules/ieee754": {
@@ -396,17 +364,41 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-unix": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/is-unix/-/is-unix-2.0.7.tgz",
+ "integrity": "sha512-5aio7Qef7QKjQxdb52cXAmim9Bh3+y3yc9IA2IsXWwZVlc1rRsJHWtBxNwGBu9KqW7PJCbhepNIkfFdilRkHpQ==",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
"node_modules/libsodium": {
- "version": "0.7.10",
- "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.10.tgz",
- "integrity": "sha512-eY+z7hDrDKxkAK+QKZVNv92A5KYkxfvIshtBJkmg5TSiCnYqZP3i9OO9whE79Pwgm4jGaoHgkM4ao/b9Cyu4zQ=="
+ "version": "0.7.11",
+ "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.11.tgz",
+ "integrity": "sha512-WPfJ7sS53I2s4iM58QxY3Inb83/6mjlYgcmZs7DJsvDlnmVUwNinBCi5vBT43P6bHRy01O4zsMU2CoVR6xJ40A=="
},
"node_modules/libsodium-wrappers": {
- "version": "0.7.10",
- "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz",
- "integrity": "sha512-pO3F1Q9NPLB/MWIhehim42b/Fwb30JNScCNh8TcQ/kIc+qGLQch8ag8wb0keK3EP5kbGakk1H8Wwo7v+36rNQg==",
+ "version": "0.7.11",
+ "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.11.tgz",
+ "integrity": "sha512-SrcLtXj7BM19vUKtQuyQKiQCRJPgbpauzl3s0rSwD+60wtHqSUuqcoawlMDheCJga85nKOQwxNYQxf/CKAvs6Q==",
"dependencies": {
- "libsodium": "^0.7.0"
+ "libsodium": "^0.7.11"
}
},
"node_modules/lodash": {
@@ -419,11 +411,21 @@
"resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
"integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
},
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/m3u8stream": {
"version": "0.8.6",
"resolved": "https://registry.npmjs.org/m3u8stream/-/m3u8stream-0.8.6.tgz",
"integrity": "sha512-LZj8kIVf9KCphiHmH7sbFQTVe4tOemb202fWwvJwR9W5ENW/1hxJN6ksAWGhQgSBSa3jyWhnjKU1Fw1GaOdbyA==",
- "peer": true,
"dependencies": {
"miniget": "^4.2.2",
"sax": "^1.2.4"
@@ -432,70 +434,77 @@
"node": ">=12"
}
},
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/miniget": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/miniget/-/miniget-4.2.2.tgz",
"integrity": "sha512-a7voNL1N5lDMxvTMExOkg+Fq89jM2vY8pAi9ZEWzZtfNmdfP6RXkvUtFnCAXoCv2T9k1v/fUJVaAEuepGcvLYA==",
- "peer": true,
"engines": {
"node": ">=12"
}
},
- "node_modules/node-fetch": {
- "version": "2.6.8",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz",
- "integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==",
- "peer": true,
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
"dependencies": {
- "whatwg-url": "^5.0.0"
+ "path-key": "^3.0.0"
},
"engines": {
- "node": "4.x || >=6.0.0"
- },
- "peerDependencies": {
- "encoding": "^0.1.0"
- },
- "peerDependenciesMeta": {
- "encoding": {
- "optional": true
- }
+ "node": ">=8"
}
},
- "node_modules/nth-check": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
- "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
- "peer": true,
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
- "boolbase": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/fb55/nth-check?sponsor=1"
+ "wrappy": "1"
}
},
- "node_modules/parse5": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
- "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
- "peer": true,
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"dependencies": {
- "entities": "^4.4.0"
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
},
"funding": {
- "url": "https://github.com/inikulin/parse5?sponsor=1"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/parse5-htmlparser2-tree-adapter": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz",
- "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==",
- "peer": true,
- "dependencies": {
- "domhandler": "^5.0.2",
- "parse5": "^7.0.0"
- },
- "funding": {
- "url": "https://github.com/inikulin/parse5?sponsor=1"
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "engines": {
+ "node": ">=8"
}
},
"node_modules/peek-readable": {
@@ -511,11 +520,11 @@
}
},
"node_modules/prism-media": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.4.tgz",
- "integrity": "sha512-eW7LXORkTCQznZs+eqe9VjGOrLBxcBPXgNyHXMTSRVhphvd/RrxgIR7WaWt4fkLuhshcdT5KHL88LAfcvS3f5g==",
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.5.tgz",
+ "integrity": "sha512-IQdl0Q01m4LrkN1EGIE9lphov5Hy7WWlH6ulf5QdGePLlPas9p2mhgddTEHrlaXYjjFToM1/rWuwF37VF4taaA==",
"peerDependencies": {
- "@discordjs/opus": "^0.8.0",
+ "@discordjs/opus": ">=0.8.0 <1.0.0",
"ffmpeg-static": "^5.0.2 || ^4.2.7 || ^3.0.0 || ^2.4.0",
"node-opus": "^0.3.3",
"opusscript": "^0.0.8"
@@ -536,9 +545,9 @@
}
},
"node_modules/readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
- "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
@@ -585,40 +594,117 @@
"node_modules/sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
- "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
- "peer": true
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
- "node_modules/soundcloud-scraper": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/soundcloud-scraper/-/soundcloud-scraper-5.0.3.tgz",
- "integrity": "sha512-AmS9KmK7mMaPVzHzBk40rANpAttZila3+iAet6EA47EeiTBUzVwjq4B+1LCOLtgPmzDSGk0qn+LZOEd5UhnZTQ==",
- "peer": true,
+ "node_modules/semver": {
+ "version": "7.5.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
+ "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
"dependencies": {
- "cheerio": "^1.0.0-rc.10",
- "m3u8stream": "^0.8.4",
- "node-fetch": "^2.6.1"
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
}
},
- "node_modules/spotify-uri": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/spotify-uri/-/spotify-uri-3.0.3.tgz",
- "integrity": "sha512-mMstJ4dAMki6GbUjg94kp/h9ZH+7T7+ro/KUC00WVh+WKoLgMRrTKLkWMIwCZNO53Xa8DRHQw/6jwYtRZrVI3g==",
- "peer": true,
+ "node_modules/semver-regex": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz",
+ "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==",
"engines": {
- "node": ">= 12"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/spotify-url-info": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/spotify-url-info/-/spotify-url-info-3.2.3.tgz",
- "integrity": "sha512-h7LCEM86kE68uWWAW0+NbKP+33qPC00SsbdJXzvmzNc18aIA/NukTi8gKZKEwHBENusLX0VRsHfIhyKDg7Fong==",
- "peer": true,
+ "node_modules/semver-truncate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-2.0.0.tgz",
+ "integrity": "sha512-Rh266MLDYNeML5h90ttdMwfXe1+Nc4LAWd9X1KdJe8pPHP4kFmvLZALtsMNHNdvTyQygbEC0D59sIz47DIaq8w==",
"dependencies": {
- "himalaya": "~1.1.0",
- "spotify-uri": "~3.0.3"
+ "semver": "^6.0.0"
},
"engines": {
- "node": ">= 12"
+ "node": ">=8"
+ }
+ },
+ "node_modules/semver-truncate/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ },
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
}
},
"node_modules/streamsearch": {
@@ -637,6 +723,14 @@
"safe-buffer": "~5.2.0"
}
},
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/strtok3": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz",
@@ -653,11 +747,6 @@
"url": "https://github.com/sponsors/Borewit"
}
},
- "node_modules/tiny-typed-emitter": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz",
- "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA=="
- },
"node_modules/token-types": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz",
@@ -674,31 +763,25 @@
"url": "https://github.com/sponsors/Borewit"
}
},
- "node_modules/tr46": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
- "peer": true
- },
"node_modules/ts-mixer": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.2.tgz",
- "integrity": "sha512-zvHx3VM83m2WYCE8XL99uaM7mFwYSkjR2OZti98fabHrwkjsCvgwChda5xctein3xGOyaQhtTeDq/1H/GNvF3A=="
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz",
+ "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ=="
},
"node_modules/tslib": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
- "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.1.tgz",
+ "integrity": "sha512-KaI6gPil5m9vF7DKaoXxx1ia9fxS4qG5YveErRRVknPDXXriu5M8h48YRjB6h5ZUOKuAKlSJYb0GaDe8I39fRw=="
},
"node_modules/undici": {
- "version": "5.14.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-5.14.0.tgz",
- "integrity": "sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ==",
+ "version": "5.22.1",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz",
+ "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==",
"dependencies": {
"busboy": "^1.6.0"
},
"engines": {
- "node": ">=12.18"
+ "node": ">=14.0"
}
},
"node_modules/util-deprecate": {
@@ -706,32 +789,35 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
- "node_modules/webidl-conversions": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
- "peer": true
- },
- "node_modules/whatwg-url": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
- "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "peer": true,
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dependencies": {
- "tr46": "~0.0.3",
- "webidl-conversions": "^3.0.0"
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
}
},
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
"node_modules/ws": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
- "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
+ "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
- "utf-8-validate": "^5.0.2"
+ "utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
@@ -742,25 +828,63 @@
}
}
},
- "node_modules/youtube-sr": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/youtube-sr/-/youtube-sr-4.3.4.tgz",
- "integrity": "sha512-olSYcR80XigutCrePEXBX3/RJJrWfonJQj7+/ggBiWU0CzTDLE1q8+lpWTWCG0JpzhzILp/IB/Bq/glGqqr1TQ==",
- "peer": true
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
+ "node_modules/youtube-dl-exec": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/youtube-dl-exec/-/youtube-dl-exec-2.4.4.tgz",
+ "integrity": "sha512-vCBdcY3IK3//wZbJDPOVVufZpYNCylaUSGB/PzgU/5jJqUqJlpVdw8Qt4RA770dT18mN7PfBD7zOOlmkTTEh0A==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "bin-version-check": "~5.0.0",
+ "dargs": "~7.0.0",
+ "execa": "~5.1.0",
+ "is-unix": "~2.0.1",
+ "simple-get": "~4.0.1"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
},
"node_modules/ytdl-core": {
- "version": "4.11.2",
- "resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.11.2.tgz",
- "integrity": "sha512-D939t9b4ZzP3v0zDvehR2q+KgG97UTgrTKju3pOPGQcXtl4W6W5z0EpznzcJFu+OOpl7S7Ge8hv8zU65QnxYug==",
- "peer": true,
+ "name": "@distube/ytdl-core",
+ "version": "4.11.10",
+ "resolved": "https://registry.npmjs.org/@distube/ytdl-core/-/ytdl-core-4.11.10.tgz",
+ "integrity": "sha512-WS7d2N5vA9ptPNaA1hOMkhSs72dJYJ7U4PxLwq0ZLnnJ1JMhdjS2b+xjTinMW9vNNcq4YTcF7pa/GR5hmbcaBw==",
"dependencies": {
"m3u8stream": "^0.8.6",
"miniget": "^4.2.2",
- "sax": "^1.1.3"
+ "sax": "^1.2.4",
+ "undici": "^5.22.1"
},
"engines": {
"node": ">=12"
}
+ },
+ "node_modules/ytpl": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/ytpl/-/ytpl-2.3.0.tgz",
+ "integrity": "sha512-Cfw2rxq3PFK6qgWr2Z8gsRefVahEzbn9XEuiJldqdXHE6GhO7kTfEvbZKdfXing1SmgW635uJ/UL2g8r0fvu2Q==",
+ "dependencies": {
+ "miniget": "^4.2.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ytsr": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/ytsr/-/ytsr-3.8.2.tgz",
+ "integrity": "sha512-J+t+a1Ic6jL0Hd0zGX8eFn3uEKtXTf6naa96KO0q7H00GKBfCG8aXW55NAMnaBeUi9Hni6u1xKnf8xZF2F0E/A==",
+ "dependencies": {
+ "miniget": "^4.2.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
}
}
}
diff --git a/node_modules/@discord-player/equalizer/LICENSE b/node_modules/@discord-player/equalizer/LICENSE
deleted file mode 100644
index eceb839..0000000
--- a/node_modules/@discord-player/equalizer/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2023 Androz2091
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
\ No newline at end of file
diff --git a/node_modules/@discord-player/equalizer/README.md b/node_modules/@discord-player/equalizer/README.md
deleted file mode 100644
index 7d05b9e..0000000
--- a/node_modules/@discord-player/equalizer/README.md
+++ /dev/null
@@ -1,74 +0,0 @@
-# `@discord-player/equalizer`
-
-This library implements Lavaplayer's 15 Band PCM Equalizer & biquad utilities.
-
-## Installation
-
-```sh
-$ npm install --save @discord-player/equalizer
-```
-
-## Example
-
-#### Equalizer
-
-```js
-import { EqualizerStream } from '@discord-player/equalizer';
-
-// initialize 15 band equalizer stream
-const equalizer = new EqualizerStream();
-
-// set equalizer bands, in this case add some bass
-equalizer.setEQ([
- { band: 0, gain: 0.25 },
- { band: 1, gain: 0.25 },
- { band: 2, gain: 0.25 }
-]);
-
-// input stream
-const input = getPCMAudioSomehow();
-
-// pipe input stream to equalizer
-const output = input.pipe(equalizer);
-
-// now do something with the output stream
-```
-
-#### Biquad
-
-```js
-import { BiquadStream, FilterType } from '@discord-player/equalizer';
-
-// initialize biquad stream
-const biquad = new BiquadStream();
-
-// initialize with filter
-const biquad = new BiquadStream({
- filter: FilterType.LowPass
-});
-
-// set filter
-biquad.setFilter(FilterType.HighPass);
-
-// set gain (Gain is only applicable to LowShelf, HighShelf and PeakingEQ)
-biquad.setGain(5);
-
-// input stream
-const input = getPCMAudioSomehow();
-
-// pipe input stream to biquad
-const output = input.pipe(biquad);
-```
-
-#### Supported Biquad Filters
-
-* SinglePoleLowPassApprox
-* SinglePoleLowPass
-* LowPass
-* HighPass
-* BandPass
-* Notch
-* AllPass
-* LowShelf
-* HighShelf
-* PeakingEQ
\ No newline at end of file
diff --git a/node_modules/@discord-player/equalizer/dist/index.d.ts b/node_modules/@discord-player/equalizer/dist/index.d.ts
deleted file mode 100644
index bad7e5f..0000000
--- a/node_modules/@discord-player/equalizer/dist/index.d.ts
+++ /dev/null
@@ -1,218 +0,0 @@
-import { TransformOptions, Transform, TransformCallback } from 'stream';
-
-declare const FilterType: {
- readonly SinglePoleLowPassApprox: 0;
- readonly SinglePoleLowPass: 1;
- readonly LowPass: 2;
- readonly HighPass: 3;
- readonly BandPass: 4;
- readonly Notch: 5;
- readonly AllPass: 6;
- readonly LowShelf: 7;
- readonly HighShelf: 8;
- readonly PeakingEQ: 9;
-};
-type BiquadFilters = keyof typeof FilterType | (typeof FilterType)[keyof typeof FilterType];
-interface CoefficientsInit {
- a1: number;
- a2: number;
- b0: number;
- b1: number;
- b2: number;
-}
-declare const Q_BUTTERWORTH: number;
-declare class Coefficients {
- a1: number;
- a2: number;
- b0: number;
- b1: number;
- b2: number;
- constructor(data?: CoefficientsInit);
- static from(filter: BiquadFilters, samplingFreq: number, cutoffFreq: number, Q: number, dbGain?: number): Coefficients;
-}
-
-interface BiquadSetFilterProps {
- f0: number;
- fs: number;
- Q: number;
- gain?: number;
-}
-declare class BiquadFilter {
- coefficients: Coefficients;
- x1: number;
- x2: number;
- y1: number;
- y2: number;
- s1: number;
- s2: number;
- constructor(coefficients: Coefficients);
- setFilter(filter: BiquadFilters, options: BiquadSetFilterProps): void;
- update(coefficients: Coefficients): void;
- replace(coefficients: Coefficients): void;
- reset(): void;
- run(input: number): number;
- runTransposed(input: number): number;
-}
-
-declare class Frequency {
- private __val;
- constructor(__val: number);
- khz(): number;
- mhz(): number;
- hz(): number;
- dt(): number;
- valueOf(): number;
- toString(): string;
- toJSON(): string;
-}
-
-type PCMType = `s${16 | 32}${'l' | 'b'}e`;
-interface PCMTransformerOptions extends TransformOptions {
- type?: PCMType;
-}
-declare class PCMTransformer extends Transform {
- readonly type: PCMType;
- bits: number;
- bytes: number;
- extremum: number;
- constructor(options?: PCMTransformerOptions);
- _readInt(buffer: Buffer, index: number): number;
- _writeInt(buffer: Buffer, int: number, index: number): number;
- clamp(val: number, max?: number, min?: number): number;
-}
-
-interface BiquadStreamOptions extends PCMTransformerOptions {
- disabled?: boolean;
- filter?: BiquadFilters;
- Q?: number;
- sample?: number;
- cutoff?: number;
- gain?: number;
-}
-interface BiquadFilterUpdateData {
- filter?: BiquadFilters;
- Q?: number;
- sample?: number;
- cutoff?: number;
- gain?: number;
-}
-declare class BiquadStream extends PCMTransformer {
- disabled: boolean;
- biquad: BiquadFilter;
- sample: number;
- cutoff: number;
- gain: number;
- filter: BiquadFilters;
- Q: number;
- constructor(options?: BiquadStreamOptions);
- disable(): void;
- enable(): void;
- toggle(): void;
- getFilterName(): BiquadFilters | null;
- update(options: BiquadFilterUpdateData): void;
- setFilter(filter: BiquadFilters): void;
- setQ(Q: number): void;
- setSample(fs: number): void;
- setCutoff(f0: number): void;
- setGain(dB: number): void;
- _transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback): void;
-}
-
-type ReadIntCallback = (buffer: Buffer, index: number) => number;
-type WriteIntCallback = (buffer: Buffer, int: number, index: number) => number;
-declare class ChannelProcessor {
- history: number[];
- bandMultipliers: number[];
- current: number;
- m1: number;
- m2: number;
- constructor(bandMultipliers: number[]);
- process(samples: Buffer, extremum?: number, bytes?: number, readInt?: ReadIntCallback, writeInt?: WriteIntCallback): Buffer;
- reset(): void;
-}
-
-declare class EqualizerCoefficients {
- beta: number;
- alpha: number;
- gamma: number;
- constructor(beta: number, alpha: number, gamma: number);
- setBeta(v: number): void;
- setAlpha(v: number): void;
- setGamma(v: number): void;
- toJSON(): {
- alpha: number;
- beta: number;
- gamma: number;
- };
-}
-
-declare class EqualizerConfiguration {
- bandMultipliers: number[];
- constructor(bandMultipliers: number[]);
- setGain(band: number, value: number): void;
- getGain(band: number): number;
- isValidBand(band: number): boolean;
-}
-
-interface ChannelProcessorInput {
- data: Buffer;
- readInt?: ReadIntCallback;
- writeInt?: WriteIntCallback;
- extremum?: number;
- bytes?: number;
-}
-declare class Equalizer extends EqualizerConfiguration {
- static BAND_COUNT: 15;
- static SAMPLE_RATE: 48000;
- static Coefficients48000: EqualizerCoefficients[];
- channels: ChannelProcessor[];
- channelCount: number;
- constructor(channelCount: number, bandMultipliers: number[]);
- createChannelProcessor(): ChannelProcessor[];
- process(input: ChannelProcessorInput[]): Buffer[];
-}
-
-interface EqualizerStreamOptions extends PCMTransformerOptions {
- bandMultiplier?: EqualizerBand[];
- disabled?: boolean;
- channels?: number;
-}
-interface EqualizerBand {
- band: number;
- gain: number;
-}
-declare class EqualizerStream extends PCMTransformer {
- disabled: boolean;
- bandMultipliers: number[];
- equalizer: Equalizer;
- constructor(options?: EqualizerStreamOptions);
- _processBands(multiplier: EqualizerBand[]): void;
- disable(): void;
- enable(): void;
- toggle(): void;
- _transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback): void;
- getEQ(): EqualizerBand[];
- setEQ(bands: EqualizerBand[]): void;
- resetEQ(): void;
-}
-
-type MSTStrategy = 'm2s' | 's2m';
-interface MonoStereoTransformerOptions extends PCMTransformerOptions {
- strategy: MSTStrategy;
-}
-declare class MonoStereoTransformer extends PCMTransformer {
- disabled: boolean;
- strategy: MSTStrategy;
- constructor(options?: MonoStereoTransformerOptions);
- disable(): void;
- enable(): void;
- toggle(): void;
- setStrategy(strategy: MSTStrategy): void;
- _transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback): void;
- toStereo(sample: Buffer, len: number): Buffer;
- toMono(sample: Buffer, len: number): Buffer;
-}
-
-declare const version: string;
-
-export { BiquadFilter, BiquadFilterUpdateData, BiquadFilters, BiquadSetFilterProps, BiquadStream, BiquadStreamOptions, ChannelProcessor, ChannelProcessorInput, Coefficients, Equalizer, EqualizerBand, EqualizerCoefficients, EqualizerConfiguration, EqualizerStream, FilterType, Frequency, MSTStrategy, MonoStereoTransformer, MonoStereoTransformerOptions, PCMTransformer, PCMTransformerOptions, PCMType, Q_BUTTERWORTH, ReadIntCallback, WriteIntCallback, version };
diff --git a/node_modules/@discord-player/equalizer/dist/index.js b/node_modules/@discord-player/equalizer/dist/index.js
deleted file mode 100644
index 9cdd74f..0000000
--- a/node_modules/@discord-player/equalizer/dist/index.js
+++ /dev/null
@@ -1,755 +0,0 @@
-"use strict";
-var __defProp = Object.defineProperty;
-var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
-var __getOwnPropNames = Object.getOwnPropertyNames;
-var __hasOwnProp = Object.prototype.hasOwnProperty;
-var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
-var __export = (target, all) => {
- for (var name in all)
- __defProp(target, name, { get: all[name], enumerable: true });
-};
-var __copyProps = (to, from, except, desc) => {
- if (from && typeof from === "object" || typeof from === "function") {
- for (let key of __getOwnPropNames(from))
- if (!__hasOwnProp.call(to, key) && key !== except)
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
- }
- return to;
-};
-var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
-
-// src/index.ts
-var src_exports = {};
-__export(src_exports, {
- BiquadFilter: () => BiquadFilter,
- BiquadStream: () => BiquadStream,
- ChannelProcessor: () => ChannelProcessor,
- Coefficients: () => Coefficients,
- Equalizer: () => Equalizer,
- EqualizerCoefficients: () => EqualizerCoefficients,
- EqualizerConfiguration: () => EqualizerConfiguration,
- EqualizerStream: () => EqualizerStream,
- FilterType: () => FilterType,
- Frequency: () => Frequency,
- MonoStereoTransformer: () => MonoStereoTransformer,
- PCMTransformer: () => PCMTransformer,
- Q_BUTTERWORTH: () => Q_BUTTERWORTH,
- version: () => version
-});
-module.exports = __toCommonJS(src_exports);
-
-// src/biquad/Coefficients.ts
-var FilterType = {
- SinglePoleLowPassApprox: 0,
- SinglePoleLowPass: 1,
- LowPass: 2,
- HighPass: 3,
- BandPass: 4,
- Notch: 5,
- AllPass: 6,
- LowShelf: 7,
- HighShelf: 8,
- PeakingEQ: 9
-};
-var Q_BUTTERWORTH = Math.SQRT1_2;
-var Coefficients = class {
- constructor(data) {
- this.a1 = 0;
- this.a2 = 0;
- this.b0 = 0;
- this.b1 = 0;
- this.b2 = 0;
- if (data) {
- this.a1 = data.a1;
- this.a2 = data.a2;
- this.b0 = data.b0;
- this.b1 = data.b1;
- this.b2 = data.b2;
- }
- }
- static from(filter, samplingFreq, cutoffFreq, Q, dbGain = 0) {
- if (2 * cutoffFreq > samplingFreq) {
- throw new Error(`Cutoff frequency is too big!`);
- }
- if (Q < 0) {
- throw new Error(`Q may not be negative`);
- }
- const omega = 2 * Math.PI * cutoffFreq / samplingFreq;
- if (typeof filter === "string")
- filter = FilterType[filter];
- switch (filter) {
- case FilterType.SinglePoleLowPassApprox: {
- const alpha = omega / (omega + 1);
- return new Coefficients({
- a1: alpha - 1,
- a2: 0,
- b0: alpha,
- b1: 0,
- b2: 0
- });
- }
- case FilterType.SinglePoleLowPass: {
- const omega_t = Math.tan(omega / 2);
- const a0 = 1 + omega_t;
- return new Coefficients({
- a1: (omega_t - 1) / a0,
- a2: 0,
- b0: omega_t / a0,
- b1: omega_t / a0,
- b2: 0
- });
- }
- case FilterType.LowPass: {
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = (1 - omega_c) * 0.5;
- const b1 = 1 - omega_c;
- const b2 = (1 - omega_c) * 0.5;
- const a0 = 1 + alpha;
- const a1 = -2 * omega_c;
- const a2 = 1 - alpha;
- const div = 1 / a0;
- return new Coefficients({
- a1: a1 * div,
- a2: a2 * div,
- b0: b0 * div,
- b1: b1 * div,
- b2: b2 * div
- });
- }
- case FilterType.HighPass: {
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = (1 + omega_c) * 0.5;
- const b1 = -(1 + omega_c);
- const b2 = (1 + omega_c) * 0.5;
- const a0 = 1 + alpha;
- const a1 = -2 * omega_c;
- const a2 = 1 - alpha;
- const div = 1 / a0;
- return new Coefficients({
- a1: a1 * div,
- a2: a2 * div,
- b0: b0 * div,
- b1: b1 * div,
- b2: b2 * div
- });
- }
- case FilterType.Notch: {
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = 1;
- const b1 = -2 * omega_c;
- const b2 = 1;
- const a0 = 1 + alpha;
- const a1 = -2 * omega_c;
- const a2 = 1 - alpha;
- const div = 1 / a0;
- return new Coefficients({
- a1: a1 * div,
- a2: a2 * div,
- b0: b0 * div,
- b1: b1 * div,
- b2: b2 * div
- });
- }
- case FilterType.BandPass: {
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = omega_s / 2;
- const b1 = 0;
- const b2 = -(omega_s / 2);
- const a0 = 1 + alpha;
- const a1 = -2 * omega_c;
- const a2 = 1 - alpha;
- const div = 1 / a0;
- return new Coefficients({
- a1: a1 * div,
- a2: a2 * div,
- b0: b0 * div,
- b1: b1 * div,
- b2: b2 * div
- });
- }
- case FilterType.AllPass: {
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = 1 - alpha;
- const b1 = -2 * omega_c;
- const b2 = 1 + alpha;
- const a0 = 1 + alpha;
- const a1 = -2 * omega_c;
- const a2 = 1 - alpha;
- return new Coefficients({
- a1: a1 / a0,
- a2: a2 / a0,
- b0: b0 / a0,
- b1: b1 / a0,
- b2: b2 / a0
- });
- }
- case FilterType.LowShelf: {
- const a = Math.pow(10, dbGain / 40);
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = a * (a + 1 - (a - 1) * omega_c + 2 * alpha * Math.sqrt(a));
- const b1 = 2 * a * (a - 1 - (a + 1) * omega_c);
- const b2 = a * (a + 1 - (a - 1) * omega_c - 2 * alpha * Math.sqrt(a));
- const a0 = a + 1 + (a - 1) * omega_c + 2 * alpha * Math.sqrt(a);
- const a1 = -2 * (a - 1 + (a + 1) * omega_c);
- const a2 = a + 1 + (a - 1) * omega_c - 2 * alpha * Math.sqrt(a);
- return new Coefficients({
- a1: a1 / a0,
- a2: a2 / a0,
- b0: b0 / a0,
- b1: b1 / a0,
- b2: b2 / a0
- });
- }
- case FilterType.HighShelf: {
- const a = Math.pow(10, dbGain / 40);
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = a * (a + 1 + (a - 1) * omega_c + 2 * alpha * Math.sqrt(a));
- const b1 = -2 * a * (a - 1 + (a + 1) * omega_c);
- const b2 = a * (a + 1 + (a - 1) * omega_c - 2 * alpha * Math.sqrt(a));
- const a0 = a + 1 - (a - 1) * omega_c + 2 * alpha * Math.sqrt(a);
- const a1 = 2 * (a - 1 - (a + 1) * omega_c);
- const a2 = a + 1 - (a - 1) * omega_c - 2 * alpha * Math.sqrt(a);
- return new Coefficients({
- a1: a1 / a0,
- a2: a2 / a0,
- b0: b0 / a0,
- b1: b1 / a0,
- b2: b2 / a0
- });
- }
- case FilterType.PeakingEQ: {
- const a = Math.pow(10, dbGain / 40);
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = 1 + alpha * a;
- const b1 = -2 * omega_c;
- const b2 = 1 - alpha * a;
- const a0 = 1 + alpha / a;
- const a1 = -2 * omega_c;
- const a2 = 1 - alpha / a;
- return new Coefficients({
- a1: a1 / a0,
- a2: a2 / a0,
- b0: b0 / a0,
- b1: b1 / a0,
- b2: b2 / a0
- });
- }
- default:
- throw new TypeError("Invalid filter type");
- }
- }
-};
-__name(Coefficients, "Coefficients");
-
-// src/biquad/Biquad.ts
-var BiquadFilter = class {
- constructor(coefficients) {
- this.coefficients = coefficients;
- this.x1 = 0;
- this.x2 = 0;
- this.y1 = 0;
- this.y2 = 0;
- this.s1 = 0;
- this.s2 = 0;
- }
- setFilter(filter, options) {
- const coefficients = Coefficients.from(filter, options.fs, options.f0, options.Q, options.gain);
- this.update(coefficients);
- }
- update(coefficients) {
- this.coefficients = coefficients;
- }
- replace(coefficients) {
- this.coefficients = coefficients;
- }
- reset() {
- this.x1 = 0;
- this.x2 = 0;
- this.y1 = 0;
- this.y2 = 0;
- this.s1 = 0;
- this.s2 = 0;
- }
- run(input) {
- const { a1, a2, b0, b1, b2 } = this.coefficients;
- const out = b0 * input + b1 * this.x1 + b2 * this.x2 - a1 * this.y1 - a2 * this.y2;
- this.x2 = this.x1;
- this.x1 = input;
- this.y2 = this.y1;
- this.y1 = out;
- return out;
- }
- runTransposed(input) {
- const { a1, a2, b0, b1, b2 } = this.coefficients;
- const out = this.s1 + b0 * input;
- this.s1 = this.s2 + b1 * input - a1 * out;
- this.s2 = b2 * input - a2 * out;
- return out;
- }
-};
-__name(BiquadFilter, "BiquadFilter");
-
-// src/utils/Frequency.ts
-var Frequency = class {
- constructor(__val) {
- this.__val = __val;
- if (typeof __val !== "number" || isNaN(__val) || __val === Infinity)
- throw new TypeError("Frequency value must be a number");
- if (this.__val < 0)
- throw new Error(`Frequency value cannot be negative (${__val})`);
- }
- khz() {
- return this.__val * 1e3;
- }
- mhz() {
- return this.__val * 1e6;
- }
- hz() {
- return this.__val;
- }
- dt() {
- return 1 / this.__val;
- }
- valueOf() {
- return this.__val;
- }
- toString() {
- return `${this.__val}Hz`;
- }
- toJSON() {
- return this.toString();
- }
-};
-__name(Frequency, "Frequency");
-
-// src/utils/PCMTransformer.ts
-var import_stream = require("stream");
-var PCMTransformer = class extends import_stream.Transform {
- constructor(options = {}) {
- super(options);
- this.type = "s16le";
- options.type ?? (options.type = "s16le");
- switch (options.type) {
- case "s16be":
- case "s16le":
- this.type = options.type;
- this.bits = 16;
- break;
- case "s32be":
- case "s32le":
- this.type = options.type;
- this.bits = 32;
- break;
- default:
- throw new TypeError(`Expected type to be one of ${["s16be", "s16le", "s32be", "s32le"].join(", ")}, got "${options.type}"`);
- }
- this.bytes = this.bits / 8;
- this.extremum = Math.pow(2, this.bits - 1);
- }
- _readInt(buffer, index) {
- const method = `readInt${this.type.substring(1).toUpperCase()}`;
- return buffer[method](index);
- }
- _writeInt(buffer, int, index) {
- const method = `writeInt${this.type.substring(1).toUpperCase()}`;
- return buffer[method](int, index);
- }
- clamp(val, max = this.extremum - 1, min = -this.extremum) {
- return Math.min(max, Math.max(min, val));
- }
-};
-__name(PCMTransformer, "PCMTransformer");
-
-// src/biquad/BiquadStream.ts
-var BiquadStream = class extends PCMTransformer {
- constructor(options = {}) {
- super(options);
- this.disabled = false;
- this.sample = 48e3;
- this.cutoff = 80;
- this.gain = 0;
- this.Q = Q_BUTTERWORTH;
- this.disabled = !!options.disabled;
- if ("sample" in options)
- this.sample = options.sample;
- if ("cutoff" in options)
- this.cutoff = options.cutoff;
- if ("gain" in options)
- this.gain = options.gain;
- if ("Q" in options)
- this.Q = options.Q;
- if ("filter" in options) {
- this.filter = options.filter;
- if (this.filter != null) {
- this.biquad = new BiquadFilter(Coefficients.from(this.filter, this.sample, this.cutoff, this.Q, this.gain));
- }
- }
- }
- disable() {
- this.disabled = true;
- }
- enable() {
- this.disabled = false;
- }
- toggle() {
- this.disabled = !this.disabled;
- }
- getFilterName() {
- if (this.filter == null)
- return null;
- if (typeof this.filter === "string")
- return this.filter;
- return Object.entries(FilterType).find((r) => r[1] === this.filter)?.[0];
- }
- update(options) {
- if ("sample" in options)
- this.sample = options.sample;
- if ("cutoff" in options)
- this.cutoff = options.cutoff;
- if ("gain" in options)
- this.gain = options.gain;
- if ("Q" in options)
- this.Q = options.Q;
- if ("filter" in options)
- this.filter = options.filter;
- if (this.filter != null) {
- this.biquad = new BiquadFilter(Coefficients.from(this.filter, this.sample, this.cutoff, this.Q, this.gain));
- }
- }
- setFilter(filter) {
- this.update({ filter });
- }
- setQ(Q) {
- this.update({ Q });
- }
- setSample(fs) {
- this.update({ sample: fs });
- }
- setCutoff(f0) {
- this.update({ cutoff: f0 });
- }
- setGain(dB) {
- this.update({ gain: dB });
- }
- _transform(chunk, encoding, callback) {
- if (this.disabled || !this.biquad) {
- this.push(chunk);
- return callback();
- }
- const endIndex = Math.floor(chunk.length / 2) * 2;
- const { bytes, extremum } = this;
- for (let sampleIndex = 0; sampleIndex < endIndex; sampleIndex += bytes) {
- const int = this._readInt(chunk, sampleIndex);
- const result = this.biquad.run(int);
- const val = Math.min(extremum - 1, Math.max(-extremum, result));
- this._writeInt(chunk, val, sampleIndex);
- }
- this.push(chunk);
- return callback();
- }
-};
-__name(BiquadStream, "BiquadStream");
-
-// src/equalizer/ChannelProcessor.ts
-var ChannelProcessor = class {
- constructor(bandMultipliers) {
- this.history = new Array(Equalizer.BAND_COUNT * 6).fill(0);
- this.bandMultipliers = bandMultipliers;
- this.current = 0;
- this.m1 = 2;
- this.m2 = 1;
- }
- process(samples, extremum = 131072, bytes = 2, readInt, writeInt) {
- const endIndex = Math.floor(samples.length / 2) * 2;
- for (let sampleIndex = 0; sampleIndex < endIndex; sampleIndex += bytes) {
- const sample = readInt?.(samples, sampleIndex) ?? samples.readInt16LE(sampleIndex);
- let result = sample * 0.25;
- for (let bandIndex = 0; bandIndex < Equalizer.BAND_COUNT; bandIndex++) {
- const x = bandIndex * 6;
- const y = x + 3;
- const coefficients = Equalizer.Coefficients48000[bandIndex];
- const bandResult = coefficients.alpha * (sample - this.history[x + this.m2]) + coefficients.gamma * this.history[y + this.m1] - coefficients.beta * this.history[y + this.m2];
- this.history[x + this.current] = sample;
- this.history[y + this.current] = bandResult;
- result += bandResult * this.bandMultipliers[bandIndex];
- }
- const val = Math.min(extremum - 1, Math.max(-extremum, result * 4));
- writeInt?.(samples, val, sampleIndex) ?? samples.writeInt16LE(val, sampleIndex);
- if (++this.current === 3) {
- this.current = 0;
- }
- if (++this.m1 === 3) {
- this.m1 = 0;
- }
- if (++this.m2 === 3) {
- this.m2 = 0;
- }
- }
- return samples;
- }
- reset() {
- this.history.fill(0);
- }
-};
-__name(ChannelProcessor, "ChannelProcessor");
-
-// src/equalizer/Coefficients.ts
-var EqualizerCoefficients = class {
- constructor(beta, alpha, gamma) {
- this.beta = beta;
- this.alpha = alpha;
- this.gamma = gamma;
- }
- setBeta(v) {
- this.beta = v;
- }
- setAlpha(v) {
- this.alpha = v;
- }
- setGamma(v) {
- this.gamma = v;
- }
- toJSON() {
- const { alpha, beta, gamma } = this;
- return { alpha, beta, gamma };
- }
-};
-__name(EqualizerCoefficients, "EqualizerCoefficients");
-
-// src/equalizer/EqualizerConfiguration.ts
-var EqualizerConfiguration = class {
- constructor(bandMultipliers) {
- this.bandMultipliers = bandMultipliers;
- }
- setGain(band, value) {
- if (this.isValidBand(band)) {
- this.bandMultipliers[band] = Math.max(Math.min(value, 1), -0.25);
- }
- }
- getGain(band) {
- if (this.isValidBand(band)) {
- return this.bandMultipliers[band];
- } else {
- return 0;
- }
- }
- isValidBand(band) {
- return band >= 0 && band < this.bandMultipliers.length;
- }
-};
-__name(EqualizerConfiguration, "EqualizerConfiguration");
-
-// src/equalizer/Equalizer.ts
-var Equalizer = class extends EqualizerConfiguration {
- constructor(channelCount, bandMultipliers) {
- super(bandMultipliers);
- this.channels = [];
- this.channelCount = channelCount;
- this.channels = this.createChannelProcessor();
- }
- createChannelProcessor() {
- return Array.from({ length: this.channelCount }, () => {
- return new ChannelProcessor(this.bandMultipliers);
- });
- }
- process(input) {
- return this.channels.map((c, i) => {
- const { data, extremum, readInt, writeInt, bytes } = input[i];
- return c.process(data, extremum, bytes, readInt, writeInt);
- });
- }
-};
-__name(Equalizer, "Equalizer");
-Equalizer.BAND_COUNT = 15;
-Equalizer.SAMPLE_RATE = 48e3;
-Equalizer.Coefficients48000 = [
- new EqualizerCoefficients(0.99847546664, 76226668143e-14, 1.9984647656),
- new EqualizerCoefficients(0.99756184654, 0.0012190767289, 1.9975344645),
- new EqualizerCoefficients(0.99616261379, 0.0019186931041, 1.9960947369),
- new EqualizerCoefficients(0.99391578543, 0.0030421072865, 1.9937449618),
- new EqualizerCoefficients(0.99028307215, 0.0048584639242, 1.9898465702),
- new EqualizerCoefficients(0.98485897264, 0.0075705136795, 1.9837962543),
- new EqualizerCoefficients(0.97588512657, 0.012057436715, 1.9731772447),
- new EqualizerCoefficients(0.96228521814, 0.018857390928, 1.9556164694),
- new EqualizerCoefficients(0.94080933132, 0.029595334338, 1.9242054384),
- new EqualizerCoefficients(0.90702059196, 0.046489704022, 1.8653476166),
- new EqualizerCoefficients(0.85868004289, 0.070659978553, 1.7600401337),
- new EqualizerCoefficients(0.78409610788, 0.10795194606, 1.5450725522),
- new EqualizerCoefficients(0.68332861002, 0.15833569499, 1.1426447155),
- new EqualizerCoefficients(0.55267518228, 0.22366240886, 0.40186190803),
- new EqualizerCoefficients(0.41811888447, 0.29094055777, -0.70905944223)
-];
-
-// src/equalizer/EqualizerStream.ts
-var EqualizerStream = class extends PCMTransformer {
- constructor(options) {
- super(options);
- this.disabled = false;
- this.bandMultipliers = new Array(Equalizer.BAND_COUNT).fill(0);
- options = Object.assign(
- {},
- {
- bandMultiplier: [],
- channels: 1,
- disabled: false
- },
- options || {}
- );
- if (options.disabled)
- this.disabled = !!options.disabled;
- this.equalizer = new Equalizer(options.channels || 1, this.bandMultipliers);
- if (Array.isArray(options.bandMultiplier))
- this._processBands(options.bandMultiplier);
- }
- _processBands(multiplier) {
- for (const mul of multiplier) {
- if (mul.band > Equalizer.BAND_COUNT - 1 || mul.band < 0)
- throw new RangeError(`Band value out of range. Expected >0 & <${Equalizer.BAND_COUNT - 1}, received "${mul.band}"`);
- this.equalizer.setGain(mul.band, mul.gain);
- }
- }
- disable() {
- this.disabled = true;
- }
- enable() {
- this.disabled = false;
- }
- toggle() {
- this.disabled = !this.disabled;
- }
- _transform(chunk, encoding, callback) {
- if (this.disabled) {
- this.push(chunk);
- return callback();
- }
- this.equalizer.process([
- {
- data: chunk,
- extremum: this.extremum,
- readInt: (b, idx) => this._readInt(b, idx),
- writeInt: (b, i, idx) => this._writeInt(b, i, idx),
- bytes: this.bytes
- }
- ]);
- this.push(chunk);
- return callback();
- }
- getEQ() {
- return this.bandMultipliers.map((m, i) => ({
- band: i,
- gain: m
- }));
- }
- setEQ(bands) {
- this._processBands(bands);
- }
- resetEQ() {
- this._processBands(
- Array.from(
- {
- length: Equalizer.BAND_COUNT
- },
- (_, i) => ({
- band: i,
- gain: 0
- })
- )
- );
- }
-};
-__name(EqualizerStream, "EqualizerStream");
-
-// src/audio/MonoStereoTransformer.ts
-var MonoStereoTransformer = class extends PCMTransformer {
- constructor(options) {
- super(options);
- this.disabled = false;
- if (!["m2s", "s2m"].includes(options?.strategy)) {
- throw new TypeError(`Strategy must be "m2s" or "s2m"`);
- }
- this.strategy = options.strategy;
- }
- disable() {
- this.disabled = true;
- }
- enable() {
- this.disabled = false;
- }
- toggle() {
- this.disabled = !this.disabled;
- }
- setStrategy(strategy) {
- this.strategy = strategy;
- }
- _transform(chunk, encoding, callback) {
- if (this.disabled) {
- this.push(chunk);
- return callback();
- }
- const len = Math.floor(chunk.length / 2) * 2;
- if (this.strategy === "m2s") {
- this.push(this.toStereo(chunk, len));
- } else {
- this.push(this.toMono(chunk, len));
- }
- return callback();
- }
- toStereo(sample, len) {
- const bytes = this.bytes;
- const stereoBuffer = Buffer.alloc(len * 2);
- for (let i = 0; i < len; i += bytes) {
- stereoBuffer[i * 2 + 0] = sample[i];
- stereoBuffer[i * 2 + 1] = sample[i + 1];
- stereoBuffer[i * 2 + 2] = sample[i];
- stereoBuffer[i * 2 + 3] = sample[i + 1];
- }
- return stereoBuffer;
- }
- toMono(sample, len) {
- const bytes = this.bytes;
- const monoBuffer = Buffer.alloc(Math.floor(len / 2));
- for (let i = 0; i < len; i += bytes) {
- monoBuffer[i] = sample[i * 2 + 0];
- monoBuffer[i + 1] = sample[i * 2 + 1];
- }
- return monoBuffer;
- }
-};
-__name(MonoStereoTransformer, "MonoStereoTransformer");
-
-// src/index.ts
-var version = "0.1.3";
-// Annotate the CommonJS export names for ESM import in node:
-0 && (module.exports = {
- BiquadFilter,
- BiquadStream,
- ChannelProcessor,
- Coefficients,
- Equalizer,
- EqualizerCoefficients,
- EqualizerConfiguration,
- EqualizerStream,
- FilterType,
- Frequency,
- MonoStereoTransformer,
- PCMTransformer,
- Q_BUTTERWORTH,
- version
-});
-//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/node_modules/@discord-player/equalizer/dist/index.js.map b/node_modules/@discord-player/equalizer/dist/index.js.map
deleted file mode 100644
index d1b792a..0000000
--- a/node_modules/@discord-player/equalizer/dist/index.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../src/index.ts","../src/biquad/Coefficients.ts","../src/biquad/Biquad.ts","../src/utils/Frequency.ts","../src/utils/PCMTransformer.ts","../src/biquad/BiquadStream.ts","../src/equalizer/ChannelProcessor.ts","../src/equalizer/Coefficients.ts","../src/equalizer/EqualizerConfiguration.ts","../src/equalizer/Equalizer.ts","../src/equalizer/EqualizerStream.ts","../src/audio/MonoStereoTransformer.ts"],"sourcesContent":["export * from './biquad';\nexport * from './equalizer';\nexport * from './utils';\nexport * from './audio';\n\n// eslint-disable-next-line @typescript-eslint/no-inferrable-types\nexport const version: string = '0.1.3';\n","export const FilterType = {\n SinglePoleLowPassApprox: 0,\n SinglePoleLowPass: 1,\n LowPass: 2,\n HighPass: 3,\n BandPass: 4,\n Notch: 5,\n AllPass: 6,\n LowShelf: 7,\n HighShelf: 8,\n PeakingEQ: 9\n} as const;\n\nexport type BiquadFilters = keyof typeof FilterType | (typeof FilterType)[keyof typeof FilterType];\n\ninterface CoefficientsInit {\n a1: number;\n a2: number;\n b0: number;\n b1: number;\n b2: number;\n}\n\nexport const Q_BUTTERWORTH = Math.SQRT1_2;\n\nexport class Coefficients {\n // Denominator coefficients\n public a1 = 0;\n public a2 = 0;\n\n // Nominator coefficients\n public b0 = 0;\n public b1 = 0;\n public b2 = 0;\n\n public constructor(data?: CoefficientsInit) {\n if (data) {\n this.a1 = data.a1;\n this.a2 = data.a2;\n this.b0 = data.b0;\n this.b1 = data.b1;\n this.b2 = data.b2;\n }\n }\n\n public static from(filter: BiquadFilters, samplingFreq: number, cutoffFreq: number, Q: number, dbGain = 0) {\n if (2.0 * cutoffFreq > samplingFreq) {\n throw new Error(`Cutoff frequency is too big!`);\n }\n\n if (Q < 0) {\n throw new Error(`Q may not be negative`);\n }\n\n const omega = (2.0 * Math.PI * cutoffFreq) / samplingFreq;\n\n if (typeof filter === 'string') filter = FilterType[filter];\n\n switch (filter) {\n case FilterType.SinglePoleLowPassApprox: {\n const alpha = omega / (omega + 1.0);\n\n return new Coefficients({\n a1: alpha - 1.0,\n a2: 0.0,\n b0: alpha,\n b1: 0.0,\n b2: 0.0\n });\n }\n case FilterType.SinglePoleLowPass: {\n const omega_t = Math.tan(omega / 2.0);\n const a0 = 1.0 + omega_t;\n\n return new Coefficients({\n a1: (omega_t - 1.0) / a0,\n a2: 0.0,\n b0: omega_t / a0,\n b1: omega_t / a0,\n b2: 0.0\n });\n }\n case FilterType.LowPass: {\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = (1.0 - omega_c) * 0.5;\n const b1 = 1.0 - omega_c;\n const b2 = (1.0 - omega_c) * 0.5;\n const a0 = 1.0 + alpha;\n const a1 = -2.0 * omega_c;\n const a2 = 1.0 - alpha;\n\n const div = 1.0 / a0;\n\n return new Coefficients({\n a1: a1 * div,\n a2: a2 * div,\n b0: b0 * div,\n b1: b1 * div,\n b2: b2 * div\n });\n }\n case FilterType.HighPass: {\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = (1.0 + omega_c) * 0.5;\n const b1 = -(1.0 + omega_c);\n const b2 = (1.0 + omega_c) * 0.5;\n const a0 = 1.0 + alpha;\n const a1 = -2.0 * omega_c;\n const a2 = 1.0 - alpha;\n\n const div = 1.0 / a0;\n\n return new Coefficients({\n a1: a1 * div,\n a2: a2 * div,\n b0: b0 * div,\n b1: b1 * div,\n b2: b2 * div\n });\n }\n case FilterType.Notch: {\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = 1.0;\n const b1 = -2.0 * omega_c;\n const b2 = 1.0;\n const a0 = 1.0 + alpha;\n const a1 = -2.0 * omega_c;\n const a2 = 1.0 - alpha;\n\n const div = 1.0 / a0;\n\n return new Coefficients({\n a1: a1 * div,\n a2: a2 * div,\n b0: b0 * div,\n b1: b1 * div,\n b2: b2 * div\n });\n }\n case FilterType.BandPass: {\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = omega_s / 2.0;\n const b1 = 0;\n const b2 = -(omega_s / 2.0);\n const a0 = 1.0 + alpha;\n const a1 = -2.0 * omega_c;\n const a2 = 1.0 - alpha;\n\n const div = 1.0 / a0;\n\n return new Coefficients({\n a1: a1 * div,\n a2: a2 * div,\n b0: b0 * div,\n b1: b1 * div,\n b2: b2 * div\n });\n }\n case FilterType.AllPass: {\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = 1.0 - alpha;\n const b1 = -2.0 * omega_c;\n const b2 = 1.0 + alpha;\n const a0 = 1.0 + alpha;\n const a1 = -2.0 * omega_c;\n const a2 = 1.0 - alpha;\n\n return new Coefficients({\n a1: a1 / a0,\n a2: a2 / a0,\n b0: b0 / a0,\n b1: b1 / a0,\n b2: b2 / a0\n });\n }\n case FilterType.LowShelf: {\n const a = Math.pow(10.0, dbGain / 40.0);\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = a * (a + 1.0 - (a - 1.0) * omega_c + 2.0 * alpha * Math.sqrt(a));\n const b1 = 2.0 * a * (a - 1.0 - (a + 1.0) * omega_c);\n const b2 = a * (a + 1.0 - (a - 1.0) * omega_c - 2.0 * alpha * Math.sqrt(a));\n const a0 = a + 1.0 + (a - 1.0) * omega_c + 2.0 * alpha * Math.sqrt(a);\n const a1 = -2.0 * (a - 1.0 + (a + 1.0) * omega_c);\n const a2 = a + 1.0 + (a - 1.0) * omega_c - 2.0 * alpha * Math.sqrt(a);\n\n return new Coefficients({\n a1: a1 / a0,\n a2: a2 / a0,\n b0: b0 / a0,\n b1: b1 / a0,\n b2: b2 / a0\n });\n }\n case FilterType.HighShelf: {\n const a = Math.pow(10.0, dbGain / 40.0);\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = a * (a + 1.0 + (a - 1.0) * omega_c + 2.0 * alpha * Math.sqrt(a));\n const b1 = -2.0 * a * (a - 1.0 + (a + 1.0) * omega_c);\n const b2 = a * (a + 1.0 + (a - 1.0) * omega_c - 2.0 * alpha * Math.sqrt(a));\n const a0 = a + 1.0 - (a - 1.0) * omega_c + 2.0 * alpha * Math.sqrt(a);\n const a1 = 2.0 * (a - 1.0 - (a + 1.0) * omega_c);\n const a2 = a + 1.0 - (a - 1.0) * omega_c - 2.0 * alpha * Math.sqrt(a);\n\n return new Coefficients({\n a1: a1 / a0,\n a2: a2 / a0,\n b0: b0 / a0,\n b1: b1 / a0,\n b2: b2 / a0\n });\n }\n case FilterType.PeakingEQ: {\n const a = Math.pow(10.0, dbGain / 40.0);\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = 1.0 + alpha * a;\n const b1 = -2.0 * omega_c;\n const b2 = 1.0 - alpha * a;\n const a0 = 1.0 + alpha / a;\n const a1 = -2.0 * omega_c;\n const a2 = 1.0 - alpha / a;\n\n return new Coefficients({\n a1: a1 / a0,\n a2: a2 / a0,\n b0: b0 / a0,\n b1: b1 / a0,\n b2: b2 / a0\n });\n }\n default:\n throw new TypeError('Invalid filter type');\n }\n }\n}\n","import { BiquadFilters, Coefficients } from './Coefficients';\n\nexport interface BiquadSetFilterProps {\n f0: number;\n fs: number;\n Q: number;\n gain?: number;\n}\n\nexport class BiquadFilter {\n public x1 = 0.0;\n public x2 = 0.0;\n public y1 = 0.0;\n public y2 = 0.0;\n public s1 = 0.0;\n public s2 = 0.0;\n\n public constructor(public coefficients: Coefficients) {}\n\n public setFilter(filter: BiquadFilters, options: BiquadSetFilterProps) {\n const coefficients = Coefficients.from(filter, options.fs, options.f0, options.Q, options.gain);\n\n this.update(coefficients);\n }\n\n public update(coefficients: Coefficients) {\n this.coefficients = coefficients;\n }\n\n public replace(coefficients: Coefficients) {\n this.coefficients = coefficients;\n }\n\n public reset() {\n this.x1 = 0.0;\n this.x2 = 0.0;\n this.y1 = 0.0;\n this.y2 = 0.0;\n this.s1 = 0.0;\n this.s2 = 0.0;\n }\n\n public run(input: number) {\n const { a1, a2, b0, b1, b2 } = this.coefficients;\n\n const out = b0 * input + b1 * this.x1 + b2 * this.x2 - a1 * this.y1 - a2 * this.y2;\n\n this.x2 = this.x1;\n this.x1 = input;\n this.y2 = this.y1;\n this.y1 = out;\n\n return out;\n }\n\n public runTransposed(input: number) {\n const { a1, a2, b0, b1, b2 } = this.coefficients;\n\n const out = this.s1 + b0 * input;\n\n this.s1 = this.s2 + b1 * input - a1 * out;\n this.s2 = b2 * input - a2 * out;\n\n return out;\n }\n}\n","export class Frequency {\n public constructor(private __val: number) {\n if (typeof __val !== 'number' || isNaN(__val) || __val === Infinity) throw new TypeError('Frequency value must be a number');\n if (this.__val < 0) throw new Error(`Frequency value cannot be negative (${__val})`);\n }\n\n public khz() {\n return this.__val * 1000.0;\n }\n\n public mhz() {\n return this.__val * 1_000_000.0;\n }\n\n public hz() {\n return this.__val;\n }\n\n public dt() {\n return 1.0 / this.__val;\n }\n\n public valueOf() {\n return this.__val;\n }\n\n public toString() {\n return `${this.__val}Hz`;\n }\n\n public toJSON() {\n return this.toString();\n }\n}\n","import { Transform, TransformOptions } from 'stream';\n\nexport type PCMType = `s${16 | 32}${'l' | 'b'}e`;\n\nexport interface PCMTransformerOptions extends TransformOptions {\n type?: PCMType;\n}\n\nexport class PCMTransformer extends Transform {\n public readonly type: PCMType = 's16le';\n public bits: number;\n public bytes: number;\n public extremum: number;\n\n public constructor(options: PCMTransformerOptions = {}) {\n super(options);\n\n options.type ??= 's16le';\n\n switch (options.type) {\n case 's16be':\n case 's16le':\n this.type = options.type;\n this.bits = 16;\n break;\n case 's32be':\n case 's32le':\n this.type = options.type;\n this.bits = 32;\n break;\n default:\n throw new TypeError(`Expected type to be one of ${(['s16be', 's16le', 's32be', 's32le'] as PCMType[]).join(', ')}, got \"${options.type}\"`);\n }\n\n this.bytes = this.bits / 8;\n this.extremum = Math.pow(2, this.bits - 1);\n }\n\n public _readInt(buffer: Buffer, index: number) {\n const method = `readInt${this.type.substring(1).toUpperCase()}` as `readInt${16 | 32}${'L' | 'B'}E`;\n return buffer[method](index);\n }\n\n public _writeInt(buffer: Buffer, int: number, index: number) {\n const method = `writeInt${this.type.substring(1).toUpperCase()}` as `writeInt${16 | 32}${'L' | 'B'}E`;\n return buffer[method](int, index);\n }\n\n public clamp(val: number, max = this.extremum - 1, min = -this.extremum) {\n return Math.min(max, Math.max(min, val));\n }\n}\n","import { TransformCallback } from 'stream';\nimport { PCMTransformer, PCMTransformerOptions } from '../utils';\nimport { BiquadFilter } from './Biquad';\nimport { BiquadFilters, Coefficients, FilterType, Q_BUTTERWORTH } from './Coefficients';\n\nexport interface BiquadStreamOptions extends PCMTransformerOptions {\n disabled?: boolean;\n filter?: BiquadFilters;\n Q?: number;\n sample?: number;\n cutoff?: number;\n gain?: number;\n}\n\nexport interface BiquadFilterUpdateData {\n filter?: BiquadFilters;\n Q?: number;\n sample?: number;\n cutoff?: number;\n gain?: number;\n}\n\nexport class BiquadStream extends PCMTransformer {\n public disabled = false;\n public biquad!: BiquadFilter;\n public sample = 48000;\n public cutoff = 80;\n public gain = 0;\n public filter!: BiquadFilters;\n public Q = Q_BUTTERWORTH;\n public constructor(options: BiquadStreamOptions = {}) {\n super(options);\n\n this.disabled = !!options.disabled;\n\n if ('sample' in options) this.sample = options.sample!;\n if ('cutoff' in options) this.cutoff = options.cutoff!;\n if ('gain' in options) this.gain = options.gain!;\n if ('Q' in options) this.Q = options.Q!;\n if ('filter' in options) {\n this.filter = options.filter!;\n if (this.filter != null) {\n this.biquad = new BiquadFilter(Coefficients.from(this.filter, this.sample, this.cutoff, this.Q, this.gain));\n }\n }\n }\n\n public disable() {\n this.disabled = true;\n }\n\n public enable() {\n this.disabled = false;\n }\n\n public toggle() {\n this.disabled = !this.disabled;\n }\n\n public getFilterName() {\n if (this.filter == null) return null;\n if (typeof this.filter === 'string') return this.filter;\n return Object.entries(FilterType).find((r) => r[1] === this.filter)?.[0] as BiquadFilters;\n }\n\n public update(options: BiquadFilterUpdateData) {\n if ('sample' in options) this.sample = options.sample!;\n if ('cutoff' in options) this.cutoff = options.cutoff!;\n if ('gain' in options) this.gain = options.gain!;\n if ('Q' in options) this.Q = options.Q!;\n if ('filter' in options) this.filter = options.filter!;\n\n if (this.filter != null) {\n this.biquad = new BiquadFilter(Coefficients.from(this.filter, this.sample, this.cutoff, this.Q, this.gain));\n }\n }\n\n public setFilter(filter: BiquadFilters) {\n this.update({ filter });\n }\n\n public setQ(Q: number) {\n this.update({ Q });\n }\n\n public setSample(fs: number) {\n this.update({ sample: fs });\n }\n\n public setCutoff(f0: number) {\n this.update({ cutoff: f0 });\n }\n\n public setGain(dB: number) {\n this.update({ gain: dB });\n }\n\n public _transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback) {\n if (this.disabled || !this.biquad) {\n this.push(chunk);\n return callback();\n }\n\n const endIndex = Math.floor(chunk.length / 2) * 2;\n const { bytes, extremum } = this;\n\n for (let sampleIndex = 0; sampleIndex < endIndex; sampleIndex += bytes) {\n const int = this._readInt(chunk, sampleIndex);\n const result = this.biquad.run(int);\n const val = Math.min(extremum - 1, Math.max(-extremum, result));\n this._writeInt(chunk, val, sampleIndex);\n }\n\n this.push(chunk);\n return callback();\n }\n}\n","import { Equalizer } from './Equalizer';\n\nexport type ReadIntCallback = (buffer: Buffer, index: number) => number;\nexport type WriteIntCallback = (buffer: Buffer, int: number, index: number) => number;\n\nexport class ChannelProcessor {\n public history: number[];\n public bandMultipliers: number[];\n public current: number;\n public m1: number;\n public m2: number;\n\n public constructor(bandMultipliers: number[]) {\n this.history = new Array(Equalizer.BAND_COUNT * 6).fill(0);\n this.bandMultipliers = bandMultipliers;\n this.current = 0;\n this.m1 = 2;\n this.m2 = 1;\n }\n\n public process(samples: Buffer, extremum = 131072, bytes = 2, readInt?: ReadIntCallback, writeInt?: WriteIntCallback) {\n const endIndex = Math.floor(samples.length / 2) * 2;\n for (let sampleIndex = 0; sampleIndex < endIndex; sampleIndex += bytes) {\n const sample = readInt?.(samples, sampleIndex) ?? samples.readInt16LE(sampleIndex);\n let result = sample * 0.25;\n\n for (let bandIndex = 0; bandIndex < Equalizer.BAND_COUNT; bandIndex++) {\n const x = bandIndex * 6;\n const y = x + 3;\n\n const coefficients = Equalizer.Coefficients48000[bandIndex];\n\n const bandResult = coefficients.alpha * (sample - this.history[x + this.m2]) + coefficients.gamma * this.history[y + this.m1] - coefficients.beta * this.history[y + this.m2];\n\n this.history[x + this.current] = sample;\n this.history[y + this.current] = bandResult;\n\n result += bandResult * this.bandMultipliers[bandIndex];\n }\n\n const val = Math.min(extremum - 1, Math.max(-extremum, result * 4.0));\n writeInt?.(samples, val, sampleIndex) ?? samples.writeInt16LE(val, sampleIndex);\n\n if (++this.current === 3) {\n this.current = 0;\n }\n\n if (++this.m1 === 3) {\n this.m1 = 0;\n }\n\n if (++this.m2 === 3) {\n this.m2 = 0;\n }\n }\n\n return samples;\n }\n\n public reset() {\n this.history.fill(0.0);\n }\n}\n","export class EqualizerCoefficients {\n public constructor(public beta: number, public alpha: number, public gamma: number) {}\n\n public setBeta(v: number) {\n this.beta = v;\n }\n\n public setAlpha(v: number) {\n this.alpha = v;\n }\n\n public setGamma(v: number) {\n this.gamma = v;\n }\n\n public toJSON() {\n const { alpha, beta, gamma } = this;\n\n return { alpha, beta, gamma };\n }\n}\n","export class EqualizerConfiguration {\n public constructor(public bandMultipliers: number[]) {}\n\n public setGain(band: number, value: number) {\n if (this.isValidBand(band)) {\n this.bandMultipliers[band] = Math.max(Math.min(value, 1.0), -0.25);\n }\n }\n\n public getGain(band: number) {\n if (this.isValidBand(band)) {\n return this.bandMultipliers[band];\n } else {\n return 0.0;\n }\n }\n\n public isValidBand(band: number) {\n return band >= 0 && band < this.bandMultipliers.length;\n }\n}\n","import { ChannelProcessor, ReadIntCallback, WriteIntCallback } from './ChannelProcessor';\nimport { EqualizerCoefficients } from './Coefficients';\nimport { EqualizerConfiguration } from './EqualizerConfiguration';\n\nexport interface ChannelProcessorInput {\n data: Buffer;\n readInt?: ReadIntCallback;\n writeInt?: WriteIntCallback;\n extremum?: number;\n bytes?: number;\n}\n\nexport class Equalizer extends EqualizerConfiguration {\n public static BAND_COUNT = 15 as const;\n public static SAMPLE_RATE = 48000 as const;\n public static Coefficients48000 = [\n new EqualizerCoefficients(9.9847546664e-1, 7.6226668143e-4, 1.9984647656),\n new EqualizerCoefficients(9.9756184654e-1, 1.2190767289e-3, 1.9975344645),\n new EqualizerCoefficients(9.9616261379e-1, 1.9186931041e-3, 1.9960947369),\n new EqualizerCoefficients(9.9391578543e-1, 3.0421072865e-3, 1.9937449618),\n new EqualizerCoefficients(9.9028307215e-1, 4.8584639242e-3, 1.9898465702),\n new EqualizerCoefficients(9.8485897264e-1, 7.5705136795e-3, 1.9837962543),\n new EqualizerCoefficients(9.7588512657e-1, 1.2057436715e-2, 1.9731772447),\n new EqualizerCoefficients(9.6228521814e-1, 1.8857390928e-2, 1.9556164694),\n new EqualizerCoefficients(9.4080933132e-1, 2.9595334338e-2, 1.9242054384),\n new EqualizerCoefficients(9.0702059196e-1, 4.6489704022e-2, 1.8653476166),\n new EqualizerCoefficients(8.5868004289e-1, 7.0659978553e-2, 1.7600401337),\n new EqualizerCoefficients(7.8409610788e-1, 1.0795194606e-1, 1.5450725522),\n new EqualizerCoefficients(6.8332861002e-1, 1.5833569499e-1, 1.1426447155),\n new EqualizerCoefficients(5.5267518228e-1, 2.2366240886e-1, 4.0186190803e-1),\n new EqualizerCoefficients(4.1811888447e-1, 2.9094055777e-1, -7.0905944223e-1)\n ];\n public channels: ChannelProcessor[] = [];\n public channelCount: number;\n\n public constructor(channelCount: number, bandMultipliers: number[]) {\n super(bandMultipliers);\n this.channelCount = channelCount;\n this.channels = this.createChannelProcessor();\n }\n\n public createChannelProcessor() {\n return Array.from({ length: this.channelCount }, () => {\n return new ChannelProcessor(this.bandMultipliers);\n });\n }\n\n public process(input: ChannelProcessorInput[]) {\n return this.channels.map((c, i) => {\n const { data, extremum, readInt, writeInt, bytes } = input[i];\n\n return c.process(data, extremum, bytes, readInt, writeInt);\n });\n }\n}\n","import { TransformCallback } from 'stream';\nimport { PCMTransformer, PCMTransformerOptions } from '../utils';\nimport { Equalizer } from './Equalizer';\n\ninterface EqualizerStreamOptions extends PCMTransformerOptions {\n bandMultiplier?: EqualizerBand[];\n disabled?: boolean;\n channels?: number;\n}\n\nexport interface EqualizerBand {\n band: number;\n gain: number;\n}\n\nexport class EqualizerStream extends PCMTransformer {\n public disabled = false;\n public bandMultipliers: number[] = new Array(Equalizer.BAND_COUNT).fill(0);\n public equalizer: Equalizer;\n public constructor(options?: EqualizerStreamOptions) {\n super(options);\n\n options = Object.assign(\n {},\n {\n bandMultiplier: [],\n channels: 1,\n disabled: false\n },\n options || {}\n );\n\n if (options.disabled) this.disabled = !!options.disabled;\n this.equalizer = new Equalizer(options.channels || 1, this.bandMultipliers);\n if (Array.isArray(options.bandMultiplier)) this._processBands(options.bandMultiplier);\n }\n\n public _processBands(multiplier: EqualizerBand[]) {\n for (const mul of multiplier) {\n if (mul.band > Equalizer.BAND_COUNT - 1 || mul.band < 0) throw new RangeError(`Band value out of range. Expected >0 & <${Equalizer.BAND_COUNT - 1}, received \"${mul.band}\"`);\n this.equalizer.setGain(mul.band, mul.gain);\n }\n }\n\n public disable() {\n this.disabled = true;\n }\n\n public enable() {\n this.disabled = false;\n }\n\n public toggle() {\n this.disabled = !this.disabled;\n }\n\n public _transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback): void {\n if (this.disabled) {\n this.push(chunk);\n return callback();\n }\n\n this.equalizer.process([\n {\n data: chunk,\n extremum: this.extremum,\n readInt: (b, idx) => this._readInt(b, idx),\n writeInt: (b, i, idx) => this._writeInt(b, i, idx),\n bytes: this.bytes\n }\n ]);\n\n this.push(chunk);\n\n return callback();\n }\n\n public getEQ() {\n return this.bandMultipliers.map((m, i) => ({\n band: i,\n gain: m\n })) as EqualizerBand[];\n }\n\n public setEQ(bands: EqualizerBand[]) {\n this._processBands(bands);\n }\n\n public resetEQ() {\n this._processBands(\n Array.from(\n {\n length: Equalizer.BAND_COUNT\n },\n (_, i) => ({\n band: i,\n gain: 0\n })\n )\n );\n }\n}\n","import { TransformCallback } from 'stream';\nimport { PCMTransformer, PCMTransformerOptions } from '../utils';\n\n/*\nMono: [0, 1, 2, 3, 4, 5]\nStereo: [0, 1, 0, 1, 2, 3, 2, 3, 4, 5, 4, 5]\n*/\n\nexport type MSTStrategy = 'm2s' | 's2m';\n\nexport interface MonoStereoTransformerOptions extends PCMTransformerOptions {\n strategy: MSTStrategy;\n}\n\nexport class MonoStereoTransformer extends PCMTransformer {\n public disabled = false;\n public strategy: MSTStrategy;\n\n public constructor(options?: MonoStereoTransformerOptions) {\n super(options);\n if (!['m2s', 's2m'].includes(options?.strategy as MSTStrategy)) {\n throw new TypeError(`Strategy must be \"m2s\" or \"s2m\"`);\n }\n\n this.strategy = options!.strategy;\n }\n\n public disable() {\n this.disabled = true;\n }\n\n public enable() {\n this.disabled = false;\n }\n\n public toggle() {\n this.disabled = !this.disabled;\n }\n\n public setStrategy(strategy: MSTStrategy) {\n this.strategy = strategy;\n }\n\n public _transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback): void {\n if (this.disabled) {\n this.push(chunk);\n return callback();\n }\n\n const len = Math.floor(chunk.length / 2) * 2;\n\n if (this.strategy === 'm2s') {\n this.push(this.toStereo(chunk, len));\n } else {\n this.push(this.toMono(chunk, len));\n }\n\n return callback();\n }\n\n public toStereo(sample: Buffer, len: number) {\n const bytes = this.bytes;\n const stereoBuffer = Buffer.alloc(len * 2);\n\n for (let i = 0; i < len; i += bytes) {\n stereoBuffer[i * 2 + 0] = sample[i];\n stereoBuffer[i * 2 + 1] = sample[i + 1];\n stereoBuffer[i * 2 + 2] = sample[i];\n stereoBuffer[i * 2 + 3] = sample[i + 1];\n }\n\n return stereoBuffer;\n }\n\n public toMono(sample: Buffer, len: number) {\n const bytes = this.bytes;\n const monoBuffer = Buffer.alloc(Math.floor(len / 2));\n\n for (let i = 0; i < len; i += bytes) {\n monoBuffer[i] = sample[i * 2 + 0];\n monoBuffer[i + 1] = sample[i * 2 + 1];\n }\n\n return monoBuffer;\n }\n}\n"],"mappings":"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","names":[]}
\ No newline at end of file
diff --git a/node_modules/@discord-player/equalizer/dist/index.mjs b/node_modules/@discord-player/equalizer/dist/index.mjs
deleted file mode 100644
index 71f5f5b..0000000
--- a/node_modules/@discord-player/equalizer/dist/index.mjs
+++ /dev/null
@@ -1,717 +0,0 @@
-var __defProp = Object.defineProperty;
-var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
-
-// src/biquad/Coefficients.ts
-var FilterType = {
- SinglePoleLowPassApprox: 0,
- SinglePoleLowPass: 1,
- LowPass: 2,
- HighPass: 3,
- BandPass: 4,
- Notch: 5,
- AllPass: 6,
- LowShelf: 7,
- HighShelf: 8,
- PeakingEQ: 9
-};
-var Q_BUTTERWORTH = Math.SQRT1_2;
-var Coefficients = class {
- constructor(data) {
- this.a1 = 0;
- this.a2 = 0;
- this.b0 = 0;
- this.b1 = 0;
- this.b2 = 0;
- if (data) {
- this.a1 = data.a1;
- this.a2 = data.a2;
- this.b0 = data.b0;
- this.b1 = data.b1;
- this.b2 = data.b2;
- }
- }
- static from(filter, samplingFreq, cutoffFreq, Q, dbGain = 0) {
- if (2 * cutoffFreq > samplingFreq) {
- throw new Error(`Cutoff frequency is too big!`);
- }
- if (Q < 0) {
- throw new Error(`Q may not be negative`);
- }
- const omega = 2 * Math.PI * cutoffFreq / samplingFreq;
- if (typeof filter === "string")
- filter = FilterType[filter];
- switch (filter) {
- case FilterType.SinglePoleLowPassApprox: {
- const alpha = omega / (omega + 1);
- return new Coefficients({
- a1: alpha - 1,
- a2: 0,
- b0: alpha,
- b1: 0,
- b2: 0
- });
- }
- case FilterType.SinglePoleLowPass: {
- const omega_t = Math.tan(omega / 2);
- const a0 = 1 + omega_t;
- return new Coefficients({
- a1: (omega_t - 1) / a0,
- a2: 0,
- b0: omega_t / a0,
- b1: omega_t / a0,
- b2: 0
- });
- }
- case FilterType.LowPass: {
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = (1 - omega_c) * 0.5;
- const b1 = 1 - omega_c;
- const b2 = (1 - omega_c) * 0.5;
- const a0 = 1 + alpha;
- const a1 = -2 * omega_c;
- const a2 = 1 - alpha;
- const div = 1 / a0;
- return new Coefficients({
- a1: a1 * div,
- a2: a2 * div,
- b0: b0 * div,
- b1: b1 * div,
- b2: b2 * div
- });
- }
- case FilterType.HighPass: {
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = (1 + omega_c) * 0.5;
- const b1 = -(1 + omega_c);
- const b2 = (1 + omega_c) * 0.5;
- const a0 = 1 + alpha;
- const a1 = -2 * omega_c;
- const a2 = 1 - alpha;
- const div = 1 / a0;
- return new Coefficients({
- a1: a1 * div,
- a2: a2 * div,
- b0: b0 * div,
- b1: b1 * div,
- b2: b2 * div
- });
- }
- case FilterType.Notch: {
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = 1;
- const b1 = -2 * omega_c;
- const b2 = 1;
- const a0 = 1 + alpha;
- const a1 = -2 * omega_c;
- const a2 = 1 - alpha;
- const div = 1 / a0;
- return new Coefficients({
- a1: a1 * div,
- a2: a2 * div,
- b0: b0 * div,
- b1: b1 * div,
- b2: b2 * div
- });
- }
- case FilterType.BandPass: {
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = omega_s / 2;
- const b1 = 0;
- const b2 = -(omega_s / 2);
- const a0 = 1 + alpha;
- const a1 = -2 * omega_c;
- const a2 = 1 - alpha;
- const div = 1 / a0;
- return new Coefficients({
- a1: a1 * div,
- a2: a2 * div,
- b0: b0 * div,
- b1: b1 * div,
- b2: b2 * div
- });
- }
- case FilterType.AllPass: {
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = 1 - alpha;
- const b1 = -2 * omega_c;
- const b2 = 1 + alpha;
- const a0 = 1 + alpha;
- const a1 = -2 * omega_c;
- const a2 = 1 - alpha;
- return new Coefficients({
- a1: a1 / a0,
- a2: a2 / a0,
- b0: b0 / a0,
- b1: b1 / a0,
- b2: b2 / a0
- });
- }
- case FilterType.LowShelf: {
- const a = Math.pow(10, dbGain / 40);
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = a * (a + 1 - (a - 1) * omega_c + 2 * alpha * Math.sqrt(a));
- const b1 = 2 * a * (a - 1 - (a + 1) * omega_c);
- const b2 = a * (a + 1 - (a - 1) * omega_c - 2 * alpha * Math.sqrt(a));
- const a0 = a + 1 + (a - 1) * omega_c + 2 * alpha * Math.sqrt(a);
- const a1 = -2 * (a - 1 + (a + 1) * omega_c);
- const a2 = a + 1 + (a - 1) * omega_c - 2 * alpha * Math.sqrt(a);
- return new Coefficients({
- a1: a1 / a0,
- a2: a2 / a0,
- b0: b0 / a0,
- b1: b1 / a0,
- b2: b2 / a0
- });
- }
- case FilterType.HighShelf: {
- const a = Math.pow(10, dbGain / 40);
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = a * (a + 1 + (a - 1) * omega_c + 2 * alpha * Math.sqrt(a));
- const b1 = -2 * a * (a - 1 + (a + 1) * omega_c);
- const b2 = a * (a + 1 + (a - 1) * omega_c - 2 * alpha * Math.sqrt(a));
- const a0 = a + 1 - (a - 1) * omega_c + 2 * alpha * Math.sqrt(a);
- const a1 = 2 * (a - 1 - (a + 1) * omega_c);
- const a2 = a + 1 - (a - 1) * omega_c - 2 * alpha * Math.sqrt(a);
- return new Coefficients({
- a1: a1 / a0,
- a2: a2 / a0,
- b0: b0 / a0,
- b1: b1 / a0,
- b2: b2 / a0
- });
- }
- case FilterType.PeakingEQ: {
- const a = Math.pow(10, dbGain / 40);
- const omega_s = Math.sin(omega);
- const omega_c = Math.cos(omega);
- const alpha = omega_s / (2 * Q);
- const b0 = 1 + alpha * a;
- const b1 = -2 * omega_c;
- const b2 = 1 - alpha * a;
- const a0 = 1 + alpha / a;
- const a1 = -2 * omega_c;
- const a2 = 1 - alpha / a;
- return new Coefficients({
- a1: a1 / a0,
- a2: a2 / a0,
- b0: b0 / a0,
- b1: b1 / a0,
- b2: b2 / a0
- });
- }
- default:
- throw new TypeError("Invalid filter type");
- }
- }
-};
-__name(Coefficients, "Coefficients");
-
-// src/biquad/Biquad.ts
-var BiquadFilter = class {
- constructor(coefficients) {
- this.coefficients = coefficients;
- this.x1 = 0;
- this.x2 = 0;
- this.y1 = 0;
- this.y2 = 0;
- this.s1 = 0;
- this.s2 = 0;
- }
- setFilter(filter, options) {
- const coefficients = Coefficients.from(filter, options.fs, options.f0, options.Q, options.gain);
- this.update(coefficients);
- }
- update(coefficients) {
- this.coefficients = coefficients;
- }
- replace(coefficients) {
- this.coefficients = coefficients;
- }
- reset() {
- this.x1 = 0;
- this.x2 = 0;
- this.y1 = 0;
- this.y2 = 0;
- this.s1 = 0;
- this.s2 = 0;
- }
- run(input) {
- const { a1, a2, b0, b1, b2 } = this.coefficients;
- const out = b0 * input + b1 * this.x1 + b2 * this.x2 - a1 * this.y1 - a2 * this.y2;
- this.x2 = this.x1;
- this.x1 = input;
- this.y2 = this.y1;
- this.y1 = out;
- return out;
- }
- runTransposed(input) {
- const { a1, a2, b0, b1, b2 } = this.coefficients;
- const out = this.s1 + b0 * input;
- this.s1 = this.s2 + b1 * input - a1 * out;
- this.s2 = b2 * input - a2 * out;
- return out;
- }
-};
-__name(BiquadFilter, "BiquadFilter");
-
-// src/utils/Frequency.ts
-var Frequency = class {
- constructor(__val) {
- this.__val = __val;
- if (typeof __val !== "number" || isNaN(__val) || __val === Infinity)
- throw new TypeError("Frequency value must be a number");
- if (this.__val < 0)
- throw new Error(`Frequency value cannot be negative (${__val})`);
- }
- khz() {
- return this.__val * 1e3;
- }
- mhz() {
- return this.__val * 1e6;
- }
- hz() {
- return this.__val;
- }
- dt() {
- return 1 / this.__val;
- }
- valueOf() {
- return this.__val;
- }
- toString() {
- return `${this.__val}Hz`;
- }
- toJSON() {
- return this.toString();
- }
-};
-__name(Frequency, "Frequency");
-
-// src/utils/PCMTransformer.ts
-import { Transform } from "stream";
-var PCMTransformer = class extends Transform {
- constructor(options = {}) {
- super(options);
- this.type = "s16le";
- options.type ?? (options.type = "s16le");
- switch (options.type) {
- case "s16be":
- case "s16le":
- this.type = options.type;
- this.bits = 16;
- break;
- case "s32be":
- case "s32le":
- this.type = options.type;
- this.bits = 32;
- break;
- default:
- throw new TypeError(`Expected type to be one of ${["s16be", "s16le", "s32be", "s32le"].join(", ")}, got "${options.type}"`);
- }
- this.bytes = this.bits / 8;
- this.extremum = Math.pow(2, this.bits - 1);
- }
- _readInt(buffer, index) {
- const method = `readInt${this.type.substring(1).toUpperCase()}`;
- return buffer[method](index);
- }
- _writeInt(buffer, int, index) {
- const method = `writeInt${this.type.substring(1).toUpperCase()}`;
- return buffer[method](int, index);
- }
- clamp(val, max = this.extremum - 1, min = -this.extremum) {
- return Math.min(max, Math.max(min, val));
- }
-};
-__name(PCMTransformer, "PCMTransformer");
-
-// src/biquad/BiquadStream.ts
-var BiquadStream = class extends PCMTransformer {
- constructor(options = {}) {
- super(options);
- this.disabled = false;
- this.sample = 48e3;
- this.cutoff = 80;
- this.gain = 0;
- this.Q = Q_BUTTERWORTH;
- this.disabled = !!options.disabled;
- if ("sample" in options)
- this.sample = options.sample;
- if ("cutoff" in options)
- this.cutoff = options.cutoff;
- if ("gain" in options)
- this.gain = options.gain;
- if ("Q" in options)
- this.Q = options.Q;
- if ("filter" in options) {
- this.filter = options.filter;
- if (this.filter != null) {
- this.biquad = new BiquadFilter(Coefficients.from(this.filter, this.sample, this.cutoff, this.Q, this.gain));
- }
- }
- }
- disable() {
- this.disabled = true;
- }
- enable() {
- this.disabled = false;
- }
- toggle() {
- this.disabled = !this.disabled;
- }
- getFilterName() {
- if (this.filter == null)
- return null;
- if (typeof this.filter === "string")
- return this.filter;
- return Object.entries(FilterType).find((r) => r[1] === this.filter)?.[0];
- }
- update(options) {
- if ("sample" in options)
- this.sample = options.sample;
- if ("cutoff" in options)
- this.cutoff = options.cutoff;
- if ("gain" in options)
- this.gain = options.gain;
- if ("Q" in options)
- this.Q = options.Q;
- if ("filter" in options)
- this.filter = options.filter;
- if (this.filter != null) {
- this.biquad = new BiquadFilter(Coefficients.from(this.filter, this.sample, this.cutoff, this.Q, this.gain));
- }
- }
- setFilter(filter) {
- this.update({ filter });
- }
- setQ(Q) {
- this.update({ Q });
- }
- setSample(fs) {
- this.update({ sample: fs });
- }
- setCutoff(f0) {
- this.update({ cutoff: f0 });
- }
- setGain(dB) {
- this.update({ gain: dB });
- }
- _transform(chunk, encoding, callback) {
- if (this.disabled || !this.biquad) {
- this.push(chunk);
- return callback();
- }
- const endIndex = Math.floor(chunk.length / 2) * 2;
- const { bytes, extremum } = this;
- for (let sampleIndex = 0; sampleIndex < endIndex; sampleIndex += bytes) {
- const int = this._readInt(chunk, sampleIndex);
- const result = this.biquad.run(int);
- const val = Math.min(extremum - 1, Math.max(-extremum, result));
- this._writeInt(chunk, val, sampleIndex);
- }
- this.push(chunk);
- return callback();
- }
-};
-__name(BiquadStream, "BiquadStream");
-
-// src/equalizer/ChannelProcessor.ts
-var ChannelProcessor = class {
- constructor(bandMultipliers) {
- this.history = new Array(Equalizer.BAND_COUNT * 6).fill(0);
- this.bandMultipliers = bandMultipliers;
- this.current = 0;
- this.m1 = 2;
- this.m2 = 1;
- }
- process(samples, extremum = 131072, bytes = 2, readInt, writeInt) {
- const endIndex = Math.floor(samples.length / 2) * 2;
- for (let sampleIndex = 0; sampleIndex < endIndex; sampleIndex += bytes) {
- const sample = readInt?.(samples, sampleIndex) ?? samples.readInt16LE(sampleIndex);
- let result = sample * 0.25;
- for (let bandIndex = 0; bandIndex < Equalizer.BAND_COUNT; bandIndex++) {
- const x = bandIndex * 6;
- const y = x + 3;
- const coefficients = Equalizer.Coefficients48000[bandIndex];
- const bandResult = coefficients.alpha * (sample - this.history[x + this.m2]) + coefficients.gamma * this.history[y + this.m1] - coefficients.beta * this.history[y + this.m2];
- this.history[x + this.current] = sample;
- this.history[y + this.current] = bandResult;
- result += bandResult * this.bandMultipliers[bandIndex];
- }
- const val = Math.min(extremum - 1, Math.max(-extremum, result * 4));
- writeInt?.(samples, val, sampleIndex) ?? samples.writeInt16LE(val, sampleIndex);
- if (++this.current === 3) {
- this.current = 0;
- }
- if (++this.m1 === 3) {
- this.m1 = 0;
- }
- if (++this.m2 === 3) {
- this.m2 = 0;
- }
- }
- return samples;
- }
- reset() {
- this.history.fill(0);
- }
-};
-__name(ChannelProcessor, "ChannelProcessor");
-
-// src/equalizer/Coefficients.ts
-var EqualizerCoefficients = class {
- constructor(beta, alpha, gamma) {
- this.beta = beta;
- this.alpha = alpha;
- this.gamma = gamma;
- }
- setBeta(v) {
- this.beta = v;
- }
- setAlpha(v) {
- this.alpha = v;
- }
- setGamma(v) {
- this.gamma = v;
- }
- toJSON() {
- const { alpha, beta, gamma } = this;
- return { alpha, beta, gamma };
- }
-};
-__name(EqualizerCoefficients, "EqualizerCoefficients");
-
-// src/equalizer/EqualizerConfiguration.ts
-var EqualizerConfiguration = class {
- constructor(bandMultipliers) {
- this.bandMultipliers = bandMultipliers;
- }
- setGain(band, value) {
- if (this.isValidBand(band)) {
- this.bandMultipliers[band] = Math.max(Math.min(value, 1), -0.25);
- }
- }
- getGain(band) {
- if (this.isValidBand(band)) {
- return this.bandMultipliers[band];
- } else {
- return 0;
- }
- }
- isValidBand(band) {
- return band >= 0 && band < this.bandMultipliers.length;
- }
-};
-__name(EqualizerConfiguration, "EqualizerConfiguration");
-
-// src/equalizer/Equalizer.ts
-var Equalizer = class extends EqualizerConfiguration {
- constructor(channelCount, bandMultipliers) {
- super(bandMultipliers);
- this.channels = [];
- this.channelCount = channelCount;
- this.channels = this.createChannelProcessor();
- }
- createChannelProcessor() {
- return Array.from({ length: this.channelCount }, () => {
- return new ChannelProcessor(this.bandMultipliers);
- });
- }
- process(input) {
- return this.channels.map((c, i) => {
- const { data, extremum, readInt, writeInt, bytes } = input[i];
- return c.process(data, extremum, bytes, readInt, writeInt);
- });
- }
-};
-__name(Equalizer, "Equalizer");
-Equalizer.BAND_COUNT = 15;
-Equalizer.SAMPLE_RATE = 48e3;
-Equalizer.Coefficients48000 = [
- new EqualizerCoefficients(0.99847546664, 76226668143e-14, 1.9984647656),
- new EqualizerCoefficients(0.99756184654, 0.0012190767289, 1.9975344645),
- new EqualizerCoefficients(0.99616261379, 0.0019186931041, 1.9960947369),
- new EqualizerCoefficients(0.99391578543, 0.0030421072865, 1.9937449618),
- new EqualizerCoefficients(0.99028307215, 0.0048584639242, 1.9898465702),
- new EqualizerCoefficients(0.98485897264, 0.0075705136795, 1.9837962543),
- new EqualizerCoefficients(0.97588512657, 0.012057436715, 1.9731772447),
- new EqualizerCoefficients(0.96228521814, 0.018857390928, 1.9556164694),
- new EqualizerCoefficients(0.94080933132, 0.029595334338, 1.9242054384),
- new EqualizerCoefficients(0.90702059196, 0.046489704022, 1.8653476166),
- new EqualizerCoefficients(0.85868004289, 0.070659978553, 1.7600401337),
- new EqualizerCoefficients(0.78409610788, 0.10795194606, 1.5450725522),
- new EqualizerCoefficients(0.68332861002, 0.15833569499, 1.1426447155),
- new EqualizerCoefficients(0.55267518228, 0.22366240886, 0.40186190803),
- new EqualizerCoefficients(0.41811888447, 0.29094055777, -0.70905944223)
-];
-
-// src/equalizer/EqualizerStream.ts
-var EqualizerStream = class extends PCMTransformer {
- constructor(options) {
- super(options);
- this.disabled = false;
- this.bandMultipliers = new Array(Equalizer.BAND_COUNT).fill(0);
- options = Object.assign(
- {},
- {
- bandMultiplier: [],
- channels: 1,
- disabled: false
- },
- options || {}
- );
- if (options.disabled)
- this.disabled = !!options.disabled;
- this.equalizer = new Equalizer(options.channels || 1, this.bandMultipliers);
- if (Array.isArray(options.bandMultiplier))
- this._processBands(options.bandMultiplier);
- }
- _processBands(multiplier) {
- for (const mul of multiplier) {
- if (mul.band > Equalizer.BAND_COUNT - 1 || mul.band < 0)
- throw new RangeError(`Band value out of range. Expected >0 & <${Equalizer.BAND_COUNT - 1}, received "${mul.band}"`);
- this.equalizer.setGain(mul.band, mul.gain);
- }
- }
- disable() {
- this.disabled = true;
- }
- enable() {
- this.disabled = false;
- }
- toggle() {
- this.disabled = !this.disabled;
- }
- _transform(chunk, encoding, callback) {
- if (this.disabled) {
- this.push(chunk);
- return callback();
- }
- this.equalizer.process([
- {
- data: chunk,
- extremum: this.extremum,
- readInt: (b, idx) => this._readInt(b, idx),
- writeInt: (b, i, idx) => this._writeInt(b, i, idx),
- bytes: this.bytes
- }
- ]);
- this.push(chunk);
- return callback();
- }
- getEQ() {
- return this.bandMultipliers.map((m, i) => ({
- band: i,
- gain: m
- }));
- }
- setEQ(bands) {
- this._processBands(bands);
- }
- resetEQ() {
- this._processBands(
- Array.from(
- {
- length: Equalizer.BAND_COUNT
- },
- (_, i) => ({
- band: i,
- gain: 0
- })
- )
- );
- }
-};
-__name(EqualizerStream, "EqualizerStream");
-
-// src/audio/MonoStereoTransformer.ts
-var MonoStereoTransformer = class extends PCMTransformer {
- constructor(options) {
- super(options);
- this.disabled = false;
- if (!["m2s", "s2m"].includes(options?.strategy)) {
- throw new TypeError(`Strategy must be "m2s" or "s2m"`);
- }
- this.strategy = options.strategy;
- }
- disable() {
- this.disabled = true;
- }
- enable() {
- this.disabled = false;
- }
- toggle() {
- this.disabled = !this.disabled;
- }
- setStrategy(strategy) {
- this.strategy = strategy;
- }
- _transform(chunk, encoding, callback) {
- if (this.disabled) {
- this.push(chunk);
- return callback();
- }
- const len = Math.floor(chunk.length / 2) * 2;
- if (this.strategy === "m2s") {
- this.push(this.toStereo(chunk, len));
- } else {
- this.push(this.toMono(chunk, len));
- }
- return callback();
- }
- toStereo(sample, len) {
- const bytes = this.bytes;
- const stereoBuffer = Buffer.alloc(len * 2);
- for (let i = 0; i < len; i += bytes) {
- stereoBuffer[i * 2 + 0] = sample[i];
- stereoBuffer[i * 2 + 1] = sample[i + 1];
- stereoBuffer[i * 2 + 2] = sample[i];
- stereoBuffer[i * 2 + 3] = sample[i + 1];
- }
- return stereoBuffer;
- }
- toMono(sample, len) {
- const bytes = this.bytes;
- const monoBuffer = Buffer.alloc(Math.floor(len / 2));
- for (let i = 0; i < len; i += bytes) {
- monoBuffer[i] = sample[i * 2 + 0];
- monoBuffer[i + 1] = sample[i * 2 + 1];
- }
- return monoBuffer;
- }
-};
-__name(MonoStereoTransformer, "MonoStereoTransformer");
-
-// src/index.ts
-var version = "0.1.3";
-export {
- BiquadFilter,
- BiquadStream,
- ChannelProcessor,
- Coefficients,
- Equalizer,
- EqualizerCoefficients,
- EqualizerConfiguration,
- EqualizerStream,
- FilterType,
- Frequency,
- MonoStereoTransformer,
- PCMTransformer,
- Q_BUTTERWORTH,
- version
-};
-//# sourceMappingURL=index.mjs.map
\ No newline at end of file
diff --git a/node_modules/@discord-player/equalizer/dist/index.mjs.map b/node_modules/@discord-player/equalizer/dist/index.mjs.map
deleted file mode 100644
index 1173559..0000000
--- a/node_modules/@discord-player/equalizer/dist/index.mjs.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../src/biquad/Coefficients.ts","../src/biquad/Biquad.ts","../src/utils/Frequency.ts","../src/utils/PCMTransformer.ts","../src/biquad/BiquadStream.ts","../src/equalizer/ChannelProcessor.ts","../src/equalizer/Coefficients.ts","../src/equalizer/EqualizerConfiguration.ts","../src/equalizer/Equalizer.ts","../src/equalizer/EqualizerStream.ts","../src/audio/MonoStereoTransformer.ts","../src/index.ts"],"sourcesContent":["export const FilterType = {\n SinglePoleLowPassApprox: 0,\n SinglePoleLowPass: 1,\n LowPass: 2,\n HighPass: 3,\n BandPass: 4,\n Notch: 5,\n AllPass: 6,\n LowShelf: 7,\n HighShelf: 8,\n PeakingEQ: 9\n} as const;\n\nexport type BiquadFilters = keyof typeof FilterType | (typeof FilterType)[keyof typeof FilterType];\n\ninterface CoefficientsInit {\n a1: number;\n a2: number;\n b0: number;\n b1: number;\n b2: number;\n}\n\nexport const Q_BUTTERWORTH = Math.SQRT1_2;\n\nexport class Coefficients {\n // Denominator coefficients\n public a1 = 0;\n public a2 = 0;\n\n // Nominator coefficients\n public b0 = 0;\n public b1 = 0;\n public b2 = 0;\n\n public constructor(data?: CoefficientsInit) {\n if (data) {\n this.a1 = data.a1;\n this.a2 = data.a2;\n this.b0 = data.b0;\n this.b1 = data.b1;\n this.b2 = data.b2;\n }\n }\n\n public static from(filter: BiquadFilters, samplingFreq: number, cutoffFreq: number, Q: number, dbGain = 0) {\n if (2.0 * cutoffFreq > samplingFreq) {\n throw new Error(`Cutoff frequency is too big!`);\n }\n\n if (Q < 0) {\n throw new Error(`Q may not be negative`);\n }\n\n const omega = (2.0 * Math.PI * cutoffFreq) / samplingFreq;\n\n if (typeof filter === 'string') filter = FilterType[filter];\n\n switch (filter) {\n case FilterType.SinglePoleLowPassApprox: {\n const alpha = omega / (omega + 1.0);\n\n return new Coefficients({\n a1: alpha - 1.0,\n a2: 0.0,\n b0: alpha,\n b1: 0.0,\n b2: 0.0\n });\n }\n case FilterType.SinglePoleLowPass: {\n const omega_t = Math.tan(omega / 2.0);\n const a0 = 1.0 + omega_t;\n\n return new Coefficients({\n a1: (omega_t - 1.0) / a0,\n a2: 0.0,\n b0: omega_t / a0,\n b1: omega_t / a0,\n b2: 0.0\n });\n }\n case FilterType.LowPass: {\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = (1.0 - omega_c) * 0.5;\n const b1 = 1.0 - omega_c;\n const b2 = (1.0 - omega_c) * 0.5;\n const a0 = 1.0 + alpha;\n const a1 = -2.0 * omega_c;\n const a2 = 1.0 - alpha;\n\n const div = 1.0 / a0;\n\n return new Coefficients({\n a1: a1 * div,\n a2: a2 * div,\n b0: b0 * div,\n b1: b1 * div,\n b2: b2 * div\n });\n }\n case FilterType.HighPass: {\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = (1.0 + omega_c) * 0.5;\n const b1 = -(1.0 + omega_c);\n const b2 = (1.0 + omega_c) * 0.5;\n const a0 = 1.0 + alpha;\n const a1 = -2.0 * omega_c;\n const a2 = 1.0 - alpha;\n\n const div = 1.0 / a0;\n\n return new Coefficients({\n a1: a1 * div,\n a2: a2 * div,\n b0: b0 * div,\n b1: b1 * div,\n b2: b2 * div\n });\n }\n case FilterType.Notch: {\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = 1.0;\n const b1 = -2.0 * omega_c;\n const b2 = 1.0;\n const a0 = 1.0 + alpha;\n const a1 = -2.0 * omega_c;\n const a2 = 1.0 - alpha;\n\n const div = 1.0 / a0;\n\n return new Coefficients({\n a1: a1 * div,\n a2: a2 * div,\n b0: b0 * div,\n b1: b1 * div,\n b2: b2 * div\n });\n }\n case FilterType.BandPass: {\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = omega_s / 2.0;\n const b1 = 0;\n const b2 = -(omega_s / 2.0);\n const a0 = 1.0 + alpha;\n const a1 = -2.0 * omega_c;\n const a2 = 1.0 - alpha;\n\n const div = 1.0 / a0;\n\n return new Coefficients({\n a1: a1 * div,\n a2: a2 * div,\n b0: b0 * div,\n b1: b1 * div,\n b2: b2 * div\n });\n }\n case FilterType.AllPass: {\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = 1.0 - alpha;\n const b1 = -2.0 * omega_c;\n const b2 = 1.0 + alpha;\n const a0 = 1.0 + alpha;\n const a1 = -2.0 * omega_c;\n const a2 = 1.0 - alpha;\n\n return new Coefficients({\n a1: a1 / a0,\n a2: a2 / a0,\n b0: b0 / a0,\n b1: b1 / a0,\n b2: b2 / a0\n });\n }\n case FilterType.LowShelf: {\n const a = Math.pow(10.0, dbGain / 40.0);\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = a * (a + 1.0 - (a - 1.0) * omega_c + 2.0 * alpha * Math.sqrt(a));\n const b1 = 2.0 * a * (a - 1.0 - (a + 1.0) * omega_c);\n const b2 = a * (a + 1.0 - (a - 1.0) * omega_c - 2.0 * alpha * Math.sqrt(a));\n const a0 = a + 1.0 + (a - 1.0) * omega_c + 2.0 * alpha * Math.sqrt(a);\n const a1 = -2.0 * (a - 1.0 + (a + 1.0) * omega_c);\n const a2 = a + 1.0 + (a - 1.0) * omega_c - 2.0 * alpha * Math.sqrt(a);\n\n return new Coefficients({\n a1: a1 / a0,\n a2: a2 / a0,\n b0: b0 / a0,\n b1: b1 / a0,\n b2: b2 / a0\n });\n }\n case FilterType.HighShelf: {\n const a = Math.pow(10.0, dbGain / 40.0);\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = a * (a + 1.0 + (a - 1.0) * omega_c + 2.0 * alpha * Math.sqrt(a));\n const b1 = -2.0 * a * (a - 1.0 + (a + 1.0) * omega_c);\n const b2 = a * (a + 1.0 + (a - 1.0) * omega_c - 2.0 * alpha * Math.sqrt(a));\n const a0 = a + 1.0 - (a - 1.0) * omega_c + 2.0 * alpha * Math.sqrt(a);\n const a1 = 2.0 * (a - 1.0 - (a + 1.0) * omega_c);\n const a2 = a + 1.0 - (a - 1.0) * omega_c - 2.0 * alpha * Math.sqrt(a);\n\n return new Coefficients({\n a1: a1 / a0,\n a2: a2 / a0,\n b0: b0 / a0,\n b1: b1 / a0,\n b2: b2 / a0\n });\n }\n case FilterType.PeakingEQ: {\n const a = Math.pow(10.0, dbGain / 40.0);\n const omega_s = Math.sin(omega);\n const omega_c = Math.cos(omega);\n const alpha = omega_s / (2.0 * Q);\n\n const b0 = 1.0 + alpha * a;\n const b1 = -2.0 * omega_c;\n const b2 = 1.0 - alpha * a;\n const a0 = 1.0 + alpha / a;\n const a1 = -2.0 * omega_c;\n const a2 = 1.0 - alpha / a;\n\n return new Coefficients({\n a1: a1 / a0,\n a2: a2 / a0,\n b0: b0 / a0,\n b1: b1 / a0,\n b2: b2 / a0\n });\n }\n default:\n throw new TypeError('Invalid filter type');\n }\n }\n}\n","import { BiquadFilters, Coefficients } from './Coefficients';\n\nexport interface BiquadSetFilterProps {\n f0: number;\n fs: number;\n Q: number;\n gain?: number;\n}\n\nexport class BiquadFilter {\n public x1 = 0.0;\n public x2 = 0.0;\n public y1 = 0.0;\n public y2 = 0.0;\n public s1 = 0.0;\n public s2 = 0.0;\n\n public constructor(public coefficients: Coefficients) {}\n\n public setFilter(filter: BiquadFilters, options: BiquadSetFilterProps) {\n const coefficients = Coefficients.from(filter, options.fs, options.f0, options.Q, options.gain);\n\n this.update(coefficients);\n }\n\n public update(coefficients: Coefficients) {\n this.coefficients = coefficients;\n }\n\n public replace(coefficients: Coefficients) {\n this.coefficients = coefficients;\n }\n\n public reset() {\n this.x1 = 0.0;\n this.x2 = 0.0;\n this.y1 = 0.0;\n this.y2 = 0.0;\n this.s1 = 0.0;\n this.s2 = 0.0;\n }\n\n public run(input: number) {\n const { a1, a2, b0, b1, b2 } = this.coefficients;\n\n const out = b0 * input + b1 * this.x1 + b2 * this.x2 - a1 * this.y1 - a2 * this.y2;\n\n this.x2 = this.x1;\n this.x1 = input;\n this.y2 = this.y1;\n this.y1 = out;\n\n return out;\n }\n\n public runTransposed(input: number) {\n const { a1, a2, b0, b1, b2 } = this.coefficients;\n\n const out = this.s1 + b0 * input;\n\n this.s1 = this.s2 + b1 * input - a1 * out;\n this.s2 = b2 * input - a2 * out;\n\n return out;\n }\n}\n","export class Frequency {\n public constructor(private __val: number) {\n if (typeof __val !== 'number' || isNaN(__val) || __val === Infinity) throw new TypeError('Frequency value must be a number');\n if (this.__val < 0) throw new Error(`Frequency value cannot be negative (${__val})`);\n }\n\n public khz() {\n return this.__val * 1000.0;\n }\n\n public mhz() {\n return this.__val * 1_000_000.0;\n }\n\n public hz() {\n return this.__val;\n }\n\n public dt() {\n return 1.0 / this.__val;\n }\n\n public valueOf() {\n return this.__val;\n }\n\n public toString() {\n return `${this.__val}Hz`;\n }\n\n public toJSON() {\n return this.toString();\n }\n}\n","import { Transform, TransformOptions } from 'stream';\n\nexport type PCMType = `s${16 | 32}${'l' | 'b'}e`;\n\nexport interface PCMTransformerOptions extends TransformOptions {\n type?: PCMType;\n}\n\nexport class PCMTransformer extends Transform {\n public readonly type: PCMType = 's16le';\n public bits: number;\n public bytes: number;\n public extremum: number;\n\n public constructor(options: PCMTransformerOptions = {}) {\n super(options);\n\n options.type ??= 's16le';\n\n switch (options.type) {\n case 's16be':\n case 's16le':\n this.type = options.type;\n this.bits = 16;\n break;\n case 's32be':\n case 's32le':\n this.type = options.type;\n this.bits = 32;\n break;\n default:\n throw new TypeError(`Expected type to be one of ${(['s16be', 's16le', 's32be', 's32le'] as PCMType[]).join(', ')}, got \"${options.type}\"`);\n }\n\n this.bytes = this.bits / 8;\n this.extremum = Math.pow(2, this.bits - 1);\n }\n\n public _readInt(buffer: Buffer, index: number) {\n const method = `readInt${this.type.substring(1).toUpperCase()}` as `readInt${16 | 32}${'L' | 'B'}E`;\n return buffer[method](index);\n }\n\n public _writeInt(buffer: Buffer, int: number, index: number) {\n const method = `writeInt${this.type.substring(1).toUpperCase()}` as `writeInt${16 | 32}${'L' | 'B'}E`;\n return buffer[method](int, index);\n }\n\n public clamp(val: number, max = this.extremum - 1, min = -this.extremum) {\n return Math.min(max, Math.max(min, val));\n }\n}\n","import { TransformCallback } from 'stream';\nimport { PCMTransformer, PCMTransformerOptions } from '../utils';\nimport { BiquadFilter } from './Biquad';\nimport { BiquadFilters, Coefficients, FilterType, Q_BUTTERWORTH } from './Coefficients';\n\nexport interface BiquadStreamOptions extends PCMTransformerOptions {\n disabled?: boolean;\n filter?: BiquadFilters;\n Q?: number;\n sample?: number;\n cutoff?: number;\n gain?: number;\n}\n\nexport interface BiquadFilterUpdateData {\n filter?: BiquadFilters;\n Q?: number;\n sample?: number;\n cutoff?: number;\n gain?: number;\n}\n\nexport class BiquadStream extends PCMTransformer {\n public disabled = false;\n public biquad!: BiquadFilter;\n public sample = 48000;\n public cutoff = 80;\n public gain = 0;\n public filter!: BiquadFilters;\n public Q = Q_BUTTERWORTH;\n public constructor(options: BiquadStreamOptions = {}) {\n super(options);\n\n this.disabled = !!options.disabled;\n\n if ('sample' in options) this.sample = options.sample!;\n if ('cutoff' in options) this.cutoff = options.cutoff!;\n if ('gain' in options) this.gain = options.gain!;\n if ('Q' in options) this.Q = options.Q!;\n if ('filter' in options) {\n this.filter = options.filter!;\n if (this.filter != null) {\n this.biquad = new BiquadFilter(Coefficients.from(this.filter, this.sample, this.cutoff, this.Q, this.gain));\n }\n }\n }\n\n public disable() {\n this.disabled = true;\n }\n\n public enable() {\n this.disabled = false;\n }\n\n public toggle() {\n this.disabled = !this.disabled;\n }\n\n public getFilterName() {\n if (this.filter == null) return null;\n if (typeof this.filter === 'string') return this.filter;\n return Object.entries(FilterType).find((r) => r[1] === this.filter)?.[0] as BiquadFilters;\n }\n\n public update(options: BiquadFilterUpdateData) {\n if ('sample' in options) this.sample = options.sample!;\n if ('cutoff' in options) this.cutoff = options.cutoff!;\n if ('gain' in options) this.gain = options.gain!;\n if ('Q' in options) this.Q = options.Q!;\n if ('filter' in options) this.filter = options.filter!;\n\n if (this.filter != null) {\n this.biquad = new BiquadFilter(Coefficients.from(this.filter, this.sample, this.cutoff, this.Q, this.gain));\n }\n }\n\n public setFilter(filter: BiquadFilters) {\n this.update({ filter });\n }\n\n public setQ(Q: number) {\n this.update({ Q });\n }\n\n public setSample(fs: number) {\n this.update({ sample: fs });\n }\n\n public setCutoff(f0: number) {\n this.update({ cutoff: f0 });\n }\n\n public setGain(dB: number) {\n this.update({ gain: dB });\n }\n\n public _transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback) {\n if (this.disabled || !this.biquad) {\n this.push(chunk);\n return callback();\n }\n\n const endIndex = Math.floor(chunk.length / 2) * 2;\n const { bytes, extremum } = this;\n\n for (let sampleIndex = 0; sampleIndex < endIndex; sampleIndex += bytes) {\n const int = this._readInt(chunk, sampleIndex);\n const result = this.biquad.run(int);\n const val = Math.min(extremum - 1, Math.max(-extremum, result));\n this._writeInt(chunk, val, sampleIndex);\n }\n\n this.push(chunk);\n return callback();\n }\n}\n","import { Equalizer } from './Equalizer';\n\nexport type ReadIntCallback = (buffer: Buffer, index: number) => number;\nexport type WriteIntCallback = (buffer: Buffer, int: number, index: number) => number;\n\nexport class ChannelProcessor {\n public history: number[];\n public bandMultipliers: number[];\n public current: number;\n public m1: number;\n public m2: number;\n\n public constructor(bandMultipliers: number[]) {\n this.history = new Array(Equalizer.BAND_COUNT * 6).fill(0);\n this.bandMultipliers = bandMultipliers;\n this.current = 0;\n this.m1 = 2;\n this.m2 = 1;\n }\n\n public process(samples: Buffer, extremum = 131072, bytes = 2, readInt?: ReadIntCallback, writeInt?: WriteIntCallback) {\n const endIndex = Math.floor(samples.length / 2) * 2;\n for (let sampleIndex = 0; sampleIndex < endIndex; sampleIndex += bytes) {\n const sample = readInt?.(samples, sampleIndex) ?? samples.readInt16LE(sampleIndex);\n let result = sample * 0.25;\n\n for (let bandIndex = 0; bandIndex < Equalizer.BAND_COUNT; bandIndex++) {\n const x = bandIndex * 6;\n const y = x + 3;\n\n const coefficients = Equalizer.Coefficients48000[bandIndex];\n\n const bandResult = coefficients.alpha * (sample - this.history[x + this.m2]) + coefficients.gamma * this.history[y + this.m1] - coefficients.beta * this.history[y + this.m2];\n\n this.history[x + this.current] = sample;\n this.history[y + this.current] = bandResult;\n\n result += bandResult * this.bandMultipliers[bandIndex];\n }\n\n const val = Math.min(extremum - 1, Math.max(-extremum, result * 4.0));\n writeInt?.(samples, val, sampleIndex) ?? samples.writeInt16LE(val, sampleIndex);\n\n if (++this.current === 3) {\n this.current = 0;\n }\n\n if (++this.m1 === 3) {\n this.m1 = 0;\n }\n\n if (++this.m2 === 3) {\n this.m2 = 0;\n }\n }\n\n return samples;\n }\n\n public reset() {\n this.history.fill(0.0);\n }\n}\n","export class EqualizerCoefficients {\n public constructor(public beta: number, public alpha: number, public gamma: number) {}\n\n public setBeta(v: number) {\n this.beta = v;\n }\n\n public setAlpha(v: number) {\n this.alpha = v;\n }\n\n public setGamma(v: number) {\n this.gamma = v;\n }\n\n public toJSON() {\n const { alpha, beta, gamma } = this;\n\n return { alpha, beta, gamma };\n }\n}\n","export class EqualizerConfiguration {\n public constructor(public bandMultipliers: number[]) {}\n\n public setGain(band: number, value: number) {\n if (this.isValidBand(band)) {\n this.bandMultipliers[band] = Math.max(Math.min(value, 1.0), -0.25);\n }\n }\n\n public getGain(band: number) {\n if (this.isValidBand(band)) {\n return this.bandMultipliers[band];\n } else {\n return 0.0;\n }\n }\n\n public isValidBand(band: number) {\n return band >= 0 && band < this.bandMultipliers.length;\n }\n}\n","import { ChannelProcessor, ReadIntCallback, WriteIntCallback } from './ChannelProcessor';\nimport { EqualizerCoefficients } from './Coefficients';\nimport { EqualizerConfiguration } from './EqualizerConfiguration';\n\nexport interface ChannelProcessorInput {\n data: Buffer;\n readInt?: ReadIntCallback;\n writeInt?: WriteIntCallback;\n extremum?: number;\n bytes?: number;\n}\n\nexport class Equalizer extends EqualizerConfiguration {\n public static BAND_COUNT = 15 as const;\n public static SAMPLE_RATE = 48000 as const;\n public static Coefficients48000 = [\n new EqualizerCoefficients(9.9847546664e-1, 7.6226668143e-4, 1.9984647656),\n new EqualizerCoefficients(9.9756184654e-1, 1.2190767289e-3, 1.9975344645),\n new EqualizerCoefficients(9.9616261379e-1, 1.9186931041e-3, 1.9960947369),\n new EqualizerCoefficients(9.9391578543e-1, 3.0421072865e-3, 1.9937449618),\n new EqualizerCoefficients(9.9028307215e-1, 4.8584639242e-3, 1.9898465702),\n new EqualizerCoefficients(9.8485897264e-1, 7.5705136795e-3, 1.9837962543),\n new EqualizerCoefficients(9.7588512657e-1, 1.2057436715e-2, 1.9731772447),\n new EqualizerCoefficients(9.6228521814e-1, 1.8857390928e-2, 1.9556164694),\n new EqualizerCoefficients(9.4080933132e-1, 2.9595334338e-2, 1.9242054384),\n new EqualizerCoefficients(9.0702059196e-1, 4.6489704022e-2, 1.8653476166),\n new EqualizerCoefficients(8.5868004289e-1, 7.0659978553e-2, 1.7600401337),\n new EqualizerCoefficients(7.8409610788e-1, 1.0795194606e-1, 1.5450725522),\n new EqualizerCoefficients(6.8332861002e-1, 1.5833569499e-1, 1.1426447155),\n new EqualizerCoefficients(5.5267518228e-1, 2.2366240886e-1, 4.0186190803e-1),\n new EqualizerCoefficients(4.1811888447e-1, 2.9094055777e-1, -7.0905944223e-1)\n ];\n public channels: ChannelProcessor[] = [];\n public channelCount: number;\n\n public constructor(channelCount: number, bandMultipliers: number[]) {\n super(bandMultipliers);\n this.channelCount = channelCount;\n this.channels = this.createChannelProcessor();\n }\n\n public createChannelProcessor() {\n return Array.from({ length: this.channelCount }, () => {\n return new ChannelProcessor(this.bandMultipliers);\n });\n }\n\n public process(input: ChannelProcessorInput[]) {\n return this.channels.map((c, i) => {\n const { data, extremum, readInt, writeInt, bytes } = input[i];\n\n return c.process(data, extremum, bytes, readInt, writeInt);\n });\n }\n}\n","import { TransformCallback } from 'stream';\nimport { PCMTransformer, PCMTransformerOptions } from '../utils';\nimport { Equalizer } from './Equalizer';\n\ninterface EqualizerStreamOptions extends PCMTransformerOptions {\n bandMultiplier?: EqualizerBand[];\n disabled?: boolean;\n channels?: number;\n}\n\nexport interface EqualizerBand {\n band: number;\n gain: number;\n}\n\nexport class EqualizerStream extends PCMTransformer {\n public disabled = false;\n public bandMultipliers: number[] = new Array(Equalizer.BAND_COUNT).fill(0);\n public equalizer: Equalizer;\n public constructor(options?: EqualizerStreamOptions) {\n super(options);\n\n options = Object.assign(\n {},\n {\n bandMultiplier: [],\n channels: 1,\n disabled: false\n },\n options || {}\n );\n\n if (options.disabled) this.disabled = !!options.disabled;\n this.equalizer = new Equalizer(options.channels || 1, this.bandMultipliers);\n if (Array.isArray(options.bandMultiplier)) this._processBands(options.bandMultiplier);\n }\n\n public _processBands(multiplier: EqualizerBand[]) {\n for (const mul of multiplier) {\n if (mul.band > Equalizer.BAND_COUNT - 1 || mul.band < 0) throw new RangeError(`Band value out of range. Expected >0 & <${Equalizer.BAND_COUNT - 1}, received \"${mul.band}\"`);\n this.equalizer.setGain(mul.band, mul.gain);\n }\n }\n\n public disable() {\n this.disabled = true;\n }\n\n public enable() {\n this.disabled = false;\n }\n\n public toggle() {\n this.disabled = !this.disabled;\n }\n\n public _transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback): void {\n if (this.disabled) {\n this.push(chunk);\n return callback();\n }\n\n this.equalizer.process([\n {\n data: chunk,\n extremum: this.extremum,\n readInt: (b, idx) => this._readInt(b, idx),\n writeInt: (b, i, idx) => this._writeInt(b, i, idx),\n bytes: this.bytes\n }\n ]);\n\n this.push(chunk);\n\n return callback();\n }\n\n public getEQ() {\n return this.bandMultipliers.map((m, i) => ({\n band: i,\n gain: m\n })) as EqualizerBand[];\n }\n\n public setEQ(bands: EqualizerBand[]) {\n this._processBands(bands);\n }\n\n public resetEQ() {\n this._processBands(\n Array.from(\n {\n length: Equalizer.BAND_COUNT\n },\n (_, i) => ({\n band: i,\n gain: 0\n })\n )\n );\n }\n}\n","import { TransformCallback } from 'stream';\nimport { PCMTransformer, PCMTransformerOptions } from '../utils';\n\n/*\nMono: [0, 1, 2, 3, 4, 5]\nStereo: [0, 1, 0, 1, 2, 3, 2, 3, 4, 5, 4, 5]\n*/\n\nexport type MSTStrategy = 'm2s' | 's2m';\n\nexport interface MonoStereoTransformerOptions extends PCMTransformerOptions {\n strategy: MSTStrategy;\n}\n\nexport class MonoStereoTransformer extends PCMTransformer {\n public disabled = false;\n public strategy: MSTStrategy;\n\n public constructor(options?: MonoStereoTransformerOptions) {\n super(options);\n if (!['m2s', 's2m'].includes(options?.strategy as MSTStrategy)) {\n throw new TypeError(`Strategy must be \"m2s\" or \"s2m\"`);\n }\n\n this.strategy = options!.strategy;\n }\n\n public disable() {\n this.disabled = true;\n }\n\n public enable() {\n this.disabled = false;\n }\n\n public toggle() {\n this.disabled = !this.disabled;\n }\n\n public setStrategy(strategy: MSTStrategy) {\n this.strategy = strategy;\n }\n\n public _transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback): void {\n if (this.disabled) {\n this.push(chunk);\n return callback();\n }\n\n const len = Math.floor(chunk.length / 2) * 2;\n\n if (this.strategy === 'm2s') {\n this.push(this.toStereo(chunk, len));\n } else {\n this.push(this.toMono(chunk, len));\n }\n\n return callback();\n }\n\n public toStereo(sample: Buffer, len: number) {\n const bytes = this.bytes;\n const stereoBuffer = Buffer.alloc(len * 2);\n\n for (let i = 0; i < len; i += bytes) {\n stereoBuffer[i * 2 + 0] = sample[i];\n stereoBuffer[i * 2 + 1] = sample[i + 1];\n stereoBuffer[i * 2 + 2] = sample[i];\n stereoBuffer[i * 2 + 3] = sample[i + 1];\n }\n\n return stereoBuffer;\n }\n\n public toMono(sample: Buffer, len: number) {\n const bytes = this.bytes;\n const monoBuffer = Buffer.alloc(Math.floor(len / 2));\n\n for (let i = 0; i < len; i += bytes) {\n monoBuffer[i] = sample[i * 2 + 0];\n monoBuffer[i + 1] = sample[i * 2 + 1];\n }\n\n return monoBuffer;\n }\n}\n","export * from './biquad';\nexport * from './equalizer';\nexport * from './utils';\nexport * from './audio';\n\n// eslint-disable-next-line @typescript-eslint/no-inferrable-types\nexport const version: string = '0.1.3';\n"],"mappings":"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","names":[]}
\ No newline at end of file
diff --git a/node_modules/@discord-player/equalizer/package.json b/node_modules/@discord-player/equalizer/package.json
deleted file mode 100644
index 1edadee..0000000
--- a/node_modules/@discord-player/equalizer/package.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "name": "@discord-player/equalizer",
- "version": "0.1.3",
- "description": "PCM Equalizer implementation for Discord Player",
- "keywords": [
- "discord-player",
- "pcm",
- "equalizer",
- "music",
- "bot",
- "discord.js",
- "javascript",
- "voip",
- "lavalink",
- "lavaplayer"
- ],
- "author": "Androz2091 ",
- "homepage": "https://discord-player.js.org",
- "license": "MIT",
- "main": "dist/index.js",
- "module": "dist/index.mjs",
- "types": "dist/index.d.ts",
- "directories": {
- "dist": "dist",
- "src": "src"
- },
- "files": [
- "dist"
- ],
- "repository": {
- "type": "git",
- "url": "git+https://github.com/Androz2091/discord-player.git"
- },
- "scripts": {
- "build": "tsup",
- "build:check": "tsc --noEmit"
- },
- "bugs": {
- "url": "https://github.com/Androz2091/discord-player/issues"
- },
- "devDependencies": {
- "@discord-player/tsconfig": "*"
- }
-}
\ No newline at end of file
diff --git a/node_modules/@discordjs/builders/CHANGELOG.md b/node_modules/@discordjs/builders/CHANGELOG.md
index 0ab0974..de5bb4f 100644
--- a/node_modules/@discordjs/builders/CHANGELOG.md
+++ b/node_modules/@discordjs/builders/CHANGELOG.md
@@ -2,6 +2,70 @@
All notable changes to this project will be documented in this file.
+# [@discordjs/builders@1.6.3](https://github.com/discordjs/discord.js/compare/@discordjs/builders@1.6.2...@discordjs/builders@1.6.3) - (2023-05-01)
+
+## Refactor
+
+- Remove `@discordjs/util` re-export (#9488) ([54ceedf](https://github.com/discordjs/discord.js/commit/54ceedf6c535d4641643d4106b6286cbef09de4a))
+
+# [@discordjs/builders@1.6.2](https://github.com/discordjs/discord.js/compare/@discordjs/builders@1.6.1...@discordjs/builders@1.6.2) - (2023-05-01)
+
+## Bug Fixes
+
+- **BaseSelectMenuBuilder:** Modify class to be `abstract` (#9358) ([ca4de2d](https://github.com/discordjs/discord.js/commit/ca4de2d9c6bc204e85d1b7eae7eabd23dbeb4475))
+- Correct `@link` tags that involve parents (#9351) ([fbbce3e](https://github.com/discordjs/discord.js/commit/fbbce3eb4ba20bc0c4806ca2259d1f86001594be))
+- Fix external links (#9313) ([a7425c2](https://github.com/discordjs/discord.js/commit/a7425c29c4f23f1b31f4c6a463107ca9eb7fd7e2))
+
+## Documentation
+
+- Reference package names properly (#9426) ([d6bca9b](https://github.com/discordjs/discord.js/commit/d6bca9bb4d976dc069a5039250db7d5b3e9142ef))
+- Generate static imports for types with api-extractor ([98a76db](https://github.com/discordjs/discord.js/commit/98a76db482879f79d6bb2fb2e5fc65ac2c34e2d9))
+- **builders:** Add some basic documentation (#9359) ([8073561](https://github.com/discordjs/discord.js/commit/8073561824f911d1a18d0b4f1de39f452bc69fa9))
+- Use `@link` in `@see` (#9348) ([d66d113](https://github.com/discordjs/discord.js/commit/d66d1133331b81563588db4500c63a18c3c3dfae))
+
+# [@discordjs/builders@1.6.2](https://github.com/discordjs/discord.js/compare/@discordjs/builders@1.6.1...@discordjs/builders@1.6.2) - (2023-05-01)
+
+## Bug Fixes
+
+- **BaseSelectMenuBuilder:** Modify class to be `abstract` (#9358) ([ca4de2d](https://github.com/discordjs/discord.js/commit/ca4de2d9c6bc204e85d1b7eae7eabd23dbeb4475))
+- Correct `@link` tags that involve parents (#9351) ([fbbce3e](https://github.com/discordjs/discord.js/commit/fbbce3eb4ba20bc0c4806ca2259d1f86001594be))
+- Fix external links (#9313) ([a7425c2](https://github.com/discordjs/discord.js/commit/a7425c29c4f23f1b31f4c6a463107ca9eb7fd7e2))
+
+## Documentation
+
+- Reference package names properly (#9426) ([d6bca9b](https://github.com/discordjs/discord.js/commit/d6bca9bb4d976dc069a5039250db7d5b3e9142ef))
+- Generate static imports for types with api-extractor ([98a76db](https://github.com/discordjs/discord.js/commit/98a76db482879f79d6bb2fb2e5fc65ac2c34e2d9))
+- **builders:** Add some basic documentation (#9359) ([8073561](https://github.com/discordjs/discord.js/commit/8073561824f911d1a18d0b4f1de39f452bc69fa9))
+- Use `@link` in `@see` (#9348) ([d66d113](https://github.com/discordjs/discord.js/commit/d66d1133331b81563588db4500c63a18c3c3dfae))
+
+# [@discordjs/builders@1.6.0](https://github.com/discordjs/discord.js/compare/@discordjs/builders@1.5.0...@discordjs/builders@1.6.0) - (2023-04-01)
+
+## Bug Fixes
+
+- **scripts:** Accessing tsComment ([d8d5f31](https://github.com/discordjs/discord.js/commit/d8d5f31d3927fd1de62f1fa3a1a6e454243ad87b))
+
+## Features
+
+- **website:** Render syntax and mdx on the server (#9086) ([ee5169e](https://github.com/discordjs/discord.js/commit/ee5169e0aadd7bbfcd752aae614ec0f69602b68b))
+
+# [@discordjs/builders@1.5.0](https://github.com/discordjs/discord.js/compare/@discordjs/builders@1.4.0...@discordjs/builders@1.5.0) - (2023-03-12)
+
+## Documentation
+
+- **EmbedBuilder#spliceFields:** Fix a typo (#9159) ([4367ab9](https://github.com/discordjs/discord.js/commit/4367ab930227048868db3ed8437f6c4507ff32e1))
+- Fix version export (#9049) ([8b70f49](https://github.com/discordjs/discord.js/commit/8b70f497a1207e30edebdecd12b926c981c13d28))
+
+## Features
+
+- **website:** Add support for source file links (#9048) ([f6506e9](https://github.com/discordjs/discord.js/commit/f6506e99c496683ee0ab67db0726b105b929af38))
+- **StringSelectMenu:** Add `spliceOptions()` (#8937) ([a6941d5](https://github.com/discordjs/discord.js/commit/a6941d536ce24ed2b5446a154cbc886b2b97c63a))
+- Add support for nsfw commands (#7976) ([7a51344](https://github.com/discordjs/discord.js/commit/7a5134459c5f06864bf74631d83b96d9c21b72d8))
+- Add `@discordjs/formatters` (#8889) ([3fca638](https://github.com/discordjs/discord.js/commit/3fca638a8470dcea2f79ddb9f18526dbc0017c88))
+
+## Styling
+
+- Run prettier (#9041) ([2798ba1](https://github.com/discordjs/discord.js/commit/2798ba1eb3d734f0cf2eeccd2e16cfba6804873b))
+
# [@discordjs/builders@1.4.0](https://github.com/discordjs/discord.js/compare/@discordjs/builders@1.3.0...@discordjs/builders@1.4.0) - (2022-11-28)
## Bug Fixes
diff --git a/node_modules/@discordjs/builders/README.md b/node_modules/@discordjs/builders/README.md
index 59508dd..2981f19 100644
--- a/node_modules/@discordjs/builders/README.md
+++ b/node_modules/@discordjs/builders/README.md
@@ -16,11 +16,15 @@
+## About
+
+`@discordjs/builders` is a utility package for easily building Discord API payloads.
+
## Installation
**Node.js 16.9.0 or newer is required.**
-```sh-session
+```sh
npm install @discordjs/builders
yarn add @discordjs/builders
pnpm add @discordjs/builders
@@ -28,16 +32,14 @@ pnpm add @discordjs/builders
## Examples
-Here are some examples for the builders and utilities you can find in this package:
-
-- [Slash Command Builders][example]
+You can find examples of how to use the builders in the [Slash Command Builders][example] examples.
## Links
- [Website][website] ([source][website-source])
- [Documentation][documentation]
- [Guide][guide] ([source][guide-source])
- See also the [Update Guide][guide-update], including updated and removed items in the library.
+ Also see the v13 to v14 [Update Guide][guide-update], which includes updated and removed items from the library.
- [discord.js Discord server][discord]
- [Discord API Discord server][discord-api]
- [GitHub][source]
@@ -52,13 +54,12 @@ See [the contribution guide][contributing] if you'd like to submit a PR.
## Help
-If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
-nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
+If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
[example]: https://github.com/discordjs/discord.js/blob/main/packages/builders/docs/examples/Slash%20Command%20Builders.md
-[website]: https://discord.js.org/
+[website]: https://discord.js.org
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
-[documentation]: https://discord.js.org/#/docs/builders
+[documentation]: https://discord.js.org/docs/packages/builders/stable
[guide]: https://discordjs.guide/
[guide-source]: https://github.com/discordjs/guide
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html
diff --git a/node_modules/@discordjs/builders/dist/index.d.ts b/node_modules/@discordjs/builders/dist/index.d.ts
index f5df124..5237d9b 100644
--- a/node_modules/@discordjs/builders/dist/index.d.ts
+++ b/node_modules/@discordjs/builders/dist/index.d.ts
@@ -1,9 +1,7 @@
import * as _sapphire_shapeshift from '@sapphire/shapeshift';
-import { APIEmbedField, APIEmbedAuthor, APIEmbedFooter, APIEmbedImage, APIEmbed, APISelectMenuOption, APIMessageComponentEmoji, ButtonStyle, ChannelType, APIActionRowComponent, APIActionRowComponentTypes, APIBaseComponent, ComponentType, APIButtonComponent, APISelectMenuComponent, APIChannelSelectComponent, APIMentionableSelectComponent, APIRoleSelectComponent, APIStringSelectComponent, APIUserSelectComponent, APITextInputComponent, TextInputStyle, APIMessageActionRowComponent, APIModalActionRowComponent, APIModalComponent, APIMessageComponent, APIModalInteractionResponseCallbackData, LocalizationMap, LocaleString, ApplicationCommandOptionType, APIApplicationCommandBasicOption, APIApplicationCommandAttachmentOption, APIApplicationCommandBooleanOption, APIApplicationCommandChannelOption, APIApplicationCommandOptionChoice, APIApplicationCommandIntegerOption, APIApplicationCommandMentionableOption, APIApplicationCommandNumberOption, APIApplicationCommandRoleOption, APIApplicationCommandStringOption, APIApplicationCommandUserOption, APIApplicationCommandSubcommandGroupOption, APIApplicationCommandSubcommandOption, Permissions, RESTPostAPIChatInputApplicationCommandsJSONBody, APIApplicationCommandOption, Locale, RESTPostAPIContextMenuApplicationCommandsJSONBody, ApplicationCommandType } from 'discord-api-types/v10';
-import { URL } from 'node:url';
-import { Snowflake } from 'discord-api-types/globals';
+import { APIEmbedField, APIEmbedAuthor, APIEmbedFooter, APIEmbedImage, APIEmbed, APISelectMenuOption, APIMessageComponentEmoji, ButtonStyle, ChannelType, APIActionRowComponent, APIActionRowComponentTypes, APIBaseComponent, ComponentType, APIButtonComponent, APISelectMenuComponent, APIChannelSelectComponent, APIMentionableSelectComponent, APIRoleSelectComponent, APIStringSelectComponent, APIUserSelectComponent, APITextInputComponent, TextInputStyle, APIMessageActionRowComponent, APIModalActionRowComponent, APIModalComponent, APIMessageComponent, APIModalInteractionResponseCallbackData, LocalizationMap, LocaleString, ApplicationCommandOptionType, APIApplicationCommandBasicOption, APIApplicationCommandAttachmentOption, APIApplicationCommandBooleanOption, APIApplicationCommandChannelOption, APIApplicationCommandOptionChoice, APIApplicationCommandIntegerOption, APIApplicationCommandMentionableOption, APIApplicationCommandNumberOption, APIApplicationCommandRoleOption, APIApplicationCommandStringOption, APIApplicationCommandUserOption, APIApplicationCommandSubcommandGroupOption, APIApplicationCommandSubcommandOption, Permissions, RESTPostAPIChatInputApplicationCommandsJSONBody, APIApplicationCommandOption, Locale, ApplicationCommandType, RESTPostAPIContextMenuApplicationCommandsJSONBody } from 'discord-api-types/v10';
+export * from '@discordjs/formatters';
import { JSONEncodable, Equatable } from '@discordjs/util';
-export * from '@discordjs/util';
declare const fieldNamePredicate: _sapphire_shapeshift.StringValidator;
declare const fieldValuePredicate: _sapphire_shapeshift.StringValidator;
@@ -54,92 +52,136 @@ declare const embedFooterPredicate: _sapphire_shapeshift.ObjectValidator<{
declare const timestampPredicate: _sapphire_shapeshift.UnionValidator;
declare const titlePredicate: _sapphire_shapeshift.UnionValidator;
-declare const Assertions$5_fieldNamePredicate: typeof fieldNamePredicate;
-declare const Assertions$5_fieldValuePredicate: typeof fieldValuePredicate;
-declare const Assertions$5_fieldInlinePredicate: typeof fieldInlinePredicate;
-declare const Assertions$5_embedFieldPredicate: typeof embedFieldPredicate;
-declare const Assertions$5_embedFieldsArrayPredicate: typeof embedFieldsArrayPredicate;
-declare const Assertions$5_fieldLengthPredicate: typeof fieldLengthPredicate;
-declare const Assertions$5_validateFieldLength: typeof validateFieldLength;
-declare const Assertions$5_authorNamePredicate: typeof authorNamePredicate;
-declare const Assertions$5_imageURLPredicate: typeof imageURLPredicate;
-declare const Assertions$5_urlPredicate: typeof urlPredicate;
-declare const Assertions$5_embedAuthorPredicate: typeof embedAuthorPredicate;
declare const Assertions$5_RGBPredicate: typeof RGBPredicate;
+declare const Assertions$5_authorNamePredicate: typeof authorNamePredicate;
declare const Assertions$5_colorPredicate: typeof colorPredicate;
declare const Assertions$5_descriptionPredicate: typeof descriptionPredicate;
-declare const Assertions$5_footerTextPredicate: typeof footerTextPredicate;
+declare const Assertions$5_embedAuthorPredicate: typeof embedAuthorPredicate;
+declare const Assertions$5_embedFieldPredicate: typeof embedFieldPredicate;
+declare const Assertions$5_embedFieldsArrayPredicate: typeof embedFieldsArrayPredicate;
declare const Assertions$5_embedFooterPredicate: typeof embedFooterPredicate;
+declare const Assertions$5_fieldInlinePredicate: typeof fieldInlinePredicate;
+declare const Assertions$5_fieldLengthPredicate: typeof fieldLengthPredicate;
+declare const Assertions$5_fieldNamePredicate: typeof fieldNamePredicate;
+declare const Assertions$5_fieldValuePredicate: typeof fieldValuePredicate;
+declare const Assertions$5_footerTextPredicate: typeof footerTextPredicate;
+declare const Assertions$5_imageURLPredicate: typeof imageURLPredicate;
declare const Assertions$5_timestampPredicate: typeof timestampPredicate;
declare const Assertions$5_titlePredicate: typeof titlePredicate;
+declare const Assertions$5_urlPredicate: typeof urlPredicate;
+declare const Assertions$5_validateFieldLength: typeof validateFieldLength;
declare namespace Assertions$5 {
export {
- Assertions$5_fieldNamePredicate as fieldNamePredicate,
- Assertions$5_fieldValuePredicate as fieldValuePredicate,
- Assertions$5_fieldInlinePredicate as fieldInlinePredicate,
- Assertions$5_embedFieldPredicate as embedFieldPredicate,
- Assertions$5_embedFieldsArrayPredicate as embedFieldsArrayPredicate,
- Assertions$5_fieldLengthPredicate as fieldLengthPredicate,
- Assertions$5_validateFieldLength as validateFieldLength,
- Assertions$5_authorNamePredicate as authorNamePredicate,
- Assertions$5_imageURLPredicate as imageURLPredicate,
- Assertions$5_urlPredicate as urlPredicate,
- Assertions$5_embedAuthorPredicate as embedAuthorPredicate,
Assertions$5_RGBPredicate as RGBPredicate,
+ Assertions$5_authorNamePredicate as authorNamePredicate,
Assertions$5_colorPredicate as colorPredicate,
Assertions$5_descriptionPredicate as descriptionPredicate,
- Assertions$5_footerTextPredicate as footerTextPredicate,
+ Assertions$5_embedAuthorPredicate as embedAuthorPredicate,
+ Assertions$5_embedFieldPredicate as embedFieldPredicate,
+ Assertions$5_embedFieldsArrayPredicate as embedFieldsArrayPredicate,
Assertions$5_embedFooterPredicate as embedFooterPredicate,
+ Assertions$5_fieldInlinePredicate as fieldInlinePredicate,
+ Assertions$5_fieldLengthPredicate as fieldLengthPredicate,
+ Assertions$5_fieldNamePredicate as fieldNamePredicate,
+ Assertions$5_fieldValuePredicate as fieldValuePredicate,
+ Assertions$5_footerTextPredicate as footerTextPredicate,
+ Assertions$5_imageURLPredicate as imageURLPredicate,
Assertions$5_timestampPredicate as timestampPredicate,
Assertions$5_titlePredicate as titlePredicate,
+ Assertions$5_urlPredicate as urlPredicate,
+ Assertions$5_validateFieldLength as validateFieldLength,
};
}
+/**
+ * Normalizes data that is a rest parameter or an array into an array with a depth of 1.
+ *
+ * @typeParam T - The data that must satisfy {@link RestOrArray}.
+ * @param arr - The (possibly variadic) data to normalize
+ */
declare function normalizeArray(arr: RestOrArray): T[];
+/**
+ * Represents data that may be an array or came from a rest parameter.
+ *
+ * @remarks
+ * This type is used throughout builders to ensure both an array and variadic arguments
+ * may be used. It is normalized with {@link normalizeArray}.
+ */
type RestOrArray = T[] | [T[]];
+/**
+ * A tuple satisfying the RGB color model.
+ *
+ * @see {@link https://developer.mozilla.org/docs/Glossary/RGB}
+ */
type RGBTuple = [red: number, green: number, blue: number];
+/**
+ * The base icon data typically used in payloads.
+ */
interface IconData {
/**
- * The URL of the icon
+ * The URL of the icon.
*/
iconURL?: string;
/**
- * The proxy URL of the icon
+ * The proxy URL of the icon.
*/
proxyIconURL?: string;
}
+/**
+ * Represents the author data of an embed.
+ */
type EmbedAuthorData = IconData & Omit;
+/**
+ * Represents the author options of an embed.
+ */
type EmbedAuthorOptions = Omit;
+/**
+ * Represents the footer data of an embed.
+ */
type EmbedFooterData = IconData & Omit;
+/**
+ * Represents the footer options of an embed.
+ */
type EmbedFooterOptions = Omit;
+/**
+ * Represents the image data of an embed.
+ */
interface EmbedImageData extends Omit {
/**
- * The proxy URL for the image
+ * The proxy URL for the image.
*/
proxyURL?: string;
}
/**
- * Represents a embed in a message (image/video preview, rich embed, etc.)
+ * A builder that creates API-compatible JSON data for embeds.
*/
declare class EmbedBuilder {
+ /**
+ * The API data associated with this embed.
+ */
readonly data: APIEmbed;
+ /**
+ * Creates a new embed from API data.
+ *
+ * @param data - The API data to create this embed with
+ */
constructor(data?: APIEmbed);
/**
- * Appends fields to the embed
+ * Appends fields to the embed.
*
* @remarks
* This method accepts either an array of fields or a variable number of field parameters.
* The maximum amount of fields that can be added is 25.
* @example
- * Using an array
+ * Using an array:
* ```ts
* const fields: APIEmbedField[] = ...;
* const embed = new EmbedBuilder()
* .addFields(fields);
* ```
* @example
- * Using rest parameters (variadic)
+ * Using rest parameters (variadic):
* ```ts
* const embed = new EmbedBuilder()
* .addFields(
@@ -151,27 +193,27 @@ declare class EmbedBuilder {
*/
addFields(...fields: RestOrArray): this;
/**
- * Removes, replaces, or inserts fields in the embed.
+ * Removes, replaces, or inserts fields for this embed.
*
* @remarks
* This method behaves similarly
- * to {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice | Array.prototype.splice}.
+ * to {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice | Array.prototype.splice()}.
* The maximum amount of fields that can be added is 25.
*
* It's useful for modifying and adjusting order of the already-existing fields of an embed.
* @example
- * Remove the first field
+ * Remove the first field:
* ```ts
* embed.spliceFields(0, 1);
* ```
* @example
- * Remove the first n fields
+ * Remove the first n fields:
* ```ts
- * const n = 4
+ * const n = 4;
* embed.spliceFields(0, n);
* ```
* @example
- * Remove the last field
+ * Remove the last field:
* ```ts
* embed.spliceFields(-1, 1);
* ```
@@ -181,7 +223,7 @@ declare class EmbedBuilder {
*/
spliceFields(index: number, deleteCount: number, ...fields: APIEmbedField[]): this;
/**
- * Sets the embed's fields
+ * Sets the fields for this embed.
*
* @remarks
* This method is an alias for {@link EmbedBuilder.spliceFields}. More specifically,
@@ -192,350 +234,80 @@ declare class EmbedBuilder {
*/
setFields(...fields: RestOrArray): this;
/**
- * Sets the author of this embed
+ * Sets the author of this embed.
*
- * @param options - The options for the author
+ * @param options - The options to use
*/
setAuthor(options: EmbedAuthorOptions | null): this;
/**
- * Sets the color of this embed
+ * Sets the color of this embed.
*
- * @param color - The color of the embed
+ * @param color - The color to use
*/
setColor(color: RGBTuple | number | null): this;
/**
- * Sets the description of this embed
+ * Sets the description of this embed.
*
- * @param description - The description
+ * @param description - The description to use
*/
setDescription(description: string | null): this;
/**
- * Sets the footer of this embed
+ * Sets the footer of this embed.
*
- * @param options - The options for the footer
+ * @param options - The footer to use
*/
setFooter(options: EmbedFooterOptions | null): this;
/**
- * Sets the image of this embed
+ * Sets the image of this embed.
*
- * @param url - The URL of the image
+ * @param url - The image URL to use
*/
setImage(url: string | null): this;
/**
- * Sets the thumbnail of this embed
+ * Sets the thumbnail of this embed.
*
- * @param url - The URL of the thumbnail
+ * @param url - The thumbnail URL to use
*/
setThumbnail(url: string | null): this;
/**
- * Sets the timestamp of this embed
+ * Sets the timestamp of this embed.
*
- * @param timestamp - The timestamp or date
+ * @param timestamp - The timestamp or date to use
*/
setTimestamp(timestamp?: Date | number | null): this;
/**
- * Sets the title of this embed
+ * Sets the title for this embed.
*
- * @param title - The title
+ * @param title - The title to use
*/
setTitle(title: string | null): this;
/**
- * Sets the URL of this embed
+ * Sets the URL of this embed.
*
- * @param url - The URL
+ * @param url - The URL to use
*/
setURL(url: string | null): this;
/**
- * Transforms the embed to a plain object
+ * Serializes this builder to API-compatible JSON data.
+ *
+ * @remarks
+ * This method runs validations on the data before serializing it.
+ * As such, it may throw an error if the data is invalid.
*/
toJSON(): APIEmbed;
}
/**
- * Wraps the content inside a codeblock with no language
- *
- * @param content - The content to wrap
- */
-declare function codeBlock(content: C): `\`\`\`\n${C}\n\`\`\``;
-/**
- * Wraps the content inside a codeblock with the specified language
- *
- * @param language - The language for the codeblock
- * @param content - The content to wrap
- */
-declare function codeBlock(language: L, content: C): `\`\`\`${L}\n${C}\n\`\`\``;
-/**
- * Wraps the content inside \`backticks\`, which formats it as inline code
- *
- * @param content - The content to wrap
- */
-declare function inlineCode(content: C): `\`${C}\``;
-/**
- * Formats the content into italic text
- *
- * @param content - The content to wrap
- */
-declare function italic(content: C): `_${C}_`;
-/**
- * Formats the content into bold text
- *
- * @param content - The content to wrap
- */
-declare function bold(content: C): `**${C}**`;
-/**
- * Formats the content into underscored text
- *
- * @param content - The content to wrap
- */
-declare function underscore(content: C): `__${C}__`;
-/**
- * Formats the content into strike-through text
- *
- * @param content - The content to wrap
- */
-declare function strikethrough(content: C): `~~${C}~~`;
-/**
- * Formats the content into a quote. This needs to be at the start of the line for Discord to format it
- *
- * @param content - The content to wrap
- */
-declare function quote(content: C): `> ${C}`;
-/**
- * Formats the content into a block quote. This needs to be at the start of the line for Discord to format it
- *
- * @param content - The content to wrap
- */
-declare function blockQuote(content: C): `>>> ${C}`;
-/**
- * Wraps the URL into `<>`, which stops it from embedding
- *
- * @param url - The URL to wrap
- */
-declare function hideLinkEmbed(url: C): `<${C}>`;
-/**
- * Wraps the URL into `<>`, which stops it from embedding
- *
- * @param url - The URL to wrap
- */
-declare function hideLinkEmbed(url: URL): `<${string}>`;
-/**
- * Formats the content and the URL into a masked URL
- *
- * @param content - The content to display
- * @param url - The URL the content links to
- */
-declare function hyperlink(content: C, url: URL): `[${C}](${string})`;
-/**
- * Formats the content and the URL into a masked URL
- *
- * @param content - The content to display
- * @param url - The URL the content links to
- */
-declare function hyperlink(content: C, url: U): `[${C}](${U})`;
-/**
- * Formats the content and the URL into a masked URL
- *
- * @param content - The content to display
- * @param url - The URL the content links to
- * @param title - The title shown when hovering on the masked link
- */
-declare function hyperlink(content: C, url: URL, title: T): `[${C}](${string} "${T}")`;
-/**
- * Formats the content and the URL into a masked URL
- *
- * @param content - The content to display
- * @param url - The URL the content links to
- * @param title - The title shown when hovering on the masked link
- */
-declare function hyperlink(content: C, url: U, title: T): `[${C}](${U} "${T}")`;
-/**
- * Wraps the content inside spoiler (hidden text)
- *
- * @param content - The content to wrap
- */
-declare function spoiler(content: C): `||${C}||`;
-/**
- * Formats a user ID into a user mention
- *
- * @param userId - The user ID to format
- */
-declare function userMention(userId: C): `<@${C}>`;
-/**
- * Formats a channel ID into a channel mention
- *
- * @param channelId - The channel ID to format
- */
-declare function channelMention(channelId: C): `<#${C}>`;
-/**
- * Formats a role ID into a role mention
- *
- * @param roleId - The role ID to format
- */
-declare function roleMention(roleId: C): `<@&${C}>`;
-/**
- * Formats an application command name, subcommand group name, subcommand name, and ID into an application command mention
- *
- * @param commandName - The application command name to format
- * @param subcommandGroupName - The subcommand group name to format
- * @param subcommandName - The subcommand name to format
- * @param commandId - The application command ID to format
- */
-declare function chatInputApplicationCommandMention(commandName: N, subcommandGroupName: G, subcommandName: S, commandId: I): `${N} ${G} ${S}:${I}>`;
-/**
- * Formats an application command name, subcommand name, and ID into an application command mention
- *
- * @param commandName - The application command name to format
- * @param subcommandName - The subcommand name to format
- * @param commandId - The application command ID to format
- */
-declare function chatInputApplicationCommandMention(commandName: N, subcommandName: S, commandId: I): `${N} ${S}:${I}>`;
-/**
- * Formats an application command name and ID into an application command mention
- *
- * @param commandName - The application command name to format
- * @param commandId - The application command ID to format
- */
-declare function chatInputApplicationCommandMention(commandName: N, commandId: I): `${N}:${I}>`;
-/**
- * Formats an emoji ID into a fully qualified emoji identifier
- *
- * @param emojiId - The emoji ID to format
- */
-declare function formatEmoji(emojiId: C, animated?: false): `<:_:${C}>`;
-/**
- * Formats an emoji ID into a fully qualified emoji identifier
- *
- * @param emojiId - The emoji ID to format
- * @param animated - Whether the emoji is animated or not. Defaults to `false`
- */
-declare function formatEmoji(emojiId: C, animated?: true): ``;
-/**
- * Formats an emoji ID into a fully qualified emoji identifier
- *
- * @param emojiId - The emoji ID to format
- * @param animated - Whether the emoji is animated or not. Defaults to `false`
- */
-declare function formatEmoji(emojiId: C, animated?: boolean): `<:_:${C}>` | ``;
-/**
- * Formats a channel link for a direct message channel.
- *
- * @param channelId - The channel's id
- */
-declare function channelLink(channelId: C): `https://discord.com/channels/@me/${C}`;
-/**
- * Formats a channel link for a guild channel.
- *
- * @param channelId - The channel's id
- * @param guildId - The guild's id
- */
-declare function channelLink(channelId: C, guildId: G): `https://discord.com/channels/${G}/${C}`;
-/**
- * Formats a message link for a direct message channel.
- *
- * @param channelId - The channel's id
- * @param messageId - The message's id
- */
-declare function messageLink(channelId: C, messageId: M): `https://discord.com/channels/@me/${C}/${M}`;
-/**
- * Formats a message link for a guild channel.
- *
- * @param channelId - The channel's id
- * @param messageId - The message's id
- * @param guildId - The guild's id
- */
-declare function messageLink(channelId: C, messageId: M, guildId: G): `https://discord.com/channels/${G}/${C}/${M}`;
-/**
- * Formats a date into a short date-time string
- *
- * @param date - The date to format, defaults to the current time
- */
-declare function time(date?: Date): ``;
-/**
- * Formats a date given a format style
- *
- * @param date - The date to format
- * @param style - The style to use
- */
-declare function time(date: Date, style: S): ``;
-/**
- * Formats the given timestamp into a short date-time string
- *
- * @param seconds - The time to format, represents an UNIX timestamp in seconds
- */
-declare function time(seconds: C): ``;
-/**
- * Formats the given timestamp into a short date-time string
- *
- * @param seconds - The time to format, represents an UNIX timestamp in seconds
- * @param style - The style to use
- */
-declare function time(seconds: C, style: S): ``;
-/**
- * The {@link https://discord.com/developers/docs/reference#message-formatting-timestamp-styles | message formatting timestamp styles} supported by Discord
- */
-declare const TimestampStyles: {
- /**
- * Short time format, consisting of hours and minutes, e.g. 16:20
- */
- readonly ShortTime: "t";
- /**
- * Long time format, consisting of hours, minutes, and seconds, e.g. 16:20:30
- */
- readonly LongTime: "T";
- /**
- * Short date format, consisting of day, month, and year, e.g. 20/04/2021
- */
- readonly ShortDate: "d";
- /**
- * Long date format, consisting of day, month, and year, e.g. 20 April 2021
- */
- readonly LongDate: "D";
- /**
- * Short date-time format, consisting of short date and short time formats, e.g. 20 April 2021 16:20
- */
- readonly ShortDateTime: "f";
- /**
- * Long date-time format, consisting of long date and short time formats, e.g. Tuesday, 20 April 2021 16:20
- */
- readonly LongDateTime: "F";
- /**
- * Relative time format, consisting of a relative duration format, e.g. 2 months ago
- */
- readonly RelativeTime: "R";
-};
-/**
- * The possible values, see {@link TimestampStyles} for more information
- */
-type TimestampStylesString = typeof TimestampStyles[keyof typeof TimestampStyles];
-/**
- * An enum with all the available faces from Discord's native slash commands
- */
-declare enum Faces {
- /**
- * Β―\\_(γ)\\_/Β―
- */
- Shrug = "\u00AF\\_(\u30C4)\\_/\u00AF",
- /**
- * (β―Β°β‘Β°οΌβ―οΈ΅ β»ββ»
- */
- Tableflip = "(\u256F\u00B0\u25A1\u00B0\uFF09\u256F\uFE35 \u253B\u2501\u253B",
- /**
- * β¬ββ¬ γ( γ-γγ)
- */
- Unflip = "\u252C\u2500\u252C \u30CE( \u309C-\u309C\u30CE)"
-}
-
-/**
- * Represents an option within a string select menu component
+ * A builder that creates API-compatible JSON data for string select menu options.
*/
declare class StringSelectMenuOptionBuilder implements JSONEncodable {
data: Partial;
/**
- * Creates a new string select menu option from API data
+ * Creates a new string select menu option from API data.
*
* @param data - The API data to create this string select menu option with
* @example
- * Creating a string select menu option from an API data object
+ * Creating a string select menu option from an API data object:
* ```ts
* const selectMenuOption = new SelectMenuOptionBuilder({
* label: 'catchy label',
@@ -543,48 +315,48 @@ declare class StringSelectMenuOptionBuilder implements JSONEncodable);
/**
- * Sets the label of this option
+ * Sets the label for this option.
*
- * @param label - The label to show on this option
+ * @param label - The label to use
*/
setLabel(label: string): this;
/**
- * Sets the value of this option
+ * Sets the value for this option.
*
- * @param value - The value of this option
+ * @param value - The value to use
*/
setValue(value: string): this;
/**
- * Sets the description of this option
+ * Sets the description for this option.
*
- * @param description - The description of this option
+ * @param description - The description to use
*/
setDescription(description: string): this;
/**
- * Sets whether this option is selected by default
+ * Sets whether this option is selected by default.
*
* @param isDefault - Whether this option is selected by default
*/
setDefault(isDefault?: boolean): this;
/**
- * Sets the emoji to display on this option
+ * Sets the emoji to display for this option.
*
- * @param emoji - The emoji to display on this option
+ * @param emoji - The emoji to use
*/
setEmoji(emoji: APIMessageComponentEmoji): this;
/**
- * {@inheritDoc ComponentBuilder.toJSON}
+ * {@inheritDoc BaseSelectMenuBuilder.toJSON}
*/
toJSON(): APISelectMenuOption;
}
@@ -636,78 +408,86 @@ declare const channelTypesValidator: _sapphire_shapeshift.ArrayValidator;
declare function validateRequiredButtonParameters(style?: ButtonStyle, label?: string, emoji?: APIMessageComponentEmoji, customId?: string, url?: string): void;
-declare const Assertions$4_customIdValidator: typeof customIdValidator;
-declare const Assertions$4_emojiValidator: typeof emojiValidator;
-declare const Assertions$4_disabledValidator: typeof disabledValidator;
declare const Assertions$4_buttonLabelValidator: typeof buttonLabelValidator;
declare const Assertions$4_buttonStyleValidator: typeof buttonStyleValidator;
-declare const Assertions$4_minMaxValidator: typeof minMaxValidator;
-declare const Assertions$4_labelValueDescriptionValidator: typeof labelValueDescriptionValidator;
+declare const Assertions$4_channelTypesValidator: typeof channelTypesValidator;
+declare const Assertions$4_customIdValidator: typeof customIdValidator;
+declare const Assertions$4_defaultValidator: typeof defaultValidator;
+declare const Assertions$4_disabledValidator: typeof disabledValidator;
+declare const Assertions$4_emojiValidator: typeof emojiValidator;
declare const Assertions$4_jsonOptionValidator: typeof jsonOptionValidator;
+declare const Assertions$4_labelValueDescriptionValidator: typeof labelValueDescriptionValidator;
+declare const Assertions$4_minMaxValidator: typeof minMaxValidator;
declare const Assertions$4_optionValidator: typeof optionValidator;
-declare const Assertions$4_optionsValidator: typeof optionsValidator;
declare const Assertions$4_optionsLengthValidator: typeof optionsLengthValidator;
-declare const Assertions$4_validateRequiredSelectMenuParameters: typeof validateRequiredSelectMenuParameters;
-declare const Assertions$4_defaultValidator: typeof defaultValidator;
-declare const Assertions$4_validateRequiredSelectMenuOptionParameters: typeof validateRequiredSelectMenuOptionParameters;
-declare const Assertions$4_channelTypesValidator: typeof channelTypesValidator;
+declare const Assertions$4_optionsValidator: typeof optionsValidator;
declare const Assertions$4_urlValidator: typeof urlValidator;
declare const Assertions$4_validateRequiredButtonParameters: typeof validateRequiredButtonParameters;
+declare const Assertions$4_validateRequiredSelectMenuOptionParameters: typeof validateRequiredSelectMenuOptionParameters;
+declare const Assertions$4_validateRequiredSelectMenuParameters: typeof validateRequiredSelectMenuParameters;
declare namespace Assertions$4 {
export {
- Assertions$4_customIdValidator as customIdValidator,
- Assertions$4_emojiValidator as emojiValidator,
- Assertions$4_disabledValidator as disabledValidator,
Assertions$4_buttonLabelValidator as buttonLabelValidator,
Assertions$4_buttonStyleValidator as buttonStyleValidator,
- placeholderValidator$1 as placeholderValidator,
- Assertions$4_minMaxValidator as minMaxValidator,
- Assertions$4_labelValueDescriptionValidator as labelValueDescriptionValidator,
+ Assertions$4_channelTypesValidator as channelTypesValidator,
+ Assertions$4_customIdValidator as customIdValidator,
+ Assertions$4_defaultValidator as defaultValidator,
+ Assertions$4_disabledValidator as disabledValidator,
+ Assertions$4_emojiValidator as emojiValidator,
Assertions$4_jsonOptionValidator as jsonOptionValidator,
+ Assertions$4_labelValueDescriptionValidator as labelValueDescriptionValidator,
+ Assertions$4_minMaxValidator as minMaxValidator,
Assertions$4_optionValidator as optionValidator,
- Assertions$4_optionsValidator as optionsValidator,
Assertions$4_optionsLengthValidator as optionsLengthValidator,
- Assertions$4_validateRequiredSelectMenuParameters as validateRequiredSelectMenuParameters,
- Assertions$4_defaultValidator as defaultValidator,
- Assertions$4_validateRequiredSelectMenuOptionParameters as validateRequiredSelectMenuOptionParameters,
- Assertions$4_channelTypesValidator as channelTypesValidator,
+ Assertions$4_optionsValidator as optionsValidator,
+ placeholderValidator$1 as placeholderValidator,
Assertions$4_urlValidator as urlValidator,
Assertions$4_validateRequiredButtonParameters as validateRequiredButtonParameters,
+ Assertions$4_validateRequiredSelectMenuOptionParameters as validateRequiredSelectMenuOptionParameters,
+ Assertions$4_validateRequiredSelectMenuParameters as validateRequiredSelectMenuParameters,
};
}
+/**
+ * Any action row component data represented as an object.
+ */
type AnyAPIActionRowComponent = APIActionRowComponent | APIActionRowComponentTypes;
/**
- * Represents a discord component
+ * The base component builder that contains common symbols for all sorts of components.
*
* @typeParam DataType - The type of internal API data that is stored within the component
*/
declare abstract class ComponentBuilder> = APIBaseComponent> implements JSONEncodable {
/**
- * The API data associated with this component
+ * The API data associated with this component.
*/
readonly data: Partial;
/**
- * Serializes this component to an API-compatible JSON object
+ * Serializes this builder to API-compatible JSON data.
*
* @remarks
* This method runs validations on the data before serializing it.
* As such, it may throw an error if the data is invalid.
*/
abstract toJSON(): AnyAPIActionRowComponent;
+ /**
+ * Constructs a new kind of component.
+ *
+ * @param data - The data to construct a component out of
+ */
constructor(data: Partial);
}
/**
- * Represents a button component
+ * A builder that creates API-compatible JSON data for buttons.
*/
declare class ButtonBuilder extends ComponentBuilder {
/**
- * Creates a new button from API data
+ * Creates a new button from API data.
*
* @param data - The API data to create this button with
* @example
- * Creating a button from an API data object
+ * Creating a button from an API data object:
* ```ts
* const button = new ButtonBuilder({
* custom_id: 'a cool button',
@@ -720,7 +500,7 @@ declare class ButtonBuilder extends ComponentBuilder {
* });
* ```
* @example
- * Creating a button using setters and API data
+ * Creating a button using setters and API data:
* ```ts
* const button = new ButtonBuilder({
* style: ButtonStyle.Secondary,
@@ -732,44 +512,44 @@ declare class ButtonBuilder extends ComponentBuilder {
*/
constructor(data?: Partial);
/**
- * Sets the style of this button
+ * Sets the style of this button.
*
- * @param style - The style of the button
+ * @param style - The style to use
*/
setStyle(style: ButtonStyle): this;
/**
- * Sets the URL for this button
+ * Sets the URL for this button.
*
* @remarks
* This method is only available to buttons using the `Link` button style.
- * Only three types of URL schemes are currently supported: `https://`, `http://` and `discord://`
- * @param url - The URL to open when this button is clicked
+ * Only three types of URL schemes are currently supported: `https://`, `http://`, and `discord://`.
+ * @param url - The URL to use
*/
setURL(url: string): this;
/**
- * Sets the custom id for this button
+ * Sets the custom id for this button.
*
* @remarks
* This method is only applicable to buttons that are not using the `Link` button style.
- * @param customId - The custom id to use for this button
+ * @param customId - The custom id to use
*/
setCustomId(customId: string): this;
/**
- * Sets the emoji to display on this button
+ * Sets the emoji to display on this button.
*
- * @param emoji - The emoji to display on this button
+ * @param emoji - The emoji to use
*/
setEmoji(emoji: APIMessageComponentEmoji): this;
/**
- * Sets whether this button is disabled
+ * Sets whether this button is disabled.
*
* @param disabled - Whether to disable this button
*/
setDisabled(disabled?: boolean): this;
/**
- * Sets the label for this button
+ * Sets the label for this button.
*
- * @param label - The label to display on this button
+ * @param label - The label to use
*/
setLabel(label: string): this;
/**
@@ -778,47 +558,58 @@ declare class ButtonBuilder extends ComponentBuilder {
toJSON(): APIButtonComponent;
}
-declare class BaseSelectMenuBuilder extends ComponentBuilder {
+/**
+ * The base select menu builder that contains common symbols for select menu builders.
+ *
+ * @typeParam SelectMenuType - The type of select menu this would be instantiated for.
+ */
+declare abstract class BaseSelectMenuBuilder extends ComponentBuilder {
/**
- * Sets the placeholder for this select menu
+ * Sets the placeholder for this select menu.
*
- * @param placeholder - The placeholder to use for this select menu
+ * @param placeholder - The placeholder to use
*/
setPlaceholder(placeholder: string): this;
/**
- * Sets the minimum values that must be selected in the select menu
+ * Sets the minimum values that must be selected in the select menu.
*
* @param minValues - The minimum values that must be selected
*/
setMinValues(minValues: number): this;
/**
- * Sets the maximum values that must be selected in the select menu
+ * Sets the maximum values that must be selected in the select menu.
*
* @param maxValues - The maximum values that must be selected
*/
setMaxValues(maxValues: number): this;
/**
- * Sets the custom id for this select menu
+ * Sets the custom id for this select menu.
*
- * @param customId - The custom id to use for this select menu
+ * @param customId - The custom id to use
*/
setCustomId(customId: string): this;
/**
- * Sets whether this select menu is disabled
+ * Sets whether this select menu is disabled.
*
* @param disabled - Whether this select menu is disabled
*/
setDisabled(disabled?: boolean): this;
+ /**
+ * {@inheritDoc ComponentBuilder.toJSON}
+ */
toJSON(): SelectMenuType;
}
+/**
+ * A builder that creates API-compatible JSON data for channel select menus.
+ */
declare class ChannelSelectMenuBuilder extends BaseSelectMenuBuilder {
/**
- * Creates a new select menu from API data
+ * Creates a new select menu from API data.
*
* @param data - The API data to create this select menu with
* @example
- * Creating a select menu from an API data object
+ * Creating a select menu from an API data object:
* ```ts
* const selectMenu = new ChannelSelectMenuBuilder({
* custom_id: 'a cool select menu',
@@ -827,31 +618,44 @@ declare class ChannelSelectMenuBuilder extends BaseSelectMenuBuilder);
+ /**
+ * Adds channel types to this select menu.
+ *
+ * @param types - The channel types to use
+ */
addChannelTypes(...types: RestOrArray): this;
+ /**
+ * Sets channel types for this select menu.
+ *
+ * @param types - The channel types to use
+ */
setChannelTypes(...types: RestOrArray): this;
/**
- * {@inheritDoc ComponentBuilder.toJSON}
+ * {@inheritDoc BaseSelectMenuBuilder.toJSON}
*/
toJSON(): APIChannelSelectComponent;
}
+/**
+ * A builder that creates API-compatible JSON data for mentionable select menus.
+ */
declare class MentionableSelectMenuBuilder extends BaseSelectMenuBuilder {
/**
- * Creates a new select menu from API data
+ * Creates a new select menu from API data.
*
* @param data - The API data to create this select menu with
* @example
- * Creating a select menu from an API data object
+ * Creating a select menu from an API data object:
* ```ts
* const selectMenu = new MentionableSelectMenuBuilder({
* custom_id: 'a cool select menu',
@@ -860,24 +664,27 @@ declare class MentionableSelectMenuBuilder extends BaseSelectMenuBuilder);
}
+/**
+ * A builder that creates API-compatible JSON data for role select menus.
+ */
declare class RoleSelectMenuBuilder extends BaseSelectMenuBuilder {
/**
- * Creates a new select menu from API data
+ * Creates a new select menu from API data.
*
* @param data - The API data to create this select menu with
* @example
- * Creating a select menu from an API data object
+ * Creating a select menu from an API data object:
* ```ts
* const selectMenu = new RoleSelectMenuBuilder({
* custom_id: 'a cool select menu',
@@ -886,31 +693,31 @@ declare class RoleSelectMenuBuilder extends BaseSelectMenuBuilder);
}
/**
- * Represents a string select menu component
+ * A builder that creates API-compatible JSON data for string select menus.
*/
declare class StringSelectMenuBuilder extends BaseSelectMenuBuilder {
/**
- * The options within this select menu
+ * The options within this select menu.
*/
readonly options: StringSelectMenuOptionBuilder[];
/**
- * Creates a new select menu from API data
+ * Creates a new select menu from API data.
*
* @param data - The API data to create this select menu with
* @example
- * Creating a select menu from an API data object
+ * Creating a select menu from an API data object:
* ```ts
* const selectMenu = new StringSelectMenuBuilder({
* custom_id: 'a cool select menu',
@@ -924,7 +731,7 @@ declare class StringSelectMenuBuilder extends BaseSelectMenuBuilder);
/**
- * Adds options to this select menu
+ * Adds options to this select menu.
*
- * @param options - The options to add to this select menu
- * @returns
+ * @param options - The options to add
*/
addOptions(...options: RestOrArray): this;
/**
- * Sets the options on this select menu
+ * Sets the options for this select menu.
*
- * @param options - The options to set on this select menu
+ * @param options - The options to set
*/
setOptions(...options: RestOrArray): this;
/**
- * {@inheritDoc ComponentBuilder.toJSON}
+ * Removes, replaces, or inserts options for this select menu.
+ *
+ * @remarks
+ * This method behaves similarly
+ * to {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice | Array.prototype.splice()}.
+ * It's useful for modifying and adjusting the order of existing options.
+ * @example
+ * Remove the first option:
+ * ```ts
+ * selectMenu.spliceOptions(0, 1);
+ * ```
+ * @example
+ * Remove the first n option:
+ * ```ts
+ * const n = 4;
+ * selectMenu.spliceOptions(0, n);
+ * ```
+ * @example
+ * Remove the last option:
+ * ```ts
+ * selectMenu.spliceOptions(-1, 1);
+ * ```
+ * @param index - The index to start at
+ * @param deleteCount - The number of options to remove
+ * @param options - The replacing option objects or builders
+ */
+ spliceOptions(index: number, deleteCount: number, ...options: RestOrArray): this;
+ /**
+ * {@inheritDoc BaseSelectMenuBuilder.toJSON}
*/
toJSON(): APIStringSelectComponent;
}
+/**
+ * A builder that creates API-compatible JSON data for user select menus.
+ */
declare class UserSelectMenuBuilder extends BaseSelectMenuBuilder {
/**
- * Creates a new select menu from API data
+ * Creates a new select menu from API data.
*
* @param data - The API data to create this select menu with
* @example
- * Creating a select menu from an API data object
+ * Creating a select menu from an API data object:
* ```ts
* const selectMenu = new UserSelectMenuBuilder({
* custom_id: 'a cool select menu',
@@ -971,24 +808,27 @@ declare class UserSelectMenuBuilder extends BaseSelectMenuBuilder);
}
+/**
+ * A builder that creates API-compatible JSON data for text inputs.
+ */
declare class TextInputBuilder extends ComponentBuilder implements Equatable> {
/**
- * Creates a new text input from API data
+ * Creates a new text input from API data.
*
* @param data - The API data to create this text input with
* @example
- * Creating a select menu option from an API data object
+ * Creating a select menu option from an API data object:
* ```ts
* const textInput = new TextInputBuilder({
* custom_id: 'a cool select menu',
@@ -997,7 +837,7 @@ declare class TextInputBuilder extends ComponentBuilder i
* });
* ```
* @example
- * Creating a select menu option using setters and API data
+ * Creating a select menu option using setters and API data:
* ```ts
* const textInput = new TextInputBuilder({
* label: 'Type something else',
@@ -1010,49 +850,49 @@ declare class TextInputBuilder extends ComponentBuilder i
type?: ComponentType.TextInput;
});
/**
- * Sets the custom id for this text input
+ * Sets the custom id for this text input.
*
- * @param customId - The custom id of this text input
+ * @param customId - The custom id to use
*/
setCustomId(customId: string): this;
/**
- * Sets the label for this text input
+ * Sets the label for this text input.
*
- * @param label - The label for this text input
+ * @param label - The label to use
*/
setLabel(label: string): this;
/**
- * Sets the style for this text input
+ * Sets the style for this text input.
*
- * @param style - The style for this text input
+ * @param style - The style to use
*/
setStyle(style: TextInputStyle): this;
/**
- * Sets the minimum length of text for this text input
+ * Sets the minimum length of text for this text input.
*
* @param minLength - The minimum length of text for this text input
*/
setMinLength(minLength: number): this;
/**
- * Sets the maximum length of text for this text input
+ * Sets the maximum length of text for this text input.
*
* @param maxLength - The maximum length of text for this text input
*/
setMaxLength(maxLength: number): this;
/**
- * Sets the placeholder of this text input
+ * Sets the placeholder for this text input.
*
- * @param placeholder - The placeholder of this text input
+ * @param placeholder - The placeholder to use
*/
setPlaceholder(placeholder: string): this;
/**
- * Sets the value of this text input
+ * Sets the value for this text input.
*
- * @param value - The value for this text input
+ * @param value - The value to use
*/
setValue(value: string): this;
/**
- * Sets whether this text input is required
+ * Sets whether this text input is required.
*
* @param required - Whether this text input is required
*/
@@ -1067,27 +907,42 @@ declare class TextInputBuilder extends ComponentBuilder i
equals(other: APITextInputComponent | JSONEncodable): boolean;
}
+/**
+ * The builders that may be used for messages.
+ */
type MessageComponentBuilder = ActionRowBuilder | MessageActionRowComponentBuilder;
+/**
+ * The builders that may be used for modals.
+ */
type ModalComponentBuilder = ActionRowBuilder | ModalActionRowComponentBuilder;
+/**
+ * The builders that may be used within an action row for messages.
+ */
type MessageActionRowComponentBuilder = ButtonBuilder | ChannelSelectMenuBuilder | MentionableSelectMenuBuilder | RoleSelectMenuBuilder | StringSelectMenuBuilder | UserSelectMenuBuilder;
+/**
+ * The builders that may be used within an action row for modals.
+ */
type ModalActionRowComponentBuilder = TextInputBuilder;
+/**
+ * Any builder.
+ */
type AnyComponentBuilder = MessageActionRowComponentBuilder | ModalActionRowComponentBuilder;
/**
- * Represents an action row component
+ * A builder that creates API-compatible JSON data for action rows.
*
* @typeParam T - The types of components this action row holds
*/
declare class ActionRowBuilder extends ComponentBuilder> {
/**
- * The components within this action row
+ * The components within this action row.
*/
readonly components: T[];
/**
- * Creates a new action row from API data
+ * Creates a new action row from API data.
*
* @param data - The API data to create this action row with
* @example
- * Creating an action row from an API data object
+ * Creating an action row from an API data object:
* ```ts
* const actionRow = new ActionRowBuilder({
* components: [
@@ -1101,7 +956,7 @@ declare class ActionRowBuilder extends ComponentB
* });
* ```
* @example
- * Creating an action row using setters and API data
+ * Creating an action row using setters and API data:
* ```ts
* const actionRow = new ActionRowBuilder({
* components: [
@@ -1120,13 +975,13 @@ declare class ActionRowBuilder extends ComponentB
/**
* Adds components to this action row.
*
- * @param components - The components to add to this action row.
+ * @param components - The components to add
*/
addComponents(...components: RestOrArray): this;
/**
- * Sets the components in this action row
+ * Sets components for this action row.
*
- * @param components - The components to set this row to
+ * @param components - The components to set
*/
setComponents(...components: RestOrArray): this;
/**
@@ -1135,24 +990,58 @@ declare class ActionRowBuilder extends ComponentB
toJSON(): APIActionRowComponent>;
}
+/**
+ * Components here are mapped to their respective builder.
+ */
interface MappedComponentTypes {
+ /**
+ * The action row component type is associated with an {@link ActionRowBuilder}.
+ */
[ComponentType.ActionRow]: ActionRowBuilder;
+ /**
+ * The button component type is associated with an {@link ButtonBuilder}.
+ */
[ComponentType.Button]: ButtonBuilder;
+ /**
+ * The string select component type is associated with an {@link StringSelectMenuBuilder}.
+ */
[ComponentType.StringSelect]: StringSelectMenuBuilder;
+ /**
+ * The text inpiut component type is associated with an {@link TextInputBuilder}.
+ */
[ComponentType.TextInput]: TextInputBuilder;
+ /**
+ * The user select component type is associated with an {@link UserSelectMenuBuilder}.
+ */
[ComponentType.UserSelect]: UserSelectMenuBuilder;
+ /**
+ * The role select component type is associated with an {@link RoleSelectMenuBuilder}.
+ */
[ComponentType.RoleSelect]: RoleSelectMenuBuilder;
+ /**
+ * The mentionable select component type is associated with an {@link MentionableSelectMenuBuilder}.
+ */
[ComponentType.MentionableSelect]: MentionableSelectMenuBuilder;
+ /**
+ * The channel select component type is associated with an {@link ChannelSelectMenuBuilder}.
+ */
[ComponentType.ChannelSelect]: ChannelSelectMenuBuilder;
}
/**
- * Factory for creating components from API data
+ * Factory for creating components from API data.
*
- * @param data - The api data to transform to a component class
+ * @typeParam T - The type of component to use
+ * @param data - The API data to transform to a component class
*/
declare function createComponentBuilder(data: (APIModalComponent | APIMessageComponent) & {
type: T;
}): MappedComponentTypes[T];
+/**
+ * Factory for creating components from API data.
+ *
+ * @typeParam C - The type of component to use
+ * @param data - The API data to transform to a component class
+ */
declare function createComponentBuilder(data: C): C;
declare const textInputStyleValidator: _sapphire_shapeshift.NativeEnumValidator;
@@ -1164,52 +1053,66 @@ declare const placeholderValidator: _sapphire_shapeshift.StringValidator
declare const labelValidator: _sapphire_shapeshift.StringValidator;
declare function validateRequiredParameters$3(customId?: string, style?: TextInputStyle, label?: string): void;
-declare const Assertions$3_textInputStyleValidator: typeof textInputStyleValidator;
-declare const Assertions$3_minLengthValidator: typeof minLengthValidator;
+declare const Assertions$3_labelValidator: typeof labelValidator;
declare const Assertions$3_maxLengthValidator: typeof maxLengthValidator;
+declare const Assertions$3_minLengthValidator: typeof minLengthValidator;
+declare const Assertions$3_placeholderValidator: typeof placeholderValidator;
declare const Assertions$3_requiredValidator: typeof requiredValidator;
+declare const Assertions$3_textInputStyleValidator: typeof textInputStyleValidator;
declare const Assertions$3_valueValidator: typeof valueValidator;
-declare const Assertions$3_placeholderValidator: typeof placeholderValidator;
-declare const Assertions$3_labelValidator: typeof labelValidator;
declare namespace Assertions$3 {
export {
- Assertions$3_textInputStyleValidator as textInputStyleValidator,
- Assertions$3_minLengthValidator as minLengthValidator,
+ Assertions$3_labelValidator as labelValidator,
Assertions$3_maxLengthValidator as maxLengthValidator,
- Assertions$3_requiredValidator as requiredValidator,
- Assertions$3_valueValidator as valueValidator,
+ Assertions$3_minLengthValidator as minLengthValidator,
Assertions$3_placeholderValidator as placeholderValidator,
- Assertions$3_labelValidator as labelValidator,
+ Assertions$3_requiredValidator as requiredValidator,
+ Assertions$3_textInputStyleValidator as textInputStyleValidator,
validateRequiredParameters$3 as validateRequiredParameters,
+ Assertions$3_valueValidator as valueValidator,
};
}
+/**
+ * A builder that creates API-compatible JSON data for modals.
+ */
declare class ModalBuilder implements JSONEncodable {
+ /**
+ * The API data associated with this modal.
+ */
readonly data: Partial;
+ /**
+ * The components within this modal.
+ */
readonly components: ActionRowBuilder[];
+ /**
+ * Creates a new modal from API data.
+ *
+ * @param data - The API data to create this modal with
+ */
constructor({ components, ...data }?: Partial);
/**
- * Sets the title of the modal
+ * Sets the title of this modal.
*
- * @param title - The title of the modal
+ * @param title - The title to use
*/
setTitle(title: string): this;
/**
- * Sets the custom id of the modal
+ * Sets the custom id of this modal.
*
- * @param customId - The custom id of this modal
+ * @param customId - The custom id to use
*/
setCustomId(customId: string): this;
/**
- * Adds components to this modal
+ * Adds components to this modal.
*
- * @param components - The components to add to this modal
+ * @param components - The components to add
*/
addComponents(...components: RestOrArray | APIActionRowComponent>): this;
/**
- * Sets the components in this modal
+ * Sets components for this modal.
*
- * @param components - The components to set this modal to
+ * @param components - The components to set
*/
setComponents(...components: RestOrArray>): this;
/**
@@ -1222,140 +1125,252 @@ declare const titleValidator: _sapphire_shapeshift.StringValidator;
declare const componentsValidator: _sapphire_shapeshift.ArrayValidator<[ActionRowBuilder, ...ActionRowBuilder[]], ActionRowBuilder>;
declare function validateRequiredParameters$2(customId?: string, title?: string, components?: ActionRowBuilder[]): void;
-declare const Assertions$2_titleValidator: typeof titleValidator;
declare const Assertions$2_componentsValidator: typeof componentsValidator;
+declare const Assertions$2_titleValidator: typeof titleValidator;
declare namespace Assertions$2 {
export {
- Assertions$2_titleValidator as titleValidator,
Assertions$2_componentsValidator as componentsValidator,
+ Assertions$2_titleValidator as titleValidator,
validateRequiredParameters$2 as validateRequiredParameters,
};
}
+/**
+ * This mixin holds name and description symbols for slash commands.
+ */
declare class SharedNameAndDescription {
+ /**
+ * The name of this command.
+ */
readonly name: string;
+ /**
+ * The name localizations of this command.
+ */
readonly name_localizations?: LocalizationMap;
+ /**
+ * The description of this command.
+ */
readonly description: string;
+ /**
+ * The description localizations of this command.
+ */
readonly description_localizations?: LocalizationMap;
/**
- * Sets the name
+ * Sets the name of this command.
*
- * @param name - The name
+ * @param name - The name to use
*/
setName(name: string): this;
/**
- * Sets the description
+ * Sets the description of this command.
*
- * @param description - The description
+ * @param description - The description to use
*/
setDescription(description: string): this;
/**
- * Sets a name localization
+ * SSets a name localization for this command.
*
- * @param locale - The locale to set a description for
- * @param localizedName - The localized description for the given locale
+ * @param locale - The locale to set
+ * @param localizedName - The localized name for the given `locale`
*/
setNameLocalization(locale: LocaleString, localizedName: string | null): this;
/**
- * Sets the name localizations
+ * Sets the name localizations for this command.
*
- * @param localizedNames - The dictionary of localized descriptions to set
+ * @param localizedNames - The object of localized names to set
*/
setNameLocalizations(localizedNames: LocalizationMap | null): this;
/**
- * Sets a description localization
+ * Sets a description localization for this command.
*
- * @param locale - The locale to set a description for
+ * @param locale - The locale to set
* @param localizedDescription - The localized description for the given locale
*/
setDescriptionLocalization(locale: LocaleString, localizedDescription: string | null): this;
/**
- * Sets the description localizations
+ * Sets the description localizations for this command.
*
- * @param localizedDescriptions - The dictionary of localized descriptions to set
+ * @param localizedDescriptions - The object of localized descriptions to set
*/
setDescriptionLocalizations(localizedDescriptions: LocalizationMap | null): this;
}
+/**
+ * The base application command option builder that contains common symbols for application command builders.
+ */
declare abstract class ApplicationCommandOptionBase extends SharedNameAndDescription {
+ /**
+ * The type of this option.
+ */
abstract readonly type: ApplicationCommandOptionType;
+ /**
+ * Whether this option is required.
+ *
+ * @defaultValue `false`
+ */
readonly required: boolean;
/**
- * Marks the option as required
+ * Sets whether this option is required.
*
- * @param required - If this option should be required
+ * @param required - Whether this option should be required
*/
setRequired(required: boolean): this;
+ /**
+ * Serializes this builder to API-compatible JSON data.
+ *
+ * @remarks
+ * This method runs validations on the data before serializing it.
+ * As such, it may throw an error if the data is invalid.
+ */
abstract toJSON(): APIApplicationCommandBasicOption;
+ /**
+ * This method runs required validators on this builder.
+ */
protected runRequiredValidations(): void;
}
+/**
+ * A slash command attachment option.
+ */
declare class SlashCommandAttachmentOption extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
readonly type: ApplicationCommandOptionType.Attachment;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON(): APIApplicationCommandAttachmentOption;
}
+/**
+ * A slash command boolean option.
+ */
declare class SlashCommandBooleanOption extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
readonly type: ApplicationCommandOptionType.Boolean;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON(): APIApplicationCommandBooleanOption;
}
+/**
+ * The allowed channel types used for a channel option in a slash command builder.
+ *
+ * @privateRemarks This can't be dynamic because const enums are erased at runtime.
+ * @internal
+ */
declare const allowedChannelTypes: readonly [ChannelType.GuildText, ChannelType.GuildVoice, ChannelType.GuildCategory, ChannelType.GuildAnnouncement, ChannelType.AnnouncementThread, ChannelType.PublicThread, ChannelType.PrivateThread, ChannelType.GuildStageVoice, ChannelType.GuildForum];
-type ApplicationCommandOptionAllowedChannelTypes = typeof allowedChannelTypes[number];
+/**
+ * The type of allowed channel types used for a channel option.
+ */
+type ApplicationCommandOptionAllowedChannelTypes = (typeof allowedChannelTypes)[number];
+/**
+ * This mixin holds channel type symbols used for options.
+ */
declare class ApplicationCommandOptionChannelTypesMixin {
+ /**
+ * The channel types of this option.
+ */
readonly channel_types?: ApplicationCommandOptionAllowedChannelTypes[];
/**
- * Adds channel types to this option
+ * Adds channel types to this option.
*
- * @param channelTypes - The channel types to add
+ * @param channelTypes - The channel types
*/
addChannelTypes(...channelTypes: ApplicationCommandOptionAllowedChannelTypes[]): this;
}
+/**
+ * A slash command channel option.
+ */
declare class SlashCommandChannelOption extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
readonly type: ApplicationCommandOptionType.Channel;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON(): APIApplicationCommandChannelOption;
}
interface SlashCommandChannelOption extends ApplicationCommandOptionChannelTypesMixin {
}
+/**
+ * This mixin holds minimum and maximum symbols used for options.
+ */
declare abstract class ApplicationCommandNumericOptionMinMaxValueMixin {
+ /**
+ * The maximum value of this option.
+ */
readonly max_value?: number;
+ /**
+ * The minimum value of this option.
+ */
readonly min_value?: number;
/**
- * Sets the maximum number value of this option
+ * Sets the maximum number value of this option.
*
* @param max - The maximum value this option can be
*/
abstract setMaxValue(max: number): this;
/**
- * Sets the minimum number value of this option
+ * Sets the minimum number value of this option.
*
* @param min - The minimum value this option can be
*/
abstract setMinValue(min: number): this;
}
+/**
+ * This mixin holds choices and autocomplete symbols used for options.
+ */
declare class ApplicationCommandOptionWithChoicesAndAutocompleteMixin {
+ /**
+ * The choices of this option.
+ */
readonly choices?: APIApplicationCommandOptionChoice[];
+ /**
+ * Whether this option utilizes autocomplete.
+ */
readonly autocomplete?: boolean;
+ /**
+ * The type of this option.
+ *
+ * @privateRemarks Since this is present and this is a mixin, this is needed.
+ */
readonly type: ApplicationCommandOptionType;
/**
- * Adds multiple choices for this option
+ * Adds multiple choices to this option.
*
* @param choices - The choices to add
*/
addChoices(...choices: APIApplicationCommandOptionChoice[]): this;
+ /**
+ * Sets multiple choices for this option.
+ *
+ * @param choices - The choices to set
+ */
setChoices[]>(...choices: Input): this;
/**
- * Marks the option as autocompletable
+ * Whether this option uses autocomplete.
*
- * @param autocomplete - If this option should be autocompletable
+ * @param autocomplete - Whether this option should use autocomplete
*/
setAutocomplete(autocomplete: boolean): this;
}
+/**
+ * A slash command integer option.
+ */
declare class SlashCommandIntegerOption extends ApplicationCommandOptionBase implements ApplicationCommandNumericOptionMinMaxValueMixin {
+ /**
+ * The type of this option.
+ */
readonly type: ApplicationCommandOptionType.Integer;
/**
* {@inheritDoc ApplicationCommandNumericOptionMinMaxValueMixin.setMaxValue}
@@ -1365,17 +1380,35 @@ declare class SlashCommandIntegerOption extends ApplicationCommandOptionBase imp
* {@inheritDoc ApplicationCommandNumericOptionMinMaxValueMixin.setMinValue}
*/
setMinValue(min: number): this;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON(): APIApplicationCommandIntegerOption;
}
interface SlashCommandIntegerOption extends ApplicationCommandNumericOptionMinMaxValueMixin, ApplicationCommandOptionWithChoicesAndAutocompleteMixin {
}
+/**
+ * A slash command mentionable option.
+ */
declare class SlashCommandMentionableOption extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
readonly type: ApplicationCommandOptionType.Mentionable;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON(): APIApplicationCommandMentionableOption;
}
+/**
+ * A slash command number option.
+ */
declare class SlashCommandNumberOption extends ApplicationCommandOptionBase implements ApplicationCommandNumericOptionMinMaxValueMixin {
+ /**
+ * The type of this option.
+ */
readonly type: ApplicationCommandOptionType.Number;
/**
* {@inheritDoc ApplicationCommandNumericOptionMinMaxValueMixin.setMaxValue}
@@ -1385,19 +1418,43 @@ declare class SlashCommandNumberOption extends ApplicationCommandOptionBase impl
* {@inheritDoc ApplicationCommandNumericOptionMinMaxValueMixin.setMinValue}
*/
setMinValue(min: number): this;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON(): APIApplicationCommandNumberOption;
}
interface SlashCommandNumberOption extends ApplicationCommandNumericOptionMinMaxValueMixin, ApplicationCommandOptionWithChoicesAndAutocompleteMixin {
}
+/**
+ * A slash command role option.
+ */
declare class SlashCommandRoleOption extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
readonly type: ApplicationCommandOptionType.Role;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON(): APIApplicationCommandRoleOption;
}
+/**
+ * A slash command string option.
+ */
declare class SlashCommandStringOption extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
readonly type: ApplicationCommandOptionType.String;
+ /**
+ * The maximum length of this option.
+ */
readonly max_length?: number;
+ /**
+ * The minimum length of this option.
+ */
readonly min_length?: number;
/**
* Sets the maximum length of this string option.
@@ -1411,179 +1468,217 @@ declare class SlashCommandStringOption extends ApplicationCommandOptionBase {
* @param min - The minimum length this option can be
*/
setMinLength(min: number): this;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON(): APIApplicationCommandStringOption;
}
interface SlashCommandStringOption extends ApplicationCommandOptionWithChoicesAndAutocompleteMixin {
}
+/**
+ * A slash command user option.
+ */
declare class SlashCommandUserOption extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
readonly type: ApplicationCommandOptionType.User;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON(): APIApplicationCommandUserOption;
}
+/**
+ * This mixin holds symbols that can be shared in slash command options.
+ *
+ * @typeParam ShouldOmitSubcommandFunctions - Whether to omit subcommand functions.
+ */
declare class SharedSlashCommandOptions {
readonly options: ToAPIApplicationCommandOptions[];
/**
- * Adds a boolean option
+ * Adds a boolean option.
*
- * @param input - A function that returns an option builder, or an already built builder
+ * @param input - A function that returns an option builder or an already built builder
*/
addBooleanOption(input: SlashCommandBooleanOption | ((builder: SlashCommandBooleanOption) => SlashCommandBooleanOption)): ShouldOmitSubcommandFunctions extends true ? Omit : this;
/**
- * Adds a user option
+ * Adds a user option.
*
- * @param input - A function that returns an option builder, or an already built builder
+ * @param input - A function that returns an option builder or an already built builder
*/
addUserOption(input: SlashCommandUserOption | ((builder: SlashCommandUserOption) => SlashCommandUserOption)): ShouldOmitSubcommandFunctions extends true ? Omit : this;
/**
- * Adds a channel option
+ * Adds a channel option.
*
- * @param input - A function that returns an option builder, or an already built builder
+ * @param input - A function that returns an option builder or an already built builder
*/
addChannelOption(input: SlashCommandChannelOption | ((builder: SlashCommandChannelOption) => SlashCommandChannelOption)): ShouldOmitSubcommandFunctions extends true ? Omit : this;
/**
- * Adds a role option
+ * Adds a role option.
*
- * @param input - A function that returns an option builder, or an already built builder
+ * @param input - A function that returns an option builder or an already built builder
*/
addRoleOption(input: SlashCommandRoleOption | ((builder: SlashCommandRoleOption) => SlashCommandRoleOption)): ShouldOmitSubcommandFunctions extends true ? Omit : this;
/**
- * Adds an attachment option
+ * Adds an attachment option.
*
- * @param input - A function that returns an option builder, or an already built builder
+ * @param input - A function that returns an option builder or an already built builder
*/
addAttachmentOption(input: SlashCommandAttachmentOption | ((builder: SlashCommandAttachmentOption) => SlashCommandAttachmentOption)): ShouldOmitSubcommandFunctions extends true ? Omit : this;
/**
- * Adds a mentionable option
+ * Adds a mentionable option.
*
- * @param input - A function that returns an option builder, or an already built builder
+ * @param input - A function that returns an option builder or an already built builder
*/
addMentionableOption(input: SlashCommandMentionableOption | ((builder: SlashCommandMentionableOption) => SlashCommandMentionableOption)): ShouldOmitSubcommandFunctions extends true ? Omit : this;
/**
- * Adds a string option
+ * Adds a string option.
*
- * @param input - A function that returns an option builder, or an already built builder
+ * @param input - A function that returns an option builder or an already built builder
*/
addStringOption(input: Omit | Omit | SlashCommandStringOption | ((builder: SlashCommandStringOption) => Omit | Omit | SlashCommandStringOption)): ShouldOmitSubcommandFunctions extends true ? Omit : this;
/**
- * Adds an integer option
+ * Adds an integer option.
*
- * @param input - A function that returns an option builder, or an already built builder
+ * @param input - A function that returns an option builder or an already built builder
*/
addIntegerOption(input: Omit | Omit | SlashCommandIntegerOption | ((builder: SlashCommandIntegerOption) => Omit | Omit | SlashCommandIntegerOption)): ShouldOmitSubcommandFunctions extends true ? Omit : this;
/**
- * Adds a number option
+ * Adds a number option.
*
- * @param input - A function that returns an option builder, or an already built builder
+ * @param input - A function that returns an option builder or an already built builder
*/
addNumberOption(input: Omit | Omit | SlashCommandNumberOption | ((builder: SlashCommandNumberOption) => Omit | Omit | SlashCommandNumberOption)): ShouldOmitSubcommandFunctions extends true ? Omit : this;
+ /**
+ * Where the actual adding magic happens. β¨
+ *
+ * @param input - The input. What else?
+ * @param Instance - The instance of whatever is being added
+ * @internal
+ */
private _sharedAddOptionMethod;
}
/**
- * Represents a folder for subcommands
+ * Represents a folder for subcommands.
*
- * For more information, go to https://discord.com/developers/docs/interactions/application-commands#subcommands-and-subcommand-groups
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#subcommands-and-subcommand-groups}
*/
declare class SlashCommandSubcommandGroupBuilder implements ToAPIApplicationCommandOptions {
/**
- * The name of this subcommand group
+ * The name of this subcommand group.
*/
readonly name: string;
/**
- * The description of this subcommand group
+ * The description of this subcommand group.
*/
readonly description: string;
/**
- * The subcommands part of this subcommand group
+ * The subcommands within this subcommand group.
*/
readonly options: SlashCommandSubcommandBuilder[];
/**
- * Adds a new subcommand to this group
+ * Adds a new subcommand to this group.
*
- * @param input - A function that returns a subcommand builder, or an already built builder
+ * @param input - A function that returns a subcommand builder or an already built builder
*/
addSubcommand(input: SlashCommandSubcommandBuilder | ((subcommandGroup: SlashCommandSubcommandBuilder) => SlashCommandSubcommandBuilder)): this;
+ /**
+ * Serializes this builder to API-compatible JSON data.
+ *
+ * @remarks
+ * This method runs validations on the data before serializing it.
+ * As such, it may throw an error if the data is invalid.
+ */
toJSON(): APIApplicationCommandSubcommandGroupOption;
}
interface SlashCommandSubcommandGroupBuilder extends SharedNameAndDescription {
}
/**
- * Represents a subcommand
+ * A builder that creates API-compatible JSON data for slash command subcommands.
*
- * For more information, go to https://discord.com/developers/docs/interactions/application-commands#subcommands-and-subcommand-groups
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#subcommands-and-subcommand-groups}
*/
declare class SlashCommandSubcommandBuilder implements ToAPIApplicationCommandOptions {
/**
- * The name of this subcommand
+ * The name of this subcommand.
*/
readonly name: string;
/**
- * The description of this subcommand
+ * The description of this subcommand.
*/
readonly description: string;
/**
- * The options of this subcommand
+ * The options within this subcommand.
*/
readonly options: ApplicationCommandOptionBase[];
+ /**
+ * Serializes this builder to API-compatible JSON data.
+ *
+ * @remarks
+ * This method runs validations on the data before serializing it.
+ * As such, it may throw an error if the data is invalid.
+ */
toJSON(): APIApplicationCommandSubcommandOption;
}
interface SlashCommandSubcommandBuilder extends SharedNameAndDescription, SharedSlashCommandOptions {
}
+/**
+ * A builder that creates API-compatible JSON data for slash commands.
+ */
declare class SlashCommandBuilder {
/**
- * The name of this slash command
+ * The name of this command.
*/
readonly name: string;
/**
- * The localized names for this command
+ * The name localizations of this command.
*/
readonly name_localizations?: LocalizationMap;
/**
- * The description of this slash command
+ * The description of this command.
*/
readonly description: string;
/**
- * The localized descriptions for this command
+ * The description localizations of this command.
*/
readonly description_localizations?: LocalizationMap;
/**
- * The options of this slash command
+ * The options of this command.
*/
readonly options: ToAPIApplicationCommandOptions[];
/**
- * Whether the command is enabled by default when the app is added to a guild
+ * Whether this command is enabled by default when the application is added to a guild.
*
- * @deprecated This property is deprecated and will be removed in the future.
- * You should use {@link (SlashCommandBuilder:class).setDefaultMemberPermissions} or {@link (SlashCommandBuilder:class).setDMPermission} instead.
+ * @deprecated Use {@link ContextMenuCommandBuilder.setDefaultMemberPermissions} or {@link ContextMenuCommandBuilder.setDMPermission} instead.
*/
readonly default_permission: boolean | undefined;
/**
- * Set of permissions represented as a bit set for the command
+ * The set of permissions represented as a bit set for the command.
*/
readonly default_member_permissions: Permissions | null | undefined;
/**
- * Indicates whether the command is available in DMs with the application, only for globally-scoped commands.
- * By default, commands are visible.
+ * Indicates whether the command is available in direct messages with the application.
+ *
+ * @remarks
+ * By default, commands are visible. This property is only for global commands.
*/
readonly dm_permission: boolean | undefined;
/**
- * Returns the final data that should be sent to Discord.
- *
- * @remarks
- * This method runs validations on the data before serializing it.
- * As such, it may throw an error if the data is invalid.
+ * Whether this command is NSFW.
*/
- toJSON(): RESTPostAPIChatInputApplicationCommandsJSONBody;
+ readonly nsfw: boolean | undefined;
/**
* Sets whether the command is enabled by default when the application is added to a guild.
*
* @remarks
* If set to `false`, you will have to later `PUT` the permissions for this command.
* @param value - Whether or not to enable this command by default
- * @see https://discord.com/developers/docs/interactions/application-commands#permissions
- * @deprecated Use {@link (SlashCommandBuilder:class).setDefaultMemberPermissions} or {@link (SlashCommandBuilder:class).setDMPermission} instead.
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
+ * @deprecated Use {@link SlashCommandBuilder.setDefaultMemberPermissions} or {@link SlashCommandBuilder.setDMPermission} instead.
*/
setDefaultPermission(value: boolean): this;
/**
@@ -1592,36 +1687,61 @@ declare class SlashCommandBuilder {
* @remarks
* You can set this to `'0'` to disable the command by default.
* @param permissions - The permissions bit field to set
- * @see https://discord.com/developers/docs/interactions/application-commands#permissions
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
*/
setDefaultMemberPermissions(permissions: Permissions | bigint | number | null | undefined): this;
/**
- * Sets if the command is available in DMs with the application, only for globally-scoped commands.
- * By default, commands are visible.
+ * Sets if the command is available in direct messages with the application.
*
- * @param enabled - If the command should be enabled in DMs
- * @see https://discord.com/developers/docs/interactions/application-commands#permissions
+ * @remarks
+ * By default, commands are visible. This method is only for global commands.
+ * @param enabled - Whether the command should be enabled in direct messages
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
*/
setDMPermission(enabled: boolean | null | undefined): this;
/**
- * Adds a new subcommand group to this command
+ * Sets whether this command is NSFW.
+ *
+ * @param nsfw - Whether this command is NSFW
+ */
+ setNSFW(nsfw?: boolean): this;
+ /**
+ * Adds a new subcommand group to this command.
*
- * @param input - A function that returns a subcommand group builder, or an already built builder
+ * @param input - A function that returns a subcommand group builder or an already built builder
*/
addSubcommandGroup(input: SlashCommandSubcommandGroupBuilder | ((subcommandGroup: SlashCommandSubcommandGroupBuilder) => SlashCommandSubcommandGroupBuilder)): SlashCommandSubcommandsOnlyBuilder;
/**
- * Adds a new subcommand to this command
+ * Adds a new subcommand to this command.
*
- * @param input - A function that returns a subcommand builder, or an already built builder
+ * @param input - A function that returns a subcommand builder or an already built builder
*/
addSubcommand(input: SlashCommandSubcommandBuilder | ((subcommandGroup: SlashCommandSubcommandBuilder) => SlashCommandSubcommandBuilder)): SlashCommandSubcommandsOnlyBuilder;
+ /**
+ * Serializes this builder to API-compatible JSON data.
+ *
+ * @remarks
+ * This method runs validations on the data before serializing it.
+ * As such, it may throw an error if the data is invalid.
+ */
+ toJSON(): RESTPostAPIChatInputApplicationCommandsJSONBody;
}
interface SlashCommandBuilder extends SharedNameAndDescription, SharedSlashCommandOptions {
}
+/**
+ * An interface specifically for slash command subcommands.
+ */
interface SlashCommandSubcommandsOnlyBuilder extends Omit> {
}
+/**
+ * An interface specifically for slash command options.
+ */
interface SlashCommandOptionsOnlyBuilder extends SharedNameAndDescription, SharedSlashCommandOptions, Pick {
}
+/**
+ * An interface that ensures the `toJSON()` call will return something
+ * that can be serialized into API-compatible data.
+ */
interface ToAPIApplicationCommandOptions {
toJSON(): APIApplicationCommandOption;
}
@@ -1635,76 +1755,87 @@ declare function validateDefaultPermission$1(value: unknown): asserts value is b
declare function validateRequired(required: unknown): asserts required is boolean;
declare function validateChoicesLength(amountAdding: number, choices?: APIApplicationCommandOptionChoice[]): void;
declare function assertReturnOfBuilder(input: unknown, ExpectedInstanceOf: new () => T): asserts input is T;
-declare const localizationMapPredicate: _sapphire_shapeshift.UnionValidator<_sapphire_shapeshift.UndefinedToOptional>> | null | undefined>;
+declare const localizationMapPredicate: _sapphire_shapeshift.UnionValidator<_sapphire_shapeshift.UndefinedToOptional>> | null | undefined>;
declare function validateLocalizationMap(value: unknown): asserts value is LocalizationMap;
declare function validateDMPermission$1(value: unknown): asserts value is boolean | null | undefined;
declare function validateDefaultMemberPermissions$1(permissions: unknown): string | null | undefined;
+declare function validateNSFW(value: unknown): asserts value is boolean;
+declare const Assertions$1_assertReturnOfBuilder: typeof assertReturnOfBuilder;
+declare const Assertions$1_localizationMapPredicate: typeof localizationMapPredicate;
+declare const Assertions$1_validateChoicesLength: typeof validateChoicesLength;
declare const Assertions$1_validateDescription: typeof validateDescription;
declare const Assertions$1_validateLocale: typeof validateLocale;
+declare const Assertions$1_validateLocalizationMap: typeof validateLocalizationMap;
declare const Assertions$1_validateMaxOptionsLength: typeof validateMaxOptionsLength;
+declare const Assertions$1_validateNSFW: typeof validateNSFW;
declare const Assertions$1_validateRequired: typeof validateRequired;
-declare const Assertions$1_validateChoicesLength: typeof validateChoicesLength;
-declare const Assertions$1_assertReturnOfBuilder: typeof assertReturnOfBuilder;
-declare const Assertions$1_localizationMapPredicate: typeof localizationMapPredicate;
-declare const Assertions$1_validateLocalizationMap: typeof validateLocalizationMap;
declare namespace Assertions$1 {
export {
- validateName$1 as validateName,
- Assertions$1_validateDescription as validateDescription,
- Assertions$1_validateLocale as validateLocale,
- Assertions$1_validateMaxOptionsLength as validateMaxOptionsLength,
- validateRequiredParameters$1 as validateRequiredParameters,
- validateDefaultPermission$1 as validateDefaultPermission,
- Assertions$1_validateRequired as validateRequired,
- Assertions$1_validateChoicesLength as validateChoicesLength,
Assertions$1_assertReturnOfBuilder as assertReturnOfBuilder,
Assertions$1_localizationMapPredicate as localizationMapPredicate,
- Assertions$1_validateLocalizationMap as validateLocalizationMap,
+ Assertions$1_validateChoicesLength as validateChoicesLength,
validateDMPermission$1 as validateDMPermission,
validateDefaultMemberPermissions$1 as validateDefaultMemberPermissions,
+ validateDefaultPermission$1 as validateDefaultPermission,
+ Assertions$1_validateDescription as validateDescription,
+ Assertions$1_validateLocale as validateLocale,
+ Assertions$1_validateLocalizationMap as validateLocalizationMap,
+ Assertions$1_validateMaxOptionsLength as validateMaxOptionsLength,
+ Assertions$1_validateNSFW as validateNSFW,
+ validateName$1 as validateName,
+ Assertions$1_validateRequired as validateRequired,
+ validateRequiredParameters$1 as validateRequiredParameters,
};
}
+/**
+ * The type a context menu command can be.
+ */
+type ContextMenuCommandType = ApplicationCommandType.Message | ApplicationCommandType.User;
+/**
+ * A builder that creates API-compatible JSON data for context menu commands.
+ */
declare class ContextMenuCommandBuilder {
/**
- * The name of this context menu command
+ * The name of this command.
*/
readonly name: string;
/**
- * The localized names for this command
+ * The name localizations of this command.
*/
readonly name_localizations?: LocalizationMap;
/**
- * The type of this context menu command
+ * The type of this command.
*/
readonly type: ContextMenuCommandType;
/**
- * Whether the command is enabled by default when the app is added to a guild
+ * Whether this command is enabled by default when the application is added to a guild.
*
- * @deprecated This property is deprecated and will be removed in the future.
- * You should use {@link ContextMenuCommandBuilder.setDefaultMemberPermissions} or {@link ContextMenuCommandBuilder.setDMPermission} instead.
+ * @deprecated Use {@link ContextMenuCommandBuilder.setDefaultMemberPermissions} or {@link ContextMenuCommandBuilder.setDMPermission} instead.
*/
readonly default_permission: boolean | undefined;
/**
- * Set of permissions represented as a bit set for the command
+ * The set of permissions represented as a bit set for the command.
*/
readonly default_member_permissions: Permissions | null | undefined;
/**
- * Indicates whether the command is available in DMs with the application, only for globally-scoped commands.
- * By default, commands are visible.
+ * Indicates whether the command is available in direct messages with the application.
+ *
+ * @remarks
+ * By default, commands are visible. This property is only for global commands.
*/
readonly dm_permission: boolean | undefined;
/**
- * Sets the name
+ * Sets the name of this command.
*
- * @param name - The name
+ * @param name - The name to use
*/
setName(name: string): this;
/**
- * Sets the type
+ * Sets the type of this command.
*
- * @param type - The type
+ * @param type - The type to use
*/
setType(type: ContextMenuCommandType): this;
/**
@@ -1712,43 +1843,44 @@ declare class ContextMenuCommandBuilder {
*
* @remarks
* If set to `false`, you will have to later `PUT` the permissions for this command.
- * @param value - Whether or not to enable this command by default
- * @see https://discord.com/developers/docs/interactions/application-commands#permissions
+ * @param value - Whether to enable this command by default
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
* @deprecated Use {@link ContextMenuCommandBuilder.setDefaultMemberPermissions} or {@link ContextMenuCommandBuilder.setDMPermission} instead.
*/
setDefaultPermission(value: boolean): this;
/**
- * Sets the default permissions a member should have in order to run the command.
+ * Sets the default permissions a member should have in order to run this command.
*
* @remarks
* You can set this to `'0'` to disable the command by default.
* @param permissions - The permissions bit field to set
- * @see https://discord.com/developers/docs/interactions/application-commands#permissions
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
*/
setDefaultMemberPermissions(permissions: Permissions | bigint | number | null | undefined): this;
/**
- * Sets if the command is available in DMs with the application, only for globally-scoped commands.
- * By default, commands are visible.
+ * Sets if the command is available in direct messages with the application.
*
- * @param enabled - If the command should be enabled in DMs
- * @see https://discord.com/developers/docs/interactions/application-commands#permissions
+ * @remarks
+ * By default, commands are visible. This method is only for global commands.
+ * @param enabled - Whether the command should be enabled in direct messages
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
*/
setDMPermission(enabled: boolean | null | undefined): this;
/**
- * Sets a name localization
+ * Sets a name localization for this command.
*
- * @param locale - The locale to set a description for
- * @param localizedName - The localized description for the given locale
+ * @param locale - The locale to set
+ * @param localizedName - The localized name for the given `locale`
*/
setNameLocalization(locale: LocaleString, localizedName: string | null): this;
/**
- * Sets the name localizations
+ * Sets the name localizations for this command.
*
- * @param localizedNames - The dictionary of localized descriptions to set
+ * @param localizedNames - The object of localized names to set
*/
setNameLocalizations(localizedNames: LocalizationMap | null): this;
/**
- * Returns the final data that should be sent to Discord.
+ * Serializes this builder to API-compatible JSON data.
*
* @remarks
* This method runs validations on the data before serializing it.
@@ -1756,7 +1888,6 @@ declare class ContextMenuCommandBuilder {
*/
toJSON(): RESTPostAPIContextMenuApplicationCommandsJSONBody;
}
-type ContextMenuCommandType = ApplicationCommandType.Message | ApplicationCommandType.User;
declare function validateDefaultPermission(value: unknown): asserts value is boolean;
declare function validateName(name: unknown): asserts name is string;
@@ -1765,33 +1896,53 @@ declare function validateRequiredParameters(name: string, type: number): void;
declare function validateDMPermission(value: unknown): asserts value is boolean | null | undefined;
declare function validateDefaultMemberPermissions(permissions: unknown): string | null | undefined;
+declare const Assertions_validateDMPermission: typeof validateDMPermission;
+declare const Assertions_validateDefaultMemberPermissions: typeof validateDefaultMemberPermissions;
declare const Assertions_validateDefaultPermission: typeof validateDefaultPermission;
declare const Assertions_validateName: typeof validateName;
-declare const Assertions_validateType: typeof validateType;
declare const Assertions_validateRequiredParameters: typeof validateRequiredParameters;
-declare const Assertions_validateDMPermission: typeof validateDMPermission;
-declare const Assertions_validateDefaultMemberPermissions: typeof validateDefaultMemberPermissions;
+declare const Assertions_validateType: typeof validateType;
declare namespace Assertions {
export {
+ Assertions_validateDMPermission as validateDMPermission,
+ Assertions_validateDefaultMemberPermissions as validateDefaultMemberPermissions,
Assertions_validateDefaultPermission as validateDefaultPermission,
Assertions_validateName as validateName,
- Assertions_validateType as validateType,
Assertions_validateRequiredParameters as validateRequiredParameters,
- Assertions_validateDMPermission as validateDMPermission,
- Assertions_validateDefaultMemberPermissions as validateDefaultMemberPermissions,
+ Assertions_validateType as validateType,
};
}
+/**
+ * Calculates the length of the embed.
+ *
+ * @param data - The embed data to check
+ */
declare function embedLength(data: APIEmbed): number;
-declare const enableValidators: () => boolean;
-declare const disableValidators: () => boolean;
-declare const isValidationEnabled: () => boolean;
+/**
+ * Enables validators.
+ *
+ * @returns Whether validation is occurring.
+ */
+declare function enableValidators(): boolean;
+/**
+ * Disables validators.
+ *
+ * @returns Whether validation is occurring.
+ */
+declare function disableValidators(): boolean;
+/**
+ * Checks whether validation is occurring.
+ */
+declare function isValidationEnabled(): boolean;
/**
- * The {@link https://github.com/discordjs/discord.js/blob/main/packages/builders/#readme | @discordjs/builders} version
+ * The {@link https://github.com/discordjs/discord.js/blob/main/packages/builders#readme | @discordjs/builders} version
* that you are currently using.
+ *
+ * @privateRemarks This needs to explicitly be `string` so it is not typed as a "const string" that gets injected by esbuild.
*/
declare const version: string;
-export { ActionRowBuilder, AnyAPIActionRowComponent, AnyComponentBuilder, ApplicationCommandNumericOptionMinMaxValueMixin, ApplicationCommandOptionAllowedChannelTypes, ApplicationCommandOptionBase, ApplicationCommandOptionChannelTypesMixin, ApplicationCommandOptionWithChoicesAndAutocompleteMixin, BaseSelectMenuBuilder, ButtonBuilder, ChannelSelectMenuBuilder, Assertions$4 as ComponentAssertions, ComponentBuilder, Assertions as ContextMenuCommandAssertions, ContextMenuCommandBuilder, ContextMenuCommandType, Assertions$5 as EmbedAssertions, EmbedAuthorData, EmbedAuthorOptions, EmbedBuilder, EmbedFooterData, EmbedFooterOptions, EmbedImageData, Faces, IconData, MappedComponentTypes, MentionableSelectMenuBuilder, MessageActionRowComponentBuilder, MessageComponentBuilder, ModalActionRowComponentBuilder, Assertions$2 as ModalAssertions, ModalBuilder, ModalComponentBuilder, RGBTuple, RestOrArray, RoleSelectMenuBuilder, StringSelectMenuBuilder as SelectMenuBuilder, StringSelectMenuOptionBuilder as SelectMenuOptionBuilder, SharedNameAndDescription, SharedSlashCommandOptions, Assertions$1 as SlashCommandAssertions, SlashCommandAttachmentOption, SlashCommandBooleanOption, SlashCommandBuilder, SlashCommandChannelOption, SlashCommandIntegerOption, SlashCommandMentionableOption, SlashCommandNumberOption, SlashCommandOptionsOnlyBuilder, SlashCommandRoleOption, SlashCommandStringOption, SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder, SlashCommandSubcommandsOnlyBuilder, SlashCommandUserOption, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, Assertions$3 as TextInputAssertions, TextInputBuilder, TimestampStyles, TimestampStylesString, ToAPIApplicationCommandOptions, UserSelectMenuBuilder, blockQuote, bold, channelLink, channelMention, chatInputApplicationCommandMention, codeBlock, createComponentBuilder, disableValidators, embedLength, enableValidators, formatEmoji, hideLinkEmbed, hyperlink, inlineCode, isValidationEnabled, italic, messageLink, normalizeArray, quote, roleMention, spoiler, strikethrough, time, underscore, userMention, version };
+export { ActionRowBuilder, AnyAPIActionRowComponent, AnyComponentBuilder, ApplicationCommandNumericOptionMinMaxValueMixin, ApplicationCommandOptionAllowedChannelTypes, ApplicationCommandOptionBase, ApplicationCommandOptionChannelTypesMixin, ApplicationCommandOptionWithChoicesAndAutocompleteMixin, BaseSelectMenuBuilder, ButtonBuilder, ChannelSelectMenuBuilder, Assertions$4 as ComponentAssertions, ComponentBuilder, Assertions as ContextMenuCommandAssertions, ContextMenuCommandBuilder, ContextMenuCommandType, Assertions$5 as EmbedAssertions, EmbedAuthorData, EmbedAuthorOptions, EmbedBuilder, EmbedFooterData, EmbedFooterOptions, EmbedImageData, IconData, MappedComponentTypes, MentionableSelectMenuBuilder, MessageActionRowComponentBuilder, MessageComponentBuilder, ModalActionRowComponentBuilder, Assertions$2 as ModalAssertions, ModalBuilder, ModalComponentBuilder, RGBTuple, RestOrArray, RoleSelectMenuBuilder, StringSelectMenuBuilder as SelectMenuBuilder, StringSelectMenuOptionBuilder as SelectMenuOptionBuilder, SharedNameAndDescription, SharedSlashCommandOptions, Assertions$1 as SlashCommandAssertions, SlashCommandAttachmentOption, SlashCommandBooleanOption, SlashCommandBuilder, SlashCommandChannelOption, SlashCommandIntegerOption, SlashCommandMentionableOption, SlashCommandNumberOption, SlashCommandOptionsOnlyBuilder, SlashCommandRoleOption, SlashCommandStringOption, SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder, SlashCommandSubcommandsOnlyBuilder, SlashCommandUserOption, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, Assertions$3 as TextInputAssertions, TextInputBuilder, ToAPIApplicationCommandOptions, UserSelectMenuBuilder, createComponentBuilder, disableValidators, embedLength, enableValidators, isValidationEnabled, normalizeArray, version };
diff --git a/node_modules/@discordjs/builders/dist/index.js b/node_modules/@discordjs/builders/dist/index.js
index 8e6a442..456ed60 100644
--- a/node_modules/@discordjs/builders/dist/index.js
+++ b/node_modules/@discordjs/builders/dist/index.js
@@ -20,6 +20,10 @@ var __copyProps = (to, from, except, desc) => {
};
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
+ // If the importer is in node compatibility mode or this is not an ESM
+ // file that has been converted to a CommonJS file using a Babel-
+ // compatible transform (i.e. "__esModule" has not been set), then set
+ // "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
@@ -51,7 +55,6 @@ __export(src_exports, {
ContextMenuCommandBuilder: () => ContextMenuCommandBuilder,
EmbedAssertions: () => Assertions_exports,
EmbedBuilder: () => EmbedBuilder,
- Faces: () => Faces,
MentionableSelectMenuBuilder: () => MentionableSelectMenuBuilder,
ModalAssertions: () => Assertions_exports4,
ModalBuilder: () => ModalBuilder,
@@ -77,33 +80,13 @@ __export(src_exports, {
StringSelectMenuOptionBuilder: () => StringSelectMenuOptionBuilder,
TextInputAssertions: () => Assertions_exports3,
TextInputBuilder: () => TextInputBuilder,
- TimestampStyles: () => TimestampStyles,
UserSelectMenuBuilder: () => UserSelectMenuBuilder,
- blockQuote: () => blockQuote,
- bold: () => bold,
- channelLink: () => channelLink,
- channelMention: () => channelMention,
- chatInputApplicationCommandMention: () => chatInputApplicationCommandMention,
- codeBlock: () => codeBlock,
createComponentBuilder: () => createComponentBuilder,
disableValidators: () => disableValidators,
embedLength: () => embedLength,
enableValidators: () => enableValidators,
- formatEmoji: () => formatEmoji,
- hideLinkEmbed: () => hideLinkEmbed,
- hyperlink: () => hyperlink,
- inlineCode: () => inlineCode,
isValidationEnabled: () => isValidationEnabled,
- italic: () => italic,
- messageLink: () => messageLink,
normalizeArray: () => normalizeArray,
- quote: () => quote,
- roleMention: () => roleMention,
- spoiler: () => spoiler,
- strikethrough: () => strikethrough,
- time: () => time,
- underscore: () => underscore,
- userMention: () => userMention,
version: () => version
});
module.exports = __toCommonJS(src_exports);
@@ -134,9 +117,18 @@ var import_shapeshift = require("@sapphire/shapeshift");
// src/util/validation.ts
var validate = true;
-var enableValidators = /* @__PURE__ */ __name(() => validate = true, "enableValidators");
-var disableValidators = /* @__PURE__ */ __name(() => validate = false, "disableValidators");
-var isValidationEnabled = /* @__PURE__ */ __name(() => validate, "isValidationEnabled");
+function enableValidators() {
+ return validate = true;
+}
+__name(enableValidators, "enableValidators");
+function disableValidators() {
+ return validate = false;
+}
+__name(disableValidators, "disableValidators");
+function isValidationEnabled() {
+ return validate;
+}
+__name(isValidationEnabled, "isValidationEnabled");
// src/messages/embed/Assertions.ts
var fieldNamePredicate = import_shapeshift.s.string.lengthGreaterThanOrEqual(1).lengthLessThanOrEqual(256).setValidationEnabled(isValidationEnabled);
@@ -186,22 +178,83 @@ __name(normalizeArray, "normalizeArray");
// src/messages/embed/Embed.ts
var EmbedBuilder = class {
+ /**
+ * The API data associated with this embed.
+ */
data;
+ /**
+ * Creates a new embed from API data.
+ *
+ * @param data - The API data to create this embed with
+ */
constructor(data = {}) {
this.data = { ...data };
if (data.timestamp)
this.data.timestamp = new Date(data.timestamp).toISOString();
}
+ /**
+ * Appends fields to the embed.
+ *
+ * @remarks
+ * This method accepts either an array of fields or a variable number of field parameters.
+ * The maximum amount of fields that can be added is 25.
+ * @example
+ * Using an array:
+ * ```ts
+ * const fields: APIEmbedField[] = ...;
+ * const embed = new EmbedBuilder()
+ * .addFields(fields);
+ * ```
+ * @example
+ * Using rest parameters (variadic):
+ * ```ts
+ * const embed = new EmbedBuilder()
+ * .addFields(
+ * { name: 'Field 1', value: 'Value 1' },
+ * { name: 'Field 2', value: 'Value 2' },
+ * );
+ * ```
+ * @param fields - The fields to add
+ */
addFields(...fields) {
- fields = normalizeArray(fields);
- validateFieldLength(fields.length, this.data.fields);
- embedFieldsArrayPredicate.parse(fields);
+ const normalizedFields = normalizeArray(fields);
+ validateFieldLength(normalizedFields.length, this.data.fields);
+ embedFieldsArrayPredicate.parse(normalizedFields);
if (this.data.fields)
- this.data.fields.push(...fields);
+ this.data.fields.push(...normalizedFields);
else
- this.data.fields = fields;
- return this;
- }
+ this.data.fields = normalizedFields;
+ return this;
+ }
+ /**
+ * Removes, replaces, or inserts fields for this embed.
+ *
+ * @remarks
+ * This method behaves similarly
+ * to {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice | Array.prototype.splice()}.
+ * The maximum amount of fields that can be added is 25.
+ *
+ * It's useful for modifying and adjusting order of the already-existing fields of an embed.
+ * @example
+ * Remove the first field:
+ * ```ts
+ * embed.spliceFields(0, 1);
+ * ```
+ * @example
+ * Remove the first n fields:
+ * ```ts
+ * const n = 4;
+ * embed.spliceFields(0, n);
+ * ```
+ * @example
+ * Remove the last field:
+ * ```ts
+ * embed.spliceFields(-1, 1);
+ * ```
+ * @param index - The index to start at
+ * @param deleteCount - The number of fields to remove
+ * @param fields - The replacing field objects
+ */
spliceFields(index, deleteCount, ...fields) {
validateFieldLength(fields.length - deleteCount, this.data.fields);
embedFieldsArrayPredicate.parse(fields);
@@ -211,10 +264,25 @@ var EmbedBuilder = class {
this.data.fields = fields;
return this;
}
+ /**
+ * Sets the fields for this embed.
+ *
+ * @remarks
+ * This method is an alias for {@link EmbedBuilder.spliceFields}. More specifically,
+ * it splices the entire array of fields, replacing them with the provided fields.
+ *
+ * You can set a maximum of 25 fields.
+ * @param fields - The fields to set
+ */
setFields(...fields) {
this.spliceFields(0, this.data.fields?.length ?? 0, ...normalizeArray(fields));
return this;
}
+ /**
+ * Sets the author of this embed.
+ *
+ * @param options - The options to use
+ */
setAuthor(options) {
if (options === null) {
this.data.author = void 0;
@@ -224,6 +292,11 @@ var EmbedBuilder = class {
this.data.author = { name: options.name, url: options.url, icon_url: options.iconURL };
return this;
}
+ /**
+ * Sets the color of this embed.
+ *
+ * @param color - The color to use
+ */
setColor(color) {
colorPredicate.parse(color);
if (Array.isArray(color)) {
@@ -234,11 +307,21 @@ var EmbedBuilder = class {
this.data.color = color ?? void 0;
return this;
}
+ /**
+ * Sets the description of this embed.
+ *
+ * @param description - The description to use
+ */
setDescription(description) {
descriptionPredicate.parse(description);
this.data.description = description ?? void 0;
return this;
}
+ /**
+ * Sets the footer of this embed.
+ *
+ * @param options - The footer to use
+ */
setFooter(options) {
if (options === null) {
this.data.footer = void 0;
@@ -248,142 +331,71 @@ var EmbedBuilder = class {
this.data.footer = { text: options.text, icon_url: options.iconURL };
return this;
}
+ /**
+ * Sets the image of this embed.
+ *
+ * @param url - The image URL to use
+ */
setImage(url) {
imageURLPredicate.parse(url);
this.data.image = url ? { url } : void 0;
return this;
}
+ /**
+ * Sets the thumbnail of this embed.
+ *
+ * @param url - The thumbnail URL to use
+ */
setThumbnail(url) {
imageURLPredicate.parse(url);
this.data.thumbnail = url ? { url } : void 0;
return this;
}
+ /**
+ * Sets the timestamp of this embed.
+ *
+ * @param timestamp - The timestamp or date to use
+ */
setTimestamp(timestamp = Date.now()) {
timestampPredicate.parse(timestamp);
this.data.timestamp = timestamp ? new Date(timestamp).toISOString() : void 0;
return this;
}
+ /**
+ * Sets the title for this embed.
+ *
+ * @param title - The title to use
+ */
setTitle(title) {
titlePredicate.parse(title);
this.data.title = title ?? void 0;
return this;
}
+ /**
+ * Sets the URL of this embed.
+ *
+ * @param url - The URL to use
+ */
setURL(url) {
urlPredicate.parse(url);
this.data.url = url ?? void 0;
return this;
}
+ /**
+ * Serializes this builder to API-compatible JSON data.
+ *
+ * @remarks
+ * This method runs validations on the data before serializing it.
+ * As such, it may throw an error if the data is invalid.
+ */
toJSON() {
return { ...this.data };
}
};
__name(EmbedBuilder, "EmbedBuilder");
-// src/messages/formatters.ts
-function codeBlock(language, content) {
- return typeof content === "undefined" ? `\`\`\`
-${language}
-\`\`\`` : `\`\`\`${language}
-${content}
-\`\`\``;
-}
-__name(codeBlock, "codeBlock");
-function inlineCode(content) {
- return `\`${content}\``;
-}
-__name(inlineCode, "inlineCode");
-function italic(content) {
- return `_${content}_`;
-}
-__name(italic, "italic");
-function bold(content) {
- return `**${content}**`;
-}
-__name(bold, "bold");
-function underscore(content) {
- return `__${content}__`;
-}
-__name(underscore, "underscore");
-function strikethrough(content) {
- return `~~${content}~~`;
-}
-__name(strikethrough, "strikethrough");
-function quote(content) {
- return `> ${content}`;
-}
-__name(quote, "quote");
-function blockQuote(content) {
- return `>>> ${content}`;
-}
-__name(blockQuote, "blockQuote");
-function hideLinkEmbed(url) {
- return `<${url}>`;
-}
-__name(hideLinkEmbed, "hideLinkEmbed");
-function hyperlink(content, url, title) {
- return title ? `[${content}](${url} "${title}")` : `[${content}](${url})`;
-}
-__name(hyperlink, "hyperlink");
-function spoiler(content) {
- return `||${content}||`;
-}
-__name(spoiler, "spoiler");
-function userMention(userId) {
- return `<@${userId}>`;
-}
-__name(userMention, "userMention");
-function channelMention(channelId) {
- return `<#${channelId}>`;
-}
-__name(channelMention, "channelMention");
-function roleMention(roleId) {
- return `<@&${roleId}>`;
-}
-__name(roleMention, "roleMention");
-function chatInputApplicationCommandMention(commandName, subcommandGroupName, subcommandName, commandId) {
- if (typeof commandId !== "undefined") {
- return `${commandName} ${subcommandGroupName} ${subcommandName}:${commandId}>`;
- }
- if (typeof subcommandName !== "undefined") {
- return `${commandName} ${subcommandGroupName}:${subcommandName}>`;
- }
- return `${commandName}:${subcommandGroupName}>`;
-}
-__name(chatInputApplicationCommandMention, "chatInputApplicationCommandMention");
-function formatEmoji(emojiId, animated = false) {
- return `<${animated ? "a" : ""}:_:${emojiId}>`;
-}
-__name(formatEmoji, "formatEmoji");
-function channelLink(channelId, guildId) {
- return `https://discord.com/channels/${guildId ?? "@me"}/${channelId}`;
-}
-__name(channelLink, "channelLink");
-function messageLink(channelId, messageId, guildId) {
- return `${typeof guildId === "undefined" ? channelLink(channelId) : channelLink(channelId, guildId)}/${messageId}`;
-}
-__name(messageLink, "messageLink");
-function time(timeOrSeconds, style) {
- if (typeof timeOrSeconds !== "number") {
- timeOrSeconds = Math.floor((timeOrSeconds?.getTime() ?? Date.now()) / 1e3);
- }
- return typeof style === "string" ? `` : ``;
-}
-__name(time, "time");
-var TimestampStyles = {
- ShortTime: "t",
- LongTime: "T",
- ShortDate: "d",
- LongDate: "D",
- ShortDateTime: "f",
- LongDateTime: "F",
- RelativeTime: "R"
-};
-var Faces = /* @__PURE__ */ ((Faces2) => {
- Faces2["Shrug"] = "\xAF\\_(\u30C4)\\_/\xAF";
- Faces2["Tableflip"] = "(\u256F\xB0\u25A1\xB0\uFF09\u256F\uFE35 \u253B\u2501\u253B";
- Faces2["Unflip"] = "\u252C\u2500\u252C \u30CE( \u309C-\u309C\u30CE)";
- return Faces2;
-})(Faces || {});
+// src/index.ts
+__reExport(src_exports, require("@discordjs/formatters"), module.exports);
// src/components/Assertions.ts
var Assertions_exports2 = {};
@@ -412,29 +424,79 @@ var import_v10 = require("discord-api-types/v10");
// src/components/selectMenu/StringSelectMenuOption.ts
var StringSelectMenuOptionBuilder = class {
+ /**
+ * Creates a new string select menu option from API data.
+ *
+ * @param data - The API data to create this string select menu option with
+ * @example
+ * Creating a string select menu option from an API data object:
+ * ```ts
+ * const selectMenuOption = new SelectMenuOptionBuilder({
+ * label: 'catchy label',
+ * value: '1',
+ * });
+ * ```
+ * @example
+ * Creating a string select menu option using setters and API data:
+ * ```ts
+ * const selectMenuOption = new SelectMenuOptionBuilder({
+ * default: true,
+ * value: '1',
+ * })
+ * .setLabel('woah');
+ * ```
+ */
constructor(data = {}) {
this.data = data;
}
+ /**
+ * Sets the label for this option.
+ *
+ * @param label - The label to use
+ */
setLabel(label) {
this.data.label = labelValueDescriptionValidator.parse(label);
return this;
}
+ /**
+ * Sets the value for this option.
+ *
+ * @param value - The value to use
+ */
setValue(value) {
this.data.value = labelValueDescriptionValidator.parse(value);
return this;
}
+ /**
+ * Sets the description for this option.
+ *
+ * @param description - The description to use
+ */
setDescription(description) {
this.data.description = labelValueDescriptionValidator.parse(description);
return this;
}
+ /**
+ * Sets whether this option is selected by default.
+ *
+ * @param isDefault - Whether this option is selected by default
+ */
setDefault(isDefault = true) {
this.data.default = defaultValidator.parse(isDefault);
return this;
}
+ /**
+ * Sets the emoji to display for this option.
+ *
+ * @param emoji - The emoji to use
+ */
setEmoji(emoji) {
this.data.emoji = emojiValidator.parse(emoji);
return this;
}
+ /**
+ * {@inheritDoc BaseSelectMenuBuilder.toJSON}
+ */
toJSON() {
validateRequiredSelectMenuOptionParameters(this.data.label, this.data.value);
return {
@@ -504,7 +566,15 @@ var import_v1011 = require("discord-api-types/v10");
// src/components/Component.ts
var ComponentBuilder = class {
+ /**
+ * The API data associated with this component.
+ */
data;
+ /**
+ * Constructs a new kind of component.
+ *
+ * @param data - The data to construct a component out of
+ */
constructor(data) {
this.data = data;
}
@@ -517,33 +587,99 @@ var import_v1010 = require("discord-api-types/v10");
// src/components/button/Button.ts
var import_v102 = require("discord-api-types/v10");
var ButtonBuilder = class extends ComponentBuilder {
+ /**
+ * Creates a new button from API data.
+ *
+ * @param data - The API data to create this button with
+ * @example
+ * Creating a button from an API data object:
+ * ```ts
+ * const button = new ButtonBuilder({
+ * custom_id: 'a cool button',
+ * style: ButtonStyle.Primary,
+ * label: 'Click Me',
+ * emoji: {
+ * name: 'smile',
+ * id: '123456789012345678',
+ * },
+ * });
+ * ```
+ * @example
+ * Creating a button using setters and API data:
+ * ```ts
+ * const button = new ButtonBuilder({
+ * style: ButtonStyle.Secondary,
+ * label: 'Click Me',
+ * })
+ * .setEmoji({ name: 'π' })
+ * .setCustomId('another cool button');
+ * ```
+ */
constructor(data) {
super({ type: import_v102.ComponentType.Button, ...data });
}
+ /**
+ * Sets the style of this button.
+ *
+ * @param style - The style to use
+ */
setStyle(style) {
this.data.style = buttonStyleValidator.parse(style);
return this;
}
+ /**
+ * Sets the URL for this button.
+ *
+ * @remarks
+ * This method is only available to buttons using the `Link` button style.
+ * Only three types of URL schemes are currently supported: `https://`, `http://`, and `discord://`.
+ * @param url - The URL to use
+ */
setURL(url) {
this.data.url = urlValidator.parse(url);
return this;
}
+ /**
+ * Sets the custom id for this button.
+ *
+ * @remarks
+ * This method is only applicable to buttons that are not using the `Link` button style.
+ * @param customId - The custom id to use
+ */
setCustomId(customId) {
this.data.custom_id = customIdValidator.parse(customId);
return this;
}
+ /**
+ * Sets the emoji to display on this button.
+ *
+ * @param emoji - The emoji to use
+ */
setEmoji(emoji) {
this.data.emoji = emojiValidator.parse(emoji);
return this;
}
+ /**
+ * Sets whether this button is disabled.
+ *
+ * @param disabled - Whether to disable this button
+ */
setDisabled(disabled = true) {
this.data.disabled = disabledValidator.parse(disabled);
return this;
}
+ /**
+ * Sets the label for this button.
+ *
+ * @param label - The label to use
+ */
setLabel(label) {
this.data.label = buttonLabelValidator.parse(label);
return this;
}
+ /**
+ * {@inheritDoc ComponentBuilder.toJSON}
+ */
toJSON() {
validateRequiredButtonParameters(
this.data.style,
@@ -564,26 +700,54 @@ var import_v103 = require("discord-api-types/v10");
// src/components/selectMenu/BaseSelectMenu.ts
var BaseSelectMenuBuilder = class extends ComponentBuilder {
+ /**
+ * Sets the placeholder for this select menu.
+ *
+ * @param placeholder - The placeholder to use
+ */
setPlaceholder(placeholder) {
this.data.placeholder = placeholderValidator.parse(placeholder);
return this;
}
+ /**
+ * Sets the minimum values that must be selected in the select menu.
+ *
+ * @param minValues - The minimum values that must be selected
+ */
setMinValues(minValues) {
this.data.min_values = minMaxValidator.parse(minValues);
return this;
}
+ /**
+ * Sets the maximum values that must be selected in the select menu.
+ *
+ * @param maxValues - The maximum values that must be selected
+ */
setMaxValues(maxValues) {
this.data.max_values = minMaxValidator.parse(maxValues);
return this;
}
+ /**
+ * Sets the custom id for this select menu.
+ *
+ * @param customId - The custom id to use
+ */
setCustomId(customId) {
this.data.custom_id = customIdValidator.parse(customId);
return this;
}
+ /**
+ * Sets whether this select menu is disabled.
+ *
+ * @param disabled - Whether this select menu is disabled
+ */
setDisabled(disabled = true) {
this.data.disabled = disabledValidator.parse(disabled);
return this;
}
+ /**
+ * {@inheritDoc ComponentBuilder.toJSON}
+ */
toJSON() {
customIdValidator.parse(this.data.custom_id);
return {
@@ -595,21 +759,57 @@ __name(BaseSelectMenuBuilder, "BaseSelectMenuBuilder");
// src/components/selectMenu/ChannelSelectMenu.ts
var ChannelSelectMenuBuilder = class extends BaseSelectMenuBuilder {
+ /**
+ * Creates a new select menu from API data.
+ *
+ * @param data - The API data to create this select menu with
+ * @example
+ * Creating a select menu from an API data object:
+ * ```ts
+ * const selectMenu = new ChannelSelectMenuBuilder({
+ * custom_id: 'a cool select menu',
+ * placeholder: 'select an option',
+ * max_values: 2,
+ * });
+ * ```
+ * @example
+ * Creating a select menu using setters and API data:
+ * ```ts
+ * const selectMenu = new ChannelSelectMenuBuilder({
+ * custom_id: 'a cool select menu',
+ * })
+ * .addChannelTypes(ChannelType.GuildText, ChannelType.GuildAnnouncement)
+ * .setMinValues(2);
+ * ```
+ */
constructor(data) {
super({ ...data, type: import_v103.ComponentType.ChannelSelect });
}
+ /**
+ * Adds channel types to this select menu.
+ *
+ * @param types - The channel types to use
+ */
addChannelTypes(...types) {
- types = normalizeArray(types);
+ const normalizedTypes = normalizeArray(types);
this.data.channel_types ??= [];
- this.data.channel_types.push(...channelTypesValidator.parse(types));
+ this.data.channel_types.push(...channelTypesValidator.parse(normalizedTypes));
return this;
}
+ /**
+ * Sets channel types for this select menu.
+ *
+ * @param types - The channel types to use
+ */
setChannelTypes(...types) {
- types = normalizeArray(types);
+ const normalizedTypes = normalizeArray(types);
this.data.channel_types ??= [];
- this.data.channel_types.splice(0, this.data.channel_types.length, ...channelTypesValidator.parse(types));
+ this.data.channel_types.splice(0, this.data.channel_types.length, ...channelTypesValidator.parse(normalizedTypes));
return this;
}
+ /**
+ * {@inheritDoc BaseSelectMenuBuilder.toJSON}
+ */
toJSON() {
customIdValidator.parse(this.data.custom_id);
return {
@@ -622,6 +822,28 @@ __name(ChannelSelectMenuBuilder, "ChannelSelectMenuBuilder");
// src/components/selectMenu/MentionableSelectMenu.ts
var import_v104 = require("discord-api-types/v10");
var MentionableSelectMenuBuilder = class extends BaseSelectMenuBuilder {
+ /**
+ * Creates a new select menu from API data.
+ *
+ * @param data - The API data to create this select menu with
+ * @example
+ * Creating a select menu from an API data object:
+ * ```ts
+ * const selectMenu = new MentionableSelectMenuBuilder({
+ * custom_id: 'a cool select menu',
+ * placeholder: 'select an option',
+ * max_values: 2,
+ * });
+ * ```
+ * @example
+ * Creating a select menu using setters and API data:
+ * ```ts
+ * const selectMenu = new MentionableSelectMenuBuilder({
+ * custom_id: 'a cool select menu',
+ * })
+ * .setMinValues(1);
+ * ```
+ */
constructor(data) {
super({ ...data, type: import_v104.ComponentType.MentionableSelect });
}
@@ -631,6 +853,28 @@ __name(MentionableSelectMenuBuilder, "MentionableSelectMenuBuilder");
// src/components/selectMenu/RoleSelectMenu.ts
var import_v105 = require("discord-api-types/v10");
var RoleSelectMenuBuilder = class extends BaseSelectMenuBuilder {
+ /**
+ * Creates a new select menu from API data.
+ *
+ * @param data - The API data to create this select menu with
+ * @example
+ * Creating a select menu from an API data object:
+ * ```ts
+ * const selectMenu = new RoleSelectMenuBuilder({
+ * custom_id: 'a cool select menu',
+ * placeholder: 'select an option',
+ * max_values: 2,
+ * });
+ * ```
+ * @example
+ * Creating a select menu using setters and API data:
+ * ```ts
+ * const selectMenu = new RoleSelectMenuBuilder({
+ * custom_id: 'a cool select menu',
+ * })
+ * .setMinValues(1);
+ * ```
+ */
constructor(data) {
super({ ...data, type: import_v105.ComponentType.RoleSelect });
}
@@ -640,34 +884,113 @@ __name(RoleSelectMenuBuilder, "RoleSelectMenuBuilder");
// src/components/selectMenu/StringSelectMenu.ts
var import_v106 = require("discord-api-types/v10");
var StringSelectMenuBuilder = class extends BaseSelectMenuBuilder {
+ /**
+ * The options within this select menu.
+ */
options;
+ /**
+ * Creates a new select menu from API data.
+ *
+ * @param data - The API data to create this select menu with
+ * @example
+ * Creating a select menu from an API data object:
+ * ```ts
+ * const selectMenu = new StringSelectMenuBuilder({
+ * custom_id: 'a cool select menu',
+ * placeholder: 'select an option',
+ * max_values: 2,
+ * options: [
+ * { label: 'option 1', value: '1' },
+ * { label: 'option 2', value: '2' },
+ * { label: 'option 3', value: '3' },
+ * ],
+ * });
+ * ```
+ * @example
+ * Creating a select menu using setters and API data:
+ * ```ts
+ * const selectMenu = new StringSelectMenuBuilder({
+ * custom_id: 'a cool select menu',
+ * })
+ * .setMinValues(1)
+ * .addOptions({
+ * label: 'Catchy',
+ * value: 'catch',
+ * });
+ * ```
+ */
constructor(data) {
const { options, ...initData } = data ?? {};
super({ ...initData, type: import_v106.ComponentType.StringSelect });
this.options = options?.map((option) => new StringSelectMenuOptionBuilder(option)) ?? [];
}
+ /**
+ * Adds options to this select menu.
+ *
+ * @param options - The options to add
+ */
addOptions(...options) {
- options = normalizeArray(options);
- optionsLengthValidator.parse(this.options.length + options.length);
+ const normalizedOptions = normalizeArray(options);
+ optionsLengthValidator.parse(this.options.length + normalizedOptions.length);
this.options.push(
- ...options.map(
- (option) => option instanceof StringSelectMenuOptionBuilder ? option : new StringSelectMenuOptionBuilder(jsonOptionValidator.parse(option))
+ ...normalizedOptions.map(
+ (normalizedOption) => normalizedOption instanceof StringSelectMenuOptionBuilder ? normalizedOption : new StringSelectMenuOptionBuilder(jsonOptionValidator.parse(normalizedOption))
)
);
return this;
}
+ /**
+ * Sets the options for this select menu.
+ *
+ * @param options - The options to set
+ */
setOptions(...options) {
- options = normalizeArray(options);
- optionsLengthValidator.parse(options.length);
- this.options.splice(
- 0,
- this.options.length,
- ...options.map(
- (option) => option instanceof StringSelectMenuOptionBuilder ? option : new StringSelectMenuOptionBuilder(jsonOptionValidator.parse(option))
+ return this.spliceOptions(0, this.options.length, ...options);
+ }
+ /**
+ * Removes, replaces, or inserts options for this select menu.
+ *
+ * @remarks
+ * This method behaves similarly
+ * to {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice | Array.prototype.splice()}.
+ * It's useful for modifying and adjusting the order of existing options.
+ * @example
+ * Remove the first option:
+ * ```ts
+ * selectMenu.spliceOptions(0, 1);
+ * ```
+ * @example
+ * Remove the first n option:
+ * ```ts
+ * const n = 4;
+ * selectMenu.spliceOptions(0, n);
+ * ```
+ * @example
+ * Remove the last option:
+ * ```ts
+ * selectMenu.spliceOptions(-1, 1);
+ * ```
+ * @param index - The index to start at
+ * @param deleteCount - The number of options to remove
+ * @param options - The replacing option objects or builders
+ */
+ spliceOptions(index, deleteCount, ...options) {
+ const normalizedOptions = normalizeArray(options);
+ const clone = [...this.options];
+ clone.splice(
+ index,
+ deleteCount,
+ ...normalizedOptions.map(
+ (normalizedOption) => normalizedOption instanceof StringSelectMenuOptionBuilder ? normalizedOption : new StringSelectMenuOptionBuilder(jsonOptionValidator.parse(normalizedOption))
)
);
+ optionsLengthValidator.parse(clone.length);
+ this.options.splice(0, this.options.length, ...clone);
return this;
}
+ /**
+ * {@inheritDoc BaseSelectMenuBuilder.toJSON}
+ */
toJSON() {
validateRequiredSelectMenuParameters(this.options, this.data.custom_id);
return {
@@ -681,6 +1004,28 @@ __name(StringSelectMenuBuilder, "StringSelectMenuBuilder");
// src/components/selectMenu/UserSelectMenu.ts
var import_v107 = require("discord-api-types/v10");
var UserSelectMenuBuilder = class extends BaseSelectMenuBuilder {
+ /**
+ * Creates a new select menu from API data.
+ *
+ * @param data - The API data to create this select menu with
+ * @example
+ * Creating a select menu from an API data object:
+ * ```ts
+ * const selectMenu = new UserSelectMenuBuilder({
+ * custom_id: 'a cool select menu',
+ * placeholder: 'select an option',
+ * max_values: 2,
+ * });
+ * ```
+ * @example
+ * Creating a select menu using setters and API data:
+ * ```ts
+ * const selectMenu = new UserSelectMenuBuilder({
+ * custom_id: 'a cool select menu',
+ * })
+ * .setMinValues(1);
+ * ```
+ */
constructor(data) {
super({ ...data, type: import_v107.ComponentType.UserSelect });
}
@@ -722,47 +1067,116 @@ __name(validateRequiredParameters, "validateRequiredParameters");
// src/components/textInput/TextInput.ts
var TextInputBuilder = class extends ComponentBuilder {
+ /**
+ * Creates a new text input from API data.
+ *
+ * @param data - The API data to create this text input with
+ * @example
+ * Creating a select menu option from an API data object:
+ * ```ts
+ * const textInput = new TextInputBuilder({
+ * custom_id: 'a cool select menu',
+ * label: 'Type something',
+ * style: TextInputStyle.Short,
+ * });
+ * ```
+ * @example
+ * Creating a select menu option using setters and API data:
+ * ```ts
+ * const textInput = new TextInputBuilder({
+ * label: 'Type something else',
+ * })
+ * .setCustomId('woah')
+ * .setStyle(TextInputStyle.Paragraph);
+ * ```
+ */
constructor(data) {
super({ type: import_v109.ComponentType.TextInput, ...data });
}
+ /**
+ * Sets the custom id for this text input.
+ *
+ * @param customId - The custom id to use
+ */
setCustomId(customId) {
this.data.custom_id = customIdValidator.parse(customId);
return this;
}
+ /**
+ * Sets the label for this text input.
+ *
+ * @param label - The label to use
+ */
setLabel(label) {
this.data.label = labelValidator.parse(label);
return this;
}
+ /**
+ * Sets the style for this text input.
+ *
+ * @param style - The style to use
+ */
setStyle(style) {
this.data.style = textInputStyleValidator.parse(style);
return this;
}
+ /**
+ * Sets the minimum length of text for this text input.
+ *
+ * @param minLength - The minimum length of text for this text input
+ */
setMinLength(minLength) {
this.data.min_length = minLengthValidator.parse(minLength);
return this;
}
+ /**
+ * Sets the maximum length of text for this text input.
+ *
+ * @param maxLength - The maximum length of text for this text input
+ */
setMaxLength(maxLength) {
this.data.max_length = maxLengthValidator.parse(maxLength);
return this;
}
+ /**
+ * Sets the placeholder for this text input.
+ *
+ * @param placeholder - The placeholder to use
+ */
setPlaceholder(placeholder) {
this.data.placeholder = placeholderValidator2.parse(placeholder);
return this;
}
+ /**
+ * Sets the value for this text input.
+ *
+ * @param value - The value to use
+ */
setValue(value) {
this.data.value = valueValidator.parse(value);
return this;
}
+ /**
+ * Sets whether this text input is required.
+ *
+ * @param required - Whether this text input is required
+ */
setRequired(required = true) {
this.data.required = requiredValidator.parse(required);
return this;
}
+ /**
+ * {@inheritDoc ComponentBuilder.toJSON}
+ */
toJSON() {
validateRequiredParameters(this.data.custom_id, this.data.style, this.data.label);
return {
...this.data
};
}
+ /**
+ * {@inheritDoc Equatable.equals}
+ */
equals(other) {
if ((0, import_util.isJSONEncodable)(other)) {
return (0, import_fast_deep_equal.default)(other.toJSON(), this.data);
@@ -802,19 +1216,69 @@ __name(createComponentBuilder, "createComponentBuilder");
// src/components/ActionRow.ts
var ActionRowBuilder = class extends ComponentBuilder {
+ /**
+ * The components within this action row.
+ */
components;
+ /**
+ * Creates a new action row from API data.
+ *
+ * @param data - The API data to create this action row with
+ * @example
+ * Creating an action row from an API data object:
+ * ```ts
+ * const actionRow = new ActionRowBuilder({
+ * components: [
+ * {
+ * custom_id: "custom id",
+ * label: "Type something",
+ * style: TextInputStyle.Short,
+ * type: ComponentType.TextInput,
+ * },
+ * ],
+ * });
+ * ```
+ * @example
+ * Creating an action row using setters and API data:
+ * ```ts
+ * const actionRow = new ActionRowBuilder({
+ * components: [
+ * {
+ * custom_id: "custom id",
+ * label: "Click me",
+ * style: ButtonStyle.Primary,
+ * type: ComponentType.Button,
+ * },
+ * ],
+ * })
+ * .addComponents(button2, button3);
+ * ```
+ */
constructor({ components, ...data } = {}) {
super({ type: import_v1011.ComponentType.ActionRow, ...data });
this.components = components?.map((component) => createComponentBuilder(component)) ?? [];
}
+ /**
+ * Adds components to this action row.
+ *
+ * @param components - The components to add
+ */
addComponents(...components) {
this.components.push(...normalizeArray(components));
return this;
}
+ /**
+ * Sets components for this action row.
+ *
+ * @param components - The components to set
+ */
setComponents(...components) {
this.components.splice(0, this.components.length, ...normalizeArray(components));
return this;
}
+ /**
+ * {@inheritDoc ComponentBuilder.toJSON}
+ */
toJSON() {
return {
...this.data,
@@ -843,20 +1307,46 @@ __name(validateRequiredParameters2, "validateRequiredParameters");
// src/interactions/modals/Modal.ts
var ModalBuilder = class {
+ /**
+ * The API data associated with this modal.
+ */
data;
+ /**
+ * The components within this modal.
+ */
components = [];
+ /**
+ * Creates a new modal from API data.
+ *
+ * @param data - The API data to create this modal with
+ */
constructor({ components, ...data } = {}) {
this.data = { ...data };
this.components = components?.map((component) => createComponentBuilder(component)) ?? [];
}
+ /**
+ * Sets the title of this modal.
+ *
+ * @param title - The title to use
+ */
setTitle(title) {
this.data.title = titleValidator.parse(title);
return this;
}
+ /**
+ * Sets the custom id of this modal.
+ *
+ * @param customId - The custom id to use
+ */
setCustomId(customId) {
this.data.custom_id = customIdValidator.parse(customId);
return this;
}
+ /**
+ * Adds components to this modal.
+ *
+ * @param components - The components to add
+ */
addComponents(...components) {
this.components.push(
...normalizeArray(components).map(
@@ -865,10 +1355,18 @@ var ModalBuilder = class {
);
return this;
}
+ /**
+ * Sets components for this modal.
+ *
+ * @param components - The components to set
+ */
setComponents(...components) {
this.components.splice(0, this.components.length, ...normalizeArray(components));
return this;
}
+ /**
+ * {@inheritDoc ComponentBuilder.toJSON}
+ */
toJSON() {
validateRequiredParameters2(this.data.custom_id, this.data.title, this.components);
return {
@@ -892,6 +1390,7 @@ __export(Assertions_exports5, {
validateLocale: () => validateLocale,
validateLocalizationMap: () => validateLocalizationMap,
validateMaxOptionsLength: () => validateMaxOptionsLength,
+ validateNSFW: () => validateNSFW,
validateName: () => validateName,
validateRequired: () => validateRequired,
validateRequiredParameters: () => validateRequiredParameters3
@@ -961,6 +1460,10 @@ function validateDefaultMemberPermissions(permissions) {
return memberPermissionPredicate.parse(permissions);
}
__name(validateDefaultMemberPermissions, "validateDefaultMemberPermissions");
+function validateNSFW(value) {
+ booleanPredicate.parse(value);
+}
+__name(validateNSFW, "validateNSFW");
// src/interactions/slashCommands/SlashCommandBuilder.ts
var import_ts_mixer6 = require("ts-mixer");
@@ -971,20 +1474,48 @@ var import_ts_mixer5 = require("ts-mixer");
// src/interactions/slashCommands/mixins/NameAndDescription.ts
var SharedNameAndDescription = class {
+ /**
+ * The name of this command.
+ */
name;
+ /**
+ * The name localizations of this command.
+ */
name_localizations;
+ /**
+ * The description of this command.
+ */
description;
+ /**
+ * The description localizations of this command.
+ */
description_localizations;
+ /**
+ * Sets the name of this command.
+ *
+ * @param name - The name to use
+ */
setName(name) {
validateName(name);
Reflect.set(this, "name", name);
return this;
}
+ /**
+ * Sets the description of this command.
+ *
+ * @param description - The description to use
+ */
setDescription(description) {
validateDescription(description);
Reflect.set(this, "description", description);
return this;
}
+ /**
+ * SSets a name localization for this command.
+ *
+ * @param locale - The locale to set
+ * @param localizedName - The localized name for the given `locale`
+ */
setNameLocalization(locale, localizedName) {
if (!this.name_localizations) {
Reflect.set(this, "name_localizations", {});
@@ -998,6 +1529,11 @@ var SharedNameAndDescription = class {
this.name_localizations[parsedLocale] = localizedName;
return this;
}
+ /**
+ * Sets the name localizations for this command.
+ *
+ * @param localizedNames - The object of localized names to set
+ */
setNameLocalizations(localizedNames) {
if (localizedNames === null) {
Reflect.set(this, "name_localizations", null);
@@ -1009,6 +1545,12 @@ var SharedNameAndDescription = class {
}
return this;
}
+ /**
+ * Sets a description localization for this command.
+ *
+ * @param locale - The locale to set
+ * @param localizedDescription - The localized description for the given locale
+ */
setDescriptionLocalization(locale, localizedDescription) {
if (!this.description_localizations) {
Reflect.set(this, "description_localizations", {});
@@ -1022,6 +1564,11 @@ var SharedNameAndDescription = class {
this.description_localizations[parsedLocale] = localizedDescription;
return this;
}
+ /**
+ * Sets the description localizations for this command.
+ *
+ * @param localizedDescriptions - The object of localized descriptions to set
+ */
setDescriptionLocalizations(localizedDescriptions) {
if (localizedDescriptions === null) {
Reflect.set(this, "description_localizations", null);
@@ -1041,12 +1588,25 @@ var import_v1013 = require("discord-api-types/v10");
// src/interactions/slashCommands/mixins/ApplicationCommandOptionBase.ts
var ApplicationCommandOptionBase = class extends SharedNameAndDescription {
+ /**
+ * Whether this option is required.
+ *
+ * @defaultValue `false`
+ */
required = false;
+ /**
+ * Sets whether this option is required.
+ *
+ * @param required - Whether this option should be required
+ */
setRequired(required) {
validateRequired(required);
Reflect.set(this, "required", required);
return this;
}
+ /**
+ * This method runs required validators on this builder.
+ */
runRequiredValidations() {
validateRequiredParameters3(this.name, this.description, []);
validateLocalizationMap(this.name_localizations);
@@ -1058,7 +1618,13 @@ __name(ApplicationCommandOptionBase, "ApplicationCommandOptionBase");
// src/interactions/slashCommands/options/attachment.ts
var SlashCommandAttachmentOption = class extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
type = import_v1013.ApplicationCommandOptionType.Attachment;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON() {
this.runRequiredValidations();
return { ...this };
@@ -1069,7 +1635,13 @@ __name(SlashCommandAttachmentOption, "SlashCommandAttachmentOption");
// src/interactions/slashCommands/options/boolean.ts
var import_v1014 = require("discord-api-types/v10");
var SlashCommandBooleanOption = class extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
type = import_v1014.ApplicationCommandOptionType.Boolean;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON() {
this.runRequiredValidations();
return { ...this };
@@ -1097,7 +1669,15 @@ var allowedChannelTypes = [
];
var channelTypesPredicate = import_shapeshift6.s.array(import_shapeshift6.s.union(...allowedChannelTypes.map((type) => import_shapeshift6.s.literal(type))));
var ApplicationCommandOptionChannelTypesMixin = class {
+ /**
+ * The channel types of this option.
+ */
channel_types;
+ /**
+ * Adds channel types to this option.
+ *
+ * @param channelTypes - The channel types
+ */
addChannelTypes(...channelTypes) {
if (this.channel_types === void 0) {
Reflect.set(this, "channel_types", []);
@@ -1110,7 +1690,13 @@ __name(ApplicationCommandOptionChannelTypesMixin, "ApplicationCommandOptionChann
// src/interactions/slashCommands/options/channel.ts
var SlashCommandChannelOption = class extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
type = import_v1016.ApplicationCommandOptionType.Channel;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON() {
this.runRequiredValidations();
return { ...this };
@@ -1128,7 +1714,13 @@ var import_ts_mixer2 = require("ts-mixer");
// src/interactions/slashCommands/mixins/ApplicationCommandNumericOptionMinMaxValueMixin.ts
var ApplicationCommandNumericOptionMinMaxValueMixin = class {
+ /**
+ * The maximum value of this option.
+ */
max_value;
+ /**
+ * The minimum value of this option.
+ */
min_value;
};
__name(ApplicationCommandNumericOptionMinMaxValueMixin, "ApplicationCommandNumericOptionMinMaxValueMixin");
@@ -1145,9 +1737,25 @@ var choicesPredicate = import_shapeshift7.s.object({
}).array;
var booleanPredicate2 = import_shapeshift7.s.boolean;
var ApplicationCommandOptionWithChoicesAndAutocompleteMixin = class {
+ /**
+ * The choices of this option.
+ */
choices;
+ /**
+ * Whether this option utilizes autocomplete.
+ */
autocomplete;
+ /**
+ * The type of this option.
+ *
+ * @privateRemarks Since this is present and this is a mixin, this is needed.
+ */
type;
+ /**
+ * Adds multiple choices to this option.
+ *
+ * @param choices - The choices to add
+ */
addChoices(...choices) {
if (choices.length > 0 && this.autocomplete) {
throw new RangeError("Autocomplete and choices are mutually exclusive to each other.");
@@ -1167,6 +1775,11 @@ var ApplicationCommandOptionWithChoicesAndAutocompleteMixin = class {
}
return this;
}
+ /**
+ * Sets multiple choices for this option.
+ *
+ * @param choices - The choices to set
+ */
setChoices(...choices) {
if (choices.length > 0 && this.autocomplete) {
throw new RangeError("Autocomplete and choices are mutually exclusive to each other.");
@@ -1176,6 +1789,11 @@ var ApplicationCommandOptionWithChoicesAndAutocompleteMixin = class {
this.addChoices(...choices);
return this;
}
+ /**
+ * Whether this option uses autocomplete.
+ *
+ * @param autocomplete - Whether this option should use autocomplete
+ */
setAutocomplete(autocomplete) {
booleanPredicate2.parse(autocomplete);
if (autocomplete && Array.isArray(this.choices) && this.choices.length > 0) {
@@ -1190,17 +1808,29 @@ __name(ApplicationCommandOptionWithChoicesAndAutocompleteMixin, "ApplicationComm
// src/interactions/slashCommands/options/integer.ts
var numberValidator = import_shapeshift8.s.number.int;
var SlashCommandIntegerOption = class extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
type = import_v1018.ApplicationCommandOptionType.Integer;
+ /**
+ * {@inheritDoc ApplicationCommandNumericOptionMinMaxValueMixin.setMaxValue}
+ */
setMaxValue(max) {
numberValidator.parse(max);
Reflect.set(this, "max_value", max);
return this;
}
+ /**
+ * {@inheritDoc ApplicationCommandNumericOptionMinMaxValueMixin.setMinValue}
+ */
setMinValue(min) {
numberValidator.parse(min);
Reflect.set(this, "min_value", min);
return this;
}
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON() {
this.runRequiredValidations();
if (this.autocomplete && Array.isArray(this.choices) && this.choices.length > 0) {
@@ -1217,7 +1847,13 @@ SlashCommandIntegerOption = __decorateClass([
// src/interactions/slashCommands/options/mentionable.ts
var import_v1019 = require("discord-api-types/v10");
var SlashCommandMentionableOption = class extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
type = import_v1019.ApplicationCommandOptionType.Mentionable;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON() {
this.runRequiredValidations();
return { ...this };
@@ -1231,17 +1867,29 @@ var import_v1020 = require("discord-api-types/v10");
var import_ts_mixer3 = require("ts-mixer");
var numberValidator2 = import_shapeshift9.s.number;
var SlashCommandNumberOption = class extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
type = import_v1020.ApplicationCommandOptionType.Number;
+ /**
+ * {@inheritDoc ApplicationCommandNumericOptionMinMaxValueMixin.setMaxValue}
+ */
setMaxValue(max) {
numberValidator2.parse(max);
Reflect.set(this, "max_value", max);
return this;
}
+ /**
+ * {@inheritDoc ApplicationCommandNumericOptionMinMaxValueMixin.setMinValue}
+ */
setMinValue(min) {
numberValidator2.parse(min);
Reflect.set(this, "min_value", min);
return this;
}
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON() {
this.runRequiredValidations();
if (this.autocomplete && Array.isArray(this.choices) && this.choices.length > 0) {
@@ -1258,7 +1906,13 @@ SlashCommandNumberOption = __decorateClass([
// src/interactions/slashCommands/options/role.ts
var import_v1021 = require("discord-api-types/v10");
var SlashCommandRoleOption = class extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
type = import_v1021.ApplicationCommandOptionType.Role;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON() {
this.runRequiredValidations();
return { ...this };
@@ -1273,19 +1927,41 @@ var import_ts_mixer4 = require("ts-mixer");
var minLengthValidator2 = import_shapeshift10.s.number.greaterThanOrEqual(0).lessThanOrEqual(6e3);
var maxLengthValidator2 = import_shapeshift10.s.number.greaterThanOrEqual(1).lessThanOrEqual(6e3);
var SlashCommandStringOption = class extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
type = import_v1022.ApplicationCommandOptionType.String;
+ /**
+ * The maximum length of this option.
+ */
max_length;
+ /**
+ * The minimum length of this option.
+ */
min_length;
+ /**
+ * Sets the maximum length of this string option.
+ *
+ * @param max - The maximum length this option can be
+ */
setMaxLength(max) {
maxLengthValidator2.parse(max);
Reflect.set(this, "max_length", max);
return this;
}
+ /**
+ * Sets the minimum length of this string option.
+ *
+ * @param min - The minimum length this option can be
+ */
setMinLength(min) {
minLengthValidator2.parse(min);
Reflect.set(this, "min_length", min);
return this;
}
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON() {
this.runRequiredValidations();
if (this.autocomplete && Array.isArray(this.choices) && this.choices.length > 0) {
@@ -1302,7 +1978,13 @@ SlashCommandStringOption = __decorateClass([
// src/interactions/slashCommands/options/user.ts
var import_v1023 = require("discord-api-types/v10");
var SlashCommandUserOption = class extends ApplicationCommandOptionBase {
+ /**
+ * The type of this option.
+ */
type = import_v1023.ApplicationCommandOptionType.User;
+ /**
+ * {@inheritDoc ApplicationCommandOptionBase.toJSON}
+ */
toJSON() {
this.runRequiredValidations();
return { ...this };
@@ -1313,33 +1995,85 @@ __name(SlashCommandUserOption, "SlashCommandUserOption");
// src/interactions/slashCommands/mixins/SharedSlashCommandOptions.ts
var SharedSlashCommandOptions = class {
options;
+ /**
+ * Adds a boolean option.
+ *
+ * @param input - A function that returns an option builder or an already built builder
+ */
addBooleanOption(input) {
return this._sharedAddOptionMethod(input, SlashCommandBooleanOption);
}
+ /**
+ * Adds a user option.
+ *
+ * @param input - A function that returns an option builder or an already built builder
+ */
addUserOption(input) {
return this._sharedAddOptionMethod(input, SlashCommandUserOption);
}
+ /**
+ * Adds a channel option.
+ *
+ * @param input - A function that returns an option builder or an already built builder
+ */
addChannelOption(input) {
return this._sharedAddOptionMethod(input, SlashCommandChannelOption);
}
+ /**
+ * Adds a role option.
+ *
+ * @param input - A function that returns an option builder or an already built builder
+ */
addRoleOption(input) {
return this._sharedAddOptionMethod(input, SlashCommandRoleOption);
}
+ /**
+ * Adds an attachment option.
+ *
+ * @param input - A function that returns an option builder or an already built builder
+ */
addAttachmentOption(input) {
return this._sharedAddOptionMethod(input, SlashCommandAttachmentOption);
}
+ /**
+ * Adds a mentionable option.
+ *
+ * @param input - A function that returns an option builder or an already built builder
+ */
addMentionableOption(input) {
return this._sharedAddOptionMethod(input, SlashCommandMentionableOption);
}
+ /**
+ * Adds a string option.
+ *
+ * @param input - A function that returns an option builder or an already built builder
+ */
addStringOption(input) {
return this._sharedAddOptionMethod(input, SlashCommandStringOption);
}
+ /**
+ * Adds an integer option.
+ *
+ * @param input - A function that returns an option builder or an already built builder
+ */
addIntegerOption(input) {
return this._sharedAddOptionMethod(input, SlashCommandIntegerOption);
}
+ /**
+ * Adds a number option.
+ *
+ * @param input - A function that returns an option builder or an already built builder
+ */
addNumberOption(input) {
return this._sharedAddOptionMethod(input, SlashCommandNumberOption);
}
+ /**
+ * Where the actual adding magic happens. β¨
+ *
+ * @param input - The input. What else?
+ * @param Instance - The instance of whatever is being added
+ * @internal
+ */
_sharedAddOptionMethod(input, Instance) {
const { options } = this;
validateMaxOptionsLength(options);
@@ -1353,9 +2087,23 @@ __name(SharedSlashCommandOptions, "SharedSlashCommandOptions");
// src/interactions/slashCommands/SlashCommandSubcommands.ts
var SlashCommandSubcommandGroupBuilder = class {
+ /**
+ * The name of this subcommand group.
+ */
name = void 0;
+ /**
+ * The description of this subcommand group.
+ */
description = void 0;
+ /**
+ * The subcommands within this subcommand group.
+ */
options = [];
+ /**
+ * Adds a new subcommand to this group.
+ *
+ * @param input - A function that returns a subcommand builder or an already built builder
+ */
addSubcommand(input) {
const { options } = this;
validateMaxOptionsLength(options);
@@ -1364,6 +2112,13 @@ var SlashCommandSubcommandGroupBuilder = class {
options.push(result);
return this;
}
+ /**
+ * Serializes this builder to API-compatible JSON data.
+ *
+ * @remarks
+ * This method runs validations on the data before serializing it.
+ * As such, it may throw an error if the data is invalid.
+ */
toJSON() {
validateRequiredParameters3(this.name, this.description, this.options);
return {
@@ -1381,9 +2136,25 @@ SlashCommandSubcommandGroupBuilder = __decorateClass([
(0, import_ts_mixer5.mix)(SharedNameAndDescription)
], SlashCommandSubcommandGroupBuilder);
var SlashCommandSubcommandBuilder = class {
+ /**
+ * The name of this subcommand.
+ */
name = void 0;
+ /**
+ * The description of this subcommand.
+ */
description = void 0;
+ /**
+ * The options within this subcommand.
+ */
options = [];
+ /**
+ * Serializes this builder to API-compatible JSON data.
+ *
+ * @remarks
+ * This method runs validations on the data before serializing it.
+ * As such, it may throw an error if the data is invalid.
+ */
toJSON() {
validateRequiredParameters3(this.name, this.description, this.options);
return {
@@ -1403,38 +2174,102 @@ SlashCommandSubcommandBuilder = __decorateClass([
// src/interactions/slashCommands/SlashCommandBuilder.ts
var SlashCommandBuilder = class {
+ /**
+ * The name of this command.
+ */
name = void 0;
+ /**
+ * The name localizations of this command.
+ */
name_localizations;
+ /**
+ * The description of this command.
+ */
description = void 0;
+ /**
+ * The description localizations of this command.
+ */
description_localizations;
+ /**
+ * The options of this command.
+ */
options = [];
+ /**
+ * Whether this command is enabled by default when the application is added to a guild.
+ *
+ * @deprecated Use {@link ContextMenuCommandBuilder.setDefaultMemberPermissions} or {@link ContextMenuCommandBuilder.setDMPermission} instead.
+ */
default_permission = void 0;
+ /**
+ * The set of permissions represented as a bit set for the command.
+ */
default_member_permissions = void 0;
+ /**
+ * Indicates whether the command is available in direct messages with the application.
+ *
+ * @remarks
+ * By default, commands are visible. This property is only for global commands.
+ */
dm_permission = void 0;
- toJSON() {
- validateRequiredParameters3(this.name, this.description, this.options);
- validateLocalizationMap(this.name_localizations);
- validateLocalizationMap(this.description_localizations);
- return {
- ...this,
- options: this.options.map((option) => option.toJSON())
- };
- }
+ /**
+ * Whether this command is NSFW.
+ */
+ nsfw = void 0;
+ /**
+ * Sets whether the command is enabled by default when the application is added to a guild.
+ *
+ * @remarks
+ * If set to `false`, you will have to later `PUT` the permissions for this command.
+ * @param value - Whether or not to enable this command by default
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
+ * @deprecated Use {@link SlashCommandBuilder.setDefaultMemberPermissions} or {@link SlashCommandBuilder.setDMPermission} instead.
+ */
setDefaultPermission(value) {
validateDefaultPermission(value);
Reflect.set(this, "default_permission", value);
return this;
}
+ /**
+ * Sets the default permissions a member should have in order to run the command.
+ *
+ * @remarks
+ * You can set this to `'0'` to disable the command by default.
+ * @param permissions - The permissions bit field to set
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
+ */
setDefaultMemberPermissions(permissions) {
const permissionValue = validateDefaultMemberPermissions(permissions);
Reflect.set(this, "default_member_permissions", permissionValue);
return this;
}
+ /**
+ * Sets if the command is available in direct messages with the application.
+ *
+ * @remarks
+ * By default, commands are visible. This method is only for global commands.
+ * @param enabled - Whether the command should be enabled in direct messages
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
+ */
setDMPermission(enabled) {
validateDMPermission(enabled);
Reflect.set(this, "dm_permission", enabled);
return this;
}
+ /**
+ * Sets whether this command is NSFW.
+ *
+ * @param nsfw - Whether this command is NSFW
+ */
+ setNSFW(nsfw = true) {
+ validateNSFW(nsfw);
+ Reflect.set(this, "nsfw", nsfw);
+ return this;
+ }
+ /**
+ * Adds a new subcommand group to this command.
+ *
+ * @param input - A function that returns a subcommand group builder or an already built builder
+ */
addSubcommandGroup(input) {
const { options } = this;
validateMaxOptionsLength(options);
@@ -1443,6 +2278,11 @@ var SlashCommandBuilder = class {
options.push(result);
return this;
}
+ /**
+ * Adds a new subcommand to this command.
+ *
+ * @param input - A function that returns a subcommand builder or an already built builder
+ */
addSubcommand(input) {
const { options } = this;
validateMaxOptionsLength(options);
@@ -1451,6 +2291,22 @@ var SlashCommandBuilder = class {
options.push(result);
return this;
}
+ /**
+ * Serializes this builder to API-compatible JSON data.
+ *
+ * @remarks
+ * This method runs validations on the data before serializing it.
+ * As such, it may throw an error if the data is invalid.
+ */
+ toJSON() {
+ validateRequiredParameters3(this.name, this.description, this.options);
+ validateLocalizationMap(this.name_localizations);
+ validateLocalizationMap(this.description_localizations);
+ return {
+ ...this,
+ options: this.options.map((option) => option.toJSON())
+ };
+ }
};
__name(SlashCommandBuilder, "SlashCommandBuilder");
SlashCommandBuilder = __decorateClass([
@@ -1506,37 +2362,101 @@ __name(validateDefaultMemberPermissions2, "validateDefaultMemberPermissions");
// src/interactions/contextMenuCommands/ContextMenuCommandBuilder.ts
var ContextMenuCommandBuilder = class {
+ /**
+ * The name of this command.
+ */
name = void 0;
+ /**
+ * The name localizations of this command.
+ */
name_localizations;
+ /**
+ * The type of this command.
+ */
type = void 0;
+ /**
+ * Whether this command is enabled by default when the application is added to a guild.
+ *
+ * @deprecated Use {@link ContextMenuCommandBuilder.setDefaultMemberPermissions} or {@link ContextMenuCommandBuilder.setDMPermission} instead.
+ */
default_permission = void 0;
+ /**
+ * The set of permissions represented as a bit set for the command.
+ */
default_member_permissions = void 0;
+ /**
+ * Indicates whether the command is available in direct messages with the application.
+ *
+ * @remarks
+ * By default, commands are visible. This property is only for global commands.
+ */
dm_permission = void 0;
+ /**
+ * Sets the name of this command.
+ *
+ * @param name - The name to use
+ */
setName(name) {
validateName2(name);
Reflect.set(this, "name", name);
return this;
}
+ /**
+ * Sets the type of this command.
+ *
+ * @param type - The type to use
+ */
setType(type) {
validateType(type);
Reflect.set(this, "type", type);
return this;
}
+ /**
+ * Sets whether the command is enabled by default when the application is added to a guild.
+ *
+ * @remarks
+ * If set to `false`, you will have to later `PUT` the permissions for this command.
+ * @param value - Whether to enable this command by default
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
+ * @deprecated Use {@link ContextMenuCommandBuilder.setDefaultMemberPermissions} or {@link ContextMenuCommandBuilder.setDMPermission} instead.
+ */
setDefaultPermission(value) {
validateDefaultPermission2(value);
Reflect.set(this, "default_permission", value);
return this;
}
+ /**
+ * Sets the default permissions a member should have in order to run this command.
+ *
+ * @remarks
+ * You can set this to `'0'` to disable the command by default.
+ * @param permissions - The permissions bit field to set
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
+ */
setDefaultMemberPermissions(permissions) {
const permissionValue = validateDefaultMemberPermissions2(permissions);
Reflect.set(this, "default_member_permissions", permissionValue);
return this;
}
+ /**
+ * Sets if the command is available in direct messages with the application.
+ *
+ * @remarks
+ * By default, commands are visible. This method is only for global commands.
+ * @param enabled - Whether the command should be enabled in direct messages
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
+ */
setDMPermission(enabled) {
validateDMPermission2(enabled);
Reflect.set(this, "dm_permission", enabled);
return this;
}
+ /**
+ * Sets a name localization for this command.
+ *
+ * @param locale - The locale to set
+ * @param localizedName - The localized name for the given `locale`
+ */
setNameLocalization(locale, localizedName) {
if (!this.name_localizations) {
Reflect.set(this, "name_localizations", {});
@@ -1550,6 +2470,11 @@ var ContextMenuCommandBuilder = class {
this.name_localizations[parsedLocale] = localizedName;
return this;
}
+ /**
+ * Sets the name localizations for this command.
+ *
+ * @param localizedNames - The object of localized names to set
+ */
setNameLocalizations(localizedNames) {
if (localizedNames === null) {
Reflect.set(this, "name_localizations", null);
@@ -1560,6 +2485,13 @@ var ContextMenuCommandBuilder = class {
this.setNameLocalization(...args);
return this;
}
+ /**
+ * Serializes this builder to API-compatible JSON data.
+ *
+ * @remarks
+ * This method runs validations on the data before serializing it.
+ * As such, it may throw an error if the data is invalid.
+ */
toJSON() {
validateRequiredParameters4(this.name, this.type);
validateLocalizationMap(this.name_localizations);
@@ -1575,8 +2507,7 @@ function embedLength(data) {
__name(embedLength, "embedLength");
// src/index.ts
-__reExport(src_exports, require("@discordjs/util"), module.exports);
-var version = "1.4.0";
+var version = "1.6.3";
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
ActionRowBuilder,
@@ -1593,7 +2524,6 @@ var version = "1.4.0";
ContextMenuCommandBuilder,
EmbedAssertions,
EmbedBuilder,
- Faces,
MentionableSelectMenuBuilder,
ModalAssertions,
ModalBuilder,
@@ -1619,33 +2549,14 @@ var version = "1.4.0";
StringSelectMenuOptionBuilder,
TextInputAssertions,
TextInputBuilder,
- TimestampStyles,
UserSelectMenuBuilder,
- blockQuote,
- bold,
- channelLink,
- channelMention,
- chatInputApplicationCommandMention,
- codeBlock,
createComponentBuilder,
disableValidators,
embedLength,
enableValidators,
- formatEmoji,
- hideLinkEmbed,
- hyperlink,
- inlineCode,
isValidationEnabled,
- italic,
- messageLink,
normalizeArray,
- quote,
- roleMention,
- spoiler,
- strikethrough,
- time,
- underscore,
- userMention,
- version
+ version,
+ ...require("@discordjs/formatters")
});
//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/node_modules/@discordjs/builders/dist/index.js.map b/node_modules/@discordjs/builders/dist/index.js.map
index 0e76328..11b933a 100644
--- a/node_modules/@discordjs/builders/dist/index.js.map
+++ b/node_modules/@discordjs/builders/dist/index.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/index.ts","../src/messages/embed/Assertions.ts","../src/util/validation.ts","../src/util/normalizeArray.ts","../src/messages/embed/Embed.ts","../src/messages/formatters.ts","../src/components/Assertions.ts","../src/components/selectMenu/StringSelectMenuOption.ts","../src/components/ActionRow.ts","../src/components/Component.ts","../src/components/Components.ts","../src/components/button/Button.ts","../src/components/selectMenu/ChannelSelectMenu.ts","../src/components/selectMenu/BaseSelectMenu.ts","../src/components/selectMenu/MentionableSelectMenu.ts","../src/components/selectMenu/RoleSelectMenu.ts","../src/components/selectMenu/StringSelectMenu.ts","../src/components/selectMenu/UserSelectMenu.ts","../src/components/textInput/TextInput.ts","../src/components/textInput/Assertions.ts","../src/interactions/modals/Assertions.ts","../src/interactions/modals/Modal.ts","../src/interactions/slashCommands/Assertions.ts","../src/interactions/slashCommands/SlashCommandBuilder.ts","../src/interactions/slashCommands/SlashCommandSubcommands.ts","../src/interactions/slashCommands/mixins/NameAndDescription.ts","../src/interactions/slashCommands/options/attachment.ts","../src/interactions/slashCommands/mixins/ApplicationCommandOptionBase.ts","../src/interactions/slashCommands/options/boolean.ts","../src/interactions/slashCommands/options/channel.ts","../src/interactions/slashCommands/mixins/ApplicationCommandOptionChannelTypesMixin.ts","../src/interactions/slashCommands/options/integer.ts","../src/interactions/slashCommands/mixins/ApplicationCommandNumericOptionMinMaxValueMixin.ts","../src/interactions/slashCommands/mixins/ApplicationCommandOptionWithChoicesAndAutocompleteMixin.ts","../src/interactions/slashCommands/options/mentionable.ts","../src/interactions/slashCommands/options/number.ts","../src/interactions/slashCommands/options/role.ts","../src/interactions/slashCommands/options/string.ts","../src/interactions/slashCommands/options/user.ts","../src/interactions/slashCommands/mixins/SharedSlashCommandOptions.ts","../src/interactions/contextMenuCommands/Assertions.ts","../src/interactions/contextMenuCommands/ContextMenuCommandBuilder.ts","../src/util/componentUtil.ts"],"sourcesContent":["export * as EmbedAssertions from './messages/embed/Assertions.js';\nexport * from './messages/embed/Embed.js';\nexport * from './messages/formatters.js';\n\nexport * as ComponentAssertions from './components/Assertions.js';\nexport * from './components/ActionRow.js';\nexport * from './components/button/Button.js';\nexport * from './components/Component.js';\nexport * from './components/Components.js';\nexport * from './components/textInput/TextInput.js';\nexport * as TextInputAssertions from './components/textInput/Assertions.js';\nexport * from './interactions/modals/Modal.js';\nexport * as ModalAssertions from './interactions/modals/Assertions.js';\n\nexport * from './components/selectMenu/BaseSelectMenu.js';\nexport * from './components/selectMenu/ChannelSelectMenu.js';\nexport * from './components/selectMenu/MentionableSelectMenu.js';\nexport * from './components/selectMenu/RoleSelectMenu.js';\nexport * from './components/selectMenu/StringSelectMenu.js';\n// TODO: Remove those aliases in v2\nexport {\n\t/**\n\t * @deprecated Will be removed in the next major version, use {@link StringSelectMenuBuilder} instead.\n\t */\n\tStringSelectMenuBuilder as SelectMenuBuilder,\n} from './components/selectMenu/StringSelectMenu.js';\nexport {\n\t/**\n\t * @deprecated Will be removed in the next major version, use {@link StringSelectMenuOptionBuilder} instead.\n\t */\n\tStringSelectMenuOptionBuilder as SelectMenuOptionBuilder,\n} from './components/selectMenu/StringSelectMenuOption.js';\nexport * from './components/selectMenu/StringSelectMenuOption.js';\nexport * from './components/selectMenu/UserSelectMenu.js';\n\nexport * as SlashCommandAssertions from './interactions/slashCommands/Assertions.js';\nexport * from './interactions/slashCommands/SlashCommandBuilder.js';\nexport * from './interactions/slashCommands/SlashCommandSubcommands.js';\nexport * from './interactions/slashCommands/options/boolean.js';\nexport * from './interactions/slashCommands/options/channel.js';\nexport * from './interactions/slashCommands/options/integer.js';\nexport * from './interactions/slashCommands/options/mentionable.js';\nexport * from './interactions/slashCommands/options/number.js';\nexport * from './interactions/slashCommands/options/role.js';\nexport * from './interactions/slashCommands/options/attachment.js';\nexport * from './interactions/slashCommands/options/string.js';\nexport * from './interactions/slashCommands/options/user.js';\nexport * from './interactions/slashCommands/mixins/ApplicationCommandNumericOptionMinMaxValueMixin.js';\nexport * from './interactions/slashCommands/mixins/ApplicationCommandOptionBase.js';\nexport * from './interactions/slashCommands/mixins/ApplicationCommandOptionChannelTypesMixin.js';\nexport * from './interactions/slashCommands/mixins/ApplicationCommandOptionWithChoicesAndAutocompleteMixin.js';\nexport * from './interactions/slashCommands/mixins/NameAndDescription.js';\nexport * from './interactions/slashCommands/mixins/SharedSlashCommandOptions.js';\n\nexport * as ContextMenuCommandAssertions from './interactions/contextMenuCommands/Assertions.js';\nexport * from './interactions/contextMenuCommands/ContextMenuCommandBuilder.js';\n\nexport * from './util/componentUtil.js';\nexport * from './util/normalizeArray.js';\nexport * from './util/validation.js';\nexport * from '@discordjs/util';\n\n/**\n * The {@link https://github.com/discordjs/discord.js/blob/main/packages/builders/#readme | @discordjs/builders} version\n * that you are currently using.\n */\n// This needs to explicitly be `string` so it is not typed as a \"const string\" that gets injected by esbuild\n// eslint-disable-next-line @typescript-eslint/no-inferrable-types\nexport const version: string = '1.4.0';\n","import { s } from '@sapphire/shapeshift';\nimport type { APIEmbedField } from 'discord-api-types/v10';\nimport { isValidationEnabled } from '../../util/validation.js';\n\nexport const fieldNamePredicate = s.string\n\t.lengthGreaterThanOrEqual(1)\n\t.lengthLessThanOrEqual(256)\n\t.setValidationEnabled(isValidationEnabled);\n\nexport const fieldValuePredicate = s.string\n\t.lengthGreaterThanOrEqual(1)\n\t.lengthLessThanOrEqual(1_024)\n\t.setValidationEnabled(isValidationEnabled);\n\nexport const fieldInlinePredicate = s.boolean.optional;\n\nexport const embedFieldPredicate = s\n\t.object({\n\t\tname: fieldNamePredicate,\n\t\tvalue: fieldValuePredicate,\n\t\tinline: fieldInlinePredicate,\n\t})\n\t.setValidationEnabled(isValidationEnabled);\n\nexport const embedFieldsArrayPredicate = embedFieldPredicate.array.setValidationEnabled(isValidationEnabled);\n\nexport const fieldLengthPredicate = s.number.lessThanOrEqual(25).setValidationEnabled(isValidationEnabled);\n\nexport function validateFieldLength(amountAdding: number, fields?: APIEmbedField[]): void {\n\tfieldLengthPredicate.parse((fields?.length ?? 0) + amountAdding);\n}\n\nexport const authorNamePredicate = fieldNamePredicate.nullable.setValidationEnabled(isValidationEnabled);\n\nexport const imageURLPredicate = s.string\n\t.url({\n\t\tallowedProtocols: ['http:', 'https:', 'attachment:'],\n\t})\n\t.nullish.setValidationEnabled(isValidationEnabled);\n\nexport const urlPredicate = s.string\n\t.url({\n\t\tallowedProtocols: ['http:', 'https:'],\n\t})\n\t.nullish.setValidationEnabled(isValidationEnabled);\n\nexport const embedAuthorPredicate = s\n\t.object({\n\t\tname: authorNamePredicate,\n\t\ticonURL: imageURLPredicate,\n\t\turl: urlPredicate,\n\t})\n\t.setValidationEnabled(isValidationEnabled);\n\nexport const RGBPredicate = s.number.int\n\t.greaterThanOrEqual(0)\n\t.lessThanOrEqual(255)\n\t.setValidationEnabled(isValidationEnabled);\nexport const colorPredicate = s.number.int\n\t.greaterThanOrEqual(0)\n\t.lessThanOrEqual(0xffffff)\n\t.or(s.tuple([RGBPredicate, RGBPredicate, RGBPredicate]))\n\t.nullable.setValidationEnabled(isValidationEnabled);\n\nexport const descriptionPredicate = s.string\n\t.lengthGreaterThanOrEqual(1)\n\t.lengthLessThanOrEqual(4_096)\n\t.nullable.setValidationEnabled(isValidationEnabled);\n\nexport const footerTextPredicate = s.string\n\t.lengthGreaterThanOrEqual(1)\n\t.lengthLessThanOrEqual(2_048)\n\t.nullable.setValidationEnabled(isValidationEnabled);\n\nexport const embedFooterPredicate = s\n\t.object({\n\t\ttext: footerTextPredicate,\n\t\ticonURL: imageURLPredicate,\n\t})\n\t.setValidationEnabled(isValidationEnabled);\n\nexport const timestampPredicate = s.union(s.number, s.date).nullable.setValidationEnabled(isValidationEnabled);\n\nexport const titlePredicate = fieldNamePredicate.nullable.setValidationEnabled(isValidationEnabled);\n","let validate = true;\n\nexport const enableValidators = () => (validate = true);\nexport const disableValidators = () => (validate = false);\nexport const isValidationEnabled = () => validate;\n","export function normalizeArray(arr: RestOrArray): T[] {\n\tif (Array.isArray(arr[0])) return arr[0];\n\treturn arr as T[];\n}\n\nexport type RestOrArray = T[] | [T[]];\n","import type { APIEmbed, APIEmbedAuthor, APIEmbedField, APIEmbedFooter, APIEmbedImage } from 'discord-api-types/v10';\nimport { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';\nimport {\n\tcolorPredicate,\n\tdescriptionPredicate,\n\tembedAuthorPredicate,\n\tembedFieldsArrayPredicate,\n\tembedFooterPredicate,\n\timageURLPredicate,\n\ttimestampPredicate,\n\ttitlePredicate,\n\turlPredicate,\n\tvalidateFieldLength,\n} from './Assertions.js';\n\nexport type RGBTuple = [red: number, green: number, blue: number];\n\nexport interface IconData {\n\t/**\n\t * The URL of the icon\n\t */\n\ticonURL?: string;\n\t/**\n\t * The proxy URL of the icon\n\t */\n\tproxyIconURL?: string;\n}\n\nexport type EmbedAuthorData = IconData & Omit;\n\nexport type EmbedAuthorOptions = Omit;\n\nexport type EmbedFooterData = IconData & Omit;\n\nexport type EmbedFooterOptions = Omit;\n\nexport interface EmbedImageData extends Omit {\n\t/**\n\t * The proxy URL for the image\n\t */\n\tproxyURL?: string;\n}\n/**\n * Represents a embed in a message (image/video preview, rich embed, etc.)\n */\nexport class EmbedBuilder {\n\tpublic readonly data: APIEmbed;\n\n\tpublic constructor(data: APIEmbed = {}) {\n\t\tthis.data = { ...data };\n\t\tif (data.timestamp) this.data.timestamp = new Date(data.timestamp).toISOString();\n\t}\n\n\t/**\n\t * Appends fields to the embed\n\t *\n\t * @remarks\n\t * This method accepts either an array of fields or a variable number of field parameters.\n\t * The maximum amount of fields that can be added is 25.\n\t * @example\n\t * Using an array\n\t * ```ts\n\t * const fields: APIEmbedField[] = ...;\n\t * const embed = new EmbedBuilder()\n\t * \t.addFields(fields);\n\t * ```\n\t * @example\n\t * Using rest parameters (variadic)\n\t * ```ts\n\t * const embed = new EmbedBuilder()\n\t * \t.addFields(\n\t * \t\t{ name: 'Field 1', value: 'Value 1' },\n\t * \t\t{ name: 'Field 2', value: 'Value 2' },\n\t * \t);\n\t * ```\n\t * @param fields - The fields to add\n\t */\n\tpublic addFields(...fields: RestOrArray): this {\n\t\t// eslint-disable-next-line no-param-reassign\n\t\tfields = normalizeArray(fields);\n\t\t// Ensure adding these fields won't exceed the 25 field limit\n\t\tvalidateFieldLength(fields.length, this.data.fields);\n\n\t\t// Data assertions\n\t\tembedFieldsArrayPredicate.parse(fields);\n\n\t\tif (this.data.fields) this.data.fields.push(...fields);\n\t\telse this.data.fields = fields;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Removes, replaces, or inserts fields in the embed.\n\t *\n\t * @remarks\n\t * This method behaves similarly\n\t * to {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice | Array.prototype.splice}.\n\t * The maximum amount of fields that can be added is 25.\n\t *\n\t * It's useful for modifying and adjusting order of the already-existing fields of an embed.\n\t * @example\n\t * Remove the first field\n\t * ```ts\n\t * embed.spliceFields(0, 1);\n\t * ```\n\t * @example\n\t * Remove the first n fields\n\t * ```ts\n\t * const n = 4\n\t * embed.spliceFields(0, n);\n\t * ```\n\t * @example\n\t * Remove the last field\n\t * ```ts\n\t * embed.spliceFields(-1, 1);\n\t * ```\n\t * @param index - The index to start at\n\t * @param deleteCount - The number of fields to remove\n\t * @param fields - The replacing field objects\n\t */\n\tpublic spliceFields(index: number, deleteCount: number, ...fields: APIEmbedField[]): this {\n\t\t// Ensure adding these fields won't exceed the 25 field limit\n\t\tvalidateFieldLength(fields.length - deleteCount, this.data.fields);\n\n\t\t// Data assertions\n\t\tembedFieldsArrayPredicate.parse(fields);\n\t\tif (this.data.fields) this.data.fields.splice(index, deleteCount, ...fields);\n\t\telse this.data.fields = fields;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the embed's fields\n\t *\n\t * @remarks\n\t * This method is an alias for {@link EmbedBuilder.spliceFields}. More specifically,\n\t * it splices the entire array of fields, replacing them with the provided fields.\n\t *\n\t * You can set a maximum of 25 fields.\n\t * @param fields - The fields to set\n\t */\n\tpublic setFields(...fields: RestOrArray) {\n\t\tthis.spliceFields(0, this.data.fields?.length ?? 0, ...normalizeArray(fields));\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the author of this embed\n\t *\n\t * @param options - The options for the author\n\t */\n\n\tpublic setAuthor(options: EmbedAuthorOptions | null): this {\n\t\tif (options === null) {\n\t\t\tthis.data.author = undefined;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Data assertions\n\t\tembedAuthorPredicate.parse(options);\n\n\t\tthis.data.author = { name: options.name, url: options.url, icon_url: options.iconURL };\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the color of this embed\n\t *\n\t * @param color - The color of the embed\n\t */\n\tpublic setColor(color: RGBTuple | number | null): this {\n\t\t// Data assertions\n\t\tcolorPredicate.parse(color);\n\n\t\tif (Array.isArray(color)) {\n\t\t\tconst [red, green, blue] = color;\n\t\t\tthis.data.color = (red << 16) + (green << 8) + blue;\n\t\t\treturn this;\n\t\t}\n\n\t\tthis.data.color = color ?? undefined;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the description of this embed\n\t *\n\t * @param description - The description\n\t */\n\tpublic setDescription(description: string | null): this {\n\t\t// Data assertions\n\t\tdescriptionPredicate.parse(description);\n\n\t\tthis.data.description = description ?? undefined;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the footer of this embed\n\t *\n\t * @param options - The options for the footer\n\t */\n\tpublic setFooter(options: EmbedFooterOptions | null): this {\n\t\tif (options === null) {\n\t\t\tthis.data.footer = undefined;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Data assertions\n\t\tembedFooterPredicate.parse(options);\n\n\t\tthis.data.footer = { text: options.text, icon_url: options.iconURL };\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the image of this embed\n\t *\n\t * @param url - The URL of the image\n\t */\n\tpublic setImage(url: string | null): this {\n\t\t// Data assertions\n\t\timageURLPredicate.parse(url);\n\n\t\tthis.data.image = url ? { url } : undefined;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the thumbnail of this embed\n\t *\n\t * @param url - The URL of the thumbnail\n\t */\n\tpublic setThumbnail(url: string | null): this {\n\t\t// Data assertions\n\t\timageURLPredicate.parse(url);\n\n\t\tthis.data.thumbnail = url ? { url } : undefined;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the timestamp of this embed\n\t *\n\t * @param timestamp - The timestamp or date\n\t */\n\tpublic setTimestamp(timestamp: Date | number | null = Date.now()): this {\n\t\t// Data assertions\n\t\ttimestampPredicate.parse(timestamp);\n\n\t\tthis.data.timestamp = timestamp ? new Date(timestamp).toISOString() : undefined;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the title of this embed\n\t *\n\t * @param title - The title\n\t */\n\tpublic setTitle(title: string | null): this {\n\t\t// Data assertions\n\t\ttitlePredicate.parse(title);\n\n\t\tthis.data.title = title ?? undefined;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the URL of this embed\n\t *\n\t * @param url - The URL\n\t */\n\tpublic setURL(url: string | null): this {\n\t\t// Data assertions\n\t\turlPredicate.parse(url);\n\n\t\tthis.data.url = url ?? undefined;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Transforms the embed to a plain object\n\t */\n\tpublic toJSON(): APIEmbed {\n\t\treturn { ...this.data };\n\t}\n}\n","import type { URL } from 'node:url';\nimport type { Snowflake } from 'discord-api-types/globals';\n\n/**\n * Wraps the content inside a codeblock with no language\n *\n * @param content - The content to wrap\n */\nexport function codeBlock(content: C): `\\`\\`\\`\\n${C}\\n\\`\\`\\``;\n\n/**\n * Wraps the content inside a codeblock with the specified language\n *\n * @param language - The language for the codeblock\n * @param content - The content to wrap\n */\nexport function codeBlock(language: L, content: C): `\\`\\`\\`${L}\\n${C}\\n\\`\\`\\``;\nexport function codeBlock(language: string, content?: string): string {\n\treturn typeof content === 'undefined' ? `\\`\\`\\`\\n${language}\\n\\`\\`\\`` : `\\`\\`\\`${language}\\n${content}\\n\\`\\`\\``;\n}\n\n/**\n * Wraps the content inside \\`backticks\\`, which formats it as inline code\n *\n * @param content - The content to wrap\n */\nexport function inlineCode(content: C): `\\`${C}\\`` {\n\treturn `\\`${content}\\``;\n}\n\n/**\n * Formats the content into italic text\n *\n * @param content - The content to wrap\n */\nexport function italic(content: C): `_${C}_` {\n\treturn `_${content}_`;\n}\n\n/**\n * Formats the content into bold text\n *\n * @param content - The content to wrap\n */\nexport function bold(content: C): `**${C}**` {\n\treturn `**${content}**`;\n}\n\n/**\n * Formats the content into underscored text\n *\n * @param content - The content to wrap\n */\nexport function underscore(content: C): `__${C}__` {\n\treturn `__${content}__`;\n}\n\n/**\n * Formats the content into strike-through text\n *\n * @param content - The content to wrap\n */\nexport function strikethrough(content: C): `~~${C}~~` {\n\treturn `~~${content}~~`;\n}\n\n/**\n * Formats the content into a quote. This needs to be at the start of the line for Discord to format it\n *\n * @param content - The content to wrap\n */\nexport function quote(content: C): `> ${C}` {\n\treturn `> ${content}`;\n}\n\n/**\n * Formats the content into a block quote. This needs to be at the start of the line for Discord to format it\n *\n * @param content - The content to wrap\n */\nexport function blockQuote(content: C): `>>> ${C}` {\n\treturn `>>> ${content}`;\n}\n\n/**\n * Wraps the URL into `<>`, which stops it from embedding\n *\n * @param url - The URL to wrap\n */\nexport function hideLinkEmbed(url: C): `<${C}>`;\n\n/**\n * Wraps the URL into `<>`, which stops it from embedding\n *\n * @param url - The URL to wrap\n */\nexport function hideLinkEmbed(url: URL): `<${string}>`;\nexport function hideLinkEmbed(url: URL | string) {\n\treturn `<${url}>`;\n}\n\n/**\n * Formats the content and the URL into a masked URL\n *\n * @param content - The content to display\n * @param url - The URL the content links to\n */\nexport function hyperlink(content: C, url: URL): `[${C}](${string})`;\n\n/**\n * Formats the content and the URL into a masked URL\n *\n * @param content - The content to display\n * @param url - The URL the content links to\n */\nexport function hyperlink(content: C, url: U): `[${C}](${U})`;\n\n/**\n * Formats the content and the URL into a masked URL\n *\n * @param content - The content to display\n * @param url - The URL the content links to\n * @param title - The title shown when hovering on the masked link\n */\nexport function hyperlink(\n\tcontent: C,\n\turl: URL,\n\ttitle: T,\n): `[${C}](${string} \"${T}\")`;\n\n/**\n * Formats the content and the URL into a masked URL\n *\n * @param content - The content to display\n * @param url - The URL the content links to\n * @param title - The title shown when hovering on the masked link\n */\nexport function hyperlink(\n\tcontent: C,\n\turl: U,\n\ttitle: T,\n): `[${C}](${U} \"${T}\")`;\nexport function hyperlink(content: string, url: URL | string, title?: string) {\n\treturn title ? `[${content}](${url} \"${title}\")` : `[${content}](${url})`;\n}\n\n/**\n * Wraps the content inside spoiler (hidden text)\n *\n * @param content - The content to wrap\n */\nexport function spoiler(content: C): `||${C}||` {\n\treturn `||${content}||`;\n}\n\n/**\n * Formats a user ID into a user mention\n *\n * @param userId - The user ID to format\n */\nexport function userMention(userId: C): `<@${C}>` {\n\treturn `<@${userId}>`;\n}\n\n/**\n * Formats a channel ID into a channel mention\n *\n * @param channelId - The channel ID to format\n */\nexport function channelMention(channelId: C): `<#${C}>` {\n\treturn `<#${channelId}>`;\n}\n\n/**\n * Formats a role ID into a role mention\n *\n * @param roleId - The role ID to format\n */\nexport function roleMention(roleId: C): `<@&${C}>` {\n\treturn `<@&${roleId}>`;\n}\n\n/**\n * Formats an application command name, subcommand group name, subcommand name, and ID into an application command mention\n *\n * @param commandName - The application command name to format\n * @param subcommandGroupName - The subcommand group name to format\n * @param subcommandName - The subcommand name to format\n * @param commandId - The application command ID to format\n */\nexport function chatInputApplicationCommandMention<\n\tN extends string,\n\tG extends string,\n\tS extends string,\n\tI extends Snowflake,\n>(commandName: N, subcommandGroupName: G, subcommandName: S, commandId: I): `${N} ${G} ${S}:${I}>`;\n\n/**\n * Formats an application command name, subcommand name, and ID into an application command mention\n *\n * @param commandName - The application command name to format\n * @param subcommandName - The subcommand name to format\n * @param commandId - The application command ID to format\n */\nexport function chatInputApplicationCommandMention(\n\tcommandName: N,\n\tsubcommandName: S,\n\tcommandId: I,\n): `${N} ${S}:${I}>`;\n\n/**\n * Formats an application command name and ID into an application command mention\n *\n * @param commandName - The application command name to format\n * @param commandId - The application command ID to format\n */\nexport function chatInputApplicationCommandMention(\n\tcommandName: N,\n\tcommandId: I,\n): `${N}:${I}>`;\n\n/**\n * Formats an application command name, subcommand group name, subcommand name, and ID into an application command mention\n *\n * @param commandName - The application command name to format\n * @param subcommandGroupName - The subcommand group name to format\n * @param subcommandName - The subcommand name to format\n * @param commandId - The application command ID to format\n */\nexport function chatInputApplicationCommandMention<\n\tN extends string,\n\tG extends Snowflake | string,\n\tS extends Snowflake | string,\n\tI extends Snowflake,\n>(\n\tcommandName: N,\n\tsubcommandGroupName: G,\n\tsubcommandName?: S,\n\tcommandId?: I,\n): `${N} ${G} ${S}:${I}>` | `${N} ${G}:${S}>` | `${N}:${G}>` {\n\tif (typeof commandId !== 'undefined') {\n\t\treturn `${commandName} ${subcommandGroupName} ${subcommandName!}:${commandId}>`;\n\t}\n\n\tif (typeof subcommandName !== 'undefined') {\n\t\treturn `${commandName} ${subcommandGroupName}:${subcommandName}>`;\n\t}\n\n\treturn `${commandName}:${subcommandGroupName}>`;\n}\n\n/**\n * Formats an emoji ID into a fully qualified emoji identifier\n *\n * @param emojiId - The emoji ID to format\n */\nexport function formatEmoji(emojiId: C, animated?: false): `<:_:${C}>`;\n\n/**\n * Formats an emoji ID into a fully qualified emoji identifier\n *\n * @param emojiId - The emoji ID to format\n * @param animated - Whether the emoji is animated or not. Defaults to `false`\n */\nexport function formatEmoji(emojiId: C, animated?: true): ``;\n\n/**\n * Formats an emoji ID into a fully qualified emoji identifier\n *\n * @param emojiId - The emoji ID to format\n * @param animated - Whether the emoji is animated or not. Defaults to `false`\n */\nexport function formatEmoji(emojiId: C, animated?: boolean): `<:_:${C}>` | ``;\n\n/**\n * Formats an emoji ID into a fully qualified emoji identifier\n *\n * @param emojiId - The emoji ID to format\n * @param animated - Whether the emoji is animated or not. Defaults to `false`\n */\nexport function formatEmoji(emojiId: C, animated = false): `<:_:${C}>` | `` {\n\treturn `<${animated ? 'a' : ''}:_:${emojiId}>`;\n}\n\n/**\n * Formats a channel link for a direct message channel.\n *\n * @param channelId - The channel's id\n */\nexport function channelLink(channelId: C): `https://discord.com/channels/@me/${C}`;\n\n/**\n * Formats a channel link for a guild channel.\n *\n * @param channelId - The channel's id\n * @param guildId - The guild's id\n */\nexport function channelLink(\n\tchannelId: C,\n\tguildId: G,\n): `https://discord.com/channels/${G}/${C}`;\n\nexport function channelLink(\n\tchannelId: C,\n\tguildId?: G,\n): `https://discord.com/channels/@me/${C}` | `https://discord.com/channels/${G}/${C}` {\n\treturn `https://discord.com/channels/${guildId ?? '@me'}/${channelId}`;\n}\n\n/**\n * Formats a message link for a direct message channel.\n *\n * @param channelId - The channel's id\n * @param messageId - The message's id\n */\nexport function messageLink(\n\tchannelId: C,\n\tmessageId: M,\n): `https://discord.com/channels/@me/${C}/${M}`;\n\n/**\n * Formats a message link for a guild channel.\n *\n * @param channelId - The channel's id\n * @param messageId - The message's id\n * @param guildId - The guild's id\n */\nexport function messageLink(\n\tchannelId: C,\n\tmessageId: M,\n\tguildId: G,\n): `https://discord.com/channels/${G}/${C}/${M}`;\n\nexport function messageLink(\n\tchannelId: C,\n\tmessageId: M,\n\tguildId?: G,\n): `https://discord.com/channels/@me/${C}/${M}` | `https://discord.com/channels/${G}/${C}/${M}` {\n\treturn `${typeof guildId === 'undefined' ? channelLink(channelId) : channelLink(channelId, guildId)}/${messageId}`;\n}\n\n/**\n * Formats a date into a short date-time string\n *\n * @param date - The date to format, defaults to the current time\n */\nexport function time(date?: Date): ``;\n\n/**\n * Formats a date given a format style\n *\n * @param date - The date to format\n * @param style - The style to use\n */\nexport function time(date: Date, style: S): ``;\n\n/**\n * Formats the given timestamp into a short date-time string\n *\n * @param seconds - The time to format, represents an UNIX timestamp in seconds\n */\nexport function time(seconds: C): ``;\n\n/**\n * Formats the given timestamp into a short date-time string\n *\n * @param seconds - The time to format, represents an UNIX timestamp in seconds\n * @param style - The style to use\n */\nexport function time(seconds: C, style: S): ``;\nexport function time(timeOrSeconds?: Date | number, style?: TimestampStylesString): string {\n\tif (typeof timeOrSeconds !== 'number') {\n\t\t// eslint-disable-next-line no-param-reassign\n\t\ttimeOrSeconds = Math.floor((timeOrSeconds?.getTime() ?? Date.now()) / 1_000);\n\t}\n\n\treturn typeof style === 'string' ? `` : ``;\n}\n\n/**\n * The {@link https://discord.com/developers/docs/reference#message-formatting-timestamp-styles | message formatting timestamp styles} supported by Discord\n */\nexport const TimestampStyles = {\n\t/**\n\t * Short time format, consisting of hours and minutes, e.g. 16:20\n\t */\n\tShortTime: 't',\n\n\t/**\n\t * Long time format, consisting of hours, minutes, and seconds, e.g. 16:20:30\n\t */\n\tLongTime: 'T',\n\n\t/**\n\t * Short date format, consisting of day, month, and year, e.g. 20/04/2021\n\t */\n\tShortDate: 'd',\n\n\t/**\n\t * Long date format, consisting of day, month, and year, e.g. 20 April 2021\n\t */\n\tLongDate: 'D',\n\n\t/**\n\t * Short date-time format, consisting of short date and short time formats, e.g. 20 April 2021 16:20\n\t */\n\tShortDateTime: 'f',\n\n\t/**\n\t * Long date-time format, consisting of long date and short time formats, e.g. Tuesday, 20 April 2021 16:20\n\t */\n\tLongDateTime: 'F',\n\n\t/**\n\t * Relative time format, consisting of a relative duration format, e.g. 2 months ago\n\t */\n\tRelativeTime: 'R',\n} as const;\n\n/**\n * The possible values, see {@link TimestampStyles} for more information\n */\nexport type TimestampStylesString = typeof TimestampStyles[keyof typeof TimestampStyles];\n\n/**\n * An enum with all the available faces from Discord's native slash commands\n */\nexport enum Faces {\n\t/**\n\t * Β―\\\\_(γ)\\\\_/Β―\n\t */\n\tShrug = 'Β―\\\\_(γ)\\\\_/Β―',\n\n\t/**\n\t * (β―Β°β‘Β°οΌβ―οΈ΅ β»ββ»\n\t */\n\tTableflip = '(β―Β°β‘Β°οΌβ―οΈ΅ β»ββ»',\n\n\t/**\n\t * β¬ββ¬ γ( γ-γγ)\n\t */\n\tUnflip = 'β¬ββ¬ γ( γ-γγ)',\n}\n","import { s } from '@sapphire/shapeshift';\nimport { ButtonStyle, ChannelType, type APIMessageComponentEmoji } from 'discord-api-types/v10';\nimport { isValidationEnabled } from '../util/validation.js';\nimport { StringSelectMenuOptionBuilder } from './selectMenu/StringSelectMenuOption.js';\n\nexport const customIdValidator = s.string\n\t.lengthGreaterThanOrEqual(1)\n\t.lengthLessThanOrEqual(100)\n\t.setValidationEnabled(isValidationEnabled);\n\nexport const emojiValidator = s\n\t.object({\n\t\tid: s.string,\n\t\tname: s.string,\n\t\tanimated: s.boolean,\n\t})\n\t.partial.strict.setValidationEnabled(isValidationEnabled);\n\nexport const disabledValidator = s.boolean;\n\nexport const buttonLabelValidator = s.string\n\t.lengthGreaterThanOrEqual(1)\n\t.lengthLessThanOrEqual(80)\n\t.setValidationEnabled(isValidationEnabled);\n\nexport const buttonStyleValidator = s.nativeEnum(ButtonStyle);\n\nexport const placeholderValidator = s.string.lengthLessThanOrEqual(150).setValidationEnabled(isValidationEnabled);\nexport const minMaxValidator = s.number.int\n\t.greaterThanOrEqual(0)\n\t.lessThanOrEqual(25)\n\t.setValidationEnabled(isValidationEnabled);\n\nexport const labelValueDescriptionValidator = s.string\n\t.lengthGreaterThanOrEqual(1)\n\t.lengthLessThanOrEqual(100)\n\t.setValidationEnabled(isValidationEnabled);\n\nexport const jsonOptionValidator = s\n\t.object({\n\t\tlabel: labelValueDescriptionValidator,\n\t\tvalue: labelValueDescriptionValidator,\n\t\tdescription: labelValueDescriptionValidator.optional,\n\t\temoji: emojiValidator.optional,\n\t\tdefault: s.boolean.optional,\n\t})\n\t.setValidationEnabled(isValidationEnabled);\n\nexport const optionValidator = s.instance(StringSelectMenuOptionBuilder).setValidationEnabled(isValidationEnabled);\n\nexport const optionsValidator = optionValidator.array\n\t.lengthGreaterThanOrEqual(0)\n\t.setValidationEnabled(isValidationEnabled);\nexport const optionsLengthValidator = s.number.int\n\t.greaterThanOrEqual(0)\n\t.lessThanOrEqual(25)\n\t.setValidationEnabled(isValidationEnabled);\n\nexport function validateRequiredSelectMenuParameters(options: StringSelectMenuOptionBuilder[], customId?: string) {\n\tcustomIdValidator.parse(customId);\n\toptionsValidator.parse(options);\n}\n\nexport const defaultValidator = s.boolean;\n\nexport function validateRequiredSelectMenuOptionParameters(label?: string, value?: string) {\n\tlabelValueDescriptionValidator.parse(label);\n\tlabelValueDescriptionValidator.parse(value);\n}\n\nexport const channelTypesValidator = s.nativeEnum(ChannelType).array.setValidationEnabled(isValidationEnabled);\n\nexport const urlValidator = s.string\n\t.url({\n\t\tallowedProtocols: ['http:', 'https:', 'discord:'],\n\t})\n\t.setValidationEnabled(isValidationEnabled);\n\nexport function validateRequiredButtonParameters(\n\tstyle?: ButtonStyle,\n\tlabel?: string,\n\temoji?: APIMessageComponentEmoji,\n\tcustomId?: string,\n\turl?: string,\n) {\n\tif (url && customId) {\n\t\tthrow new RangeError('URL and custom id are mutually exclusive');\n\t}\n\n\tif (!label && !emoji) {\n\t\tthrow new RangeError('Buttons must have a label and/or an emoji');\n\t}\n\n\tif (style === ButtonStyle.Link) {\n\t\tif (!url) {\n\t\t\tthrow new RangeError('Link buttons must have a url');\n\t\t}\n\t} else if (url) {\n\t\tthrow new RangeError('Non-link buttons cannot have a url');\n\t}\n}\n","import type { JSONEncodable } from '@discordjs/util';\nimport type { APIMessageComponentEmoji, APISelectMenuOption } from 'discord-api-types/v10';\nimport {\n\tdefaultValidator,\n\temojiValidator,\n\tlabelValueDescriptionValidator,\n\tvalidateRequiredSelectMenuOptionParameters,\n} from '../Assertions.js';\n\n/**\n * Represents an option within a string select menu component\n */\nexport class StringSelectMenuOptionBuilder implements JSONEncodable {\n\t/**\n\t * Creates a new string select menu option from API data\n\t *\n\t * @param data - The API data to create this string select menu option with\n\t * @example\n\t * Creating a string select menu option from an API data object\n\t * ```ts\n\t * const selectMenuOption = new SelectMenuOptionBuilder({\n\t * \tlabel: 'catchy label',\n\t * \tvalue: '1',\n\t * });\n\t * ```\n\t * @example\n\t * Creating a string select menu option using setters and API data\n\t * ```ts\n\t * const selectMenuOption = new SelectMenuOptionBuilder({\n\t * \tdefault: true,\n\t * \tvalue: '1',\n\t * })\n\t * \t.setLabel('woah')\n\t * ```\n\t */\n\tpublic constructor(public data: Partial = {}) {}\n\n\t/**\n\t * Sets the label of this option\n\t *\n\t * @param label - The label to show on this option\n\t */\n\tpublic setLabel(label: string) {\n\t\tthis.data.label = labelValueDescriptionValidator.parse(label);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the value of this option\n\t *\n\t * @param value - The value of this option\n\t */\n\tpublic setValue(value: string) {\n\t\tthis.data.value = labelValueDescriptionValidator.parse(value);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the description of this option\n\t *\n\t * @param description - The description of this option\n\t */\n\tpublic setDescription(description: string) {\n\t\tthis.data.description = labelValueDescriptionValidator.parse(description);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets whether this option is selected by default\n\t *\n\t * @param isDefault - Whether this option is selected by default\n\t */\n\tpublic setDefault(isDefault = true) {\n\t\tthis.data.default = defaultValidator.parse(isDefault);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the emoji to display on this option\n\t *\n\t * @param emoji - The emoji to display on this option\n\t */\n\tpublic setEmoji(emoji: APIMessageComponentEmoji) {\n\t\tthis.data.emoji = emojiValidator.parse(emoji);\n\t\treturn this;\n\t}\n\n\t/**\n\t * {@inheritDoc ComponentBuilder.toJSON}\n\t */\n\tpublic toJSON(): APISelectMenuOption {\n\t\tvalidateRequiredSelectMenuOptionParameters(this.data.label, this.data.value);\n\n\t\treturn {\n\t\t\t...this.data,\n\t\t} as APISelectMenuOption;\n\t}\n}\n","/* eslint-disable jsdoc/check-param-names */\n\nimport {\n\ttype APIActionRowComponent,\n\tComponentType,\n\ttype APIMessageActionRowComponent,\n\ttype APIModalActionRowComponent,\n\ttype APIActionRowComponentTypes,\n} from 'discord-api-types/v10';\nimport { normalizeArray, type RestOrArray } from '../util/normalizeArray.js';\nimport { ComponentBuilder } from './Component.js';\nimport { createComponentBuilder } from './Components.js';\nimport type { ButtonBuilder } from './button/Button.js';\nimport type { ChannelSelectMenuBuilder } from './selectMenu/ChannelSelectMenu.js';\nimport type { MentionableSelectMenuBuilder } from './selectMenu/MentionableSelectMenu.js';\nimport type { RoleSelectMenuBuilder } from './selectMenu/RoleSelectMenu.js';\nimport type { StringSelectMenuBuilder } from './selectMenu/StringSelectMenu.js';\nimport type { UserSelectMenuBuilder } from './selectMenu/UserSelectMenu.js';\nimport type { TextInputBuilder } from './textInput/TextInput.js';\n\nexport type MessageComponentBuilder =\n\t| ActionRowBuilder\n\t| MessageActionRowComponentBuilder;\nexport type ModalComponentBuilder = ActionRowBuilder | ModalActionRowComponentBuilder;\nexport type MessageActionRowComponentBuilder =\n\t| ButtonBuilder\n\t| ChannelSelectMenuBuilder\n\t| MentionableSelectMenuBuilder\n\t| RoleSelectMenuBuilder\n\t| StringSelectMenuBuilder\n\t| UserSelectMenuBuilder;\nexport type ModalActionRowComponentBuilder = TextInputBuilder;\nexport type AnyComponentBuilder = MessageActionRowComponentBuilder | ModalActionRowComponentBuilder;\n\n/**\n * Represents an action row component\n *\n * @typeParam T - The types of components this action row holds\n */\nexport class ActionRowBuilder extends ComponentBuilder<\n\tAPIActionRowComponent\n> {\n\t/**\n\t * The components within this action row\n\t */\n\tpublic readonly components: T[];\n\n\t/**\n\t * Creates a new action row from API data\n\t *\n\t * @param data - The API data to create this action row with\n\t * @example\n\t * Creating an action row from an API data object\n\t * ```ts\n\t * const actionRow = new ActionRowBuilder({\n\t * \tcomponents: [\n\t * \t\t{\n\t * \t\t\tcustom_id: \"custom id\",\n\t * \t\t\tlabel: \"Type something\",\n\t * \t\t\tstyle: TextInputStyle.Short,\n\t * \t\t\ttype: ComponentType.TextInput,\n\t * \t\t},\n\t * \t],\n\t * });\n\t * ```\n\t * @example\n\t * Creating an action row using setters and API data\n\t * ```ts\n\t * const actionRow = new ActionRowBuilder({\n\t * \tcomponents: [\n\t * \t\t{\n\t * \t\t\tcustom_id: \"custom id\",\n\t * \t\t\tlabel: \"Click me\",\n\t * \t\t\tstyle: ButtonStyle.Primary,\n\t * \t\t\ttype: ComponentType.Button,\n\t * \t\t},\n\t * \t],\n\t * })\n\t * \t.addComponents(button2, button3);\n\t * ```\n\t */\n\tpublic constructor({ components, ...data }: Partial> = {}) {\n\t\tsuper({ type: ComponentType.ActionRow, ...data });\n\t\tthis.components = (components?.map((component) => createComponentBuilder(component)) ?? []) as T[];\n\t}\n\n\t/**\n\t * Adds components to this action row.\n\t *\n\t * @param components - The components to add to this action row.\n\t */\n\tpublic addComponents(...components: RestOrArray) {\n\t\tthis.components.push(...normalizeArray(components));\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the components in this action row\n\t *\n\t * @param components - The components to set this row to\n\t */\n\tpublic setComponents(...components: RestOrArray) {\n\t\tthis.components.splice(0, this.components.length, ...normalizeArray(components));\n\t\treturn this;\n\t}\n\n\t/**\n\t * {@inheritDoc ComponentBuilder.toJSON}\n\t */\n\tpublic toJSON(): APIActionRowComponent> {\n\t\treturn {\n\t\t\t...this.data,\n\t\t\tcomponents: this.components.map((component) => component.toJSON()),\n\t\t} as APIActionRowComponent>;\n\t}\n}\n","import type { JSONEncodable } from '@discordjs/util';\nimport type {\n\tAPIActionRowComponent,\n\tAPIActionRowComponentTypes,\n\tAPIBaseComponent,\n\tComponentType,\n} from 'discord-api-types/v10';\n\nexport type AnyAPIActionRowComponent = APIActionRowComponent | APIActionRowComponentTypes;\n\n/**\n * Represents a discord component\n *\n * @typeParam DataType - The type of internal API data that is stored within the component\n */\nexport abstract class ComponentBuilder<\n\tDataType extends Partial> = APIBaseComponent,\n> implements JSONEncodable\n{\n\t/**\n\t * The API data associated with this component\n\t */\n\tpublic readonly data: Partial;\n\n\t/**\n\t * Serializes this component to an API-compatible JSON object\n\t *\n\t * @remarks\n\t * This method runs validations on the data before serializing it.\n\t * As such, it may throw an error if the data is invalid.\n\t */\n\tpublic abstract toJSON(): AnyAPIActionRowComponent;\n\n\tpublic constructor(data: Partial) {\n\t\tthis.data = data;\n\t}\n}\n","import { ComponentType, type APIMessageComponent, type APIModalComponent } from 'discord-api-types/v10';\nimport {\n\tActionRowBuilder,\n\ttype AnyComponentBuilder,\n\ttype MessageComponentBuilder,\n\ttype ModalComponentBuilder,\n} from './ActionRow.js';\nimport { ComponentBuilder } from './Component.js';\nimport { ButtonBuilder } from './button/Button.js';\nimport { ChannelSelectMenuBuilder } from './selectMenu/ChannelSelectMenu.js';\nimport { MentionableSelectMenuBuilder } from './selectMenu/MentionableSelectMenu.js';\nimport { RoleSelectMenuBuilder } from './selectMenu/RoleSelectMenu.js';\nimport { StringSelectMenuBuilder } from './selectMenu/StringSelectMenu.js';\nimport { UserSelectMenuBuilder } from './selectMenu/UserSelectMenu.js';\nimport { TextInputBuilder } from './textInput/TextInput.js';\n\nexport interface MappedComponentTypes {\n\t[ComponentType.ActionRow]: ActionRowBuilder;\n\t[ComponentType.Button]: ButtonBuilder;\n\t[ComponentType.StringSelect]: StringSelectMenuBuilder;\n\t[ComponentType.TextInput]: TextInputBuilder;\n\t[ComponentType.UserSelect]: UserSelectMenuBuilder;\n\t[ComponentType.RoleSelect]: RoleSelectMenuBuilder;\n\t[ComponentType.MentionableSelect]: MentionableSelectMenuBuilder;\n\t[ComponentType.ChannelSelect]: ChannelSelectMenuBuilder;\n}\n\n/**\n * Factory for creating components from API data\n *\n * @param data - The api data to transform to a component class\n */\nexport function createComponentBuilder(\n\t// eslint-disable-next-line @typescript-eslint/sort-type-union-intersection-members\n\tdata: (APIModalComponent | APIMessageComponent) & { type: T },\n): MappedComponentTypes[T];\nexport function createComponentBuilder(data: C): C;\nexport function createComponentBuilder(\n\tdata: APIMessageComponent | APIModalComponent | MessageComponentBuilder,\n): ComponentBuilder {\n\tif (data instanceof ComponentBuilder) {\n\t\treturn data;\n\t}\n\n\tswitch (data.type) {\n\t\tcase ComponentType.ActionRow:\n\t\t\treturn new ActionRowBuilder(data);\n\t\tcase ComponentType.Button:\n\t\t\treturn new ButtonBuilder(data);\n\t\tcase ComponentType.StringSelect:\n\t\t\treturn new StringSelectMenuBuilder(data);\n\t\tcase ComponentType.TextInput:\n\t\t\treturn new TextInputBuilder(data);\n\t\tcase ComponentType.UserSelect:\n\t\t\treturn new UserSelectMenuBuilder(data);\n\t\tcase ComponentType.RoleSelect:\n\t\t\treturn new RoleSelectMenuBuilder(data);\n\t\tcase ComponentType.MentionableSelect:\n\t\t\treturn new MentionableSelectMenuBuilder(data);\n\t\tcase ComponentType.ChannelSelect:\n\t\t\treturn new ChannelSelectMenuBuilder(data);\n\t\tdefault:\n\t\t\t// @ts-expect-error: This case can still occur if we get a newer unsupported component type\n\t\t\tthrow new Error(`Cannot properly serialize component type: ${data.type}`);\n\t}\n}\n","import {\n\tComponentType,\n\ttype APIMessageComponentEmoji,\n\ttype APIButtonComponent,\n\ttype APIButtonComponentWithURL,\n\ttype APIButtonComponentWithCustomId,\n\ttype ButtonStyle,\n} from 'discord-api-types/v10';\nimport {\n\tbuttonLabelValidator,\n\tbuttonStyleValidator,\n\tcustomIdValidator,\n\tdisabledValidator,\n\temojiValidator,\n\turlValidator,\n\tvalidateRequiredButtonParameters,\n} from '../Assertions.js';\nimport { ComponentBuilder } from '../Component.js';\n\n/**\n * Represents a button component\n */\nexport class ButtonBuilder extends ComponentBuilder {\n\t/**\n\t * Creates a new button from API data\n\t *\n\t * @param data - The API data to create this button with\n\t * @example\n\t * Creating a button from an API data object\n\t * ```ts\n\t * const button = new ButtonBuilder({\n\t * \tcustom_id: 'a cool button',\n\t * \tstyle: ButtonStyle.Primary,\n\t * \tlabel: 'Click Me',\n\t * \temoji: {\n\t * \t\tname: 'smile',\n\t * \t\tid: '123456789012345678',\n\t * \t},\n\t * });\n\t * ```\n\t * @example\n\t * Creating a button using setters and API data\n\t * ```ts\n\t * const button = new ButtonBuilder({\n\t * \tstyle: ButtonStyle.Secondary,\n\t * \tlabel: 'Click Me',\n\t * })\n\t * \t.setEmoji({ name: 'π' })\n\t * \t.setCustomId('another cool button');\n\t * ```\n\t */\n\tpublic constructor(data?: Partial) {\n\t\tsuper({ type: ComponentType.Button, ...data });\n\t}\n\n\t/**\n\t * Sets the style of this button\n\t *\n\t * @param style - The style of the button\n\t */\n\tpublic setStyle(style: ButtonStyle) {\n\t\tthis.data.style = buttonStyleValidator.parse(style);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the URL for this button\n\t *\n\t * @remarks\n\t * This method is only available to buttons using the `Link` button style.\n\t * Only three types of URL schemes are currently supported: `https://`, `http://` and `discord://`\n\t * @param url - The URL to open when this button is clicked\n\t */\n\tpublic setURL(url: string) {\n\t\t(this.data as APIButtonComponentWithURL).url = urlValidator.parse(url);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the custom id for this button\n\t *\n\t * @remarks\n\t * This method is only applicable to buttons that are not using the `Link` button style.\n\t * @param customId - The custom id to use for this button\n\t */\n\tpublic setCustomId(customId: string) {\n\t\t(this.data as APIButtonComponentWithCustomId).custom_id = customIdValidator.parse(customId);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the emoji to display on this button\n\t *\n\t * @param emoji - The emoji to display on this button\n\t */\n\tpublic setEmoji(emoji: APIMessageComponentEmoji) {\n\t\tthis.data.emoji = emojiValidator.parse(emoji);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets whether this button is disabled\n\t *\n\t * @param disabled - Whether to disable this button\n\t */\n\tpublic setDisabled(disabled = true) {\n\t\tthis.data.disabled = disabledValidator.parse(disabled);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the label for this button\n\t *\n\t * @param label - The label to display on this button\n\t */\n\tpublic setLabel(label: string) {\n\t\tthis.data.label = buttonLabelValidator.parse(label);\n\t\treturn this;\n\t}\n\n\t/**\n\t * {@inheritDoc ComponentBuilder.toJSON}\n\t */\n\tpublic toJSON(): APIButtonComponent {\n\t\tvalidateRequiredButtonParameters(\n\t\t\tthis.data.style,\n\t\t\tthis.data.label,\n\t\t\tthis.data.emoji,\n\t\t\t(this.data as APIButtonComponentWithCustomId).custom_id,\n\t\t\t(this.data as APIButtonComponentWithURL).url,\n\t\t);\n\n\t\treturn {\n\t\t\t...this.data,\n\t\t} as APIButtonComponent;\n\t}\n}\n","import type { APIChannelSelectComponent, ChannelType } from 'discord-api-types/v10';\nimport { ComponentType } from 'discord-api-types/v10';\nimport { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';\nimport { channelTypesValidator, customIdValidator } from '../Assertions.js';\nimport { BaseSelectMenuBuilder } from './BaseSelectMenu.js';\n\nexport class ChannelSelectMenuBuilder extends BaseSelectMenuBuilder {\n\t/**\n\t * Creates a new select menu from API data\n\t *\n\t * @param data - The API data to create this select menu with\n\t * @example\n\t * Creating a select menu from an API data object\n\t * ```ts\n\t * const selectMenu = new ChannelSelectMenuBuilder({\n\t * \tcustom_id: 'a cool select menu',\n\t * \tplaceholder: 'select an option',\n\t * \tmax_values: 2,\n\t * });\n\t * ```\n\t * @example\n\t * Creating a select menu using setters and API data\n\t * ```ts\n\t * const selectMenu = new ChannelSelectMenuBuilder({\n\t * \tcustom_id: 'a cool select menu',\n\t * })\n\t * \t.addChannelTypes(ChannelType.GuildText, ChannelType.GuildAnnouncement)\n\t * \t.setMinValues(2)\n\t * ```\n\t */\n\tpublic constructor(data?: Partial) {\n\t\tsuper({ ...data, type: ComponentType.ChannelSelect });\n\t}\n\n\tpublic addChannelTypes(...types: RestOrArray) {\n\t\t// eslint-disable-next-line no-param-reassign\n\t\ttypes = normalizeArray(types);\n\n\t\tthis.data.channel_types ??= [];\n\t\tthis.data.channel_types.push(...channelTypesValidator.parse(types));\n\t\treturn this;\n\t}\n\n\tpublic setChannelTypes(...types: RestOrArray) {\n\t\t// eslint-disable-next-line no-param-reassign\n\t\ttypes = normalizeArray(types);\n\n\t\tthis.data.channel_types ??= [];\n\t\tthis.data.channel_types.splice(0, this.data.channel_types.length, ...channelTypesValidator.parse(types));\n\t\treturn this;\n\t}\n\n\t/**\n\t * {@inheritDoc ComponentBuilder.toJSON}\n\t */\n\tpublic override toJSON(): APIChannelSelectComponent {\n\t\tcustomIdValidator.parse(this.data.custom_id);\n\n\t\treturn {\n\t\t\t...this.data,\n\t\t} as APIChannelSelectComponent;\n\t}\n}\n","import type { APISelectMenuComponent } from 'discord-api-types/v10';\nimport { customIdValidator, disabledValidator, minMaxValidator, placeholderValidator } from '../Assertions.js';\nimport { ComponentBuilder } from '../Component.js';\n\nexport class BaseSelectMenuBuilder<\n\tSelectMenuType extends APISelectMenuComponent,\n> extends ComponentBuilder {\n\t/**\n\t * Sets the placeholder for this select menu\n\t *\n\t * @param placeholder - The placeholder to use for this select menu\n\t */\n\tpublic setPlaceholder(placeholder: string) {\n\t\tthis.data.placeholder = placeholderValidator.parse(placeholder);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the minimum values that must be selected in the select menu\n\t *\n\t * @param minValues - The minimum values that must be selected\n\t */\n\tpublic setMinValues(minValues: number) {\n\t\tthis.data.min_values = minMaxValidator.parse(minValues);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the maximum values that must be selected in the select menu\n\t *\n\t * @param maxValues - The maximum values that must be selected\n\t */\n\tpublic setMaxValues(maxValues: number) {\n\t\tthis.data.max_values = minMaxValidator.parse(maxValues);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the custom id for this select menu\n\t *\n\t * @param customId - The custom id to use for this select menu\n\t */\n\tpublic setCustomId(customId: string) {\n\t\tthis.data.custom_id = customIdValidator.parse(customId);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets whether this select menu is disabled\n\t *\n\t * @param disabled - Whether this select menu is disabled\n\t */\n\tpublic setDisabled(disabled = true) {\n\t\tthis.data.disabled = disabledValidator.parse(disabled);\n\t\treturn this;\n\t}\n\n\tpublic toJSON(): SelectMenuType {\n\t\tcustomIdValidator.parse(this.data.custom_id);\n\t\treturn {\n\t\t\t...this.data,\n\t\t} as SelectMenuType;\n\t}\n}\n","import type { APIMentionableSelectComponent } from 'discord-api-types/v10';\nimport { ComponentType } from 'discord-api-types/v10';\nimport { BaseSelectMenuBuilder } from './BaseSelectMenu.js';\n\nexport class MentionableSelectMenuBuilder extends BaseSelectMenuBuilder {\n\t/**\n\t * Creates a new select menu from API data\n\t *\n\t * @param data - The API data to create this select menu with\n\t * @example\n\t * Creating a select menu from an API data object\n\t * ```ts\n\t * const selectMenu = new MentionableSelectMenuBuilder({\n\t * \tcustom_id: 'a cool select menu',\n\t * \tplaceholder: 'select an option',\n\t * \tmax_values: 2,\n\t * });\n\t * ```\n\t * @example\n\t * Creating a select menu using setters and API data\n\t * ```ts\n\t * const selectMenu = new MentionableSelectMenuBuilder({\n\t * \tcustom_id: 'a cool select menu',\n\t * })\n\t * \t.setMinValues(1)\n\t * ```\n\t */\n\tpublic constructor(data?: Partial) {\n\t\tsuper({ ...data, type: ComponentType.MentionableSelect });\n\t}\n}\n","import type { APIRoleSelectComponent } from 'discord-api-types/v10';\nimport { ComponentType } from 'discord-api-types/v10';\nimport { BaseSelectMenuBuilder } from './BaseSelectMenu.js';\n\nexport class RoleSelectMenuBuilder extends BaseSelectMenuBuilder {\n\t/**\n\t * Creates a new select menu from API data\n\t *\n\t * @param data - The API data to create this select menu with\n\t * @example\n\t * Creating a select menu from an API data object\n\t * ```ts\n\t * const selectMenu = new RoleSelectMenuBuilder({\n\t * \tcustom_id: 'a cool select menu',\n\t * \tplaceholder: 'select an option',\n\t * \tmax_values: 2,\n\t * });\n\t * ```\n\t * @example\n\t * Creating a select menu using setters and API data\n\t * ```ts\n\t * const selectMenu = new RoleSelectMenuBuilder({\n\t * \tcustom_id: 'a cool select menu',\n\t * })\n\t * \t.setMinValues(1)\n\t * ```\n\t */\n\tpublic constructor(data?: Partial) {\n\t\tsuper({ ...data, type: ComponentType.RoleSelect });\n\t}\n}\n","import type { APIStringSelectComponent } from 'discord-api-types/v10';\nimport { ComponentType, type APISelectMenuOption } from 'discord-api-types/v10';\nimport { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';\nimport { jsonOptionValidator, optionsLengthValidator, validateRequiredSelectMenuParameters } from '../Assertions.js';\nimport { BaseSelectMenuBuilder } from './BaseSelectMenu.js';\nimport { StringSelectMenuOptionBuilder } from './StringSelectMenuOption.js';\n\n/**\n * Represents a string select menu component\n */\nexport class StringSelectMenuBuilder extends BaseSelectMenuBuilder {\n\t/**\n\t * The options within this select menu\n\t */\n\tpublic readonly options: StringSelectMenuOptionBuilder[];\n\n\t/**\n\t * Creates a new select menu from API data\n\t *\n\t * @param data - The API data to create this select menu with\n\t * @example\n\t * Creating a select menu from an API data object\n\t * ```ts\n\t * const selectMenu = new StringSelectMenuBuilder({\n\t * \tcustom_id: 'a cool select menu',\n\t * \tplaceholder: 'select an option',\n\t * \tmax_values: 2,\n\t * \toptions: [\n\t * \t\t{ label: 'option 1', value: '1' },\n\t * \t\t{ label: 'option 2', value: '2' },\n\t * \t\t{ label: 'option 3', value: '3' },\n\t * \t],\n\t * });\n\t * ```\n\t * @example\n\t * Creating a select menu using setters and API data\n\t * ```ts\n\t * const selectMenu = new StringSelectMenuBuilder({\n\t * \tcustom_id: 'a cool select menu',\n\t * })\n\t * \t.setMinValues(1)\n\t * \t.addOptions({\n\t * \t\tlabel: 'Catchy',\n\t * \t\tvalue: 'catch',\n\t * \t});\n\t * ```\n\t */\n\tpublic constructor(data?: Partial) {\n\t\tconst { options, ...initData } = data ?? {};\n\t\tsuper({ ...initData, type: ComponentType.StringSelect });\n\t\tthis.options = options?.map((option: APISelectMenuOption) => new StringSelectMenuOptionBuilder(option)) ?? [];\n\t}\n\n\t/**\n\t * Adds options to this select menu\n\t *\n\t * @param options - The options to add to this select menu\n\t * @returns\n\t */\n\tpublic addOptions(...options: RestOrArray) {\n\t\t// eslint-disable-next-line no-param-reassign\n\t\toptions = normalizeArray(options);\n\t\toptionsLengthValidator.parse(this.options.length + options.length);\n\t\tthis.options.push(\n\t\t\t...options.map((option) =>\n\t\t\t\toption instanceof StringSelectMenuOptionBuilder\n\t\t\t\t\t? option\n\t\t\t\t\t: new StringSelectMenuOptionBuilder(jsonOptionValidator.parse(option)),\n\t\t\t),\n\t\t);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the options on this select menu\n\t *\n\t * @param options - The options to set on this select menu\n\t */\n\tpublic setOptions(...options: RestOrArray) {\n\t\t// eslint-disable-next-line no-param-reassign\n\t\toptions = normalizeArray(options);\n\t\toptionsLengthValidator.parse(options.length);\n\t\tthis.options.splice(\n\t\t\t0,\n\t\t\tthis.options.length,\n\t\t\t...options.map((option) =>\n\t\t\t\toption instanceof StringSelectMenuOptionBuilder\n\t\t\t\t\t? option\n\t\t\t\t\t: new StringSelectMenuOptionBuilder(jsonOptionValidator.parse(option)),\n\t\t\t),\n\t\t);\n\t\treturn this;\n\t}\n\n\t/**\n\t * {@inheritDoc ComponentBuilder.toJSON}\n\t */\n\tpublic override toJSON(): APIStringSelectComponent {\n\t\tvalidateRequiredSelectMenuParameters(this.options, this.data.custom_id);\n\n\t\treturn {\n\t\t\t...this.data,\n\t\t\toptions: this.options.map((option) => option.toJSON()),\n\t\t} as APIStringSelectComponent;\n\t}\n}\n","import type { APIUserSelectComponent } from 'discord-api-types/v10';\nimport { ComponentType } from 'discord-api-types/v10';\nimport { BaseSelectMenuBuilder } from './BaseSelectMenu.js';\n\nexport class UserSelectMenuBuilder extends BaseSelectMenuBuilder {\n\t/**\n\t * Creates a new select menu from API data\n\t *\n\t * @param data - The API data to create this select menu with\n\t * @example\n\t * Creating a select menu from an API data object\n\t * ```ts\n\t * const selectMenu = new UserSelectMenuBuilder({\n\t * \tcustom_id: 'a cool select menu',\n\t * \tplaceholder: 'select an option',\n\t * \tmax_values: 2,\n\t * });\n\t * ```\n\t * @example\n\t * Creating a select menu using setters and API data\n\t * ```ts\n\t * const selectMenu = new UserSelectMenuBuilder({\n\t * \tcustom_id: 'a cool select menu',\n\t * })\n\t * \t.setMinValues(1)\n\t * ```\n\t */\n\tpublic constructor(data?: Partial) {\n\t\tsuper({ ...data, type: ComponentType.UserSelect });\n\t}\n}\n","import { isJSONEncodable, type Equatable, type JSONEncodable } from '@discordjs/util';\nimport { ComponentType, type TextInputStyle, type APITextInputComponent } from 'discord-api-types/v10';\nimport isEqual from 'fast-deep-equal';\nimport { customIdValidator } from '../Assertions.js';\nimport { ComponentBuilder } from '../Component.js';\nimport {\n\tmaxLengthValidator,\n\tminLengthValidator,\n\tplaceholderValidator,\n\trequiredValidator,\n\tvalueValidator,\n\tvalidateRequiredParameters,\n\tlabelValidator,\n\ttextInputStyleValidator,\n} from './Assertions.js';\n\nexport class TextInputBuilder\n\textends ComponentBuilder\n\timplements Equatable>\n{\n\t/**\n\t * Creates a new text input from API data\n\t *\n\t * @param data - The API data to create this text input with\n\t * @example\n\t * Creating a select menu option from an API data object\n\t * ```ts\n\t * const textInput = new TextInputBuilder({\n\t * \tcustom_id: 'a cool select menu',\n\t * \tlabel: 'Type something',\n\t * \tstyle: TextInputStyle.Short,\n\t * });\n\t * ```\n\t * @example\n\t * Creating a select menu option using setters and API data\n\t * ```ts\n\t * const textInput = new TextInputBuilder({\n\t * \tlabel: 'Type something else',\n\t * })\n\t * \t.setCustomId('woah')\n\t * \t.setStyle(TextInputStyle.Paragraph);\n\t * ```\n\t */\n\tpublic constructor(data?: APITextInputComponent & { type?: ComponentType.TextInput }) {\n\t\tsuper({ type: ComponentType.TextInput, ...data });\n\t}\n\n\t/**\n\t * Sets the custom id for this text input\n\t *\n\t * @param customId - The custom id of this text input\n\t */\n\tpublic setCustomId(customId: string) {\n\t\tthis.data.custom_id = customIdValidator.parse(customId);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the label for this text input\n\t *\n\t * @param label - The label for this text input\n\t */\n\tpublic setLabel(label: string) {\n\t\tthis.data.label = labelValidator.parse(label);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the style for this text input\n\t *\n\t * @param style - The style for this text input\n\t */\n\tpublic setStyle(style: TextInputStyle) {\n\t\tthis.data.style = textInputStyleValidator.parse(style);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the minimum length of text for this text input\n\t *\n\t * @param minLength - The minimum length of text for this text input\n\t */\n\tpublic setMinLength(minLength: number) {\n\t\tthis.data.min_length = minLengthValidator.parse(minLength);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the maximum length of text for this text input\n\t *\n\t * @param maxLength - The maximum length of text for this text input\n\t */\n\tpublic setMaxLength(maxLength: number) {\n\t\tthis.data.max_length = maxLengthValidator.parse(maxLength);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the placeholder of this text input\n\t *\n\t * @param placeholder - The placeholder of this text input\n\t */\n\tpublic setPlaceholder(placeholder: string) {\n\t\tthis.data.placeholder = placeholderValidator.parse(placeholder);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the value of this text input\n\t *\n\t * @param value - The value for this text input\n\t */\n\tpublic setValue(value: string) {\n\t\tthis.data.value = valueValidator.parse(value);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets whether this text input is required\n\t *\n\t * @param required - Whether this text input is required\n\t */\n\tpublic setRequired(required = true) {\n\t\tthis.data.required = requiredValidator.parse(required);\n\t\treturn this;\n\t}\n\n\t/**\n\t * {@inheritDoc ComponentBuilder.toJSON}\n\t */\n\tpublic toJSON(): APITextInputComponent {\n\t\tvalidateRequiredParameters(this.data.custom_id, this.data.style, this.data.label);\n\n\t\treturn {\n\t\t\t...this.data,\n\t\t} as APITextInputComponent;\n\t}\n\n\t/**\n\t * {@inheritDoc Equatable.equals}\n\t */\n\tpublic equals(other: APITextInputComponent | JSONEncodable): boolean {\n\t\tif (isJSONEncodable(other)) {\n\t\t\treturn isEqual(other.toJSON(), this.data);\n\t\t}\n\n\t\treturn isEqual(other, this.data);\n\t}\n}\n","import { s } from '@sapphire/shapeshift';\nimport { TextInputStyle } from 'discord-api-types/v10';\nimport { isValidationEnabled } from '../../util/validation.js';\nimport { customIdValidator } from '../Assertions.js';\n\nexport const textInputStyleValidator = s.nativeEnum(TextInputStyle);\nexport const minLengthValidator = s.number.int\n\t.greaterThanOrEqual(0)\n\t.lessThanOrEqual(4_000)\n\t.setValidationEnabled(isValidationEnabled);\nexport const maxLengthValidator = s.number.int\n\t.greaterThanOrEqual(1)\n\t.lessThanOrEqual(4_000)\n\t.setValidationEnabled(isValidationEnabled);\nexport const requiredValidator = s.boolean;\nexport const valueValidator = s.string.lengthLessThanOrEqual(4_000).setValidationEnabled(isValidationEnabled);\nexport const placeholderValidator = s.string.lengthLessThanOrEqual(100).setValidationEnabled(isValidationEnabled);\nexport const labelValidator = s.string\n\t.lengthGreaterThanOrEqual(1)\n\t.lengthLessThanOrEqual(45)\n\t.setValidationEnabled(isValidationEnabled);\n\nexport function validateRequiredParameters(customId?: string, style?: TextInputStyle, label?: string) {\n\tcustomIdValidator.parse(customId);\n\ttextInputStyleValidator.parse(style);\n\tlabelValidator.parse(label);\n}\n","import { s } from '@sapphire/shapeshift';\nimport { ActionRowBuilder, type ModalActionRowComponentBuilder } from '../../components/ActionRow.js';\nimport { customIdValidator } from '../../components/Assertions.js';\nimport { isValidationEnabled } from '../../util/validation.js';\n\nexport const titleValidator = s.string\n\t.lengthGreaterThanOrEqual(1)\n\t.lengthLessThanOrEqual(45)\n\t.setValidationEnabled(isValidationEnabled);\nexport const componentsValidator = s\n\t.instance(ActionRowBuilder)\n\t.array.lengthGreaterThanOrEqual(1)\n\t.setValidationEnabled(isValidationEnabled);\n\nexport function validateRequiredParameters(\n\tcustomId?: string,\n\ttitle?: string,\n\tcomponents?: ActionRowBuilder[],\n) {\n\tcustomIdValidator.parse(customId);\n\ttitleValidator.parse(title);\n\tcomponentsValidator.parse(components);\n}\n","import type { JSONEncodable } from '@discordjs/util';\nimport type {\n\tAPIActionRowComponent,\n\tAPIModalActionRowComponent,\n\tAPIModalInteractionResponseCallbackData,\n} from 'discord-api-types/v10';\nimport { ActionRowBuilder, type ModalActionRowComponentBuilder } from '../../components/ActionRow.js';\nimport { customIdValidator } from '../../components/Assertions.js';\nimport { createComponentBuilder } from '../../components/Components.js';\nimport { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';\nimport { titleValidator, validateRequiredParameters } from './Assertions.js';\n\nexport class ModalBuilder implements JSONEncodable {\n\tpublic readonly data: Partial;\n\n\tpublic readonly components: ActionRowBuilder[] = [];\n\n\tpublic constructor({ components, ...data }: Partial = {}) {\n\t\tthis.data = { ...data };\n\t\tthis.components = (components?.map((component) => createComponentBuilder(component)) ??\n\t\t\t[]) as ActionRowBuilder[];\n\t}\n\n\t/**\n\t * Sets the title of the modal\n\t *\n\t * @param title - The title of the modal\n\t */\n\tpublic setTitle(title: string) {\n\t\tthis.data.title = titleValidator.parse(title);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the custom id of the modal\n\t *\n\t * @param customId - The custom id of this modal\n\t */\n\tpublic setCustomId(customId: string) {\n\t\tthis.data.custom_id = customIdValidator.parse(customId);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds components to this modal\n\t *\n\t * @param components - The components to add to this modal\n\t */\n\tpublic addComponents(\n\t\t...components: RestOrArray<\n\t\t\tActionRowBuilder | APIActionRowComponent\n\t\t>\n\t) {\n\t\tthis.components.push(\n\t\t\t...normalizeArray(components).map((component) =>\n\t\t\t\tcomponent instanceof ActionRowBuilder\n\t\t\t\t\t? component\n\t\t\t\t\t: new ActionRowBuilder