You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
3.8 KiB
126 lines
3.8 KiB
3 years ago
|
var _ = require('underscore');
|
||
|
|
||
|
// Escape XML entites in a given string
|
||
|
function esc(str) {
|
||
|
return String(str).replace(/&/g, '&')
|
||
|
.replace(/\"/g, '"')
|
||
|
.replace(/\'/g, ''')
|
||
|
.replace(/</g, '<')
|
||
|
.replace(/>/g, '>');
|
||
|
}
|
||
|
|
||
|
//helper to generate a helper function which returns XML node for a given parent
|
||
|
function addTwimlFunction(node, twimlName) {
|
||
|
//Generate a function on the parent node
|
||
|
node[twimlName.charAt(0).toLowerCase() + twimlName.slice(1)] = function() {
|
||
|
var text, attributes, builder, legalNodes = [];
|
||
|
|
||
|
//Get XML components from the caller
|
||
|
for (var i = 0, l = arguments.length; i < l; i++) {
|
||
|
var arg = arguments[i];
|
||
|
if (typeof arg === 'string') {
|
||
|
text = arg;
|
||
|
} else if (typeof arg === 'function') {
|
||
|
builder = arg;
|
||
|
} else {
|
||
|
attributes = arg;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//determine legal sub-nodes based on the node name
|
||
|
switch(twimlName) {
|
||
|
case 'Gather': legalNodes = ['Say','Play','Pause']; break;
|
||
|
case 'Dial': legalNodes = ['Number','Client','Conference','Queue','Sip']; break;
|
||
|
case 'Message': legalNodes = ['Media', 'Body']; break;
|
||
|
case 'Enqueue': legalNodes = ['Task']; break;
|
||
|
default: break;
|
||
|
}
|
||
|
|
||
|
//create new node object
|
||
|
var newNode = new Node({
|
||
|
name:twimlName,
|
||
|
attributes:attributes,
|
||
|
text:text,
|
||
|
legalNodes:legalNodes
|
||
|
});
|
||
|
|
||
|
//create node's API for subnodes and call builder function, if need be
|
||
|
if (!text && legalNodes.length > 0 && builder) {
|
||
|
legalNodes.forEach(function(legalNodeName) {
|
||
|
addTwimlFunction(newNode, legalNodeName);
|
||
|
});
|
||
|
builder.call(newNode, newNode);
|
||
|
}
|
||
|
|
||
|
//Assemble the proper XML node and add to parent node
|
||
|
node.children.push(newNode);
|
||
|
|
||
|
//return the node, to allow for chaining
|
||
|
return node;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
A TwiML response node - nestable with other TwiML nodes
|
||
|
|
||
|
@param {object} config - options for HTTP request
|
||
|
- name {string}: name of this node
|
||
|
- attributes {object}: key-value pairs for XML attributes for this node
|
||
|
- text {string}: text content, if any, for this node
|
||
|
- topLevel {boolean}: indicates a top level node which should also print an XML instruction
|
||
|
- legalNodes {array<string>}: a list of child functions which should be allowable for this node
|
||
|
*/
|
||
|
function Node(config) {
|
||
|
_.extend(this,config);
|
||
|
this.children = [];
|
||
|
|
||
|
//create child adder functions based on legal nodes
|
||
|
var that = this;
|
||
|
this.legalNodes.forEach(function(val) {
|
||
|
addTwimlFunction(that,val);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
//Output the contents of this XML node as a string
|
||
|
Node.prototype.toString = function() {
|
||
|
var buffer = [];
|
||
|
if (this.topLevel) {
|
||
|
buffer.push('<?xml version="1.0" encoding="UTF-8"?>');
|
||
|
}
|
||
|
|
||
|
//Start node
|
||
|
buffer.push('<'+this.name);
|
||
|
|
||
|
//handle attributes
|
||
|
for (var attr in this.attributes) {
|
||
|
buffer.push(' ' + attr + '="' + esc(this.attributes[attr]) + '"');
|
||
|
}
|
||
|
|
||
|
//Close start tag
|
||
|
buffer.push('>');
|
||
|
|
||
|
//process contents of tag
|
||
|
if (this.text) {
|
||
|
buffer.push(esc(this.text));
|
||
|
} else {
|
||
|
//process child tags
|
||
|
for (var i = 0, l = this.children.length; i < l; i++) {
|
||
|
buffer.push(this.children[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//close tag
|
||
|
buffer.push('</'+this.name+'>');
|
||
|
|
||
|
return buffer.join('');
|
||
|
};
|
||
|
|
||
|
//Public interface is a Response node with the initial set of TwiML child nodes available
|
||
|
module.exports = function() {
|
||
|
return new Node({
|
||
|
topLevel:true,
|
||
|
name:'Response',
|
||
|
legalNodes:['Say', 'Play', 'Gather', 'Record', 'Sms', 'Dial', 'Enqueue', 'Task', 'Leave', 'Hangup', 'Redirect', 'Reject', 'Pause', 'Message']
|
||
|
});
|
||
|
};
|