diff --git a/integrations/whatsapp/integration.definition.ts b/integrations/whatsapp/integration.definition.ts index 7fbc1b6549c..5596a4a26b7 100644 --- a/integrations/whatsapp/integration.definition.ts +++ b/integrations/whatsapp/integration.definition.ts @@ -94,7 +94,7 @@ const defaultBotPhoneNumberId = { export default new IntegrationDefinition({ name: INTEGRATION_NAME, - version: '4.4.0', + version: '4.5.0', title: 'WhatsApp', description: 'Send and receive messages through WhatsApp.', icon: 'icon.svg', @@ -183,6 +183,61 @@ export default new IntegrationDefinition({ filename: z.string().optional(), }), }, + bloc: { + schema: z.object({ + items: z.array( + z.discriminatedUnion('type', [ + z.object({ + type: z.literal('text'), + payload: z.object({ + text: z.string(), + }), + }), + z.object({ + type: z.literal('markdown'), // TODO Remove for 4.0.0 + payload: z.object({ + markdown: z.string(), + }), + }), + z.object({ + type: z.literal('image'), + payload: z.object({ + imageUrl: z.string(), + }), + }), + z.object({ + type: z.literal('audio'), + payload: z.object({ + audioUrl: z.string(), + }), + }), + z.object({ + type: z.literal('video'), + payload: z.object({ + videoUrl: z.string(), + }), + }), + z.object({ + type: z.literal('file'), + payload: z.object({ + fileUrl: z.string(), + title: z.string().optional(), + filename: z.string().optional(), + }), + }), + z.object({ + type: z.literal('location'), + payload: z.object({ + latitude: z.number(), + longitude: z.number(), + address: z.string().optional(), + title: z.string().optional(), + }), + }), + ]) + ), + }), + }, }, message: { tags: { diff --git a/integrations/whatsapp/src/channels/channel.ts b/integrations/whatsapp/src/channels/channel.ts index 0354c2e94e2..1a5fa8a6400 100644 --- a/integrations/whatsapp/src/channels/channel.ts +++ b/integrations/whatsapp/src/channels/channel.ts @@ -1,4 +1,3 @@ -import { RuntimeError } from '@botpress/sdk' import { Text, Audio, @@ -101,8 +100,49 @@ export const channel: bp.IntegrationProps['channels']['channel'] = { }) } }, - bloc: () => { - throw new RuntimeError('Not implemented') + bloc: async ({ payload, ...props }) => { + if (!payload.items) { + return + } + for (const item of payload.items) { + switch (item.type) { + case 'text': + await _send({ ...props, message: new Text(convertMarkdownToWhatsApp(item.payload.text)) }) + break + case 'image': + await _send({ + ...props, + message: await image.generateOutgoingMessage({ payload: item.payload, logger: props.logger }), + }) + break + case 'audio': + await _send({ ...props, message: new Audio(item.payload.audioUrl.trim(), false) }) + break + case 'video': + await _send({ + ...props, + message: new Video(item.payload.videoUrl.trim(), false), + }) + break + case 'file': + const title = item.payload.title?.trim() + const url = item.payload.fileUrl.trim() + const inputFilename = item.payload.filename?.trim() + let filename = inputFilename || title || 'file' + const fileExtension = _extractFileExtension(filename) + if (!fileExtension) { + filename += _extractFileExtension(url) ?? '' + } + await _send({ ...props, message: new Document(url, false, title, filename) }) + break + case 'location': + await _send({ ...props, message: new Location(item.payload.longitude, item.payload.latitude) }) + break + default: + props.logger.forBot().warn('The type passed in bloc is not supported') + continue + } + } }, }, }