discord.js v13结合quick.db存储交互频道失败且重复创建频道问题
问题排查与修复方案
核心问题点
- 没有提前校验数据库存储记录,直接先执行频道创建逻辑,导致每次触发交互必然生成新频道
- 数据库存储键规则错误,存储值不符合业务需求:当前存储键绑定的是触发交互的频道ID,值为用户ID,无法实现「校验指定用户是否已创建专属频道」的需求,且db.set返回值恒为存入的值,导致判断永远为真,首次触发也会弹出提示
- 事件监听逻辑括号配对错误,
del按钮的触发判断写在了general交互的判断块内,del按钮事件无法正常触发 MessageActionRow.addComponents参数格式错误,多嵌套了一层数组,按钮组件会加载失败async/await与.then混用,逻辑执行顺序混乱
修复后完整代码
const { MessageButton, MessageActionRow } = require('discord.js'); const db = require('quick.db'); client.on('interactionCreate', async (interaction) => { // 处理general创建频道按钮 if (interaction.customId === "general") { await interaction.deferUpdate(); const userId = interaction.member.id; const guildId = interaction.guild.id; // 先查询当前用户是否已有创建的频道 const savedChannelId = await db.get(`user_channel_${guildId}_${userId}`); // 校验频道是否还存在 if (savedChannelId && interaction.guild.channels.cache.has(savedChannelId)) { // 已有频道直接发提示 return interaction.member.send({ content: `你已创建过专属频道:<#${savedChannelId}>` }).catch(e => console.log(e.message)); } try { // 没有记录/频道已删除,创建新频道 const channel = await interaction.guild.channels.create(`name-${interaction.member.user.username}`, { type: 'GUILD_TEXT' }); // 构造删除按钮 const del = new MessageButton() .setStyle("DANGER") .setLabel("🔒 Delete") .setCustomId("del"); const delbut = new MessageActionRow() .addComponents(del); // 发送频道初始化消息 await channel.send({ content: `test`, // 注意test embed需要提前定义,此处保留原变量 embeds: [test], components: [delbut] }); // 存储用户ID与对应频道ID的绑定关系 await db.set(`user_channel_${guildId}_${userId}`, channel.id); // 给用户发通知 await interaction.member.send({ content: `已为你创建专属频道:<#${channel.id}>` }); } catch (e) { console.log('频道创建失败:', e.message); } } // 处理删除频道按钮 if (interaction.customId === "del") { await interaction.deferUpdate(); const channelId = interaction.channel.id; const guildId = interaction.guild.id; // 删除频道同时删除数据库绑定记录 await interaction.channel.delete().catch(e => console.log(e.message)); // 匹配删除对应用户的存储记录 const allBindings = await db.all(); const targetRecord = allBindings.find(item => item.data === channelId && item.ID.startsWith(`user_channel_${guildId}_`)); if (targetRecord) { await db.delete(targetRecord.ID); } } });
修复点说明
- 新增前置校验逻辑:触发创建按钮后先查询数据库,确认用户无已存在的有效频道再执行创建操作,避免重复生成
- 调整数据库存储规则:键改为绑定服务器ID+用户ID,值存储对应频道ID,可准确匹配用户专属频道
- 修正括号配对问题,将
del按钮的判断逻辑移到外层,保证按钮事件可正常触发 - 修复
MessageActionRow组件参数格式,去掉多余嵌套的数组 - 删除
.then回调,统一用async/await梳理逻辑顺序,避免异步执行混乱 - 新增删除频道后的数据库记录清理逻辑,避免用户删除频道后无法再次创建新频道
内容的提问来源于stack exchange,提问作者Peaky
相关产品推荐
相关产品推荐

