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

Discord.js频道/角色权限变更审计日志实现求助

看起来你已经把基础的频道更新日志推送搞定了,接下来要处理频道/角色的权限、层级变更这类场景,核心还是围绕审计日志和事件监听来展开,我给你梳理几个具体的开发方向和实现思路:

1. 完善频道变更的细节处理(覆盖权限、层级)

你现有的channelUpdate代码只处理了名称变更,但频道的层级位置、权限规则等变更也需要捕捉。可以通过对比新旧频道对象的属性,再结合审计日志获取执行者和具体变更详情:

const { RichEmbed } = require("discord.js");
const { purple_light } = require("../../colours.json");
module.exports = (bot, oldChannel, newChannel) => {
  const logChannel = oldChannel.guild.channels.find(c => c.id === "687260937744416798");
  if (!logChannel) return;

  // 收集所有变更项
  let changes = [];
  if (oldChannel.name !== newChannel.name) {
    changes.push(`名称: **${oldChannel.name}** → **${newChannel.name}**`);
  }
  if (oldChannel.position !== newChannel.position) {
    changes.push(`层级位置: **${oldChannel.position}** → **${newChannel.position}**`);
  }
  // 对比频道内角色权限规则的变化
  const oldPerms = oldChannel.permissionOverwrites.map(ow => `${ow.id}: ${ow.allow.bitfield}`);
  const newPerms = newChannel.permissionOverwrites.map(ow => `${ow.id}: ${ow.allow.bitfield}`);
  if (JSON.stringify(oldPerms) !== JSON.stringify(newPerms)) {
    changes.push("频道内角色权限规则已更新");
  }

  if (changes.length === 0) return;

  // 同时获取频道基础更新(type:11)和权限更新(type:10)的审计日志
  oldChannel.guild.fetchAuditLogs({ type: [10, 11], limit: 1 })
    .then(audit => {
      const entry = audit.entries.first();
      if (!entry) return;
      const user = entry.executor;

      const logEmbed = new RichEmbed()
        .setAuthor(`频道已更新: ${oldChannel.name}`, user.displayAvatarURL())
        .addField("频道ID", newChannel.id, true)
        .addField("更新者", `${user.tag} (${user.id})`, true)
        .addField("变更内容", changes.join("\n"))
        .setColor(purple_light)
        .setTimestamp();

      // 如果是权限变更,补充具体的权限详情
      if (entry.type === "CHANNEL_OVERWRITE_UPDATE") {
        const extra = entry.extra;
        logEmbed.addField("权限变更详情", 
          `目标角色/用户: ${extra.target.tag || extra.target.id}\n` +
          `新增允许权限: ${extra.allow.toArray().join(", ") || "无"}\n` +
          `新增拒绝权限: ${extra.deny.toArray().join(", ") || "无"}`
        );
      }

      logChannel.send(logEmbed).catch(err => console.error("发送日志失败:", err));
    })
    .catch(err => console.error("获取审计日志失败:", err));
};
2. 新增角色变更事件的监听

针对角色层级、权限的变更,需要单独监听roleUpdate事件,同样结合审计日志实现:

// roleUpdate事件处理文件
const { RichEmbed } = require("discord.js");
const { purple_light } = require("../../colours.json");
module.exports = (bot, oldRole, newRole) => {
  const logChannel = oldRole.guild.channels.find(c => c.id === "687260937744416798");
  if (!logChannel) return;

  let changes = [];
  if (oldRole.name !== newRole.name) {
    changes.push(`名称: **${oldRole.name}** → **${newRole.name}**`);
  }
  if (oldRole.position !== newRole.position) {
    changes.push(`层级位置: **${oldRole.position}** → **${newRole.position}**`);
  }
  // 对比权限差异
  if (!oldRole.permissions.equals(newRole.permissions)) {
    const addedPerms = newRole.permissions.difference(oldRole.permissions).toArray();
    const removedPerms = oldRole.permissions.difference(newRole.permissions).toArray();
    if (addedPerms.length > 0) changes.push(`新增权限: ${addedPerms.join(", ")}`);
    if (removedPerms.length > 0) changes.push(`移除权限: ${removedPerms.join(", ")}`);
  }

  if (changes.length === 0) return;

  oldRole.guild.fetchAuditLogs({ type: 25, limit: 1 })
    .then(audit => {
      const entry = audit.entries.first();
      if (!entry) return;
      const user = entry.executor;

      const logEmbed = new RichEmbed()
        .setAuthor(`角色已更新: ${oldRole.name}`, user.displayAvatarURL())
        .addField("角色ID", newRole.id, true)
        .addField("更新者", `${user.tag} (${user.id})`, true)
        .addField("变更内容", changes.join("\n"))
        .setColor(purple_light)
        .setTimestamp();

      logChannel.send(logEmbed).catch(err => console.error("发送日志失败:", err));
    })
    .catch(err => console.error("获取审计日志失败:", err));
};
3. 用guildAuditLogEntryCreate统一处理所有审计事件

