Skip to content

Commit bc751bb

Browse files
committed
feat: send list and buttons
1 parent da77af5 commit bc751bb

File tree

1 file changed

+89
-30
lines changed

1 file changed

+89
-30
lines changed

src/api/integrations/channel/meta/whatsapp.business.service.ts

Lines changed: 89 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { NumberBusiness } from '@api/dto/chat.dto';
22
import {
3+
Button,
34
ContactMessage,
45
MediaMessage,
56
Options,
@@ -12,6 +13,7 @@ import {
1213
SendReactionDto,
1314
SendTemplateDto,
1415
SendTextDto,
16+
TypeButton,
1517
} from '@api/dto/sendMessage.dto';
1618
import * as s3Service from '@api/integrations/storage/s3/libs/minio.server';
1719
import { ProviderFiles } from '@api/provider/sessions';
@@ -24,12 +26,14 @@ import { Chatwoot, ConfigService, Database, Openai, S3, WaBusiness } from '@conf
2426
import { BadRequestException, InternalServerErrorException } from '@exceptions';
2527
import { status } from '@utils/renderStatus';
2628
import axios from 'axios';
29+
import { proto } from 'baileys';
2730
import { arrayUnique, isURL } from 'class-validator';
2831
import EventEmitter2 from 'eventemitter2';
2932
import FormData from 'form-data';
3033
import { createReadStream } from 'fs';
3134
import mime from 'mime';
3235
import { join } from 'path';
36+
import { v4 } from 'uuid';
3337

3438
export class BusinessStartupService extends ChannelStartupService {
3539
constructor(
@@ -1108,42 +1112,97 @@ export class BusinessStartupService extends ChannelStartupService {
11081112
return audioSent;
11091113
}
11101114

1111-
public async buttonMessage(data: SendButtonsDto) {
1112-
const embeddedMedia: any = {};
1115+
private toJSONString(button: Button): string {
1116+
const toString = (obj: any) => JSON.stringify(obj);
11131117

1114-
const btnItems = {
1115-
text: data.buttons.map((btn) => btn.text),
1116-
ids: data.buttons.map((btn) => btn.id),
1118+
const json = {
1119+
call: () => toString({ display_text: button.displayText, phone_number: button.phoneNumber }),
1120+
reply: () => toString({ display_text: button.displayText, id: button.id }),
1121+
copy: () => toString({ display_text: button.displayText, copy_code: button.copyCode }),
1122+
url: () =>
1123+
toString({
1124+
display_text: button.displayText,
1125+
url: button.url,
1126+
merchant_url: button.url,
1127+
}),
11171128
};
11181129

1119-
if (!arrayUnique(btnItems.text) || !arrayUnique(btnItems.ids)) {
1120-
throw new BadRequestException('Button texts cannot be repeated', 'Button IDs cannot be repeated.');
1121-
}
1130+
return json[button.type]?.() || '';
1131+
}
11221132

1123-
return await this.sendMessageWithTyping(
1124-
data.number,
1125-
{
1126-
text: !embeddedMedia?.mediaKey ? data.title : undefined,
1127-
buttons: data.buttons.map((button) => {
1128-
return {
1129-
type: 'reply',
1130-
reply: {
1131-
title: button.text,
1132-
id: button.id,
1133+
private readonly mapType = new Map<TypeButton, string>([
1134+
['reply', 'quick_reply'],
1135+
['copy', 'cta_copy'],
1136+
['url', 'cta_url'],
1137+
['call', 'cta_call'],
1138+
]);
1139+
1140+
public async buttonMessage(data: SendButtonsDto) {
1141+
const generate = await (async () => {
1142+
if (data?.thumbnailUrl) {
1143+
return await this.prepareMediaMessage({
1144+
mediatype: 'image',
1145+
media: data.thumbnailUrl,
1146+
});
1147+
}
1148+
})();
1149+
1150+
const buttons = data.buttons.map((value) => {
1151+
return {
1152+
name: this.mapType.get(value.type),
1153+
buttonParamsJson: this.toJSONString(value),
1154+
};
1155+
});
1156+
1157+
const message: proto.IMessage = {
1158+
viewOnceMessage: {
1159+
message: {
1160+
messageContextInfo: {
1161+
deviceListMetadata: {},
1162+
deviceListMetadataVersion: 2,
1163+
},
1164+
interactiveMessage: {
1165+
body: {
1166+
text: (() => {
1167+
let t = '*' + data.title + '*';
1168+
if (data?.description) {
1169+
t += '\n\n';
1170+
t += data.description;
1171+
t += '\n';
1172+
}
1173+
return t;
1174+
})(),
11331175
},
1134-
};
1135-
}),
1136-
[embeddedMedia?.mediaKey]: embeddedMedia?.message,
1137-
},
1138-
{
1139-
delay: data?.delay,
1140-
presence: 'composing',
1141-
quoted: data?.quoted,
1142-
linkPreview: data?.linkPreview,
1143-
mentionsEveryOne: data?.mentionsEveryOne,
1144-
mentioned: data?.mentioned,
1176+
footer: {
1177+
text: data?.footer,
1178+
},
1179+
header: (() => {
1180+
if (generate?.message?.imageMessage) {
1181+
return {
1182+
hasMediaAttachment: !!generate.message.imageMessage,
1183+
imageMessage: generate.message.imageMessage,
1184+
};
1185+
}
1186+
})(),
1187+
nativeFlowMessage: {
1188+
buttons: buttons,
1189+
messageParamsJson: JSON.stringify({
1190+
from: 'api',
1191+
templateId: v4(),
1192+
}),
1193+
},
1194+
},
1195+
},
11451196
},
1146-
);
1197+
};
1198+
1199+
return await this.sendMessageWithTyping(data.number, message, {
1200+
delay: data?.delay,
1201+
presence: 'composing',
1202+
quoted: data?.quoted,
1203+
mentionsEveryOne: data?.mentionsEveryOne,
1204+
mentioned: data?.mentioned,
1205+
});
11471206
}
11481207

11491208
public async locationMessage(data: SendLocationDto) {

0 commit comments

Comments
 (0)