UNPKG

@apidaze/node-red-contrib-apidaze

Version:
180 lines (146 loc) 5.19 kB
module.exports = function (RED) { 'use strict'; const jsonata = require('jsonata'); const callsDb = require('../../helpers/call-store'); const operations = { contains: (value1, value2) => value1.toString().includes(value2.toString()), notContains: (value1, value2) => !value1.toString().includes(value2.toString()), equal: (value1, value2) => value1 === value2, notEqual: (value1, value2) => value1 !== value2, regex: (value1, value2) => { const regexMatch = value2 .toString() .match(new RegExp('^/(.*?)/([gimy]*)$')); let regex; if (!regexMatch) { regex = new RegExp(value2.toString()); } else if (regexMatch.length === 1) { regex = new RegExp(regexMatch[1]); } else { regex = new RegExp(regexMatch[1], regexMatch[2]); } return !!value1.toString().match(regex); }, }; function MessageProcessor(config) { RED.nodes.createNode(this, config); this.callUuid = config.callUuid; this.matches = config.matches; let allConditionsMatch = true; this.on('input', async (msg, send, done) => { const { payload } = msg; const { hookType, body } = payload; if (hookType !== 'message') return null; try { const calls = await callsDb.fetch(this.callUuid); if (calls && calls[0]) { msg.payload.call = calls[0]; } } catch (err) { console.error('An error has occured.', payload, err); } msg.payload.message = body; const tempMessage = { ...msg.payload.message }; let hasUpdates = false; for (const match of this.matches) { const conditions = match.conditions; const properties = match.properties; const allCaseConditionsMatch = conditions.every((condition) => { const { property, propertyValueExp, operation, value, action, } = condition; const operationFunc = operations[operation]; const isPropertyMessage = property === 'text'; const isPropertyCustomString = property === 'custom_string'; const data = (() => { if (isPropertyMessage) { return tempMessage.text; } else if (isPropertyCustomString) { try { return jsonata(propertyValueExp).evaluate(msg); } catch (err) { console.error( 'An error has occured with jsonata.', payload, err ); return ''; } } return msg.payload.call[property]; })(); const operationResult = operationFunc(data, value); if (isPropertyMessage && operationResult) { if (action === 'removeMessage') { tempMessage.text = ''; } else if (action === 'removeMatch') { if (operation === 'equal') { tempMessage.text = ''; } else if (operation === 'regex') { tempMessage.text = tempMessage.text.replace(value, ''); } else if (operation === 'contains') { const regex = new RegExp(value, 'gi'); tempMessage.text = tempMessage.text.replace(regex, ''); } } } return operationResult; }); if (allCaseConditionsMatch) { msg.payload.message = tempMessage; properties.forEach((property) => { const { key, value } = property; msg.payload.call.custom[key] = value; }); if (properties.length) { hasUpdates = true; } } else { allConditionsMatch = false; } } const destinationNumber = msg.payload.message.destination_number; const flowContext = this.context().flow; const addressBook = flowContext.get('addressBook'); const contact = addressBook && (addressBook[destinationNumber] || addressBook.default); const messageStore = flowContext.get('messageStore'); if (contact) { const messageEntryKey = `${contact.mobileDestination}-${destinationNumber}`; const messageEntry = messageStore[messageEntryKey]; const associatedCallUuid = messageEntry && messageEntry.call_uuid; if (associatedCallUuid) { const calls = await callsDb.fetch(associatedCallUuid); if (calls && calls[0]) { const associatedCall = calls[0]; msg.payload.call = { ...msg.payload.call, ...associatedCall, }; } } } if (contact) { msg.payload.call.custom = { ...msg.payload.call.custom, ...contact, }; hasUpdates = true; } if (hasUpdates) { await callsDb.update(this.callsUuid, msg.payload.call); } if (allConditionsMatch) { send(msg); } else { send(null); } done(); }); } RED.nodes.registerType('message-processor', MessageProcessor); };