finesse-toolkit
Version:
useful tools for finesse phone system
194 lines • 8.06 kB
JavaScript
;
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