mm_cmd 1.1.0 → 1.1.1

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.
@@ -0,0 +1,76 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * mm_cmd 指令框架模块示例
5
+ * 演示:注册一条"打招呼"指令,加载脚本后用字符串消息触发匹配与执行。
6
+ * 注:管理器 add() 存在未定义 Drive 的缺陷,此处直接实例化 Cmd 驱动演示核心 API。
7
+ * 运行:node example/index.js
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const os = require('os');
12
+ const path = require('path');
13
+ const { cmdAdmin, Cmd } = require('../index.js');
14
+
15
+ /**
16
+ * 生成临时指令脚本(导出 main 方法)
17
+ * @returns {string} 脚本文件路径
18
+ */
19
+ function createScript() {
20
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'mm_cmd-'));
21
+ const file = path.join(dir, 'hello.js');
22
+ fs.writeFileSync(
23
+ file,
24
+ `'use strict';
25
+ module.exports = {
26
+ /**
27
+ * 指令主函数
28
+ * @param {object} msg 消息对象
29
+ * @returns {string} 回复内容
30
+ */
31
+ main: async function (msg) {
32
+ return '你好,我是机器人!';
33
+ }
34
+ };
35
+ `,
36
+ 'utf8'
37
+ );
38
+ return file;
39
+ }
40
+
41
+ /**
42
+ * 主函数
43
+ * @returns {Promise<void>} 无返回值
44
+ */
45
+ async function main() {
46
+ // 1. 获取指令管理器(同 scope 复用实例)
47
+ const manager = cmdAdmin('demo', { title: '示例指令管理器' });
48
+ const manager2 = cmdAdmin('demo');
49
+ console.log('管理器实例复用:', manager === manager2);
50
+
51
+ // 2. 创建指令驱动(匹配"你好"开头的消息)
52
+ const drive = new Cmd(
53
+ {
54
+ name: 'hello',
55
+ title: '打招呼',
56
+ match: ['/你好/'],
57
+ main: createScript(),
58
+ func_name: 'main'
59
+ },
60
+ manager
61
+ );
62
+ console.log('驱动类型:', drive instanceof Cmd);
63
+
64
+ // 3. 匹配并执行
65
+ const ret = await drive.run({ content: '你好', from_user: 'u1', to_user: 'bot', chatid: 'c1' }, {});
66
+ console.log('执行结果:', JSON.stringify(ret));
67
+
68
+ // 4. 不匹配的内容返回空
69
+ const no_match = await drive.run({ content: '再见' }, {});
70
+ console.log('不匹配时结果:', no_match);
71
+ }
72
+
73
+ main().catch((err) => {
74
+ console.error('示例执行失败:', err);
75
+ process.exit(1);
76
+ });
package/index.js CHANGED
@@ -5,13 +5,13 @@ let admin = new Admin();
5
5
  admin.setClass(Manager);
6
6
 
7
7
  module.exports = {
8
- Drive: require('./lib/drive'),
8
+ Cmd: require('./lib/cmd'),
9
9
  Manager,
10
10
  admin,
11
11
  cmdAdmin(scope, config) {
12
12
  if (!scope) {
13
13
  scope = 'os';
14
14
  }
15
- return admin.get(scope, { name: scope, ...config });
15
+ return admin.get(scope, config);
16
16
  }
17
17
  };
@@ -1,5 +1,5 @@
1
1
  const path = require('path');
2
- const Item = require('mm_corejs').Base;
2
+ const Item = require('mm_mod').Base;
3
3
  // 指令匹配依赖 mm_matchs 注入的 String.prototype.matchs(需 mm_matchs 环境)
4
4
  require('mm_matchs');
5
5
 
@@ -8,7 +8,7 @@ require('mm_matchs');
8
8
  * @augments {Item}
9
9
  * @class
10
10
  */
