| 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 |
| } |
| }; |
| log(data); |
| } catch (e) { |
| console.log(e); |
| } |
| } |