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

如何解决Discord中fetchAuditLogs语音操作日志合并计数问题

解决Discord审计日志合并导致的用户断开/移动操作跟踪问题

问题分析

Discord会在5分钟内合并同一管理员的重复断开/移动操作,仅显示累计计数,这导致仅通过fetchAuditLogs({limit:1})只能获取合并后的条目,无法捕捉每一次单独操作。以下是两种可行的解决思路:


方法1:跟踪审计日志条目的计数变化

通过缓存最近的审计日志条目,每次触发voiceStateUpdate时对比最新条目与缓存的计数差异,以此识别合并操作的次数。

代码示例:

// 缓存每个服务器的最近审计日志信息(键:guildId,值:{entryId, count, timestamp})
const auditLogCache = new Map();

client.on('voiceStateUpdate', async (voiceOld, voiceNew) => {
  // 跳过无意义的状态变更(如静音/取消静音)
  if (!voiceOld.channel || (voiceNew.channel && voiceOld.channel.id === voiceNew.channel.id)) return;

  const guild = voiceOld.guild;
  // 获取最新的断开操作审计日志
  const auditLogs = await guild.fetchAuditLogs({ limit: 1, type: "MEMBER_DISCONNECT" });
  const latestEntry = auditLogs.entries.first();
  if (!latestEntry) return;

  const cacheKey = guild.id;
  const cachedEntry = auditLogCache.get(cacheKey);

  if (cachedEntry && cachedEntry.entryId === latestEntry.id) {
    // 同一合并条目,计数有新增
    const countDiff = latestEntry.extra.count - cachedEntry.count;
    if (countDiff > 0) {
      console.log(`管理员 ${latestEntry.executor.tag} 新增断开了 ${countDiff} 位用户,累计:${latestEntry.extra.count}`);
    }
  } else {
    // 新的操作条目
    console.log(`管理员 ${latestEntry.executor.tag} 断开了 ${latestEntry.extra.count} 位用户`);
  }

  // 更新缓存并设置5分钟过期(匹配Discord的合并窗口)
  auditLogCache.set(cacheKey, {
    entryId: latestEntry.id,
    count: latestEntry.extra.count,
    timestamp: Date.now()
  });
  setTimeout(() => auditLogCache.delete(cacheKey), 5 * 60 * 1000);
});

方法2:结合voiceStateUpdate事件本身统计操作

每次用户断开或移动频道都会触发voiceStateUpdate,可以直接在事件中判断状态变化,再通过审计日志验证操作是否由管理员发起,以此统计每一次操作。

代码示例:

client.on('voiceStateUpdate', async (voiceOld, voiceNew) => {
  let actionType = null;
  // 判断操作类型:断开或移动
  if (voiceOld.channel && !voiceNew.channel) {
    actionType = "MEMBER_DISCONNECT";
  } else if (voiceOld.channel && voiceNew.channel && voiceOld.channel.id !== voiceNew.channel.id) {
    actionType = "MEMBER_MOVE";
  }
  if (!actionType) return;

  const guild = voiceOld.guild;
  const auditLogs = await guild.fetchAuditLogs({ limit: 1, type: actionType });
  const latestEntry = auditLogs.entries.first();
  if (!latestEntry) return;

  // 验证操作是否为管理员发起(时间差判断避免误匹配)
  const timeDiff = Date.now() - latestEntry.createdTimestamp;
  if (timeDiff < 5000) {
    console.log(`管理员 ${latestEntry.executor.tag} 对用户 ${voiceOld.member.tag} 执行了${actionType === "MEMBER_DISCONNECT" ? "断开语音" : "移动频道"}操作`);
  }
});

注意事项

  • 确保机器人拥有VIEW_AUDIT_LOGS权限,否则无法获取审计日志。
  • 方法1中的缓存过期时间建议设置为5分钟,与Discord的日志合并窗口一致,避免无效缓存干扰判断。
  • 方法2中的时间差判断可根据实际情况调整,避免因网络延迟导致的误匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 00:40:19