mm_os 2.0.5 → 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/com/cmd/README.md +3 -0
- package/core/com/cmd/com.json +4 -0
- package/core/com/cmd/config.tpl.json +41 -0
- package/core/com/cmd/drive.js +512 -0
- package/core/com/cmd/index.js +213 -0
- package/core/com/cmd/old/5w2h.js +54 -0
- package/core/com/cmd/old/drive.js +423 -0
- package/core/com/cmd/script.js +11 -0
- package/package.json +4 -3
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
// 指令名称, 用于动态增删改配置
|
|
3
|
+
"name": "demo",
|
|
4
|
+
// 标题, 用于查询指令时
|
|
5
|
+
"title": "指令标题",
|
|
6
|
+
// 标题, 用于介绍该指令的作用
|
|
7
|
+
"description": "暂无描述",
|
|
8
|
+
// 时态, 分before之前、main主要、after之后三个时态,
|
|
9
|
+
"tense": "main",
|
|
10
|
+
// 执行顺序, 数值越小的指令越优先执行
|
|
11
|
+
"sort": 1000,
|
|
12
|
+
// 指令分组, 可以将特有的指令分一个组, 方便用户查询
|
|
13
|
+
"group": "default",
|
|
14
|
+
// 指令分类, 例如: 查询服务类query、管理类admin、游戏类game
|
|
15
|
+
"type": "",
|
|
16
|
+
// 匹配关键词组, 当聊天中出现其中一个关键词则会执行该指令
|
|
17
|
+
"match": [],
|
|
18
|
+
// 不包含关键词, 如果匹配后, 出现不应该包含的关键词, 则不会执行指令
|
|
19
|
+
"not": [],
|
|
20
|
+
// 移除关键词, 如果聊天中含这些词, 将会被剔除在执行指令
|
|
21
|
+
"remove": [],
|
|
22
|
+
// 提取特定词, 如果聊天中含有特定词, 会被提取出来再执行指令
|
|
23
|
+
"extract": [],
|
|
24
|
+
/* 参数, 用于执行指令行为前抽取关键词进行验证, 然后再执行指令 */
|
|
25
|
+
"param": [{
|
|
26
|
+
// 参数名称, 用于提交数据时
|
|
27
|
+
"name": "number",
|
|
28
|
+
// 参数标题, 用于提示用户什么参数错误
|
|
29
|
+
"title": "快递单号",
|
|
30
|
+
// 抽验顺序, 越小的越优先验证, 并且抽取后排列在前
|
|
31
|
+
"sort": 10,
|
|
32
|
+
// 抽取/校验格式, 如果格式不符合, 则表示验证未通过,提示用户
|
|
33
|
+
"format": "/[a-zA-Z0-9_]+/g",
|
|
34
|
+
// 缺少参数提示, 如果不包含该参数, 则做出的提示
|
|
35
|
+
"not_tip": "快递单号多少?",
|
|
36
|
+
// 错误提示, 提示用户补充参数时, 补充参数错误时做出的提示
|
|
37
|
+
"error_tip": "快递单号不正确",
|
|
38
|
+
// 校验/抽取的函数名, 通过函数的方式抽取/校验参数
|
|
39
|
+
"func_name": ""
|
|
40
|
+
}]
|
|
41
|
+
}
|
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
const Item = require('mm_machine').Item;
|
|
2
|
+
const Param = require('../param/drive.js');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 指令驱动类
|
|
6
|
+
* @extends {Item}
|
|
7
|
+
* @class
|
|
8
|
+
*/
|
|
9
|
+
class Drive extends Item {
|
|
10
|
+
/**
|
|
11
|
+
* 构造函数
|
|
12
|
+
* @param {String} dir 当前目录
|
|
13
|
+
* @constructor
|
|
14
|
+
*/
|
|
15
|
+
constructor(dir) {
|
|
16
|
+
super(dir, __dirname);
|
|
17
|
+
this.default_file = "./cmd.json";
|
|
18
|
+
|
|
19
|
+
// 开关 true为开启, false为关闭
|
|
20
|
+
this.onOff = true;
|
|
21
|
+
|
|
22
|
+
/* 通用项 */
|
|
23
|
+
// 配置参数
|
|
24
|
+
this.config = {
|
|
25
|
+
// 标识名
|
|
26
|
+
"name": "demo",
|
|
27
|
+
// 分组名
|
|
28
|
+
"title": "指令标题",
|
|
29
|
+
// 描述, 用于描述该接口有什么用的
|
|
30
|
+
"description": "暂无描述",
|
|
31
|
+
// 文件名
|
|
32
|
+
"func_file": "./index.js",
|
|
33
|
+
// 时态, 分before之前、main主要、after之后三个时态,
|
|
34
|
+
"tense": "main",
|
|
35
|
+
// 加载顺序,数字越大越后面加载
|
|
36
|
+
"sort": 1000,
|
|
37
|
+
// 分组
|
|
38
|
+
"group": "default",
|
|
39
|
+
// 类型: query便民查询,action执行,game游戏,orther其他,为空表示未分类
|
|
40
|
+
"type": "",
|
|
41
|
+
// 匹配关键词
|
|
42
|
+
"match": [],
|
|
43
|
+
// 不含关键词
|
|
44
|
+
"not_match": [],
|
|
45
|
+
// 去除关键词
|
|
46
|
+
"remove": [],
|
|
47
|
+
// 摘取
|
|
48
|
+
"extract": [],
|
|
49
|
+
// 第一阶段
|
|
50
|
+
"stage1": {
|
|
51
|
+
// 方式
|
|
52
|
+
"mode": "fill",
|
|
53
|
+
// 验证参数集
|
|
54
|
+
"param": [
|
|
55
|
+
// {
|
|
56
|
+
// // 参数名
|
|
57
|
+
// "name": "name",
|
|
58
|
+
// // 参数介绍名
|
|
59
|
+
// "title": "名称",
|
|
60
|
+
// // 参数格式
|
|
61
|
+
// "format": "",
|
|
62
|
+
// // 缺少参数提示语,传键值对,例如:{ number: "快递单号多少?" }
|
|
63
|
+
// "not_tip": "",
|
|
64
|
+
// // 错误提示
|
|
65
|
+
// "error_tip": "",
|
|
66
|
+
// // 监听语法
|
|
67
|
+
// "listen": "",
|
|
68
|
+
// // 校验函数明
|
|
69
|
+
// "func_name": ""
|
|
70
|
+
// },
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
// 第二阶段
|
|
74
|
+
"stage2": {
|
|
75
|
+
// 方式
|
|
76
|
+
"mode": "update",
|
|
77
|
+
// 验证参数集
|
|
78
|
+
"param": []
|
|
79
|
+
},
|
|
80
|
+
// 第三阶段
|
|
81
|
+
"stage3": {
|
|
82
|
+
// 方式
|
|
83
|
+
"mode": "fill",
|
|
84
|
+
// 验证参数集
|
|
85
|
+
"param": []
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 创建一个参数模型
|
|
94
|
+
*/
|
|
95
|
+
Drive.prototype.model = function() {
|
|
96
|
+
return {
|
|
97
|
+
// 参数名
|
|
98
|
+
"name": "name",
|
|
99
|
+
// 参数介绍名
|
|
100
|
+
"title": "名称",
|
|
101
|
+
// 排序
|
|
102
|
+
"sort": 10,
|
|
103
|
+
// 监听语法
|
|
104
|
+
"listen": "",
|
|
105
|
+
// 参数格式
|
|
106
|
+
"format": "",
|
|
107
|
+
// 缺少参数提示语
|
|
108
|
+
"not_tip": "",
|
|
109
|
+
// 更新提示
|
|
110
|
+
"update_tip": "",
|
|
111
|
+
// 错误提示
|
|
112
|
+
"error_tip": ""
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* 校验是否匹配指令
|
|
119
|
+
* @param {Object} content 请求的正文
|
|
120
|
+
* @param {Object} db 数据管理器
|
|
121
|
+
* @return {Boolean} 匹配返回true,不匹配返回false
|
|
122
|
+
*/
|
|
123
|
+
Drive.prototype.match = function(content, db) {
|
|
124
|
+
var bl = false;
|
|
125
|
+
var arr = this.config.match;
|
|
126
|
+
for (var i = 0; i < arr.length; i++) {
|
|
127
|
+
var format = arr[i];
|
|
128
|
+
if (content.matchs(format)) {
|
|
129
|
+
bl = true;
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return bl;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 校验是否不含关键词
|
|
139
|
+
* @param {Object} content 请求的正文
|
|
140
|
+
* @param {Object} db 数据管理器
|
|
141
|
+
* @return {Boolean} 不含返回true,含有返回false
|
|
142
|
+
*/
|
|
143
|
+
Drive.prototype.not_match = function(content, db) {
|
|
144
|
+
var bl = true;
|
|
145
|
+
var arr = this.config.not_match;
|
|
146
|
+
for (var i = 0; i < arr.length; i++) {
|
|
147
|
+
var format = arr[i];
|
|
148
|
+
if (content.matchs(format)) {
|
|
149
|
+
bl = false;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return bl;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* 抽取正文
|
|
159
|
+
* @param {String} content 正文
|
|
160
|
+
* @param {Object} db 数据管理器
|
|
161
|
+
* @return {Object} 返回过滤后的参数
|
|
162
|
+
*/
|
|
163
|
+
Drive.prototype.extract = async function(content, db) {
|
|
164
|
+
var list = this.config.extract;
|
|
165
|
+
var ret = content;
|
|
166
|
+
var len = list.length;
|
|
167
|
+
for (var i = 0; i < len; i++) {
|
|
168
|
+
var format = list[i];
|
|
169
|
+
var str = content.matchs(format);
|
|
170
|
+
if (str) {
|
|
171
|
+
ret += "\r\n" + str;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return ret;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* 移除关键词
|
|
180
|
+
* @param {String} content 正文
|
|
181
|
+
* @param {Object} db 数据管理器
|
|
182
|
+
* @return {Object} 返回过滤后的参数
|
|
183
|
+
*/
|
|
184
|
+
Drive.prototype.remove = async function(content, db) {
|
|
185
|
+
var list = this.config.remove;
|
|
186
|
+
var len = list.length;
|
|
187
|
+
for (var i = 0; i < len; i++) {
|
|
188
|
+
var str = list[i];
|
|
189
|
+
var value = content.matchs(str);
|
|
190
|
+
if (value) {
|
|
191
|
+
content = content.replace(value, '');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return content;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* 修改提示
|
|
199
|
+
* @param {Object} msg 消息上下文
|
|
200
|
+
* @param {Object} db 数据管理器
|
|
201
|
+
* @return {Object} 返回过滤后的参数
|
|
202
|
+
*/
|
|
203
|
+
Drive.prototype.view_tip = async function(msg, db, tip) {
|
|
204
|
+
var form = this.view(msg, db);
|
|
205
|
+
tip = tip.replace("{form}", form);
|
|
206
|
+
return tip;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* 1. 检验阶段, 判断条件是否满足
|
|
211
|
+
* @param {Object} msg 消息上下文
|
|
212
|
+
* @param {Object} db 数据管理器
|
|
213
|
+
* @return {String} 验证失败返回错误提示
|
|
214
|
+
*/
|
|
215
|
+
Drive.prototype.check = async function(msg, db) {
|
|
216
|
+
// 校验是否匹配指令
|
|
217
|
+
var bl = await this.match(msg.content, db);
|
|
218
|
+
if (bl) {
|
|
219
|
+
bl = await this.not_match(msg.content, db);
|
|
220
|
+
}
|
|
221
|
+
return bl;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* 2. 过滤阶段, 抽出主要的内容
|
|
227
|
+
* @param {Object} msg 消息上下文
|
|
228
|
+
* @param {Object} db 数据管理器
|
|
229
|
+
* @return {Object} 返回过滤后的参数
|
|
230
|
+
*/
|
|
231
|
+
Drive.prototype.filter = async function(msg, db) {
|
|
232
|
+
var content = await this.extract(msg.content);
|
|
233
|
+
return await this.remove(content);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* 3.1 信息补全阶段 用于通知用户补全执行的必要条件
|
|
238
|
+
* @param {Object} msg 消息上下文
|
|
239
|
+
* @param {Object} db 数据管理器
|
|
240
|
+
* @param {Object} stage 阶段参数
|
|
241
|
+
* @return {Object} 返回参数表单
|
|
242
|
+
*/
|
|
243
|
+
Drive.prototype.fill = async function(msg, db, stage) {
|
|
244
|
+
if (!stage) {
|
|
245
|
+
return "";
|
|
246
|
+
}
|
|
247
|
+
var list = stage.param;
|
|
248
|
+
if(!list || list.length === 0){
|
|
249
|
+
return "";
|
|
250
|
+
}
|
|
251
|
+
var form = {};
|
|
252
|
+
var keyword = "";
|
|
253
|
+
// 是否有进行填充
|
|
254
|
+
var has_fill = false;
|
|
255
|
+
|
|
256
|
+
var ct = "";
|
|
257
|
+
// 判断参数
|
|
258
|
+
if (db.msg.form) {
|
|
259
|
+
form = db.msg.form.toJson();
|
|
260
|
+
} else {
|
|
261
|
+
// 补全内容
|
|
262
|
+
ct = db.msg.content;
|
|
263
|
+
var len = list.length;
|
|
264
|
+
for (var i = 0; i < len; i++) {
|
|
265
|
+
var o = list[i];
|
|
266
|
+
var k = o.name;
|
|
267
|
+
if (!form[k]) {
|
|
268
|
+
var value = ct.matchs(o.format);
|
|
269
|
+
if (value) {
|
|
270
|
+
form[k] = value;
|
|
271
|
+
keyword = k;
|
|
272
|
+
ct = ct.replace(value, '');
|
|
273
|
+
has_fill = true;
|
|
274
|
+
} else {
|
|
275
|
+
form[k] = "";
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
ct = msg.content;
|
|
281
|
+
var tip = "";
|
|
282
|
+
for (var k in form) {
|
|
283
|
+
if (!form[k]) {
|
|
284
|
+
keyword = k;
|
|
285
|
+
var o = list.getObj({
|
|
286
|
+
name: k
|
|
287
|
+
});
|
|
288
|
+
var value = ct.matchs(o.format);
|
|
289
|
+
if (value) {
|
|
290
|
+
form[k] = value;
|
|
291
|
+
ct = ct.replace(value, '');
|
|
292
|
+
has_fill = true;
|
|
293
|
+
} else {
|
|
294
|
+
msg.form = form;
|
|
295
|
+
if (ct && o.error_tip && has_fill == false) {
|
|
296
|
+
tip = await this.view_tip(msg, db, o.error_tip);
|
|
297
|
+
} else if (o.not_tip) {
|
|
298
|
+
tip = await this.view_tip(msg, db, o.not_tip);
|
|
299
|
+
}
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
db.msg.keyword = keyword;
|
|
306
|
+
db.msg.form = JSON.stringify(form);
|
|
307
|
+
msg.form = form;
|
|
308
|
+
return tip;
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* 3.2 更新信息 用于用户更改完善
|
|
313
|
+
* @param {Object} msg 消息上下文
|
|
314
|
+
* @param {Object} db 数据管理器
|
|
315
|
+
* @param {Object} stage 阶段参数
|
|
316
|
+
* @return {Object} 返回参数表单
|
|
317
|
+
*/
|
|
318
|
+
Drive.prototype.update = async function(msg, db, stage) {
|
|
319
|
+
if (!stage || !db.msg.form) {
|
|
320
|
+
return "";
|
|
321
|
+
}
|
|
322
|
+
var list = stage.param;
|
|
323
|
+
|
|
324
|
+
var tip = "";
|
|
325
|
+
var ct = msg.content;
|
|
326
|
+
var keyword = db.msg.keyword + "";
|
|
327
|
+
var form = db.msg.form.toJson();
|
|
328
|
+
var len = list.length;
|
|
329
|
+
for (var i = 0; i < len; i++) {
|
|
330
|
+
var o = list[i];
|
|
331
|
+
var k = o.name;
|
|
332
|
+
if (form[k]) {
|
|
333
|
+
var value = ct.matchs(o.listen);
|
|
334
|
+
if (value) {
|
|
335
|
+
if (o.update_tip) {
|
|
336
|
+
tip = o.update_tip;
|
|
337
|
+
} else {
|
|
338
|
+
tip = "那" + value.replace(value.matchs("{不对}"), '是?');
|
|
339
|
+
}
|
|
340
|
+
keyword = k;
|
|
341
|
+
break;
|
|
342
|
+
} else if (keyword == k && o.format) {
|
|
343
|
+
value = ct.matchs(o.format);
|
|
344
|
+
if (value) {
|
|
345
|
+
form[k] = value;
|
|
346
|
+
ct = ct.replace(value, '');
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
db.msg.keyword = keyword;
|
|
353
|
+
db.msg.form = JSON.stringify(form);
|
|
354
|
+
msg.form = form;
|
|
355
|
+
return tip;
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* 4. 执行阶段
|
|
360
|
+
* @param {Object} msg 消息上下文
|
|
361
|
+
* @param {Object} db 数据管理器
|
|
362
|
+
* @return {Object} 返回执行结果
|
|
363
|
+
*/
|
|
364
|
+
Drive.prototype.main = async function(msg, db) {
|
|
365
|
+
return "你好";
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* 5. 结束阶段 用来判断是否结束会话
|
|
370
|
+
* @param {Object} msg 消息上下文
|
|
371
|
+
* @param {Object} db 数据管理器
|
|
372
|
+
* @param {Object} ret 执行结果
|
|
373
|
+
* @return {Boolean} 返回会话结果
|
|
374
|
+
*/
|
|
375
|
+
Drive.prototype.end = async function(msg, db, ret) {
|
|
376
|
+
if (ret) {
|
|
377
|
+
var txt = "";
|
|
378
|
+
if (typeof(ret) == "object") {
|
|
379
|
+
txt = JSON.stringify(ret);
|
|
380
|
+
} else {
|
|
381
|
+
txt = ret;
|
|
382
|
+
}
|
|
383
|
+
if (txt.indexOf('?') === -1) {
|
|
384
|
+
db.msg.end = 1;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return ret;
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* 执行但不记录指令
|
|
392
|
+
* @param {Object} msg 消息上下文
|
|
393
|
+
* @param {Object} db 数据管理器
|
|
394
|
+
* @return {Object} 返回执行结果
|
|
395
|
+
*/
|
|
396
|
+
Drive.prototype.run_cmd = async function(msg, db) {
|
|
397
|
+
var ret;
|
|
398
|
+
// 第一步, 验证阶段
|
|
399
|
+
var bl = await this.check(msg, db);
|
|
400
|
+
if (bl) {
|
|
401
|
+
ret = await this.run(msg, db);
|
|
402
|
+
}
|
|
403
|
+
return ret;
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* 执行
|
|
409
|
+
* @param {Object} msg 消息上下文
|
|
410
|
+
* @param {Object} db 数据管理器
|
|
411
|
+
* @return {Object} 返回执行结果
|
|
412
|
+
*/
|
|
413
|
+
Drive.prototype.run_first = async function(msg, db) {
|
|
414
|
+
var ret;
|
|
415
|
+
// 第一步, 验证阶段
|
|
416
|
+
var bl = await this.check(msg, db);
|
|
417
|
+
if (bl) {
|
|
418
|
+
ret = await this.run(msg, db);
|
|
419
|
+
if(ret){
|
|
420
|
+
// 如果匹配指令则将该消息定义为使用该指令
|
|
421
|
+
db.msg.cmd = this.config.name;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return ret;
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* 执行前 用于有历史信息时,直接获取,不重复询问
|
|
429
|
+
* @param {Object} msg 消息上下文
|
|
430
|
+
* @param {Object} db 数据管理器
|
|
431
|
+
* @return {Object} 执行结果, 如果有结果则直接跳过其他步骤,并返回
|
|
432
|
+
*/
|
|
433
|
+
Drive.prototype.run_before = async function(msg, db) {
|
|
434
|
+
return null;
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* 执行后, 用于特殊情况下的不结束会话
|
|
439
|
+
* @param {Object} msg 消息上下文
|
|
440
|
+
* @param {Object} db 数据管理器
|
|
441
|
+
* @param {Object} ret 执行结果
|
|
442
|
+
* @return {Object}
|
|
443
|
+
*/
|
|
444
|
+
Drive.prototype.run_after = async function(msg, db, ret) {
|
|
445
|
+
return ret;
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* 执行
|
|
450
|
+
* @param {Object} param 状态参数
|
|
451
|
+
* @param {Object} db 数据管理器
|
|
452
|
+
* @return {Object} 返回执行结果
|
|
453
|
+
*/
|
|
454
|
+
Drive.prototype.run = async function(msg, db) {
|
|
455
|
+
|
|
456
|
+
// 第二步, 过滤阶段
|
|
457
|
+
msg.content = await this.filter(msg, db);
|
|
458
|
+
|
|
459
|
+
// 执行前
|
|
460
|
+
var ret = await this.run_before(msg, db);
|
|
461
|
+
if (!ret) {
|
|
462
|
+
// 第三步, 信息补全或更新阶段
|
|
463
|
+
var stage = this.config["stage" + db.msg.stage];
|
|
464
|
+
if (stage) {
|
|
465
|
+
var mode = stage.mode ? stage.mode : "fill";
|
|
466
|
+
if (this[mode]) {
|
|
467
|
+
ret = await this[mode](msg, db, stage);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (!ret) {
|
|
472
|
+
// 第五步, 执行阶段
|
|
473
|
+
ret = await this.main(msg, db);
|
|
474
|
+
|
|
475
|
+
// 第六步, 结束会话阶段
|
|
476
|
+
ret = this.end(msg, db, ret);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
// 执行后
|
|
480
|
+
ret = await this.run_after(msg, db, ret);
|
|
481
|
+
return ret;
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* 查看参数
|
|
486
|
+
* @param {Object} param 状态参数
|
|
487
|
+
* @param {Object} db 数据管理器
|
|
488
|
+
* @return {Object} 返回结构化参数
|
|
489
|
+
*/
|
|
490
|
+
Drive.prototype.view = function(msg, db) {
|
|
491
|
+
var ret = "";
|
|
492
|
+
var json = msg.form;
|
|
493
|
+
if (json) {
|
|
494
|
+
var stage = this.config.stage1;
|
|
495
|
+
if (stage) {
|
|
496
|
+
var list = stage.param;
|
|
497
|
+
if (list) {
|
|
498
|
+
var len = list.length;
|
|
499
|
+
for (var i = 0; i < len; i++) {
|
|
500
|
+
var o = list[i];
|
|
501
|
+
var value = json[o.name];
|
|
502
|
+
if (value) {
|
|
503
|
+
ret += o.title + ": " + value + "\r\n";
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return ret.trim();
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
module.exports = Drive;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
const Index = require('mm_machine').Index;
|
|
2
|
+
const Drive = require('./drive');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Cmd导航类
|
|
6
|
+
* @extends {Index}
|
|
7
|
+
* @class
|
|
8
|
+
*/
|
|
9
|
+
class Cmd extends Index {
|
|
10
|
+
/**
|
|
11
|
+
* 构造函数
|
|
12
|
+
* @param {Object} scope 作用域
|
|
13
|
+
* @param {String} title 标题
|
|
14
|
+
* @constructor
|
|
15
|
+
*/
|
|
16
|
+
constructor(scope, title) {
|
|
17
|
+
super(scope, __dirname);
|
|
18
|
+
this.Drive = Drive;
|
|
19
|
+
this.type = "cmd";
|
|
20
|
+
this.title = title;
|
|
21
|
+
this.list_before = [];
|
|
22
|
+
this.list_main = [];
|
|
23
|
+
this.list_after = [];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 执行导航
|
|
29
|
+
* @param {Object} msg 消息
|
|
30
|
+
* @param {Object} db 数据管理器
|
|
31
|
+
* @param {String} table 表名
|
|
32
|
+
* @return {Object|String}
|
|
33
|
+
*/
|
|
34
|
+
Cmd.prototype.run = async function(msg, db, table) {
|
|
35
|
+
var ret;
|
|
36
|
+
// 判断是否含有消息和消息正文
|
|
37
|
+
if (msg && msg.content) {
|
|
38
|
+
db.msg = {
|
|
39
|
+
content: "",
|
|
40
|
+
content_last: msg.content,
|
|
41
|
+
form: "",
|
|
42
|
+
stage: 1
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// 判断是否启用数据库存储消息,如果表名为空则不存储消息
|
|
46
|
+
if (table) {
|
|
47
|
+
db.table = table;
|
|
48
|
+
db.key = "message_id";
|
|
49
|
+
var query = {
|
|
50
|
+
from_user: msg.from_user,
|
|
51
|
+
to_user: msg.to_user,
|
|
52
|
+
group: msg.group,
|
|
53
|
+
type: msg.type,
|
|
54
|
+
end: 0
|
|
55
|
+
};
|
|
56
|
+
// 获取当前未结束的会话记录
|
|
57
|
+
var msg_log = await db.getObj(query);
|
|
58
|
+
// 如果不存在未结束会话,则创建新会话记录
|
|
59
|
+
if (!msg_log) {
|
|
60
|
+
var bl = await db.add(msg);
|
|
61
|
+
if (bl) {
|
|
62
|
+
msg_log = await db.getObj(query);
|
|
63
|
+
if (msg_log) {
|
|
64
|
+
msg_log.create_time = new Date().toStr('yyyy-MM-dd hh:mm:ss');
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
$.log.error('添加微信消息到wechat_message表失败!', msg_log);
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
} else if (msg_log.content_last !== msg.content) {
|
|
71
|
+
// 判断是否重复会话内容,如果未重复则添加新内容
|
|
72
|
+
msg_log.content += '\r\n' + msg.content;
|
|
73
|
+
}
|
|
74
|
+
msg_log.content_last = msg.content;
|
|
75
|
+
db.msg = msg_log;
|
|
76
|
+
|
|
77
|
+
var lt = this.list_before;
|
|
78
|
+
for (var i = 0, o; o = lt[i++];) {
|
|
79
|
+
if (o.onOff) {
|
|
80
|
+
ret = await o.run_cmd(msg, db);
|
|
81
|
+
if (ret) {
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (!ret) {
|
|
87
|
+
// 判断会话记录是否锁定了指令, 如果存在则继续执行该指令程序
|
|
88
|
+
if (msg_log.cmd) {
|
|
89
|
+
// 检索指令驱动是否存在
|
|
90
|
+
var drive = this.list.getObj({
|
|
91
|
+
config: {
|
|
92
|
+
name: msg_log.cmd
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (drive) {
|
|
97
|
+
// 如果存在则执行指令
|
|
98
|
+
ret = await drive.run(msg, db);
|
|
99
|
+
} else {
|
|
100
|
+
// 如果不存在则结束会话, 并创建新会话
|
|
101
|
+
db.msg.end = 1;
|
|
102
|
+
var bl = await db.add(msg);
|
|
103
|
+
if (bl) {
|
|
104
|
+
msg_log = await db.getObj(query);
|
|
105
|
+
if (msg_log) {
|
|
106
|
+
msg_log.create_time = new Date().toStr('yyyy-MM-dd hh:mm:ss');
|
|
107
|
+
}
|
|
108
|
+
db.msg = msg_log;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (db.msg.keyword) {
|
|
114
|
+
// 添加消息
|
|
115
|
+
msg.content = db.msg.keyword + "\r\n" + msg.content;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (!ret) {
|
|
120
|
+
var lt = this.list_main;
|
|
121
|
+
for (var i = 0, o; o = lt[i++];) {
|
|
122
|
+
if (o.onOff) {
|
|
123
|
+
ret = await o.run_first(msg, db);
|
|
124
|
+
if (ret) {
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (!ret) {
|
|
131
|
+
var lt = this.list_after;
|
|
132
|
+
for (var i = 0, o; o = lt[i++];) {
|
|
133
|
+
if (o.onOff) {
|
|
134
|
+
ret = await o.run_first(msg, db);
|
|
135
|
+
if (ret) {
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return ret;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* 执行排序
|
|
147
|
+
*/
|
|
148
|
+
Cmd.prototype.sort = async function() {
|
|
149
|
+
this.list.sort(function(o1, o2) {
|
|
150
|
+
var p1 = o1.sort;
|
|
151
|
+
var p2 = o2.sort;
|
|
152
|
+
return p2 - p1;
|
|
153
|
+
});
|
|
154
|
+
this.sort_tense();
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* 排序时态
|
|
159
|
+
*/
|
|
160
|
+
Cmd.prototype.sort_tense = async function() {
|
|
161
|
+
this.list_before.clear();
|
|
162
|
+
this.list_after.clear();
|
|
163
|
+
this.list_main.clear();
|
|
164
|
+
|
|
165
|
+
var lt = this.list;
|
|
166
|
+
for (var i = 0; i < lt.length; i++) {
|
|
167
|
+
var o = lt[i];
|
|
168
|
+
switch (o.config.tense) {
|
|
169
|
+
case "before":
|
|
170
|
+
this.list_before.push(o);
|
|
171
|
+
break;
|
|
172
|
+
case "after":
|
|
173
|
+
this.list_after.push(o);
|
|
174
|
+
break;
|
|
175
|
+
default:
|
|
176
|
+
this.list_main.push(o);
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/* 导出指令 */
|
|
183
|
+
exports.Cmd = Cmd;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Cmd事件池
|
|
187
|
+
*/
|
|
188
|
+
if (!$.pool.cmd) {
|
|
189
|
+
$.pool.cmd = {};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Cmd管理器,用于创建缓存
|
|
194
|
+
* @param {String} scope 作用域
|
|
195
|
+
* @param {string} title 标题
|
|
196
|
+
* @return {Object} 返回一个缓存类
|
|
197
|
+
*/
|
|
198
|
+
function cmd_admin(scope, title) {
|
|
199
|
+
if (!scope) {
|
|
200
|
+
scope = $.val.scope + '';
|
|
201
|
+
}
|
|
202
|
+
var obj = $.pool.cmd[scope];
|
|
203
|
+
if (!obj) {
|
|
204
|
+
$.pool.cmd[scope] = new Cmd(scope, title);
|
|
205
|
+
obj = $.pool.cmd[scope];
|
|
206
|
+
}
|
|
207
|
+
return obj;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @module 导出Cmd管理器
|
|
212
|
+
*/
|
|
213
|
+
exports.cmd_admin = cmd_admin;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// 条件(待开发)
|
|
2
|
+
"condition": {
|
|
3
|
+
// 什么时候
|
|
4
|
+
"when": {
|
|
5
|
+
"datetime": "{0}",
|
|
6
|
+
},
|
|
7
|
+
// 什么地点
|
|
8
|
+
"where": {
|
|
9
|
+
// 省份
|
|
10
|
+
"province": "{0}",
|
|
11
|
+
// 城市
|
|
12
|
+
"city": "{0}",
|
|
13
|
+
// 管辖区
|
|
14
|
+
"area": "{0}",
|
|
15
|
+
// 详细地址
|
|
16
|
+
"address": ""
|
|
17
|
+
},
|
|
18
|
+
// 什么地点
|
|
19
|
+
"who": {
|
|
20
|
+
// 发话人
|
|
21
|
+
"fromUser": "{0}",
|
|
22
|
+
// 听话人
|
|
23
|
+
"toUser": "{0}",
|
|
24
|
+
// 牵涉人员
|
|
25
|
+
"involve": [],
|
|
26
|
+
// 机器人
|
|
27
|
+
"robot": "{0}"
|
|
28
|
+
},
|
|
29
|
+
// 做什么
|
|
30
|
+
"what": "",
|
|
31
|
+
// 为什么(一般为空)
|
|
32
|
+
"why": "",
|
|
33
|
+
// 怎么做
|
|
34
|
+
"how": [
|
|
35
|
+
/**
|
|
36
|
+
{
|
|
37
|
+
// 行为名称(当询问为空时,也是回调函数名称)
|
|
38
|
+
name: "not number",
|
|
39
|
+
// 执行标识
|
|
40
|
+
title: "缺少快递单号",
|
|
41
|
+
// 执行的先后顺序
|
|
42
|
+
sort: 10,
|
|
43
|
+
// 缺少参数的判断方法
|
|
44
|
+
not_match: "/[a-zA-Z0-9_]+/g",
|
|
45
|
+
// 询问用户,加强条件用
|
|
46
|
+
question: "快递单号多少?",
|
|
47
|
+
// 校验方法名称,通过函数判断
|
|
48
|
+
func_name: "",
|
|
49
|
+
}
|
|
50
|
+
*/
|
|
51
|
+
],
|
|
52
|
+
// 做到什么程度(传函数名, 成功表示满足条件, 不成功表示不满足)
|
|
53
|
+
"how much": {}
|
|
54
|
+
}
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
const Item = require('mm_machine').Item;
|
|
2
|
+
const Param = require('../param/drive.js');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 指令驱动类
|
|
6
|
+
* @extends {Item}
|
|
7
|
+
* @class
|
|
8
|
+
*/
|
|
9
|
+
class Drive extends Item {
|
|
10
|
+
/**
|
|
11
|
+
* 构造函数
|
|
12
|
+
* @param {String} dir 当前目录
|
|
13
|
+
* @constructor
|
|
14
|
+
*/
|
|
15
|
+
constructor(dir) {
|
|
16
|
+
super(dir, __dirname);
|
|
17
|
+
this.default_file = "./cmd.json";
|
|
18
|
+
|
|
19
|
+
// 开关 true为开启, false为关闭
|
|
20
|
+
this.onOff = true;
|
|
21
|
+
|
|
22
|
+
/* 通用项 */
|
|
23
|
+
// 配置参数
|
|
24
|
+
this.config = {
|
|
25
|
+
// 标识名
|
|
26
|
+
"name": "demo",
|
|
27
|
+
// 分组名
|
|
28
|
+
"title": "指令标题",
|
|
29
|
+
// 描述, 用于描述该接口有什么用的
|
|
30
|
+
"description": "暂无描述",
|
|
31
|
+
// 文件名
|
|
32
|
+
"func_file": "./index.js",
|
|
33
|
+
// 加载顺序,数字越大越后面加载
|
|
34
|
+
"sort": 1000,
|
|
35
|
+
// 分组
|
|
36
|
+
"group": "default",
|
|
37
|
+
// 类型: query便民查询,action执行,game游戏,orther其他,为空表示未分类
|
|
38
|
+
"type": "",
|
|
39
|
+
// 匹配关键词
|
|
40
|
+
"match": [],
|
|
41
|
+
// 不含关键词
|
|
42
|
+
"not_match": [],
|
|
43
|
+
// 过滤关键词
|
|
44
|
+
"filter": [],
|
|
45
|
+
// 摘取
|
|
46
|
+
"extract": [],
|
|
47
|
+
// 验证参数集
|
|
48
|
+
"param": [
|
|
49
|
+
// {
|
|
50
|
+
// // 参数名
|
|
51
|
+
// "name": "name",
|
|
52
|
+
// // 参数介绍名
|
|
53
|
+
// "title": "名称",
|
|
54
|
+
// // 参数格式
|
|
55
|
+
// "format": "",
|
|
56
|
+
// // 缺少参数提示语,传键值对,例如:{ number: "快递单号多少?" }
|
|
57
|
+
// "not_tip": "",
|
|
58
|
+
// // 错误提示
|
|
59
|
+
// "error_tip": ""
|
|
60
|
+
// },
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 创建一个参数模型
|
|
68
|
+
*/
|
|
69
|
+
Drive.prototype.model = function() {
|
|
70
|
+
return {
|
|
71
|
+
// 参数名
|
|
72
|
+
"name": "name",
|
|
73
|
+
// 参数介绍名
|
|
74
|
+
"title": "名称",
|
|
75
|
+
// 参数格式
|
|
76
|
+
"format": "",
|
|
77
|
+
// 缺少参数提示语,传键值对,例如:{ number: "快递单号多少?" }
|
|
78
|
+
"not_tip": "",
|
|
79
|
+
// 错误提示
|
|
80
|
+
"error_tip": ""
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* 为什么要这样做(疑问)
|
|
86
|
+
* @param {Object} param 状态参数
|
|
87
|
+
*/
|
|
88
|
+
Drive.prototype.why = async function(param, db) {
|
|
89
|
+
return true;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 什么时候(时间)
|
|
94
|
+
* @param {Object} param 状态参数
|
|
95
|
+
* @param {Object} db 数据管理器
|
|
96
|
+
* @return {Boolean} 条件满足返回true, 否则返回false
|
|
97
|
+
*/
|
|
98
|
+
Drive.prototype.when = async function(param, db) {
|
|
99
|
+
return true;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 什么地方(地点)
|
|
104
|
+
* @param {Object} param 状态参数
|
|
105
|
+
* @param {Object} db 数据管理器
|
|
106
|
+
* @return {Boolean} 条件满足返回true, 否则返回false
|
|
107
|
+
*/
|
|
108
|
+
Drive.prototype.where = async function(param, db) {
|
|
109
|
+
return true;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* 什么人(人物)
|
|
114
|
+
* @param {Object} param 状态参数
|
|
115
|
+
* @param {Object} db 数据管理器
|
|
116
|
+
* @return {Boolean} 条件满足返回true, 否则返回false
|
|
117
|
+
*/
|
|
118
|
+
Drive.prototype.who = async function(param, db) {
|
|
119
|
+
return true;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 做什么(事件)
|
|
124
|
+
* @param {Object} param 状态参数
|
|
125
|
+
* @param {Object} db 数据管理器
|
|
126
|
+
* @return {Boolean} 条件满足返回true, 否则返回false
|
|
127
|
+
*/
|
|
128
|
+
Drive.prototype.what = async function(param, db) {
|
|
129
|
+
return true;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 怎么做(方法), 对行为做决策
|
|
134
|
+
* @param {Object} param 状态参数
|
|
135
|
+
* @param {Object} db 数据管理器
|
|
136
|
+
* @return {String} 返回执行函数
|
|
137
|
+
*/
|
|
138
|
+
Drive.prototype.how = async function(param, db) {
|
|
139
|
+
var obj = {
|
|
140
|
+
name: "main"
|
|
141
|
+
};
|
|
142
|
+
var cg = this.config;
|
|
143
|
+
var lt = cg.condition.how;
|
|
144
|
+
var content = param.content;
|
|
145
|
+
var len = lt.length;
|
|
146
|
+
for (var i = 0; i < len; i++) {
|
|
147
|
+
var o = lt[i];
|
|
148
|
+
var str = o.not_match;
|
|
149
|
+
if (str) {
|
|
150
|
+
if (str.startWith('/')) {
|
|
151
|
+
try {
|
|
152
|
+
var rx = eval(str);
|
|
153
|
+
if (rx.test(content) === false) {
|
|
154
|
+
var ct = db.msg_log.content;
|
|
155
|
+
if (ct) {
|
|
156
|
+
var mh = ct.match(rx);
|
|
157
|
+
var txt = "";
|
|
158
|
+
if (mh) {
|
|
159
|
+
var value = mh[mh.length - 1];
|
|
160
|
+
var keyword = db.msg_log.keyword + "\r\n" + value;
|
|
161
|
+
db.msg_log.keyword = keyword.trim();
|
|
162
|
+
param.content = content.trim() + "\r\n" + value;
|
|
163
|
+
} else {
|
|
164
|
+
obj = o;
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
obj = o;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
db.msg_log.keyword = content.trim();
|
|
173
|
+
}
|
|
174
|
+
} catch (e) {
|
|
175
|
+
$.log.error('正则表达式错误:' + str);
|
|
176
|
+
}
|
|
177
|
+
} else if (!content.has(str)) {
|
|
178
|
+
obj = o;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
} else if (o.func_name) {
|
|
182
|
+
var func = this[o.func_name];
|
|
183
|
+
if (func) {
|
|
184
|
+
var bl = await func(param, db);
|
|
185
|
+
if (!bl) {
|
|
186
|
+
obj = o;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return obj;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* 做到什么程度(结束条件)
|
|
196
|
+
* @param {Object} param 状态参数
|
|
197
|
+
* @param {Object} ret 执行结果
|
|
198
|
+
* @param {Object} db 数据管理器
|
|
199
|
+
* @return {Boolean} 返回执行结果判断 true表示已完成一个行为周期,false为未完成,未完成则继续缓存
|
|
200
|
+
*/
|
|
201
|
+
Drive.prototype.how_much = async function(param, db, ret) {
|
|
202
|
+
if (param.content.length > 255) {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
return false;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 补全参数
|
|
210
|
+
* @param {Object} content 正文
|
|
211
|
+
* @param {Object} db 数据管理器
|
|
212
|
+
* @return {Object} 返回参数表单
|
|
213
|
+
*/
|
|
214
|
+
Drive.prototype.supply = async function(content, db) {
|
|
215
|
+
var form = {};
|
|
216
|
+
if (db.msg_log.form) {
|
|
217
|
+
form = db.msg_log.form.toJson();
|
|
218
|
+
} else {
|
|
219
|
+
var ct = content + "";
|
|
220
|
+
var cg = this.config;
|
|
221
|
+
var post = cg.post;
|
|
222
|
+
var arr = [];
|
|
223
|
+
arr.addList(post.body);
|
|
224
|
+
arr.addList(post.body_required);
|
|
225
|
+
var list = cg.list;
|
|
226
|
+
for (var i = 0; i < arr.length; i++) {
|
|
227
|
+
var k = arr[i];
|
|
228
|
+
var o = list[k];
|
|
229
|
+
if (o.string) {
|
|
230
|
+
var str = o.string.regex;
|
|
231
|
+
if (str) {
|
|
232
|
+
try {
|
|
233
|
+
var rx = eval(str);
|
|
234
|
+
var mh = str.match(rx);
|
|
235
|
+
if (mh) {
|
|
236
|
+
var value = mh[0];
|
|
237
|
+
form[k] = value;
|
|
238
|
+
ct = ct.replace(value, '');
|
|
239
|
+
}
|
|
240
|
+
} catch (e) {
|
|
241
|
+
$.log.error('正则表达式错误:' + str);
|
|
242
|
+
}
|
|
243
|
+
} else {
|
|
244
|
+
form[k] = "";
|
|
245
|
+
}
|
|
246
|
+
} else {
|
|
247
|
+
form[k] = 0;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return form;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* 检验条件是否满足
|
|
256
|
+
* @param {Object} form 表单
|
|
257
|
+
* @param {Object} db 数据管理器
|
|
258
|
+
* @param {Boolean} first 是否第一次验证,第一次验证时会将错误参数清空,提示填写。而非第一次验证则提示错误重填
|
|
259
|
+
* @return {String} 验证失败返回错误提示
|
|
260
|
+
*/
|
|
261
|
+
Drive.prototype.check = async function(form, db, first) {
|
|
262
|
+
var func = new Param();
|
|
263
|
+
db.msg_log.form = JSON.stringify(form);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* 执行
|
|
268
|
+
* @param {Object} param 状态参数
|
|
269
|
+
* @param {Object} db 数据管理器
|
|
270
|
+
* @return {Object} 返回执行结果
|
|
271
|
+
*/
|
|
272
|
+
Drive.prototype.main = async function(param, db) {
|
|
273
|
+
return "你好";
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* 执行
|
|
278
|
+
* @param {Object} param 状态参数
|
|
279
|
+
* @param {Object} db 数据管理器
|
|
280
|
+
* @return {Object} 返回执行结果
|
|
281
|
+
*/
|
|
282
|
+
Drive.prototype.run = async function(param, db) {
|
|
283
|
+
var content = await this.extract(param.content);
|
|
284
|
+
content = await this.filter(content);
|
|
285
|
+
param.content = content;
|
|
286
|
+
|
|
287
|
+
var bl = true;
|
|
288
|
+
bl = await this.what(param, db);
|
|
289
|
+
if (!bl) {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
bl = await this.who(param, db);
|
|
293
|
+
if (!bl) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
bl = await this.where(param, db);
|
|
297
|
+
if (!bl) {
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
bl = await this.when(param, db);
|
|
301
|
+
if (!bl) {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
var ret = "";
|
|
305
|
+
var o = await this.how(param, db);
|
|
306
|
+
if (o.question) {
|
|
307
|
+
ret = o.question;
|
|
308
|
+
} else if (o.name) {
|
|
309
|
+
var func = this[o.name];
|
|
310
|
+
if (func) {
|
|
311
|
+
ret = await func(param, db);
|
|
312
|
+
if (ret) {
|
|
313
|
+
bl = this.how_much(param, db, ret);
|
|
314
|
+
// if (bl && db.msg_log) {
|
|
315
|
+
// db.msg_log.end = 1;
|
|
316
|
+
// }
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return ret;
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* 校验是否匹配指令
|
|
325
|
+
* @param {Object} content 请求的正文
|
|
326
|
+
* @param {Object} db 数据管理器
|
|
327
|
+
* @return {Boolean} 匹配返回true,不匹配返回false
|
|
328
|
+
*/
|
|
329
|
+
Drive.prototype.match = function(content, db) {
|
|
330
|
+
var cg = this.config;
|
|
331
|
+
var lt = cg.match;
|
|
332
|
+
var bl = false;
|
|
333
|
+
for (var i = 0, o; o = lt[i++];) {
|
|
334
|
+
if (content.matchs(o)) {
|
|
335
|
+
bl = true;
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return bl;
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* 校验是否不含关键词
|
|
344
|
+
* @param {Object} content 请求的正文
|
|
345
|
+
* @param {Object} db 数据管理器
|
|
346
|
+
* @return {Boolean} 不含返回true,含有返回false
|
|
347
|
+
*/
|
|
348
|
+
Drive.prototype.not_match = function(content, db) {
|
|
349
|
+
var cg = this.config;
|
|
350
|
+
var lt = cg.not_match;
|
|
351
|
+
var bl = true;
|
|
352
|
+
for (var i = 0, o; o = lt[i++];) {
|
|
353
|
+
if (content.matchs(o)) {
|
|
354
|
+
bl = false;
|
|
355
|
+
break;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return bl;
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* 过滤正文
|
|
363
|
+
* @param {String} content 正文
|
|
364
|
+
* @param {Object} db 数据管理器
|
|
365
|
+
* @return {Object} 返回过滤后的参数
|
|
366
|
+
*/
|
|
367
|
+
Drive.prototype.filter = async function(content, db) {
|
|
368
|
+
var cg = this.config;
|
|
369
|
+
var lt = cg.filter;
|
|
370
|
+
var bl = false;
|
|
371
|
+
for (var i = 0, str; str = lt[i++];) {
|
|
372
|
+
if (str.startWith('/')) {
|
|
373
|
+
try {
|
|
374
|
+
var rx = eval(str);
|
|
375
|
+
content = content.replace(rx, '');
|
|
376
|
+
} catch (e) {
|
|
377
|
+
$.log.error('正则表达式错误:' + str);
|
|
378
|
+
}
|
|
379
|
+
} else {
|
|
380
|
+
content = content.replace(str, '');
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return content;
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* 抽取正文
|
|
388
|
+
* @param {String} content 正文
|
|
389
|
+
* @param {Object} db 数据管理器
|
|
390
|
+
* @return {Object} 返回过滤后的参数
|
|
391
|
+
*/
|
|
392
|
+
Drive.prototype.extract = async function(content, db) {
|
|
393
|
+
var cg = this.config;
|
|
394
|
+
var lt = cg.extract;
|
|
395
|
+
var bl = false;
|
|
396
|
+
for (var i = 0, str; str = lt[i++];) {
|
|
397
|
+
if (str.startWith('/')) {
|
|
398
|
+
try {
|
|
399
|
+
var rx = eval(str);
|
|
400
|
+
var mh = content.match(rx);
|
|
401
|
+
var ct = "";
|
|
402
|
+
if (mh) {
|
|
403
|
+
for (var n = 0; n < mh.length; n++) {
|
|
404
|
+
ct += "\r\n" + mh[0];
|
|
405
|
+
}
|
|
406
|
+
content = ct;
|
|
407
|
+
}
|
|
408
|
+
} catch (e) {
|
|
409
|
+
$.log.error('正则表达式错误:' + str);
|
|
410
|
+
}
|
|
411
|
+
} else if (str.startWith('*')) {
|
|
412
|
+
content = content.left(str.replace('*', ''), true)
|
|
413
|
+
} else if (str.endWith('*')) {
|
|
414
|
+
content = content.right(str.replace('*', ''), true)
|
|
415
|
+
} else if (str.indexOf('*') !== -1) {
|
|
416
|
+
var arr = str.split('*');
|
|
417
|
+
content = content.between(arr[0], arr[1], true);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return content;
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
module.exports = Drive;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_os",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.7",
|
|
4
4
|
"description": "这是超级美眉服务端框架,用于快速构建应用程序。",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -45,13 +45,14 @@
|
|
|
45
45
|
"mm_mongodb": "^1.4.1",
|
|
46
46
|
"mm_mqtt": "^1.0.5",
|
|
47
47
|
"mm_mysql": "^1.7.9",
|
|
48
|
+
"mm_os": "^2.0.6",
|
|
48
49
|
"mm_redis": "^1.4.0",
|
|
49
50
|
"mm_ret": "^1.3.8",
|
|
50
51
|
"mm_session": "^1.4.5",
|
|
51
52
|
"mm_statics": "^1.4.1",
|
|
52
|
-
"mm_tpl": "^2.3.
|
|
53
|
+
"mm_tpl": "^2.3.8",
|
|
53
54
|
"mm_xml": "^1.1.4",
|
|
54
55
|
"mosca": "^2.8.3",
|
|
55
|
-
"mqtt": "^5.
|
|
56
|
+
"mqtt": "^5.9.1"
|
|
56
57
|
}
|
|
57
58
|
}
|