README.md
<img src="https://raw.githubusercontent.com/miki2826/botly/master/botly_logo.png" width="250" height="250" />
[![Built with Grunt](https://cdn.gruntjs.com/builtwith.svg)](http://gruntjs.com/)
[![Build Status](https://travis-ci.org/miki2826/botly.svg)](https://travis-ci.org/miki2826/botly)
[![Test Coverage](https://codeclimate.com/github/Askrround/botly/badges/coverage.svg)](https://codeclimate.com/github/Askrround/botly/coverage)
[![npm version](https://badge.fury.io/js/botly.svg)](http://badge.fury.io/js/botly)
[![Dependency Status](https://david-dm.org/Askrround/botly.svg?theme=shields.io)](https://david-dm.org/Askrround/botly)
[![devDependency Status](https://david-dm.org/Askrround/botly/dev-status.svg?theme=shields.io)](https://david-dm.org/Askrround/botly#info=devDependencies)
[![npm downloads](https://img.shields.io/npm/dm/botly.svg)](https://img.shields.io/npm/dm/botly.svg)
[![license](https://img.shields.io/npm/l/botly.svg)](LICENSE)
[![NPM](https://nodei.co/npm/botly.png?downloads=true&downloadRank=true)](https://nodei.co/npm/botly/)
> Simple Facebook Messenger Platform Bot API
- [Install](#install)
- [Example](#example)
- [API](#api)
- [send (options[, callback])](#send-options-callback)
- [upload (options[, callback])](#upload-options-callback)
- [sendText (options[, callback])](#sendtext-options-callback)
- [sendAttachment (options[, callback])](#sendattachment-options-callback)
- [sendImage (options[, callback])](#sendimage-options-callback)
- [sendButtons (options[, callback])](#sendbuttons-options-callback)
- [sendGeneric (options[, callback])](#sendgeneric-options-callback)
- [sendList (options[, callback])](#sendlist-options-callback)
- [sendOpenGraph (options[, callback])](#sendopengraph-options-callback)
- [sendAction (options[, callback])](#sendaction-options-callback)
- [sendReceipt (options[, callback])](#sendreceipt-options-callback)
- [setGetStarted (options[, callback])](#setgetstarted-options-callback)
- [setGreetingText (options[, callback])](#setgreetingtext-options-callback)
- [setTargetAudience (options[, callback])](#settargetaudience-options-callback)
- [setWhitelist (options[, callback])](#setwhitelist-options-callback)
- [setPersistentMenu (options[, callback])](#setpersistentmenue-options-callback)
- [removePersistentMenu (options[, callback])](#removepersistentmenue-options-callback)]
- [getUserProfile (options[, callback])](#getuserprofile-options-callback)
- [getPSID (accountLinkingToken[, callback])](#getpsid-accountlinkingtoken-callback)
- [createWebURLButton (title, url[, heightRatio][, supportExtension][, fallbackURL][, disableShare])](#createweburlbutton-title-url-heightratio-supportextension-fallbackurl-disableshare)
- [createAccountLinkButton (url)](#createaccountlinkbutton-url)
- [createPostbackButton (title, payload)](#createpostbackbutton-title-payload)
- [createShareButton ()](#createsharebutton-)
- [createQuickReply (title, payload[, imageURL])](#createquickreply-title-payload-imageurl)
- [createShareLocation ()](#createsharelocation-)
- [createListElement (options)](#createlistelement-options)
- [createOpenGraphElement (options)](#createopengraphelement-options)
- [createButtonTemplate (text, buttons)](#createbuttontemplate-text-buttons)
- [createGenericTemplate (elements[, aspectRatio])](#creategenerictemplate-elements-aspectratio)
- [createListTemplate (options)](#createlisttemplate-options)
- [createOpenGraphTemplate (elements])](#createopengraphtemplate-elements-aspectratio)
- [handleMessage (req)](#handlemessage-req)
- [Events](#events)
- [Change Log](#change-log)
### Install
`npm i botly --save`
### Example
```javascript
const express = require("express");
const bodyParser = require("body-parser");
const Botly = require("botly");
const botly = new Botly({
accessToken: pageAccessToken, // page access token provided by facebook
verifyToken: verificationToken, // needed when using express - the verification token you provided when defining the webhook in facebook
webHookPath: yourWebHookPath, // defaults to "/",
notificationType: Botly.CONST.REGULAR, // already the default (optional)
FB_URL: 'https://graph.facebook.com/v2.6/' // this is the default - allows overriding for testing purposes
});
botly.on("message", (senderId, message, data) => {
let text = `echo: ${data.text}`;
botly.sendText({
id: senderId,
text: text
});
});
const app = express();
app.use(bodyParser.json({
verify: botly.getVerifySignature(process.env.APP_SECRET) //allow signature verification based on the app secret
}));
app.use(bodyParser.urlencoded({ extended: false }));
app.use("/webhook", botly.router());
app.listen(3000);
```
You can also clone the repository and run a complete bot example from the `example` folder.
### API
#### send (options[, callback])
```javascript
botly.send({
id: userId,
message: {text: "Hi There!"}
}, function (err, data) {
//log it
});
```
#### upload (options[, callback])
```javascript
botly.upload({
type: Botly.CONST.ATTACHMENT_TYPE.IMAGE,
payload: {url: "http://example.com/image.png"}
}, (err, data) => {
//save data.attachment_id
});
```
#### sendText (options[, callback])
```javascript
botly.sendText({id: userId, text: "Hi There!"}, function (err, data) {
//log it
});
```
#### sendAttachment (options[, callback])
Also supports `options.filedata = '@/tmp/receipt.pdf'`.
```javascript
botly.sendAttachment({
id: userId,
type: Botly.CONST.ATTACHMENT_TYPE.IMAGE,
payload: {url: "http://example.com/image.png"}
}, (err, data) => {
//log it
});
```
#### sendImage (options[, callback])
```javascript
botly.sendImage({id: userId, url: "http://example.com/image.png"}, (err, data) => {
//log it
});
```
#### sendButtons (options[, callback])
```javascript
let buttons = [];
buttons.push(botly.createWebURLButton("Go to Askrround", "http://askrround.com"));
buttons.push(botly.createPostbackButton("Continue", "continue"));
botly.sendButtons({id: userId, text: "What do you want to do next?", buttons: buttons}
, (err, data) => {
//log it
});
```
#### sendGeneric (options[, callback])
```javascript
let buttons = [];
buttons.push(botly.createWebURLButton("Go to Askrround", "http://askrround.com"));
buttons.push(botly.createPostbackButton("Continue", "continue"));
let element = {
title: "What do you want to do next?",
item_url: "http://example.com",
image_url: "http://example.com/image.png",
subtitle: "Choose now!",
buttons: buttons
}
botly.sendGeneric({id: userId, elements: element, aspectRatio: Botly.CONST.IMAGE_ASPECT_RATIO.HORIZONTAL}, (err, data) => {
console.log("send generic cb:", err, data);
});
```
#### sendList (options[, callback])
```javascript
const element = botly.createListElement({
title: 'First Element',
image_url: 'https://peterssendreceiveapp.ngrok.io/img/collection.png',
subtitle: 'subtitle text',
buttons: [
{title: 'Payload Button', payload: 'first_element'},
],
default_action: {
'url': 'https://peterssendreceiveapp.ngrok.io/shop_collection',
}
});
const element2 = botly.createListElement({
title: 'Other Element',
image_url: 'https://peterssendreceiveapp.ngrok.io/img/collection.png',
subtitle: 'even more subtitle',
buttons: [
{title: "Go to Askrround", url: "http://askrround.com"},
],
default_action: {
'url': 'https://peterssendreceiveapp.ngrok.io/shop_collection',
}
});
botly.sendList({id: sender, elements: [element, element2], buttons: botly.createPostbackButton('More Plans', 'MORE_PLANS'), top_element_style: Botly.CONST.TOP_ELEMENT_STYLE.LARGE},function (err, data) {
console.log('send list cb:', err, data);
});
```
#### sendAction (options[, callback])
```javascript
botly.sendAction({id: userId, action: Botly.CONST.ACTION_TYPES.TYPING_ON}, (err, data) => {
//log it
});
```
#### sendReceipt (options[, callback])
```javascript
let payload = {
"recipient_name": "Stephane Crozatier",
"order_number": "12345678902",
"currency": "USD",
"payment_method": "Visa 2345",
"order_url": "http://petersapparel.parseapp.com/order?order_id=123456",
"timestamp": "1428444852",
"elements": [
{
"title": "Classic White T-Shirt",
"subtitle": "100% Soft and Luxurious Cotton",
"quantity": 2,
"price": 50,
"currency": "USD",
"image_url": "http://petersapparel.parseapp.com/img/whiteshirt.png"
},
{
"title": "Classic Gray T-Shirt",
"subtitle": "100% Soft and Luxurious Cotton",
"quantity": 1,
"price": 25,
"currency": "USD",
"image_url": "http://petersapparel.parseapp.com/img/grayshirt.png"
}
],
"address": {
"street_1": "1 Hacker Way",
"street_2": "",
"city": "Menlo Park",
"postal_code": "94025",
"state": "CA",
"country": "US"
},
"summary": {
"subtotal": 75.00,
"shipping_cost": 4.95,
"total_tax": 6.19,
"total_cost": 56.14
},
"adjustments": [
{
"name": "New Customer Discount",
"amount": 20
},
{
"name": "$10 Off Coupon",
"amount": 10
}
]
};
botly.sendReceipt({id: sender, payload: payload}, function (err, data) {
console.log("send generic cb:", err, data);
});
```
#### setGetStarted (options[, callback])
```javascript
botly.setGetStarted({pageId: "myPage", payload: "GET_STARTED_CLICKED"}, (err, body) => {
//log it
});
```
#### setGreetingText (options[, callback])
```javascript
botly.setGreetingText({
pageId: "myPage",
greeting: [{
"locale":"default",
"text":"Hello!"
}, {
"locale":"en_US",
"text":"Timeless apparel for the masses."
}]}, (err, body) => {
//log it
});
```
#### setTargetAudience (options[, callback])
```javascript
botly.setTargetAudience({
pageId: "myPage",
audience: {
"audience_type":"custom",
"countries":{
"whitelist":["US", "CA"]
}
}}, (err, body) => {
//log it
});
```
#### setWhitelist (options[, callback])
```javascript
botly.setWhitelist({whiteList: ["https://askhaley.com"]}, (err, body) => {
//log it
});
```
#### setPersistentMenu (options[, callback])
```javascript
botly.setPersistentMenu({
pageId: "myPage",
menu: [
{
"locale":"default",
"composer_input_disabled":true,
"call_to_actions":[
{
"title":"My Account",
"type":"nested",
"call_to_actions":[
{
"title":"Pay Bill",
"type":"postback",
"payload":"PAYBILL_PAYLOAD"
},
{
"title":"History",
"type":"postback",
"payload":"HISTORY_PAYLOAD"
},
{
"title":"Contact Info",
"type":"postback",
"payload":"CONTACT_INFO_PAYLOAD"
}
]
},
{
"type":"web_url",
"title":"Latest News",
"url":"http://petershats.parseapp.com/hat-news",
"webview_height_ratio":"full"
}
]
},
{
"locale":"zh_CN",
"composer_input_disabled":false
}
]}, (err, body) => {
//log it
});
```
#### removePersistentMenu (options[, callback])
```javascript
botly.removePersistentMenu(
{
pageId: "myPage",
},
(err, body) => {
//log it
});
```
#### getUserProfile (options[, callback])
Used to retrieve basic profile details by user page-scoped ID (PSID). You can pass the `userID` directly, in which case a default set of fields (`first_name`, `last_name`, `profile_pic`) are requested.
Also supports passing an object as
```javascript
const options = {
id: userId,
fields: [
Botly.CONST.USER_PROFILE_FIELD.FIRST_NAME,
Botly.CONST.USER_PROFILE_FIELD.LAST_NAME
],
accessToken: OTHER_TOKEN
}
botly.getUserProfile(options, function (err, info) {
//cache it
});
```
or
```javascript
botly.getUserProfile(userId, function (err, info) {
//cache it
});
```
#### getPSID (accountLinkingToken[, callback])
Used to retrieve the user page-scoped ID (PSID) during the linking flow.
Also supports passing an object as `{token: accountLinkingToken, accessToken: OTHER_TOKEN}`
```javascript
botly.getUserProfile(accountLinkingToken, function (err, info) {
//cache it
});
```
#### createWebURLButton (title, url[, heightRatio][, supportExtension][, fallbackURL][, disableShare])
#### createAccountLinkButton (url)
#### createPostbackButton (title, payload)
### createShareButton ()
#### createQuickReply (title, payload[, imageURL])
`sendAttachment` and `sendText` both support optional `quick_replies`
### createShareLocation ()
share location quick reply
#### createListElement (options)
Will create a list element. `default_action` will be added `web_url` type, and will create button according to properties (`url` means `web_url` and `payload` means `postback`)
#### createButtonTemplate (text, buttons)
Where `buttons` can be a single button or an array of buttons.
#### createGenericTemplate (elements[, aspectRatio])
Where `elements` can be a single element or an array of elements.
and `aspectRatio` defaults to `horizontal`
#### createListTemplate (options)
Where `options` has `bottons` and `elements` - an array will be created automatically if a single item was passed.
#### handleMessage (req)
If you are not using express, you can use this function to parse the request from facebook in order to generate the proper events.
`req` should have a body property.
### Events
```javascript
botly.on("message", (sender, message, data) => {
/**
* where data can be a text message or an attachment
* data = {
* text: "text entered by user"
* }
* OR
* data = {
* attachments: {
* image: ["imageURL1", "imageURL2"],
* video: ["videoURL"],
* audio: ["audioURL1"],
* location: [{coordinates}]
* }
* }
*/
});
botly.on("postback", (sender, message, postback, ref) => {
/**
* where postback is the postback payload
* and ref will arrive if m.me params were passed on a get started button (if defined)
*/
});
botly.on("delivery", (sender, message, mids) => {
/**
* where mids is an array of mids
*/
});
botly.on("optin", (sender, message, optin) => {
/**
* where optin is the ref pass through param
*/
});
botly.on("error", (ex) => {
/* handle exceptions */
});
botly.on("sent", (to, message) => {
/* track it */
});
botly.on("echo", (sender, message, content, recipient) => {
/* track it */
});
botly.on("account_link", (sender, message, link) => {
/**
* where link is the the object containing the status and authorization code
*/
});
botly.on("referral", (sender, message, ref) => {
/**
* where ref is the data in the m.me param
*/
});
```
### Change Log
### version 1.5.0
- added required `messaging_type` parameter when sending message
- added the ability to override the `FB_URL` for testing purposes
- added `getVerifySignature(APP_SECRET)` function to allow signature verification - provide the result to `bodyParser.json({verify})`
### version 1.4.0
- support version 1.4 of messenger api
- new `setPersistentMenu` API aligned with v1.4
- added `setGreetingText`, `setAccountLinkingURL`, `setTargetAudience` API
- aligned all thread settings to the new profile API
- added support for filedata upload in the `sendAttachment`
- added support for the new upload attachment API,
- support for new image_aspect_ratio in generic template
### version 1.3.0
- support version 1.3 of messenger including the new list template
- support for referral params on m.me links
### version 1.2.0
- added support for webview height in web url button
- added support setWhitelist for webview items
- added createShare button
- added support for location share quick reply
- added imageURL to quick reply
#### version 1.1.6
- Send 403 status code when verify token is invalid
#### version 1.1.5
- fixed duplicate messages on echo
- added echo event support
#### version 1.1.4
- added support for account linking functionality (event, getPSID)
- added ability to override accessToken on all APIs for multiple pages support
#### version 1.1.0
- added support for sender actions using `sendAction` (mark seen/ typing on/ typing off)
#### version 1.0.3
- added send event - useful for tracking
#### version 1.0.1
- quick replies are considered as postback and not regular message
#### version 1.0.0
- removed `createTemplate` function - was too verbose
- moved to object parameters - too many parameters
- added support for quick replies
- add support for persistent menu
- added support for audio/video/file attachments
- renamed setWelcomeScreen to setGetStarted since no longer supported by facebook.