A Node client for RCS MaaP chatbots.
Requires Node >=4.0.0.
npm install rcs-maap-bot
See more examples in the example folder.
const http = require('http')
const Maap = require('rcs-maap-bot')
let bot = new Maap.Bot({
token: 'TOKEN',
api_url: 'API_URL',
bot_id: 'BOT_ID'
})
bot.on('error', (err) => {
console.log(err.message)
})
bot.on('message', (payload, reply) => {
reply(
"You wrote: " + payload.RCSMessage.textMessage,
null,
(err, body) => {
if (err) throw err
}
)
})
http.createServer(bot.handleWebhook()).listen(3000)
console.log('Echo bot server running on port 3000.')
reply
Is a convenience function that calls bot.sendMessage
, with the recipient already set to the message
sender.
An example of calling bot.sendMessage
with suggestions
is below:
bot.on('message', (payload, reply) => {
let suggestions = new Maap.Suggestions();
suggestions.addReply('English', 'Language_en');
suggestions.addReply('日本語', 'Language_jp');
bot.sendMessage(
payload.messageContact,
"What language do you prefer?",
suggestions,
(err, body) => {
if (err) throw err
}
)
})
Specifiying the recipient
can be done by creating a MessageContact
object:
bot.on('message', (payload, reply) => {
let suggestions = new Maap.Suggestions();
suggestions.addReply('English', 'Language_en');
suggestions.addReply('日本語', 'Language_jp');
bot.sendMessage(
new Maap.MessageContact("+18055551234", null),
"What language do you prefer?",
suggestions,
(err, body) => {
if (err) throw err
}
)
})
Returns a new Bot
instance.
opts
- Object
token
- String: The authentication token for your bot.api_url
- String: The URL to the MaaP gateway endpoint (http://host:port/serverRoot/rcs/bot/v1).bot_id
- String: The identifier for your bot.
Sends a message with content
and optional suggestions
to the target recipient
, and calls the callback if any. Returns a promise.
recipient
- Object: AMessageContact
object.content
- Object: The message payload. Either a string, anAudioMessage
object, aFileMessage
object, aGeolocationPushMessage
object, aRichcard
object, or aRichcardCarousel
object.suggestions
- (Optional) Object: ASuggestions
object.cb
- (Optional) Function: Called with(err, body)
once the request has completed.err
contains an error, if any, andbody
contains the response from the MaaP gateway.
Gets the status of a message with messageId
, and calls the callback if any. Returns a promise.
messageId
- String: The message identifier.cb
- (Optional) Function: Called with(err, body)
once the request has completed.err
contains an error, if any, andbody
contains the response from the MaaP gateway.
Updates the status of a message with messageId
to status
, and calls the callback if any. Returns a promise.
messageId
- String: The message identifier.status
- String: The requested status. Needs to be eitherMaap.MESSAGE_STATUS_CANCELLED
orMaap.MESSAGE_STATUS_DISPLAYED
.cb
- (Optional) Function: Called with(err, body)
once the request has completed.err
contains an error, if any, andbody
contains the response from the MaaP gateway.
Gets the capabilities for a subscriber, and calls the callback if any. Returns a promise. Either userContact
or chatId
needs to be specified.
userContact
- String: The subscriber's MSISDN.chatId
- String: The user's anonymous token.cb
- (Optional) Function: Called with(err, body)
once the request has completed.err
contains an error, if any, andbody
contains the response from the MaaP gateway.
Uploads a file of type fileType
to the MaaP content storage until it expires at date until
, and calls the callback if any. Returns a promise. Either path
or url
needs to be specified.
path
- String: The path to the file.url
- String: The URL to the file.fileType
- String: The file's content type.until
- Date: The date at which time the content should be expired.cb
- (Optional) Function: Called with(err, body)
once the request has completed.err
contains an error, if any, andbody
contains the response from the MaaP gateway.
Deletes a file with identifier fileId
from the MaaP content storage, and calls the callback if any. Returns a promise.
fileId
- String: The file identifier.cb
- (Optional) Function: Called with(err, body)
once the request has completed.err
contains an error, if any, andbody
contains the response from the MaaP gateway.
Gets info for a file with identifier fileId
from the MaaP content storage, and calls the callback if any. Returns a promise.
fileId
- String: The file identifier.cb
- (Optional) Function: Called with(err, body)
once the request has completed.err
contains an error, if any, andbody
contains the response from the MaaP gateway.
Starts the 'is typing' indicator for the target recipient
, and calls the callback if any. Returns a promise.
recipient
- Object: AMessageContact
object.cb
- (Optional) Function: Called with(err, body)
once the request has completed.err
contains an error, if any, andbody
contains the response from the MaaP gateway.
Stops the 'is typing' indicator for the target recipient
, and calls the callback if any. Returns a promise.
recipient
- Object: AMessageContact
object.cb
- (Optional) Function: Called with(err, body)
once the request has completed.err
contains an error, if any, andbody
contains the response from the MaaP gateway.
The main middleware for your bot's webhook. Returns a function.
The underlying method used by bot.handleWebhook()
to parse the message payload, and fire the appropriate events.
An FileMessage
object representes a file and has the following properties:
Property | Type | Mandatory | Description |
---|---|---|---|
fileUrl |
String | Yes | The URL of the file. |
fileName |
String | No | The file name. |
fileMIMEType |
String | No | The MIME type of the file. |
fileSize |
Number | No | The size of the file. |
thumbnailUrl |
String | No | The URL of the thumbnail. |
thumbnailFileName |
String | No | The file name of the thumbnail. |
thumbnailMIMEType |
String | No | The MIME type of the thumbnail. |
thumbnailFileSize |
Number | No | The size of the thumbnail. |
Returns a new FileMessage
instance.
fileUrl
- String: The URL of the file.
Set the fileName
property.
fileName
- String: The file name.
Set the fileMIMEType
property.
fileMIMEType
- String: The MIME type of the file.
Set the fileSize
property.
fileSize
- Number: The size of the file.
Set the thumbnailUrl
property.
thumbnailUrl
- String: The URL of the thumbnail.
Set the thumbnailFileName
property.
thumbnailFileName
- String: The file name of the thumbnail.
Set the thumbnailMIMEType
property.
thumbnailMIMEType
- String: The MIME type of the thumbnail.
Set the thumbnailFileSize
property.
thumbnailFileSize
- Number: The size of the thumbnail.
An AudioMessage
object representes an audio file and has the following properties:
Property | Type | Mandatory | Description |
---|---|---|---|
fileUrl |
String | Yes | The URL of the file. |
fileName |
String | No | The file name. |
fileMIMEType |
String | No | The MIME type of the file. |
fileSize |
Number | No | The size of the file. |
playingLength |
Number | No | The playing length of the audio. |
Returns a new AudioMessage
instance.
fileUrl
- String: The URL of the file.
Set the fileName
property.
fileName
- String: The file name.
Set the fileMIMEType
property.
fileMIMEType
- String: The MIME type of the file.
Set the fileSize
property.
fileSize
- Number: The size of the file.
Set the playingLength
property.
playingLength
- Number: The playing length of the audio.
Property | Type | Mandatory | Description |
---|---|---|---|
pos |
String | Yes | This are the coordinates in WGS 84 (latitude, longitude) decimal notation. Example "26.118 1289 - 80.1283921" |
label |
String | No | This can be used to tag the nature of the location. |
timestamp |
String | No | This is the time when the location information was pushed. |
expiry |
String | No | This is an absolute date at which time the recipient is no longer permitted to possess the location information. |
timeOffset |
Number | No | This is the time zone where the location information was pushed, expressed as the number of minutes away from UTC. |
radius |
Number | No | The radius of the circle will be represented in meters. |
Returns a new GeolocationPushMessage
instance. This is a geolocation push to be sent via RCS Geolocation Push.
pos
- String: This are the coordinates in WGS 84 (latitude, longitude) decimal notation.
Set the label
property.
label
- String: This can be used to tag the nature of the location.
Set the timestamp
property.
timestamp
- String: This is the time when the location information was pushed.
Set the expiry
property.
expiry
- String: This is an absolute date at which time the recipient is no longer permitted to possess the location information.
Set the timeOffset
property.
timeOffset
- Number: This is the time zone where the location information was pushed, expressed as the number of minutes away from UTC.
Set the radius
property.
radius
- Number: The radius of the circle will be represented in meters.
Returns a new Richcard
instance.
Set the orientation of the card.
cardOrientation
- String: EitherMaap.ORIENTATION_HORIZONTAL
orMaap.ORIENTATION_VERTICAL
.
Set the alignment of the image on the card.
imageAlignment
- String: EitherMaap.ALIGNMENT_LEFT
orMaap.ALIGNMENT_RIGHT
.
setMedia(mediaUrl, mediaContentType, mediaFileSize, height, [thumbnailUrl], [thumbnailContentType], [thumbnailFileSize], [contentDescription])
Set the media (image) to be displayed on the richcard.
mediaUrl
- String: The URL to the image.mediaContentType
- String: The content type of the image.mediaFileSize
- Number: The size of the image.height
- String: EitherMaap.MEDIA_SHORT_HEIGHT
orMaap.MEDIA_MEDIUM_HEIGHT
orMaap.MEDIA_TALL_HEIGHT
.thumbnailUrl
- (Optional) String: The URL to the thumbnail for the image.thumbnailContentType
- (Optional) String: The content type of the thumbnail.thumbnailFileSize
- (Optional) Number: The size of the thumbnail.contentDescription
- (Optional) String: Textual description of media content.
The thumbnailUrl
property is optional, but if used, thumbnailContentType
and thumbnailFileSize
must be provided as well.
Set the title of the card.
title
- String: The title.
Set the description of the card.
description
- String: The description.
Add suggestions to the card.
suggestions
- Suggestions: The suggestions.
Returns a new RichcardCarousel
instance.
Set the width of the cards in the carousel.
cardWidth
- String: EitherMaap.CARD_WIDTH_SMALL
orMaap.CARD_WIDTH_MEDIUM
.
Add a card to the carousel.
richcard
- Richcard: TheRichcard
object.
Suggested Replies consist of a display text and a set of postback data.
Suggested Actions are grouped into seven different categories supporting a total of twelve different suggested actions:
- urlAction:
- openUrl - Opens a web site or app via deep linking.
- dialerAction:
- dialPhoneNumber - Calls a phone number via the user's dialer app.
- dialEnrichedCall - Start an Enriched Call via the user’s dialer app.
- dialVideoCall - Start a video call via the user’s dialer app.
- mapAction:
- showLocation - Show location(s) on a map for given coordinates or search query.
- requestLocationPush - Request for a one-time geo location push.
- calendarAction:
- createCalendarEvent - Creates a new event on the user's calendar.
- composeAction:
- composeTextMessage - Compose a draft text message.
- composeRecordingMessage - Compose a draft message and start recording audio or video.
- deviceAction:
- requestDeviceSpecifics - Request for a one-time share of device specifics (device model, operating system version, messaging client identifier and version, and remaining battery charge in minutes).
- settingsAction:
- disableAnonymization - Ask the user to disable the anonymization setting.
- enableDisplayedNotifications - Ask the user to enable sending displayed notifications.
Most actions allow fallback URLs in case a user does not have any app of the required type installed. Chatbot platforms can use the fallback URL to suggest an appropriate app to the user.
Returns a new Suggestions
instance.
On-the-wire example:
{
"reply": {
"displayText": "Yes",
"postback": {
"data": "set_by_chatbot_reply_yes"
}
}
}
On-the-wire example:
{
"action": {
"urlAction": {
"openUrl": {
"url": "https://www.google.com"
}
},
"displayText": "Open website or deep link",
"postback": {
"data": "set_by_chatbot_open_url"
}
}
}
On-the-wire example:
{
"action": {
"dialerAction": {
"dialPhoneNumber": {
"phoneNumber": "+1650253000"
}
},
"displayText": "Call a phone number",
"postback": {
"data": "set_by_chatbot_dial_phone_number"
}
}
},
{
"action": {
"dialerAction": {
"dialEnrichedCall": {
"phoneNumber": "+1650253000",
"subject": "The optional subject for the enriched call"
}
},
"displayText": "Start enriched call",
"postback": {
"data": "set_by_chatbot_dial_enriched_call"
}
}
},
{
"action": {
"dialerAction": {
"dialVideoCall": {
"phoneNumber": "+1650253000"
}
},
"displayText": "Start video call",
"postback": {
"data": "set_by_chatbot_dial_video_call"
}
}
}
On-the-wire example:
{
"action": {
"mapAction": {
"requestLocationPush": {}
},
"displayText": "Request a geo location",
"postback": {
"data": "set_by_chatbot_request_location_push"
}
}
}
On-the-wire example:
{
"action": {
"mapAction": {
"showLocation": {
"location": {
"latitude": 37.4220041,
"longitude": -122.0862515,
"label": "Googleplex"
},
"fallbackUrl": "https://www.google.com/maps/@37.4219162,-122.078063,15z"
}
},
"displayText": "Show location on a map",
"postback": {
"data": "set_by_chatbot_show_location"
}
}
},
{
"action": {
"mapAction": {
"showLocation": {
"location": {
"query": "restaurants"
},
"fallbackUrl": "https://www.google.com/maps/search/restaurants"
}
},
"displayText": "Search location(s) on map",
"postback": {
"data": "set_by_chatbot_search_locations"
}
}
}
On-the-wire example:
{
"action": {
"calendarAction": {
"createCalendarEvent": {
"startTime": "2017-03-14T00:00:00Z",
"endTime": "2017-03-14T23:59:59Z",
"title": "Meeting",
"description": "GSG review meeting"
}
},
"displayText": "Schedule Meeting",
"postback": {
"data": "set_by_chatbot_create_calendar_event"
}
}
}
On-the-wire example:
{
"action": {
"composeAction": {
"composeTextMessage": {
"phoneNumber": "+1650253000",
"text": "Draft to go into the send message text field."
}
},
"displayText": "Draft a text message",
"postback": {
"data": "set_by_chatbot_compose_text_message"
}
}
}
On-the-wire example:
{
"action": {
"composeAction": {
"composeRecordingMessage": {
"phoneNumber": "+1650253000",
"type": "VIDEO"
}
},
"displayText": "Record audio or video",
"postback": {
"data": "set_by_chatbot_compose_recording_message"
}
}
}
On-the-wire example:
{
"action": {
"deviceAction": {
"requestDeviceSpecifics": {}
},
"displayText": "Request device specifics",
"postback": {
"data": "set_by_chatbot_request_device_specifics"
}
}
}
On-the-wire example:
{
"action": {
"settingsAction": {
"disableAnonymization": {}
},
"displayText": "Share your phone number",
"postback": {
"data": "set_by_chatbot_disable_anonymization"
}
}
},
{
"action": {
"settingsAction": {
"enableDisplayedNotifications": {}
},
"displayText": "Send read receipts",
"postback": {
"data": "set_by_chatbot_enable_displayed_notifications"
}
}
}
A different event is triggered for each type of event an RCS MaaP chatbot can receive. Below are all the possible events with an example of the payload they provide.
Triggered when a 'message' event is sent to the bot.
payload
- Object: An object containing the 'message' event payload.reply
- Function: A convenience function that callsbot.sendMessage
, with the recipient already set to the message sender.
Example usage:
bot.on('message', (payload, reply) => {
reply('we got your message!', null, (err, info) => {})
})
Sample payload:
{
"RCSMessage": {
"msgId": "Xs8CI3tdf",
"textMessage": "hello world",
"timestamp": "2017-09-26T01:33:20.315Z"
},
"messageContact": {
"userContact": "+14251234567"
},
"event": "message"
}
Triggered when an 'isTyping' event is sent to the bot.
payload
- Object: An object containing the 'isTyping' event payload.reply
- Function: A convenience function that callsbot.sendMessage
, with the recipient already set to the message sender.
Example usage:
bot.on('isTyping', (payload, reply) => {
reply('we see you are typing!', null, (err, info) => {})
})
Sample payload:
{
"RCSMessage": {
"msgId": "Xs8CI3tdf",
"isTyping": "active",
"timestamp": "2017-09-26T01:33:20.315Z"
},
"messageContact": {
"userContact": "+14251234567"
},
"event": "isTyping"
}
Triggered when a 'messageStatus' event is sent to the bot.
payload
- Object: An object containing the 'messageStatus' event payload.reply
- Function: A convenience function that callsbot.sendMessage
, with the recipient already set to the message sender.
Example usage:
bot.on('messageStatus', (payload, reply) => {
reply('you read our message!', null, (err, info) => {})
})
Sample payload:
{
"RCSMessage": {
"msgId": "MzJmajlmamVzZGZ8bmk5MHNlbmRmZTAz",
"status": "displayed",
"timestamp": "2017-09-26T01:33:20.315Z"
},
"messageContact": {
"userContact": "+14251234567"
},
"event": "messageStatus"
}
Triggered when a 'fileStatus' event is sent to the bot.
payload
- Object: An object containing the 'fileStatus' event payload.
Example usage:
bot.on('fileStatus', (payload) => {
console.log('was the file uploaded?')
})
Sample payload:
{
"file": {
"fileId": "MzJmajlmamVzZGZ8bmk5MHNlbmRmZTAz",
"fileUrl": "http://www.example.com/files/f.jpg",
"fileSize": 123456,
"status": "ready",
"validity": "2017-10-03T22:31:00.597Z"
},
"event": "fileStatus"
}
Triggered when a 'response' event is sent to the bot.
payload
- Object: An object containing the 'response' event payload.reply
- Function: A convenience function that callsbot.sendMessage
, with the recipient already set to the message sender.
Example usage:
bot.on('response', (payload, reply) => {
reply('you clicked on a button?', null, (err, info) => {})
})
Sample payload:
{
"RCSMessage": {
"msgId": "MzJmajlmamVzZGZ8bmk5MHNlbmRmZTAz",
"suggestedResponse": {
"response": {
"action": {
"displayText": "Visit Website",
"postback": {
"data": "set_by_chatbot_reply_yes"
}
}
}
},
"timestamp": "2017-09-26T01:33:20.315Z"
},
"messageContact": {
"userContact": "+14251234567"
},
"event": "response"
}
Triggered when a 'alias' event is sent to the bot.
payload
- Object: An object containing the 'alias' event payload.reply
- Function: A convenience function that callsbot.sendMessage
, with the recipient already set to the message sender.
Example usage:
bot.on('alias', (payload, reply) => {
reply('thank you for sharing your info', null, (err, info) => {})
})
Sample payload:
{
"RCSMessage": {
"msgId": "MzJmajlmamVzZGZ8bmk5MHNlbmRmZTAz",
"timestamp": "2017-09-26T01:33:20.315Z"
},
"messageContact": {
"userContact": "+14251234567",
"chatId": "93JF93SEIJFE"
},
"event": "alias"
}
Triggered when a 'newUser' event is sent to the bot.
payload
- Object: An object containing the 'newUser' event payload.reply
- Function: A convenience function that callsbot.sendMessage
, with the recipient already set to the message sender.
Example usage:
bot.on('newUser', (payload, reply) => {
reply('welcome!', null, (err, info) => {})
})
Sample payload:
{
"RCSMessage": {
"msgId": "MzJmajlmamVzZGZ8bmk5MHNlbmRmZTAz",
"suggestedResponse": {
"response": {
"reply": {
"displayText": "Start Chat",
"postback": {
"data": "new_bot_user_initiation"
}
}
}
},
"timestamp": "2017-09-26T01:33:20.315Z"
},
"messageContact": {
"userContact": "+14251234567"
},
"event": "newUser"
}
- Verify constraints before sending
- Look for missing fields like trafficType (there may be more)