UNPKG

finesse-toolkit

Version:

useful tools for finesse phone system

194 lines 8.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const libxmljs = require("libxmljs"); const lodash_1 = require("lodash"); const Promise = require("bluebird"); const util_1 = require("../lib/util"); const DIALOG_PREFIX = '(//Dialog|//dialog)'; const USER_PREFIX = '(//User|//user)'; class XmlHelper { constructor(xml) { xml = xml.replace(/\sxmlns[^"]+"[^"]+"/g, ''); // remove namespaces try { this._parsed = libxmljs.parseXml(lodash_1.unescape(xml)).root(); } catch (e) { this._parsed = null; console.error('Could not parse XML', e, xml); } } isUser() { return !!this._parsed && !!this._parsed.get(USER_PREFIX); } isDialog() { return !!this._parsed && !!this._parsed.get(DIALOG_PREFIX); } userJson() { if (!this.isUser()) { return null; } let xml = this._parsed.get(USER_PREFIX); let reason = xml.get('./reasonCode'); let reasonObj = !reason ? null : { code: XmlHelper._safelyGet('id', { xml: reason }), label: XmlHelper._safelyGet('label', { xml: reason }) }; return { reason: reasonObj, agentState: XmlHelper._safelyGet('./state', { xml, callback: util_1.default._sanitizeState }), lastChange: XmlHelper._safelyGet('./stateChangeTime', { xml }), pendingState: XmlHelper._safelyGet('./pendingState', { xml }) }; } reasonsJson() { return this._promisedFind('/ReasonCodes/ReasonCode', this._parsed) .then(reasons => reasons.map(reason => { let opts = { xml: reason }; let getCode = { callback: data => data.substr(data.lastIndexOf('/') + 1) }; let code = XmlHelper._safelyGet('./uri', Object.assign(opts, getCode)); return { category: XmlHelper._safelyGet('./category', opts), label: XmlHelper._safelyGet('./label', opts), code }; })); } dialogJson(extension) { if (!this.isDialog()) return { dialog: false }; let dialogs = this._parsed.find(DIALOG_PREFIX).reduce((acc, dialog) => { let opts = { xml: dialog }; let agent = dialog.get(`./participants/Participant[mediaAddress = '${extension}']`); let participants = dialog.find(`./participants/Participant[mediaAddress != '${extension}']`); participants = participants.filter((participant) => { return XmlHelper._safelyGet('./state', { xml: participant, callback: util_1.default._sanitizeState }) !== 'DROPPED'; }).map((participant) => { let opts = { xml: participant, callback: util_1.default._formatPhone }; return XmlHelper._safelyGet('./mediaAddress', opts); }, []); let dialogId = XmlHelper._safelyGet('./id', opts); let phoneNumberOpts = Object.assign({}, opts, { callback: util_1.default._formatPhone }); acc[dialogId] = { dialogId, fromAddress: XmlHelper._safelyGet('./fromAddress', phoneNumberOpts), toAddress: XmlHelper._safelyGet('./toAddress', phoneNumberOpts), type: XmlHelper._safelyGet('./mediaProperties/callType', opts), start: XmlHelper._safelyGet('.//startTime', opts), lastChange: XmlHelper._safelyGet('./stateChangeTime', { xml: agent }), dialogState: XmlHelper._safelyGet('./state', { xml: agent, callback: util_1.default._sanitizeState }), participants }; return acc; }, {}); return { dialog: true, dialogs }; } _filterParticipants(participants) { let formatted = participants.filter((participant) => { return XmlHelper._safelyGet('./state', { xml: participant }); }).map((filtered) => { return XmlHelper._promisedSafelyGet('./mediaAddress', { xml: filtered }); }); return Promise.all(formatted); } _promisedFind(xpath, root) { return new Promise((resolve, reject) => { try { resolve(root.find(xpath)); } catch (e) { reject(`Couldn't find xpath: ${e}`); } }); } promisedDialogJson(extension) { if (!this.isDialog()) return Promise.resolve({ dialog: false }); let resolveValue = this._promisedFind(DIALOG_PREFIX, this._parsed).map((dialog) => { let scope = { dialogId: '', fromAddress: '', toAddress: '', type: '', start: '', lastChange: '', dialogState: '', participants: [] }; let opts = { xml: dialog }; return XmlHelper._promisedSafelyGet('./id', opts) .then((data) => { scope.dialogId = data; return this._promisedFind(`./participants/Participant[mediaAddress != '${extension}']`, dialog); }) .then(this._filterParticipants) .then((formatted) => { scope.participants = formatted; return XmlHelper._promisedSafelyGet('./fromAddress', opts); }) .then((data) => { scope.fromAddress = data; return XmlHelper._promisedSafelyGet('./toAddress', opts); }) .then((data) => { scope.toAddress = data; let type = XmlHelper._safelyGet('./mediaProperties/callType', opts); let start = XmlHelper._safelyGet('.//startTime', opts); let agent = dialog.get(`./participants/Participant[mediaAddress = '${extension}']`); let lastChange = XmlHelper._safelyGet('./stateChangeTime', { xml: agent }); let dialogState = XmlHelper._safelyGet('./state', { xml: agent, callback: util_1.default._sanitizeState }); return { dialogId: scope.dialogId, fromAddress: scope.fromAddress, toAddress: scope.toAddress, type, start, lastChange, dialogState, participants: scope.participants }; }).catch(util_1.default._promiseErrorHandler); }); let promisedDialogs = Promise.all(resolveValue).then((allDialogs) => { return allDialogs.reduce((acc, val) => { acc[val.dialogId] = val; return acc; }, {}); }).catch(util_1.default._promiseErrorHandler); return promisedDialogs.then((data) => { return { dialog: true, dialogs: data }; }).catch(util_1.default._promiseErrorHandler); } static _safelyGet(xpath, opts) { let xml = opts.xml; if (!xml) return null; let node = xml.get(xpath); let returnValue = node ? node.text() : null; return (opts && opts.callback) ? opts.callback(returnValue) : returnValue; } static _promisedSafelyGet(xpath, opts) { return new Promise((resolve, reject) => { let xml = opts.xml; if (!xml) reject('No XML object'); let node = xml.get(xpath); return node ? resolve(node.text()) : reject('Node not found'); }); } // Doesn't support nested properties (yet) static objToXml(obj) { let doc = new libxmljs.Document(); let rootNode = doc.node(obj.root); Object.keys(obj.properties).map((val) => { rootNode.node(val, obj.properties[val]); }); return rootNode.toString(); } } exports.default = XmlHelper; ; //# sourceMappingURL=index.js.map