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
123 lines (106 loc) • 4.47 kB
JavaScript
const _ = require('lodash');
const { when, isCommand } = require('../lib/utils')
const GlobalContextHelper = require('../lib/helpers/global-context-helper');
const GetConfigurationNode = require('../lib/helpers/get-configuration-node');
module.exports = function(RED) {
const { Events } = require('./mc')(RED);
const sendMessage = (topic, payload) => {
RED.comms.publish('redbot', { topic, payload });
}
const getConfigurationNode = GetConfigurationNode(RED);
function MissionControlSimulatorReceiver(config) {
RED.nodes.createNode(this, config);
const node = this;
const globalContextHelper = GlobalContextHelper(RED);
this.chatbotId = config.chatbotId;
globalContextHelper.init(this.context().global);
const nodeGlobalKey = 'simulator_master';
let isMaster = false;
if (globalContextHelper.get(nodeGlobalKey) == null) {
isMaster = true;
globalContextHelper.set(nodeGlobalKey, node.id);
}
const handler = async (topic, message) => {
// only process simulator messages coming from the right chatbotId
if (topic === 'simulator' && message != null && message.chatbotId === node.chatbotId) {
// get the configuration node from the chatbotId
let serverNode = getConfigurationNode(message.chatbotId);
if (serverNode == null || serverNode.chat == null) {
node.error(`Unable to find a RedBot chat bot with id "${message.chatbotId}"`);
sendMessage('simulator_error', {
message: `Unable to find a RedBot chat bot with id "${message.chatbotId}"`
});
return;
}
// get simulator options from payload
const { echo = true } = message.simulatorOptions || {};
const chatServer = serverNode.chat;
const chatId = 'simulator';
const userId = String(message.userId);
const username = message.username;
const language = message.language;
const firstName = message.firstName;
const lastName = message.lastName;
const messageId = _.uniqueId('msg_');
// create blank message
const msg = await chatServer.createMessage(null, userId, messageId, {});
const context = msg.chat();
// set payload
msg.payload = {
..._.omit(message.payload, 'simulatorOptions'),
chatId,
messageId,
userId,
inbound: true
};
msg.originalMessage = {
...msg.originalMessage,
simulator: true,
userId: userId,
username: username
}
// store the message in context, also prepara arguments of command if any
let text;
if (_.isString(msg.payload.content) && !_.isEmpty(msg.payload.content)) {
text = msg.payload.content;
if (isCommand(msg.payload.content)) {
msg.payload.arguments = msg.payload.content.split(' ').slice(1);
}
}
await context.set({ username, language, firstName, lastName, message: text });
context.statics = { ...context.statics, userId }; // tricky
// send back the evaluated message so also originated messages are visible in the simulator
if (echo) {
sendMessage('simulator', {
...msg.payload,
messageId: _.uniqueId('msg_'),
transport: msg.originalMessage.transport,
userId: userId,
username: username
});
}
// check if there is a conversation is going on
const currentConversationNode = await when(context.get('simulator_currentConversationNode'));
// if there's a current converation, then the message must be forwarded
if (currentConversationNode != null) {
// if the current node is master, then redirect, if not master do nothing
if (isMaster) {
await when(context.remove('simulator_currentConversationNode'))
// emit message directly the node where the conversation stopped
RED.events.emit('node:' + currentConversationNode, msg);
}
} else {
// continue the flow
node.send(msg);
}
}
}
// listen to incoming socket messages
Events.on('message', handler);
this.on('close', done => {
Events.removeListener('message', handler);
done();
});
}
RED.nodes.registerType('mc-simulator-receiver', MissionControlSimulatorReceiver);
};