DiscordJS开发:DM场景下用户角色缓存未自动更新问题求助
问题根因
- discord.js 客户端的本地缓存仅会在服务器侧事件(比如用户发服务器消息、成员更新事件触发)时自动更新,用户发送DM消息不会触发服务器成员数据的缓存同步,因此你通过
.cache获取到的永远是旧的角色数据,必须主动拉取最新数据才能拿到最新的角色配置。
解决方案
1. 开启必要的网关意图
首先在Discord开发者门户的机器人设置页,开启Server Members Intent权限,同时初始化client时要配置对应意图:
const { Client, GatewayIntentBits } = require('discord.js'); const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMessages, GatewayIntentBits.DirectMessages, GatewayIntentBits.MessageContent ] });
2. 每次处理DM消息前主动拉取最新成员数据
不要直接从缓存拿成员,改用fetch方法拉取API最新数据,同时将事件处理改为异步逻辑适配异步fetch操作。修改后的完整代码示例:
// 统一提前配置服务器ID,不用每次事件触发重复获取 const TARGET_SERVER_ID = '替换为你的服务器ID'; client.on('messageCreate', async (msg) => { const server = client.guilds.cache.get(TARGET_SERVER_ID); if (!server) return; // 预拉取所有需要的角色,不用每次事件重复查找 const role1 = server.roles.cache.find(r => r.name === 'role1'); const role2 = server.roles.cache.find(r => r.name === 'role2'); const role3 = server.roles.cache.find(r => r.name === 'role3'); const role4 = server.roles.cache.find(r => r.name === 'role4'); const finalRole = server.roles.cache.find(r => r.name === 'FinalRole'); // 关键:主动拉取最新的成员数据,覆盖旧缓存 let member; try { member = await server.members.fetch(msg.author.id); } catch (e) { // 用户不在目标服务器内直接返回 return; } // 处理!start指令 if (msg.content === "!start") { await msg.author.send("Riddle1"); await member.roles.add(role1); // 加完角色后主动刷新一次成员缓存,保证后续判断用最新数据 await member.fetch(); return; } // 只处理DM消息的答题逻辑 if (msg.channel.type !== 'DM') return; // 判断当前角色走拉取到的最新member对象即可,不用再去缓存重复查询 if (member.roles.cache.some(r => r.name === 'Role1')) { if (msg.content === 'Answer1') { await member.roles.add(role2); await msg.author.send("Riddle2"); await member.fetch(); } } else if (member.roles.cache.some(r => r.name === 'Role2')) { if (msg.content === 'Answer2') { await member.roles.add(role3); await msg.author.send("Riddle3"); await member.fetch(); } } else if (member.roles.cache.some(r => r.name === 'Role3')) { if (msg.content === 'Answer3') { await member.roles.add(role4); await msg.author.send("Riddle4"); await member.fetch(); } } else if (member.roles.cache.some(r => r.name === 'Role4')) { if (msg.content === 'Answer4') { await member.roles.add(finalRole); } } });
3. 额外优化建议
你可以将题目、答案、对应奖励角色做成配置数组,不用写多段重复的if else逻辑,后续维护更方便:
const quizConfig = [ { roleCheck: 'Role1', answer: 'Answer1', awardRole: 'role2', nextRiddle: 'Riddle2' }, { roleCheck: 'Role2', answer: 'Answer2', awardRole: 'role3', nextRiddle: 'Riddle3' }, { roleCheck: 'Role3', answer: 'Answer3', awardRole: 'role4', nextRiddle: 'Riddle4' }, { roleCheck: 'Role4', answer: 'Answer4', awardRole: 'FinalRole', nextRiddle: null } ];
答题逻辑直接遍历这个配置即可,不用重复写判断逻辑。
内容的提问来源于stack exchange,提问作者Aleks
相关产品推荐
相关产品推荐

