【问题标题】:Discord.js | Buttons doesn't work after bot restarts不和谐.js |机器人重启后按钮不起作用
【发布时间】:2021-07-17 17:57:30
【问题描述】:

按钮在执行命令后工作,但在重新启动机器人并按下按钮后,它显示interaction failed Here's my ticket.js

const { MessageButton } = require('discord-buttons');

module.exports = {
    name: 'ticket-setup',
    aliases: ['close'],
    category: 'Miscellaneous',
    description: 'Makes a ticket embed',
    async execute(message, args, cmd, client, Discord){

        if(!message.member.permissions.has("MANAGE_CHANNELS")) return message.reply("Normies can't do this command")

        if (cmd == 'close') {
            if (!message.channel.name.includes('ticket-')) return message.channel.send('You cannot use that here!');
            message.channel.delete();
           }
       
        let title;
        let desc;
        let ticketMsg;

        const filter = msg => msg.author.id == message.author.id;
        let options = {
            max: 1
        };
    
        message.channel.send("What will the ticket title be?\nSay cancel to cancel")
        let col = await message.channel.awaitMessages(filter, options)
        if(col.first().content == 'cancel') return message.channel.send("Cancelled");
        title = col.first().content
    
        message.channel.send('What will the description be?\nSay cancel to cancel')
        let col2 = await message.channel.awaitMessages(filter, options)
        if(col2.first().content == 'cancel') return message.channel.send("Cancelled");
        desc = col2.first().content
        
        message.channel.send('What is the message that the user will see when they make a ticket?\nSay cancel to cancel')
        let col3 = await message.channel.awaitMessages(filter, options)
        if(col3.first().content == 'cancel') return message.channel.send("Cancelled");
        ticketMsg = col3.first().content

        const setupEmbed =  new Discord.MessageEmbed()
        .setTitle(title)
        .setDescription(desc)
        .setFooter(message.guild.name, message.guild.iconURL({ dynamic: true }))
        .setColor('00f8ff')

        const hiEmbed = new Discord.MessageEmbed()
        .addField(ticketMsg, "\n\nDo a.close or press the button to close the ticket")
        .setColor("RANDOM")
        .setTimestamp()
        
        const createTicketButton = new MessageButton()
        .setID("ticketCreate")
        .setStyle("blurple")
        .setLabel("????");

        const closeTicketButton = new MessageButton()
        .setID("ticketClose")
        .setLabel("Close ticket")
        .setStyle("red");



        if(cmd == 'ticket-setup'){ 
        message.channel.send({embed: setupEmbed, button: createTicketButton })      
        }

           client.on('clickButton', async (button) => {
            await button.clicker.fetch();
            await button.reply.defer();
               const user = button.clicker.user
            if (button.id === 'ticketCreate') {
              button.guild.channels.create(`ticket-${user.id}`,  {
                permissionOverwrites: [
                 {
                  id: user.id,
                  allow: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
                 },
                 {
                  id: button.message.guild.roles.everyone,
                  deny: ['VIEW_CHANNEL'],
                 },
                ],
                type: 'text',
               }).then(async (channel) =>{
                   channel.send({embed: hiEmbed, button: closeTicketButton })
               })
            } else if(button.id == 'ticketClose'){
                button.message.channel.delete()
            }
          });
    }
}

我使用包discord-buttonsDocs link

我尝试将 clickButton 事件放在我的事件处理程序中,但它没有工作,因为我得到了很多错误。重启后如何让按钮仍然工作?

【问题讨论】:

  • 使用事件处理程序/侦听器是按钮在重新启动后工作的唯一方法,因为按钮收集器和 awaitButtons 在重新启动时都会停止侦听。你最好尝试解决你的错误而不是避免它。

标签: javascript node.js discord discord.js discord-buttons


【解决方案1】:

问题

在您的机器人重新启动后您的按钮无法正常工作的原因是因为您的 client.on("clickButton") 事件处理程序您的“ticket-setup”命令的代码中。这意味着只有在机器人重新启动后使用 ticket-setup 命令,或者换句话说,在机器人启动后对该文件调用 execute() 时,才会设置您的事件。