如果想更高效地覆盖所有需要审核的操作(包括频道/角色的创建、删除、变更),可以监听guildAuditLogEntryCreate事件,它会在每次有审计日志条目生成时触发,不用单独监听每个事件:

// guildAuditLogEntryCreate事件处理文件
const { RichEmbed } = require("discord.js");
const { purple_light } = require("../../colours.json");
module.exports = (bot, entry) => {
  const logChannel = entry.guild.channels.find(c => c.id === "687260937744416798");
  if (!logChannel) return;

  // 筛选我们关心的事件类型
  const targetTypes = [
    "CHANNEL_UPDATE", "CHANNEL_OVERWRITE_UPDATE", "ROLE_UPDATE",
    "CHANNEL_CREATE", "CHANNEL_DELETE", "ROLE_CREATE", "ROLE_DELETE"
  ];
  if (!targetTypes.includes(entry.type)) return;

  let embed = new RichEmbed()
    .setAuthor(`审计日志: ${entry.type}`, entry.executor.displayAvatarURL())
    .addField("执行者", `${entry.executor.tag} (${entry.executor.id})`, true)
    .addField("目标ID", entry.target.id, true)
    .setColor(purple_light)
    .setTimestamp();

  // 根据事件类型添加具体内容
  switch(entry.type) {
    case "CHANNEL_UPDATE":
      embed.setTitle(`频道更新: ${entry.target.name}`);
      const channelChanges = entry.changes.map(change => `${change.key}: **${change.old}** → **${change.new}**`);
      embed.addField("变更内容", channelChanges.join("\n"));
      break;
    case "CHANNEL_OVERWRITE_UPDATE":
      embed.setTitle(`频道权限更新: ${entry.target.name}`);
      embed.addField("受影响角色/用户", entry.extra.target.tag || entry.extra.target.id);
      embed.addField("新增允许权限", entry.extra.allow.toArray().join(", ") || "无");
      embed.addField("新增拒绝权限", entry.extra.deny.toArray().join(", ") || "无");
      break;
    case "ROLE_UPDATE":
      embed.setTitle(`角色更新: ${entry.target.name}`);
      const roleChanges = entry.changes.map(change => `${change.key}: **${change.old}** → **${change.new}**`);
      embed.addField("变更内容", roleChanges.join("\n"));
      break;
    case "CHANNEL_CREATE":
      embed.setTitle(`频道创建: ${entry.target.name}`);
      embed.addField("频道类型", entry.target.type);
      break;
    case "CHANNEL_DELETE":
      embed.setTitle(`频道删除: ${entry.target.name}`);
      embed.addField("频道类型", entry.target.type);
      break;
  }

  logChannel.send(embed).catch(err => console.error("发送日志失败:", err));
};
相关资料查询方向
  • 优先查阅Discord.js官方文档中Guild.fetchAuditLogs()方法和AuditLogEntry类的说明,里面详细讲解了审计日志的类型参数、返回结构(比如changes、extra属性的含义)。
  • 查看Discord官方API文档的Audit Log Event Types枚举,里面列出了所有事件类型对应的数字和名称,方便你精准筛选需要监听的操作。
  • 参考Discord.js的事件文档,比如channelUpdate、roleUpdate、guildAuditLogEntryCreate的参数说明,明确每个事件触发的时机和传递的数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 00:29:07