From d80b2e91e6a4d09cc8d084b044ce5bc35d04931b Mon Sep 17 00:00:00 2001 From: Saurabh Newatiya Date: Sun, 12 May 2024 12:51:03 +0530 Subject: [PATCH 1/4] Adding support for location whatsapp messages --- CHANGELOG.md | 5 +++ README.md | 63 +++++++++++++++++++++++++++++++++++ lib/resources/messages.js | 29 ++++++++++++++-- lib/utils/common.js | 6 ++++ lib/utils/location.js | 20 +++++++++++ lib/utils/template.js | 2 ++ package.json | 2 +- types/resources/messages.d.ts | 2 ++ 8 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 lib/utils/location.js diff --git a/CHANGELOG.md b/CHANGELOG.md index fe0505ed..1444e224 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## [v4.66.0](https://github.com/plivo/plivo-node/tree/v4.66.0) (2024-05-07) +**Feature - Adding support for location whatsapp messages** +- Added new param `location` to [send message API](https://www.plivo.com/docs/sms/api/message#send-a-message) to support location `whatsapp` messages +- Added new param `location` in templates to support location based templated messages + ## [v4.65.0](https://github.com/plivo/plivo-node/tree/v4.65.0) (2024-05-07) **Feature - Adding support for interactive whatsapp messages** - Added new param `interactive` to [send message API](https://www.plivo.com/docs/sms/api/message#send-a-message) to support interactive `whatsapp` messages diff --git a/README.md b/README.md index 103a94ac..90c2b9bf 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,69 @@ console.log('Phlo run result', result); }); ``` + +## WhatsApp Messaging +Plivo's WhatsApp API allows you to send different types of messages over WhatsApp, including templated messages, free form messages and interactive messages. Below are some examples on how to use the Plivo Go SDK to send these types of messages. + +### Templated Messages +Templated messages are a crucial to your WhatsApp messaging experience, as businesses can only initiate WhatsApp conversation with their customers using templated messages. + +WhatsApp templates support 4 components: `header` , `body`, `footer` and `button`. At the point of sending messages, the template object you see in the code acts as a way to pass the dynamic values within these components. `header` can accomodate `text` or `media` (images, video, documents) content. `body` can accomodate text content. `button` can support dynamic values in a `url` button or to specify a developer-defined payload which will be returned when the WhatsApp user clicks on the `quick_reply` button. `footer` cannot have any dynamic variables. + +Example: +```javascript +``` + +### Free Form Messages +Non-templated or Free Form WhatsApp messages can be sent as a reply to a user-initiated conversation (Service conversation) or if there is an existing ongoing conversation created previously by sending a templated WhatsApp message. + +#### Free Form Text Message +Example: +```javascript +``` + +#### Free Form Media Message +Example: +```javascript +``` + +### Interactive Messages +This guide shows how to send non-templated interactive messages to recipients using Plivo’s APIs. + +#### Quick Reply Buttons +Quick reply buttons allow customers to quickly respond to your message with predefined options. + +Example: +```javascript +``` + +#### Interactive Lists +Interactive lists allow you to present customers with a list of options. + +Example: +```javascript +``` + +#### Interactive CTA URLs +CTA URL messages allow you to send links and call-to-action buttons. + +Example: +```javascript +``` + +### Location Messages +This guide shows how to send templated and non-templated location messages to recipients using Plivo’s APIs. + +#### Templated Location Messages +Example: +```javascript +``` + +#### Non-Templated Location Messages +Example: +```javascript +``` + ### More examples More examples are available [here](https://github.com/plivo/plivo-examples-node). Also refer to the [guides for configuring the Express server to run various scenarios](https://www.plivo.com/docs/sms/quickstart/node-expressjs/) & use it to test out your integration in under 5 minutes. diff --git a/lib/resources/messages.js b/lib/resources/messages.js index 605bc725..b12ad240 100644 --- a/lib/resources/messages.js +++ b/lib/resources/messages.js @@ -196,6 +196,7 @@ export class MessageInterface extends PlivoResourceInterface { * @param {string} [optionalParams.dlt_template_category] This is the DLT template category passed in the message request. * @param {Template} [optionalParams.template] For sending templated whatsapp messages. * @param {Interactive} [optionalParams.interactive] For sending interactive whatsapp messages. + * @param {Location} [optionalParams.location] For sending location whatsapp messages. * @promise {object} return {@link PlivoGenericMessage} object if success * @fail {Error} return Error */ @@ -221,6 +222,7 @@ export class MessageInterface extends PlivoResourceInterface { * @param {string} [optionalParams.dlt_template_id] This is the DLT template id passed in the message request. * @param {string} [optionalParams.dlt_template_category] This is the DLT template category passed in the message request. * @param {Interactive} [optionalParams.interactive] For sending interactive whatsapp messages. + * @param {Location} [optionalParams.location] For sending location whatsapp messages. * @promise {object} return {@link PlivoGenericMessage} object if success * @fail {Error} return Error */ @@ -240,6 +242,7 @@ export class MessageInterface extends PlivoResourceInterface { var messageExpiry = src.messageExpiry; var template = src.template; var interactive = src.interactive; + var location = src.location; var dlt_entity_id = src.dlt_entity_id; var dlt_template_id = src.dlt_template_id; var dlt_template_category = src.dlt_template_category; @@ -303,6 +306,9 @@ export class MessageInterface extends PlivoResourceInterface { if(interactive) { params.interactive = interactive; } + if(location) { + params.location = location; + } if (dlt_entity_id) { params.dlt_entity_id = dlt_entity_id } @@ -322,18 +328,24 @@ export class MessageInterface extends PlivoResourceInterface { }); } - if ((params.type !== 'whatsapp') && params.template){ + if (params.type && (params.type !== 'whatsapp') && params.template){ let errorText = 'Template paramater is only applicable when message_type is whatsapp' return new Promise(function(resolve, reject) { reject(new Error(errorText)); }); } - if ((params.type !== 'whatsapp') && params.interactive) { + if (params.type && (params.type !== 'whatsapp') && params.interactive) { let errorText = 'Interactive paramater is only applicable when message_type is whatsapp' return new Promise(function(resolve, reject) { reject(new Error(errorText)); }); } + if (params.type && (params.type !== 'whatsapp') && params.location) { + let errorText = 'Location paramater is only applicable when message_type is whatsapp' + return new Promise(function(resolve, reject) { + reject(new Error(errorText)); + }); + } if (params.template){ let errors = validate([{ @@ -361,6 +373,19 @@ export class MessageInterface extends PlivoResourceInterface { } } + if (params.location){ + let errors = validate([{ + field: 'location', + value: params.location, + validators: ['isLocation'] + }, + ]); + + if (errors) { + return errors; + } + } + if (src) { params.src = src; } diff --git a/lib/utils/common.js b/lib/utils/common.js index 009207c9..6f6cad3f 100644 --- a/lib/utils/common.js +++ b/lib/utils/common.js @@ -1,5 +1,6 @@ import { validateTemplate } from '../utils/template.js'; import { validateInteractive } from '../utils/interactive.js'; +import { validateLocation } from '../utils/location.js'; export let extend = (instance, data) => { data = data || {}; @@ -45,6 +46,11 @@ export let validate = (() => { const { error, value } = validateInteractive(field); return {error, value} }; + + Validators.isLocation = field => { + const { error, value } = validateLocation(field); + return {error, value} + }; return (data = []) => { diff --git a/lib/utils/location.js b/lib/utils/location.js new file mode 100644 index 00000000..1a8f8ac0 --- /dev/null +++ b/lib/utils/location.js @@ -0,0 +1,20 @@ +const Joi = require('joi'); + +// Schema for Location +const locationSchema = Joi.object({ + latitude: Joi.string().required(), + longitude: Joi.string().required(), + name: Joi.string().required(), + address: Joi.string().required() +}); + +// Function to validate location data +function validateLocation(data) { + const { error, value } = locationSchema.validate(data, { allowUnknown: true }); + return { error, value }; + } + +module.exports = { + locationSchema, + validateLocation +}; diff --git a/lib/utils/template.js b/lib/utils/template.js index ede01001..e88e4fe1 100644 --- a/lib/utils/template.js +++ b/lib/utils/template.js @@ -1,4 +1,5 @@ const Joi = require('joi'); +const { locationSchema } = require('./location'); const currencySchema = Joi.object({ fallback_value: Joi.string().required(), @@ -17,6 +18,7 @@ const parameterSchema = Joi.object({ payload: Joi.string().optional(), currency: currencySchema.optional(), date_time: dateTimeSchema.optional(), + location: locationSchema.optional(), }); const componentSchema = Joi.object({ diff --git a/package.json b/package.json index 25baba3e..576e75dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "plivo", - "version": "4.65.0", + "version": "4.66.0", "description": "A Node.js SDK to make voice calls and send SMS using Plivo and to generate Plivo XML", "homepage": "https://github.com/plivo/plivo-node", "files": [ diff --git a/types/resources/messages.d.ts b/types/resources/messages.d.ts index 9ab1847d..dc518699 100644 --- a/types/resources/messages.d.ts +++ b/types/resources/messages.d.ts @@ -92,6 +92,7 @@ export class MessageInterface extends PlivoResourceInterface { * @param {boolean} [optionalParams.log] If set to false, the content of this message will not be logged on the Plivo infrastructure and the dst value will be masked (e.g., 141XXXXX528). Default is set to true. * @param {Template} [optionalParams.template] For sending templated whatsapp messages. * @param {Interactive} [optionalParams.interactive] For sending interactive whatsapp messages. + * @param {Location} [optionalParams.location] For sending location whatsapp messages. * @promise {object} return {@link PlivoGenericMessage} object if success * @fail {Error} return Error */ @@ -116,6 +117,7 @@ export class MessageInterface extends PlivoResourceInterface { * @param {Array} [optionalParams.media_urls] For sending mms, specify the media urls in list of string * @param {Template} [optionalParams.template] For sending templated whatsapp messages. * @param {Interactive} [optionalParams.interactive] For sending interactive whatsapp messages. + * @param {Location} [optionalParams.location] For sending location whatsapp messages. * @promise {object} return {@link MessageResponse} object if success * @fail {Error} return Error */ From 52d9e336ba7fe1f9238aad795c72d86b9c774fa2 Mon Sep 17 00:00:00 2001 From: Saurabh Newatiya Date: Thu, 16 May 2024 17:07:48 +0530 Subject: [PATCH 2/4] removing type check for whatsapp cases --- lib/resources/messages.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/lib/resources/messages.js b/lib/resources/messages.js index b12ad240..34a6ac81 100644 --- a/lib/resources/messages.js +++ b/lib/resources/messages.js @@ -328,25 +328,6 @@ export class MessageInterface extends PlivoResourceInterface { }); } - if (params.type && (params.type !== 'whatsapp') && params.template){ - let errorText = 'Template paramater is only applicable when message_type is whatsapp' - return new Promise(function(resolve, reject) { - reject(new Error(errorText)); - }); - } - if (params.type && (params.type !== 'whatsapp') && params.interactive) { - let errorText = 'Interactive paramater is only applicable when message_type is whatsapp' - return new Promise(function(resolve, reject) { - reject(new Error(errorText)); - }); - } - if (params.type && (params.type !== 'whatsapp') && params.location) { - let errorText = 'Location paramater is only applicable when message_type is whatsapp' - return new Promise(function(resolve, reject) { - reject(new Error(errorText)); - }); - } - if (params.template){ let errors = validate([{ field: 'template', From 6857690d4f78f42b7bdaa622db6fe3781ec26a35 Mon Sep 17 00:00:00 2001 From: Saurabh Newatiya Date: Fri, 17 May 2024 12:11:08 +0530 Subject: [PATCH 3/4] updating README with whatsapp samples --- README.md | 250 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) diff --git a/README.md b/README.md index 90c2b9bf..db11d708 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,43 @@ WhatsApp templates support 4 components: `header` , `body`, `footer` and `bu Example: ```javascript +var plivo = require('plivo'); + +var client = new plivo.Client("", ""); + +const template = { + "name": "template_name", + "language": "en_US", + "components": [ + { + "type": "header", + "parameters": [ + { + "type": "media", + "media": "https://xyz.com/s3/img.jpg" + } + ] + }, + { + "type": "body", + "parameters": [ + { + "type": "text", + "text": "WA-Text" + } + ] + } + ] + } +client.messages.create({ + src:"+14156667778", + dst:"+14156667777", + type:"whatsapp", + template:template, + url: "https://foo.com/wa_status/" +}).then(function (response) { + console.log(response); +}); ``` ### Free Form Messages @@ -143,11 +180,36 @@ Non-templated or Free Form WhatsApp messages can be sent as a reply to a user-in #### Free Form Text Message Example: ```javascript +var plivo = require('plivo'); + +var client = new plivo.Client("", ""); +client.messages.create({ + src:"+14156667778", + dst:"+14156667777", + type:"whatsapp", + text: "Hello, this is sample text", + url: "https://foo.com/wa_status/" +}).then(function (response) { + console.log(response); +}); ``` #### Free Form Media Message Example: ```javascript +var plivo = require('plivo'); + +var client = new plivo.Client("", ""); +client.messages.create({ + src:"+14156667778", + dst:"+14156667777", + type:"whatsapp", + text: "Hello, this is sample text", + media_urls:["https://sample-videos.com/img/Sample-png-image-1mb.png"], + url: "https://foo.com/wa_status/" +}).then(function (response) { + console.log(response); +}); ``` ### Interactive Messages @@ -158,6 +220,45 @@ Quick reply buttons allow customers to quickly respond to your message with pred Example: ```javascript +let plivo = require('plivo'); + +var client = new plivo.Client("",""); + +const interactive = { + "type": "button", + "header": { + "type": "media", + "media": "https://xyz.com/s3/img.jpg" + }, + "body": { + "text": "Make your selection" + }, + "action": { + "buttons": [ + { + "title": "Click here", + "id": "bt1" + }, + { + "title": "Know More", + "id": "bt2" + }, + { + "title": "Request Callback", + "id": "bt3" + } + ] + } + } + +client.messages.create({ + src:"+14156667778", + dst:"+14156667777", + type:"whatsapp", + interactive:interactive +}).then(function (response) { + console.log(response); +}); ``` #### Interactive Lists @@ -165,6 +266,69 @@ Interactive lists allow you to present customers with a list of options. Example: ```javascript +let plivo = require('plivo'); + +var client = new plivo.Client("",""); + +const interactive = { + "type": "list", + "header": { + "type": "text", + "text": "Welcome to Plivo" + }, + "body": { + "text": "You can review the list of rewards we offer" + }, + "footer": { + "text": "Yours Truly" + }, + "action": { + "buttons": [{ + "title": "Click here" + }], + "sections": [ + { + "title": "SECTION_1_TITLE", + "rows": [ + { + "id": "SECTION_1_ROW_1_ID", + "title": "SECTION_1_ROW_1_TITLE", + "description": "SECTION_1_ROW_1_DESCRIPTION" + }, + { + "id": "SECTION_1_ROW_2_ID", + "title": "SECTION_1_ROW_2_TITLE", + "description": "SECTION_1_ROW_2_DESCRIPTION" + } + ] + }, + { + "title": "SECTION_2_TITLE", + "rows": [ + { + "id": "SECTION_2_ROW_1_ID", + "title": "SECTION_2_ROW_1_TITLE", + "description": "SECTION_2_ROW_1_DESCRIPTION" + }, + { + "id": "SECTION_2_ROW_2_ID", + "title": "SECTION_2_ROW_2_TITLE", + "description": "SECTION_2_ROW_2_DESCRIPTION" + } + ] + } + ] + } + } + +client.messages.create({ + src:"+14156667778", + dst:"+14156667777", + type:"whatsapp", + interactive:interactive +}).then(function (response) { + console.log(response); +}); ``` #### Interactive CTA URLs @@ -172,6 +336,40 @@ CTA URL messages allow you to send links and call-to-action buttons. Example: ```javascript +let plivo = require('plivo'); + +var client = new plivo.Client("",""); + +const interactive = { + "type": "cta_url", + "header": { + "type": "media", + "media": "https://xyz.com/s3/img.jpg" + }, + "body": { + "text": "Know More" + }, + "footer": { + "text": "Plivo" + }, + "action": { + "buttons": [ + { + "title": "Click here", + "cta_url": "https:plivo.com" + } + ] + } + } + +client.messages.create({ + src:"+14156667778", + dst:"+14156667777", + type:"whatsapp", + interactive:interactive +}).then(function (response) { + console.log(response); +}); ``` ### Location Messages @@ -180,11 +378,63 @@ This guide shows how to send templated and non-templated location messages to re #### Templated Location Messages Example: ```javascript +let plivo = require('plivo'); + +var client = new plivo.Client("",""); + +const template = { + "name": "plivo_order_pickup", + "language": "en_US", + "components": [ + { + "type": "header", + "parameters": [ + { + "type": "location", + "location": { + "longitude": "122.148981", + "latitude": "37.483307", + "name": "Pablo Morales", + "address": "1 Hacker Way, Menlo Park, CA 94025" + } + } + ] + } + ] + } + +client.messages.create({ + src:"+14156667778", + dst:"+14156667777", + type:"whatsapp", + template:template +}).then(function (response) { + console.log(response); +}); ``` #### Non-Templated Location Messages Example: ```javascript +let plivo = require('plivo'); + +var client = new plivo.Client("",""); + +const location = { + "longitude": "122.148981", + "latitude": "37.483307", + "name": "Pablo Morales", + "address": "1 Hacker Way, Menlo Park, CA 94025" + } + +client.messages.create({ + src:"+14156667778", + dst:"+14156667777", + type:"whatsapp", + location:location +}).then(function (response) { + console.log(response); +}); ``` ### More examples From 59b5515e3217cef840f2161de81d7320321c121e Mon Sep 17 00:00:00 2001 From: Saurabh Newatiya Date: Fri, 17 May 2024 15:18:01 +0530 Subject: [PATCH 4/4] updating release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1444e224..355726ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change Log -## [v4.66.0](https://github.com/plivo/plivo-node/tree/v4.66.0) (2024-05-07) +## [v4.66.0](https://github.com/plivo/plivo-node/tree/v4.66.0) (2024-05-17) **Feature - Adding support for location whatsapp messages** - Added new param `location` to [send message API](https://www.plivo.com/docs/sms/api/message#send-a-message) to support location `whatsapp` messages - Added new param `location` in templates to support location based templated messages