comet-messenger
Node-JS microservice-oriented framework for interacting with Facebook Messenger.
Some important factors to bear in mind:
- Comet makes absolutely no assumptions about your architecture, but does assume the API service will be attached to an Express application (happy to accept PRs for more web frameworks).
- It does provide some structure for building your own messenger bots.
async/await
functions are used in the core, and are encouraged.- Follows the hop naming convention: 🍻.
Installation
$ npm install comet-messenger
If preferred you can clone directly from the GitHub repository. master
is guaranteed to be stable, but there's no
guarantee of changes between major versions breaking existing code. Trust Semver.
Usage
In Comet, the concept of a bot is split into pages
, schema
, router
and worker
.
pages
exist as an array of objects defining a page. At a minimum you will need the page ID, the name of the page, and
the page token you created on Facebook.
Think of the schema
as a conversation tree - every outcome is mapped and this is how you programmatically control
your Messenger bot. All your business logic is going to end up in here! See the Schema API section for
more information on the methods here and other methods you can use.
const comet = ;const schema = comet; /** * In Messenger, a postback occurs when a user clicks a button. */schema; /** * Once a state has been set, free-form input can be accurately handled! */schema;
The router
is the API router that the
Facebook webhook will hit. It takes
messages sent from Facebook and pushes the messages onto your preferred queue stack. This example assumes you'll be
dropping it into an existing Express application and using async for your queue. The router
requires your Facebook app secret & the verify token that you specified when setting up that Facebook webhook.
const async = ;const comet = ;const pages = ... ; // The array of pages from above, for example const queue = async; app;
Finally, the worker
operates at the other end of your preferred queue stack, processing messages and sending replies
on behalf of your bot.
const async = ;const comet = ;const pages = ... ; // The array of pages from above, for example const schema = comet;/* Omitted here is all the business logic & methods used to configure the schema */ const worker = comet;const queue = async;
Schema API
The schema holds all the business logic of your bot, and has several methods to help you map out your conversation as you see fit.
The Messenger platform sends hooks to your API for you to consume (and hopefully pass to Comet!). But their main form
of communication is a little.. fractured. They send messages and they send postback
s, which are supposed to
be when a user presses a button, but they don't specify how this should be properly used (and if a user scrolls back
through the conversation they can re-fire a postback, which plays havoc with any sort of state management!).
So, in order to continue this separation of concerns, Comet lets you setup functions for raw input and postbacks.
schema.onPostback(pointer, function)
This sets a function for a particular postback type, and will execute that function when this postback is received.
Important note: Comet does a little pre-processing on these postbacks, most importantly taking a string and
transforming it into { type: "%s" }
. Why? This immediately allows for complex postback functions, with types and
parameters, as long as you remember to JSON-encode any postback payloads (as seen above in the messenger_buttons
array).
schema;
schema.catchInput(function)
This sets a function that will execute whenever free-flowing text is received. This includes attachments.
schema;
schema.before(function)
This queues a function to run before the main input/postback function, allowing data to be fetched before all business logic. Use this to fetch the user's profile from Facebook or load state or record analytics.
schema;
schema.after(function)
This queues a function to run after the main input/postback function.
schema;
schema.onInput(pointer, callback)
Suddenly, if the concept of state is introduced we don't need one function to handle all free-flowing text that a user
sends to a bot. Which could be a lot, they're inside a messaging app, it's sort of a given? In any case, setting
req.pointer
in a before function will mean Comet will look for a input function referring
to a particular state, exactly like a postback function, which means we can handle all kinds of input from the user
with little difficulty:
schema; schema;
TODO
- More documentation
- Unit tests. Although this has been built in a modular-fashion unit-tests are still required! Going for 100% code-coverage too, so watch this space!
Questions
- Open an issue or feel free to tweet me.