Update message with select menu in Discord.js v14 - javascript

Discord.js Version: 14.6.0
I am currently working with select menu. When I interacted with the menu, supposing there should be edits on the message, and it does. The problem I'm currently having is the reset of the select menu. Every time I have interacted with the menu, the menu itself reset to it default setting.
Expected Output: (Having checkmark on the selected item and with the originally message edited)
Current Output: (Having original message edited but the menu is resetted)
I can only get either replying a new message and then have the menu working fine OR updating the original bot message but a resetted menu bar. Below I'm inserting the code I'm using. Let me know if you need more information.
index.js:
client.on('interactionCreate', async interaction => {
// ... Command Handler here
})
test.js:
const row = new Discord.ActionRowBuilder()
.addComponents(new Discord.SelectMenuBuilder()
.setCustomId('test')
.setPlaceholder('test 1')
.setMinValues(1)
.setMaxValues(1)
.addOptions(
{
label: 'test 1',
value: 'first_option'
},
{
label: 'test 2',
value: 'second_option'
}
))
const testEmbed = new Discord.EmbedBuilder()
.setTitle('Testing')
interaction.reply({ embeds: [testEmbed], components: [row] })
selectMenu.js:
const Embed = new Discord.EmbedBuilder()
.setTitle('Testing 2')
interaction.update({ embeds: [Embed] })
PS: The image of Expected Output is not perfect since I cannot do what I want. Imagine I want an edited message like the second photo and the select menu like the first photo.

You have to set the boolean default on one of the menu options to true, then it will be highlighted.
So if you want to highlight the first option it would be
const row = new Discord.ActionRowBuilder()
.addComponents(new Discord.SelectMenuBuilder()
.setCustomId('test')
.setPlaceholder('test 1')
.setMinValues(1)
.setMaxValues(1)
.addOptions(
{
label: 'test 1',
value: 'first_option',
default: true
},
{
label: 'test 2',
value: 'second_option'
}
)
);
If you would want to highlight the second option it would be
const row = new Discord.ActionRowBuilder()
.addComponents(new Discord.SelectMenuBuilder()
.setCustomId('test')
.setPlaceholder('test 1')
.setMinValues(1)
.setMaxValues(1)
.addOptions(
{
label: 'test 1',
value: 'first_option'
},
{
label: 'test 2',
value: 'second_option',
default: true
}
)
);

Related

Discord Modal with SelectMenu

I'm trying to add a select menu inside a modal (I pretty sure it's possible) but I ended up in this situation and getting this error in the console:
const modal = new client.discord.ModalBuilder()
.setCustomId('verification-modal')
.setTitle('Verify yourself')
.addComponents([
new client.discord.ActionRowBuilder().addComponents(
new client.discord.SelectMenuBuilder()
.setCustomId('t')
.setPlaceholder('Nothing selected')
.addOptions(
{
label: 'Select me',
description: 'This is a description',
value: 'first_option',
},
{
label: 'You can select me too',
description: 'This is also a description',
value: 'second_option',
},
),
new client.discord.TextInputBuilder()
.setCustomId('verification-input')
.setLabel('Answer')
.setStyle(client.discord.TextInputStyle.Short)
.setMinLength(4)
.setMaxLength(12)
.setPlaceholder('ABCDEF')
.setRequired(true),
),
]);
await interaction.showModal(modal);
ode:events:490
throw er; // Unhandled 'error' event
^
DiscordAPIError[50035]: Invalid Form Body
data.components[0].components[0][UNION_TYPE_CHOICES]: Value of field "type" must be one of (4,).
if you have any solution '^^
Only text inputs are supported on modals.
documentation

How to hide or show menu labels in Electron app

