diff --git a/src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts b/src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts
index 8554c41c..8a785ac7 100644
--- a/src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts
+++ b/src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts
@@ -16,16 +16,56 @@
along with this program. If not, see .
*/
-import { InteractionCallbackSchema, InteractionCallbackType, MessageCreateSchema, MessageType } from "@spacebar/schemas";
+import { ButtonStyle, InteractionCallbackSchema, InteractionCallbackType, MessageComponentType, MessageCreateSchema, MessageType } from "@spacebar/schemas";
import { route } from "@spacebar/api";
import { Request, Response, Router } from "express";
-import { emitEvent, InteractionSuccessEvent, Message, MessageCreateEvent, pendingInteractions, User } from "@spacebar/util";
+import { emitEvent, FieldErrors, InteractionSuccessEvent, Message, MessageCreateEvent, pendingInteractions, User } from "@spacebar/util";
const router = Router({ mergeParams: true });
router.post("/", route({}), async (req: Request, res: Response) => {
const body = req.body as InteractionCallbackSchema;
+ const errors: Record = {};
+ const knownComponentIds: string[] = [];
+
+ for (const row of body.data.components || []) {
+ if (!row.components) {
+ continue;
+ }
+
+ if (row.components.length < 1 || row.components.length > 5) {
+ errors[`data.components[${body.data.components!.indexOf(row)}].components`] = {
+ code: "BASE_TYPE_BAD_LENGTH",
+ message: `Must be between 1 and 5 in length.`,
+ };
+ }
+
+ for (const component of row.components) {
+ if (component.type == MessageComponentType.Button && component.style != ButtonStyle.Link) {
+ if (component.custom_id?.trim() === "") {
+ errors[`data.components[${body.data.components!.indexOf(row)}].components[${row.components.indexOf(component)}].custom_id`] = {
+ code: "BUTTON_COMPONENT_CUSTOM_ID_REQUIRED",
+ message: "A custom id required",
+ };
+ }
+
+ if (knownComponentIds.includes(component.custom_id!)) {
+ errors[`data.components[${body.data.components!.indexOf(row)}].components[${row.components.indexOf(component)}].custom_id`] = {
+ code: "COMPONENT_CUSTOM_ID_DUPLICATED",
+ message: "Component custom id cannot be duplicated",
+ };
+ } else {
+ knownComponentIds.push(component.custom_id!);
+ }
+ }
+ }
+ }
+
+ if (Object.keys(errors).length > 0) {
+ throw FieldErrors(errors);
+ }
+
const interactionId = req.params.interaction_id;
const interaction = pendingInteractions.get(req.params.interaction_id);