skip to Main Content

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


  1. Chosen as BEST ANSWER

    Solved this by passing the interaction.member.user.id to the embed sent to the verification channel like so:

    verificationModalEvent.js

    // request verification embed
    const requestVerificationEmbed = new EmbedBuilder()
        .setTitle(``)
        .setDescription(``)
        .addFields({}, {})
        .setColor(0xffffb9)
        .setTimestamp()
        .setFooter({
            text: `${interaction.member.user.id}`, <—— *this is where I get the user ID*
            iconURL: interaction.member.user.displayAvatarURL()
        });
    

    Then in the file verificationCheckEvent.js I obtain the id from the embed and the message object it's in:

    verificationCheckEvent.js

    const userId = interaction.message.embeds[0].data.footer.text;
    

  2. 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 used message.embeds[0].author to read it later.

    I can’t test this right now, but here’s another answer that might help.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search