Skip to content

Commit 08f8d05

Browse files
author
root
committed
fix(baileys): interactive buttons via deviceSentMessage + CTA limits
1 parent d15c434 commit 08f8d05

File tree

1 file changed

+70
-41
lines changed

1 file changed

+70
-41
lines changed

src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

Lines changed: 70 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3310,48 +3310,57 @@ export class BaileysStartupService extends ChannelStartupService {
33103310
['random', 'EVP'],
33113311
]);
33123312

3313-
public async buttonMessage(data: SendButtonsDto) {
3314-
if (data.buttons.length === 0) {
3313+
aqui?
3314+
3315+
public async buttonMessage(data: SendButtonsDto) {
3316+
if (!data.buttons || data.buttons.length === 0) {
33153317
throw new BadRequestException('At least one button is required');
33163318
}
33173319

33183320
const hasReplyButtons = data.buttons.some((btn) => btn.type === 'reply');
33193321
const hasPixButton = data.buttons.some((btn) => btn.type === 'pix');
3320-
const hasOtherButtons = data.buttons.some((btn) => btn.type !== 'reply' && btn.type !== 'pix');
3322+
const hasCTAButtons = data.buttons.some(
3323+
(btn) => btn.type === 'url' || btn.type === 'call' || btn.type === 'copy',
3324+
);
3325+
3326+
/* =========================
3327+
* REGRAS DE VALIDAÇÃO
3328+
* ========================= */
33213329

3322-
// Reply rules
3330+
// Reply
33233331
if (hasReplyButtons) {
33243332
if (data.buttons.length > 3) {
33253333
throw new BadRequestException('Maximum of 3 reply buttons allowed');
33263334
}
3327-
if (hasOtherButtons) {
3328-
throw new BadRequestException('Reply buttons cannot be mixed with other button types');
3329-
}
3330-
}
3331-
3332-
// CTA rules (url/call/copy) - WhatsApp limits to 2 CTAs
3333-
if (hasOtherButtons && !hasReplyButtons && !hasPixButton) {
3334-
if (data.buttons.length > 2) {
3335-
throw new BadRequestException('Maximum of 2 CTA buttons allowed (url/call/copy)');
3335+
if (hasCTAButtons || hasPixButton) {
3336+
throw new BadRequestException('Reply buttons cannot be mixed with CTA or PIX buttons');
33363337
}
33373338
}
33383339

3339-
// PIX rules
3340+
// PIX
33403341
if (hasPixButton) {
33413342
if (data.buttons.length > 1) {
33423343
throw new BadRequestException('Only one PIX button is allowed');
33433344
}
3344-
if (hasOtherButtons) {
3345+
if (hasReplyButtons || hasCTAButtons) {
33453346
throw new BadRequestException('PIX button cannot be mixed with other button types');
33463347
}
33473348

33483349
const message: proto.IMessage = {
3349-
deviceSentMessage: {
3350+
viewOnceMessage: {
33503351
message: {
33513352
interactiveMessage: {
33523353
nativeFlowMessage: {
3353-
buttons: [{ name: this.mapType.get('pix'), buttonParamsJson: this.toJSONString(data.buttons[0]) }],
3354-
messageParamsJson: JSON.stringify({ from: 'api', templateId: v4() }),
3354+
buttons: [
3355+
{
3356+
name: this.mapType.get('pix'),
3357+
buttonParamsJson: this.toJSONString(data.buttons[0]),
3358+
},
3359+
],
3360+
messageParamsJson: JSON.stringify({
3361+
from: 'api',
3362+
templateId: v4(),
3363+
}),
33553364
},
33563365
},
33573366
},
@@ -3367,43 +3376,63 @@ export class BaileysStartupService extends ChannelStartupService {
33673376
});
33683377
}
33693378

3370-
const generate = await (async () => {
3371-
if (data?.thumbnailUrl) {
3372-
return await this.prepareMediaMessage({ mediatype: 'image', media: data.thumbnailUrl });
3379+
// CTA (url / call / copy)
3380+
if (hasCTAButtons) {
3381+
if (data.buttons.length > 2) {
3382+
throw new BadRequestException('Maximum of 2 CTA buttons allowed');
3383+
}
3384+
if (hasReplyButtons) {
3385+
throw new BadRequestException('CTA buttons cannot be mixed with reply buttons');
33733386
}
3374-
})();
3387+
}
33753388

3376-
const buttons = data.buttons.map((value) => {
3377-
return { name: this.mapType.get(value.type), buttonParamsJson: this.toJSONString(value) };
3378-
});
3389+
/* =========================
3390+
* HEADER (opcional)
3391+
* ========================= */
3392+
3393+
const generatedMedia = data?.thumbnailUrl
3394+
? await this.prepareMediaMessage({ mediatype: 'image', media: data.thumbnailUrl })
3395+
: null;
3396+
3397+
/* =========================
3398+
* BOTÕES
3399+
* ========================= */
3400+
3401+
const buttons = data.buttons.map((btn) => ({
3402+
name: this.mapType.get(btn.type),
3403+
buttonParamsJson: this.toJSONString(btn),
3404+
}));
3405+
3406+
/* =========================
3407+
* MENSAGEM FINAL
3408+
* ========================= */
33793409

33803410
const message: proto.IMessage = {
3381-
deviceSentMessage: {
3411+
viewOnceMessage: {
33823412
message: {
33833413
interactiveMessage: {
33843414
body: {
33853415
text: (() => {
3386-
let t = '*' + data.title + '*';
3416+
let text = `*${data.title}*`;
33873417
if (data?.description) {
3388-
t += '\n\n';
3389-
t += data.description;
3390-
t += '\n';
3418+
text += `\n\n${data.description}`;
33913419
}
3392-
return t;
3420+
return text;
33933421
})(),
33943422
},
3395-
footer: { text: data?.footer },
3396-
header: (() => {
3397-
if (generate?.message?.imageMessage) {
3398-
return {
3399-
hasMediaAttachment: !!generate.message.imageMessage,
3400-
imageMessage: generate.message.imageMessage,
3401-
};
3402-
}
3403-
})(),
3423+
footer: data?.footer ? { text: data.footer } : undefined,
3424+
header: generatedMedia?.message?.imageMessage
3425+
? {
3426+
hasMediaAttachment: true,
3427+
imageMessage: generatedMedia.message.imageMessage,
3428+
}
3429+
: undefined,
34043430
nativeFlowMessage: {
34053431
buttons,
3406-
messageParamsJson: JSON.stringify({ from: 'api', templateId: v4() }),
3432+
messageParamsJson: JSON.stringify({
3433+
from: 'api',
3434+
templateId: v4(),
3435+
}),
34073436
},
34083437
},
34093438
},

0 commit comments

Comments
 (0)