I have Electron app and I am trying to hide or show label base on user input. The label aways show. I am trying to hide or show Tutorials
{
id: "tut",
label: "Tutorials",
submenu: [
{
id: "subTut",
label: "Tutorials",
click: async () => {
const { shell } = require("electron");
await shell.openExternal("https://example.app/tutorials");
},
},
],
},
In my main.js process I call the menu
When I call:
Menu.getApplicationMenu().getMenuItemById("tut").visible = false;
it does not hide anything, however it I call
Menu.getApplicationMenu().getMenuItemById("subTut").visible = false;
it will hide the sub menu item
Here is a solution for any that runs across this issue this can be done by using the function
Menu.setApplicationMenu()
Just pass object to the function where you call you menu to handle if item is visible or not
const MenuItems = (options) => {
// MENU
const template = [
{
label: "Window",
submenu: [
{
visible: options.option,
label: "Support",
click: async () => {
await shell.openExternal("https://example.com");
},
},
]
]
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
};
When you run the function for you menu just pass object in function for what's to show.
In Mac OS, you cannot hide top-level menu items, just submenu items:
Nota Bene: The enabled and visibility properties are not available for top-level menu items in the tray on macOS.
Source: docs

Username in embed footer discord bot

I want that the username of the user, who requested the command gets displayed in the footer. I have tried many things, but I dont know how I am supposed to do it.
My code is here:
const exampleEmbed = new Discord.MessageEmbed()
.setColor('#000033')
.setTitle('```Help```')
.setDescription('For more help, type .help (command)')
.addFields(
{ name: '.list', value: 'Opens list of all the achievements' },
{ name: '.profile', value: 'Opens achievement statistics from a member', },
{ name: '.leaderbord', value: 'Opens a leaderbord of the members with most achievements', },
{ name: '.bot', value: 'Opens bot links and information about the bot', },
{ name: '.setup', value: 'Starts the setup of the bot (only for administrators)', }
)
.setTimestamp()
.setFooter("here should the name stand")
client.on("message", (message) => {
if (message.content == ".help") {
message.channel.send(exampleEmbed)
console.log(message.member.user.tag +' executed command .HELP')
}
})
You are looking for .setFooter(message.author.username)
Full Code:
client.on("message", (message) => {
if (message.content == ".help") {
const exampleEmbed = new Discord.MessageEmbed()
.setColor('#000033')
.setTitle('```Help```')
.setDescription('For more help, type .help (command)')
.addFields(
{ name: '.list', value: 'Opens list of all the achievements' },
{ name: '.profile', value: 'Opens achievement statistics from a member', },
{ name: '.leaderbord', value: 'Opens a leaderbord of the members with most achievements', },
{ name: '.bot', value: 'Opens bot links and information about the bot', },
{ name: '.setup', value: 'Starts the setup of the bot (only for administrators)', }
)
.setTimestamp()
.setFooter(message.author.username);
message.channel.send(exampleEmbed)
console.log(message.member.user.tag +' executed command .HELP')
}
})
as mentioned below, you need to put your embed inside the message event listener

Electron (Windows) not showing the menu when tray icon is clicked

Im want to create a tray app, before all Im trying to create a simple icon showing a menu with radios inputs to test Electron tray apps exact how the doc example shows up. But when i click on the icon nothing happening.
const { app, Menu, Tray } = require('electron')
const { resolve } = require('path')
app.on('ready', () => {
createTray()
})
const createTray = () => {
const tray = new Tray(resolve(__dirname, 'assets', 'tray-icon.png'))
const contextMenu = Menu.buildFromTemplate([
{ label: 'Item1', type: 'radio' },
{ label: 'Item2', type: 'radio' },
{ label: 'Item3', type: 'radio', checked: true },
{ label: 'Item4', type: 'radio' }
])
tray.setToolTip('This is my application.')
tray.setContextMenu(contextMenu)
// using this to check if the click event is working
tray.on('click', () => {
console.log('clicked')
})
}
On Windows, the menu normally opens with a right click on the tray icon.
You can also trigger it by using tray.popUpContextMenu() in the click event handler that you have.
tray.on("click", ()=>{
tray.popUpContextMenu();
});

finding an embed created by a bot (discord.js)

This might be a little bit complicated...
I have made on my server a report system, where if a user reacts with an "❗", this message gets reported in a channel only the owner sees. This is my code so far:
client.on("messageReactionAdd", (messageReaction, user) => {
const msg = messageReaction.message;
if (messageReaction.emoji.name == "❗") {
if (messageReaction.count > 1) {
// code missing here
} else {
const embed = new Discord.MessageEmbed()
.setColor("#ff9e00")
.setDescription("§ Report")
.setFooter(`${msg.member.user.tag}`, msg.member.user.displayAvatarURL())
.setTimestamp()
.addFields(
{name: "Message", value: `[${msg.cleanContent}](${msg.url})`, inline: false},
{name: "Amount", value: messageReaction.count, inline: true},
{name: "Channel", value: `${msg.channel.name}`, inline: true});
msg.member.guild.channels.cache.get(config.channels.report).send((embed));
}
};
});
so, everytime someone reports a message, and he was the first one reporting it, my bot will send a new bot, but I want now if a reaction is not the first, I want that the bot edits the according embed, and increases/updates the messageReaction.count.
Anyone an idea how I find the initial message without having a database?
Thanks in advance!
I have modified the code to keep a collection of message IDs from reports that have been sent.
When a report needs to be edited, its ID is fetched from the collection and used to get the actual message, then a new embed is then created from the old embed with the second field incremented. Finally, the message is edited with the new embed containing the incremented field.
client.on("messageReactionAdd", async (messageReaction, user) => {
const msg = messageReaction.message;
if (messageReaction.emoji.name == "❗") {
if (messageReaction.count > 1) {
const message = (await msg.guild.channels.cache.get(config.channels.report).messages.fetch()).find(message => message.embeds[0].fields[3].value === msg.id);
const embed = new Discord.MessageEmbed(message.embeds[0])
.spliceFields(1, 1, {name: "Amount", value: messageReaction.count, inline: true});
message.edit(embed);
} else {
const embed = new Discord.MessageEmbed()
.setColor("#ff9e00")
.setDescription("§ Report")
.setFooter(`${msg.member.user.tag}`, msg.member.user.displayAvatarURL())
.setTimestamp()
.addFields(
{name: "Message", value: `[${msg.cleanContent}](${msg.url})`, inline: false},
{name: "Amount", value: messageReaction.count, inline: true},
{name: "Channel", value: `${msg.channel.name}`, inline: true},
{name: "Message ID", value: msg.id, inline: false});
msg.guild.channels.cache.get(config.channels.report).send(embed);
}
};
});
Here is some extra code if you want to edit reports when the original message gets deleted:
client.on("messageDelete", async (msg) => {
const message = (await msg.guild.channels.cache.get(config.channels.report).messages.fetch()).find(message => message.embeds[0].fields[3].value === msg.id);
if (message) {
const embed = new Discord.MessageEmbed(message.embeds[0])
.spliceFields(0, 1, {name: "Message", value: `[${msg.cleanContent}](*deleted*)`, inline: false})
.spliceFields(3, 1, {name: "Message ID", value: '*deleted*', inline: false})
.setDescription("§ Report\n**The user deleted their message, but here is its content.**");
message.edit(embed);
}
});

Categories

Resources