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.
@@ -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
- "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
- }
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
+ }
@@ -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
- "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
- }
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 bl = false;
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
- if (content.matchs(format)) {
129
- bl = true;
132
+ var str = content.matchs(format);
133
+ if (str) {
134
+ word = str;
130
135
  break;
131
136
  }
132
137
  }
133
- return bl;
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
- var ret = content;
166
- var len = list.length;
167
- for (var i = 0; i < len; i++) {
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 str = content.matchs(format);
170
- if (str) {
171
- ret += "\r\n" + str;
174
+ var ret = content.matchs(format);
175
+ if (ret) {
176
+ content = ret;
172
177
  }
173
178
  }
174
- return ret;
179
+ return content;
175
180
  };
176
181
 
177
-
178
182
  /**
179
183
  * 移除关键词
180
- * @param {String} content 正文
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 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, '');
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 bl = await this.match(msg.content, db);
218
- if (bl) {
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 bl;
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
- return await this.remove(content);
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
- 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
- }
268
+ // 获取已有参数
269
+ var form = {};
270
+ if (msg.form) {
271
+ form = msg.form.toJson();
279
272
  }
280
- ct = msg.content;
281
- var tip = "";
282
- for (var k in form) {
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
- 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) {
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.msg.keyword = keyword;
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 || !db.msg.form) {
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
- 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++) {
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
- keyword = k;
343
+ msg.note = k;
341
344
  break;
342
- } else if (keyword == k && o.format) {
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
- db.msg.keyword = keyword;
353
- db.msg.form = JSON.stringify(form);
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 (txt.indexOf('?') === -1) {
384
- db.msg.end = 1;
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
- msg.content = await this.filter(msg, db);
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 stage = this.config["stage" + db.msg.stage];
481
- if (stage) {
482
- var mode = stage.mode ? stage.mode : "fill";
483
- if (this[mode]) {
484
- ret = await this[mode](msg, db, stage);
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
- var json = msg.form;
513
- if (json) {
514
- var stage = this.config.stage1;
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 len = list.length;
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) {
@@ -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 {String} table 表名
34
- * @return {Object|String}
51
+ * @param {Object} msg 消息对象
52
+ * @param {Object} db 数据库对象
53
+ * @param {Object} list 数据库对象
54
+ * @return {Object} 返回值
35
55
  */
36
- Cmd.prototype.run = async function(msg, db, table) {
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
- if (msg && msg.content) {
40
- db.msg = {
41
- content: "",
42
- content_last: msg.content,
43
- form: "",
44
- stage: 1
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
- msg_log.content_last = msg.content;
77
- db.msg = msg_log;
78
-
79
- var lt = this.list_before;
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
- if (db.msg.keyword) {
116
- // 添加消息
117
- msg.content = db.msg.keyword + "\r\n" + msg.content;
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
- if (!ret) {
122
- var lt = this.list_main;
123
- for (var i = 0, o; o = lt[i++];) {
124
- if (o.config.state === 1) {
125
- ret = await o.run_first(msg, db);
126
- if (ret) {
127
- break;
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
- var lt = this.list_after;
134
- for (var i = 0, o; o = lt[i++];) {
135
- if (o.config.state === 1) {
136
- ret = await o.run_first(msg, db);
137
- if (ret) {
138
- break;
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.list_after.clear();
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;
@@ -31,7 +31,7 @@ class MQTT extends Index {
31
31
  port: "1883",
32
32
  protocol: "mqtt",
33
33
  clientId: "iot_test",
34
- subscribe_qos: 0,
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.run(push_topic, msg, topic, i);
278
+ ret = await o.exec('handle', push_topic, msg, topic, i);
279
279
  }
280
280
  }
281
281
  }
@@ -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(this.main)));
305
+ await this.setInterval(this.setPeriod(this.setNum(() => {
306
+ this.main();
307
+ })));
303
308
  }
304
309
  return this;
305
310
  };
@@ -18,6 +18,8 @@ class Task extends Index {
18
18
  this.Drive = Drive;
19
19
  this.type = "task";
20
20
  this.title = title;
21
+ // 更新配置并重载脚本
22
+ this.mode = 3;
21
23
  }
22
24
  }
23
25
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_os",
3
- "version": "2.9.2",
3
+ "version": "2.9.4",
4
4
  "description": "这是超级美眉服务端框架,用于快速构建应用程序。",
5
5
  "main": "index.js",
6
6
  "scripts": {