I have been trying to make a slash command with subcommand that sends message to specified channel.
When i try to deploy it, i get:
DiscordAPIError[50035]: Invalid Form Body
options[1][APPLICATION_COMMAND_OPTIONS_TYPE_INVALID]: Sub-command and sub-command group option types are mutually exclusive to all other types
at SequentialHandler.runRequest (D:\projs\cpp\tbot\node_modules\#discordjs\rest\dist\index.js:659:15)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async SequentialHandler.queueRequest (D:\projs\cpp\tbot\node_modules\#discordjs\rest\dist\index.js:458:14)
at async REST.request (D:\projs\cpp\tbot\node_modules\#discordjs\rest\dist\index.js:902:22)
at async D:\projs\cpp\tbot\deploy-commands.js:24:16 {
requestBody: { files: undefined, json: [ [Object], [Object] ] },
rawError: {
code: 50035,
errors: { options: [Object] },
message: 'Invalid Form Body'
},
code: 50035,
status: 400,
method: 'PUT',
url: 'https://discord.com/api/v10/applications/752621311494455367/guilds/1039125828790919240/commands'
}
My code:
const { SlashCommandBuilder } = require('discord.js');
const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
module.exports = {
data: new SlashCommandBuilder()
.setName('say')
.setDescription('Make bot say anything the executor wants')
.addSubcommand(subcommand =>
subcommand
.setName('channel')
.setDescription('Says ')
.addChannelOption(option =>
option
.setName('target_channel')
.setDescription('Channel to send message in.')
.setRequired(true)))
.addStringOption(option =>
option
.setName('text')
.setDescription("Message to be sent in specified channel")
.setRequired(true)),
async execute(interaction) {
const channel = interaction.options.getChannel('target_channel');
const text = interaction.options.getString('text');
client.channels.cache.get(channel).send(text);
},
};
I have no clue about it. I didn't find anything about it anywhere. I expected it to deploy the commands via node deploy-commands.js but it resulted in error above.
The error is emitted when you attempt to add an option to a command which also has a subcommand. To illustrate this better I've create an ascii table, note how channel and text options are on the same level, which would result in an error.
say
|- channel: SUB_COMMAND
| |- name: STRING
| |- target_channel: TEXTCHANNEL
|- text: STRING
| |- option: STRING
If I've interpreted your code correctly you may want to add the string option to the subcommand, as so:
data: new SlashCommandBuilder()
.setName('say')
.setDescription('Make bot say anything the executor wants')
.addSubcommand(subcommand =>
subcommand
.setName('channel')
.setDescription('Says ')
.addStringOption(option =>
option
.setName('text')
.setDescription("Message to be sent in specified channel")
.setRequired(true)
)
.addChannelOption(option =>
option
.setName('target_channel')
.setDescription('Channel to send message in.')
.setRequired(true)
)
)
Related
the code says invalid bitfield and has no idea how to fix it, the intents are fine I think and I think everything should be normal. i have tried to combine code from a bot from a snippet someone sent, maybe thats why this doesnt work
code :
const { Client, Intents, Message} = require('discord.js');
const util = require('minecraft-server-util');
const {EmbedBuilder} = require('discord.js');
const options = {
timeout: 1000 * 5,
enableSRV: true
};
const prefix = "!mcstatus";
const client = new Client({
intents: [
"Guilds",
"GuildMessages",
"MessageContent"
]
});
client.on('ready', () => {
console.log('bot started');
client.user.setPresence({ activities: [{ name: `${server_ip}`, type: 'WATCHING' }], status: 'active' });
});
const server_ip = "mc.hypixel.net";
const server_port = 25565;
client.on('messageCreate', (message) => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
if(message.content.startsWith(prefix)){
util.status(server_ip, server_port, options)
.then((result) => {
const embed = new EmbedBuilder()
let args = message.content.split(" "); // Splitting with a blank space.
args = args.slice(1); // Remove the first argument which would be the command itself.
const server_port = 25565; // Leave the default port for MC servers.
if (args.length < 1) return message.reply("Didn't provide arguments.")
// Run a forEach loop for every argument.
args.forEach((arg) => {
util
.status(arg, server_port, options)
.then((result) => {
const embed = new EmbedBuilder()
.setColor("#FF0000")
.setTitle("Results")
.setDescription(
`This will show the status and info about the minecraft server \n **Server ip:** ${arg} \n **Server port:** ${server_port}`
)
.addFields(
{ name: "Server Version", value: `${result.version.name}` },
{
name: "Server Protocol Version",
value: `${result.version.protocol}`,
},
{ name: "Players Online", value: `${result.players.online}` },
{ name: "Max Players", value: `${result.players.max}` },
{
name: "MOTD (May Not Display Accurately)",
value: `${result.motd.clean}`,
},
{ name: "Latency", value: `${result.roundTripLatency}` }
)
.setTimestamp();
message.channel.send({ embeds: [embed] });
})
.catch((error) => {
const embed = new EmbedBuilder()
.setColor("#808080")
.setTitle("Error")
.setDescription(
`${arg} was unable to be pinged or you mis-typed the info`
)
.setTimestamp();
message.channel.send({ embeds: [embed] });
});
});
message.channel.send({embeds: [embed]})
})}});
log i have tried to google things but i couldnt find anything that helps my thing
RangeError [BITFIELD_INVALID]: Invalid bitfield flag or number: Guilds.
at Intents.resolve (C:\Users\jason\Desktop\discord minecraft bot test 2\node_modules\discord.js\src\util\BitField.js:152:11)
at C:\Users\jason\Desktop\discord minecraft bot test 2\node_modules\discord.js\src\util\BitField.js:147:54
at Array.map (<anonymous>)
at Intents.resolve (C:\Users\jason\Desktop\discord minecraft bot test 2\node_modules\discord.js\src\util\BitField.js:147:40)
at Client._validateOptions (C:\Users\jason\Desktop\discord minecraft bot test 2\node_modules\discord.js\src\client\Client.js:550:33)
at new Client (C:\Users\jason\Desktop\discord minecraft bot test 2\node_modules\discord.js\src\client\Client.js:76:10)
at Object.<anonymous> (C:\Users\jason\Desktop\discord minecraft bot test 2\index.js:9:16)
at Module._compile (node:internal/modules/cjs/loader:1159:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
at Module.load (node:internal/modules/cjs/loader:1037:32) {
[Symbol(code)]: 'BITFIELD_INVALID'
}
Node.js v18.12.1
PS C:\Users\jason\Desktop\discord minecraft bot test 2>
First of all, please see the guide on how to use intents. (It's really useful!)
This doesn't look like DJSv14 code either. v14 snippets can be found in the guide as well.
To fix your issue you can change the way you define your intents when instantiating your new client like so;
const { GatewayIntentBits } = require('discord.js');
// ...
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
],
});
OT: Newer D.JS versions have application commands, I highly recommend you use those instead of prefix commands!
discord js v13.3.1
I have a set up with my bot that allows me to update and push slash commands via a command, deploy. The deploy command looks like this:
module.exports = {
name: "deploy",
description: "deploys slash commands",
disabled: false,
async execute(interaction, args, client) {
if (interaction.author.id !== process.env.OWNERID) return interaction.reply('You must be the owner to use this!');
const cmds = client.commands
.filter(command => command.slash)
.map(command => {
let {
name,
description = "missing description",
options = [],
slash = false,
defaultPermission = true,
slashPermissions = [],
} = command;
if (typeof name === "string") name = [name];
const cmd = { name: name[0], description, options, defaultPermission, permissions: slashPermissions };
return cmd;
});
await setCommands(interaction.guild?.commands)
.then(interaction.reply(`Registered ${cmds.length} commands to this guild!`));
async function setCommands(commandManager) {
const appCommands = await commandManager.set(
commandManager?.guild ? cmds : cmds.filter(cmd => !cmd.permissions.length)
);
if (commandManager?.guild) {
const fullPermissions = appCommands
.map(appCommand => {
const permissions = cmds.find(cmd => cmd.name === appCommand.name).permissions;
return { id: appCommand.id, permissions };
})
.filter(appCommand => appCommand.permissions.length);
await commandManager.permissions.set({ fullPermissions });
}
}
}
}
I stopped work on my bot awhile back, and now am trying to update the rest of my commands to have slash functionality. I have slash commands registered to my guild, so this command has worked in the past as is. Now, when I try to deploy my slash commands, I am getting this error in my console:
main\node_modules\discord.js\src\managers\ApplicationCommandManager.js:246
options: command.options?.map(o => ApplicationCommand.transformOption(o)),
^
TypeError: command.options?.map is not a function
at Function.transformCommand (main\node_modules\discord.js\src\managers\ApplicationCommandManager.js:246:33)
at main\node_modules\discord.js\src\managers\ApplicationCommandManager.js:163:48
at Array.map (<anonymous>)
at GuildApplicationCommandManager.set (main\node_modules\discord.js\src\managers\ApplicationCommandManager.js:163:22)
at setCommands (main\commands\admin\deploy.js:34:54)
at Object.execute (main\commands\admin\deploy.js:29:19)
at module.exports (main\events\guild\messageCreate.js:28:51)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
For reference, my commands are built as such:
module.exports = {
name: "move",
description: "Move all users from one vc to another",
usage: `\`${process.env.PREFIX}move <vc1> <vc2>\``,
alias: ["mv"],
disabled: false,
slash: true,
options: [
{
name: 'target',
type: 'CHANNEL',
channelTypes: ['GUILD_VOICE'],
description: 'Channel to move users from',
required: true
},
{
name: 'destination',
type: 'CHANNEL',
channelTypes: ['GUILD_VOICE'],
description: 'Channel to move users into',
required: true
}
],
permission: ['MOVE_MEMBERS'],
async execute(interaction, args){
}
}
Is this an issue with how I am building my options blocks in my commands themselves, or how I am parsing them to send to guildCommandManager? I'm assuming the former because the error is a TypeError, but I am historically bad at working with maps and objects, so I could be wrong, and it's hard for me to figure out since the error is being thrown from the djs module and not my code itself
Just use the rest method which you can view the code of it here on the discord.js guide.
https://discordjs.guide/creating-your-bot/creating-commands.html#command-deployment-script
You can create global commands with: applicationCommands
and create local commands for 1 server with: applicationGuildCommands
In attempt to create slash commands in Discord.JS V14 following the official guide, I came across the following error:
DiscordAPIError[50035]: Invalid Form Body
0[LIST_TYPE_CONVERT]: Only iterables may be used in a ListType
The specific command (ping) that I would like to create doesn't have any additional options as it's a very basic command and simply is just unethical to add any options.
ping.js:
module.exports = {
name: "ping",
description: "View the reaction times",
slashInfo: {
enabled: true,
public: false,
},
getSlashInfo: function() {
const { SlashCommandBuilder } = require("discord.js");
const builder = new SlashCommandBuilder();
// Set basic command information
builder.setName(this.name);
builder.setDescription(this.description);
// If the command can be used in DMs
builder.setDMPermission(true);
// Return the information in JSON format
return builder.toJSON();
},
async execute(interaction, _prefix, client) {
interaction.reply({ content: `**Pong** in ${client.ws.ping}ms` });
}
}
commandHandler.js:
function postSlashCommand(data, to, client) {
if (!to) {
// Post command to all guilds
rest.put(
Routes.applicationCommands(client.user.id),
{ body: data }
);
} else {
// Post command for use only in a specific server
rest.put(
Routes.applicationGuildCommands(client.user.id, to),
{ body: data }
);
}
}
async function setupSlashCommands(directory, client) {
// Loop through known command files
const commandFolders = fs.readdirSync(`./${directory}`).filter(file => !file.endsWith(".js") && !file.endsWith(".json"));
for (const folder of commandFolders) {
const commandFiles = fs.readdirSync(`./${directory}/${folder}`).filter(file => file.endsWith(".js"));
for (const file of commandFiles) {
// Find the command object
const command = require(`../../${directory}/${folder}/${file}`);
// Ensure the command supports slash
if (!command.slashInfo?.enabled) return;
// Get the slash data
let data = command.getSlashInfo();
// Post the command to Discord
if (command.slashInfo.public) { // If the slash command is public
// Post command to all guilds
postSlashCommand(data, null, client);
} else { // If the slash command is in testing
// Post command for use only in the dev server
postSlashCommand(data, require("../../utils/config.json").DevServer, client);
}
}
}
}
module.exports = (client) => setupSlashCommands("commands", client);
Full error:
throw new DiscordAPIError.DiscordAPIError(data, "code" in data ? data.code : data.error, status, method, url, requestData);
^
DiscordAPIError[50035]: Invalid Form Body
0[LIST_TYPE_CONVERT]: Only iterables may be used in a ListType
at SequentialHandler.runRequest (D:\Projects\...\node_modules\#discordjs\rest\dist\lib\handlers\SequentialHandler.cjs:287:15)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async SequentialHandler.queueRequest (D:\Projects\...\node_modules\#discordjs\rest\dist\lib\handlers\SequentialHandler.cjs:99:14)
at async REST.request (D:\Projects\...\node_modules\#discordjs\rest\dist\lib\REST.cjs:52:22) {
rawError: {
code: 50035,
errors: {
_errors: [
{
code: 'LIST_TYPE_CONVERT',
message: 'Only iterables may be used in a ListType'
}
]
},
message: 'Invalid Form Body'
},
code: 50035,
status: 400,
method: 'PUT',
url: 'https://discord.com/api/v10/applications/<application_id>/guilds/<guild_id>/commands',
requestBody: {
files: undefined,
json: {
options: [],
name: 'ping',
name_localizations: undefined,
description: 'View the reaction times',
description_localizations: undefined,
default_permission: undefined,
default_member_permissions: undefined,
dm_permission: true
}
}
}
Is there any way to simply create a slash command without providing the options property?
That endpoint takes an array of application commands. Instead of attempting to put a single command at a time, put all of them at once. Add the data to an array, then you will register them
const globalCommands = [],
guildCommands = [];
// Loop through known command files
const commandFolders = fs.readdirSync(`./${directory}`).filter(file => !file.endsWith(".js") && !file.endsWith(".json"));
for (const folder of commandFolders) {
const commandFiles = fs.readdirSync(`./${directory}/${folder}`).filter(file => file.endsWith(".js"));
for (const file of commandFiles) {
const command = require(`../../${directory}/${folder}/${file}`);
// Ensure the command supports slash
if (!command.slashInfo?.enabled) return;
// Add the slash data to the array
if (command.slashInfo.public) globalCommands.push(command.getSlashInfo());
else guildCommands.push(command.getSlashInfo())
}
}
Afterward, simply put the commands, and with what I see, you want to do global and guild commands, separately
postSlashCommand(guildCommands, require("../../utils/config.json").DevServer, client)
postSlashCommand(globalCommands, null, client)
Repository (code): https://github.com/JavascriptLearner815/spelta-discord-bot/tree/development
I am creating a Discord bot with Discord.js. I wanted to add three DM commands for the bot:
dm, reply, and followup.
In order to reply to the last DM, I needed to use SQLITE. I made and required a database.js file to do that, using the discord.js guide for SQLite. But when I run the command dm, the table isn't even created!
My code editor does in fact show the files database.js and database.sqlite.
I have also tried using node database.js.
In Discord, I get the messages from my alt and my main account, but it replies to my interaction with "Error! Either you or the recipient have disabled DMs!" This is actually my message that gets sent with a catch.
What could be the problem here?
P.S. If you prefer viewing the code right here on StackOverflow, here it is:
commands/dm.js:
const { SlashCommandBuilder } = require("#discordjs/builders")
const { DirectMessages } = require("../database")
module.exports = {
data: new SlashCommandBuilder()
.setName("dm")
.setDescription("Directly messages a user!")
.addUserOption(option =>
option
.setRequired(true)
.setName("user")
.setDescription("The user to message"))
.addStringOption(option =>
option
.setRequired(true)
.setName("message")
.setDescription("The message to send")),
async execute(interaction) {
const user = interaction.options.getUser("user")
const message = interaction.options.getString("message")
try {
await user.send(`**${interaction.user.tag} sent a message:** ${message}`)
await interaction.user.send(`**Sent ${user.tag} a message:** ${message}`)
await DirectMessages.create({
message,
from: interaction.user.id,
to: user.id,
})
interaction.reply({ content: "Successfully sent your message!", ephemeral: true })
}
catch (error) {
console.error(error)
interaction.reply({ content: "Error! Either the recipient or yourself has disabled DMs!", ephemeral: true })
}
},
}
database.js:
const Sequelize = require("sequelize")
const sequelize = new Sequelize("database", "user", "password", {
host: "localhost",
dialect: "sqlite",
logging: false,
// SQLite only
storage: "database.sqlite",
})
const DirectMessages = sequelize.define("dms", {
message: Sequelize.TEXT,
from: Sequelize.STRING,
to: Sequelize.STRING,
})
module.exports = {
sequelize,
DirectMessages,
}
await sequelize.sync({ force: true });
console.log("All models were synchronized successfully.");
you should check Sequelize Synchronizing all model
I've been working on a command which will make the bot exchange currency.
Here is the code:
const {
Client,
Intents,
DiscordAPIError,
Permissions,
Emoji
} = require('discord.js');
const {
MessageEmbed
} = require('discord.js');
const fetch = require("node-fetch");
const client = new Client({
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES]
});
const prefix = '-';
client.once('ready', () => {
console.log('Floppa is online!');
client.user.setActivity("-help", {});
client.user.set
});
client.on('message', message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(" ");
const command = args.shift().toLocaleLowerCase();
const api_url = 'https://free.currconv.com/api/v7/convert?q=USD_ILS,ILS_USD&compact=ultra&apiKey=xxxxxxxxxxxx';
async function getCurrencyILS()
{
const response = await fetch(api_url);
const data = await response.json();
message.channel.send(data.USD_ILS);
}
async function getCurrencyUSD()
{
const response = await fetch(api_url);
const data = await response.json();
message.channel.send(data.ILS_USD);
}
//Exchanges currency from USD to ILS, currently working on it!
if(command == 'excusdils'){
getCurrencyILS();
}
//Exchanges currency from ILS to USD, currently working on it!
if(command == 'excilsusd'){
getCurrencyUSD();
}
for some reason when I send the command there is some sort of an error:
C:\Users\amare\Desktop\DiscordBot\node_modules\discord.js\src\rest\RequestHandler.js:349
throw new DiscordAPIError(data, res.status, request);
^
DiscordAPIError: Cannot send an empty message
at RequestHandler.execute (C:\Users\amare\Desktop\DiscordBot\node_modules\discord.js\src\rest\RequestHandler.js:349:13)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async RequestHandler.push (C:\Users\amare\Desktop\DiscordBot\node_modules\discord.js\src\rest\RequestHandler.js:50:14)
at async TextChannel.send (C:\Users\amare\Desktop\DiscordBot\node_modules\discord.js\src\structures\interfaces\TextBasedChannel.js:172:15) {
method: 'post',
path: '/channels/923881113955500115/messages',
code: 50006,
httpStatus: 400,
requestData: {
json: {
content: undefined,
tts: false,
nonce: undefined,
embeds: undefined,
components: undefined,
username: undefined,
avatar_url: undefined,
allowed_mentions: undefined,
flags: undefined,
message_reference: undefined,
attachments: undefined,
sticker_ids: undefined
},
files: []
}
}
Thing is, whenever I run this code in the console, it works perfectly (when I change the code inside the function from message.channel.send(data.USD_ILS) to console.log(data.USD_ILS).
Why does that happen?
As far as I know. When I use something like MongoDB (or another external API). It will output the result to a JSON Format. Not a string. So in order to send it to a channel. You must convert it to a string.
Example :
Discord JS v12 :
message.channel.send(data.USD_ILS.toString());
Discord JS v13 :
message.channel.send({ content: data.USD_ILS.toString() });
The reason why it works with console.log() is because it was automatically converted to the format that console understand.
Tell me if its work or not.