diff --git a/src/api/dto/sendMessage.dto.ts b/src/api/dto/sendMessage.dto.ts index 46839366..07ef804e 100644 --- a/src/api/dto/sendMessage.dto.ts +++ b/src/api/dto/sendMessage.dto.ts @@ -90,18 +90,15 @@ export class SendAudioDto extends Metadata { } class Button { - buttonText: string; - buttonId: string; + text: string; + id: string; } -class ButtonMessage { +export class SendButtonDto extends Metadata { title: string; description: string; footerText?: string; buttons: Button[]; } -export class SendButtonDto extends Metadata { - buttonMessage: ButtonMessage; -} export class SendLocationDto extends Metadata { latitude: number; diff --git a/src/api/routes/sendMessage.router.ts b/src/api/routes/sendMessage.router.ts index 006b49ef..b8bee8e5 100644 --- a/src/api/routes/sendMessage.router.ts +++ b/src/api/routes/sendMessage.router.ts @@ -2,6 +2,7 @@ import { RequestHandler, Router } from 'express'; import { audioMessageSchema, + buttonMessageSchema, contactMessageSchema, listMessageSchema, locationMessageSchema, @@ -16,6 +17,7 @@ import { import { RouterBroker } from '../abstract/abstract.router'; import { SendAudioDto, + SendButtonDto, SendContactDto, SendListDto, SendLocationDto, @@ -144,17 +146,17 @@ export class MessageRouter extends RouterBroker { }); return res.status(HttpStatus.CREATED).json(response); - }); - // .post(this.routerPath('sendButtons'), ...guards, async (req, res) => { - // const response = await this.dataValidate({ - // request: req, - // schema: buttonMessageSchema, - // ClassRef: SendButtonDto, - // execute: (instance, data) => sendMessageController.sendButtons(instance, data), - // }); + }) + .post(this.routerPath('sendButtons'), ...guards, async (req, res) => { + const response = await this.dataValidate({ + request: req, + schema: buttonMessageSchema, + ClassRef: SendButtonDto, + execute: (instance, data) => sendMessageController.sendButtons(instance, data), + }); - // return res.status(HttpStatus.CREATED).json(response); - // }) + return res.status(HttpStatus.CREATED).json(response); + }); } public readonly router = Router(); diff --git a/src/api/services/channels/whatsapp.business.service.ts b/src/api/services/channels/whatsapp.business.service.ts index 4f51c9b6..d5fd9289 100644 --- a/src/api/services/channels/whatsapp.business.service.ts +++ b/src/api/services/channels/whatsapp.business.service.ts @@ -738,7 +738,7 @@ export class BusinessStartupService extends ChannelStartupService { message = { conversation: `${message['text'] || 'Select'}\n` + formattedText }; return await this.post(content, 'messages'); } - if (message['sections']) { + if (message['listMessage']) { content = { messaging_product: 'whatsapp', recipient_type: 'individual', @@ -748,29 +748,29 @@ export class BusinessStartupService extends ChannelStartupService { type: 'list', header: { type: 'text', - text: message['title'], + text: message['listMessage']['title'], }, body: { - text: message['text'], + text: message['listMessage']['description'], }, footer: { - text: message['footerText'], + text: message['listMessage']['footerText'], }, action: { - button: message['buttonText'], - sections: message['sections'], + button: message['listMessage']['buttonText'], + sections: message['listMessage']['sections'], }, }, }; quoted ? (content.context = { message_id: quoted.id }) : content; let formattedText = ''; - for (const section of message['sections']) { + for (const section of message['listMessage']['sections']) { formattedText += `${section?.title}\n`; for (const row of section.rows) { formattedText += `${row?.title}\n`; } } - message = { conversation: `${message['title']}\n` + formattedText }; + message = { conversation: `${message['listMessage']['title']}\n` + formattedText }; return await this.post(content, 'messages'); } if (message['template']) { @@ -993,8 +993,8 @@ export class BusinessStartupService extends ChannelStartupService { const embeddedMedia: any = {}; const btnItems = { - text: data.buttonMessage.buttons.map((btn) => btn.buttonText), - ids: data.buttonMessage.buttons.map((btn) => btn.buttonId), + text: data.buttons.map((btn) => btn.text), + ids: data.buttons.map((btn) => btn.id), }; if (!arrayUnique(btnItems.text) || !arrayUnique(btnItems.ids)) { @@ -1004,13 +1004,13 @@ export class BusinessStartupService extends ChannelStartupService { return await this.sendMessageWithTyping( data.number, { - text: !embeddedMedia?.mediaKey ? data.buttonMessage.title : undefined, - buttons: data.buttonMessage.buttons.map((button) => { + text: !embeddedMedia?.mediaKey ? data.title : undefined, + buttons: data.buttons.map((button) => { return { type: 'reply', reply: { - title: button.buttonText, - id: button.buttonId, + title: button.text, + id: button.id, }, }; }), @@ -1058,11 +1058,10 @@ export class BusinessStartupService extends ChannelStartupService { throw new BadRequestException('Section tiles cannot be repeated'); } - return await this.sendMessageWithTyping( - data.number, - { + const sendData: any = { + listMessage: { title: data.title, - text: data.description, + description: data.description, footerText: data?.footerText, buttonText: data?.buttonText, sections: data.sections.map((section) => { @@ -1071,22 +1070,23 @@ export class BusinessStartupService extends ChannelStartupService { rows: section.rows.map((row) => { return { title: row.title, - description: row.description, + description: row.description.substring(0, 72), id: row.rowId, }; }), }; }), }, - { - delay: data?.delay, - presence: 'composing', - quoted: data?.quoted, - linkPreview: data?.linkPreview, - mentionsEveryOne: data?.mentionsEveryOne, - mentioned: data?.mentioned, - }, - ); + }; + + return await this.sendMessageWithTyping(data.number, sendData, { + delay: data?.delay, + presence: 'composing', + quoted: data?.quoted, + linkPreview: data?.linkPreview, + mentionsEveryOne: data?.mentionsEveryOne, + mentioned: data?.mentioned, + }); } public async templateMessage(data: SendTemplateDto, isIntegration = false) { diff --git a/src/validate/message.schema.ts b/src/validate/message.schema.ts index 1f7548b1..fee7bcfe 100644 --- a/src/validate/message.schema.ts +++ b/src/validate/message.schema.ts @@ -358,3 +358,48 @@ export const listMessageSchema: JSONSchema7 = { }, required: ['number', 'title', 'footerText', 'buttonText', 'sections'], }; + +export const buttonMessageSchema: JSONSchema7 = { + $id: v4(), + type: 'object', + properties: { + number: { ...numberDefinition }, + title: { type: 'string' }, + description: { type: 'string' }, + footerText: { type: 'string' }, + buttons: { + type: 'array', + minItems: 1, + uniqueItems: true, + items: { + type: 'object', + properties: { + text: { type: 'string' }, + id: { type: 'string' }, + }, + required: ['text', 'id'], + ...isNotEmpty('text', 'id'), + }, + }, + media: { type: 'string' }, + fileName: { type: 'string' }, + mediatype: { type: 'string', enum: ['image', 'document', 'video'] }, + delay: { + type: 'integer', + description: 'Enter a value in milliseconds', + }, + quoted: { ...quotedOptionsSchema }, + everyOne: { type: 'boolean', enum: [true, false] }, + mentioned: { + type: 'array', + minItems: 1, + uniqueItems: true, + items: { + type: 'string', + pattern: '^\\d+', + description: '"mentioned" must be an array of numeric strings', + }, + }, + }, + required: ['number', 'title', 'buttons'], +};