Discord.js交互问卷报错:无法读取null的createMessageCollector属性
问题分析与修复方案
核心错误原因
interaction.channel为空值:用户在DM中点击GBAStart按钮时,interaction.channel无法正确获取DM频道对象,导致调用createMessageCollector时抛出空值读取错误。- 未定义变量引用:
GBAStart分支中使用的message.author.id属于messageCreate事件的局部变量,此处无法访问,会导致消息过滤逻辑失效。 - 收集器停止条件错误:原代码中
counter == questions.length + 1的判断会导致多等待一次无效回复,应该在所有问题发送完毕后立即停止收集器。
修复后的完整代码
// Main requirements const { CHANNEL_SSU, CHANNEL_ROLESEL, BOT_PREFIX, ROLE_DEV } = require('../../config.json') const commandName = 'gba' // Optional Requirements const { MessageEmbed, MessageActionRow, MessageButton, MessageCollector } = require('discord.js') // Main Code module.exports = client => { client.on('messageCreate', async message => { if (message.author.bot) return; if (!message.content.toLowerCase().startsWith(BOT_PREFIX)) return; const command = message.content.split(' ') const args = message.content.substring(1).split(' ') if (command.toString().toLowerCase().replace(BOT_PREFIX, '').startsWith(commandName)) { if (!message.member.roles.cache.has(ROLE_DEV)) return message.reply("Only Developers can use this command!") const buttonsRow1 = new MessageActionRow().addComponents( new MessageButton() .setCustomId('GBAempty1') .setLabel(' ') .setStyle('SECONDARY') .setDisabled(true), new MessageButton() .setCustomId('GBA') .setLabel('Appeal') .setStyle('DANGER') .setDisabled(false), new MessageButton() .setCustomId('GBAempty2') .setLabel(' ') .setStyle('SECONDARY') .setDisabled(true) ) const GBAEmbed = new MessageEmbed() .setTitle('Appeal Your Game Ban!') .setColor('DARK_BLUE') .setFooter({ text: 'ASRP | System Bot' }) .setThumbnail(message.guild.iconURL({ dynamic: true, size: 512 })) message.delete() message.channel.send({ embeds: [GBAEmbed], components: [buttonsRow1] }) } }) client.on(`interactionCreate`, async (interaction) => { if (!interaction.isButton) return if (interaction.customId == 'GBA') { await interaction.deferReply({ ephemeral: true }) const appealEmbed = new MessageEmbed() .setTitle(`Started Appeal.`) .setDescription(`Please check your DM for the appeal.`) .setFooter({ text: 'ASRP | System Bot' }) .setTimestamp() .setColor('ORANGE') await interaction.editReply({ embeds: [appealEmbed], ephemeral: true }) const user = interaction.user; const buttonsRow2 = new MessageActionRow().addComponents( new MessageButton() .setCustomId('GBAempty3') .setLabel(' ') .setStyle('SECONDARY') .setDisabled(true), new MessageButton() .setCustomId('GBAStart') .setLabel('Appeal') .setStyle('DANGER') .setDisabled(false), new MessageButton() .setCustomId('GBAempty4') .setLabel(' ') .setStyle('SECONDARY') .setDisabled(true) ) const GBAstart = new MessageEmbed() .setTitle(`Start Appeal.`) .setDescription(`Press 'Start' to start appealing your game ban.`) .setFooter({ text: 'ASRP | System Bot' }) .setThumbnail(interaction.guild.iconURL({ dynamic: true, size: 512 })) await user.send({ embeds: [GBAstart], components: [buttonsRow2] }) } if (interaction.customId == 'GBAStart') { await interaction.deferReply({ ephemeral: true }); await interaction.editReply("Appeal started! Check your DM for questions."); const questions = [ "How old are you?", "How are you?", "What time is it for you?" ] let counter = 0 const targetUser = interaction.user; const dmChannel = await targetUser.createDM(); const filter = m => m.author.id === targetUser.id; const collector = dmChannel.createMessageCollector({ filter, time: 1000 * 1200, max: questions.length }); await dmChannel.send(questions[counter++]); collector.on('collect', (m) => { if (counter < questions.length) { m.reply(questions[counter++]); } if (counter === questions.length) { collector.stop(); } }); collector.on('end', collected => { console.log(`Collected ${collected.size} messages`); if (collected.size < questions.length) { dmChannel.send("You didn't answer in time, please restart the appeal."); return; } let counter = 0; collected.forEach((value) => { console.log(questions[counter++], value.content); }); }); } }) }
关键修复点说明
- 获取有效DM频道:使用
interaction.user.createDM()确保获取到可用的DM频道对象,彻底解决interaction.channel为空的问题。 - 修正过滤逻辑:用
interaction.user.id替代未定义的message.author.id,保证只收集目标用户的回复。 - 调整收集器停止时机:将停止条件改为
counter === questions.length,确保所有问题回复完成后立即终止收集。 - 优化交互提示:点击
GBAStart后明确告知用户查看DM,提升操作体验。
内容的提问来源于stack exchange,提问作者Hamoodi youtube
相关产品推荐
相关产品推荐

