You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord Bot嵌入消息返回undefined问题求助

Discord Bot Embed Variables Showing "undefined" After Modal & Select Menu Interaction

我刚仔细看了你的代码和问题截图,发现两个核心问题导致变量显示undefined,咱们一步步来解决:

问题根源

1. 变量作用域不匹配

你在模态框提交的回调里定义了ginputdata和sinputdata,但这两个变量是该回调函数的局部变量。当用户后续选择下拉菜单时,触发的是另一个独立的回调函数,根本访问不到之前定义的这两个变量,自然就显示undefined了。

2. 重复绑定全局监听器

每次运行sendspielersuche命令,你的代码都会给client添加新的interactionCreate监听器。这会导致后续的交互被多次处理,不仅逻辑混乱,还会浪费资源。

解决方案:用临时存储+独立交互收集器

推荐用Map来存储用户的临时输入(避免全局变量被多用户操作覆盖),同时改用MessageComponentCollector替代全局监听器,每个交互链都是独立的一次性监听。

修改后的完整代码如下:

const Discord = require('discord.js')
const Command = require('../../structures/CommandClass');
const { stripIndents } = require('common-tags');
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, TextInputStyle, StringSelectMenuBuilder, Events, ModalBuilder, TextInputBuilder } = require('discord.js');