11
- class Drive extends Item {
11
+ class Cmd extends Item {
12
12
  /**
13
13
  * 配置参数
14
14
  * @type {object}
@@ -56,7 +56,7 @@ class Drive extends Item {
56
56
  * @param {object} parent 父对象(管理器实例)
57
57
  */
58
58
  constructor(config, parent) {
59
- super({ ...Drive.config, ...config });
59
+ super({ ...Cmd.config, ...config });
60
60
 
61
61
  // 父级管理器引用(用于配置回退与插件查找)
62
62
  this.parent = parent || null;
@@ -72,7 +72,7 @@ class Drive extends Item {
72
72
  * @returns {string} 脚本绝对路径,未配置 main 返回空字符串
73
73
  * @private
74
74
  */
75
- Drive.prototype._getScriptFile = function () {
75
+ Cmd.prototype._getScriptFile = function () {
76
76
  var main = this.config.main || '';
77
77
  if (!main) {
78
78
  return '';
@@ -87,7 +87,7 @@ Drive.prototype._getScriptFile = function () {
87
87
  * 加载主脚本文件并注册导出方法(替代旧基类 loadScript + _setMainMethod)
88
88
  * @returns {object|null} 加载的模块对象
89
89
  */
90
- Drive.prototype.loadScript = function () {
90
+ Cmd.prototype.loadScript = function () {
91
91
  var file = this._getScriptFile();
92
92
  if (!file) {
93
93
  return null;
@@ -109,7 +109,7 @@ Drive.prototype.loadScript = function () {
109
109
  * @returns {void}
110
110
  * @private
111
111
  */
112
- Drive.prototype._registerMethods = function (mod) {
112
+ Cmd.prototype._registerMethods = function (mod) {
113
113
  if (!mod) {
114
114
  return;
115
115
  }
@@ -124,7 +124,7 @@ Drive.prototype._registerMethods = function (mod) {
124
124
  * 卸载脚本(清除模块缓存与方法集合)
125
125
  * @returns {void}
126
126
  */
127
- Drive.prototype.unloadScript = function () {
127
+ Cmd.prototype.unloadScript = function () {
128
128
  var file = this._getScriptFile();
129
129
  if (file) {
130
130
  try {
@@ -141,7 +141,7 @@ Drive.prototype.unloadScript = function () {
141
141
  * 重新加载脚本
142
142
  * @returns {object|null} 加载的模块对象
143
143
  */
144
- Drive.prototype.reloadScript = function () {
144
+ Cmd.prototype.reloadScript = function () {
145
145
  this.unloadScript();
146
146
  return this.loadScript();
147
147
  };
@@ -152,7 +152,7 @@ Drive.prototype.reloadScript = function () {
152
152
  * @param {...*} params 参数列表
153
153
  * @returns {Promise<*>} 执行结果
154
154
  */
155
- Drive.prototype.call = async function (method, ...params) {
155
+ Cmd.prototype.call = async function (method, ...params) {
156
156
  if (!this.loaded) {
157
157
  this.loadScript();
158
158
  }
@@ -191,7 +191,7 @@ Drive.prototype.call = async function (method, ...params) {
191
191
  * @param {string} content 消息内容
192
192
  * @returns {string} 匹配返回关键词字符串, 否则返回空字符串
193
193
  */
194
- Drive.prototype.match = function (content) {
194
+ Cmd.prototype.match = function (content) {
195
195
  var match_arr = this.config.match;
196
196
  if (!match_arr || match_arr.length === 0) {
197
197
  return '';
@@ -219,7 +219,7 @@ Drive.prototype.match = function (content) {
219
219
  * @param {object} db 数据管理器
220
220
  * @returns {object|string} 返回执行结果, 不匹配返回null
221
221
  */
222
- Drive.prototype.run = async function (msg, db) {
222
+ Cmd.prototype.run = async function (msg, db) {
223
223
  if (!msg || !msg.content) {
224
224
  return null;
225
225
  }
@@ -257,7 +257,7 @@ Drive.prototype.run = async function (msg, db) {
257
257
  * @returns {string|null} 返回追问内容, 全部满足返回null
258
258
  * @private
259
259
  */
260
- Drive.prototype._fillParams = function (msg) {
260
+ Cmd.prototype._fillParams = function (msg) {
261
261
  var params = this.config.params;
262
262
  if (!params || !params.properties) {
263
263
  return null;
@@ -287,7 +287,7 @@ Drive.prototype._fillParams = function (msg) {
287
287
  * @param {object} param 参数配置
288
288
  * @private
289
289
  */
290
- Drive.prototype._tryExtractParam = function (msg, name, param) {
290
+ Cmd.prototype._tryExtractParam = function (msg, name, param) {
291
291
  if (msg.form[name]) {
292
292
  return;
293
293
  }
@@ -313,7 +313,7 @@ Drive.prototype._tryExtractParam = function (msg, name, param) {
313
313
  * @returns {string} 清理后的值
314
314
  * @private
315
315
  */
316
- Drive.prototype._cleanVal = function (val, param) {
316
+ Cmd.prototype._cleanVal = function (val, param) {
317
317
  if (!val) return '';
318
318
  var result = val;
319
319
  if (param.remove && param.remove.length) {
@@ -327,4 +327,4 @@ Drive.prototype._cleanVal = function (val, param) {
327
327
  return result;
328
328
  };
329
329
 
330
- module.exports = Drive;
330
+ module.exports = Cmd;
@@ -0,0 +1,61 @@
1
+
2
+
3
+ /**
4
+ * 内置会话缓存类(替代原框架注入的全局缓存服务,进程内 Map + 过期时间)
5
+ * @class
6
+ */
7
+ class LocalCache {
8
+ /**
9
+ * 构造函数
10
+ * @class
11
+ */
12
+ constructor() {
13
+ /**
14
+ * 缓存存储(key => { value, expire })
15
+ * @type {Map}
16
+ */
17
+ this.store = new Map();
18
+ }
19
+
20
+ /**
21
+ * 读取缓存(过期自动删除)
22
+ * @param {string} key 缓存键
23
+ * @returns {*} 缓存值,不存在返回 undefined
24
+ */
25
+ get(key) {
26
+ var item = this.store.get(key);
27
+ if (!item) {
28
+ return undefined;
29
+ }
30
+ if (item.expire && item.expire < Date.now()) {
31
+ this.store.delete(key);
32
+ return undefined;
33
+ }
34
+ return item.value;
35
+ }
36
+
37
+ /**
38
+ * 写入缓存
39
+ * @param {string} key 缓存键
40
+ * @param {*} value 缓存值
41
+ * @param {number} timeout 有效期秒数,0 或不传为不过期
42
+ * @returns {void}
43
+ */
44
+ set(key, value, timeout = 0) {
45
+ this.store.set(key, {
46
+ value,
47
+ expire: timeout > 0 ? Date.now() + timeout * 1000 : 0,
48
+ });
49
+ }
50
+
51
+ /**
52
+ * 删除缓存
53
+ * @param {string} key 缓存键
54
+ * @returns {boolean} 是否删除成功
55
+ */
56
+ del(key) {
57
+ return this.store.delete(key);
58
+ }
59
+ }
60
+
61
+ module.exports = LocalCache;
package/lib/manager.js CHANGED
@@ -1,70 +1,13 @@
1
- const Manager = require('mm_corejs').Manager;
2
- const Drive = require('./drive');
3
-
4
- /**
5
- * 内置会话缓存类(替代原框架注入的全局缓存服务,进程内 Map + 过期时间)
6
- * @class
7
- */
8
- class LocalCache {
9
- /**
10
- * 构造函数
11
- * @class
12
- */
13
- constructor() {
14
- /**
15
- * 缓存存储(key => { value, expire })
16
- * @type {Map}
17
- */
18
- this.store = new Map();
19
- }
20
-
21
- /**
22
- * 读取缓存(过期自动删除)
23
- * @param {string} key 缓存键
24
- * @returns {*} 缓存值,不存在返回 undefined
25
- */
26
- get(key) {
27
- var item = this.store.get(key);
28
- if (!item) {
29
- return undefined;
30
- }
31
- if (item.expire && item.expire < Date.now()) {
32
- this.store.delete(key);
33
- return undefined;
34
- }
35
- return item.value;
36
- }
37
-
38
- /**
39
- * 写入缓存
40
- * @param {string} key 缓存键
41
- * @param {*} value 缓存值
42
- * @param {number} timeout 有效期秒数,0 或不传为不过期
43
- * @returns {void}
44
- */
45
- set(key, value, timeout = 0) {
46
- this.store.set(key, {
47
- value,
48
- expire: timeout > 0 ? Date.now() + timeout * 1000 : 0,
49
- });
50
- }
51
-
52
- /**
53
- * 删除缓存
54
- * @param {string} key 缓存键
55
- * @returns {boolean} 是否删除成功
56
- */
57
- del(key) {
58
- return this.store.delete(key);
59
- }
60
- }
1
+ const Manager = require('mm_mod').Manager;
2
+ const Cmd = require('./cmd');
3
+ const LocalCache = require('./local_cache');
61
4
 
62
5
  /**
63
6
  * 指令管理器类(迁移自 mm_os com/cmd,基于 mm_corejs 内置管理器模式)
64
7
  * @augments {Manager}
65
8
  * @class
66
9
  */
67
- class Cmd extends Manager {
10
+ class CmdManager extends Manager {
68
11
  /**
69
12
  * 配置参数(方案B:无目录扫描机制键,drive 由 add() 手动注册)
70
13
  * @type {object}
@@ -103,30 +46,28 @@ class Cmd extends Manager {
103
46
  * @param {object} parent 父级模块
104
47
  */
105
48
  constructor(config, parent) {
106
- super({ ...Cmd.config, ...config }, parent);
49
+ super({ ...CmdManager.config, ...config }, parent);
107
50
  this.list_before = [];
108
51
  this.list_main = [];
109
52
  this.list_after = [];
110
- // 插件注册表(方案B:手动注册,供 usePlugin 登记)
111
- this.plugins = {};
112
53
  // 内置会话缓存(config.cache 未注入时使用)
113
54
  this._local_cache = new LocalCache();
114
55
  }
115
56
  }
116
57
 
117
58
  /**
118
- * Cmd驱动类
59
+ * CmdManager驱动类
119
60
  * @type {Drive}
120
61
  */
121
- Cmd.prototype.Drive = Drive;
62
+ CmdManager.prototype.Drive = Cmd;
122
63
 
123
64
  /**
124
65
  * 注册一个指令驱动(方案B:手动注册,不扫描目录)
125
66
  * @param {object} config 驱动配置(必须包含 name)
126
67
  * @returns {object} 驱动实例
127
68
  */
128
- Cmd.prototype.add = function (config) {
129
- var drive = new Drive({ ...config }, this);
69
+ CmdManager.prototype.add = function (config) {
70
+ var drive = new Drive(config, this);
130
71
  this.set(drive.config.name, drive);
131
72
  this._fullList();
132
73
  return drive;
@@ -137,7 +78,7 @@ Cmd.prototype.add = function (config) {
137
78
  * @param {string} name 驱动名称
138
79
  * @returns {Promise<boolean>} 是否删除成功
139
80
  */
140
- Cmd.prototype.del = async function (name) {
81
+ CmdManager.prototype.del = async function (name) {
141
82
  var result = await Manager.prototype.del.call(this, name);
142
83
  this._fullList();
143
84
  return result;
@@ -148,7 +89,7 @@ Cmd.prototype.del = async function (name) {
148
89
  * @param {string} name 驱动名称
149
90
  * @returns {boolean} 是否执行成功
150
91
  */
151
- Cmd.prototype.reload = function (name) {
92
+ CmdManager.prototype.reload = function (name) {
152
93
  var drive = this.get(name);
153
94
  if (!drive) {
154
95
  this.log('warn', '驱动不存在,无法重载', name);
@@ -159,23 +100,12 @@ Cmd.prototype.reload = function (name) {
159
100
  return true;
160
101
  };
161
102
 
162
- /**
163
- * 注册插件集合(供驱动 plugin() 查找,替代原全局插件池)
164
- * @param {string} name 插件作用域名称(app 名)
165
- * @param {object} obj 插件集合对象(需含 get 方法)
166
- * @returns {object} 当前管理器实例
167
- */
168
- Cmd.prototype.usePlugin = function (name, obj) {
169
- this.plugins[name] = obj;
170
- return this;
171
- };
172
-
173
103
  /**
174
104
  * 获取所有驱动配置列表(方案B:来自注册表,按 sort 升序,替代旧基类 getInfos)
175
105
  * @returns {Array} 驱动配置数组
176
106
  * @private
177
107
  */
178
- Cmd.prototype._getInfos = function () {
108
+ CmdManager.prototype._getInfos = function () {
179
109
  var infos = this.values().map((d) => d.config);
180
110
  infos.sort((a, b) => (a.sort || 0) - (b.sort || 0));
181
111
  return infos;
@@ -186,7 +116,7 @@ Cmd.prototype._getInfos = function () {
186
116
  * @returns {object} 含 get/set/del 的缓存实例
187
117
  * @private
188
118
  */
189
- Cmd.prototype._getCache = function () {
119
+ CmdManager.prototype._getCache = function () {
190
120
  var cache = this.config.cache;
191
121
  if (cache && typeof cache.get === 'function' && typeof cache.set === 'function') {
192
122
  return cache;
@@ -199,12 +129,11 @@ Cmd.prototype._getCache = function () {
199
129
  * @returns {void}
200
130
  * @private
201
131
  */
202
- Cmd.prototype._fullList = function () {
132
+ CmdManager.prototype._fullList = function () {
203
133
  this.list_before = [];
204
134
  this.list_main = [];
205
135
  this.list_after = [];
206
-
207
- var infos = this._getInfos();
136
+ var infos = this.configs;
208
137
  for (var i = 0; i < infos.length; i++) {
209
138
  var info = infos[i];
210
139
  if (info.state !== 1) {
@@ -232,7 +161,7 @@ Cmd.prototype._fullList = function () {
232
161
  * 更新后回调
233
162
  * @param {string} dir_path 目录路径
234
163
  */
235
- Cmd.prototype.updateAfter = async function (dir_path) {
164
+ CmdManager.prototype.updateAfter = async function (dir_path) {
236
165
  this._fullList();
237
166
  };
238
167
 
@@ -242,7 +171,7 @@ Cmd.prototype.updateAfter = async function (dir_path) {
242
171
  * @param {object} db 数据管理器
243
172
  * @returns {object|string} 返回执行结果
244
173
  */
245
- Cmd.prototype.run = async function (msg, db) {
174
+ CmdManager.prototype.run = async function (msg, db) {
246
175
  if (!msg || !msg.content) {
247
176
  return null;
248
177
  }
@@ -272,7 +201,7 @@ Cmd.prototype.run = async function (msg, db) {
272
201
  * @param {string} tense 时态
273
202
  * @returns {object|string} 返回执行结果
274
203
  */
275
- Cmd.prototype.runSub = async function (msg, db, tense) {
204
+ CmdManager.prototype.runSub = async function (msg, db, tense) {
276
205
  var list = this['list_' + tense];
277
206
  if (!list) {
278
207
  return null;
@@ -314,7 +243,7 @@ Cmd.prototype.runSub = async function (msg, db, tense) {
314
243
  * @returns {object|string} 返回执行结果
315
244
  * @private
316
245
  */
317
- Cmd.prototype._runSession = async function (msg, db, session) {
246
+ CmdManager.prototype._runSession = async function (msg, db, session) {
318
247
  var mod = this.get(session.cmd);
319
248
  if (!mod) {
320
249
  this._clearSession(msg);
@@ -351,7 +280,7 @@ Cmd.prototype._runSession = async function (msg, db, session) {
351
280
  * @returns {object} 出站消息
352
281
  * @private
353
282
  */
354
- Cmd.prototype._makeResult = function (msg, ret) {
283
+ CmdManager.prototype._makeResult = function (msg, ret) {
355
284
  if (!ret) return ret;
356
285
  var result = typeof ret === 'string' ? { content: ret } : { ...ret };
357
286
  if (msg.to_user) result.from_user = msg.to_user;
@@ -369,7 +298,7 @@ Cmd.prototype._makeResult = function (msg, ret) {
369
298
  * @returns {object|null} 会话信息
370
299
  * @private
371
300
  */
372
- Cmd.prototype._getSession = async function (msg) {
301
+ CmdManager.prototype._getSession = async function (msg) {
373
302
  var key = this._getKey(msg);
374
303
  var val = await this._getCache().get(key);
375
304
  if (!val) {
@@ -387,7 +316,7 @@ Cmd.prototype._getSession = async function (msg) {
387
316
  * @param {object} session 会话信息
388
317
  * @private
389
318
  */
390
- Cmd.prototype._saveSession = function (msg, session) {
319
+ CmdManager.prototype._saveSession = function (msg, session) {
391
320
  var key = this._getKey(msg);
392
321
  this._getCache().set(key, session, this.config.session_timeout);
393
322
  };
@@ -397,7 +326,7 @@ Cmd.prototype._saveSession = function (msg, session) {
397
326
  * @param {object} msg 消息对象
398
327
  * @private
399
328
  */
400
- Cmd.prototype._clearSession = function (msg) {
329
+ CmdManager.prototype._clearSession = function (msg) {
401
330
  var key = this._getKey(msg);
402
331
  this._getCache().del(key);
403
332
  };
@@ -408,11 +337,11 @@ Cmd.prototype._clearSession = function (msg) {
408
337
  * @returns {string} 缓存键
409
338
  * @private
410
339
  */
411
- Cmd.prototype._getKey = function (msg) {
340
+ CmdManager.prototype._getKey = function (msg) {
412
341
  return 'cmd_session_' + (msg.chatid || msg.from_user || 'default');
413
342
  };
414
343
 
415
344
  /**
416
345
  * @module 导出指令管理器类
417
346
  */
418
- module.exports = Cmd;
347
+ module.exports = CmdManager;
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "mm_cmd",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "指令框架,用于以聊天的方式操作程序,前端发送字符串,后端判断是否为指令并执行(基于 mm_corejs,内置管理器池,无全局/原型扩展依赖)",
5
5
  "main": "index.js",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://gitee.com/qiuwenwu91/mm_cmd.git"
9
+ },
6
10
  "keywords": [
7
11
  "mm_mod",
8
12
  "mm_adapter",
@@ -18,6 +22,7 @@
18
22
  "license": "ISC",
19
23
  "dependencies": {
20
24
  "mm_corejs": "^1.1.4",
25
+ "mm_mod": "^1.0.1",
21
26
  "mm_matchs": "^1.1.10"
22
27
  },
23
28
  "scripts": {