foreverlost
foreverlost

Reputation: 85

Discord.js message user on react for applications

I would like to convert this so that people just need to react and the application gets sent to them, I have no clue on how to do message on react stuff so if anyone could help me out it will be greatly appreciated.

Two very helpful people have helped me

@Skulaurun Mrusal and @PerplexingParadox

Thank you! 🙂

enter image description here

client.on("message", async (message) => {
      // Don't reply to bots
  if (message.author.bot) return;

  if (message.content == "#req") {
         if(!message.member.hasPermission("MANAGE_MESSAGES"))
     {
        message.reply("You do not have permission to do that!");
        return;
     }
    // Perform raw API request and send a message with a button,
    // since it isn't supported natively in discord.js v12
    client.api.channels(message.channel.id).messages.post({
      data: {
        embeds: [reqEmbed],
        components: [
          {
            type: 1,
            components: [
              {
                type: 2,
                style:  4,
                label: "Apply",
                // Our button id, we can use that later to identify,
                // that the user has clicked this specific button
                custom_id: "send_application"
              }
            ]
          }
        ]
      }
    });
  }
});

// Channel id where the application will be sent
const applicationChannelId = "652099170835890177";

// Our questions the bot will ask the user
const questions = [
  "What is your In-Game Username?",
  "How long have you been drifting on FiveM?",
  "Do you use Controller or Keyboard?",
  "How much do you play weekly?",
  "Have you been in any other teams? If so, why did you leave?",
  "Short description about yourself and why you would like to be apart of Blind Spot? (Age, Country)"
];

// Function that will ask a GuildMember a question and returns a reply
async function askQuestion(member, question) {

  const message = await member.send(question);
  const reply = await message.channel.awaitMessages((m) => {
    return m.author.id === member.id;
  }, { time: 5 * 60000, max: 1 });

  return reply.first();

}

client.ws.on("INTERACTION_CREATE", async (interaction) => {

  // If component type is a button
  if (interaction.data.component_type === 2) {

    const guildId = interaction.guild_id;
    const userId = interaction.member.user.id;
    const buttonId = interaction.data.custom_id;
    const member = client.guilds.resolve(guildId).member(userId);

    if (buttonId == "send_application") {

      // Reply to an interaction, so we don't get "This interaction failed" error
      client.api.interactions(interaction.id, interaction.token).callback.post({
        data: {
          type: 4,
          data: {
            content: "I have started the application process in your DM's.",
            flags: 64 // make the message ephemeral
          }
        }
      });

      try {

        // Create our application, we will fill it later
        const application = new MessageEmbed()
          .setTitle("New Application")
          .setDescription(`This application was submitted by ${member.user.tag}`)
          .setColor("#ED4245");

        const cancel = () => member.send("Your application has been canceled.\n**If you would like to start your application again Click on the Apply button in** <#657393981851697153>");
        

        // Ask the user if he wants to continue
        const reply = await askQuestion(member,
          "Please fill in this form so we can proceed with your tryout.\n" +
          "**Type `yes` to continue or type `cancel` to cancel.**"
        );
  
        // If not cancel the process
        if (reply.content.toLowerCase() != "yes") {
          cancel(); return;
        }
  
        // Ask the user questions one by one and add them to application
        for (const question of questions) {
          const reply = await askQuestion(member, question);
          // The user can cancel the process anytime he wants
          if (reply.content.toLowerCase() == "cancel") {
            cancel(); return;
          }
          application.addField(question, reply);
        }
  
           await askQuestion(member,
          "Do you want your application to be submitted?\n" +
          "**Type `yes` to get your Application submitted and reviewed by Staff Members**"
        );
  
        // If not cancel the process
        if (reply.content.toLowerCase() != "yes") {
          cancel(); return;
        }
        // Send the filled application to the application channel
        client.channels.cache.get(applicationChannelId).send(application);

      } catch {
        // If the user took too long to respond an error will be thrown,
        // we can handle that case here.
        member.send(
          "You took too long to respond or Something went wrong, Please contact a Staff member\n" +
          "The process was canceled."
        );
      }

    }

  }

});

Upvotes: 2

Views: 2868

Answers (1)

Skulaurun Mrusal
Skulaurun Mrusal

Reputation: 2837

You could use Client's messageReactionAdd event.

