From 0b033aa51b4b3369513d264853e11ce034a6cdaf Mon Sep 17 00:00:00 2001 From: Vendicated Date: Fri, 21 Jun 2024 22:42:25 +0200 Subject: [PATCH] PluginManager: catch errors during plugin flux handlers --- src/plugins/index.ts | 13 +- src/plugins/xsOverlay.desktop/index.ts | 185 ++++++++++++------------- src/utils/types.ts | 2 +- 3 files changed, 103 insertions(+), 97 deletions(-) diff --git a/src/plugins/index.ts b/src/plugins/index.ts index 29420d0c..9268051f 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -169,7 +169,18 @@ export function subscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof Flux logger.debug("Subscribing to flux events of plugin", p.name); for (const [event, handler] of Object.entries(p.flux)) { - fluxDispatcher.subscribe(event as FluxEvents, handler); + const wrappedHandler = p.flux[event] = function () { + try { + const res = handler.apply(p, arguments as any); + return res instanceof Promise + ? res.catch(e => logger.error(`${p.name}: Error while handling ${event}\n`, e)) + : res; + } catch (e) { + logger.error(`${p.name}: Error while handling ${event}\n`, e); + } + }; + + fluxDispatcher.subscribe(event as FluxEvents, wrappedHandler); } } } diff --git a/src/plugins/xsOverlay.desktop/index.ts b/src/plugins/xsOverlay.desktop/index.ts index b42d2021..8b06475c 100644 --- a/src/plugins/xsOverlay.desktop/index.ts +++ b/src/plugins/xsOverlay.desktop/index.ts @@ -154,104 +154,99 @@ export default definePlugin({ } }, MESSAGE_CREATE({ message, optimistic }: { message: Message; optimistic: boolean; }) { - // Apparently without this try/catch, discord's socket connection dies if any part of this errors - try { - if (optimistic) return; - const channel = ChannelStore.getChannel(message.channel_id); - if (!shouldNotify(message, message.channel_id)) return; + if (optimistic) return; + const channel = ChannelStore.getChannel(message.channel_id); + if (!shouldNotify(message, message.channel_id)) return; - const pingColor = settings.store.pingColor.replaceAll("#", "").trim(); - const channelPingColor = settings.store.channelPingColor.replaceAll("#", "").trim(); - let finalMsg = message.content; - let titleString = ""; + const pingColor = settings.store.pingColor.replaceAll("#", "").trim(); + const channelPingColor = settings.store.channelPingColor.replaceAll("#", "").trim(); + let finalMsg = message.content; + let titleString = ""; - if (channel.guild_id) { - const guild = GuildStore.getGuild(channel.guild_id); - titleString = `${message.author.username} (${guild.name}, #${channel.name})`; - } - - - switch (channel.type) { - case ChannelTypes.DM: - titleString = message.author.username.trim(); - break; - case ChannelTypes.GROUP_DM: - const channelName = channel.name.trim() ?? channel.rawRecipients.map(e => e.username).join(", "); - titleString = `${message.author.username} (${channelName})`; - break; - } - - if (message.referenced_message) { - titleString += " (reply)"; - } - - if (message.embeds.length > 0) { - finalMsg += " [embed] "; - if (message.content === "") { - finalMsg = "sent message embed(s)"; - } - } - - if (message.sticker_items) { - finalMsg += " [sticker] "; - if (message.content === "") { - finalMsg = "sent a sticker"; - } - } - - const images = message.attachments.filter(e => - typeof e?.content_type === "string" - && e?.content_type.startsWith("image") - ); - - - images.forEach(img => { - finalMsg += ` [image: ${img.filename}] `; - }); - - message.attachments.filter(a => a && !a.content_type?.startsWith("image")).forEach(a => { - finalMsg += ` [attachment: ${a.filename}] `; - }); - - // make mentions readable - if (message.mentions.length > 0) { - finalMsg = finalMsg.replace(/<@!?(\d{17,20})>/g, (_, id) => `@${UserStore.getUser(id)?.username || "unknown-user"}`); - } - - // color role mentions (unity styling btw lol) - if (message.mention_roles.length > 0) { - for (const roleId of message.mention_roles) { - const role = GuildStore.getRole(channel.guild_id, roleId); - if (!role) continue; - const roleColor = role.colorString ?? `#${pingColor}`; - finalMsg = finalMsg.replace(`<@&${roleId}>`, `@${role.name}`); - } - } - - // make emotes and channel mentions readable - const emoteMatches = finalMsg.match(new RegExp("()", "g")); - const channelMatches = finalMsg.match(new RegExp("<(#\\d+)>", "g")); - - if (emoteMatches) { - for (const eMatch of emoteMatches) { - finalMsg = finalMsg.replace(new RegExp(`${eMatch}`, "g"), `:${eMatch.split(":")[1]}:`); - } - } - - // color channel mentions - if (channelMatches) { - for (const cMatch of channelMatches) { - let channelId = cMatch.split("<#")[1]; - channelId = channelId.substring(0, channelId.length - 1); - finalMsg = finalMsg.replace(new RegExp(`${cMatch}`, "g"), `#${ChannelStore.getChannel(channelId).name}`); - } - } - - if (shouldIgnoreForChannelType(channel)) return; - sendMsgNotif(titleString, finalMsg, message); - } catch (err) { - XSLog.error(`Failed to catch MESSAGE_CREATE: ${err}`); + if (channel.guild_id) { + const guild = GuildStore.getGuild(channel.guild_id); + titleString = `${message.author.username} (${guild.name}, #${channel.name})`; } + + + switch (channel.type) { + case ChannelTypes.DM: + titleString = message.author.username.trim(); + break; + case ChannelTypes.GROUP_DM: + const channelName = channel.name.trim() ?? channel.rawRecipients.map(e => e.username).join(", "); + titleString = `${message.author.username} (${channelName})`; + break; + } + + if (message.referenced_message) { + titleString += " (reply)"; + } + + if (message.embeds.length > 0) { + finalMsg += " [embed] "; + if (message.content === "") { + finalMsg = "sent message embed(s)"; + } + } + + if (message.sticker_items) { + finalMsg += " [sticker] "; + if (message.content === "") { + finalMsg = "sent a sticker"; + } + } + + const images = message.attachments.filter(e => + typeof e?.content_type === "string" + && e?.content_type.startsWith("image") + ); + + + images.forEach(img => { + finalMsg += ` [image: ${img.filename}] `; + }); + + message.attachments.filter(a => a && !a.content_type?.startsWith("image")).forEach(a => { + finalMsg += ` [attachment: ${a.filename}] `; + }); + + // make mentions readable + if (message.mentions.length > 0) { + finalMsg = finalMsg.replace(/<@!?(\d{17,20})>/g, (_, id) => `@${UserStore.getUser(id)?.username || "unknown-user"}`); + } + + // color role mentions (unity styling btw lol) + if (message.mention_roles.length > 0) { + for (const roleId of message.mention_roles) { + const role = GuildStore.getRole(channel.guild_id, roleId); + if (!role) continue; + const roleColor = role.colorString ?? `#${pingColor}`; + finalMsg = finalMsg.replace(`<@&${roleId}>`, `@${role.name}`); + } + } + + // make emotes and channel mentions readable + const emoteMatches = finalMsg.match(new RegExp("()", "g")); + const channelMatches = finalMsg.match(new RegExp("<(#\\d+)>", "g")); + + if (emoteMatches) { + for (const eMatch of emoteMatches) { + finalMsg = finalMsg.replace(new RegExp(`${eMatch}`, "g"), `:${eMatch.split(":")[1]}:`); + } + } + + // color channel mentions + if (channelMatches) { + for (const cMatch of channelMatches) { + let channelId = cMatch.split("<#")[1]; + channelId = channelId.substring(0, channelId.length - 1); + finalMsg = finalMsg.replace(new RegExp(`${cMatch}`, "g"), `#${ChannelStore.getChannel(channelId).name}`); + } + } + + if (shouldIgnoreForChannelType(channel)) return; + sendMsgNotif(titleString, finalMsg, message); } } }); diff --git a/src/utils/types.ts b/src/utils/types.ts index 2fa4a826..8c24843f 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -128,7 +128,7 @@ export interface PluginDef { * Allows you to subscribe to Flux events */ flux?: { - [E in FluxEvents]?: (event: any) => void; + [E in FluxEvents]?: (event: any) => void | Promise; }; /** * Allows you to manipulate context menus