UNPKG

@sammachin/node-red-dragonpbx

Version:

A Node-RED node to append JSON objects to an array in msg.callScript

194 lines (176 loc) 5.86 kB
const {fetch} = require('undici'); var mustache = require('mustache'); mustache.escape = function(text) {return text;}; // helper functions exports.appendVerb = (msg, obj) => { const data = {}; Object.keys(obj).forEach((key) => { const v = obj[key]; if (null === v || typeof v === 'undefined' || (typeof v === 'string' && !v.length) || (typeof v === 'object' && Object.keys(v).length === 0)) return; data[key] = v; }); msg.jambonz = msg.jambonz || []; msg.jambonz.push(data); } /** * resolve a value that may be either a string or a property of the msg, flow, or global context * Redundant code now replaced with new_resolve, leaving for now just in case */ exports.v_resolve= (val, valType, context, msg, asJson) => { if (!val || !valType) return val; switch (valType) { case 'str': case 'num': return val; case 'json': return JSON.parse(val); case 'msg': return asJson === true ? msg[val] : mustache.render('{{' + val + '}}', msg); } var data = {}; var dataobject = 'flow' === valType ? context.flow : context.global; if (asJson === true) return dataobject.get(val); var keys = dataobject.keys(); for (var k in keys) { data[keys[k]] = dataobject.get(keys[k]); } return mustache.render('{{' + val + '}}', data); } exports.new_resolve = async (RED, val, valtype, node, msg) => { if (!val || !valtype) return val; switch (valtype) { case 'str': case 'bool': case 'num': case 'env': case 'msg': case 'flow': case 'global': case 'jsonata': try { return await asyncEvaluateNodeProperty(RED, val, valtype, node, msg); } catch (e) { node.error(`Error evaluating ${valtype} property: ${e.message}`); return null; } case 'mustache': let data = dataobject(node.context(), msg); return mustache.render(val, data); case 'json': return JSON.parse(val); } } function asyncEvaluateNodeProperty(RED, value, type, node, msg) { return new Promise(function (resolve, reject) { RED.util.evaluateNodeProperty(value, type, node, msg, function (e, r) { if (e) { reject(e); } else { resolve(r); } }); }); } function dataobject(context, msg){ let data = Object.assign({}, msg); data.global = {}; data.flow = {}; g_keys = context.global.keys(); f_keys = context.flow.keys(); for (k in g_keys){ data.global[g_keys[k]] = context.global.get(g_keys[k]); }; for (k in f_keys){ data.flow[f_keys[k]] = context.flow.get(f_keys[k]); }; return data } exports.v_text_resolve = (node, val, context, msg) => { const flow = {}; const glob = {}; let keys = context.flow.keys(); for (const k in keys) { flow[keys[k]] = context.flow.get(keys[k]); } keys = context.global.keys(); for (const k in keys) { glob[keys[k]] = context.global.get(keys[k]); } const newString = val.trim().replace(/\${([^{}]*)}/g, (a, b) => { if (b.startsWith('msg.')) { const prop = b.slice(4); return msg[prop]; } else if (b.startsWith('flow.')) { const prop = b.slice(5); return flow[prop]; } else if (b.startsWith('global.')) { const prop = b.slice(7); return glob[prop]; } return '${' + b + '}'; }); data = {'global' : glob, 'flow' : flow, 'msg' : msg} return mustache.render(newString, data); } exports.doLCC = async (node, baseUrl, accountSid, apiToken, callSid, opts) => { const url = `${baseUrl}/v1/Accounts/${accountSid}/Calls/${callSid}`; node.log(`invoking LCC with payload ${JSON.stringify(opts)} at ${url}`); const response = await fetch(url, { method: 'POST', // TODO Should move this to PUT in next major update but will need regression testing headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiToken}` }, body: JSON.stringify(opts) }); if (!response.ok) { const error = new Error('Bad response'); error.statusCode = response.status; error.statusText = response.statusText; throw error; } const contentType = response.headers.get('content-type'); if (contentType && contentType.indexOf('application/json') !== -1) { return response.json(); } return response.text(); } exports.doCreateCall = async (node, baseUrl, accountSid, apiToken, opts) => { node.log(`invoking create call with payload ${JSON.stringify(opts)}`); const response = await fetch(`${baseUrl}/v1/Accounts/${accountSid}/Calls`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiToken}` }, body: JSON.stringify(opts) }); if (!response.ok) { const error = new Error('Bad response'); error.statusCode = response.status; error.statusText = response.statusText; throw error; } return response.json(); } exports.doCreateMessage = async (node, baseUrl, accountSid, apiToken, opts) => { node.log(`invoking create message with payload ${JSON.stringify(opts)}`); const response = await fetch(`${baseUrl}/v1/Accounts/${accountSid}/Messages`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiToken}` }, body: JSON.stringify(opts) }); if (!response.ok) { const error = new Error('Bad response'); error.statusCode = response.status; error.statusText = response.statusText; throw error; } return response.json(); }