bottender-compose
An utility library for Bottender and higher-order handlers
Installation
npm install bottender-compose
API Reference
TOC
Actions
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.'));
branch
works well with predicates.
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')],
])
);
condition
works well with predicates.
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 used 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()
Does side effects and mutate state or parameters.
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);
}
)
);
attachOptions()
Attaches additional options to the action.
const { attachOptions, sendText } = require('bottender-compose');
bot.onEvent(
attachOptions({ tag: 'ISSUE_RESOLUTION' }, sendText('Issue Resolved'))
);
const attachIssueResolutionTag = attachOptions({ tag: 'ISSUE_RESOLUTION' });
bot.onEvent(attachIssueResolutionTag(sendText('Issue Resolved')));
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
setState()
resetState()
typing()
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()
sendLike()
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
, user
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}}');
B.sendText('User: {{user.first_name}} {{user.last_name}}');
Or use param
to access object values that provided as sencond argument when calling action:
B.sendText('User: {{param.name}}')(context, { name: 'Super User' });
Predicates
isTextMatch()
Creates a predicate function to return true when text matches.
const { isTextMatch } = require('bottender-compose');
isTextMatch('abc')(context);
isTextMatch(/abc/)(context);
isPayloadMatch()
Creates a predicate function to return true when payload matches.
const { isPayloadMatch } = require('bottender-compose');
isPayloadMatch('abc')(context);
isPayloadMatch(/abc/)(context);
hasStateEqual()
Creates a predicate function to return true when state matches.
const { hasStateEqual } = require('bottender-compose');
hasStateEqual('x', 1)(context);
hasStateEqual('x.y.z', 1)(context);
hasStateEqual('x', { y: { z: 1 } })(context);
not()
Creates a predicate function with not condition.
const { not, hasStateEqual } = require('bottender-compose');
const predicate = not(hasStateEqual('x', 1));
predicate(context);
and()
Creates a predicate function with and condition.
const { and, hasStateEqual } = require('bottender-compose');
const predicate = and([
isTextMatch('abc'),
hasStateEqual('x', 1))
]);
predicate(context)
or()
Creates a predicate function with or condition.
const { or, hasStateEqual } = require('bottender-compose');
const predicate = or([
isTextMatch('abc'),
hasStateEqual('x', 1))
]);
predicate(context)
alwaysTrue
Creates a predicate function that always return true
.
const { alwaysTrue } = require('bottender-compose');
const predicate = alwaysTrue();
predicate(context);
alwaysFalse
Creates a predicate function that always return false
.
const { alwaysFalse } = require('bottender-compose');
const predicate = alwaysFalse();
predicate(context);
Event Predicates
Messenger
isMessage()
isText()
hasAttachment()
isImage()
isAudio()
isVideo()
isLocation()
isFile()
isFallback()
isSticker()
isLikeSticker()
isQuickReply()
isEcho()
isPostback()
isGamePlay()
isOptin()
isPayment()
isCheckoutUpdate()
isPreCheckout()
isRead()
isDelivery()
isPayload()
isPolicyEnforcement()
isAppRoles()
isStandby()
isPassThreadControl()
isTakeThreadControl()
isRequestThreadControl()
isRequestThreadControlFromPageInbox()
isFromCustomerChatPlugin()
isReferral()
isBrandedCamera()
LINE
isMessage()
isText()
isImage()
isVideo()
isAudio()
isLocation()
isSticker()
isFollow()
isUnfollow()
isJoin()
isLeave()
isPostback()
isPayload()
isBeacon()
isAccountLink()
Slack
isMessage()
isChannelsMessage()
isGroupsMessage()
isImMessage()
isMpimMessage()
isText()
isInteractiveMessage()
isAppUninstalled()
isChannelArchive()
isChannelCreated()
isChannelDeleted()
isChannelHistoryChanged()
isChannelRename()
isChannelUnarchive()
isDndUpdated()
isDndUpdated_user()
isEmailDomainChanged()
isEmojiChanged()
isFileChange()
isFileCommentAdded()
isFileCommentDeleted()
isFileCommentEdited()
isFileCreated()
isFileDeleted()
isFilePublic()
isFileShared()
isFileUnshared()
isGridMigrationFinished()
isGridMigrationStarted()
isGroupArchive()
isGroupClose()
isGroupHistoryChanged()
isGroupOpen()
isGroupRename()
isGroupUnarchive()
isImClose()
isImCreated()
isImHistoryChanged()
isImOpen()
isLinkShared()
isMemberJoinedChannel()
isMemberLeftChannel()
isPinAdded()
isPinRemoved()
isReactionAdded()
isReactionRemoved()
isStarAdded()
isStarRemoved()
isSubteamCreated()
isSubteamMembersChanged()
isSubteamSelfAdded()
isSubteamSelfRemoved()
isSubteamUpdated()
isTeamDomainChange()
isTeamJoin()
isTeamRename()
isTokensRevoked()
isUrlVerification()
isUserChange()
Telegram
isMessage()
isText()
isAudio()
isDocument()
isGame()
isPhoto()
isSticker()
isVideo()
isVoice()
isVideoNote()
isContact()
isLocation()
isVenue()
isEditedMessage()
isChannelPost()
isEditedChannelPost()
isInlineQuery()
isChosenInlineResult()
isCallbackQuery()
isPayload()
isShippingQuery()
isPreCheckoutQuery()
Viber
isMessage()
isText()
isPicture()
isVideo()
isFile()
isSticker()
isContact()
isURL()
isLocation()
isSubscribed()
isUnsubscribed()
isConversationStarted()
isDelivered()
isSeen()
isFailed()
Facebook
isFeed()
isStatus()
isStatusAdd()
isStatusEdited()
isPost()
isPostRemove()
isComment()
isCommentAdd()
isCommentEdited()
isCommentRemove()
isLike()
isLikeAdd()
isLikeRemove()
isReaction()
isReactionAdd()
isReactionEdit()
isReactionRemove()
License
MIT © Yoctol