From 1568439a42cd39914ed1f065409ca448b948866e Mon Sep 17 00:00:00 2001 From: artie Date: Thu, 27 Mar 2025 17:43:40 +0100 Subject: [PATCH] improve errors --- src/client.ts | 15 +++++++++++ src/commands/language/translate.ts | 2 +- src/commands/ocr/ocr.ts | 2 +- src/events/interactionCreate.ts | 6 ++++- src/utils/error.ts | 42 ++++++++++++++++++++---------- 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/client.ts b/src/client.ts index 2c5d1b9..0e2ea27 100644 --- a/src/client.ts +++ b/src/client.ts @@ -5,7 +5,9 @@ import { Collection, GatewayIntentBits, InteractionContextType, + lazy, Partials, + TextChannel, } from "discord.js"; import { REST } from "@discordjs/rest"; import { env } from "./env"; @@ -56,6 +58,19 @@ export class ArtemisClient extends Client { return this.users.fetch(this.ownerId); } + getDevWebhook = lazy(async () => { + const channel = (await client.channels.fetch( + env.DEV_CHANNEL_ID + )) as TextChannel; + return channel + .fetchWebhooks() + .then( + webhooks => + webhooks.find(wh => wh.applicationId === env.APPLICATION_ID) ?? + channel.createWebhook({ name: "artemis" }) + ); + }); + async loadCommands() { const commandsDir = path.join(import.meta.dir, "commands"); const categories = await fs diff --git a/src/commands/language/translate.ts b/src/commands/language/translate.ts index 7f2b97b..6ae5f1f 100644 --- a/src/commands/language/translate.ts +++ b/src/commands/language/translate.ts @@ -52,7 +52,7 @@ export async function translateImpl( target ).catch(err => { logger.error(err, "DeepL error, falling back to Google Translate"); - sendErrorAlert(err); + sendErrorAlert(err, { source, target, ocrModel }); return translateGoogle(text, "auto", "en"); }); diff --git a/src/commands/ocr/ocr.ts b/src/commands/ocr/ocr.ts index 453275a..0972be0 100644 --- a/src/commands/ocr/ocr.ts +++ b/src/commands/ocr/ocr.ts @@ -88,7 +88,7 @@ export async function ocrImpl(url: string) { const result = await lensOcr(compressed) .catch(err => { logger.error(err, "Google Lens error, falling back to Yandex"); - sendErrorAlert(err); + sendErrorAlert(err, { mime: type.mime }); return yandexOcr(compressed, type.mime); }) .catch(() => abort("Failed to OCR the image")); diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts index cb3e74b..cbccac3 100644 --- a/src/events/interactionCreate.ts +++ b/src/events/interactionCreate.ts @@ -75,7 +75,11 @@ async function handleChatInputCommand( const trace = nanoid(); content += `\ntrace: ${inlineCode(trace)}`; logger.error({ trace, err }); - sendErrorAlert(err, trace); + sendErrorAlert(err, { + trace, + command: command.data.name, + user: `${interaction.user.id} (${interaction.user.tag})`, + }); } await interaction[ diff --git a/src/utils/error.ts b/src/utils/error.ts index ba68e72..3a9350b 100644 --- a/src/utils/error.ts +++ b/src/utils/error.ts @@ -1,4 +1,4 @@ -import { codeBlock } from "discord.js"; +import { bold, codeBlock } from "discord.js"; import { client } from "../client"; export class ExplicitCommandError extends Error {} @@ -13,17 +13,31 @@ export function isExplicitCommandError( return error instanceof ExplicitCommandError; } -export async function sendErrorAlert(error: any, trace?: string) { - return client.getOwner().then(owner => - owner.send({ - content: trace, - embeds: [ - { - title: "Unhandled Error", - description: codeBlock("js", error.stack ?? error.message), - color: 0xff0000, - }, - ], - }) - ); +export async function sendErrorAlert( + error: any, + meta?: Record +) { + const owner = await client.getOwner(); + const webhook = await client.getDevWebhook(); + + return webhook.send({ + username: "artemis error", + avatarURL: "https://files.catbox.moe/g52ano.png", + allowedMentions: { users: [owner.id] }, + content: + `${owner}\n` + + (meta + ? Object.entries(meta) + .filter(([_, value]) => value) + .map(([key, value]) => `${bold(key)}: ${value}`) + .join("\n") + : ""), + embeds: [ + { + title: "Unhandled Error", + description: codeBlock("js", error.stack ?? error.message), + color: 0xff0000, + }, + ], + }); }