Framework for building reusable chatbot components. Routing, Keyword recognition is built-in.
- requires
mongoose
> 4.0 - requires
nodejs
> 6.0 - requires
express
> 4.0 - requires
body-parser
> 1.10
$ npm i -S prg-chatbot
It's easy. This basic example can handle everything. Note, that the handler is STRICTLY SYNCHRONOUS.
const express = require('express');
const bodyParser = require('body-parser');
const { createRouter, createProcessor } = require('prg-chatbot/express');
const handler = (req, res, postBack) => {
res.typingOn()
.wait();
switch (req.action()) {
case 'hello':
res.text('Hello world');
return;
default:
// send one quick reply
res.text('What you want?', {
hello: 'Say hello world'
})
}
};
const processor = createProcessor(handler, {
pageToken: 'stringhere',
appSecret: 'botappsecret'
});
// app = express();
app.use('/bot', createRouter(processor));
How to deal with asynchronous action, when handlers are synchronous? Use postBack(action[, data])).
const handler = (req, res, postBack) => {
switch (req.action()) {
case 'downloaded':
const { data, err } = req.action(true);
if (err && err.code === 400) {
res.text('Image size exceeded');
} else if (err) {
res.text('Upload failed');
} else {
res.text('Hello world');
}
return;
default:
if (req.isImage()) {
const resolve = postBack.wait(); // usefull for tests
bufferloader(req.attachmentUrl(), 1000000)
.then(buffer => resolve('downloaded', { data: buffer }))
.catch(err => resolve('donwloaded', { err }))
}
}
};
Router is the way to handle strucured complex bots
const { Router } = require('prg-chatbot');
const app = new Router();
// middleware
app.use('*', (req, res, postBack, next) => {
res.typingOn()
.wait();
next();
});
app.use('actionName', (req, res) => {
if (req.state.secondAttempt) {
res.text('hello again');
} else {
res.text('hello')
.setState({ secondAttempt: true });
}
});
app.use('textAction', /keyword|two-words?/, (req, res) => {
res.text('Welcome', {
actionName: 'Say hello' // quick reply
})
});
- Request
- Responder
- ButtonTemplate ⇐
BaseTemplate
- ReceiptTemplate ⇐
BaseTemplate
- GenericTemplate ⇐
ButtonTemplate
- Router ⇐
ReducerWrapper
- ReducerWrapper ⇐
EventEmitter
- Tester
- ResponseAssert
- AnyResponseAssert
- Settings
- bufferloader(url, [limit], [limitJustByBody], [redirCount]) ⇒
Downloads a file from url into a buffer. Supports size limits and redirects.
- attachmentType(response, type, [message]) ⇒
boolean
Checks attachment type
- isText(response, [message]) ⇒
boolean
Checks, that response is a text
- contains(response, search, [message]) ⇒
boolean
Checks, that text contain a message
- quickReplyAction(response, action, [message]) ⇒
boolean
Checks quick response action
- templateType(response, expectedType, [message]) ⇒
boolean
Checks template type
- waiting(response, [message]) ⇒
boolean
Looks for waiting message
Kind: global class
- Request
- new Request()
- .senderId
- .recipientId
- .pageId
- .state
- .isAttachment() ⇒
boolean
- .isImage([attachmentIndex]) ⇒
boolean
- .isFile([attachmentIndex]) ⇒
boolean
- .attachment([attachmentIndex]) ⇒
object
|null
- .attachmentUrl([attachmentIndex]) ⇒
string
|null
- .isMessage() ⇒
boolean
- .text([tokenized]) ⇒
string
- .quickReply([getData]) ⇒
null
|string
|object
- .isPostBack() ⇒
boolean
- .isReferral() ⇒
boolean
- .isOptin() ⇒
boolean
- .action([getData]) ⇒
null
|string
|object
- .postBack([getData]) ⇒
null
|string
|object
Instance of {Request} class is passed as first parameter of handler (req)
Kind: instance property of Request
Properties
Name | Type | Description |
---|---|---|
senderId | string |
sender.id from the event |
Kind: instance property of Request
Properties
Name | Type | Description |
---|---|---|
recipientId | string |
recipient.id from the event |
Kind: instance property of Request
Properties
Name | Type | Description |
---|---|---|
pageId | string |
page identifier from the event |
Kind: instance property of Request
Properties
Name | Type | Description |
---|---|---|
state | object |
current state of the conversation |
Checks, when message contains an attachment (file, image or location)
Kind: instance method of Request
Checks, when the attachment is an image
Kind: instance method of Request
Param | Type | Default | Description |
---|---|---|---|
[attachmentIndex] | number |
0 |
use, when user sends more then one attachment |
Checks, when the attachment is a file
Kind: instance method of Request
Param | Type | Default | Description |
---|---|---|---|
[attachmentIndex] | number |
0 |
use, when user sends more then one attachment |
Returns whole attachment or null
Kind: instance method of Request
Param | Type | Default | Description |
---|---|---|---|
[attachmentIndex] | number |
0 |
use, when user sends more then one attachment |
Returns attachment URL
Kind: instance method of Request
Param | Type | Default | Description |
---|---|---|---|
[attachmentIndex] | number |
0 |
use, when user sends more then one attachment |
Returns true, when the request is text message, quick reply or attachment
Kind: instance method of Request
Returns text of the message
Kind: instance method of Request
Param | Type | Default | Description |
---|---|---|---|
[tokenized] | boolean |
false |
when true, message is normalized to lowercase with - |
Example
console.log(req.text(true)) // "can-you-help-me"
Returns action or data of quick reply
When getData
is true
, object will be returned. Otherwise string or null.
Kind: instance method of Request
Param | Type | Default |
---|---|---|
[getData] | boolean |
false |
Example
typeof res.quickReply() === 'string' || res.quickReply() === null;
typeof res.quickReply(true) === 'object';
Returns true, if request is the postback
Kind: instance method of Request
Returns true, if request is the referral
Kind: instance method of Request
Returns true, if request is the optin
Kind: instance method of Request
Returns action of the postback or quickreply
When getData
is true
, object will be returned. Otherwise string or null.
- the postback is checked
- the referral is checked
- the quick reply is checked
- expected keywords are checked
- expected state is checked
Kind: instance method of Request
Param | Type | Default |
---|---|---|
[getData] | boolean |
false |
Example
typeof res.action() === 'string' || res.action() === null;
typeof res.action(true) === 'object';
Returns action or data of postback
When getData
is true
, object will be returned. Otherwise string or null.
Kind: instance method of Request
Param | Type | Default |
---|---|---|
[getData] | boolean |
false |
Example
typeof res.postBack() === 'string' || res.postBack() === null;
typeof res.postBack(true) === 'object';
Kind: global class
- Responder
- new Responder()
- .text(text, [quickReplys]) ⇒
this
- .setState(object) ⇒
this
- .expected(action) ⇒
this
- .image(imageUrl) ⇒
this
- .wait([ms]) ⇒
this
- .typingOn() ⇒
this
- .typingOff() ⇒
this
- .seen() ⇒
this
- .receipt(recipientName, [paymentMethod], [currency], [uniqueCode]) ⇒
ReceiptTemplate
- .button(text) ⇒
ButtonTemplate
- .genericTemplate() ⇒
GenericTemplate
Instance of responder is passed as second parameter of handler (res)
Send text as a response
Kind: instance method of Responder
Param | Type | Description |
---|---|---|
text | string |
text to send to user, can contain placeholders (%s) |
[quickReplys] | object.<string, string> |
Example
res.text('Hello %s', name, {
action: 'Quick reply',
complexAction: {
title: 'Another quick reply', // required
match: 'string' || /regexp/, // optional
someData: 'Will be included in payload data' // optional
}
})
Sets new attributes to state (with Object.assign())
Kind: instance method of Responder
Param | Type |
---|---|
object | object |
Example
res.setState({ visited: true });
When user writes some text as reply, it will be processed as action
Kind: instance method of Responder
Param | Type | Description |
---|---|---|
action | string |
desired action |
Sends image as response. Requires appUrl option to send images from server
Kind: instance method of Responder
Param | Type | Description |
---|---|---|
imageUrl | string |
relative or absolute url |
Example
// image on same server (appUrl option)
res.image('/img/foo.png');
// image at url
res.image('https://google.com/img/foo.png');
Sets delay between two responses
Kind: instance method of Responder
Param | Type | Default |
---|---|---|
[ms] | number |
600 |
Sends "typing..." information
Kind: instance method of Responder
Stops "typing..." information
Kind: instance method of Responder
Reports last message from user as seen
Kind: instance method of Responder
responder.receipt(recipientName, [paymentMethod], [currency], [uniqueCode]) ⇒ ReceiptTemplate
Sends Receipt template
Kind: instance method of Responder
Param | Type | Default | Description |
---|---|---|---|
recipientName | string |
||
[paymentMethod] | string |
"'Cash'" |
should not contain more then 4 numbers |
[currency] | string |
"'USD'" |
sets right currency |
[uniqueCode] | string |
null |
when omitted, will be generated randomly |
Example
res.receipt('Name', 'Cash', 'CZK', '1')
.addElement('Element name', 1, 2, '/inside.png', 'text')
.send();
responder.button(text) ⇒ ButtonTemplate
Sends nice button template. It can redirect user to server with token in url
Kind: instance method of Responder
Param | Type |
---|---|
text | string |
Example
res.button('Hello')
.postBackButton('Text', 'action')
.urlButton('Url button', '/internal', true) // opens webview with token
.urlButton('Other button', 'https://goo.gl') // opens in internal browser
.send();
responder.genericTemplate() ⇒ GenericTemplate
Creates a generic template
Kind: instance method of Responder
Example
res.genericTemplate()
.addElement('title', 'subtitle')
.setElementImage('/local.png')
.setElementUrl('https://www.seznam.cz')
.postBackButton('Button title', 'action', { actionData: 1 })
.addElement('another', 'subtitle')
.setElementImage('https://goo.gl/image.png')
.setElementAction('action', { actionData: 1 })
.urlButton('Local link with extension', '/local/path', true, 'compact')
.send();
Kind: global class
Extends: BaseTemplate
- ButtonTemplate ⇐
BaseTemplate
Helps with creating of button template Instance of button template is returned by {Responder}
Adds button. When hasExtension
is set to true
, url will contain hash like:
#token=foo&senderId=23344
Kind: instance method of ButtonTemplate
Param | Type | Default | Description |
---|---|---|---|
title | string |
button text | |
url | string |
button url | |
hasExtension | boolean |
includes token in url | |
[webviewHeight] | string |
null |
compact |
Adds button, which makes another action
Kind: instance method of ButtonTemplate
Param | Type | Default | Description |
---|---|---|---|
title | string |
Button title | |
action | string |
Button action (can be absolute or relative) | |
[data] | object |
{} |
Action data |
Kind: global class
Extends: BaseTemplate
- ReceiptTemplate ⇐
BaseTemplate
Provides fluent interface to make nice Receipts Instance of button template is returned by {Responder}
Adds item to receipt
Kind: instance method of ReceiptTemplate
Param | Type | Default | Description |
---|---|---|---|
title | string |
||
[price] | number |
0 |
a item price |
[quantity] | number |
|
amount of items |
[image] | string |
null |
image of item |
[subtitle] | string |
null |
optional subtitle |
GenericTemplate ⇐ ButtonTemplate
Kind: global class
Extends: ButtonTemplate
- GenericTemplate ⇐
ButtonTemplate
- new GenericTemplate()
- .addElement(title, [subtitle], [dontTranslate]) ⇒
this
- .setElementUrl(url, [hasExtension]) ⇒
this
- .setElementImage(image) ⇒
this
- .setElementAction(url, hasExtension, [webviewHeight])
- .urlButton(title, url, hasExtension, [webviewHeight]) ⇒
this
- .postBackButton(title, action, [data]) ⇒
this
Generic template utility
Adds element to generic template
Kind: instance method of GenericTemplate
Param | Type | Default |
---|---|---|
title | string |
|
[subtitle] | string |
null |
[dontTranslate] | boolean |
false |
Sets url of recently added element
Kind: instance method of GenericTemplate
Param | Type | Default |
---|---|---|
url | any |
|
[hasExtension] | boolean |
false |
Sets image of recently added element
Kind: instance method of GenericTemplate
Param | Type |
---|---|
image | string |
Sets default action of recently added element
Kind: instance method of GenericTemplate
Param | Type | Default | Description |
---|---|---|---|
url | string |
button url | |
hasExtension | boolean |
false |
includes token in url |
[webviewHeight] | string |
null |
compact |
Adds button. When hasExtension
is set to true
, url will contain hash like:
#token=foo&senderId=23344
Kind: instance method of GenericTemplate
Param | Type | Default | Description |
---|---|---|---|
title | string |
button text | |
url | string |
button url | |
hasExtension | boolean |
includes token in url | |
[webviewHeight] | string |
null |
compact |
Adds button, which makes another action
Kind: instance method of GenericTemplate
Param | Type | Default | Description |
---|---|---|---|
title | string |
Button title | |
action | string |
Button action (can be absolute or relative) | |
[data] | object |
{} |
Action data |
Router ⇐ ReducerWrapper
Kind: global class
Extends: ReducerWrapper
Cascading router
Appends middleware, action handler or another router
Kind: instance method of Router
Param | Type | Description |
---|---|---|
[action] | string |
name of the action |
[pattern] | RegExp | string | function |
|
...reducers | function | Router |
Example
// middleware
router.use((req, res, postBack, next) => {
next(); // strictly synchronous
});
// route with matching regexp
router.use('action', /help/, (req, res) => {
res.text('Hello!');
});
// route with matching function (the function is considered as matcher
// in case of the function accepts zero or one arguments)
router.use('action', req => req.text() === 'a', (req, res) => {
res.text('Hello!');
});
// use multiple reducers
router.use('/path', reducer1, reducer2)
.next('exitAction', (data, req, res, postBack, next) => {
postBack('anotherAction', { someData: true })
});
// append router with exit action
router.use('/path', subRouter)
.next('exitAction', (data, req, res, postBack, next) => {
postBack('anotherAction', { someData: true })
});
Reducer function
Kind: instance method of Router
Overrides: reduce
Param | Type |
---|---|
req | Request |
res | Responder |
postBack | function |
Kind: global class
Extends: EventEmitter
Emits: ReducerWrapper#event:action
- ReducerWrapper ⇐
EventEmitter
Solution for catching events. This is useful for analytics.
Example
const reducer = new ReducerWrapper((req, res) => {
res.text('Hello');
});
reducer.on('action', (senderId, processedAction, text, req) => {
// log action
});
Reducer function
Kind: instance method of ReducerWrapper
Param | Type |
---|---|
req | Request |
res | Responder |
postBack | function |
Kind: static class of ReducerWrapper
Creates an instance of ReducerWrapper.
Param | Type | Default | Description |
---|---|---|---|
[reduce] | function |
o => o |
the handler function |
Kind: global class
- Tester
- new Tester()
- instance
- .res([index]) ⇒
ResponseAssert
- .any() ⇒
AnyResponseAssert
- .lastRes() ⇒
ResponseAssert
- .passedAction(path) ⇒
this
- .getState() ⇒
object
- .setState([state])
- .text(text) ⇒
Promise
- .optin(action, [data]) ⇒
Promise
- .quickReply(action, [data]) ⇒
Promise
- .postBack(action, [data]) ⇒
Promise
- .res([index]) ⇒
- static
Utility for testing requests
tester.res([index]) ⇒ ResponseAssert
Returns single response asserter
Kind: instance method of Tester
Param | Type | Default | Description |
---|---|---|---|
[index] | number |
0 |
response index |
tester.any() ⇒ AnyResponseAssert
Returns any response asserter
Kind: instance method of Tester
tester.lastRes() ⇒ ResponseAssert
Returns last response asserter
Kind: instance method of Tester
Checks, that app past the action
Kind: instance method of Tester
Param | Type |
---|---|
path | string |
Returns state
Kind: instance method of Tester
Sets state with Object.assign()
Kind: instance method of Tester
Param | Type | Default |
---|---|---|
[state] | object |
{} |
Makes text request
Kind: instance method of Tester
Param | Type |
---|---|
text | string |
Make optin call
Kind: instance method of Tester
Param | Type | Default |
---|---|---|
action | string |
|
[data] | object |
{} |
Send quick reply
Kind: instance method of Tester
Param | Type | Default |
---|---|---|
action | string |
|
[data] | object |
{} |
Sends postback
Kind: instance method of Tester
Param | Type | Default |
---|---|---|
action | string |
|
[data] | object |
{} |
Kind: static class of Tester
Creates an instance of Tester.
Param | Type | Default | Description |
---|---|---|---|
reducer | Router | ReducerWrapper | function |
||
[senderId] | string |
null |
|
[processorOptions] | object |
{} |
options for Processor |
[storage] | MemoryStateStorage |
place to override the storage |
Kind: global class
- ResponseAssert
- new ResponseAssert()
- instance
- .contains(search) ⇒
this
- .quickReplyAction(action) ⇒
this
- .templateType(type) ⇒
this
- .attachmentType(type) ⇒
this
- .contains(search) ⇒
- static
Utility for asserting single response
Checks, that response contains text
Kind: instance method of ResponseAssert
Param | Type |
---|---|
search | string |
Checks quick response action
Kind: instance method of ResponseAssert
Param | Type |
---|---|
action | string |
Checks template type
Kind: instance method of ResponseAssert
Param | Type |
---|---|
type | string |
Checks attachment type
Kind: instance method of ResponseAssert
Param | Type |
---|---|
type | string |
Checks, that response contains text
Kind: static method of ResponseAssert
Param | Type |
---|---|
search | string |
Checks quick response action
Kind: static method of ResponseAssert
Param | Type |
---|---|
action | string |
Checks template type
Kind: static method of ResponseAssert
Param | Type |
---|---|
type | string |
Checks attachment type
Kind: static method of ResponseAssert
Param | Type |
---|---|
type | string |
Utility for searching among responses
Kind: global class
- Settings
- new Settings()
- instance
- .greeting([text]) ⇒
this
- .getStartedButton([payload]) ⇒
this
- .whitelistDomain(domains) ⇒
this
- .menu([locale], [inputDisabled]) ⇒
MenuComposer
- .greeting([text]) ⇒
- static
Utility, which helps us to set up chatbot behavior
Sets or clears bot's greeting
Kind: instance method of Settings
Param | Type | Default | Description |
---|---|---|---|
[text] | string |
false |
leave empty to clear |
Sets up the Get Started Button
Kind: instance method of Settings
Param | Type | Default | Description |
---|---|---|---|
[payload] | string | object |
false |
leave blank to remove button, or provide the action |
Example
const settings = new Settings(config.facebook.pageToken);
settings.getStartedButton('/start'); // just an action
Useful for using facebook extension in webviews
Kind: instance method of Settings
Param | Type |
---|---|
domains | string | Array.<string> |
Sets up the persistent menu
Kind: instance method of Settings
Param | Type | Default |
---|---|---|
[locale] | string |
"default" |
[inputDisabled] | boolean |
false |
Example
const { Settings } = require('prg-chatbot');
const settings = new Settings('page-token-string');
settings.menu()
.addNested('Nested Menu')
.addUrl('Go to google', 'https://google.com')
.done()
.addPostBack('Do something', '/the/action')
.done();
Kind: static class of Settings
Creates an instance of Settings.
Param | Type |
---|---|
token | string |
[log] | Object |
Downloads a file from url into a buffer. Supports size limits and redirects.
Kind: global function
Returns: Promise.
Param | Type | Default | Description |
---|---|---|---|
url | string |
||
[limit] | number |
0 |
limit in bytes |
[limitJustByBody] | boolean |
false |
when true, content size in header is ignored |
[redirCount] | number |
3 |
maximmum amount of redirects |
Example
router.use('*', (req, res, postBack) => {
if (req.isFile()) {
bufferloader(req.attachmentUrl())
.then(buffer => postBack('downloaded', { data: buffer }))
.catch(err => postBack('donwloaded', { err }))
}
});
Checks attachment type
Kind: global function
Param | Type | Default | Description |
---|---|---|---|
response | object |
||
type | string |
||
[message] | string | false |
"'Attachment type does not match'" |
use false for no asserts |
Checks, that response is a text
Kind: global function
Param | Type | Default | Description |
---|---|---|---|
response | object |
||
[message] | string | false |
"'Should be a text'" |
use false for no asserts |
Checks, that text contain a message
Kind: global function
Param | Type | Default | Description |
---|---|---|---|
response | object |
||
search | string |
||
[message] | string | false |
"'Should contain a text'" |
use false for no asserts |
Checks quick response action
Kind: global function
Param | Type | Default | Description |
---|---|---|---|
response | object |
||
action | string |
||
[message] | string | false |
"'Should contain the action'" |
use false for no asserts |
Checks template type
Kind: global function
Param | Type | Default | Description |
---|---|---|---|
response | object |
||
expectedType | string |
||
[message] | string | false |
"'Template type does not match'" |
use false for no asserts |
Looks for waiting message
Kind: global function
Param | Type | Default | Description |
---|---|---|---|
response | object |
||
[message] | string | false |
"'Should be waiting placeholder'" |
use false for no asserts |