bottender-compose
An utility library for Bottender and higher-order handlers
Installation
npm install bottender-compose
API Reference
series
Creates a function that executes methods in series.
const { series, sendText } = require('bottender-compose');
bot.onEvent(
series([
sendText('1. First Item'),
sendText('2. Second Item'),
sendText('3. Third Item'),
])
);
parallel
Creates a function that executes methods in parallel.
const { parallel, sendText } = require('bottender-compose');
bot.onEvent(
parallel([
sendText('- You got one of Items'),
sendText('- You got one of Items'),
sendText('- You got one of Items'),
])
);
random
Creates a function that executes one of method randomly.
const { random, sendText } = require('bottender-compose');
bot.onEvent(
random([
sendText('You got a random item: A'),
sendText('You got a random item: B'),
sendText('You got a random item: C'),
])
);
branch
Creates a function that will process either the onTrue
or the onFalse
function depending upon the result of the condition predicate.
Furthermore, branch
can be sued as curry function.
const { branch, sendText } = require('bottender-compose');
bot.onEvent(
branch(
context => true,
sendText('You are the lucky one.'),
sendText('Too bad.')
)
);
const trueConditionBranch = branch(context => true);
bot.onEvent(
trueConditionBranch(sendText('You are the lucky one.'), sendText('Too bad.'))
);
Or you can executes function on true
and do nothing when received false
.
branch(context => true, sendText('You are the lucky one.'));
condition
Creates a function that encapsulates if/else
, if/else
, ... logic.
const { condition, sendText } = require('bottender-compose');
bot.onEvent(
condition([
[context => false, sendText('a')],
[context => false, sendText('b')],
[context => true, sendText('c')],
])
);
match
Creates a function that encapsulates value matching logic.
const { match, sendText } = require('bottender-compose');
bot.onEvent(
match('a', [
['a', sendText('You got a A')],
['b', sendText('You got a B')],
['c', sendText('You got a C')],
])
);
It accepts function with context
argument:
bot.onEvent(
match(context => context.state.answer, [
['a', sendText('You got a A')],
['b', sendText('You got a B')],
['c', sendText('You got a C')],
])
);
const matchAnswer = match(context => context.state.answer);
bot.onEvent(
matchAnswer([
['a', sendText('You got a A')],
['b', sendText('You got a B')],
['c', sendText('You got a C')],
])
);
To assign default action, use _
as pattern:
const { _, match, sendText } = require('bottender-compose');
bot.onEvent(
match('a', [
['a', sendText('You got a A')],
['b', sendText('You got a B')],
['c', sendText('You got a C')],
[_, sendText('You got something')],
])
);
platform
Creates a function that will process function depending upon the platform context.
const {
platform,
sendGenericTemplate,
sendImagemap,
} = require('bottender-compose');
bot.onEvent(platform({
messenger: sendGenericTemplate(...),
line: sendImagemap(...),
}));
Or you can use others
key to match other platforms:
platform({
messenger: sendGenericTemplate(...),
line: sendImagemap(...),
others: sendText('Unsupported.'),
});
tryCatch
Creates a function that calls error handler on error.
Furthermore, tryCatch
can be sued as curry function.
const { tryCatch, sendText } = require('bottender-compose');
bot.onEvent(
tryCatch(doSomethingMayFail(), sendText('Error Happened~~~~~~~~~~~!'))
);
const mayFailTryCatch = tryCatch(doSomethingMayFail());
bot.onEvent(mayFailTryCatch(sendText('Error Happened~~~~~~~~~~~!')));
weight
Creates a function that randomly executes one of method by its weight.
const { weight, sendText } = require('bottender-compose');
bot.onEvent(
weight([
[0.2, sendText('20%')],
[0.4, sendText('40%')],
[0.4, sendText('40%')],
])
);
doNothing
Creates a no-op function.
const { branch, sendText, doNothing } = require('bottender-compose');
bot.onEvent(
branch(
context => false,
sendText('You are the lucky one.'),
doNothing()
)
);
repeat
Creates a function that executes the method repeatedly.
Furthermore, repeat
can be sued as curry function.
const { repeat, sendText } = require('bottender-compose');
bot.onEvent(repeat(3, sendText('This will be sent 3 times.')));
const repeatFiveTimes = repeat(5);
bot.onEvent(repeatFiveTimes(sendText('This will be sent 5 times.')));
delay
Creates a function that executes methods after a number of milliseconds.
const { series, delay, sendText } = require('bottender-compose');
bot.onEvent(
series([
sendText('1. First Item'),
delay(1000),
sendText('2. Second Item'),
delay(1000),
sendText('3. Third Item'),
])
);
setDisplayName
Assigns to the displayName
property on the action.
const { setDisplayName, sendText } = require('bottender-compose');
setDisplayName('sayHello', sendText('hello'));
setDisplayName('sayHello')(sendText('hello'));
effect
const { effect } = require('bottender-compose');
bot.onEvent(
effect(
async context => {
await doSomeSideEffects();
return {
derivedState: {
x: 1,
},
derivedParam: {
y: 2,
},
};
},
async (context, param) => {
console.log(context.state.x);
console.log(param.y);
}
)
);
Logger Methods
B.series([
B.log('sending hello'),
B.info('sending hello'),
B.warn('sending hello'),
B.error('sending hello'),
B.sendText('hello'),
]);
It supports template too.
B.series([
B.log('user: {{ session.user.id }} x: {{ state.x }}'),
B.sendText('hello'),
]);
You can use your owner adapter for the logger:
const { log, info, warn, error } = B.createLogger({
log: debug('log'),
info: debug('info'),
warn: debug('warn'),
error: debug('error'),
});
B.series([log('sending hello'), B.sendText('hello')]);
Context Methods
Common
Messenger
sendMessage
sendText
sendAttachment
sendAudio
sendImage
sendVideo
sendFile
sendTemplate
sendButtonTemplate
sendGenericTemplate
sendListTemplate
sendOpenGraphTemplate
sendMediaTemplate
sendReceiptTemplate
sendAirlineBoardingPassTemplate
sendAirlineCheckinTemplate
sendAirlineItineraryTemplate
sendAirlineFlightUpdateTemplate
sendSenderAction
markSeen
typingOn
typingOff
passThreadControl
passThreadControlToPageInbox
takeThreadControl
requestThreadControl
associateLabel
dissociateLabel
LINE
sendText
sendImage
sendVideo
sendAudio
sendLocation
sendSticker
sendImagemap
sendButtonTemplate
sendConfirmTemplate
sendCarouselTemplate
sendImageCarouselTemplate
reply
replyText
replyImage
replyVideo
replyAudio
replyLocation
replySticker
replyImagemap
replyButtonTemplate
replyConfirmTemplate
replyCarouselTemplate
replyImageCarouselTemplate
push
pushText
pushImage
pushVideo
pushAudio
pushLocation
pushSticker
pushImagemap
pushButtonTemplate
pushConfirmTemplate
pushCarouselTemplate
pushImageCarouselTemplate
linkRichMenu
unlinkRichMenu
Slack
sendText
postMessage
postEphemeral
Telegram
sendText
sendMessage
sendPhoto
sendAudio
sendDocument
sendSticker
sendVideo
sendVoice
sendVideoNote
sendMediaGroup
sendLocation
sendVenue
sendContact
sendChatAction
editMessageText
editMessageCaption
editMessageReplyMarkup
deleteMessage
editMessageLiveLocation
stopMessageLiveLocation
forwardMessageFrom
forwardMessageTo
kickChatMember
unbanChatMember
restrictChatMember
promoteChatMember
exportChatInviteLink
setChatPhoto
deleteChatPhoto
setChatTitle
setChatDescription
setChatStickerSet
deleteChatStickerSet
pinChatMessage
unpinChatMessage
leaveChat
sendInvoice
answerShippingQuery
answerPreCheckoutQuery
answerInlineQuery
sendGame
setGameScore
Viber
sendMessage
sendText
sendPicture
sendVideo
sendFile
sendContact
sendLocation
sendURL
sendSticker
sendCarouselContent
Facebook
sendComment
sendPrivateReply
Passing Function as Argument to Context Method
You can pass function as argument to handle time-specified or context-specified case, for example:
B.sendText(() => `Now: ${new Date()}`);
B.sendText(
context =>
`${context.session.user.first_name} ${
context.session.user.last_name
}, You are the lucky one.`
);
B.sendText(context => `Received: ${context.event.text}`);
Use Template in String
You can use context
, session
, event
, state
to access values in your template string:
B.sendText('Hi, {{session.user.first_name}} {{session.user.last_name}}');
B.sendText('Received: {{event.text}}');
B.sendText('State: {{state.xxx}}');
License
MIT © Yoctol