blob: c4a4efbd9a3a9513a2fafdf8164eabfb665272cc [file] [log] [blame]
import { AuditLogEvent, GuildAuditLogsEntry, GuildChannel, Webhook } from "discord.js";
import type Discord from "discord.js";
import type { NucleusClient } from "../utils/client.js";
export const event = "webhookUpdate";
interface accType {
before: Record<string, string>;
after: Record<string, string>;
}
export async function callback(client: NucleusClient, channel: Discord.GuildChannel) {
try {
const { getAuditLog, isLogging, log, NucleusColors, entry, renderUser, renderChannel, renderDelta } =
client.logger;
if (!(await isLogging(channel.guild.id, "webhookUpdate"))) return;
const auditCreate = (await getAuditLog(channel.guild, AuditLogEvent.WebhookCreate)).filter(
(entry: GuildAuditLogsEntry | null) =>
entry?.target ? (entry.target as Webhook)!.channelId === channel.id : false
)[0];
const auditDelete = (await getAuditLog(channel.guild, AuditLogEvent.WebhookDelete, 0)).filter(
(entry: GuildAuditLogsEntry | null) =>
entry?.target ? (entry.target as Webhook)!.channelId === channel.id : false
)[0];
const auditUpdate = (await getAuditLog(channel.guild, AuditLogEvent.WebhookUpdate, 0)).filter(
(entry: GuildAuditLogsEntry | null) =>
entry?.target ? (entry.target as Webhook)!.channelId === channel.id : false
)[0];
if (!auditCreate && !auditUpdate && !auditDelete) return;
let action: "Create" | "Update" | "Delete" = "Create";
let list: Record<string, ReturnType<typeof entry> | string> = {};
const createTimestamp = auditCreate ? auditCreate.createdTimestamp : 0;
const deleteTimestamp = auditDelete ? auditDelete.createdTimestamp : 0;
const updateTimestamp = auditUpdate ? auditUpdate.createdTimestamp : 0;
if (updateTimestamp > createTimestamp && updateTimestamp > deleteTimestamp && auditUpdate) {
const { before, after } = auditUpdate.changes.reduce(
(acc: accType, change) => {
acc.before[change.key] = change.old?.toString()!;
acc.after[change.key] = change.new?.toString()!;
return acc;
},
{ before: {}, after: {} }
);
if (before["name"] !== after["name"])
list["name"] = entry([before["name"]!, after["name"]!], `${before["name"]} -> ${after["name"]}`);
if (before["channel_id"] !== after["channel_id"])
list["channel"] = entry(
[before["channel_id"]!, after["channel_id"]!],
renderChannel((await client.channels.fetch(before["channel_id"]!)) as GuildChannel) +
" -> " +
renderChannel((await client.channels.fetch(after["channel_id"]!)) as GuildChannel)
);
if (!Object.keys(list).length) return;
list["created"] = entry(
(auditUpdate.target! as Extract<GuildAuditLogsEntry, { createdTimestamp: number }>).createdTimestamp,
renderDelta(
(auditUpdate.target! as Extract<GuildAuditLogsEntry, { createdTimestamp: number }>).createdTimestamp
)
);
list["edited"] = entry(after["editedTimestamp"]!, renderDelta(Date.now()));
list["editedBy"] = entry(auditUpdate.executor!.id, renderUser(auditUpdate.executor!));
action = "Update";
} else if (deleteTimestamp > createTimestamp && deleteTimestamp > updateTimestamp && auditDelete) {
const { before } = auditDelete.changes.reduce(
(acc: accType, change) => {
acc.before[change.key] = change.old?.toString()!;
acc.after[change.key] = change.new?.toString()!;
return acc;
},
{ before: {}, after: {} }
);
list = {
name: entry(before["name"]!, `${before["name"]}`),
channel: entry(
before["channel_id"]!,
renderChannel((await client.channels.fetch(before["channel_id"]!)) as GuildChannel)
),
created: entry(
(auditDelete.target! as Extract<GuildAuditLogsEntry, { createdTimestamp: number }>)
.createdTimestamp,
renderDelta(
(auditDelete.target! as Extract<GuildAuditLogsEntry, { createdTimestamp: number }>)
.createdTimestamp
)
),
deleted: entry(Date.now(), renderDelta(Date.now())),
deletedBy: entry(
auditDelete.executor!.id,
renderUser((await channel.guild.members.fetch(auditDelete.executor!.id)).user)
)
};
action = "Delete";
} else {
const { before } = auditDelete!.changes.reduce(
(acc: accType, change) => {
acc.before[change.key] = change.old?.toString()!;
acc.after[change.key] = change.new?.toString()!;
return acc;
},
{ before: {}, after: {} }
);
list = {
name: entry(before["name"]!, `${before["name"]}`),
channel: entry(
before["channel_id"]!,
renderChannel((await client.channels.fetch(before["channel_id"]!)) as GuildChannel)
),
createdBy: entry(
auditCreate!.executor!.id,
renderUser((await channel.guild.members.fetch(auditCreate!.executor!.id)).user)
),
created: entry(Date.now(), renderDelta(Date.now()))
};
}
const cols = {
Create: "green",
Update: "yellow",
Delete: "red"
};
const data = {
meta: {
type: "webhook" + action,
displayName: `Webhook ${action}d`,
calculateType: "webhookUpdate",
color: NucleusColors[cols[action] as keyof typeof NucleusColors],
emoji: "WEBHOOK." + action.toUpperCase(),
timestamp: Date.now()
},
list: list,
hidden: {
guild: channel.guild.id
}
};
await log(data);
} catch (e) {
console.log(e);
}
}