想一想:在调用 ticket-setup 命令的 execute() 函数之前,不会到达您的 client.on("clickButton") 代码。这会给您带来多个问题。首先,如上所述,在机器人启动后至少使用一次ticket-setup 之前,甚至不会处理clickButton 事件。其次,这将在每次使用命令时创建一个额外的事件处理程序。换句话说,如果您使用ticket-setup 命令两次或更多次,您的clickButton 处理程序中的代码将在每次单击按钮时执行不止一次(在您的特定场景中,每次按钮点击会创建不止一张票)。

解决方案

您面临的问题有一个非常简单的解决方案。您只需将整个clickButton 事件处理程序移出execute() 方法。也许将它移动到您的主要server.jsbot.js 文件中,以及您的client.on("ready")client.on("message") 事件处理程序。这将确保 clickButton 事件处理程序只设置一次,并且在机器人启动时立即设置。

但是,请注意,您确实需要对您的 clickButton 事件处理程序进行一些细微的添加,以确保其正常工作。您需要将 hiEmbedcloseTicketButton 的代码移动到您的 client.on("clickButton") 处理程序中。

根据您问题中的代码,这可能是server.js 中的样子:

client.on('clickButton', async (button) => {        
    await button.clicker.fetch();
    await button.reply.defer();
    const user = button.clicker.user;

    const hiEmbed = new Discord.MessageEmbed()
    .addField(ticketMsg, "\n\nDo a.close or press the button to close the ticket")
    .setColor("RANDOM")
    .setTimestamp();

    const closeTicketButton = new MessageButton()
    .setID("ticketClose")
    .setLabel("Close ticket")
    .setStyle("red");

    if (button.id === 'ticketCreate') {
        button.guild.channels.create(`ticket-${user.id}`,  {
            permissionOverwrites: [
            {
                id: user.id,
                allow: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
            },
            {
                id: button.message.guild.roles.everyone,
                deny: ['VIEW_CHANNEL'],
            },
            ],
            type: 'text',
        }).then(async (channel) =>{
            channel.send({embed: hiEmbed, button: closeTicketButton })
        })
    } else if(button.id == 'ticketClose'){
        button.message.channel.delete()
    }
});

您可能已经注意到另一个问题:ticketMsg 变量将不会被定义。您还需要进行更改以解决该问题。我建议将ticketMsg 的值保存到JSON 文件或数据库中,并在client.on("clickButton") 中访问该信息。如果此代码代表正确的票务系统,无论您是否使用此解决方案,您都需要执行此操作,否则您的用户将需要使用 ticket-setup 再次设置票务系统每次您的机器人重新启动时.

【讨论】:

  • 这正是我所做的。我将 clickButton 事件移至我的事件处理程序,并将 ticketMsg 保存到数据库中,现在它工作正常,也感谢您的解释并让我更好地理解!
【解决方案2】:

我也遇到过这个问题,但不是交互失败,而是按钮信息不完整。

client.ws.on('INTERACTION_CREATE', interaction => {
//complete interaction
})

按钮是触发这个的交互,你可以用interaction.data.custom_id检查这是一个斜杠命令还是按钮(这可能是错误的,我无法测试它)。如果不是按钮,它将是未定义的,但如果是按钮,它将保存按钮的自定义 id。

【讨论】:

  • 我应该把它放在我的事件处理程序还是命令文件中?我必须添加什么?我尝试了 Squidleton 的建议,即使在重新启动后它也确实有效,只是它返回 ticketMsg 为未定义或其他内容
  • 而不是 client.on('clickButton' 替换它
  • 有两点需要注意。 A)按钮和选择菜单交互都使用custom_id,所以这个答案也会触发选择菜单(如果 OP 也想使用选择菜单,这可能会导致错误)。区分斜杠命令、按钮和选择菜单的最佳方法是使用interaction.data.component_type,它专门用于区分这些。按钮的组件类型是2,所以只要检查它是否等于2。B)如果你看discord-buttons的代码,这个事件处理程序正是它用来为clickButton供电的东西。
猜你喜欢
  • 2021-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 2020-11-18
  • 2019-02-14
  • 2021-02-19
相关资源
最近更新 更多