I’m discovering discord.js
library and specifically bot development to myself and I’ve been stuck with an idea I have no clue how to implement so far.
In a verification channel I have a message with a button (customId of which is requestVerification
) which in its turn shows a modal
. The data of the input of this modal is later sent to the requests channel in a form of an embed message
with two buttons
(first one is for approving, second one is for denying).
I want these buttons to directly interact with a user that NOT triggered a button click, but the user who actually filled in the inputs in the modal.
The code looks something like this:
verificationButtonEvent.js
(here I’m showing the modal to a user)
const {
Events, ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, EmbedBuilder, PermissionsBitField
} = require("discord.js");
module.exports = {
name: Events.InteractionCreate, execute(interaction) {
if (!interaction.isButton()) return;
switch (interaction.customId) {
case "requestVerification": {
// create the modal
const verificationModal = new ModalBuilder()
.setCustomId("verificationModal")
.setTitle("");
// verified member role
const verifiedMemberRole = interaction.guild.roles.cache.get("");
// nickname text input
const nicknameInput = new TextInputBuilder()
.setCustomId("nicknameInput")
.setLabel()
.setStyle(TextInputStyle.Short)
.setPlaceholder()
.setMaxLength(35)
.setMinLength(7);
// source text input
const sourceInput = new TextInputBuilder()
.setCustomId("sourceInput")
.setLabel()
.setStyle(TextInputStyle.Paragraph)
.setPlaceholder()
.setMaxLength(150)
.setMinLength(10);
// action rows
const nicknameRow = new ActionRowBuilder().addComponents(nicknameInput);
const sourceRow = new ActionRowBuilder().addComponents(sourceInput);
verificationModal.addComponents(nicknameRow, sourceRow);
// denied verification message
const deniedVerificationMessage = new EmbedBuilder()
.setTitle()
.setDescription()
.setColor(0xf08080)
.setTimestamp()
.setFooter({
text: `${interaction.client.user.username}`, iconURL: `${interaction.client.user.avatarURL()}`,
});
// check if interaction.member is viable to show the modal
if (interaction.member.roles.cache.has(verifiedMemberRole)) {
interaction.reply({embeds: [deniedVerificationMessage], ephemeral: true})
} else if (interaction.member.permissions.has(PermissionsBitField.Flags.ManageRoles) || interaction.member.permissions.has(PermissionsBitField.Flags.Administrator)) {
interaction.reply({embeds: [deniedVerificationMessage], ephemeral: true})
} else {
interaction.showModal(verificationModal);
}
break;
}
}
},
};
verificationModalEvent.js
(here I’m working with a submit of the modal & sending text inputs’ info to the channel)
const {Events, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle} = require("discord.js");
module.exports = {
name: Events.InteractionCreate, async execute(interaction) {
if (!interaction.isModalSubmit()) return;
switch (interaction.customId) {
case "verificationModal": {
// verified member role
const verifiedMemberRole = interaction.guild.roles.cache.get("");
// verification requests channel
const verificationRequestsChannel = interaction.client.channels.cache.get("");
// text inputs
const memberNickname = interaction.fields.getTextInputValue("nicknameInput");
const memberSource = interaction.fields.getTextInputValue("sourceInput");
// message that is shown to the user when submitting the modal
const requestedVerificationEmbed = new EmbedBuilder()
.setTitle()
.setDescription()
.setColor(0xffffb9)
.setTimestamp()
.setFooter({
text: `${interaction.client.user.username}`, iconURL: `${interaction.client.user.avatarURL()}`,
});
// verification request sent to the channel (verificationRequestsChannel)
const requestVerificationEmbed = new EmbedBuilder()
.setTitle()
.setDescription()
.addFields(
{name: "", value: memberNickname, inline: true},
{name: "", value: memberSource, inline: true}
)
.setColor(0xffffb9)
.setTimestamp()
.setFooter({
text: `ID: ${interaction.member.user.id}`, iconURL: `${interaction.client.user.avatarURL()}`,
});
// buttons for approving or denying user's verification
const requestVerificationButtons = new ActionRowBuilder().addComponents(
new ButtonBuilder()
.setCustomId("approveVerification")
.setLabel("Approve")
.setEmoji("✅")
.setStyle(ButtonStyle.Success),
new ButtonBuilder()
.setCustomId("denyVerification")
.setLabel("Deny")
.setEmoji("❎")
.setStyle(ButtonStyle.Danger)
)
await verificationRequestsChannel.send({
embeds: [requestVerificationEmbed],
components: [requestVerificationButtons]
})
// await interaction.member.setNickname(memberNickname);
await interaction.reply({
embeds: [requestedVerificationEmbed], ephemeral: true
})
break;
}
}
}
}
So the question is how to work with new interactions of buttons (approveVerification & denyVerification) by also using the old author that submits the modal? Maybe I’ve done my so called ‘verification system’ completely wrong, not avoiding that possibility, but also keen on learning my mistakes.
2
Answers
Solved this by passing the
interaction.member.user.id
to the embed sent to the verification channel like so:verificationModalEvent.js
Then in the file
verificationCheckEvent.js
I obtain the id from the embed and the message object it's in:verificationCheckEvent.js
I’ve written a similar system in the past for a role application system. I just added the user’s @ into the
author
field of the embed, and then usedmessage.embeds[0].author
to read it later.I can’t test this right now, but here’s another answer that might help.