fbbot

Minimal framework/SDK for facebook messenger bots. BYOS (Bring Your Own Server).

Usage no npm install needed!

<script type="module">
  import fbbot from 'https://cdn.skypack.dev/fbbot';
</script>

README

fbbot NPM Module

Minimal framework/SDK for facebook messenger bots. BYOS (Bring Your Own Server).

patform@1.2

Linux Build MacOS Build Windows Build

Coverage Status Dependency Status bitHound Overall Score

express hapi restify http

Install

npm install --save fbbot

Table of Contents

Examples

Listening for messages

// also works with `hapi`, `restify` and built-in `http`
var express = require('express');
var Fbbot = require('fbbot');

var app = express();
var fbbot = new Fbbot({token: '...', secret: '...'});

// plug-in fbbot
// It will also listen for GET requests to authorize fb app.
app.all('/webhook', fbbot.requestHandler);
// assuming HTTPS is terminated elsewhere,
// or you can use standard express https capabilities
app.listen(8080);

// catching messages
fbbot.on('message', function(message, send)
{
  // message.type <-- type of the message (text, attachment, quick_reply, sticker, etc)
  // message.user <-- user object
  // message.text <-- text for text messages
  // message.attachments <-- list of attachments if available
  // send <-- send method with baked in user.id `send(fbbot.<message_type>, <payload>, <callback>)`
});

// handle only text messages
fbbot.on('message.text', function(message, send)
{
  // message.user <-- user object
  // message.text <-- text for text messages
  // send <-- send method with baked in user.id `send(fbbot.<message_type>, <payload>, <callback>)`
});

fbbot.on('postback', function(postback, send)
{
  // postback.user <-- user object
  // postback.payload <-- parsed payload
  // send <-- send method with baked in user.id `send(fbbot.<message_type>, <payload>, <callback>)`
});

Check out test folder for available options.

Adding middleware

var express = require('express');
var Fbbot = require('fbbot');

var app = express();
var fbbot = new Fbbot({token: '...', secret: '...'});

// plug-in fbbot
app.all('/webhook', fbbot.requestHandler);
// assuming HTTPS is terminated elsewhere,
// or you can use standard express https capabilities
app.listen(8080);

fbbot.use('message', function(payload, callback)
{
  // do something with the payload, async or sync
  setTimeout(function()
  {
    payload.fooWasHere = true;
    // pass it to callback
    callback(null, payload);
  }, 500);
});

// catching messages
fbbot.on('message', function(message, send)
{
  // modified message payload
  message.fooWasHere; // true
});

More middleware examples could be found in incoming folder.

Sending messages to user

Here are two ways of sending messages, using per-instance fbbot.send method, or the one tailored to the user, provided to the event handlers.

var express = require('express');
var Fbbot = require('fbbot');

var app = express();
var fbbot = new Fbbot({token: '...', secret: '...'});

// plug-in fbbot
app.all('/webhook', fbbot.requestHandler);
// assuming HTTPS is terminated elsewhere,
// or you can use standard express https capabilities
app.listen(8080);

// "standalone" send function
// send reguar text message
fbbot.send(1234567890, fbbot.TEXT, 'Hi there!', function(error, response)
{
  // error <!-- message composition error or transport error
  // response <-- response from the remote server
});

// sending messages as reply
fbbot.on('message', function(message, send)
{
  // tailored to the user
  // callback is optional
  send(fbbot.IMAGE, 'https://petersapparel.com/img/shirt.png');

  // also message type tailored methods are available
  send.image('https://petersapparel.com/img/shirt.png');
});

More details could be found in test-send.js.

Logging

var Fbbot = require('fbbot');
var fbbot = new Fbbot({token: '...', secret: '...', logger: myCustomLogger});

// turn on logging
// uses `bole` out of the box
Fbbot.logger.output({
  level : 'info',
  stream: process.stdout
});

API

Fbbot#use

Adds middleware for both incoming and outgoing flows. Outgoing hooks prefixed with send. Each middleware handler function expected to invoke callback with payload object, modified or not.

fbbot.use([String hook ,] Function handler)

If no hook specified, provided function will be applied to entire incoming payload.

  • hook: (optional) hook handle to attach middleware handler to.
  • handler: middleware handler, expected to have following signature:
handler(Object payload, Function callback)
  • payload: chunk of the payload corresponding to the attached hook.
  • callback: standard error-back pattern, with updated payload as second argument.

List of available hooks could be found below.

Fbbot#on

Adds event listener for both incoming and outgoing flows. Outgoing events (hooks) prefixed with send. Each event listener function will receive send method tailored for the event in question.

fbbot.on(String hook, Function listener)
  • hook: hook handle to attach event listener to.
  • listener: event listener, expected to have following signature:
listener(Object payload, Function send)
  • payload: chunk of the payload corresponding to the attached hook.1
  • send: function being tailored specifically for the event – baked in user id where it's available, and set of convenience methods for sending specific message types, listed below.

