Discord.js /giveaway命令无控制台报错但无法正常运行求助
问题:Discord抽奖命令弹窗报错且modalData返回undefined
执行自定义的/giveaway抽奖命令时,弹窗顶部显示“Something went wrong. Try again”,控制台输出如下:
Starting giveaway command Showing modal to user Modal data: undefined
已尝试更新Node.js、discord.js至最新版本,问题仍存在。
问题根源
interaction.showModal()仅负责触发模态框展示,不会返回用户提交的模态框数据。原代码错误地将该方法的返回值赋值给modalData,导致其为undefined,后续依赖该数据的逻辑无法执行,最终触发弹窗报错。
正确的做法是使用interaction.awaitModalSubmit()监听用户提交模态框的操作,以此获取用户输入的数据。
修复后的完整代码
const { ActionRowBuilder, ModalBuilder, SlashCommandBuilder, TextInputBuilder, TextInputStyle } = require('discord.js'); module.exports = { data: new SlashCommandBuilder().setName('giveaway').setDescription("Starts a giveaway."), run: async ({ interaction }) => { try { console.log('Starting giveaway command'); const modal = new ModalBuilder() .setCustomId('giveawayModal') .setTitle('Start a Giveaway'); const prizeInput = new TextInputBuilder() .setCustomId('prizeInput') .setLabel("What is the prize for this giveaway?") .setStyle(TextInputStyle.Short) .setRequired(true); // 设为必填,避免用户空提交 const durationInput = new TextInputBuilder() .setCustomId('durationInput') .setLabel("Giveaway duration (in minutes)") .setStyle(TextInputStyle.Short) .setRequired(true); // 设为必填 const firstActionRow = new ActionRowBuilder().addComponents(prizeInput); const secondActionRow = new ActionRowBuilder().addComponents(durationInput); modal.addComponents(firstActionRow, secondActionRow); console.log('Showing modal to user'); // 展示模态框,无返回值 await interaction.showModal(modal); // 监听模态框提交,设置超时时间(10分钟),仅允许命令发起者提交 const submitted = await interaction.awaitModalSubmit({ time: 600000, filter: i => i.user.id === interaction.user.id, }).catch(err => { console.error('Modal submit error:', err); interaction.followUp({ content: 'Giveaway setup timed out or failed.', ephemeral: true }); return null; }); if (!submitted) return; // 通过submitted对象获取用户输入的数据 const prize = submitted.fields.getTextInputValue('prizeInput'); const duration = parseInt(submitted.fields.getTextInputValue('durationInput')) * 60; // 转换为秒 // 校验时长是否为有效数字 if (isNaN(duration)) { return submitted.reply({ content: 'Please enter a valid number for duration.', ephemeral: true }); } const data = { prize, duration }; console.log('Giveaway data:', data); console.log('Starting giveaway'); const announcementMessage = await submitted.channel.send(`The giveaway for "${data.prize}" has started! React with 🎉 to enter. It will end in ${data.duration / 60} minutes.`); await announcementMessage.react('🎉'); await new Promise(resolve => setTimeout(resolve, data.duration * 1000)); const reaction = announcementMessage.reactions.cache.get('🎉'); const users = await reaction.users.fetch(); const participants = users.filter(user => !user.bot).array(); console.log('Participants:', participants); // 处理无参与者的情况 if (participants.length === 0) { return submitted.channel.send('No one entered the giveaway, so there\'s no winner.'); } const winner = participants[Math.floor(Math.random() * participants.length)]; console.log('Winner:', winner); await submitted.channel.send(`Congratulations, ${winner}! You won the "${data.prize}" giveaway! 🎉`); // 回复模态框提交,关闭用户侧的加载状态 await submitted.reply({ content: 'Giveaway started successfully!', ephemeral: true }); } catch (error) { console.error(error); // 全局错误提示 if (interaction.replied || interaction.deferred) { interaction.followUp({ content: 'An error occurred while starting the giveaway.', ephemeral: true }); } else { interaction.reply({ content: 'An error occurred while starting the giveaway.', ephemeral: true }); } } }, };
额外优化说明
- 给输入框添加
setRequired(true),强制用户填写必要信息 - 为
awaitModalSubmit设置超时时间和用户过滤规则,确保操作安全性 - 增加时长合法性校验,避免非数字输入导致后续逻辑崩溃
- 处理无参与者的边界情况,防止报错
- 添加多场景错误提示,让用户明确知晓问题状态
内容的提问来源于stack exchange,提问作者delyrious
相关产品推荐
相关产品推荐

