Mateo-tem / discord-modals

discord-modals is a package that allows your bot of discord.js v13 to create the new Discord Modals and interact with them.
https://www.npmjs.com/package/discord-modals
MIT License
92 stars 28 forks source link

[discord-modals] SHOW_MODAL_ERROR #8

Closed snxraven closed 2 years ago

snxraven commented 2 years ago

Hello There :)

First of all, I love this work, great job!

I have the modal working and I am able to use the information submitted from the form and process it perfectly.

However, this does only work error log free on the first run, on any other runs, I see this, the interesting thing is, the functionality still works, the form still pops up the information is still sent to my api as coded but this error is reported in my bots log:

[discord-modals] SHOW_MODAL_ERROR: An error occurred when showing a modal. DiscordAPIError: Interaction has already been acknowledged.
    at RequestHandler.execute (/home/CodeBoard/node_modules/discord.js/src/rest/RequestHandler.js:350:13)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async RequestHandler.push (/home/CodeBoard/node_modules/discord.js/src/rest/RequestHandler.js:51:14)
    at async showModal (/home/CodeBoard/node_modules/discord-modals/src/structures/ShowModal.js:18:9) {
  method: 'post',
  path: '/interactions/THESTINRG/callback',
  code: 40060,
  httpStatus: 400,
  requestData: { json: { type: 9, data: [Object] }, files: [] }
}
            const discordModals = require('discord-modals') // Define the discord-modals package!
            const { Modal, TextInputComponent, showModal } = require('discord-modals') // Now we extract the showModal method
            discordModals(client); // Provide the client to the discord-modals package

            let titleCompontent = new TextInputComponent() // We create an Text Input Component
              .setCustomId('title') // We set the customId to title
              .setLabel('Title Name Here')
              .setStyle('SHORT') //IMPORTANT: Text Input Component Style can be 'SHORT' or 'LONG'
              .setMinLength(4)
              .setMaxLength(15)
              .setPlaceholder('Write a text here')
              .setRequired(true) // If it's required or not
              .setValue('value')

            let descCompontent = new TextInputComponent() // We create an Text Input Component
              .setCustomId('desc') // We set the customId to title
              .setLabel('Description')
              .setStyle('LONG') //IMPORTANT: Text Input Component Style can be 'SHORT' or 'LONG'
              .setMinLength(4)
              .setMaxLength(250)
              .setPlaceholder('Write a text here')
              .setRequired(true) // If it's required or not
              .setValue('value')

            let components = [titleCompontent, descCompontent]
            console.log(components)

            const modal = new Modal() // We create a Modal
              .setCustomId('title')
              .setTitle('Task Information')
              .addComponents(components);

            showModal(modal, {
              client: client, // The showModal() method needs the client to send the modal through the API.
              interaction: interaction // The showModal() method needs the interaction to send the modal with the Interaction ID & Token.
            })

            client.on('modalSubmit', (modal) => {
              if (modal.customId === 'title') {
                (async () => {

                  const title = modal.getTextInputValue('title')
                  const desc = modal.getTextInputValue('desc')
                  var Request = http.post('https://' + process.env.ROOT_DOMAIN + '/jsonrpc.php').headers({ Accept: 'application/json', 'Content-Type': 'application/json' }).send({
                    "jsonrpc": "2.0",
                    "method": "createTask",
                    "id": 1176509098,
                    "params": {
                      "owner_id": userID,
                      "creator_id": userID,
                      "date_due": "",
                      "description": desc,
                      "category_id": 0,
                      "score": 0,
                      "title": title,
                      "project_id": projectID,
                      "color_id": "yellow",
                      "column_id": 0,
                      "recurrence_status": 0,
                      "recurrence_trigger": 0,
                      "recurrence_factor": 0,
                      "recurrence_timeframe": 0,
                      "recurrence_basedate": 0
                    }
                  });

                  // Begin the request and send authenication using the jsonrpc2.0 protocol.
                  Request.auth({
                    user: 'jsonrpc',
                    pass: process.env.API_KEY,
                    sendImmediately: false
                  }).then(function (response) {
                    console.log(response.body)
                  })

                  await modal.reply({ content: 'Task Created!', components: [] });

                })()
            I am not sure if I am doing something wrong in the this or the rest of my code or if the library may be having an issue.
Mateo-tem commented 2 years ago

¡Thanks to report the issue!

Actually, that error is not of Discord-Modals, but the error (Discord API Error) says that the interaction has already been acknowledged. That means, that interaction has already been deferred. I think you put interaction.deferReply() right? If not, please tell me.

snxraven commented 2 years ago

I did have that, however, if I remove this it still is an issue, I am looking at my code further to see if its my issue instead of bugging you and if I cannot find anything I will provide as much info as possible.

Mateo-tem commented 2 years ago

Oh ok, I'll wait for it.

snxraven commented 2 years ago

If this is helpful to you, this is the commands code: (HasteBin Link) https://r-bin.ssh.surf/amovutahal.js

I am also using https://github.com/AnIdiotsGuide/guidebot and their slash command handler

I will continue to look into it aswell

Mateo-tem commented 2 years ago

Uh, I don't find the error. I recommend you to put your modalSubmit event in an Event Handler or on index.js. That can work.

snxraven commented 2 years ago

@Mateo-tem Ohhhh I see, Thank you. You do bring a very valid point, I will continue to code this out and see how it goes.

Mateo-tem commented 2 years ago

No problem :)

snxraven commented 2 years ago

Ok, so more trying here, I am seeing odd behavior.

Currently, I am trying this with the ping command, the command itself has no code in it:

exports.run = async (client, interaction) => { // eslint-disable-line no-unused-vars
  // await interaction.deferReply();
  // const reply = await interaction.editReply("Ping?");
  // await interaction.editReply(`Pong! Latency is ${reply.createdTimestamp - interaction.createdTimestamp}ms. API Latency is ${Math.round(client.ws.ping)}ms.`);

}

exports.commandData = {
  name: "ping",
  description: "Pongs when pinged.",
  options: [],
  defaultPermission: true,
};

// Set guildOnly to true if you want it to be available on guilds only.
// Otherwise false is global.
exports.conf = {
  permLevel: "User",
  guildOnly: false
};

This is the interactionCreate.js as I have implemented your example:

https://r-bin.ssh.surf/korojumedu.typescript

Here is the bot log attempting to run the example:

https://r-bin.ssh.surf/ibidawufej.yaml

You can see in the first run everything runs smooth and I do get the proper reply in discord.

However, the second run of the command, modalSubmit is being called multiple times.

You can see the command handler is not calling the command more than the single time when the command is being ran.

As you can see here both replies are sent to discord, but the errors and the odd loop is concerning:

https://ssh.surf/works.png

It is very odd and I am not too sure I understand this behavior

If you are able to spot what I may be doing wrong it would be amazing xD

Mateo-tem commented 2 years ago

Oh, I have not been able to discover the error. I don't know where to put it, but a return would be nice.

snxraven commented 2 years ago

To allow while trying to figure this out ive done:

              count = count + 1
              if (count != 1) return
              if (count == 1) {
          within modalSubmit this still runs a ton of times but only really sends to the API once, its a gross bandaid to whatever issue there is
Mateo-tem commented 2 years ago

Oh ok.

snxraven commented 2 years ago

Sadly, I worked for a while and was unable to find any other way to resolve the issue besides using the above count to only allow a single request from ModalSubmit.

Not too sure what the issue is adding a return anywhere in the code wont work because the module is calling ModalSubmit so many times.

I may look into this further as some point

Mateo-tem commented 2 years ago

Uh, you can put your modalSubmit event on index.js? That can work, or I don't know.