diff --git a/src/index.ts b/src/index.ts index f9d89aa..f2162ba 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,7 @@ import { Command } from './types/index'; import { startServer } from './web/web'; import { init as initPVP } from './lib/rpg/pvp'; import { autocomplete } from './lib/autocomplete'; +import { setupListeners } from './lib/events'; const bot = new Client({ intents: [ @@ -69,6 +70,8 @@ bot.on(Events.ClientReady, async () => { log.nonsense(`| ${prettyBytes(memory.rss)} memory usage, ${prettyBytes(memory.heapUsed)} / ${prettyBytes(memory.heapTotal)} heap usage`); }); +setupListeners(bot); + function stringifyArg(arg: CommandInteractionOption): string { switch (arg.type) { case ApplicationCommandOptionType.Boolean: diff --git a/src/lib/db.ts b/src/lib/db.ts index 69d7cb1..72fe33a 100644 --- a/src/lib/db.ts +++ b/src/lib/db.ts @@ -102,4 +102,10 @@ export interface RoleSeperator { guild: string, role: string, type: RoleSeperatorType, +} +export interface AuditLog { + guild: string, + channel: string, + // comma-seperated + eventTypes: string, } \ No newline at end of file diff --git a/src/lib/events.ts b/src/lib/events.ts index 687ad07..596abff 100644 --- a/src/lib/events.ts +++ b/src/lib/events.ts @@ -1,39 +1,41 @@ -import { Sticker, ThreadChannel, Message, User, Invite, GuildMember, GuildScheduledEvent, GuildEmoji, Channel } from 'discord.js'; +import { Sticker, ThreadChannel, Message, User, Invite, GuildMember, GuildScheduledEvent, GuildEmoji, Channel, Client, Events, GuildAuditLogsEntry, AuditLogEvent } from 'discord.js'; +import { AuditLog, db } from './db'; +import * as log from './log'; export enum EventType { - ChannelCreate, - ChannelRename, - ChannelDelete, + ChannelCreate = 'CHANNEL_CREATE', + ChannelRename = 'CHANNEL_RENAME', + ChannelDelete = 'CHANNEL_DELETE', - EmojiCreate, - EmojiRename, - EmojiDelete, + EmojiCreate = 'EMOJI_CREATE', + EmojiRename = 'EMOJI_RENAME', + EmojiDelete = 'EMOJI_DELETE', - EventCreate, - EventEdit, - EventDelete, + EventCreate = 'EVENT_CREATE', + EventEdit = 'EVENT_EDIT', + EventDelete = 'EVENT_DELETE', - InviteCreate, - InviteUpdate, - InviteDelete, + InviteCreate = 'INVITE_CREATE', + InviteUpdate = 'INVITE_UPDATE', + InviteDelete = 'INVITE_DELETE', - MemberBan, - MemberUnban, - MemberKick, - MemberDisconnect, - MemberNickname, - MemberChangeRoles, + MemberBan = 'MEMBER_BAN', + MemberUnban = 'MEMBER_UNBAN', + MemberKick = 'MEMBER_KICK', + MemberDisconnect = 'MEMBER_DISCONNECT', + MemberNickname = 'MEMBER_NICKNAME', + MemberChangeRoles = 'MEMBER_CHANGE_ROLES', - MessageDelete, - MessageEdit, + MessageDelete = 'MESSAGE_DELETE', + MessageEdit = 'MESSAGE_EDIT', - StickerCreate, - StickerRename, - StickerDelete, + StickerCreate = 'STICKER_CREATE', + StickerRename = 'STICKER_RENAME', + StickerDelete = 'STICKER_DELETE', - ThreadCreate, - ThreadEdit, - ThreadDelete, + ThreadCreate = 'THREAD_CREATE', + ThreadEdit = 'THREAD_EDIT', + ThreadDelete = 'THREAD_DELETE', } export type Event = { @@ -153,6 +155,49 @@ export type Event = { thread: ThreadChannel, }; -export async function triggerEvent(event: Event) { - +export async function triggerEvent(bot: Client, event: Event) { + const type = event.type; + + log.info(`Got event ${event.type}: ${JSON.stringify(event)}`); + + const logs = await db('auditLogs') + .select('guild', 'channel') + // @ts-expect-error this LITERALLY works + .whereLike(db.raw('UPPER(eventTypes)'), `%${type.toUpperCase()}%`); + + for (const auditLog of logs) { + let channel; + try { + channel = await bot.channels.fetch(auditLog.channel); + } catch (err) { + log.warn(err); + } + + if (channel && channel.isText()) { + channel.send(`${JSON.stringify(event)}`); + } else { + log.warn(`Channel ${auditLog.channel} from guild ${auditLog.guild} not found! Deleting audit log`); + await db('auditLogs') + .where('channel', auditLog.channel) + .delete(); + } + } +} + +export function setupListeners(bot: Client) { + /*bot.on(Events.GuildAuditLogEntryCreate, async (auditLog: GuildAuditLogsEntry) => { + const { action, extra: channel, executorId, targetId } = auditLog; + + // Check only for deleted messages. + if (action !== AuditLogEvent.MessageDelete) return; + + // Ensure the executor is cached. + const executor = await bot.users.fetch(executorId); + + // Ensure the author whose message was deleted is cached. + const target = await bot.users.fetch(targetId); + + // Log the output. + console.log(`A message by ${target.tag} was deleted by ${executor.tag} in ${channel}.`); + });*/ } \ No newline at end of file