规则(options)
使用 webot.set
和 webot.wait
等方法时,会自动新建一条 rule ,
rule 定义的具体可用参数如下:
options.name
为规则命名,方便使用 webot.get
获取规则。
options.pattern
消息匹配规则,用以判断是否对用户发送的消息进行回复。如果为正则表达式和字符串,
则只匹配用户发送的文本消息(也就是 info.text !== undefined
的消息)。
所有支持的格式:
- {String} 如果是潜在的 RegExp (如字符串 '/abc/igm' ),会被转为 RegExp,如果以 '=' 打头,则完全匹配,否则模糊匹配
- {RegExp} 正则表达式,匹配到的捕获组会被赋予
info.param
,可通过info.param[1]
,info.param[2]
.. 获取 - {Function} 该函数只接受一个参数
info
,返回布尔值 - {NULL} 不指定 pattern ,则视为通过匹配,此 Rule 的 handler 将总是会执行
示例:
// 匹配下列所有消息:
//
// 你是机器人吗
// 难道你是机器人?
// 你是不是机器人?
// ...
//
webot.set('Blur match', {
pattern: '是机器人',
handler: '是的,我就是一名光荣的机器人'
});
// 当字符串 pattern 以 "=" 开头时,则会完全匹配
webot.set('Exact match', {
pattern: '=a',
handler: '只有回复「a」时才会看到本消息'
});
// 利用正则来匹配
webot.set('your name', {
pattern: /^(?:my name is|i am|我(?:的名字)?(?:是|叫)?)\s*(.*)$/i,
handler: function(info) {
return '你好,' + info.param[1];
},
// 或者直接返回字符串,webot 会自动替换匹配关键字
// handler: '你好,{1}'
});
// 类正则的字符串会被还原为正则
webot.set('/(good\s*)morning/i', '早上好,先生');
// 可以接受 function
webot.set('pattern as fn', {
pattern: function(info){
return info.param.eventKey === 'subscribe';
},
handler: '你好,欢迎关注我'
});
options.handler
指定如何生成回复消息
当返回非真值(null/false)时继续执行下一个动作,否则返回值会被回复给用户。
支持的定义格式:
- {String} 直接返回字符串
- {Array} 从数组中随机取一个作为 handler
- {Object} 直接返回
- {Function} 执行函数获取返回值,第一个参数为消息请求的 info 对象
支持异步:
webot.set('search_database', {
description: 'Search a keyword from database',
pattern: /^(?:s\s+)(.+)$/i,
handler: function(info, next) {
// assert(this.name == 'search_database');
// 函数内的 this 变量即此规则
// 执行一个异步操作..
query_from_database(info.text, function(err, ret) {
if (err) return next(500);
return next(null, ret);
});
}
});
在函数执行过程中,如果设置 info.ended = true
,即使没有返回可用的回复,也不会再继续下一条规则。
此时会 fallback 到预设的 404 错误,参见 webot.codeReplies。
注意:
你是否注意到,handler
允许异步操作,而 pattern
却不可以?
事实上,所有的 pattern 操作,都可以放到 handler
里执行:
webot.set('test_A', {
handler: function(info, next) {
if (info.text == 'A') {
next(null, 'You said A.');
}
next();
}
});
或者更省略一点:
webot.set(function test_A(info) {
if (info.text == 'A') {
return 'You said A.';
}
});
所以,异步的匹配可以写成:
webot.set('test', {
handler: function(info, next) {
var uid = info.uid;
User.findOne(uid, function(err, doc) {
if (!doc) {
// 异步判断失败,进入下一条规则
return next();
}
// 判断成功后需要执行的操作在这里
return next(null, '欢迎你,' + doc.name);
});
}
});
相信你并不会太需要在匹配消息规则时也进行异步。
事实上,很多需求都可以转化为使用 webot.beforeReply
。
options.replies
指定如何再次回复用户的回复。即用户回复了根据当前规则回复的消息后,如何继续对话。必须先配置 session支持。
webot.set('guess my sex', {
pattern: /是男.还是女.|你.*男的女的/,
handler: '你猜猜看呐',
replies: {
'/女|girl/i': '人家才不是女人呢',
'/男|boy/i': '是的,我就是翩翩公子一枚',
'both|不男不女': '你丫才不男不女呢',
'不猜': '好的,再见',
'/.*/': function(info) {
// 在 replies 的 handler 里可以获得等待回复的重试次数参数
if (info.rewaitCount < 2) {
info.rewait();
return '你到底还猜不猜嘛!';
}
return '看来你真的不想猜啊';
},
}
也可以用一个函数搞定:
replies: function(info){
return '嘻嘻,不告诉你'
}
也可以是数组格式,每个元素为一条rule
replies: [{
pattern: '/^g(irl)?\\??$/i',
handler: '猜错'
},{
pattern: '/^b(oy)?\\??$/i',
handler: '猜对了'
},{
pattern: 'both',
handler: '对你无语...'
}]
});