3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-05-10 20:35:02 +00:00

feat: add member cache; handle all role changes with RoleManagerPlugin; exit gracefully

This commit is contained in:
Dragory 2023-05-07 17:56:55 +03:00
parent fd60a09947
commit fa50110766
No known key found for this signature in database
GPG key ID: 5F387BA66DF8AAC1
48 changed files with 755 additions and 264 deletions

View file

@ -8,7 +8,7 @@ import { LogType } from "../../data/LogType";
import { logger } from "../../logger";
import { makeIoTsConfigParser, mapToPublicFn } from "../../pluginUtils";
import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
import { createTypedTemplateSafeValueContainer, TypedTemplateSafeValueContainer } from "../../templateFormatter";
import { TypedTemplateSafeValueContainer, createTypedTemplateSafeValueContainer } from "../../templateFormatter";
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { LogsChannelCreateEvt, LogsChannelDeleteEvt, LogsChannelUpdateEvt } from "./events/LogsChannelModifyEvts";
@ -40,6 +40,7 @@ import { onMessageUpdate } from "./util/onMessageUpdate";
import { escapeCodeBlock } from "discord.js";
import { InternalPosterPlugin } from "../InternalPoster/InternalPosterPlugin";
import { LogsGuildMemberRoleChangeEvt } from "./events/LogsGuildMemberRoleChangeEvt";
import { logAutomodAction } from "./logFunctions/logAutomodAction";
import { logBotAlert } from "./logFunctions/logBotAlert";
import { logCaseCreate } from "./logFunctions/logCaseCreate";
@ -173,6 +174,7 @@ export const LogsPlugin = zeppelinGuildPlugin<LogsPluginType>()({
LogsStickerCreateEvt,
LogsStickerDeleteEvt,
LogsStickerUpdateEvt,
LogsGuildMemberRoleChangeEvt,
],
public: {

View file

@ -0,0 +1,58 @@
import { APIRole, AuditLogChange, AuditLogEvent } from "discord.js";
import { guildPluginEventListener } from "knub";
import { resolveRole } from "../../../utils";
import { logMemberRoleAdd } from "../logFunctions/logMemberRoleAdd";
import { logMemberRoleRemove } from "../logFunctions/logMemberRoleRemove";
import { LogsPluginType } from "../types";
type RoleAddChange = AuditLogChange & {
key: "$add";
new: Array<Pick<APIRole, "id" | "name">>;
};
function isRoleAddChange(change: AuditLogChange): change is RoleAddChange {
return change.key === "$add";
}
type RoleRemoveChange = AuditLogChange & {
key: "$remove";
new: Array<Pick<APIRole, "id" | "name">>;
};
function isRoleRemoveChange(change: AuditLogChange): change is RoleRemoveChange {
return change.key === "$remove";
}
export const LogsGuildMemberRoleChangeEvt = guildPluginEventListener<LogsPluginType>()({
event: "guildAuditLogEntryCreate",
async listener({ pluginData, args: { auditLogEntry } }) {
// Ignore the bot's own audit log events
if (auditLogEntry.executorId === pluginData.client.user?.id) {
return;
}
if (auditLogEntry.action !== AuditLogEvent.MemberRoleUpdate) {
return;
}
const member = await pluginData.guild.members.fetch(auditLogEntry.targetId!);
const mod = await pluginData.client.users.fetch(auditLogEntry.executorId!);
for (const change of auditLogEntry.changes) {
if (isRoleAddChange(change)) {
const addedRoles = change.new.map((r) => resolveRole(pluginData.guild, r.id));
logMemberRoleAdd(pluginData, {
member,
mod,
roles: addedRoles,
});
}
if (isRoleRemoveChange(change)) {
const removedRoles = change.new.map((r) => resolveRole(pluginData.guild, r.id));
logMemberRoleRemove(pluginData, {
member,
mod,
roles: removedRoles,
});
}
}
},
});

View file

@ -1,10 +1,4 @@
import diff from "lodash.difference";
import isEqual from "lodash.isequal";
import { LogType } from "../../../data/LogType";
import { logMemberNickChange } from "../logFunctions/logMemberNickChange";
import { logMemberRoleAdd } from "../logFunctions/logMemberRoleAdd";
import { logMemberRoleChanges } from "../logFunctions/logMemberRoleChanges";
import { logMemberRoleRemove } from "../logFunctions/logMemberRoleRemove";
import { logsEvt } from "../types";
export const LogsGuildMemberUpdateEvt = logsEvt({
@ -14,8 +8,6 @@ export const LogsGuildMemberUpdateEvt = logsEvt({
const pluginData = meta.pluginData;
const oldMember = meta.args.oldMember;
const member = meta.args.newMember;
const oldRoles = [...oldMember.roles.cache.keys()];
const currentRoles = [...member.roles.cache.keys()];
if (!oldMember || oldMember.partial) {
return;
@ -28,62 +20,5 @@ export const LogsGuildMemberUpdateEvt = logsEvt({
newNick: member.nickname != null ? member.nickname : "<none>",
});
}
if (!isEqual(oldRoles, currentRoles)) {
const addedRoles = diff(currentRoles, oldRoles);
const removedRoles = diff(oldRoles, currentRoles);
let skip = false;
if (
addedRoles.length &&
removedRoles.length &&
pluginData.state.guildLogs.isLogIgnored(LogType.MEMBER_ROLE_CHANGES, member.id)
) {
skip = true;
} else if (addedRoles.length && pluginData.state.guildLogs.isLogIgnored(LogType.MEMBER_ROLE_ADD, member.id)) {
skip = true;
} else if (
removedRoles.length &&
pluginData.state.guildLogs.isLogIgnored(LogType.MEMBER_ROLE_REMOVE, member.id)
) {
skip = true;
}
if (!skip) {
if (addedRoles.length && removedRoles.length) {
// Roles added *and* removed
logMemberRoleChanges(pluginData, {
member,
addedRoles: addedRoles.map(
(roleId) => pluginData.guild.roles.cache.get(roleId) ?? { id: roleId, name: `Unknown (${roleId})` },
),
removedRoles: removedRoles.map(
(roleId) => pluginData.guild.roles.cache.get(roleId) ?? { id: roleId, name: `Unknown (${roleId})` },
),
mod: null,
});
} else if (addedRoles.length) {
// Roles added
logMemberRoleAdd(pluginData, {
member,
roles: addedRoles.map(
(roleId) => pluginData.guild.roles.cache.get(roleId) ?? { id: roleId, name: `Unknown (${roleId})` },
),
mod: null,
});
} else if (removedRoles.length && !addedRoles.length) {
// Roles removed
logMemberRoleRemove(pluginData, {
member,
roles: removedRoles.map(
(roleId) => pluginData.guild.roles.cache.get(roleId) ?? { id: roleId, name: `Unknown (${roleId})` },
),
mod: null,
});
}
}
}
},
});
// TODO: Reimplement USERNAME_CHANGE

View file

@ -2,6 +2,7 @@ import { GuildMember, Role, User } from "discord.js";
import { GuildPluginData } from "knub";
import { LogType } from "../../../data/LogType";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter";
import { UnknownRole } from "../../../utils";
import { memberToTemplateSafeMember, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
import { LogsPluginType } from "../types";
import { log } from "../util/log";
@ -9,7 +10,7 @@ import { log } from "../util/log";
interface LogMemberRoleAddData {
mod: User | null;
member: GuildMember;
roles: Role[];
roles: Array<Role | UnknownRole>;
}
export function logMemberRoleAdd(pluginData: GuildPluginData<LogsPluginType>, data: LogMemberRoleAddData) {

View file

@ -14,6 +14,9 @@ interface LogMemberRoleChangesData {
removedRoles: Role[];
}
/**
* @deprecated Use logMemberRoleAdd() and logMemberRoleRemove() instead
*/
export function logMemberRoleChanges(pluginData: GuildPluginData<LogsPluginType>, data: LogMemberRoleChangesData) {
return log(
pluginData,

View file

@ -2,6 +2,7 @@ import { GuildMember, Role, User } from "discord.js";
import { GuildPluginData } from "knub";
import { LogType } from "../../../data/LogType";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter";
import { UnknownRole } from "../../../utils";
import { memberToTemplateSafeMember, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
import { LogsPluginType } from "../types";
import { log } from "../util/log";
@ -9,7 +10,7 @@ import { log } from "../util/log";
interface LogMemberRoleRemoveData {
mod: User | null;
member: GuildMember;
roles: Role[];
roles: Array<Role | UnknownRole>;
}
export function logMemberRoleRemove(pluginData: GuildPluginData<LogsPluginType>, data: LogMemberRoleRemoveData) {