mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-12 02:19:43 +00:00
80 lines
3.1 KiB
Diff
80 lines
3.1 KiB
Diff
diff --git a/dist/index.js b/dist/index.js
|
|
index ab5a27df2d1cde5530b33d24d6e30dc67e5be84d..6141dc9a651a2d7a568cc5b7eaa0a20c269437eb 100644
|
|
--- a/dist/index.js
|
|
+++ b/dist/index.js
|
|
@@ -25,6 +25,13 @@ var MAX_REPLY_BUTTONS = 3;
|
|
var MAX_BUTTON_TITLE_LENGTH = 20;
|
|
var MAX_BODY_LENGTH = 1024;
|
|
var MAX_HEADER_LENGTH = 60;
|
|
+// n8n patch (upstream: TODO file issue against vercel/chat) — WhatsApp's own
|
|
+// limits on interactive list messages.
|
|
+var MAX_LIST_ROWS = 10;
|
|
+var MAX_LIST_ROW_TITLE_LENGTH = 24;
|
|
+var MAX_LIST_ROW_DESCRIPTION_LENGTH = 72;
|
|
+var MAX_LIST_BUTTON_LABEL_LENGTH = 20;
|
|
+var MAX_LIST_ROW_ID_LENGTH = 200;
|
|
function encodeWhatsAppCallbackData(actionId, value) {
|
|
const payload = { a: actionId };
|
|
if (typeof value === "string") {
|
|
@@ -78,6 +85,42 @@ function cardToWhatsApp(card, options) {
|
|
}
|
|
};
|
|
}
|
|
+ // n8n patch (upstream: TODO file issue against vercel/chat) — builds a
|
|
+ // real WhatsApp list message instead of falling through to broken text.
|
|
+ const actionSelect = actions ? extractSelect(actions) : null;
|
|
+ if (actionSelect) {
|
|
+ // A long value can push a row's encoded id past MAX_LIST_ROW_ID_LENGTH,
|
|
+ // and Meta rejects the whole send if any row is invalid. Drop the row
|
|
+ // rather than truncate it, which would resume the wrong option.
|
|
+ const rows = actionSelect.options.map((opt) => ({
|
|
+ id: encodeWhatsAppCallbackData(actionSelect.id, opt.value),
|
|
+ title: truncate(opt.label, MAX_LIST_ROW_TITLE_LENGTH),
|
|
+ ...(opt.description ? { description: truncate(opt.description, MAX_LIST_ROW_DESCRIPTION_LENGTH) } : {})
|
|
+ })).filter((row) => {
|
|
+ if (row.id.length <= MAX_LIST_ROW_ID_LENGTH) return true;
|
|
+ console.warn(
|
|
+ `[WhatsAppAdapter] Dropping list option "${row.title}" — its encoded callback id exceeds WhatsApp's ${MAX_LIST_ROW_ID_LENGTH}-character row id limit.`
|
|
+ );
|
|
+ return false;
|
|
+ }).slice(0, MAX_LIST_ROWS);
|
|
+ if (rows.length > 0) {
|
|
+ const bodyText = [buildBodyText(card), ...cardLinkButtonLines(card)].filter(Boolean).join("\n");
|
|
+ return {
|
|
+ type: "interactive",
|
|
+ interactive: {
|
|
+ type: "list",
|
|
+ ...buildInteractiveEnvelope(
|
|
+ card,
|
|
+ bodyText || "Please choose an option"
|
|
+ ),
|
|
+ action: {
|
|
+ button: truncate(actionSelect.label || "Choose an option", MAX_LIST_BUTTON_LABEL_LENGTH),
|
|
+ sections: [{ rows }]
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ }
|
|
if (options?.allowCtaUrl !== false) {
|
|
const ctaLink = findPromotableCtaLink(card);
|
|
if (ctaLink) {
|
|
@@ -219,6 +262,17 @@ function extractReplyButtons(actions) {
|
|
}
|
|
return buttons.slice(0, MAX_REPLY_BUTTONS);
|
|
}
|
|
+// n8n patch (upstream: TODO file issue against vercel/chat) — mirrors
|
|
+// extractReplyButtons above, for a `select`/`radio_select` actions child.
|
|
+function extractSelect(actions) {
|
|
+ const select = actions.children.find(
|
|
+ (child) => child.type === "select" || child.type === "radio_select"
|
|
+ );
|
|
+ if (!select || !select.options || select.options.length === 0) {
|
|
+ return null;
|
|
+ }
|
|
+ return select;
|
|
+}
|
|
function buildInteractiveEnvelope(card, bodyText) {
|
|
return {
|
|
...card.title ? {
|