Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: interactive flow #19

Merged
merged 3 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Here is the diagram to understand the flow:

- Webhook endpoint to receive messages from WhatsApp
- Integration with Dify and Rasa for natural language processing and response generation
- Verification of incoming webhook requests
- Displaying interactive whatsapp message like [List](https://developers.facebook.com/docs/whatsapp/cloud-api/messages/interactive-list-messages), [Reply Buttons](https://developers.facebook.com/docs/whatsapp/cloud-api/messages/interactive-reply-buttons-messages), and [Flow](https://developers.facebook.com/docs/whatsapp/cloud-api/messages/interactive-flow-messages)

## Prerequisites

Expand Down Expand Up @@ -91,6 +91,53 @@ Now just use your WhatsApp app to send a text message to the WhatsApp Business n
![configuration](./docs/whatsapp-configuration.png)
![api setup](./docs/whatsap-api-setup.png)

## Interactive Message Configuration

### Flow

To create a Flow, you must setup many things like in the [docs](https://developers.facebook.com/docs/whatsapp/flows). I will mention over-simplified version for easy starting point:

1. Create a Flow
2. Setup server endpoint
3. Setup Dify to trigger sending HTTP Request with this [JSON format](https://developers.facebook.com/docs/whatsapp/flows/gettingstarted/sendingaflow). Here is the example request body:

```json
{
"recipient_type": "individual",
"messaging_product": "whatsapp",
"to": "{{#sys.user_id#}}",
"type": "interactive",
"interactive": {
"type": "flow",
"header": {
"type": "text",
"text": "Event Registration"
},
"body": {
"text": "Click button below to authenticate yourself"
},
"action": {
"name": "flow",
"parameters": {
"mode": "draft", // delete this field for production use (when your flow is published)
"flow_message_version": "3",
"flow_token": "auth_flow-{{#sys.user_id#}}.",
"flow_id": "1234567812345678",
"flow_cta": "Start",
"flow_action": "data_exchange"
}
}
}
}
```

4. It will send CTA button to trigger the Flow
![flow cta](./docs/flow-cta.jpeg)
5. Fill in, complete, and submit the form
![flow form](./docs/flow-form.jpeg)
6. Sent status will be displayed
![flow sent](./docs/flow-sent.jpeg)

## Deployment

You can deploy this app to any server that runs Node.js. The easiest one is to use Vercel. Just clone this repo and connect it from Vercel Dashboard then you are good to go.
Expand Down
13 changes: 11 additions & 2 deletions api/webhook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ webhookRoutes.post("/", async (req, res) => {
return;
}

// aknowledge that the message has been read and be processed
await markChatAsRead(message.id);

let chatbotReply = null;
let queryText = "";

Expand All @@ -54,27 +57,33 @@ webhookRoutes.post("/", async (req, res) => {
queryText = message.interactive.button_reply.id;
} else if (message.interactive.type === "list_reply") {
queryText = message.interactive.list_reply.id;
} else if (message.interactive.type === "nfm_reply") {
queryText = "";
}
break;
default:
queryText = message.text.body;
break;
}

if (!queryText) {
res.sendStatus(200);
return;
}

if (CONNECTION_PLATFORM === DIFY) {
chatbotReply = await queryToDify({ req, query: queryText });
} else if (CONNECTION_PLATFORM === RASA) {
chatbotReply = await queryToRasa({ req, query: queryText });
}
console.log("Chatbot Reply:\n", chatbotReply);

if (!chatbotReply) {
if (!chatbotReply || !chatbotReply.text) {
res.sendStatus(200);
return;
}

await sendChatbotReply({ to: message.from, chatbotReply });
await markChatAsRead(message.id);

res.sendStatus(200);
});
Expand Down
Binary file added docs/flow-cta.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/flow-form.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/flow-sent.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading