Skip to content

Commit 3c8cc89

Browse files
committed
🐛 Fix WA crash when trying to send duplicate buttons (after truncation)
1 parent 6d21dc2 commit 3c8cc89

File tree

1 file changed

+58
-17
lines changed

1 file changed

+58
-17
lines changed

packages/whatsapp/src/convertInputToWhatsAppMessage.ts

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -126,16 +126,23 @@ export const convertInputToWhatsAppMessages = (
126126
interactive: {
127127
type: "button",
128128
body: {
129-
text: idx === 0 ? (lastMessageText ?? "...") : "...",
129+
text: idx === 0 ? (lastMessageText ?? "") : "",
130130
},
131131
action: {
132-
buttons: items.map((item) => ({
133-
type: "reply",
134-
reply: {
135-
id: item.id,
136-
title: trimTextTo20Chars(item.content as string),
137-
},
138-
})),
132+
buttons: (() => {
133+
const buttonTexts = items
134+
.filter((item) => item.content)
135+
.map((item) => item.content as string);
136+
const uniqueTitles = getUniqueButtonTitles(buttonTexts);
137+
138+
return items.map((item, index) => ({
139+
type: "reply",
140+
reply: {
141+
id: item.id,
142+
title: uniqueTitles[index],
143+
},
144+
}));
145+
})(),
139146
},
140147
},
141148
}));
@@ -162,13 +169,19 @@ export const convertInputToWhatsAppMessages = (
162169
: undefined,
163170
body: isEmpty(bodyText) ? undefined : { text: bodyText },
164171
action: {
165-
buttons: (item.paths ?? []).slice(0, 3).map((path) => ({
166-
type: "reply",
167-
reply: {
168-
id: path.id,
169-
title: trimTextTo20Chars(path.text ?? ""),
170-
},
171-
})),
172+
buttons: (() => {
173+
const paths = (item.paths ?? []).slice(0, 3);
174+
const buttonTexts = paths.map((path) => path.text ?? "");
175+
const uniqueTitles = getUniqueButtonTitles(buttonTexts);
176+
177+
return paths.map((path, index) => ({
178+
type: "reply",
179+
reply: {
180+
id: path.id,
181+
title: uniqueTitles[index],
182+
},
183+
}));
184+
})(),
172185
},
173186
},
174187
};
@@ -177,8 +190,36 @@ export const convertInputToWhatsAppMessages = (
177190
}
178191
};
179192

180-
const trimTextTo20Chars = (text: string): string =>
181-
text.length > 20 ? `${text.slice(0, 18)}..` : text;
193+
const trimTextTo20Chars = (
194+
text: string,
195+
existingTitles: string[] = [],
196+
): string => {
197+
const baseTitle = text.length > 20 ? `${text.slice(0, 18)}..` : text;
198+
199+
if (!existingTitles.includes(baseTitle)) return baseTitle;
200+
201+
let counter = 1;
202+
let uniqueTitle = "";
203+
204+
do {
205+
const suffix = ` (${counter})`;
206+
const availableChars = 20 - suffix.length - 3; // 3 for ".." and a space
207+
uniqueTitle = `${text.slice(0, availableChars)} ${suffix}..`;
208+
counter++;
209+
} while (existingTitles.includes(uniqueTitle));
210+
211+
return uniqueTitle;
212+
};
213+
214+
const getUniqueButtonTitles = (texts: string[]): string[] => {
215+
const uniqueTitles: string[] = [];
216+
217+
return texts.map((text) => {
218+
const uniqueTitle = trimTextTo20Chars(text, uniqueTitles);
219+
uniqueTitles.push(uniqueTitle);
220+
return uniqueTitle;
221+
});
222+
};
182223

183224
const groupArrayByArraySize = (arr: any[], n: number) =>
184225
arr.reduce(

0 commit comments

Comments
 (0)