mm_os
Version:
这是超级美眉服务端框架,用于快速构建应用程序。
354 lines (329 loc) • 7.97 kB
JavaScript
const Index = require('mm_machine').Index;
const Drive = require('./drive');
/**
* Cmd导航类
* @extends {Index}
* @class
*/
class Cmd extends Index {
/**
* 构造函数
* @param {Object} scope 作用域
* @param {String} title 标题
* @constructor
*/
constructor(scope, title) {
super(scope, __dirname);
this.Drive = Drive;
this.type = "cmd";
this.title = title;
this.list_before = [];
this.list_check = [];
this.list_main = [];
this.list_render = [];
this.list_after = [];
// 默认启用热更新
this.mode = 3;
/**
* 配置参数
*/
this.config = {
table: "wechat_message",
key: "message_id",
// 聊天间隔时长,单位:秒,600秒为10分钟
interval: 600
};
}
}
/**
* 设置配置
* @param {Object} config 配置参数
*/
Cmd.prototype.set_config = function(config) {
Object.assign(this.config, config);
}
/**
* 执行指令
* @param {Object} msg 消息对象
* @param {Object} db 数据库对象
* @param {Object} list 数据库对象
* @return {Object} 返回值
*/
Cmd.prototype.run_cmd_sub = async function(msg, db, tense = 'main') {
var list = this['list_' + tense];
if (!list) {
return
}
var ret;
for (var i = 0, o; o = list[i++];) {
if (o.config.state === 1) {
ret = await o.run(msg, db);
if (ret) {
db.ret = ret;
// 如果匹配指令则将该消息定义为使用该指令
msg.cmd = o.config.name;
if (o.config.end) {
break;
}
}
}
}
return ret;
}
// // 获取当前未结束的会话记录
// var log = await db.getObj(query);
// // 如果不存在未结束会话,则创建新会话记录
// if (!log) {
// var bl = await db.add(msg);
// if (bl) {
// log = await db.getObj(query);
// if (log) {
// log.time_create = new Date().toStr('yyyy-MM-dd hh:mm:ss');
// }
// } else {
// $.log.error('添加微信消息到wechat_message表失败!', log);
// return null;
// }
// } else if (log.content_last !== msg.content) {
// // 判断是否重复会话内容,如果未重复则添加新内容
// log.content += '\r\n' + msg.content;
// }
// log.content_last = msg.content;
// db.msg = log;
// var lt = this.list_before;
// for (var i = 0, o; o = lt[i++];) {
// if (o.config.state === 1) {
// ret = await o.run_cmd(msg, db);
// if (ret) {
// break;
// }
// }
// }
// if (!ret) {
// // 判断会话记录是否锁定了指令, 如果存在则继续执行该指令程序
// if (msg_log.cmd) {
// // 检索指令驱动是否存在
// var drive = this.list.getObj({
// config: {
// name: msg_log.cmd
// }
// });
// if (drive) {
// // 如果存在则执行指令
// ret = await drive.run(msg, db);
// } else {
// // 如果不存在则结束会话, 并创建新会话
// db.msg.end = 1;
// var bl = await db.add(msg);
// if (bl) {
// msg_log = await db.getObj(query);
// if (msg_log) {
// msg_log.time_create =;
// }
// db.msg = msg_log;
// }
// }
// }
// if (db.msg.keyword) {
// // 添加消息
// msg.content = db.msg.keyword + "\r\n" + msg.content;
// }
// }
/**
* 获取上下文
* @param {Object} msg 消息
* @param {Object} db 数据管理器
* @return {Object}
*/
Cmd.prototype.get_context = async function(msg, db) {
var cg = this.config;
var now = new Date();
var query = {
from_user: msg.from_user,
to_user: msg.to_user,
group: msg.group,
type: msg.type,
time_create_max: now.addSeconds(cg.interval).toStr('yyyy-MM-dd hh:mm:ss')
};
var db1 = db.new(cg.table, cg.key);
var log = await db1.getObj(query, '`time_create` desc');
if(log && !log.end)
{
return log;
}
return null;
}
/**
* 合并消息
* @param {Object} msg
* @param {Array} log
*/
Cmd.prototype.merge_msg = function(msg, log) {
var m = Object.assign({}, msg, log);
m.content = log.content + "\r\n" + msg.content;
m.content_last = msg.content;
return m;
}
/**
* 保存消息
* @param {Object} msg 消息
* @param {Object} db 数据管理器
*/
Cmd.prototype.save_msg = async function(msg, db) {
var cg = this.config;
var db1 = db.new(cg.table, cg.key);
var ret = db.ret;
if (ret) {
if (typeof(ret) == "object") {
ret = JSON.stringify(ret);
}
msg.result = ret;
}
if (msg[cg.key]) {
var qy = {};
qy[cg.key] = msg[cg.key];
return await db1.set(qy, msg);
} else {
return await db1.add(msg);
}
}
/**
* 执行指令
* @param {Object} msg 消息
* @param {Object} db 数据管理器
* @return {Object|String}
*/
Cmd.prototype.run = async function(msg, db) {
// 判断是否含有消息和消息正文
if (!msg || !msg.content) {
return;
}
db.table = this.config.table;
db.key = this.config.key;
msg.stage = 1;
// 1.先执行前时态指令
var ret = await this.run_cmd_sub(msg, db, 'before');
db.ret = ret;
// console.log("执行前", ret);
// 2.先执行验证时态指令,如果通过则返回空,否则返回验证失败结果。
var ret_check = await this.run_cmd_sub(msg, db, 'check');
// console.log("执行检查", ret_check);
if (ret_check || ret_check === "") {
ret = ret_check;
} else {
// 3-1.先判断本次内容是否为指令,如果是则执行指令。
var ret_main = await this.run_cmd_sub(msg, db, 'main');
console.log("执行", ret_main);
if (ret_main) {
ret = ret_main;
}
if (!ret) {
// 3-2.如果本次内容非指令,则先获取历史未完成的指令。拼接本次内容,并执行指令。
var log = await this.get_context(msg, db);
if (log) {
msg = this.merge_msg(msg, log);
ret_main = await this.run_cmd_sub(msg, db, 'main');
console.log("合并执行", ret_main);
if (ret_main) {
ret = ret_main;
}
}
}
}
// 4.执行后时态指令
var ret_after = await this.run_cmd_sub(msg, db, 'after');
if (ret_after) {
ret = ret_after;
// console.log("执行后", ret);
}
if (ret) {
db.ret = ret;
}
// 5.记录本次消息
await this.save_msg(msg, db);
return ret;
};
/**
* 执行排序
*/
Cmd.prototype.sort = async function() {
this.list.sort(function(o1, o2) {
var p1 = o1.sort;
var p2 = o2.sort;
return p2 - p1;
});
this.sort_tense();
};
/**
* 排序时态
*/
Cmd.prototype.sort_tense = async function() {
this.list_before.clear();
this.list_check.clear();
this.list_main.clear();
this.list_render.clear();
this.list_after.clear();
var lt = this.list;
for (var i = 0; i < lt.length; i++) {
var o = lt[i];
switch (o.config.tense) {
case "before":
this.list_before.push(o);
break;
case "check":
this.list_check.push(o);
break;
case "render":
this.list_render.push(o);
break;
case "after":
this.list_after.push(o);
break;
default:
this.list_main.push(o);
break;
}
}
};
/**
* 下达指令
* @param {String} name 名称
* @param {Number} state 状态
* @param {Array} ...params 参数集合
*/
Cmd.prototype.cmd = async function(name, state, ...params) {
var obj = this.get(name);
if (!obj) {
return "error: program does not exist";
}
return await obj.exec("cmd", state, ...params);
}
/* 导出指令 */
exports.Cmd = Cmd;
/**
* Cmd事件池
*/
if (!$.pool.cmd) {
$.pool.cmd = {};
}
/**
* Cmd管理器,用于创建缓存
* @param {String} scope 作用域
* @param {string} title 标题
* @return {Object} 返回一个缓存类
*/
function cmd_admin(scope, title) {
if (!scope) {
scope = $.val.scope + '';
}
var obj = $.pool.cmd[scope];
if (!obj) {
$.pool.cmd[scope] = new Cmd(scope, title);
obj = $.pool.cmd[scope];
}
return obj;
}
/**
* @module 导出Cmd管理器
*/
$.cmd_admin = cmd_admin;