Awesome
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');
module.exports = function App() {
return 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');
module.exports = function App() {
return 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');
module.exports = function App() {
return 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');
module.exports = function App() {
return branch(
context => true,
sendText('You are the lucky one.'),
sendText('Too bad.')
);
};
// curry function
const trueConditionBranch = branch(context => true);
module.exports = function App() {
return 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');
module.exports = function App() {
return 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');
module.exports = function App() {
return 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:
module.exports = function App() {
return match(context => context.state.answer, [
['a', sendText('You got a A')],
['b', sendText('You got a B')],
['c', sendText('You got a C')],
]);
};
// curry function
const matchAnswer = match(context => context.state.answer);
module.exports = function App() {
return 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');
module.exports = function App() {
return 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');
module.exports = function App() {
return platform({
messenger: sendGenericTemplate(...),
line: sendImagemap(...),
});
};
Or you can use others
key to match other platforms:
platform({
messenger: sendGenericTemplate(...),
line: sendImagemap(...),
others: sendText('Unsupported.'),
});
weight()
Creates a function that randomly executes one of method by its weight.
const { weight, sendText } = require('bottender-compose');
module.exports = function App() {
return weight([
[0.2, sendText('20%')],
[0.4, sendText('40%')],
[0.4, sendText('40%')],
]);
};
noop()
Creates a no-op function.
const { branch, sendText, noop } = require('bottender-compose');
module.exports = function App() {
return branch(
context => false,
sendText('You are the lucky one.'),
noop() // do exactly nothing...
);
};
repeat()
Creates a function that executes the method repeatedly.
Furthermore, repeat
can be sued as curry function.
const { repeat, sendText } = require('bottender-compose');
module.exports = function App() {
return repeat(3, sendText('This will be sent 3 times.'));
};
// curry function
const repeatFiveTimes = repeat(5);
module.exports = function App() {
return 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');
module.exports = function App() {
return 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'));
// curry function
setDisplayName('sayHello')(sendText('hello'));
attachOptions()
Attaches additional options to the action.
const { attachOptions, sendText } = require('bottender-compose');
module.exports = function App() {
return attachOptions(
{ tag: 'ISSUE_RESOLUTION' },
sendText('Issue Resolved')
);
};
// curry function
const attachIssueResolutionTag = attachOptions({
tag: 'ISSUE_RESOLUTION',
});
module.exports = function App() {
reutnr 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()
sendAirlineUpdateTemplate()
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()
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:
// Lazy execution
B.sendText(() => `Now: ${new Date()}`);
// Use event information
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('Received: {{event.text}}');
B.sendText('State: {{state.xxx}}');
Or use props
to access object values that provided as props when calling action:
B.sendText('User: {{props.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); // boolean
isTextMatch(/abc/)(context); // boolean
isPayloadMatch()
Creates a predicate function to return true when payload matches.
const { isPayloadMatch } = require('bottender-compose');
isPayloadMatch('abc')(context); // boolean
isPayloadMatch(/abc/)(context); // boolean
hasStateEqual()
Creates a predicate function to return true when state matches.
const { hasStateEqual } = require('bottender-compose');
hasStateEqual('x', 1)(context); // boolean
hasStateEqual('x.y.z', 1)(context); // boolean
hasStateEqual('x', { y: { z: 1 } })(context); // boolean
not()
Creates a predicate function with not condition.
const { not, hasStateEqual } = require('bottender-compose');
const predicate = not(hasStateEqual('x', 1));
predicate(context); // boolean
and()
Creates a predicate function with and condition.
const { and, hasStateEqual } = require('bottender-compose');
const predicate = and([
isTextMatch('abc'),
hasStateEqual('x', 1))
]);
predicate(context) // boolean
or()
Creates a predicate function with or condition.
const { or, hasStateEqual } = require('bottender-compose');
const predicate = or([
isTextMatch('abc'),
hasStateEqual('x', 1))
]);
predicate(context) // boolean
alwaysTrue
Creates a predicate function that always return true
.
const { alwaysTrue } = require('bottender-compose');
const predicate = alwaysTrue();
predicate(context); // true
alwaysFalse
Creates a predicate function that always return false
.
const { alwaysFalse } = require('bottender-compose');
const predicate = alwaysFalse();
predicate(context); // false
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()
isFeed()
isStatus()
isStatusAdd()
isStatusEdited()
isPost()
isPostRemove()
isComment()
isCommentAdd()
isCommentEdited()
isCommentRemove()
isLike()
isLikeAdd()
isLikeRemove()
isReaction()
isReactionAdd()
isReactionEdit()
isReactionRemove()
License
MIT © Yoctol