From 7453b46e61e324749eb913828287285b46596c7d Mon Sep 17 00:00:00 2001 From: Larsundso Date: Tue, 31 Dec 2024 15:47:21 +0100 Subject: [PATCH] fix #286 --- src/BaseClient/Other/constants/events.ts | 14 ++++ .../Other/language/events/logs/channel.ts | 13 ++++ src/BaseClient/UtilModules/emotes.ts | 18 +++++ src/BaseClient/UtilModules/getEvents.ts | 4 +- .../requestHandler/guilds/getAuditLogs.ts | 22 +++++- .../channelStatusUpdate.ts | 14 ++++ .../channelEvents/channelStatusUpdate/log.ts | 75 +++++++++++++++++++ .../BotEvents/raw/voiceChannelStatusUpdate.ts | 9 +++ src/Languages/en-GB.json | 8 +- 9 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 src/Events/BotEvents/channelEvents/channelStatusUpdate/channelStatusUpdate.ts create mode 100644 src/Events/BotEvents/channelEvents/channelStatusUpdate/log.ts diff --git a/src/BaseClient/Other/constants/events.ts b/src/BaseClient/Other/constants/events.ts index 8b8702427..727a4abf0 100644 --- a/src/BaseClient/Other/constants/events.ts +++ b/src/BaseClient/Other/constants/events.ts @@ -1,3 +1,5 @@ +import emotes from '../../UtilModules/emotes.js'; + export default { logs: { automodRule: { @@ -26,6 +28,18 @@ export default { close: 'https://cdn.ayakobot.com/Ayako_Assets/Events/StageInstanceClose.png', }, channel: { + MediaChannelUpdate: 'https://cdn.ayakobot.com/Ayako_Assets/Events/MediaChannelUpdate.png', + MediaChannelCreate: 'https://cdn.ayakobot.com/Ayako_Assets/Events/MediaChannelCreate.png', + MediaChannelDelete: 'https://cdn.ayakobot.com/Ayako_Assets/Events/MediaChannelDelete.png', + GroupDmUpdate: emotes.updated.link, + GroupDmDelete: emotes.deleted.link, + GroupDmCreate: emotes.created.link, + DMDelete: emotes.deleted.link, + DMCreate: emotes.created.link, + DMUpdate: emotes.updated.link, + UnknownUpdate: emotes.updated.link, + UnknownCreate: emotes.created.link, + UnknownDelete: emotes.deleted.link, TextChannelCreate: 'https://cdn.ayakobot.com/Ayako_Assets/Events/TextChannelCreate.png', ThreadCreate: 'https://cdn.ayakobot.com/Ayako_Assets/Events/ThreadCreate.png', VoiceCreate: 'https://cdn.ayakobot.com/Ayako_Assets/Events/VoiceCreate.png', diff --git a/src/BaseClient/Other/language/events/logs/channel.ts b/src/BaseClient/Other/language/events/logs/channel.ts index 313fe80b8..df9220160 100644 --- a/src/BaseClient/Other/language/events/logs/channel.ts +++ b/src/BaseClient/Other/language/events/logs/channel.ts @@ -104,6 +104,19 @@ export default (t: CT.Language) => ({ user: t.languageFunction.getUser(user), channel: t.languageFunction.getChannel(channel, channelType), }), + descStatusUpdate: (channel: Discord.GuildChannel | Discord.AnyThreadChannel, type: string) => + t.stp(t.JSON.events.logs.channel.descDelete, { + channel: t.languageFunction.getChannel(channel, type), + }), + descStatusUpdateAudit: ( + user: Discord.User, + channel: Discord.GuildChannel | Discord.AnyThreadChannel, + type: string, + ) => + t.stp(t.JSON.events.logs.channel.descStatusUpdateAudit, { + user: t.languageFunction.getUser(user), + channel: t.languageFunction.getChannel(channel, type), + }), privacyLevel: { 1: t.JSON.events.logs.channel.privacyLevel[1], 2: t.JSON.events.logs.channel.privacyLevel[2], diff --git a/src/BaseClient/UtilModules/emotes.ts b/src/BaseClient/UtilModules/emotes.ts index 9e90cf523..8cc7ca9ff 100644 --- a/src/BaseClient/UtilModules/emotes.ts +++ b/src/BaseClient/UtilModules/emotes.ts @@ -451,4 +451,22 @@ export default { id: '1208434096678895676', link: 'https://cdn.discordapp.com/emojis/1208434096678895676.png', }, + created: { + name: 'Created', + animated: false, + id: '1155171800578261042', + link: 'https://cdn.discordapp.com/emojis/1155171800578261042.png', + }, + updated: { + name: 'Updated', + animated: false, + id: '1155171880303591464', + link: 'https://cdn.discordapp.com/emojis/1155171880303591464.png', + }, + deleted: { + name: 'Deleted', + animated: false, + id: '1155171841128796210', + link: 'https://cdn.discordapp.com/emojis/1155171841128796210.png', + }, }; diff --git a/src/BaseClient/UtilModules/getEvents.ts b/src/BaseClient/UtilModules/getEvents.ts index a5ed81402..a061f221e 100644 --- a/src/BaseClient/UtilModules/getEvents.ts +++ b/src/BaseClient/UtilModules/getEvents.ts @@ -37,7 +37,9 @@ export const getBotEvents = async () => const eventName = path.replace('.js', '').split(/\/+/).pop(); if (!eventName) return false; - if (!Object.values(Discord.Events).includes(eventName as never)) return false; + if (!Object.values(Discord.Events).includes(eventName as never)) { + return false; + } return true; }); diff --git a/src/BaseClient/UtilModules/requestHandler/guilds/getAuditLogs.ts b/src/BaseClient/UtilModules/requestHandler/guilds/getAuditLogs.ts index ee3e1b84a..1543c5613 100644 --- a/src/BaseClient/UtilModules/requestHandler/guilds/getAuditLogs.ts +++ b/src/BaseClient/UtilModules/requestHandler/guilds/getAuditLogs.ts @@ -25,7 +25,27 @@ export default async (guild: Discord.Guild, query?: Discord.RESTGetAPIAuditLogQu return (await getAPI(guild)).guilds .getAuditLogs(guild.id, query) - .then((a) => new Classes.GuildAuditLogs(guild, a)) + .then((a) => { + const logs = new Classes.GuildAuditLogs(guild, a); + + a.audit_log_entries.forEach((entry) => { + switch (entry.action_type as number) { + case 192: { + const parsedEntry = logs.entries.find((e) => e.id === entry.id); + if (!parsedEntry) break; + + // TODO: Wait for djs to support 192 193 + // @ts-ignore + parsedEntry.extra = entry.options; + break; + } + default: + break; + } + }); + + return logs; + }) .catch((e: Discord.DiscordAPIError) => { error(guild, new Error((e as Discord.DiscordAPIError).message)); return e; diff --git a/src/Events/BotEvents/channelEvents/channelStatusUpdate/channelStatusUpdate.ts b/src/Events/BotEvents/channelEvents/channelStatusUpdate/channelStatusUpdate.ts new file mode 100644 index 000000000..309160ece --- /dev/null +++ b/src/Events/BotEvents/channelEvents/channelStatusUpdate/channelStatusUpdate.ts @@ -0,0 +1,14 @@ +import type { BaseGuildVoiceChannel } from 'discord.js'; + +import log from './log.js'; + +export default async ( + channel: BaseGuildVoiceChannel, + oldStatus: string, + newStatus: string, + internal: boolean, +) => { + if (!internal) throw new Error('ChannelStatusUpdate received from unknown source'); + + log(channel, oldStatus, newStatus); +}; diff --git a/src/Events/BotEvents/channelEvents/channelStatusUpdate/log.ts b/src/Events/BotEvents/channelEvents/channelStatusUpdate/log.ts new file mode 100644 index 000000000..3504988dd --- /dev/null +++ b/src/Events/BotEvents/channelEvents/channelStatusUpdate/log.ts @@ -0,0 +1,75 @@ +import type { APIEmbed, AuditLogEvent, BaseGuildVoiceChannel } from 'discord.js'; +import { Colors, type AcceptedMergingTypes } from '../../../../Typings/Typings.js'; + +export default async (channel: BaseGuildVoiceChannel, oldStatus: string, newStatus: string) => { + const channels = await channel.client.util.getLogChannels('channelevents', channel.guild); + if (!channels) return; + + const language = await channel.client.util.getLanguage(channel.guild.id); + const lan = language.events.logs.channel; + const con = channel.client.util.constants.events.logs.channel; + + const audit = await channel.client.util.request.guilds.getAuditLogs(channel.guild, { + action_type: (newStatus.length ? 192 : 193) as AuditLogEvent, + limit: 50, + }); + + const relevantAudit = + 'message' in audit + ? undefined + : audit.entries + .filter((e) => + e.targetId === channel.id && e.action === (192 as AuditLogEvent) + ? (e.extra as { status: string } | null)?.status === newStatus + : true, + ) + .sort((a, b) => b.createdTimestamp - a.createdTimestamp) + .first(); + + const getTitle = () => { + if (!newStatus.length) return lan.nameStatusDelete; + if (!oldStatus.length) return lan.nameStatusCreate; + return lan.nameStatusUpdate; + }; + + const getColor = () => { + if (!newStatus.length) return Colors.Danger; + if (!oldStatus.length) return Colors.Success; + return Colors.Loading; + }; + + const getType = (): 'Delete' | 'Create' | 'Update' => { + if (!newStatus.length) return 'Delete'; + if (!oldStatus.length) return 'Create'; + return 'Update'; + }; + + const embed: APIEmbed = { + author: { + icon_url: con[`${channel.client.util.getTrueChannelType(channel, channel.guild)}${getType()}`], + name: getTitle(), + }, + description: + relevantAudit && relevantAudit.executor + ? lan.descStatusUpdateAudit( + relevantAudit.executor, + channel, + language.channelTypes[channel.type], + ) + : lan.descStatusUpdate(channel, language.channelTypes[channel.type]), + fields: [], + color: getColor(), + timestamp: new Date().toISOString(), + }; + + const merge = (before: unknown, after: unknown, type: AcceptedMergingTypes, name: string) => + channel.client.util.mergeLogging(before, after, type, embed, language, name); + + if (oldStatus !== newStatus) { + merge(oldStatus || language.t.None, newStatus || language.t.None, 'string', lan.channelStatus); + } + + if (!embed.fields?.length) return; + + channel.client.util.send({ id: channels, guildId: channel.guild.id }, { embeds: [embed] }, 10000); +}; diff --git a/src/Events/BotEvents/raw/voiceChannelStatusUpdate.ts b/src/Events/BotEvents/raw/voiceChannelStatusUpdate.ts index 14a8aa09a..46f6ce415 100644 --- a/src/Events/BotEvents/raw/voiceChannelStatusUpdate.ts +++ b/src/Events/BotEvents/raw/voiceChannelStatusUpdate.ts @@ -1,5 +1,14 @@ import client from '../../../BaseClient/Bot/Client.js'; +import channelStatusUpdate from '../channelEvents/channelStatusUpdate/channelStatusUpdate.js'; export default async (data: { status: string; id: string; guild_id: string }) => { + const oldStatus = client.util.cache.voiceChannelStatus.get(data.id); client.util.cache.voiceChannelStatus.set(data.id, data.status); + + const channel = client.channels.cache.get(data.id); + if (!channel) return; + if (channel.isDMBased()) return; + if (!channel.isVoiceBased()) return; + + channelStatusUpdate(channel, oldStatus || '', data.status, true); }; diff --git a/src/Languages/en-GB.json b/src/Languages/en-GB.json index 7459d4c4f..d582686a0 100644 --- a/src/Languages/en-GB.json +++ b/src/Languages/en-GB.json @@ -527,6 +527,9 @@ "pending": "Pending" }, "channel": { + "nameStatusCreate": "Channel-Status created", + "nameStatusUpdate": "Channel-Status updated", + "nameStatusDelete": "Channel-Status deleted", "nameCreate": "Channel created", "nameDelete": "Channel deleted", "nameTyping": "User started typing", @@ -547,6 +550,7 @@ "1": "Public", "2": "Server Only" }, + "channelStatus": "Channel-Status", "bitrate": "Bitrate", "nsfw": "NSFW", "permissions": "Permissions", @@ -593,7 +597,9 @@ "descPinCreate": "> {{msg}}> was pinned in\n> {{channel}}", "descPinRemoveAudit": "> {{user}}> has unpinned\n> {{msg}}in\n> {{channel}}", "descPinRemove": "> {{msg}}> was unpinned in\n> {{channel}}", - "descTyping": "> {{user}}> has started typing in\n> {{channel}}" + "descTyping": "> {{user}}> has started typing in\n> {{channel}}", + "descStatusUpdate": "> Channel-Status of\n> {{channel}}> has changed", + "descStatusUpdateAudit": "> {{user}}> has changed the Channel-Status of\n> {{channel}}" }, "user": { "name": "User updated",