mm_os 2.9.2 → 2.9.4
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/config.tpl.json +44 -19
- package/core/com/cmd/drive.js +149 -190
- package/core/com/cmd/index.js +227 -102
- package/core/com/mqtt/index.js +4 -4
- package/core/com/task/drive.js +7 -2
- package/core/com/task/index.js +2 -0
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "指令标题",
|
|
6
6
|
// 描述, 用于介绍该指令的作用
|
|
7
7
|
"description": "暂无描述",
|
|
8
|
-
// 时态, 分before之前、main主要、after
|
|
8
|
+
// 时态, 分before之前、check验证、main主要、render渲染、after之后五个时态
|
|
9
9
|
"tense": "main",
|
|
10
10
|
// 执行顺序, 数值越小的指令越优先执行
|
|
11
11
|
"sort": 1000,
|
|
@@ -15,27 +15,52 @@
|
|
|
15
15
|
"type": "",
|
|
16
16
|
// 匹配关键词组, 当聊天中出现其中一个关键词则会执行该指令
|
|
17
17
|
"match": [],
|
|
18
|
+
// 执行顺序, 数值越小的指令越优先执行
|
|
19
|
+
"sort": 1000,
|
|
20
|
+
// 结束会话 当值为1时,指令触发并返回了内容后不再执行其他指令。为0时,指令触发仍继续执行其他指令
|
|
21
|
+
"end": 1,
|
|
22
|
+
// 指令分组, 可以将特有的指令分一个组, 方便用户查询
|
|
23
|
+
"group": "default",
|
|
24
|
+
// 指令分类, 例如: 查询服务类query、管理类admin、游戏类game
|
|
25
|
+
"type": "",
|
|
26
|
+
// 匹配关键词组, 当聊天中出现其中一个关键词则会执行该指令
|
|
27
|
+
"match": [],
|
|
18
28
|
// 不包含关键词, 如果匹配后, 出现不应该包含的关键词, 则不会执行指令
|
|
19
29
|
"not": [],
|
|
20
30
|
// 移除关键词, 如果聊天中含这些词, 将会被剔除在执行指令
|
|
21
31
|
"remove": [],
|
|
22
32
|
// 提取特定词, 如果聊天中含有特定词, 会被提取出来再执行指令
|
|
23
33
|
"extract": [],
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
// 阶段
|
|
35
|
+
"stage": [
|
|
36
|
+
// 第一阶段
|
|
37
|
+
{
|
|
38
|
+
// 方式 fill为补全,会将本次消息加入到msg.form[name]中
|
|
39
|
+
"mode": "fill",
|
|
40
|
+
/* 参数, 用于执行指令行为前抽取关键词进行验证, 然后再执行指令 */
|
|
41
|
+
"param": [{
|
|
42
|
+
// 参数名称, 用于提交数据时
|
|
43
|
+
"name": "number",
|
|
44
|
+
// 参数标题, 用于提示用户什么参数错误
|
|
45
|
+
"title": "快递单号",
|
|
46
|
+
// 抽验顺序, 越小的越优先验证, 并且抽取后排列在前
|
|
47
|
+
"sort": 10,
|
|
48
|
+
// 抽取/校验格式, 如果格式不符合, 则表示验证未通过,提示用户
|
|
49
|
+
"format": "/[a-zA-Z0-9_]+/g",
|
|
50
|
+
// 缺少参数提示, 如果不包含该参数, 则做出的提示
|
|
51
|
+
"not_tip": "快递单号多少?",
|
|
52
|
+
// 错误提示, 提示用户补充参数时, 补充参数错误时做出的提示
|
|
53
|
+
"error_tip": "快递单号不正确",
|
|
54
|
+
// 校验/抽取的函数名, 通过函数的方式抽取/校验参数
|
|
55
|
+
"func_name": ""
|
|
56
|
+
}]
|
|
57
|
+
},
|
|
58
|
+
// 第二阶段
|
|
59
|
+
{
|
|
60
|
+
// 方式 update为更新,会将本次消息替换掉msg.form[name]的值
|
|
61
|
+
"mode": "update",
|
|
62
|
+
// 验证参数集
|
|
63
|
+
"param": []
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
package/core/com/cmd/drive.js
CHANGED
|
@@ -34,6 +34,8 @@ class Drive extends Item {
|
|
|
34
34
|
"tense": "main",
|
|
35
35
|
// 加载顺序,数字越大越后面加载
|
|
36
36
|
"sort": 1000,
|
|
37
|
+
// 结束会话 当值为1时,指令触发并返回了内容后不再执行其他指令。为0时,指令触发仍继续执行其他指令
|
|
38
|
+
"end": 1,
|
|
37
39
|
// 分组
|
|
38
40
|
"group": "default",
|
|
39
41
|
// 类型: query便民查询,action执行,game游戏,orther其他,为空表示未分类
|
|
@@ -46,44 +48,47 @@ class Drive extends Item {
|
|
|
46
48
|
"remove": [],
|
|
47
49
|
// 摘取
|
|
48
50
|
"extract": [],
|
|
49
|
-
//
|
|
50
|
-
"
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
51
|
+
// 阶段
|
|
52
|
+
"stage": [
|
|
53
|
+
// 第一阶段
|
|
54
|
+
{
|
|
55
|
+
// 方式
|
|
56
|
+
"mode": "fill",
|
|
57
|
+
// 验证参数集
|
|
58
|
+
"param": [
|
|
59
|
+
// {
|
|
60
|
+
// // 参数名
|
|
61
|
+
// "name": "name",
|
|
62
|
+
// // 参数介绍名
|
|
63
|
+
// "title": "名称",
|
|
64
|
+
// // 参数格式
|
|
65
|
+
// "format": "",
|
|
66
|
+
// // 缺少参数提示语,传键值对,例如:{ number: "快递单号多少?" }
|
|
67
|
+
// "not_tip": "",
|
|
68
|
+
// // 错误提示
|
|
69
|
+
// "error_tip": "",
|
|
70
|
+
// // 监听语法
|
|
71
|
+
// "listen": "",
|
|
72
|
+
// // 校验函数明
|
|
73
|
+
// "func_name": ""
|
|
74
|
+
// },
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
// 第二阶段
|
|
78
|
+
{
|
|
79
|
+
// 方式
|
|
80
|
+
"mode": "update",
|
|
81
|
+
// 验证参数集
|
|
82
|
+
"param": []
|
|
83
|
+
},
|
|
84
|
+
// 第三阶段
|
|
85
|
+
{
|
|
86
|
+
// 方式
|
|
87
|
+
"mode": "fill",
|
|
88
|
+
// 验证参数集
|
|
89
|
+
"param": []
|
|
90
|
+
}
|
|
91
|
+
]
|
|
87
92
|
}
|
|
88
93
|
}
|
|
89
94
|
};
|
|
@@ -113,7 +118,6 @@ Drive.prototype.model = function() {
|
|
|
113
118
|
};
|
|
114
119
|
};
|
|
115
120
|
|
|
116
|
-
|
|
117
121
|
/**
|
|
118
122
|
* 校验是否匹配指令
|
|
119
123
|
* @param {Object} content 请求的正文
|
|
@@ -121,19 +125,19 @@ Drive.prototype.model = function() {
|
|
|
121
125
|
* @return {Boolean} 匹配返回true,不匹配返回false
|
|
122
126
|
*/
|
|
123
127
|
Drive.prototype.match = function(content, db) {
|
|
124
|
-
var
|
|
128
|
+
var word;
|
|
125
129
|
var arr = this.config.match;
|
|
126
130
|
for (var i = 0; i < arr.length; i++) {
|
|
127
131
|
var format = arr[i];
|
|
128
|
-
|
|
129
|
-
|
|
132
|
+
var str = content.matchs(format);
|
|
133
|
+
if (str) {
|
|
134
|
+
word = str;
|
|
130
135
|
break;
|
|
131
136
|
}
|
|
132
137
|
}
|
|
133
|
-
return
|
|
138
|
+
return word;
|
|
134
139
|
};
|
|
135
140
|
|
|
136
|
-
|
|
137
141
|
/**
|
|
138
142
|
* 校验是否不含关键词
|
|
139
143
|
* @param {Object} content 请求的正文
|
|
@@ -155,40 +159,44 @@ Drive.prototype.not_match = function(content, db) {
|
|
|
155
159
|
|
|
156
160
|
|
|
157
161
|
/**
|
|
158
|
-
*
|
|
162
|
+
* 抽取主要内容
|
|
159
163
|
* @param {String} content 正文
|
|
160
164
|
* @param {Object} db 数据管理器
|
|
161
165
|
* @return {Object} 返回过滤后的参数
|
|
162
166
|
*/
|
|
163
167
|
Drive.prototype.extract = async function(content, db) {
|
|
164
168
|
var list = this.config.extract;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
169
|
+
if (!list.length) {
|
|
170
|
+
return content
|
|
171
|
+
}
|
|
172
|
+
for (var i = 0; i < list.length; i++) {
|
|
168
173
|
var format = list[i];
|
|
169
|
-
var
|
|
170
|
-
if (
|
|
171
|
-
|
|
174
|
+
var ret = content.matchs(format);
|
|
175
|
+
if (ret) {
|
|
176
|
+
content = ret;
|
|
172
177
|
}
|
|
173
178
|
}
|
|
174
|
-
return
|
|
179
|
+
return content;
|
|
175
180
|
};
|
|
176
181
|
|
|
177
|
-
|
|
178
182
|
/**
|
|
179
183
|
* 移除关键词
|
|
180
|
-
* @param {
|
|
184
|
+
* @param {Array} content 内容
|
|
181
185
|
* @param {Object} db 数据管理器
|
|
182
186
|
* @return {Object} 返回过滤后的参数
|
|
183
187
|
*/
|
|
184
188
|
Drive.prototype.remove = async function(content, db) {
|
|
185
189
|
var list = this.config.remove;
|
|
186
|
-
var
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
for (var i = 0; i < list.length; i++) {
|
|
191
|
+
var format = list[i];
|
|
192
|
+
if (format.indexOf("/") === 0) {
|
|
193
|
+
var fmt = format.replace(/\//g, '\\/').replace(/\r/g, '\\r').replace(/\n/g, '\\n')
|
|
194
|
+
.replace(/\*/g, '.*').replace(
|
|
195
|
+
/\{[a-zA-Z\u4e00-\u9fa5_]+\}/g, '[\\s\\S]*');
|
|
196
|
+
var rx = eval(fmt);
|
|
197
|
+
content = content.replace(rx, "").trim();
|
|
198
|
+
} else {
|
|
199
|
+
content = content.replace(format, "").trim();
|
|
192
200
|
}
|
|
193
201
|
}
|
|
194
202
|
return content;
|
|
@@ -214,14 +222,16 @@ Drive.prototype.view_tip = async function(msg, db, tip) {
|
|
|
214
222
|
*/
|
|
215
223
|
Drive.prototype.check = async function(msg, db) {
|
|
216
224
|
// 校验是否匹配指令
|
|
217
|
-
var
|
|
218
|
-
if (
|
|
219
|
-
bl = await this.not_match(msg.content, db);
|
|
225
|
+
var word = await this.match(msg.content, db);
|
|
226
|
+
if (word) {
|
|
227
|
+
var bl = await this.not_match(msg.content, db);
|
|
228
|
+
if (!bl) {
|
|
229
|
+
return
|
|
230
|
+
}
|
|
220
231
|
}
|
|
221
|
-
return
|
|
232
|
+
return word;
|
|
222
233
|
};
|
|
223
234
|
|
|
224
|
-
|
|
225
235
|
/**
|
|
226
236
|
* 2. 过滤阶段, 抽出主要的内容
|
|
227
237
|
* @param {Object} msg 消息上下文
|
|
@@ -230,7 +240,11 @@ Drive.prototype.check = async function(msg, db) {
|
|
|
230
240
|
*/
|
|
231
241
|
Drive.prototype.filter = async function(msg, db) {
|
|
232
242
|
var content = await this.extract(msg.content);
|
|
233
|
-
|
|
243
|
+
content = await this.remove(content);
|
|
244
|
+
if (content) {
|
|
245
|
+
msg.keyword = content;
|
|
246
|
+
}
|
|
247
|
+
return content;
|
|
234
248
|
};
|
|
235
249
|
|
|
236
250
|
/**
|
|
@@ -248,63 +262,45 @@ Drive.prototype.fill = async function(msg, db, stage) {
|
|
|
248
262
|
if (!list || list.length === 0) {
|
|
249
263
|
return "";
|
|
250
264
|
}
|
|
251
|
-
var form = {};
|
|
252
265
|
var keyword = "";
|
|
253
|
-
|
|
254
|
-
var has_fill = false;
|
|
266
|
+
var tip = "";
|
|
255
267
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
if (
|
|
259
|
-
form =
|
|
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
|
-
}
|
|
268
|
+
// 获取已有参数
|
|
269
|
+
var form = {};
|
|
270
|
+
if (msg.form) {
|
|
271
|
+
form = msg.form.toJson();
|
|
279
272
|
}
|
|
280
|
-
|
|
281
|
-
var
|
|
282
|
-
|
|
273
|
+
// 补全内容
|
|
274
|
+
var ct = msg.content_last || "";
|
|
275
|
+
var len = list.length;
|
|
276
|
+
for (var i = 0; i < len; i++) {
|
|
277
|
+
var o = list[i];
|
|
278
|
+
var k = o.name;
|
|
283
279
|
if (!form[k]) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
has_fill = true;
|
|
293
|
-
} else {
|
|
294
|
-
msg.form = form;
|
|
295
|
-
if (ct && o.error_tip && has_fill == false) {
|
|
280
|
+
if (ct) {
|
|
281
|
+
var value = ct;
|
|
282
|
+
if (o.format) {
|
|
283
|
+
value = value.matchs(o.format);
|
|
284
|
+
}
|
|
285
|
+
if (value) {
|
|
286
|
+
form[k] = value;
|
|
287
|
+
} else if (o.error_tip) {
|
|
296
288
|
tip = await this.view_tip(msg, db, o.error_tip);
|
|
289
|
+
break;
|
|
297
290
|
} else if (o.not_tip) {
|
|
298
291
|
tip = await this.view_tip(msg, db, o.not_tip);
|
|
292
|
+
break;
|
|
299
293
|
}
|
|
294
|
+
ct = "";
|
|
295
|
+
} else {
|
|
296
|
+
keyword = k;
|
|
297
|
+
tip = await this.view_tip(msg, db, o.not_tip);
|
|
300
298
|
break;
|
|
301
299
|
}
|
|
302
300
|
}
|
|
303
301
|
}
|
|
304
|
-
|
|
305
|
-
db.
|
|
306
|
-
db.msg.form = JSON.stringify(form);
|
|
307
|
-
msg.form = form;
|
|
302
|
+
msg.form = JSON.stringify(form);
|
|
303
|
+
db.form = form;
|
|
308
304
|
return tip;
|
|
309
305
|
};
|
|
310
306
|
|
|
@@ -316,17 +312,24 @@ Drive.prototype.fill = async function(msg, db, stage) {
|
|
|
316
312
|
* @return {Object} 返回参数表单
|
|
317
313
|
*/
|
|
318
314
|
Drive.prototype.update = async function(msg, db, stage) {
|
|
319
|
-
if (!stage
|
|
315
|
+
if (!stage) {
|
|
320
316
|
return "";
|
|
321
317
|
}
|
|
322
318
|
var list = stage.param;
|
|
323
|
-
|
|
319
|
+
if (!list || list.length === 0) {
|
|
320
|
+
return "";
|
|
321
|
+
}
|
|
324
322
|
var tip = "";
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
var form =
|
|
328
|
-
|
|
329
|
-
|
|
323
|
+
|
|
324
|
+
// 获取已有参数
|
|
325
|
+
var form = {};
|
|
326
|
+
if (msg.form) {
|
|
327
|
+
form = msg.form.toJson();
|
|
328
|
+
}
|
|
329
|
+
// 补全内容
|
|
330
|
+
var ct = msg.content_last || "";
|
|
331
|
+
var form = msg.form.toJson();
|
|
332
|
+
for (var i = 0; i < list.length; i++) {
|
|
330
333
|
var o = list[i];
|
|
331
334
|
var k = o.name;
|
|
332
335
|
if (form[k]) {
|
|
@@ -337,9 +340,9 @@ Drive.prototype.update = async function(msg, db, stage) {
|
|
|
337
340
|
} else {
|
|
338
341
|
tip = "那" + value.replace(value.matchs("{不对}"), '是?');
|
|
339
342
|
}
|
|
340
|
-
|
|
343
|
+
msg.note = k;
|
|
341
344
|
break;
|
|
342
|
-
} else if (
|
|
345
|
+
} else if (msg.note == k && o.format) {
|
|
343
346
|
value = ct.matchs(o.format);
|
|
344
347
|
if (value) {
|
|
345
348
|
form[k] = value;
|
|
@@ -349,9 +352,8 @@ Drive.prototype.update = async function(msg, db, stage) {
|
|
|
349
352
|
}
|
|
350
353
|
}
|
|
351
354
|
}
|
|
352
|
-
|
|
353
|
-
db.
|
|
354
|
-
msg.form = form;
|
|
355
|
+
msg.form = JSON.stringify(form);
|
|
356
|
+
db.form = form;
|
|
355
357
|
return tip;
|
|
356
358
|
};
|
|
357
359
|
|
|
@@ -380,62 +382,11 @@ Drive.prototype.end = async function(msg, db, ret) {
|
|
|
380
382
|
} else {
|
|
381
383
|
txt = ret;
|
|
382
384
|
}
|
|
383
|
-
if (
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
}
|
|
387
|
-
return ret;
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* 下达指令
|
|
392
|
-
* @param {Number} state 状态 0为不可以,1为可用
|
|
393
|
-
* @param {Array} ...params 参数集合
|
|
394
|
-
*/
|
|
395
|
-
Drive.prototype.cmd = function(state, ...params) {
|
|
396
|
-
return null;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* 执行但不记录指令
|
|
401
|
-
* @param {Object} msg 消息上下文
|
|
402
|
-
* @param {Object} db 数据管理器
|
|
403
|
-
* @return {Object} 返回执行结果
|
|
404
|
-
*/
|
|
405
|
-
Drive.prototype.run_cmd = async function(msg, db) {
|
|
406
|
-
var ret;
|
|
407
|
-
try {
|
|
408
|
-
// 第一步, 验证阶段
|
|
409
|
-
var bl = await this.check(msg, db);
|
|
410
|
-
if (bl) {
|
|
411
|
-
ret = await this.run(msg, db);
|
|
412
|
-
}
|
|
413
|
-
} catch (err) {
|
|
414
|
-
$.log.error("指令错误", this.config.name, err);
|
|
415
|
-
}
|
|
416
|
-
return ret;
|
|
417
|
-
};
|
|
418
|
-
|
|
419
|
-
/**
|
|
420
|
-
* 执行
|
|
421
|
-
* @param {Object} msg 消息上下文
|
|
422
|
-
* @param {Object} db 数据管理器
|
|
423
|
-
* @return {Object} 返回执行结果
|
|
424
|
-
*/
|
|
425
|
-
Drive.prototype.run_first = async function(msg, db) {
|
|
426
|
-
var ret;
|
|
427
|
-
try {
|
|
428
|
-
// 第一步, 验证阶段
|
|
429
|
-
var bl = await this.check(msg, db);
|
|
430
|
-
if (bl) {
|
|
431
|
-
ret = await this.run(msg, db);
|
|
432
|
-
if (ret) {
|
|
433
|
-
// 如果匹配指令则将该消息定义为使用该指令
|
|
434
|
-
db.msg.cmd = this.config.name;
|
|
385
|
+
if (this.config.tense == "main") {
|
|
386
|
+
if (txt.indexOf('?') === -1 && txt.indexOf('?') === -1) {
|
|
387
|
+
msg.end = 0;
|
|
435
388
|
}
|
|
436
389
|
}
|
|
437
|
-
} catch (err) {
|
|
438
|
-
$.log.error("指令错误", this.config.name, err);
|
|
439
390
|
}
|
|
440
391
|
return ret;
|
|
441
392
|
};
|
|
@@ -470,18 +421,27 @@ Drive.prototype.run_after = async function(msg, db, ret) {
|
|
|
470
421
|
Drive.prototype.run = async function(msg, db) {
|
|
471
422
|
var ret;
|
|
472
423
|
try {
|
|
424
|
+
// 第一步, 验证阶段
|
|
425
|
+
var match = await this.check(msg, db);
|
|
426
|
+
if (!match) {
|
|
427
|
+
return
|
|
428
|
+
}
|
|
429
|
+
msg.match = match.substring(0, 255);
|
|
473
430
|
// 第二步, 过滤阶段
|
|
474
|
-
|
|
431
|
+
await this.filter(msg, db);
|
|
475
432
|
|
|
476
433
|
// 执行前
|
|
477
434
|
ret = await this.run_before(msg, db);
|
|
478
435
|
if (!ret) {
|
|
479
436
|
// 第三步, 信息补全或更新阶段
|
|
480
|
-
var
|
|
481
|
-
if (stage) {
|
|
482
|
-
var
|
|
483
|
-
if (
|
|
484
|
-
|
|
437
|
+
var stages = this.config.stage;
|
|
438
|
+
if (stages.length >= msg.stage) {
|
|
439
|
+
var stage = stages[msg.stage - 1];
|
|
440
|
+
if (stage) {
|
|
441
|
+
var mode = stage.mode ? stage.mode : "fill";
|
|
442
|
+
if (this[mode]) {
|
|
443
|
+
ret = await this[mode](msg, db, stage);
|
|
444
|
+
}
|
|
485
445
|
}
|
|
486
446
|
}
|
|
487
447
|
|
|
@@ -509,14 +469,13 @@ Drive.prototype.run = async function(msg, db) {
|
|
|
509
469
|
*/
|
|
510
470
|
Drive.prototype.view = function(msg, db) {
|
|
511
471
|
var ret = "";
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
var stage = this.config.
|
|
515
|
-
if (stage) {
|
|
516
|
-
var list = stage.param;
|
|
472
|
+
if (msg.form) {
|
|
473
|
+
var json = msg.form.toJson();
|
|
474
|
+
var stage = this.config.stage;
|
|
475
|
+
if (stage && stage.length >= msg.stage) {
|
|
476
|
+
var list = stage[msg.stage - 1].param;
|
|
517
477
|
if (list) {
|
|
518
|
-
var
|
|
519
|
-
for (var i = 0; i < len; i++) {
|
|
478
|
+
for (var i = 0; i < list.length; i++) {
|
|
520
479
|
var o = list[i];
|
|
521
480
|
var value = json[o.name];
|
|
522
481
|
if (value) {
|
package/core/com/cmd/index.js
CHANGED
|
@@ -19,128 +19,245 @@ class Cmd extends Index {
|
|
|
19
19
|
this.type = "cmd";
|
|
20
20
|
this.title = title;
|
|
21
21
|
this.list_before = [];
|
|
22
|
+
this.list_check = [];
|
|
22
23
|
this.list_main = [];
|
|
24
|
+
this.list_render = [];
|
|
23
25
|
this.list_after = [];
|
|
24
26
|
// 默认启用热更新
|
|
25
27
|
this.mode = 3;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 配置参数
|
|
31
|
+
*/
|
|
32
|
+
this.config = {
|
|
33
|
+
table: "wechat_message",
|
|
34
|
+
key: "message_id",
|
|
35
|
+
// 聊天间隔时长,单位:秒,600秒为10分钟
|
|
36
|
+
interval: 600
|
|
37
|
+
};
|
|
26
38
|
}
|
|
27
39
|
}
|
|
28
40
|
|
|
41
|
+
/**
|
|
42
|
+
* 设置配置
|
|
43
|
+
* @param {Object} config 配置参数
|
|
44
|
+
*/
|
|
45
|
+
Cmd.prototype.set_config = function(config) {
|
|
46
|
+
Object.assign(this.config, config);
|
|
47
|
+
}
|
|
48
|
+
|
|
29
49
|
/**
|
|
30
50
|
* 执行指令
|
|
31
|
-
* @param {Object} msg
|
|
32
|
-
* @param {Object} db
|
|
33
|
-
* @param {
|
|
34
|
-
* @return {Object
|
|
51
|
+
* @param {Object} msg 消息对象
|
|
52
|
+
* @param {Object} db 数据库对象
|
|
53
|
+
* @param {Object} list 数据库对象
|
|
54
|
+
* @return {Object} 返回值
|
|
35
55
|
*/
|
|
36
|
-
Cmd.prototype.
|
|
56
|
+
Cmd.prototype.run_cmd_sub = async function(msg, db, tense = 'main') {
|
|
57
|
+
var list = this['list_' + tense];
|
|
58
|
+
if (!list) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
37
61
|
var ret;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// 判断是否启用数据库存储消息,如果表名为空则不存储消息
|
|
48
|
-
if (table) {
|
|
49
|
-
db.table = table;
|
|
50
|
-
db.key = "message_id";
|
|
51
|
-
var query = {
|
|
52
|
-
from_user: msg.from_user,
|
|
53
|
-
to_user: msg.to_user,
|
|
54
|
-
group: msg.group,
|
|
55
|
-
type: msg.type,
|
|
56
|
-
end: 0
|
|
57
|
-
};
|
|
58
|
-
// 获取当前未结束的会话记录
|
|
59
|
-
var msg_log = await db.getObj(query);
|
|
60
|
-
// 如果不存在未结束会话,则创建新会话记录
|
|
61
|
-
if (!msg_log) {
|
|
62
|
-
var bl = await db.add(msg);
|
|
63
|
-
if (bl) {
|
|
64
|
-
msg_log = await db.getObj(query);
|
|
65
|
-
if (msg_log) {
|
|
66
|
-
msg_log.time_create = new Date().toStr('yyyy-MM-dd hh:mm:ss');
|
|
67
|
-
}
|
|
68
|
-
} else {
|
|
69
|
-
$.log.error('添加微信消息到wechat_message表失败!', msg_log);
|
|
70
|
-
return null;
|
|
62
|
+
for (var i = 0, o; o = list[i++];) {
|
|
63
|
+
if (o.config.state === 1) {
|
|
64
|
+
ret = await o.run(msg, db);
|
|
65
|
+
if (ret) {
|
|
66
|
+
db.ret = ret;
|
|
67
|
+
// 如果匹配指令则将该消息定义为使用该指令
|
|
68
|
+
msg.cmd = o.config.name;
|
|
69
|
+
if (o.config.end) {
|
|
70
|
+
break;
|
|
71
71
|
}
|
|
72
|
-
} else if (msg_log.content_last !== msg.content) {
|
|
73
|
-
// 判断是否重复会话内容,如果未重复则添加新内容
|
|
74
|
-
msg_log.content += '\r\n' + msg.content;
|
|
75
72
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
for (var i = 0, o; o = lt[i++];) {
|
|
81
|
-
if (o.config.state === 1) {
|
|
82
|
-
ret = await o.run_cmd(msg, db);
|
|
83
|
-
if (ret) {
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
if (!ret) {
|
|
89
|
-
// 判断会话记录是否锁定了指令, 如果存在则继续执行该指令程序
|
|
90
|
-
if (msg_log.cmd) {
|
|
91
|
-
// 检索指令驱动是否存在
|
|
92
|
-
var drive = this.list.getObj({
|
|
93
|
-
config: {
|
|
94
|
-
name: msg_log.cmd
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
if (drive) {
|
|
99
|
-
// 如果存在则执行指令
|
|
100
|
-
ret = await drive.run(msg, db);
|
|
101
|
-
} else {
|
|
102
|
-
// 如果不存在则结束会话, 并创建新会话
|
|
103
|
-
db.msg.end = 1;
|
|
104
|
-
var bl = await db.add(msg);
|
|
105
|
-
if (bl) {
|
|
106
|
-
msg_log = await db.getObj(query);
|
|
107
|
-
if (msg_log) {
|
|
108
|
-
msg_log.time_create = new Date().toStr('yyyy-MM-dd hh:mm:ss');
|
|
109
|
-
}
|
|
110
|
-
db.msg = msg_log;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return ret;
|
|
76
|
+
}
|
|
114
77
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
// // 获取当前未结束的会话记录
|
|
81
|
+
// var log = await db.getObj(query);
|
|
82
|
+
// // 如果不存在未结束会话,则创建新会话记录
|
|
83
|
+
// if (!log) {
|
|
84
|
+
// var bl = await db.add(msg);
|
|
85
|
+
// if (bl) {
|
|
86
|
+
// log = await db.getObj(query);
|
|
87
|
+
// if (log) {
|
|
88
|
+
// log.time_create = new Date().toStr('yyyy-MM-dd hh:mm:ss');
|
|
89
|
+
// }
|
|
90
|
+
// } else {
|
|
91
|
+
// $.log.error('添加微信消息到wechat_message表失败!', log);
|
|
92
|
+
// return null;
|
|
93
|
+
// }
|
|
94
|
+
// } else if (log.content_last !== msg.content) {
|
|
95
|
+
// // 判断是否重复会话内容,如果未重复则添加新内容
|
|
96
|
+
// log.content += '\r\n' + msg.content;
|
|
97
|
+
// }
|
|
98
|
+
// log.content_last = msg.content;
|
|
99
|
+
// db.msg = log;
|
|
100
|
+
|
|
101
|
+
// var lt = this.list_before;
|
|
102
|
+
// for (var i = 0, o; o = lt[i++];) {
|
|
103
|
+
// if (o.config.state === 1) {
|
|
104
|
+
// ret = await o.run_cmd(msg, db);
|
|
105
|
+
// if (ret) {
|
|
106
|
+
// break;
|
|
107
|
+
// }
|
|
108
|
+
// }
|
|
109
|
+
// }
|
|
110
|
+
// if (!ret) {
|
|
111
|
+
// // 判断会话记录是否锁定了指令, 如果存在则继续执行该指令程序
|
|
112
|
+
// if (msg_log.cmd) {
|
|
113
|
+
// // 检索指令驱动是否存在
|
|
114
|
+
// var drive = this.list.getObj({
|
|
115
|
+
// config: {
|
|
116
|
+
// name: msg_log.cmd
|
|
117
|
+
// }
|
|
118
|
+
// });
|
|
119
|
+
|
|
120
|
+
// if (drive) {
|
|
121
|
+
// // 如果存在则执行指令
|
|
122
|
+
// ret = await drive.run(msg, db);
|
|
123
|
+
// } else {
|
|
124
|
+
// // 如果不存在则结束会话, 并创建新会话
|
|
125
|
+
// db.msg.end = 1;
|
|
126
|
+
// var bl = await db.add(msg);
|
|
127
|
+
// if (bl) {
|
|
128
|
+
// msg_log = await db.getObj(query);
|
|
129
|
+
// if (msg_log) {
|
|
130
|
+
// msg_log.time_create =;
|
|
131
|
+
// }
|
|
132
|
+
// db.msg = msg_log;
|
|
133
|
+
// }
|
|
134
|
+
// }
|
|
135
|
+
// }
|
|
136
|
+
|
|
137
|
+
// if (db.msg.keyword) {
|
|
138
|
+
// // 添加消息
|
|
139
|
+
// msg.content = db.msg.keyword + "\r\n" + msg.content;
|
|
140
|
+
// }
|
|
141
|
+
// }
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* 获取上下文
|
|
145
|
+
* @param {Object} msg 消息
|
|
146
|
+
* @param {Object} db 数据管理器
|
|
147
|
+
* @return {Object}
|
|
148
|
+
*/
|
|
149
|
+
Cmd.prototype.get_context = async function(msg, db) {
|
|
150
|
+
var cg = this.config;
|
|
151
|
+
var now = new Date();
|
|
152
|
+
var query = {
|
|
153
|
+
from_user: msg.from_user,
|
|
154
|
+
to_user: msg.to_user,
|
|
155
|
+
group: msg.group,
|
|
156
|
+
type: msg.type,
|
|
157
|
+
time_create_max: now.addSeconds(cg.interval).toStr('yyyy-MM-dd hh:mm:ss')
|
|
158
|
+
};
|
|
159
|
+
var db1 = db.new(cg.table, cg.key);
|
|
160
|
+
var log = await db1.getObj(query, '`time_create` desc');
|
|
161
|
+
if(log && !log.end)
|
|
162
|
+
{
|
|
163
|
+
return log;
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* 合并消息
|
|
170
|
+
* @param {Object} msg
|
|
171
|
+
* @param {Array} log
|
|
172
|
+
*/
|
|
173
|
+
Cmd.prototype.merge_msg = function(msg, log) {
|
|
174
|
+
var m = Object.assign({}, msg, log);
|
|
175
|
+
m.content = log.content + "\r\n" + msg.content;
|
|
176
|
+
m.content_last = msg.content;
|
|
177
|
+
return m;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* 保存消息
|
|
182
|
+
* @param {Object} msg 消息
|
|
183
|
+
* @param {Object} db 数据管理器
|
|
184
|
+
*/
|
|
185
|
+
Cmd.prototype.save_msg = async function(msg, db) {
|
|
186
|
+
var cg = this.config;
|
|
187
|
+
var db1 = db.new(cg.table, cg.key);
|
|
188
|
+
var ret = db.ret;
|
|
189
|
+
if (ret) {
|
|
190
|
+
if (typeof(ret) == "object") {
|
|
191
|
+
ret = JSON.stringify(ret);
|
|
120
192
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
193
|
+
msg.result = ret;
|
|
194
|
+
}
|
|
195
|
+
if (msg[cg.key]) {
|
|
196
|
+
var qy = {};
|
|
197
|
+
qy[cg.key] = msg[cg.key];
|
|
198
|
+
return await db1.set(qy, msg);
|
|
199
|
+
} else {
|
|
200
|
+
return await db1.add(msg);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* 执行指令
|
|
206
|
+
* @param {Object} msg 消息
|
|
207
|
+
* @param {Object} db 数据管理器
|
|
208
|
+
* @return {Object|String}
|
|
209
|
+
*/
|
|
210
|
+
Cmd.prototype.run = async function(msg, db) {
|
|
211
|
+
// 判断是否含有消息和消息正文
|
|
212
|
+
if (!msg || !msg.content) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
db.table = this.config.table;
|
|
216
|
+
db.key = this.config.key;
|
|
217
|
+
msg.stage = 1;
|
|
218
|
+
|
|
219
|
+
// 1.先执行前时态指令
|
|
220
|
+
var ret = await this.run_cmd_sub(msg, db, 'before');
|
|
221
|
+
db.ret = ret;
|
|
222
|
+
// console.log("执行前", ret);
|
|
223
|
+
// 2.先执行验证时态指令,如果通过则返回空,否则返回验证失败结果。
|
|
224
|
+
var ret_check = await this.run_cmd_sub(msg, db, 'check');
|
|
225
|
+
// console.log("执行检查", ret_check);
|
|
226
|
+
if (ret_check || ret_check === "") {
|
|
227
|
+
ret = ret_check;
|
|
228
|
+
} else {
|
|
229
|
+
// 3-1.先判断本次内容是否为指令,如果是则执行指令。
|
|
230
|
+
var ret_main = await this.run_cmd_sub(msg, db, 'main');
|
|
231
|
+
console.log("执行", ret_main);
|
|
232
|
+
if (ret_main) {
|
|
233
|
+
ret = ret_main;
|
|
131
234
|
}
|
|
132
235
|
if (!ret) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
236
|
+
// 3-2.如果本次内容非指令,则先获取历史未完成的指令。拼接本次内容,并执行指令。
|
|
237
|
+
var log = await this.get_context(msg, db);
|
|
238
|
+
if (log) {
|
|
239
|
+
msg = this.merge_msg(msg, log);
|
|
240
|
+
ret_main = await this.run_cmd_sub(msg, db, 'main');
|
|
241
|
+
console.log("合并执行", ret_main);
|
|
242
|
+
if (ret_main) {
|
|
243
|
+
ret = ret_main;
|
|
140
244
|
}
|
|
141
245
|
}
|
|
142
246
|
}
|
|
143
247
|
}
|
|
248
|
+
|
|
249
|
+
// 4.执行后时态指令
|
|
250
|
+
var ret_after = await this.run_cmd_sub(msg, db, 'after');
|
|
251
|
+
if (ret_after) {
|
|
252
|
+
ret = ret_after;
|
|
253
|
+
// console.log("执行后", ret);
|
|
254
|
+
}
|
|
255
|
+
if (ret) {
|
|
256
|
+
db.ret = ret;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// 5.记录本次消息
|
|
260
|
+
await this.save_msg(msg, db);
|
|
144
261
|
return ret;
|
|
145
262
|
};
|
|
146
263
|
|
|
@@ -161,8 +278,10 @@ Cmd.prototype.sort = async function() {
|
|
|
161
278
|
*/
|
|
162
279
|
Cmd.prototype.sort_tense = async function() {
|
|
163
280
|
this.list_before.clear();
|
|
164
|
-
this.
|
|
281
|
+
this.list_check.clear();
|
|
165
282
|
this.list_main.clear();
|
|
283
|
+
this.list_render.clear();
|
|
284
|
+
this.list_after.clear();
|
|
166
285
|
|
|
167
286
|
var lt = this.list;
|
|
168
287
|
for (var i = 0; i < lt.length; i++) {
|
|
@@ -171,6 +290,12 @@ Cmd.prototype.sort_tense = async function() {
|
|
|
171
290
|
case "before":
|
|
172
291
|
this.list_before.push(o);
|
|
173
292
|
break;
|
|
293
|
+
case "check":
|
|
294
|
+
this.list_check.push(o);
|
|
295
|
+
break;
|
|
296
|
+
case "render":
|
|
297
|
+
this.list_render.push(o);
|
|
298
|
+
break;
|
|
174
299
|
case "after":
|
|
175
300
|
this.list_after.push(o);
|
|
176
301
|
break;
|
package/core/com/mqtt/index.js
CHANGED
|
@@ -31,7 +31,7 @@ class MQTT extends Index {
|
|
|
31
31
|
port: "1883",
|
|
32
32
|
protocol: "mqtt",
|
|
33
33
|
clientId: "iot_test",
|
|
34
|
-
subscribe_qos:
|
|
34
|
+
subscribe_qos: 1,
|
|
35
35
|
publish_qos: 1,
|
|
36
36
|
username: "iot_test",
|
|
37
37
|
password: "asd123",
|
|
@@ -125,7 +125,7 @@ MQTT.prototype.match = function(topic, top) {
|
|
|
125
125
|
/**
|
|
126
126
|
* 初始化
|
|
127
127
|
*/
|
|
128
|
-
MQTT.prototype.update_after = function() {
|
|
128
|
+
MQTT.prototype.update_after = async function() {
|
|
129
129
|
var _this = this;
|
|
130
130
|
var list = this.list;
|
|
131
131
|
for (var i = 0, o; o = list[i++];) {
|
|
@@ -135,7 +135,7 @@ MQTT.prototype.update_after = function() {
|
|
|
135
135
|
_this.send(topic, msg, qos, retain);
|
|
136
136
|
}
|
|
137
137
|
};
|
|
138
|
-
o.exec('init');
|
|
138
|
+
await o.exec('init');
|
|
139
139
|
var topics = o.config.topic;
|
|
140
140
|
if (topics) {
|
|
141
141
|
for (var i = 0; i < topics.length; i++) {
|
|
@@ -275,7 +275,7 @@ MQTT.prototype.receive = async function(push_topic, msg) {
|
|
|
275
275
|
for (var i = 0; i < topics.length; i++) {
|
|
276
276
|
var topic = topics[i];
|
|
277
277
|
if (this.match(push_topic, topic)) {
|
|
278
|
-
ret = await o.
|
|
278
|
+
ret = await o.exec('handle', push_topic, msg, topic, i);
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
281
|
}
|
package/core/com/task/drive.js
CHANGED
|
@@ -42,7 +42,10 @@ class Drive extends Item {
|
|
|
42
42
|
constructor(dir) {
|
|
43
43
|
super(dir, __dirname);
|
|
44
44
|
this.default_file = "./task.json";
|
|
45
|
-
|
|
45
|
+
|
|
46
|
+
// 更新配置并重载脚本
|
|
47
|
+
this.mode = 3;
|
|
48
|
+
|
|
46
49
|
/// 配置参数
|
|
47
50
|
this.config = {
|
|
48
51
|
// 名称, 由中英文和下“_”组成, 用于修改或卸载 例如: demo
|
|
@@ -299,7 +302,9 @@ Drive.prototype.run = async function(func) {
|
|
|
299
302
|
if (func) {
|
|
300
303
|
await this.setInterval(this.setPeriod(this.setNum(func)));
|
|
301
304
|
} else {
|
|
302
|
-
await this.setInterval(this.setPeriod(this.setNum(
|
|
305
|
+
await this.setInterval(this.setPeriod(this.setNum(() => {
|
|
306
|
+
this.main();
|
|
307
|
+
})));
|
|
303
308
|
}
|
|
304
309
|
return this;
|
|
305
310
|
};
|
package/core/com/task/index.js
CHANGED