1 Message payload augmented with type property and reference user object. All payloads have prototype object with reference to the "parent" object.

List of available hooks could be found below.

Fbbot#send

Sends provided payload to the specified (by either id or phone_number) user, reconstructs platform expected payload based on the message type and minimal data set.

Will automatically stringify payload object for postback buttons, since Messenger Platform expects it to be a string.

fbbot.send(String|Object user, [String type ,] [String|Array|Object payload ,] [Function callback]);
  • user: user id or phone number, provided via string (user id) or object with id or phone_number properties.
  • type: (optional) message type, if not provided, will fallback to Fbbot#MESSAGE type.
  • payload: (optional) payload object for the chosen message type, not expected for MARK_SEEN, TYPING_ON and TYPING_OFF types.
  • callback: (optional) standard error-back pattern, with response object as second argument.

List of available message types could be found below.

Also send method with backed in user id available as second argument for event listeners:

send([String type ,] [String|Array|Object payload ,] [Function callback]);

Along with convenience methods per supported message type:

send.<type>([Object payload ,] [Function callback]);

Convenience Methods

send.message

Sends payload as raw message.

send.message(Object payload [, Function callback])

Example payload could be found below.

send.markSeen

Marks last message as read.

send.markSeen([Function callback])

send.typingOn

Turns typing indicators on.

send.typingOn([Function callback])

send.typingOff

Turns typing indicators off.

send.typingOff([Function callback])

send.text

Sends text message. Expects text string as payload. Will truncate provided string to 320 characters, as per Messenger Platform limitations.

send.text(String text [, Function callback])

send.image

Sends image attachment. Expects string with image url as payload.

send.image(String url [, Function callback])

send.audio

Sends audio attachment. Expects string with url to audio file as payload.

send.audio(String url [, Function callback])

send.video

Sends video attachment. Expects string with url to video file as payload.

send.video(String url [, Function callback])

send.file

Sends generic file attachment. Expects string with url to a file as payload.

send.file(String url [, Function callback])

send.generic

Sends generic template attachment. Expects array of "card" objects as payload. Will send first 10 elements, as per Messenger Platform limitations.

send.generic(Array elements [, Function callback])

Example payload could be found below.

send.button

Sends button template attachment. Expects object with text and array of buttons as payload. Will send first 3 buttons, as per Messenger Platform limitations.

send.button(Object payload [, Function callback])

Example payload could be found below.

send.receipt

Sends receipt template attachment. Expects receipt object as payload. Will send first 100 item elements, as per Messenger Platform limitations.

send.receipt(Object payload [, Function callback])

Example payload could be found below.

send.quickReplies

Sends quick replies object. Expects object with text and array of quick_reply buttons as payload. Will send first 10 buttons, as per Messenger Platform limitations. Will automatically stringify payload property.

send.quickReplies(Object payload [, Function callback])

Example payload could be found below.

Message Types

Available as properties of the Fbbot instance, like fbbot.MESSAGE and fbbot.MARK_SEEN.

MESSAGE

Treats payload as raw message.

Example payload:

{
  "attachment": {
    "type": "template",
    "payload": {
      "template_type": "generic",
      "elements": [{
        "title": "Welcome to Peter's Hats",
        "item_url": "https://petersfancybrownhats.com",
        "image_url": "https://petersfancybrownhats.com/company_image.png",
        "subtitle": "We've got the right hat for everyone.",
        "buttons": [{
          "type": "web_url",
          "url": "https://petersfancybrownhats.com",
          "title": "View Website"
        }, {
          "type": "postback",
          "title": "Start Chatting",
          "payload": {
            "developer": ["defined", "payload"],
          }
        }]
      }]
    }
  }
}

MARK_SEEN

Doesn't require payload, corresponds to mark_seen sender action.

TYPING_ON

Doesn't require payload, corresponds to typing_on sender action.

TYPING_OFF

Doesn't require payload, corresponds to typing_off sender action.

TEXT

Treats payload as text message. Expects text string as payload. Will truncate provided string to 320 characters, as per Messenger Platform limitations.

IMAGE

Treats payload as image attachment. Expects string with image url as payload.

AUDIO

Treats payload as audio attachment. Expects string with url to audio file as payload.

VIDEO

Treats payload as video attachment. Expects string with url to video file as payload.

FILE

Treats payload as generic file attachment. Expects string with url to a file as payload.

GENERIC

Treats payload as generic template attachment. Expects array of "card" objects as payload. Will send first 10 elements, as per Messenger Platform limitations.

Example payload:

