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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 18:54:05