Skip to content

Commit

Permalink
🐛 (whatsapp) Fix webhook listener in prod
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Oct 4, 2024
1 parent 53df53b commit 4ee9428
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 248 deletions.
51 changes: 36 additions & 15 deletions apps/builder/src/features/whatsapp/receiveMessagePreview.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { publicProcedure } from "@/helpers/server/trpc";
import { TRPCError } from "@trpc/server";
import { env } from "@typebot.io/env";
import { isNotDefined } from "@typebot.io/lib/utils";
import { resumeWhatsAppFlow } from "@typebot.io/whatsapp/resumeWhatsAppFlow";
import { whatsAppWebhookRequestBodySchema } from "@typebot.io/whatsapp/schemas";
import {
type WhatsAppWebhookRequestBody,
whatsAppWebhookRequestBodySchema,
} from "@typebot.io/whatsapp/schemas";
import { z } from "@typebot.io/zod";

const whatsAppPreviewSessionIdPrefix = "wa-preview-";

export const receiveMessagePreview = publicProcedure
.meta({
openapi: {
Expand All @@ -22,23 +26,40 @@ export const receiveMessagePreview = publicProcedure
}),
)
.mutation(async ({ input: { entry } }) => {
if (!env.WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID)
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID is not defined",
});
const receivedMessage = entry.at(0)?.changes.at(0)?.value.messages?.at(0);
if (isNotDefined(receivedMessage)) return { message: "No message found" };
const contactName =
entry.at(0)?.changes.at(0)?.value?.contacts?.at(0)?.profile?.name ?? "";
const contactPhoneNumber =
entry.at(0)?.changes.at(0)?.value?.messages?.at(0)?.from ?? "";
return resumeWhatsAppFlow({
assertEnv();

const { receivedMessage, contactName, contactPhoneNumber } =
extractMessageData(entry);
if (!receivedMessage) return { message: "No message found" };

await resumeWhatsAppFlow({
receivedMessage,
sessionId: `wa-preview-${receivedMessage.from}`,
sessionId: `${whatsAppPreviewSessionIdPrefix}${receivedMessage.from}`,
contact: {
name: contactName,
phoneNumber: contactPhoneNumber,
},
});

return {
message: "Message received",
};
});

const assertEnv = () => {
if (!env.WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID)
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID is not defined",
});
};

const extractMessageData = (entry: WhatsAppWebhookRequestBody["entry"]) => {
const receivedMessage = entry.at(0)?.changes.at(0)?.value.messages?.at(0);
const contactName =
entry.at(0)?.changes.at(0)?.value?.contacts?.at(0)?.profile?.name ?? "";
const contactPhoneNumber =
entry.at(0)?.changes.at(0)?.value?.messages?.at(0)?.from ?? "";

return { receivedMessage, contactName, contactPhoneNumber };
};
41 changes: 28 additions & 13 deletions apps/viewer/src/features/whatsapp/api/receiveMessage.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { publicProcedure } from "@/helpers/server/trpc";
import { isNotDefined } from "@typebot.io/lib/utils";
import { resumeWhatsAppFlow } from "@typebot.io/whatsapp/resumeWhatsAppFlow";
import { whatsAppWebhookRequestBodySchema } from "@typebot.io/whatsapp/schemas";
import {
type WhatsAppWebhookRequestBody,
whatsAppWebhookRequestBodySchema,
} from "@typebot.io/whatsapp/schemas";
import { z } from "@typebot.io/zod";

const whatsAppSessionIdPrefix = "wa-";

export const receiveMessage = publicProcedure
.meta({
openapi: {
Expand All @@ -24,18 +28,14 @@ export const receiveMessage = publicProcedure
}),
)
.mutation(async ({ input: { entry, credentialsId, workspaceId } }) => {
const receivedMessage = entry.at(0)?.changes.at(0)?.value.messages?.at(0);
if (isNotDefined(receivedMessage)) return { message: "No message found" };
const contactName =
entry.at(0)?.changes.at(0)?.value?.contacts?.at(0)?.profile?.name ?? "";
const contactPhoneNumber =
entry.at(0)?.changes.at(0)?.value?.messages?.at(0)?.from ?? "";
const phoneNumberId = entry.at(0)?.changes.at(0)?.value
.metadata.phone_number_id;
if (!phoneNumberId) return { message: "No phone number id found" };
return resumeWhatsAppFlow({
const { receivedMessage, contactName, contactPhoneNumber, phoneNumberId } =
extractMessageDetails(entry);
if (!receivedMessage) return { message: "No message found" };
if (!phoneNumberId) return { message: "No phone number found" };

await resumeWhatsAppFlow({
receivedMessage,
sessionId: `wa-${phoneNumberId}-${receivedMessage.from}`,
sessionId: `${whatsAppSessionIdPrefix}${phoneNumberId}-${receivedMessage.from}`,
phoneNumberId,
credentialsId,
workspaceId,
Expand All @@ -44,4 +44,19 @@ export const receiveMessage = publicProcedure
phoneNumber: contactPhoneNumber,
},
});

return {
message: "Message received",
};
});

const extractMessageDetails = (entry: WhatsAppWebhookRequestBody["entry"]) => {
const receivedMessage = entry.at(0)?.changes.at(0)?.value.messages?.at(0);
const contactName =
entry.at(0)?.changes.at(0)?.value?.contacts?.at(0)?.profile?.name ?? "";
const contactPhoneNumber =
entry.at(0)?.changes.at(0)?.value?.messages?.at(0)?.from ?? "";
const phoneNumberId = entry.at(0)?.changes.at(0)?.value
.metadata.phone_number_id;
return { receivedMessage, contactName, contactPhoneNumber, phoneNumberId };
};
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import type { PublicTypebot } from "@typebot.io/typebot/schemas/publicTypebot";
import type { Typebot } from "@typebot.io/typebot/schemas/typebot";
import type { Variable } from "@typebot.io/variables/schemas";
import Cors from "cors";
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { NextApiRequest, NextApiResponse } from "next";

const cors = initMiddleware(Cors());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
},
sessionId: chatSession.id,
credentialsId: typebot.whatsAppCredentialsId,
force: true,
origin: "webhook",
});
return res.status(200).send("OK");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
: JSON.stringify({ data: req.body }, null, 2),
},
},
force: true,
sessionId: chatSession.id,
origin: "webhook",
});
return res.status(200).send("OK");
}
Expand Down
1 change: 1 addition & 0 deletions packages/bot-engine/src/schemas/clientSideAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,4 @@ export const clientSideActionSchema = z.discriminatedUnion("type", [
title: "Listen to webhook",
}),
]);
export type ClientSideAction = z.infer<typeof clientSideActionSchema>;
35 changes: 0 additions & 35 deletions packages/whatsapp/src/receiveMessage.ts

This file was deleted.

31 changes: 0 additions & 31 deletions packages/whatsapp/src/receiveMessagePreview.ts

This file was deleted.

Loading

0 comments on commit 4ee9428

Please sign in to comment.