├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .istanbul.yml ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── appveyor.yml ├── incoming ├── index.js ├── postback.js ├── quick_reply.js ├── type_cast.js └── user_init.js ├── index.js ├── lib ├── attach.js ├── messaging.js ├── middleware.js ├── normalize.js ├── pipeline.js ├── request.js ├── send.js └── verify_endpoint.js ├── outgoing ├── button_postback.js ├── index.js └── quick_reply.js ├── package.json ├── templates ├── button.js ├── generic.js └── receipt.js ├── test ├── common.js ├── fixtures │ ├── incoming │ │ ├── delivery.json │ │ ├── message-attachment-audio.json │ │ ├── message-attachment-fallback-text.json │ │ ├── message-attachment-file.json │ │ ├── message-attachment-image.json │ │ ├── message-attachment-location.json │ │ ├── message-quick_reply-text.json │ │ ├── message-sticker-attachment-image.json │ │ ├── message-text-multi-entry-multi-messaging.json │ │ ├── message-text-multi-entry.json │ │ ├── message-text.json │ │ └── postback.json │ └── outgoing │ │ ├── audio.json │ │ ├── bad_transport.json │ │ ├── button.json │ │ ├── file.json │ │ ├── generic.json │ │ ├── image.json │ │ ├── mark_seen.json │ │ ├── message.json │ │ ├── non_existent.json │ │ ├── quick_replies.json │ │ ├── receipt.json │ │ ├── text.json │ │ ├── typing_off.json │ │ ├── typing_on.json │ │ └── video.json ├── shared-tests.js ├── test-express.js ├── test-hapi.js ├── test-http.js ├── test-restify.js ├── test-send.js └── test-traverse.js └── traverse ├── incoming.js ├── index.js └── outgoing.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | 11 | [**.{css,hbs,js,json,md,scss}] 12 | indent_style = space 13 | indent_size = 2 14 | insert_final_newline = true 15 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [2, 2, {"SwitchCase": 1}], 4 | "quotes": [2, "single"], 5 | "linebreak-style": [2, "unix"], 6 | "semi": [2, "always"], 7 | "curly": [2, "multi-line"], 8 | "handle-callback-err": [2, "^err"], 9 | "valid-jsdoc": [2, { 10 | "requireReturn": false, 11 | "requireReturnDescription": false, 12 | "prefer": { 13 | "return": "returns" 14 | } 15 | }], 16 | "require-jsdoc": [2, { 17 | "require": { 18 | "FunctionDeclaration": true 19 | } 20 | }], 21 | "no-redeclare": [2, { "builtinGlobals": true }], 22 | "no-shadow": [2, { "builtinGlobals": true, "hoist": "all" }], 23 | "no-use-before-define": [2, "nofunc"], 24 | "no-shadow-restricted-names": 2, 25 | "no-extra-semi": 2, 26 | "no-unused-vars": 2, 27 | "no-undef": 2, 28 | "no-irregular-whitespace": 2, 29 | "no-console": 2, 30 | "key-spacing": 0, 31 | "strict": 0, 32 | "dot-notation": 0, 33 | "eol-last": 0, 34 | "no-new": 0, 35 | "semi-spacing": 0, 36 | "no-multi-spaces": 0, 37 | "eqeqeq": 0, 38 | "no-mixed-requires": 0, 39 | }, 40 | "env": { 41 | "node": true 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | coverage 3 | node_modules 4 | 5 | *.log 6 | -------------------------------------------------------------------------------- /.istanbul.yml: -------------------------------------------------------------------------------- 1 | verbose: false 2 | instrumentation: 3 | root: . 4 | extensions: 5 | - .js 6 | default-excludes: true 7 | excludes: ['**/node_modules/**'] 8 | compact: false 9 | reporting: 10 | root: ./coverage/tmp 11 | print: summary 12 | reports: 13 | - lcov 14 | dir: ./coverage 15 | report-config: 16 | json: 17 | file: coverage.json 18 | watermarks: 19 | statements: [90, 99] 20 | lines: [90, 99] 21 | functions: [90, 99] 22 | branches: [90, 99] 23 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .editorconfig 3 | .eslintignore 4 | .eslintrc 5 | .gitignore 6 | .istanbul.yml 7 | .npmignore 8 | .travis.yml 9 | appveyor.yml 10 | 11 | coverage 12 | node_modules 13 | test 14 | 15 | *.log 16 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: node_js 4 | node_js: 5 | - "0.12" 6 | - "iojs" 7 | - "4" 8 | - "5" 9 | - "6" 10 | 11 | os: 12 | - osx 13 | - linux 14 | 15 | install: 16 | - travis_retry npm install 17 | 18 | script: 19 | - uname -a 20 | - node --version 21 | - npm --version 22 | - npm run ci-lint 23 | - npm run ci-test 24 | 25 | after_success: 26 | - "cat coverage/lcov.info | ./node_modules/.bin/coveralls" 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Alex Indigo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fbbot [![NPM Module](https://img.shields.io/npm/v/fbbot.svg?style=flat)](https://www.npmjs.com/package/fbbot) 2 | 3 | Minimal framework/SDK for facebook messenger bots. BYOS (Bring Your Own Server). 4 | 5 | [![patform@1.2](https://img.shields.io/badge/messenger_platform-v1.2-brightgreen.svg?style=flat)](https://developers.facebook.com/docs/messenger-platform) 6 | 7 | [![Linux Build](https://img.shields.io/travis/alexindigo/fbbot/master.svg?label=linux:0.12-6.x&style=flat)](https://travis-ci.org/alexindigo/fbbot) 8 | [![MacOS Build](https://img.shields.io/travis/alexindigo/fbbot/master.svg?label=macos:0.12-6.x&style=flat)](https://travis-ci.org/alexindigo/fbbot) 9 | [![Windows Build](https://img.shields.io/appveyor/ci/alexindigo/fbbot/master.svg?label=windows:0.12-6.x&style=flat)](https://ci.appveyor.com/project/alexindigo/fbbot) 10 | 11 | [![Coverage Status](https://img.shields.io/coveralls/alexindigo/fbbot/master.svg?label=code+coverage&style=flat)](https://coveralls.io/github/alexindigo/fbbot?branch=master) 12 | [![Dependency Status](https://img.shields.io/david/alexindigo/fbbot/master.svg?style=flat)](https://david-dm.org/alexindigo/fbbot) 13 | [![bitHound Overall Score](https://www.bithound.io/github/alexindigo/fbbot/badges/score.svg)](https://www.bithound.io/github/alexindigo/fbbot) 14 | 15 | [![express](https://img.shields.io/badge/express-tested-brightgreen.svg?style=flat)](http://expressjs.com) 16 | [![hapi](https://img.shields.io/badge/hapi-tested-brightgreen.svg?lstyle=flat)](http://hapijs.com) 17 | [![restify](https://img.shields.io/badge/restify-tested-brightgreen.svg?style=flat)](http://restify.com) 18 | [![http](https://img.shields.io/badge/http-tested-brightgreen.svg?style=flat)](https://nodejs.org/api/http.html) 19 | 20 | ## Install 21 | 22 | ``` 23 | npm install --save fbbot 24 | ``` 25 | 26 | ## Table of Contents 27 | 28 | 29 | - [Examples](#examples) 30 | - [Listening for messages](#listening-for-messages) 31 | - [Adding middleware](#adding-middleware) 32 | - [Sending messages to user](#sending-messages-to-user) 33 | - [Logging](#logging) 34 | - [API](#api) 35 | - [Fbbot#use](#fbbotuse) 36 | - [Fbbot#on](#fbboton) 37 | - [Fbbot#send](#fbbotsend) 38 | - [Convenience Methods](#convenience-methods) 39 | - [`send.message`](#sendmessage) 40 | - [`send.markSeen`](#sendmarkseen) 41 | - [`send.typingOn`](#sendtypingon) 42 | - [`send.typingOff`](#sendtypingoff) 43 | - [`send.text`](#sendtext) 44 | - [`send.image`](#sendimage) 45 | - [`send.audio`](#sendaudio) 46 | - [`send.video`](#sendvideo) 47 | - [`send.file`](#sendfile) 48 | - [`send.generic`](#sendgeneric) 49 | - [`send.button`](#sendbutton) 50 | - [`send.receipt`](#sendreceipt) 51 | - [`send.quickReplies`](#sendquickreplies) 52 | - [Message Types](#message-types) 53 | - [`MESSAGE`](#message) 54 | - [`MARK_SEEN`](#mark_seen) 55 | - [`TYPING_ON`](#typing_on) 56 | - [`TYPING_OFF`](#typing_off) 57 | - [`TEXT`](#text) 58 | - [`IMAGE`](#image) 59 | - [`AUDIO`](#audio) 60 | - [`VIDEO`](#video) 61 | - [`FILE`](#file) 62 | - [`GENERIC`](#generic) 63 | - [`BUTTON`](#button) 64 | - [`RECEIPT`](#receipt) 65 | - [`QUICK_REPLIES`](#quick_replies) 66 | - [Hooks](#hooks) 67 | - [Incoming](#incoming) 68 | - [Outgoing](#outgoing) 69 | - [Roadmap](#roadmap) 70 | - [License](#license) 71 | 72 | 73 | 74 | ## Examples 75 | 76 | ### Listening for messages 77 | 78 | ```javascript 79 | // also works with `hapi`, `restify` and built-in `http` 80 | var express = require('express'); 81 | var Fbbot = require('fbbot'); 82 | 83 | var app = express(); 84 | var fbbot = new Fbbot({token: '...', secret: '...'}); 85 | 86 | // plug-in fbbot 87 | // It will also listen for GET requests to authorize fb app. 88 | app.all('/webhook', fbbot.requestHandler); 89 | // assuming HTTPS is terminated elsewhere, 90 | // or you can use standard express https capabilities 91 | app.listen(8080); 92 | 93 | // catching messages 94 | fbbot.on('message', function(message, send) 95 | { 96 | // message.type <-- type of the message (text, attachment, quick_reply, sticker, etc) 97 | // message.user <-- user object 98 | // message.text <-- text for text messages 99 | // message.attachments <-- list of attachments if available 100 | // send <-- send method with baked in user.id `send(fbbot., , )` 101 | }); 102 | 103 | // handle only text messages 104 | fbbot.on('message.text', function(message, send) 105 | { 106 | // message.user <-- user object 107 | // message.text <-- text for text messages 108 | // send <-- send method with baked in user.id `send(fbbot., , )` 109 | }); 110 | 111 | fbbot.on('postback', function(postback, send) 112 | { 113 | // postback.user <-- user object 114 | // postback.payload <-- parsed payload 115 | // send <-- send method with baked in user.id `send(fbbot., , )` 116 | }); 117 | ``` 118 | 119 | Check out [test folder](test/fixtures) for available options. 120 | 121 | ### Adding middleware 122 | 123 | ```javascript 124 | var express = require('express'); 125 | var Fbbot = require('fbbot'); 126 | 127 | var app = express(); 128 | var fbbot = new Fbbot({token: '...', secret: '...'}); 129 | 130 | // plug-in fbbot 131 | app.all('/webhook', fbbot.requestHandler); 132 | // assuming HTTPS is terminated elsewhere, 133 | // or you can use standard express https capabilities 134 | app.listen(8080); 135 | 136 | fbbot.use('message', function(payload, callback) 137 | { 138 | // do something with the payload, async or sync 139 | setTimeout(function() 140 | { 141 | payload.fooWasHere = true; 142 | // pass it to callback 143 | callback(null, payload); 144 | }, 500); 145 | }); 146 | 147 | // catching messages 148 | fbbot.on('message', function(message, send) 149 | { 150 | // modified message payload 151 | message.fooWasHere; // true 152 | }); 153 | 154 | ``` 155 | 156 | More middleware examples could be found in [incoming](incoming/) folder. 157 | 158 | ### Sending messages to user 159 | 160 | Here are two ways of sending messages, using per-instance fbbot.send method, 161 | or the one tailored to the user, provided to the event handlers. 162 | 163 | ```javascript 164 | var express = require('express'); 165 | var Fbbot = require('fbbot'); 166 | 167 | var app = express(); 168 | var fbbot = new Fbbot({token: '...', secret: '...'}); 169 | 170 | // plug-in fbbot 171 | app.all('/webhook', fbbot.requestHandler); 172 | // assuming HTTPS is terminated elsewhere, 173 | // or you can use standard express https capabilities 174 | app.listen(8080); 175 | 176 | // "standalone" send function 177 | // send reguar text message 178 | fbbot.send(1234567890, fbbot.TEXT, 'Hi there!', function(error, response) 179 | { 180 | // error