- [new] add better name to the return functions
- [breaking] rename param to props in effects and template (#95)
params
is deprecated. Use props
instead.
In effect
:
effect(
// function has side effects
async context => {
await doSomeSideEffects();
return {
derivedState: {
x: 1,
},
derivedProps: {
y: 2,
},
};
},
// action
async (context, props) => {
console.log(context.state.x); // 1
console.log(props.y); // 2
}
);
In template: Hi, {{ props.name }}
- [new] support isMemberJoined, isMemberLeft predicates (#94)
B.isMemberJoined();
B.isMemberLeft();
- [fix] support Chinese variable (#92)
- [new] support facebook
sendLike
- [fix] pass required otherArgs to compileTemplate
- [improve] improve warning when compiling template #82
Properties accessors in template is invalid -- expected return a string but got: object
Properties accessors (context.session.user) in template is invalid -- expected return a non-empty string but got: object
- [new] add param support for template string:
use param
to access object values that provided as sencond argument when calling action:
B.sendText('User: {{param.name}}')(context, { name: 'Super User' });
- [fix] add missing export for
attachOptions
.
- [new] add
attachOptions
:
Attaches additional options to the action.
const { attachOptions, sendText } = require('bottender-compose');
bot.onEvent(
attachOptions({ tag: 'ISSUE_RESOLUTION' }, sendText('Issue Resolved'))
);
// curry function
const attachIssueResolutionTag = attachOptions({ tag: 'ISSUE_RESOLUTION' });
bot.onEvent(attachIssueResolutionTag(sendText('Issue Resolved')));
- [new] add predicates:
Creates a predicate function to return true when text matches.
const { isTextMatch } = require('bottender-compose');
isTextMatch('abc')(context); // boolean
isTextMatch(/abc/)(context); // boolean
Creates a predicate function to return true when payload matches.
const { isPayloadMatch } = require('bottender-compose');
isPayloadMatch('abc')(context); // boolean
isPayloadMatch(/abc/)(context); // boolean
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
Creates a predicate function with not condition.
const { not, hasStateEqual } = require('bottender-compose');
const predicate = not(hasStateEqual('x', 1));
predicate(context); // boolean
Creates a predicate function with and condition.
const { and, hasStateEqual } = require('bottender-compose');
const predicate = and([
isTextMatch('abc'),
hasStateEqual('x', 1))
]);
predicate(context) // boolean
Creates a predicate function with or condition.
const { or, hasStateEqual } = require('bottender-compose');
const predicate = or([
isTextMatch('abc'),
hasStateEqual('x', 1))
]);
predicate(context) // boolean
Creates a predicate function that always return true
.
const { alwaysTrue } = require('bottender-compose');
const predicate = alwaysTrue();
predicate(context); // true
Creates a predicate function that always return false
.
const { alwaysFalse } = require('bottender-compose');
const predicate = alwaysFalse();
predicate(context); // false
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
isMessage
isText
isImage
isVideo
isAudio
isLocation
isSticker
isFollow
isUnfollow
isJoin
isLeave
isPostback
isPayload
isBeacon
isAccountLink
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
isMessage
isText
isAudio
isDocument
isGame
isPhoto
isSticker
isVideo
isVoice
isVideoNote
isContact
isLocation
isVenue
isEditedMessage
isChannelPost
isEditedChannelPost
isInlineQuery
isChosenInlineResult
isCallbackQuery
isPayload
isShippingQuery
isPreCheckoutQuery
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
- [fix] fallback to empty string when template getting falsy value
- [new] Support user accessor:
{{user.xxx}}
in template.
- [fix] run babel compilation before publish.
- [new] build source with babel to have real support for node >= 7.6
- Add new 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')]);
- [new]
effect
:
const { effect } = require('bottender-compose');
bot.onEvent(
effect(
// function has side effects
async context => {
await doSomeSideEffects();
return {
derivedState: {
x: 1,
},
derivedParam: {
y: 2,
},
};
},
// action
async (context, param) => {
console.log(context.state.x); // 1
console.log(param.y); // 2
}
)
);
- [new] also overwrite name in
setDisplayName
- [fix] pass extra args to match value function (#58)
- [fix] pass extra args to all of context fns (#59)
- [new] Add
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'));
- [fix] warning condition on compileTemplate method.
- [new] 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}}');
- [new] Support
match
:
Create 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')],
])
);
// curry function
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')],
])
);
- [new] Curry branch, repeat and tryCatch:
// curry branch
const trueConditionBranch = branch(context => true);
bot.onEvent(
trueConditionBranch(sendText('You are the lucky one.'), sendText('Too bad.'))
);
// curry repeat
const repeatFiveTimes = repeat(5);
bot.onEvent(repeatFiveTimes(sendText('This will be sent 5 times.')));
// curry tryCatch
const mayFailTryCatch = tryCatch(doSomethingMayFail());
bot.onEvent(mayFailTryCatch(sendText('Error Happened~~~~~~~~~~~!')));
- [new] support otherArgs:
const action = (context, ...otherArgs) => {};
- [new] Support new methods:
telegram:
-
editMessageText
-
editMessageCaption
-
editMessageReplyMarkup
-
deleteMessage
-
editMessageLiveLocation
-
stopMessageLiveLocation
-
forwardMessageFrom
-
forwardMessageTo
-
[removed] remove useless
messenger:
getAssociatedLabels
line:
getLinkedRichMenu
- [new] Support new methods:
messenger:
requestThreadControl
slack:
postEphemeral
telegram:
kickChatMember
unbanChatMember
restrictChatMember
promoteChatMember
exportChatInviteLink
setChatPhoto
deleteChatPhoto
setChatTitle
setChatDescription
setChatStickerSet
deleteChatStickerSet
pinChatMessage
unpinChatMessage
leaveChat
answerShippingQuery
answerPreCheckoutQuery
answerInlineQuery
- [new] Support passing function as argument to context methods:
You can pass function as argument to handle time-specified or context-specified case, for example:
// Lazy execution
B.sendText(() => `Now: ${new Date()}`);
// Use user information on context
B.sendText(
context =>
`${context.session.user.first_name} ${context.session.user.last_name}, You are the lucky one.`
);
// Use event information
B.sendText(context => `Received: ${context.event.text}`);
- [new] Support methods:
passThreadControl
passThreadControlToPageInbox
takeThreadControl
sendMediaGroup
sendInvoice
sendGame
setGameScore
- [new] Support
repeat
anddelay
.
- [new] Support
weight
anddoNothing
.
- [fix] Fix
random
runtime bug
- [new] Support
platform
andtryCatch
. - [new] Export
typing
. - [new] Export Viber, FB methods.
- [new] Support
branch
andcondition
.
- [fix] Export
series
,parallel
api methods.
- [new] Support
series
,parallel
,random
, and most of api methods.