client.on("messageReactionAdd", (reaction, user) => {

    if (!reaction.emoji.name === "👌") return;

    // Check if the message is the right message we want users to react to
    // Obviously you need to enable partials for this to work
    if (reaction.message.id != "...") return;

    const member = reaction.message.guild.member(user);
    member.send("Here's your form!");
    // ... Rest of your code ...

});

Note that this won't work for reactions cast on messages sent before the bot was started. The solution is to enable Partial Structures. (If you are dealing with partial data, don't forget to fetch.)

Or create a ReactionCollector using Message.createReactionCollector().

// ... The variable message defined somewhere ...

const collector = message.createReactionCollector((reaction, user) => {
    return reaction.emoji.name === "👌";
});

collector.on("collect", (reaction, user) => {
    const member = message.guild.member(user);
    member.send("Here's your form!");
    // ... Rest of your code ...
});

Maybe it would be better to use buttons in this case instead of reactions. To create a message with a button you could perform a raw API request or use third party library like discord-buttons. The solution below is for discord.js v12.

client.on("message", async (message) => {

  // Don't reply to bots
  if (message.author.bot) return;

  if (message.content == "#createButton") {
    // Perform raw API request and send a message with a button,
    // since it isn't supported natively in discord.js v12
    client.api.channels(message.channel.id).messages.post({
      data: {
        content: "If you want to apply, click the button below.",
        components: [
          {
            type: 1,
            components: [
              {
                type: 2,
                style: 1,
                label: "Apply",
                // Our button id, we can use that later to identify,
                // that the user has clicked this specific button
                custom_id: "send_application"
              }
            ]
          }
        ]
      }
    });
  }

});

enter image description here

And then we need to listen for an event INTERACTION_CREATE indicating that the user has clicked our button. (Or some other interaction triggered the event, for example a slash command.)

// Channel id where the application will be sent
const applicationChannelId = "871527842180132895";

// Our questions the bot will ask the user
const questions = [
  "What is your In-Game Username?",
  "How long have you been drifting on FiveM?",
  "Do you use Controller or Keyboard?",
  "How much do you play weekly?",
  "Have you been in any other teams? If so, why did you leave?",
  "Short description about yourself and why you would like to be apart of Blind Spot? (Age, Country)"
];

// Function that will ask a GuildMember a question and returns a reply
async function askQuestion(member, question) {

  const message = await member.send(question);
  const reply = await message.channel.awaitMessages((m) => {
    return m.author.id === member.id;
  }, { time: 5 * 60000, max: 1 });

  return reply.first();

}

client.ws.on("INTERACTION_CREATE", async (interaction) => {

  // If component type is a button
  if (interaction.data.component_type === 2) {

    const guildId = interaction.guild_id;
    const userId = interaction.member.user.id;
    const buttonId = interaction.data.custom_id;
    const member = client.guilds.resolve(guildId).member(userId);

    if (buttonId == "send_application") {

      // Reply to an interaction, so we don't get "This interaction failed" error
      client.api.interactions(interaction.id, interaction.token).callback.post({
        data: {
          type: 4,
          data: {
            content: "I have started the application process in your DM's.",
            flags: 64 // make the message ephemeral
          }
        }
      });

      try {

        // Create our application, we will fill it later
        const application = new Discord.MessageEmbed()
          .setTitle("New Application")
          .setDescription(`This application was submitted by ${member.user.tag}`)
          .setColor("#ED4245");

        const cancel = () => member.send("Ok, I have cancelled this process.");

        // Ask the user if he wants to continue
        const reply = await askQuestion(member,
          "Please fill in this form so we can proceed with your tryout.\n" +
          "**Type `yes` to continue or type `cancel` to cancel.**"
        );
  
        // If not cancel the process
        if (reply.content.toLowerCase() != "yes") {
          cancel(); return;
        }
  
        // Ask the user questions one by one and add them to application
        for (const question of questions) {
          const reply = await askQuestion(member, question);
          // The user can cancel the process anytime he wants
          if (reply.content.toLowerCase() == "cancel") {
            cancel(); return;
          }
          application.addField(question, reply);
        }
  
        // Send the filled application to the application channel
        client.channels.cache.get(applicationChannelId).send(application);

      } catch {
        // If the user took too long to respond an error will be thrown,
        // we can handle that case here.
        member.send(
          "Something went wrong or you took too long to respond.\n" +
          "The process was cancelled."
        );
      }

    }

  }

});

Upvotes: 2

Related Questions