[
  {
    "title": "Welcome to Peter's Hats",
    "item_url": "https://petersfancybrownhats.com",
    "image_url": "https://petersfancybrownhats.com/company_image.png",
    "subtitle": "We've got the right hat for everyone.",
    "buttons": [{
      "type": "web_url",
      "url": "https://petersfancybrownhats.com",
      "title": "View Website"
    }, {
      "type": "postback",
      "title": "Start Chatting",
      "payload": "DEVELOPER_DEFINED_PAYLOAD"
    }]
  },

  {
    "title": "Welcome to Peter's Boots",
    "item_url": "https://petersokredboots.com",
    "image_url": "https://petersokredboots.com/company_image.png",
    "subtitle": "We've got the left boots for everyone.",
    "buttons": [{
      "type": "web_url",
      "url": "https://petersokredboots.com",
      "title": "View Website"
    }, {
      "type": "postback",
      "title": "Start Chatting",
      "payload": {
        "developer": ["defined", "payload"],
      }
    }]
  }
]

BUTTON

Treats payload as button template attachment. Expects object with text and array of buttons as payload. Will send first 3 buttons, as per Messenger Platform limitations.

Example payload:

{
  "text": "What do you want to do next?",
  "buttons":
  [
    {
      "type": "web_url",
      "url": "https://petersapparel.parseapp.com",
      "title": "Show Website"
    },
    {
      "type": "postback",
      "title": "Start Chatting",
      "payload": {
        "developer": ["defined", "payload"],
      }
    }
  ]
}

RECEIPT

Treats payload as receipt template attachment. Expects receipt object as payload. Will send first 100 item elements, as per Messenger Platform limitations.

Example 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
  }]
}

QUICK_REPLIES

Treats payload as quick replies object. Expects object with text and array of quick_reply buttons as payload. Will send first 10 buttons, as per Messenger Platform limitations. Will automatically stringify payload property.

Example payload:

{
  "text": "Pick a color:",
  "quick_replies": [{
    "content_type": "text",
    "title": "Red",
    "payload": "DEVELOPER_DEFINED_PAYLOAD_FOR_PICKING_RED"
  }, {
    "content_type": "text",
    "title": "Green",
    "payload": {
      "custom": "payload",
      "for": "quick_reply"
    }
  }, {
    "content_type": "location"
  }]
}

Hooks

Same hooks work (applied) for both middleware and event listeners.

Incoming

Available incoming hooks (in the following order):

  • payload: (default, if no hook specified) applied to entire payload.
  • entry: applied per each entry of the payload.
  • messaging: applied per each messaging element of the payload.
  • delivery: applied to delivery notifications.
  • postback: applied to postback messages.
  • message: applied to regular messages.
    • message.attachment: applied to attachment type messages only.
    • message.quick_reply: applied to quick reply type messages only.
    • message.sticker: applied to sticker type messages only.
    • message.text: applied to text type messages only.
  • quick_reply: applied to quick reply payload.
  • attachment: applied per each attachment.
    • attachment.audio: applied to audio attachments only.
    • attachment.fallback: applied to fallback attachments only.2
    • attachment.file: applied to file attachments only.
    • attachment.image: applied to image attachments only.
    • attachment.location: applied to location attachments only.

2 Some undocumented case when user sends only link without any other text in the message, your bot would receive as dual quantum state message, which would have regular text field with the link as text, as well as attachment object with type fallback with url field and prefetched title of the linked page. Example of such payload could be found in message-attachment-fallback-text.json.

Sample payloads could be found in incoming fixtures folder.

Outgoing

  • send: applied to the entire outgoing payload.
  • send.message: applied to all outgoing messages (status updates, like typing_on are not messages).
  • send.attachment: applied to outgoing attachments.
    • send.attachment.audio: applied to outgoing audio attachments only.
    • send.attachment.file: applied to outgoing file attachments only.
    • send.attachment.image: applied to outgoing image attachments only.
    • send.attachment.video: applied to outgoing video attachments only.
    • send.attachment.template: applied to templated attachments.
  • send.quick_reply: applied per each outgoing quick reply element.
  • send.payload: applied to payload objects within outgoing message.
    • send.payload.generic: applied to payload objects with generic template.
    • send.payload.receipt: applied to payload objects with receipt template.
    • send.payload.button: applied to payload objects with button template.
  • send.element: applied per each element of the outgoing payload.
  • send.button: applied per button options within message, either button template or buttons option within other templates.
    • send.button.web_url: applied to buttons with urls only.
    • send.button.postback: applied to postback buttons only.
    • send.button.phone_number: applied to call buttons only.
    • send.button.element_share: applied to share buttons only.3
    • send.button.payment: applied to buy buttons only.4

3 The Share Button only works with the Generic Template.

4 The Buy Button only works with the Generic Template and it must be the first button.

Roadmap

  • add send.batch method, for sending series of messages, with smart notification_types.
  • support for read and echo notification
  • add airline templates
  • fetch user info middleware
  • initialization actions (welcome page, menu, white-listing, etc)

License

FBBot is released under the MIT license.