summary refs log tree commit diff
diff options
context:
space:
mode:
authorCyber <cyber.hf18@gmail.com>2025-11-19 16:09:33 +0100
committerGitHub <noreply@github.com>2025-11-19 16:09:33 +0100
commit652657d78f4e7ef4e8e13807383ed753273c3620 (patch)
treed3a78750b332b87de0a55cb4cd40efa131ee9afd
parentMerge pull request #1394 from MathMan05/readStates (diff)
parentMerge branch 'master' into webhookFix (diff)
downloadserver-ts-652657d78f4e7ef4e8e13807383ed753273c3620.tar.xz
Merge pull request #1393 from MathMan05/webhookFix
-rw-r--r--src/api/util/handlers/Webhook.ts123
1 files changed, 46 insertions, 77 deletions
diff --git a/src/api/util/handlers/Webhook.ts b/src/api/util/handlers/Webhook.ts

index 9040f74c..54ef26ec 100644 --- a/src/api/util/handlers/Webhook.ts +++ b/src/api/util/handlers/Webhook.ts
@@ -1,57 +1,14 @@ 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(); - - 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 - ) { - throw DiscordApiErrors.CANNOT_SEND_EMPTY_MESSAGE; - } - - // 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) { - return res.status(400).json({ - username: [`Username cannot be "${word}"`], - }); - } - } + const { webhook_id, token } = req.params; const webhook = await Webhook.findOne({ where: { @@ -64,52 +21,66 @@ export const executeWebhook = async (req: Request, res: Response) => { throw DiscordApiErrors.UNKNOWN_WEBHOOK; } - if (!webhook.channel.isWritable()) { - throw new HTTPError( - `Cannot send messages to channel of type ${webhook.channel.type}`, - 400, - ); - } - if (webhook.token !== token) { 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.wait === "true"; + + 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); + } 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) { 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)), }, }); 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[]) ?? []; 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 +117,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; };