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
相关产品推荐
相关产品推荐

