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

Roblox与Discord频道ID变量存值异常:点击保存返回undefined

解决Discord机器人频道ID存储后点击保存返回undefined的问题

你的核心问题是每次交互都是独立的函数调用:用户选择频道、点击保存这两个操作会分别触发两次函数执行,而你定义的roblox和discord是函数内部的局部变量,每次调用都会重新初始化,之前选择的频道ID根本无法跨交互保留,所以点击保存时自然拿到的是undefined。

针对这个问题,给你两个可行的解决方案:

方案1:利用服务器对象临时存储(简单直接)

把临时选择的频道ID存在guild对象的自定义属性里,因为同一个服务器的所有交互都会复用这个guild实例,能临时保存数据直到保存完成:

const { EmbedBuilder } = require('discord.js');
const config = require('../../schemas/configuration');

module.exports = async (interaction, guild) => {
    // 初始化临时存储结构,避免重复创建
    if (!guild.tempLogChannels) {
        guild.tempLogChannels = { roblox: null, discord: null };
    }

    if (interaction.customId === 'discord_logs') {
        guild.tempLogChannels.discord = interaction.values[0];
        await interaction.reply({ content: `该频道将在保存后接收日志。`, ephemeral: true });
        console.log(guild.tempLogChannels.discord);
    }

    if (interaction.customId === 'roblox_logs') {
        guild.tempLogChannels.roblox = interaction.values[0];
        await interaction.reply({ content: `该频道将在保存后接收日志。`, ephemeral: true });
        console.log(guild.tempLogChannels.roblox);
    }

    if (interaction.customId === 'setup_save') {
        const { roblox, discord } = guild.tempLogChannels;
        await interaction.reply({ content: `已更新日志频道:Roblox(${roblox})、Discord(${discord})`, ephemeral: true });
        
        // 这里添加将数据保存到数据库的逻辑
        await config.findOneAndUpdate(
            { guildId: guild.id },
            { robloxLogChannel: roblox, discordLogChannel: discord },
            { upsert: true }
        );
        
        // 保存完成后可以清空临时数据,避免残留
        delete guild.tempLogChannels;
    }
};

方案2:用数据库暂存中间状态(适合多服务器/持久化场景)

如果你的机器人需要跨重启保留中间选择状态,可以在用户选择频道时先把数据临时存入数据库,点击保存时再读取并正式更新:

const { EmbedBuilder } = require('discord.js');
const config = require('../../schemas/configuration');

module.exports = async (interaction, guild) => {
    // 先获取当前服务器的配置(临时状态也存在这里)
    let guildConfig = await config.findOne({ guildId: guild.id });
    if (!guildConfig) {
        guildConfig = new config({ guildId: guild.id });
    }

    if (interaction.customId === 'discord_logs') {
        guildConfig.tempDiscordLog = interaction.values[0];
        await guildConfig.save();
        await interaction.reply({ content: `该频道将在保存后接收日志。`, ephemeral: true });
        console.log(guildConfig.tempDiscordLog);
    }

    if (interaction.customId === 'roblox_logs') {
        guildConfig.tempRobloxLog = interaction.values[0];
        await guildConfig.save();
        await interaction.reply({ content: `该频道将在保存后接收日志。`, ephemeral: true });
        console.log(guildConfig.tempRobloxLog);
    }

    if (interaction.customId === 'setup_save') {
        const roblox = guildConfig.tempRobloxLog;
        const discord = guildConfig.tempDiscordLog;
        await interaction.reply({ content: `已更新日志频道:Roblox(${roblox})、Discord(${discord})`, ephemeral: true });
        
        // 正式更新配置并清空临时状态
        guildConfig.robloxLogChannel = roblox;
        guildConfig.discordLogChannel = discord;
        guildConfig.tempRobloxLog = null;
        guildConfig.tempDiscordLog = null;
        await guildConfig.save();
    }
};

另外,你提到之前用数组存储时会被覆盖,大概率是因为直接用数组索引赋值(比如arr[0] = robloxId、arr[0] = discordId),应该用键值对对象来区分两个频道ID,就像上面方案里的tempLogChannels结构,这样就不会出现覆盖问题。

内容的提问来源于stack exchange,提问作者shara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:19:53