From c583c14dd73d6833de7b0eaa51271e1b543091cd Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Tue, 18 Nov 2025 16:07:34 -0600 Subject: [PATCH 1/6] make not wait work correctly --- src/api/util/handlers/Webhook.ts | 66 ++++++++++---------------------- 1 file changed, 20 insertions(+), 46 deletions(-) diff --git a/src/api/util/handlers/Webhook.ts b/src/api/util/handlers/Webhook.ts index 9040f74c..f3c31644 100644 --- a/src/api/util/handlers/Webhook.ts +++ b/src/api/util/handlers/Webhook.ts @@ -1,24 +1,15 @@ import { handleMessage, postHandleMessage } from "@spacebar/api"; -import { - Attachment, - Config, - DiscordApiErrors, - emitEvent, - FieldErrors, - Message, - MessageCreateEvent, - uploadFile, - ValidateName, - Webhook, -} from "@spacebar/util"; +import { Attachment, Config, DiscordApiErrors, emitEvent, FieldErrors, Message, MessageCreateEvent, uploadFile, ValidateName, Webhook } from "@spacebar/util"; import { Request, Response } from "express"; import { HTTPError } from "lambert-server"; import { MoreThan } from "typeorm"; -import { WebhookExecuteSchema } from "@spacebar/schemas" +import { WebhookExecuteSchema } from "@spacebar/schemas"; export const executeWebhook = async (req: Request, res: Response) => { const { wait } = req.query; - if (!wait) return res.status(204).send(); + if (!wait) { + res.status(204).send(); + } const { webhook_id, token } = req.params; @@ -26,13 +17,7 @@ export const executeWebhook = async (req: Request, res: Response) => { const attachments: Attachment[] = []; // ensure one of content, embeds, components, or file is present - if ( - !body.content && - !body.embeds && - !body.components && - !body.file && - !body.attachments - ) { + if (!body.content && !body.embeds && !body.components && !body.file && !body.attachments) { throw DiscordApiErrors.CANNOT_SEND_EMPTY_MESSAGE; } @@ -47,9 +32,11 @@ export const executeWebhook = async (req: Request, res: Response) => { const blockedEquals = ["everyone", "here"]; for (const word of blockedEquals) { if (body.username?.toLowerCase() === word) { - return res.status(400).json({ - username: [`Username cannot be "${word}"`], - }); + if (wait) + res.status(400).json({ + username: [`Username cannot be "${word}"`], + }); + return; } } @@ -65,10 +52,7 @@ export const executeWebhook = async (req: Request, res: Response) => { } if (!webhook.channel.isWritable()) { - throw new HTTPError( - `Cannot send messages to channel of type ${webhook.channel.type}`, - 400, - ); + throw new HTTPError(`Cannot send messages to channel of type ${webhook.channel.type}`, 400); } if (webhook.token !== token) { @@ -81,11 +65,7 @@ export const executeWebhook = async (req: Request, res: Response) => { const count = await Message.count({ where: { channel_id: webhook.channel_id, - timestamp: MoreThan( - new Date( - Date.now() - limits.absoluteRate.sendMessage.window, - ), - ), + timestamp: MoreThan(new Date(Date.now() - limits.absoluteRate.sendMessage.window)), }, }); @@ -101,15 +81,11 @@ export const executeWebhook = async (req: Request, res: Response) => { const files = (req.files as Express.Multer.File[]) ?? []; for (const currFile of files) { try { - const file = await uploadFile( - `/attachments/${webhook.channel.id}`, - currFile, - ); - attachments.push( - Attachment.create({ ...file, proxy_url: file.url }), - ); + const file = await uploadFile(`/attachments/${webhook.channel.id}`, currFile); + attachments.push(Attachment.create({ ...file, proxy_url: file.url })); } catch (error) { - return res.status(400).json({ message: error?.toString() }); + if (wait) res.status(400).json({ message: error?.toString() }); + return; } } @@ -146,9 +122,7 @@ export const executeWebhook = async (req: Request, res: Response) => { ]); // no await as it shouldnt block the message send function and silently catch error - postHandleMessage(message).catch((e) => - console.error("[Message] post-message handler failed", e), - ); - - return res.json(message); + postHandleMessage(message).catch((e) => console.error("[Message] post-message handler failed", e)); + if (wait) res.json(message); + return; }; From 45be3023025dfac216bc4457e3a97af07b647a91 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Wed, 19 Nov 2025 08:39:30 -0600 Subject: [PATCH 2/6] some fixes --- src/api/util/handlers/Webhook.ts | 42 ++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/api/util/handlers/Webhook.ts b/src/api/util/handlers/Webhook.ts index f3c31644..e77bcbde 100644 --- a/src/api/util/handlers/Webhook.ts +++ b/src/api/util/handlers/Webhook.ts @@ -7,6 +7,7 @@ import { WebhookExecuteSchema } from "@spacebar/schemas"; export const executeWebhook = async (req: Request, res: Response) => { const { wait } = req.query; + if (!wait) { res.status(204).send(); } @@ -18,7 +19,11 @@ export const executeWebhook = async (req: Request, res: Response) => { // ensure one of content, embeds, components, or file is present if (!body.content && !body.embeds && !body.components && !body.file && !body.attachments) { - throw DiscordApiErrors.CANNOT_SEND_EMPTY_MESSAGE; + if (wait) { + throw DiscordApiErrors.CANNOT_SEND_EMPTY_MESSAGE; + } else { + return; + } } // block username from containing certain words @@ -46,17 +51,30 @@ export const executeWebhook = async (req: Request, res: Response) => { }, relations: ["channel", "guild", "application"], }); + console.log("in here?", wait); if (!webhook) { - throw DiscordApiErrors.UNKNOWN_WEBHOOK; + if (wait) { + throw DiscordApiErrors.UNKNOWN_WEBHOOK; + } else { + return; + } } if (!webhook.channel.isWritable()) { - throw new HTTPError(`Cannot send messages to channel of type ${webhook.channel.type}`, 400); + if (wait) { + throw new HTTPError(`Cannot send messages to channel of type ${webhook.channel.type}`, 400); + } else { + return; + } } if (webhook.token !== token) { - throw DiscordApiErrors.INVALID_WEBHOOK_TOKEN_PROVIDED; + if (wait) { + throw DiscordApiErrors.INVALID_WEBHOOK_TOKEN_PROVIDED; + } else { + return; + } } // TODO: creating messages by users checks if the user can bypass rate limits, we cant do that on webhooks, but maybe we could check the application if there is one? @@ -70,12 +88,16 @@ export const executeWebhook = async (req: Request, res: Response) => { }); if (count >= limits.absoluteRate.sendMessage.limit) - throw FieldErrors({ - channel_id: { - code: "TOO_MANY_MESSAGES", - message: req.t("common:toomany.MESSAGE"), - }, - }); + if (wait) { + throw FieldErrors({ + channel_id: { + code: "TOO_MANY_MESSAGES", + message: req.t("common:toomany.MESSAGE"), + }, + }); + } else { + return; + } } const files = (req.files as Express.Multer.File[]) ?? []; From 4135390e009022c18727f8704f56a20d188491fc Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Wed, 19 Nov 2025 08:39:38 -0600 Subject: [PATCH 3/6] get rid of log --- src/api/util/handlers/Webhook.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/api/util/handlers/Webhook.ts b/src/api/util/handlers/Webhook.ts index e77bcbde..e9e0bf6c 100644 --- a/src/api/util/handlers/Webhook.ts +++ b/src/api/util/handlers/Webhook.ts @@ -51,7 +51,6 @@ export const executeWebhook = async (req: Request, res: Response) => { }, relations: ["channel", "guild", "application"], }); - console.log("in here?", wait); if (!webhook) { if (wait) { From 8ee8c8c28c3b611b87b95bf8d35f9ebfd729258b Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Wed, 19 Nov 2025 08:56:15 -0600 Subject: [PATCH 4/6] fixes --- src/api/util/handlers/Webhook.ts | 61 +++++++++----------------------- 1 file changed, 17 insertions(+), 44 deletions(-) diff --git a/src/api/util/handlers/Webhook.ts b/src/api/util/handlers/Webhook.ts index e9e0bf6c..3980b47e 100644 --- a/src/api/util/handlers/Webhook.ts +++ b/src/api/util/handlers/Webhook.ts @@ -6,44 +6,17 @@ import { MoreThan } from "typeorm"; import { WebhookExecuteSchema } from "@spacebar/schemas"; export const executeWebhook = async (req: Request, res: Response) => { - const { wait } = req.query; - - if (!wait) { - res.status(204).send(); - } - - const { webhook_id, token } = req.params; - const body = req.body as WebhookExecuteSchema; - const attachments: Attachment[] = []; - // ensure one of content, embeds, components, or file is present - if (!body.content && !body.embeds && !body.components && !body.file && !body.attachments) { - if (wait) { - throw DiscordApiErrors.CANNOT_SEND_EMPTY_MESSAGE; - } else { - return; - } - } - - // block username from containing certain words - // TODO: configurable additions if (body.username) { ValidateName(body.username); } - // block username from being certain words - // TODO: configurable additions - const blockedEquals = ["everyone", "here"]; - for (const word of blockedEquals) { - if (body.username?.toLowerCase() === word) { - if (wait) - res.status(400).json({ - username: [`Username cannot be "${word}"`], - }); - return; - } + // ensure one of content, embeds, components, or file is present + if (!body.content && !body.embeds && !body.components && !body.file && !body.attachments) { + throw DiscordApiErrors.CANNOT_SEND_EMPTY_MESSAGE; } + const { webhook_id, token } = req.params; const webhook = await Webhook.findOne({ where: { @@ -53,13 +26,21 @@ export const executeWebhook = async (req: Request, res: Response) => { }); if (!webhook) { - if (wait) { - throw DiscordApiErrors.UNKNOWN_WEBHOOK; - } else { - return; - } + throw DiscordApiErrors.UNKNOWN_WEBHOOK; } + if (webhook.token !== token) { + throw DiscordApiErrors.INVALID_WEBHOOK_TOKEN_PROVIDED; + } + + const { wait } = req.query; + + if (!wait) { + res.status(204).send(); + } + + const attachments: Attachment[] = []; + if (!webhook.channel.isWritable()) { if (wait) { throw new HTTPError(`Cannot send messages to channel of type ${webhook.channel.type}`, 400); @@ -68,14 +49,6 @@ export const executeWebhook = async (req: Request, res: Response) => { } } - if (webhook.token !== token) { - if (wait) { - throw DiscordApiErrors.INVALID_WEBHOOK_TOKEN_PROVIDED; - } else { - return; - } - } - // TODO: creating messages by users checks if the user can bypass rate limits, we cant do that on webhooks, but maybe we could check the application if there is one? const limits = Config.get().limits; if (limits.absoluteRate.register.enabled) { From ced0421ee92457c433eca88ee7d1bb3df8b05376 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Wed, 19 Nov 2025 09:04:47 -0600 Subject: [PATCH 5/6] rearange errors --- src/api/util/handlers/Webhook.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/api/util/handlers/Webhook.ts b/src/api/util/handlers/Webhook.ts index 3980b47e..9037f650 100644 --- a/src/api/util/handlers/Webhook.ts +++ b/src/api/util/handlers/Webhook.ts @@ -8,14 +8,6 @@ import { WebhookExecuteSchema } from "@spacebar/schemas"; export const executeWebhook = async (req: Request, res: Response) => { const body = req.body as WebhookExecuteSchema; - if (body.username) { - ValidateName(body.username); - } - - // ensure one of content, embeds, components, or file is present - if (!body.content && !body.embeds && !body.components && !body.file && !body.attachments) { - throw DiscordApiErrors.CANNOT_SEND_EMPTY_MESSAGE; - } const { webhook_id, token } = req.params; const webhook = await Webhook.findOne({ @@ -33,6 +25,15 @@ export const executeWebhook = async (req: Request, res: Response) => { throw DiscordApiErrors.INVALID_WEBHOOK_TOKEN_PROVIDED; } + if (body.username) { + ValidateName(body.username); + } + + // ensure one of content, embeds, components, or file is present + if (!body.content && !body.embeds && !body.components && !body.file && !body.attachments) { + throw DiscordApiErrors.CANNOT_SEND_EMPTY_MESSAGE; + } + const { wait } = req.query; if (!wait) { From 8bdc577f6fdb87fb95ba81399d7f3a2f5467db97 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Wed, 19 Nov 2025 09:07:57 -0600 Subject: [PATCH 6/6] correctly check query --- src/api/util/handlers/Webhook.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/util/handlers/Webhook.ts b/src/api/util/handlers/Webhook.ts index 9037f650..54ef26ec 100644 --- a/src/api/util/handlers/Webhook.ts +++ b/src/api/util/handlers/Webhook.ts @@ -34,7 +34,7 @@ export const executeWebhook = async (req: Request, res: Response) => { throw DiscordApiErrors.CANNOT_SEND_EMPTY_MESSAGE; } - const { wait } = req.query; + const wait = req.query.wait === "true"; if (!wait) { res.status(204).send();