node-red-contrib-chatbot
Version:
REDBot a Chat bot for a full featured chat bot for Telegram, Facebook Messenger and Slack. Almost no coding skills required
359 lines (326 loc) • 9.03 kB
JavaScript
const _ = require('lodash');
const utils = require('../lib/helpers/utils');
const helpers = require('../lib/helpers/regexps');
const GlobalContextHelper = require('../lib/helpers/global-context-helper');
const GetEnvironment = require('../lib/helpers/get-environment');
const when = utils.when;
const Types = {
isLanguage(rule, message) {
return new Promise((resolve, reject) => {
var chatContext = message.chat();
when(chatContext.get('language'))
.then(language => {
if (rule.language === language) {
resolve(rule);
} else {
reject();
}
});
});
},
isTransportPreferred(rule, message) {
return new Promise((resolve, reject) => {
message.isTransportPreferred(rule.transport, message)
.then(
isAvailable => {
if (isAvailable) {
resolve(rule)
} else {
reject();
}
},
() => reject()
);
});
},
isTransportAvailable(rule, message) {
return new Promise((resolve, reject) => {
message.isTransportAvailable(rule.transport, message)
.then(
isAvailable => {
if (isAvailable) {
resolve(rule)
} else {
reject();
}
},
() => reject()
);
});
},
pending(rule, message) {
return new Promise(function(resolve, reject) {
var chatContext = message.chat();
when(chatContext.get('pending'))
.then(function(pending) {
if (pending) {
resolve(rule);
} else {
reject();
}
});
});
},
notPending(rule, message) {
return new Promise(function(resolve, reject) {
var chatContext = message.chat();
when(chatContext.get('pending'))
.then(function(pending) {
if (!pending) {
resolve(rule);
} else {
reject();
}
});
});
},
isVariable(rule, message) {
return new Promise(function(resolve, reject) {
var chatContext = message.chat();
when(chatContext.get(rule.variable))
.then(
function(variable) {
if (variable == rule.value) {
resolve(rule);
} else {
reject();
}
},
function() {
reject();
});
});
},
transport(rule, message) {
return new Promise(function(resolve, reject) {
if (message != null && message.payload != null) {
if (message.originalMessage.transport === rule.transport) {
resolve(rule);
} else {
reject();
}
}
});
},
messageType(rule, message) {
return new Promise(function(resolve, reject) {
if (message != null && message.payload != null) {
if ((helpers.isCommand(message.payload.content) && rule.messageType === 'command') ||
(message.payload.type === rule.messageType)) {
resolve(rule);
} else {
reject();
}
}
});
},
messageEvent(rule, message) {
return new Promise(function(resolve, reject) {
if (message != null && message.payload != null) {
if (message.payload.type === 'event' && message.payload.eventType === rule.event) {
resolve(rule);
} else {
reject();
}
}
});
},
messageAnyEvent(rule, message) {
return new Promise(function(resolve, reject) {
if (message != null && message.payload != null) {
if (message.payload.type === 'event') {
resolve(rule);
} else {
reject();
}
}
});
},
notMessageType(rule, message) {
return new Promise(function(resolve, reject) {
if (message != null && message.payload != null) {
if ((helpers.isCommand(message.payload.content) && rule.messageType === 'command') ||
(message.payload.type === rule.messageType)) {
reject();
} else {
resolve(rule);
}
}
});
},
environment(rule, message, global) {
var environment = global != null && global.environment === 'production' ? 'production' : 'development';
return new Promise(function(resolve, reject) {
if (environment === rule.environment) {
resolve(rule);
} else {
reject();
}
});
},
inbound(rule, message) {
return new Promise(function(resolve, reject) {
if (message.payload != null && message.payload.inbound === true) {
resolve(rule);
} else {
reject();
}
});
},
anyCommand(rule, message) {
return new Promise(function(resolve, reject) {
if (message.payload != null && _.isString(message.payload.content) && helpers.isCommand(message.payload.content)) {
resolve(rule);
} else {
reject();
}
});
},
commandStartsWith(rule, message) {
return new Promise(function(resolve, reject) {
if (message.payload != null && helpers.isCommandStartsWith(message.payload.content, rule.command)) {
resolve(rule);
} else {
reject();
}
});
},
command(rule, message) {
return new Promise(function(resolve, reject) {
if (message.payload != null && helpers.isCommand(message.payload.content, rule.command)) {
resolve(rule);
} else {
reject();
}
});
},
outbound(rule, message) {
return new Promise(function(resolve, reject) {
if (message.payload != null && message.payload.inbound === false) {
resolve(rule);
} else {
reject();
}
});
},
catchAll(rule) {
return new Promise(function (resolve) {
resolve(rule);
});
},
hasNotVariable(rule, message) {
return new Promise(function (resolve, reject) {
var chatContext = message.chat();
when(chatContext.get(rule.variable))
.then(
function (content) {
if (content == null) {
resolve(rule);
} else {
reject();
}
},
function () {
reject();
});
});
},
hasVariable(rule, message) {
return new Promise(function (resolve, reject) {
var chatContext = message.chat();
when(chatContext.get(rule.variable))
.then(
function (content) {
if (content != null) {
resolve(rule);
} else {
reject();
}
},
function () {
reject();
});
});
}
};
/**
* @method executeRules
* Execute a set of rules, the first rules that complies resolve the promise with argument the rule (augumented with
* the position of the rule in the list)
* @deferred
* @param {Array} rules
* @param {Object} message
* @param {Object} RED
* @param {Number} [current=1]
*/
function executeRules(rules, message, global, current) {
current = current || 1;
if (_.isEmpty(rules)) {
// if empty, means all rules failed
return new Promise(function(resolve, reject) {
reject();
});
}
var first = _.first(rules);
return new Promise(function(resolve, reject) {
// rules doesn't exist
if (!_.isFunction(Types[first.type])) {
reject();
}
// check if the first rule applies
Types[first.type](first, message, global)
.then(
function () {
var rule = _.clone(first);
rule.index = current;
resolve(rule);
},
function () {
var nextRules = _.tail(rules);
if (_.isEmpty(nextRules)) {
reject();
} else {
executeRules(nextRules, message, global, current + 1)
.then(
function(rule) {
resolve(rule);
},
function() {
reject();
}
);
}
}
);
});
}
module.exports = function(RED) {
const globalContextHelper = GlobalContextHelper(RED);
const getEnvironment = GetEnvironment(RED);
function ChatBotRules(config) {
RED.nodes.createNode(this, config);
globalContextHelper.init(this.context().global);
const node = this;
const global = {
environment: getEnvironment()
};
node.rules = config.rules;
this.on('input', function(msg) {
const rules = utils.extractValue('arrayOfObject', 'rules', node, msg, true);
executeRules(rules, msg, global)
.then(
function(rule) {
var result = new Array(rules.length);
result = _.map(result, function(value, idx) {
return idx === (rule.index - 1) ? msg : null
});
node.send(result);
},
function() {
// all rules failed, do nothing
}
);
});
}
RED.nodes.registerType('chatbot-rules', ChatBotRules);
};