Discord Bot模态框获取输入值报错TypeError求助
Discord.js v14:模态框获取输入值时TypeError问题解决
错误原因
你遇到的TypeError: Cannot read properties of undefined (reading 'getTextInputValue'),核心问题是混淆了Slash命令交互对象和模态框提交交互对象:
- 模态框的输入字段数据只存在于
awaitModalSubmit返回的交互对象中,而你试图从原Slash命令的interaction.options里获取,原交互的options根本没有fields属性,所以报错。
代码问题分析
- 用
.then(interaction => ...)处理模态框提交时,覆盖了原interaction变量,但后续代码依然错误地使用原Slash命令的交互对象获取数据。 - 未处理频道选项的默认值:如果用户没选择频道,
options.get('channel')会返回null,解构channel会报错。 - 回复逻辑混乱:原交互已经用来显示模态框,后续应该用模态框提交的交互对象进行回复操作。
修正后的完整代码
const {SlashCommandBuilder, EmbedBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder} = require('discord.js'); module.exports = { data: new SlashCommandBuilder() .setName('embed-create') .setDescription('everything with embeds') .addStringOption(option => option.setName('title').setDescription('set the title for the embed').setRequired(true)) .addStringOption(option => option.setName('color').setDescription('set color for your embed (6-digit hex, no #)').setMaxLength(6).setRequired(true)) .addStringOption(option => option.setName('thumbnail').setDescription('set thumbnail for your embed').setRequired(false)) .addStringOption(option => option.setName('image').setDescription('set image for your embed').setRequired(false)) .addChannelOption(option => option.setName('channel').setDescription('which channel should it be send to').setRequired(false)), async execute(interaction) { // 创建模态框 const modal = new ModalBuilder() .setCustomId('creating') .setTitle('Nowy Embed'); const desc = new TextInputBuilder() .setCustomId('a') .setLabel("Write Description here") .setStyle(TextInputStyle.Paragraph) .setPlaceholder("ex. sth went to school"); const secondActionRow = new ActionRowBuilder().addComponents(desc); modal.addComponents(secondActionRow); // 显示模态框 await interaction.showModal(modal); // 等待模态框提交,获取模态框交互对象 const modalInteraction = await interaction.awaitModalSubmit({ time: 60_000 }); await modalInteraction.reply({content: "Let's see", ephemeral: true}); // 从原Slash命令交互获取参数 const {options} = interaction; const title = options.getString('title'); const color = options.getString('color'); const thumbnail = options.getString('thumbnail'); const image = options.getString('image'); // 处理频道默认值:没选则用当前命令所在频道 const targetChannel = options.getChannel('channel') || interaction.channel; // 验证图片链接 if (image && !image.startsWith('https')) { await modalInteraction.followUp({content:"Your image cannot be used! Use a link starting with https.", ephemeral: true}); return; } if (thumbnail && !thumbnail.startsWith('https')) { await modalInteraction.followUp ({content:"Your thumbnail cannot be used! Use a link starting with https.", ephemeral: true}); return; } // 从模态框交互对象获取描述 const description = modalInteraction.fields.getTextInputValue('a'); // 创建Embed const embed = new EmbedBuilder() .setTitle(title) .setDescription(description) .setColor(`#${color}`) .setThumbnail(thumbnail) .setImage(image); await modalInteraction.followUp({content:"Your embed has been sent below", ephemeral: true}); await targetChannel.send({ embeds:[embed] }); } }
关键修改点
- 分离交互对象:用
modalInteraction存储awaitModalSubmit返回的模态框提交交互对象,和原Slash命令的interaction区分开。 - 正确获取模态框输入:从
modalInteraction.fields.getTextInputValue('a')获取描述内容,这是模态框输入数据的正确存储位置。 - 处理频道默认值:用
options.getChannel('channel') || interaction.channel确保targetChannel永远有有效值,避免报错。 - 统一回复对象:所有后续回复操作都使用
modalInteraction,因为原交互已经完成了显示模态框的操作。 - 优化颜色提示:在命令选项描述里明确提示用户输入不带#的6位十六进制颜色值,避免格式问题。
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