module.exports = class spielersuche extends Command {
    constructor(client) {
        super(client, {
            data: new SlashCommandBuilder()
                .setName('sendspielersuche')
                .setDescription('Sende das Spielersuche Embed')
                .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers)
                .setDMPermission(false),          
        });
    }
        
    async run(client, interaction) {
        const member = await interaction.member.fetch();
        const anfragechannelID = '889302458906591344';
        const anfragechannel = member.guild.channels.cache.get(anfragechannelID);
        const createanfragechannelID = '1061113274130772058';
        const createanfragechannel = member.guild.channels.cache.get(createanfragechannelID);
   
        // 用来临时存储用户输入的Map,键是用户ID,值是输入的理由和游戏
        const userTempData = new Map();

        // 平台选择下拉菜单
        const platformMenu = new ActionRowBuilder()
            .addComponents(
                new StringSelectMenuBuilder()
                    .setCustomId('pfmenü')
                    .setPlaceholder('Plattform auswählen')
                    .addOptions(
                        { label: 'PS4', value: 'ps4' },
                        { label: 'PS5', value: 'ps5' },
                        { label: 'PS4/PS5', value: 'ps4ps5' },
                        { label: 'PC', value: 'pc' },
                        { label: 'Switch', value: 'switch' },
                        { label: 'Alle', value: 'alle' },
                    ),
            );

        // 游戏和理由输入模态框
        const requestModal = new ModalBuilder()
            .setCustomId('minput')
            .setTitle('Spielersuche 🔎');

        const gameInput = new TextInputBuilder()
            .setCustomId('spielinput') 
            .setLabel("Für welches Spiel?")
            .setPlaceholder('GTA5, Fortnite, Call of Duty, Minecraft ...')
            .setStyle(TextInputStyle.Short)
            .setMinLength(2)
            .setMaxLength(20)
            .setRequired(true);

        const reasonInput = new TextInputBuilder()
            .setCustomId('grundinput')         
            .setLabel("Der Grund der Anfrage?")   
            .setPlaceholder('Beispiel: Suche Spieler für Cayo Perico Heist.') 
            .setStyle(TextInputStyle.Short)
            .setMinLength(10)
            .setMaxLength(60)
            .setRequired(true);
        
        const gameRow = new ActionRowBuilder().addComponents(gameInput);
        const reasonRow = new ActionRowBuilder().addComponents(reasonInput);
        requestModal.addComponents(gameRow, reasonRow);

        // 主Embed和触发按钮
        const mainEmbed = new EmbedBuilder()
            .setTitle(`Spieler suchen Spieler 🔎`)
            .setColor('#00ff0c')
            .setDescription(stripIndents`Drücke auf denn Button um eine Spielersuche Anzufragen!`)
            .setFooter({ text: 'YANKEEUNIT91 COMMUNITY'})
            .setTimestamp();
        
        const requestButton = new ActionRowBuilder()
            .addComponents(
                new ButtonBuilder()
                    .setCustomId('buttonanfrage')
                    .setEmoji('🔎')
                    .setLabel('Spielersuche Anfragen')
                    .setStyle(ButtonStyle.Success),
            );

        // 发送主Embed到指定频道
        const sentMainMsg = await createanfragechannel.send({ embeds: [mainEmbed], components: [requestButton] });
        await interaction.reply({ content: 'Spielersuche Embed wurde versendet!', ephemeral: true });

        // 监听按钮点击(一次性收集器,避免全局监听器重复绑定)
        const buttonCollector = sentMainMsg.createMessageComponentCollector({
            filter: i => i.customId === 'buttonanfrage' && i.user.id !== client.user.id,
            time: 86400000 // 24小时后自动过期
        });

        buttonCollector.on('collect', async buttonInt => {
            // 打开模态框
            await buttonInt.showModal(requestModal);

            // 监听模态框提交
            const modalCollector = buttonInt.channel.createModalSubmitCollector({
                filter: modalInt => modalInt.customId === 'minput' && modalInt.user.id === buttonInt.user.id,
                time: 300000 // 5分钟未提交则过期
            });

            modalCollector.on('collect', async modalInt => {
                // 获取用户输入的理由和游戏
                const userReason = modalInt.fields.getTextInputValue('grundinput');
                const userGame = modalInt.fields.getTextInputValue('spielinput');
                
                // 把数据存到Map里,用用户ID做键
                userTempData.set(modalInt.user.id, { reason: userReason, game: userGame });

                // 回复用户让其选择平台
                await modalInt.reply({ content:'**Wähle deine Plattform!**', components: [platformMenu], ephemeral: true });

                // 监听平台下拉菜单选择
                const selectCollector = modalInt.channel.createMessageComponentCollector({
                    filter: selectInt => selectInt.customId === 'pfmenü' && selectInt.user.id === modalInt.user.id,
                    time: 300000 // 5分钟未选择则过期
                });

                selectCollector.on('collect', async selectInt => {
                    const selectedPlatform = selectInt.values.join(', ');
                    // 从Map里取出当前用户的输入数据
                    const userData = userTempData.get(selectInt.user.id);

                    // 容错处理:如果没找到数据就提示错误
                    if (!userData) {
                        return await selectInt.reply({ content: 'Fehler: Keine Eingabedaten gefunden! Bitte starte die Anfrage neu.', ephemeral: true });
                    }

                    // 构建最终的Embed
                    const finalEmbed = new EmbedBuilder()
                        .setTitle(`${userData.reason}`)
                        .setColor('#00ff0c')
                        .setFooter({ text: 'YANKEEUNIT91 COMMUNITY'})
                        .setTimestamp()
                        .addFields(
                            {
                                name: '**Spiel:**',
                                value: `${userData.game}`,
                                inline: true,
                            },
                            {
                                name: `**Plattform:**`,
                                value: `${selectedPlatform}`,
                                inline: false,
                            },
                        );
                    
                    // 更新用户的回复,发送最终Embed到指定频道
                    await selectInt.update({ content:'**Spielersuche erfolgreich Angefragt!**', components: [], ephemeral: true });
                    await anfragechannel.send({ content: `**Anfrage von:** <@${selectInt.user.id}>`, embeds: [finalEmbed] });

                    // 从Map里删除已处理的数据,释放内存
                    userTempData.delete(selectInt.user.id);
                });
            });
        });
    }
};

核心改进说明

  1. 解决作用域问题:用Map存储每个用户的输入数据,确保下拉菜单回调能精准获取到当前用户的理由和游戏信息,不会出现undefined。
  2. 避免重复监听器:改用MessageComponentCollector和ModalSubmitCollector,每个交互链都是独立的一次性监听,不会因为多次运行命令而堆积监听器。
  3. 并发安全:每个用户的数据单独存储,多个用户同时操作时不会互相覆盖数据。
  4. 容错处理:增加了数据不存在时的错误提示,提升用户体验。
  5. 内存优化:用户完成操作后自动删除临时数据,避免内存浪费。

直接替换你原代码中的run函数部分,测试后应该就能解决变量显示undefined的问题了。

内容的提问来源于stack exchange,提问作者Marc-Anthony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 17:36:10