Routing
Routing is a pattern that helps you organize your Bottender actions in your Bottender app. For example, you can use the router
function and the text
function to create an action that handles "hi" and "hello" text message events with the different actions (SayHi
and SayHello
) as follows:
const { router, text } = require('bottender/router');
async function SayHi(context) {
await context.sendText('Hi!');
}
async function SayHello(context) {
await context.sendText('Hello!');
}
async function App() {
return router([
// return the `SayHi` action when receiving "hi" text messages
text('hi', SayHi),
// return the `SayHello` action when receiving "hello" text messages
text('hello', SayHello),
]);
}
Note: The
router
function, thetext
function, and some other functions that we introduce below are coming from thebottender/router
module. If you want to use them, make sure to import them from thebottender/router
module correctly.
The router
function takes an array of routes to create a router. The created router checks each route is matching the condition or not in the specified order and returns the provided action of the first matching route.
The first argument of the text
function defines the matching rule, which could also be an array of strings. In the following example, when receiving "hi", "hello" or "hey" text messages, the router returns the SayHi
action:
async function App(context) {
return router([
// return the `SayHi` action when receiving "hi", "hello" or "hey" text messages
text(['hi', 'hello', 'hey'], SayHi),
]);
}
Regular Expression Routes
If you are familiar with regular expressions, you can use JavaScript RegExp
to extend your matching rules as follows:
async function App(context) {
return router([
// return the `SayHi` action when receiving case-insensitive "hi" or "hello" text messages
text(/^(hi|hello)$/i, SayHi),
]);
}
By using the regular expression, your bot now handles "HI", "Hello" text messages as well.
Sometimes you may want to add named capture groups to your JavaScript RegExps:
async function App(context) {
return router([
// return the `Command` action when receiving "/join", "/invite", or "/whatever" text messages
text(/^\/(?<command>\S+)$/i, Command),
]);
}
Then, you can access the result of the match groups in your props
:
async function Command(
context,
{
match: {
groups: { command },
},
}
) {
// | input | command |
// | --------- | ---------- |
// | /join | `join` |
// | /invite | `invite` |
// | /whatever | `whatever` |
await context.sendText(`Executing command: ${command}`);
}
Note:
RegExp Named Capturing Groups
is supported by Node 10+.
Fallback Routes
By using the *
as the first argument of the text
function, you may define a route for the unhandled text message events. The route triggers whenever no other route matches the incoming text event. Meanwhile, handling unhandled text message events is a chance to guide your users by sending a fallback message or a user's manual. For example:
async function Unknown(context) {
await context.sendText('Sorry. I do not understand what you say.');
}
async function App(context) {
return router([
text(/^(hi|hello)$/i, SayHi),
// return the `Unknown` action when when no other route matches the incoming text message
text('*', Unknown),
]);
}
Besides all unhandled text message events, you can fallback all kind of events by using route('*', ...)
instead:
const { router, route, text } = require('bottender/router');
async function App(context) {
return router([
text(/^(hi|hello)$/i, SayHi),
// return the `Unknown` action when no other route matches the incoming event
route('*', Unknown),
]);
}
Note: The fallback route must be the last route in your router.
Payload Routes
Payload events typically happen when users send payload data by clicking buttons, selecting menus, or clicking keyboards. For example, you may catch GET_STARTED
payload that sends by clicking the button and respond with the SayHi
action:
const { router, payload } = require('bottender/router');
async function App(context) {
return router([
payload('GET_STARTED', SayHi),
// return the `Unknown` action when no other route matches the incoming event
route('*', Unknown),
]);
}
Custom Routes
If you prefer to use your route predicate, you may use the route
function to create your route wrapper. The route
function takes a function that returns a boolean as the first argument:
const { router, route } = require('bottender/router');
function sayHiTo(name, Action) {
return route((context) => context.event.text === `Hi ${name}`, Action);
}
async function App(context) {
return router([
sayHiTo('Bottender', SayHi),
// return the `Unknown` action when no other route matches the incoming event
route('*', Unknown),
]);
}
In the above example, the custom route matches the "Hi Bottender" text messages and returns the SayHi
action.
Platform Specific Routes
Bottender includes a bunch of helpers to route within your multi-platform app. To learn more about the details of those specific routes, check out their documentation accordingly: