Skip to content

Commit d9b1385

Browse files
committed
feat: send list and buttons
1 parent 238b5c2 commit d9b1385

File tree

1 file changed

+88
-31
lines changed

1 file changed

+88
-31
lines changed

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

Lines changed: 88 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import { NumberBusiness } from '@api/dto/chat.dto';
22
import {
3+
Button,
34
ContactMessage,
45
MediaMessage,
56
Options,
67
SendAudioDto,
7-
SendButtonDto,
8+
SendButtonsDto,
89
SendContactDto,
910
SendListDto,
1011
SendLocationDto,
1112
SendMediaDto,
1213
SendReactionDto,
1314
SendTemplateDto,
1415
SendTextDto,
16+
TypeButton,
1517
} from '@api/dto/sendMessage.dto';
1618
import { PrismaRepository } from '@api/repository/repository.service';
1719
import { ChannelStartupService } from '@api/services/channel.service';
@@ -20,11 +22,13 @@ import { ConfigService, Database, WaBusiness } from '@config/env.config';
2022
import { BadRequestException, InternalServerErrorException } from '@exceptions';
2123
import { status } from '@utils/renderStatus';
2224
import axios from 'axios';
25+
import { proto } from 'baileys';
2326
import { arrayUnique, isURL } from 'class-validator';
2427
import EventEmitter2 from 'eventemitter2';
2528
import FormData from 'form-data';
2629
import { createReadStream } from 'fs';
2730
import mime from 'mime';
31+
import { v4 } from 'uuid';
2832

2933
export class BusinessStartupService extends ChannelStartupService {
3034
constructor(
@@ -951,42 +955,95 @@ export class BusinessStartupService extends ChannelStartupService {
951955
);
952956
}
953957

954-
public async buttonMessage(data: SendButtonDto) {
955-
const embeddedMedia: any = {};
958+
private toJSONString(button: Button): string {
959+
const toString = (obj: any) => JSON.stringify(obj);
956960

957-
const btnItems = {
958-
text: data.buttons.map((btn) => btn.text),
959-
ids: data.buttons.map((btn) => btn.id),
961+
const json = {
962+
call: () => toString({ display_text: button.displayText, phone_number: button.phoneNumber }),
963+
reply: () => toString({ display_text: button.displayText, id: button.id }),
964+
copy: () => toString({ display_text: button.displayText, copy_code: button.copyCode }),
965+
url: () =>
966+
toString({
967+
display_text: button.displayText,
968+
url: button.url,
969+
merchant_url: button.url,
970+
}),
960971
};
961972

962-
if (!arrayUnique(btnItems.text) || !arrayUnique(btnItems.ids)) {
963-
throw new BadRequestException('Button texts cannot be repeated', 'Button IDs cannot be repeated.');
964-
}
973+
return json[button.type]?.() || '';
974+
}
965975

966-
return await this.sendMessageWithTyping(
967-
data.number,
968-
{
969-
text: !embeddedMedia?.mediaKey ? data.title : undefined,
970-
buttons: data.buttons.map((button) => {
971-
return {
972-
type: 'reply',
973-
reply: {
974-
title: button.text,
975-
id: button.id,
976+
private readonly mapType = new Map<TypeButton, string>([
977+
['reply', 'quick_reply'],
978+
['copy', 'cta_copy'],
979+
['url', 'cta_url'],
980+
['call', 'cta_call'],
981+
]);
982+
983+
public async buttonMessage(data: SendButtonsDto) {
984+
const generate = await (async () => {
985+
if (data?.thumbnailUrl) {
986+
return await this.prepareMediaMessage({
987+
mediatype: 'image',
988+
media: data.thumbnailUrl,
989+
});
990+
}
991+
})();
992+
993+
const buttons = data.buttons.map((value) => {
994+
return {
995+
name: this.mapType.get(value.type),
996+
buttonParamsJson: this.toJSONString(value),
997+
};
998+
});
999+
1000+
const message: proto.IMessage = {
1001+
viewOnceMessage: {
1002+
message: {
1003+
interactiveMessage: {
1004+
body: {
1005+
text: (() => {
1006+
let t = '*' + data.title + '*';
1007+
if (data?.description) {
1008+
t += '\n\n';
1009+
t += data.description;
1010+
t += '\n';
1011+
}
1012+
return t;
1013+
})(),
9761014
},
977-
};
978-
}),
979-
[embeddedMedia?.mediaKey]: embeddedMedia?.message,
980-
},
981-
{
982-
delay: data?.delay,
983-
presence: 'composing',
984-
quoted: data?.quoted,
985-
linkPreview: data?.linkPreview,
986-
mentionsEveryOne: data?.mentionsEveryOne,
987-
mentioned: data?.mentioned,
1015+
footer: {
1016+
text: data?.footer,
1017+
},
1018+
header: (() => {
1019+
if (generate?.message?.imageMessage) {
1020+
return {
1021+
hasMediaAttachment: !!generate.message.imageMessage,
1022+
imageMessage: generate.message.imageMessage,
1023+
};
1024+
}
1025+
})(),
1026+
nativeFlowMessage: {
1027+
buttons: buttons,
1028+
messageParamsJson: JSON.stringify({
1029+
from: 'api',
1030+
templateId: v4(),
1031+
}),
1032+
},
1033+
},
1034+
},
9881035
},
989-
);
1036+
};
1037+
1038+
console.log(JSON.stringify(message));
1039+
1040+
return await this.sendMessageWithTyping(data.number, message, {
1041+
delay: data?.delay,
1042+
presence: 'composing',
1043+
quoted: data?.quoted,
1044+
mentionsEveryOne: data?.mentionsEveryOne,
1045+
mentioned: data?.mentioned,
1046+
});
9901047
}
9911048

9921049
public async locationMessage(data: SendLocationDto) {

0 commit comments

Comments
 (0)