node-red-contrib-motechat
Version:
ultranet topic and payload communication
477 lines (419 loc) • 12.8 kB
JavaScript
var when = require('when');
var nodeFn = require('when/node/function');
var keys = require('when/keys');
var fs = require('fs-extra');
var fspath = require("path");
var mkdirp = fs.mkdirs;
var crypto = require('crypto');
var mc = require('./lib/mcClient.js');
var caller = {
SetConfig: mc.set,
GetConfig: mc.get,
call: mc.call,
reged: mc.reged
}
var initialFlowLoadComplete = false;
var settings;
var runtime;
var flowsFile;
var projectFile;
var flowsFullPath;
var flowsFileBackup;
var credentialsFile;
var credentialsFileBackup;
var oldCredentialsFile;
var sessionsFile;
var libDir;
var libFlowsDir;
var globalSettingsFile;
var qName;
var qCode;
var qType;
var oid;
var uid;
var eiName;
var promiseDir = nodeFn.lift(mkdirp);
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
function log(){
var str = "";
if(oid)
str+= " OID = " + oid;
if(qName)
str+= " QNAME = " + qName;
if(qCode)
str+= " QCODE = " + qCode;
if(qType)
str+= " QTYPE = " + qType;
if(uid)
str+= " UID = " + uid;
return str;
}
function log2(){
var str = "";
if(oid)
str+= " OID = " + oid;
if(qName)
str+= " QNAME = " + qName;
if(qCode)
str+= " QCODE = " + qCode;
if(eiName)
str+= " EINAME = " + eiName;
return str;
}
function loadObjMMS(){
return when.promise(async function(resolve, reject){
let payload = {
type: "flow"
};
if(qType)
payload.type = qType;
if(oid && oid != null)
payload._id = oid;
else if(qName){
payload.qname = qName;
if(qCode)
payload.qcode = qCode;
if(uid)
payload.uid = uid;
}
if(!qCode && !qName && !oid)
reject('QCODE or QNAME or OID is required.');
while(1){
if(caller.reged() != ""){
break;
}
await new Promise(resolve => setTimeout(resolve, 500));
}
caller.call('', process.env.OBJMMS_DDN || '>svc/objc', 'obj://get', {}, payload).then(reply => {
if (reply) {
let result;
if (typeof reply == 'object')
result = reply;
else
result = reply[0];
if (Array.isArray(result))
result = result[0];
//console.log("ObjMMS Call Result = %s", JSON.stringify(result));
if(!result.Reply || result.Reply == ''){
reject(result.IN.State.ErrMsg);
}else{
result = result.Reply;
}
if (result.ErrMsg != 'OK') {
reject(result.ErrMsg);
}
else if (result.ErrMsg == 'OK') {
result = result.Data;
if(result && result.data){
if(qType == 'project')
resolve(result.data.flows);
else
resolve(result.data.flow);
}
else{
reject(`Flow not found: QNAME = ${qName} QCODE = ${qCode}`);
}
}
} else {
reject("Call objmms not response")
}
}).catch(err => {
console.log(err);
reject(err);
});
})
}
function objLoad(type, path) {
if (!initialFlowLoadComplete) {
initialFlowLoadComplete = true;
}
return when.promise(async function(resolve, reject) {
if(type == 'flows'){
console.log("Flow params: " + log());
loadObjMMS().then((reply)=>{
if(reply && reply.length > 0){
console.log("Flow loaded from objstore: OK");
objSave('flows', '/', reply).then((result)=>{
console.log("Flow stored at xstorage: OK");
resolve(reply);
}).catch((err)=>{
console.log("Flow can't store at xstorage: " + log2());
console.log(err);
loadFromXstore(type, resolve, reject);
//reject(err.message);
});
}else{
console.log("Flow not found in objstore");
loadFromXstore(type, resolve, reject);
}
}).catch((err) => {
console.log("Flow can't load from objstore");
console.log(err);
loadFromXstore(type, resolve, reject);
});
}else{
let idname = `${eiName}_${type}`;
if(path)
idname += `_${path}`;
let payload = {
catalog: type == 'flows' ? 'flow' : type,
idname: idname
};
caller.GetConfig(payload).then((reply) => {
if (reply) {
let result;
if (typeof reply == 'object')
result = reply;
else
result = reply[0];
if (Array.isArray(result))
result = result[0];
if (result.ErrMsg != 'OK') {
reject(result.ErrMsg);
}
else if (result.ErrMsg == 'OK') {
if(result.result)
resolve(result.result);
else if(type == 'flows'){
resolve([]);
}
else{
resolve([]);
}
}
} else {
reject("Call xstorage not response")
}
});
}
});
}
function loadFromXstore(type, resolve, reject){
let payload = {
catalog: 'flow',
idname: eiName
};
console.log("Flow xstorage params: " + log2());
caller.GetConfig(payload).then((reply) => {
if (reply) {
let result;
if (typeof reply == 'object')
result = reply;
else
result = reply[0];
if (Array.isArray(result))
result = result[0];
if (result.ErrMsg != 'OK') {
reject(result.ErrMsg);
}
else if (result.ErrMsg == 'OK') {
console.log("Flow loaded from xstorage");
if(result.result)
resolve(result.result);
else if(type == 'flows'){
resolve([]);
}
else{
resolve([]);
}
}
} else {
console.log("Flow can't load from xstorage");
reject("Call xstorage not response")
}
});
}
function objSave(type, path, blob) { //need to check
return when.promise(function(resolve, reject) {
let idname = `${eiName}_${type}`;
if(path)
idname += `_${path}`;
if(type == 'flows'){
idname = eiName;
}
let payload = {
catalog: type == 'flows' ? 'flow' : type,
idname: idname,
data: blob
};
caller.SetConfig(payload).then((reply) => {
if (reply) {
let result;
if (typeof reply == 'object')
result = reply;
else
result = reply[0];
if (Array.isArray(result))
result = result[0];
if (result.ErrMsg != 'OK') {
reject(result.ErrMsg);
}
else if (result.ErrMsg == 'OK') {
resolve('OK')
}
} else {
reject('Call xstorage not response');
}
});
});
}
var storage = process.env.FBOT_MODE || "";
if(storage === "xstorage"){
var xStorage = {
init: function(_settings, _runtime) {
var promises = [];
settings = _settings;
runtime = _runtime;
if (!settings.userDir) {
try {
fs.statSync(fspath.join(process.env.NODE_RED_HOME,".config.json"));
settings.userDir = process.env.NODE_RED_HOME;
} catch(err) {
settings.userDir = fspath.join(process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE || process.env.NODE_RED_HOME,".node-red");
if (!settings.readOnly) {
promises.push(promiseDir(fspath.join(settings.userDir,"node_modules")));
}
}
}
if (process.env.FLOW_FILE || settings.flowFile) {
flowsFile = process.env.FBOT_FLOWFILE || settings.flowFile;
// handle Unix and Windows "C:\"
if ((flowsFile[0] == "/") || (flowsFile[1] == ":")) {
// Absolute path
flowsFullPath = flowsFile;
} else if (flowsFile.substring(0,2) === "./") {
// Relative to cwd
flowsFullPath = fspath.join(process.cwd(),flowsFile);
} else {
try {
fs.statSync(fspath.join(process.cwd(),flowsFile));
// Found in cwd
flowsFullPath = fspath.join(process.cwd(),flowsFile);
} catch(err) {
// Use userDir
flowsFullPath = fspath.join(settings.userDir,flowsFile);
}
}
} else {
flowsFile = 'flows_'+require('os').hostname()+'.json';
flowsFullPath = fspath.join(settings.userDir,flowsFile);
}
var ffExt = fspath.extname(flowsFullPath);
var ffName = fspath.basename(flowsFullPath);
var ffBase = fspath.basename(flowsFullPath,ffExt);
var ffDir = fspath.dirname(flowsFullPath);
credentialsFile = fspath.join(settings.userDir,ffBase+"_cred"+ffExt);
credentialsFileBackup = fspath.join(settings.userDir,"."+ffBase+"_cred"+ffExt+".backup");
oldCredentialsFile = fspath.join(settings.userDir,"credentials.json");
//flowsFileBackup = fspath.join(ffDir,"."+ffName+".backup");
sessionsFile = fspath.join(settings.userDir,".sessions.json");
//projectFile = fspath.join(settings.userDir,"projects.json");
libDir = fspath.join(settings.userDir,"lib");
libFlowsDir = fspath.join(libDir,"flows");
globalSettingsFile = fspath.join(settings.userDir,".config.json");
if (!settings.readOnly) {
promises.push(promiseDir(libFlowsDir));
}
qName = process.env.FBOT_QNAME;
qCode = process.env.FBOT_QCODE;
qType = process.env.FBOT_QTYPE;
oid = process.env.FBOT_OID || null;
uid = process.env.FBOT_UID || null;
eiName = process.env.MCHAT_EINAME;
promises.push(mc.setup());
return when.all(promises);
},
getFlows: function() {
return objLoad('flows', '/');
},
saveFlows: function(flows) {
return objSave('flows', '/', flows);
},
getCredentials: function() {
return objLoad('credentials', '/');
},
saveCredentials: function(credentials) {
return objSave('credentials', '/', credentials);
},
getSettings: function() {
return objLoad('settings', '/');
},
saveSettings: function(settings) {
return objSave('settings', '/', settings);
},
getSessions: function() {
return objLoad('sessions', '/');
},
saveSessions: function(sessions) {
return objSave('sessions', '/', sessions);
},
getLibraryEntry: function(type, path) {
return when.promise(function(resolve, reject) {
let idname = `${eiName}_library`;
if(type)
idname += `_${type}`;
if(path)
idname += `_${path}`;
let payload = {
catalog: type,
idname: idname
}
caller.GetConfig(payload).then((reply) => {
if (reply) {
let result;
if (typeof reply == 'object')
result = reply;
else
result = reply[0];
if (Array.isArray(result))
result = result[0];
if (result.ErrMsg != 'OK') {
reject(result.ErrMsg);
}
else if (result.ErrMsg == 'OK') {
resolve(result.result || {});
}
} else {
reject("Call xstorage not response")
}
});
});
},
saveLibraryEntry: function(type, path, meta, body) {
return when.promise(function(resolve, reject) {
let idname = `${eiName}_library`;
if(type)
idname += `_${type}`;
if(path)
idname += `_${path}`;
let payload = {
catalog: type,
idname: idname,
data: {meta : meta, body: body}
};
caller.SetConfig(payload).then((reply) => {
if (reply) {
let result;
if (typeof reply == 'object')
result = reply;
else
result = reply[0];
if (Array.isArray(result))
result = result[0];
if (result.ErrMsg != 'OK') {
reject(result.ErrMsg);
}
else if (result.ErrMsg == 'OK') {
resolve('OK')
}
} else {
reject('Call xstorage not response');
}
});
});
}
};
module.exports = xStorage;
}