feat(signalwire): add add-voice-xml-node and respond-with-voice-xml actions
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import { XMLBuilder } from 'fast-xml-parser';
|
||||
import defineAction from '../../../../helpers/define-action.js';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Add voice XML node',
|
||||
key: 'addVoiceXmlNode',
|
||||
description: 'Add a voice XML node in the XML document',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Node name',
|
||||
key: 'nodeName',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'The name of the node to be added.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Node value',
|
||||
key: 'nodeValue',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'The value of the node to be added.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Attributes',
|
||||
key: 'attributes',
|
||||
type: 'dynamic',
|
||||
required: false,
|
||||
description: 'Add or remove attributes for the node as needed',
|
||||
value: [
|
||||
{
|
||||
key: '',
|
||||
value: '',
|
||||
},
|
||||
],
|
||||
fields: [
|
||||
{
|
||||
label: 'Attribute name',
|
||||
key: 'key',
|
||||
type: 'string',
|
||||
required: false,
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Attribute value',
|
||||
key: 'value',
|
||||
type: 'string',
|
||||
required: false,
|
||||
variables: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Add children node',
|
||||
key: 'hasChildrenNodes',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: 'Add a nested node to the main node',
|
||||
value: false,
|
||||
options: [
|
||||
{ label: 'Yes', value: true },
|
||||
{ label: 'No', value: false },
|
||||
],
|
||||
additionalFields: {
|
||||
type: 'query',
|
||||
name: 'getDynamicFields',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listNodeFields',
|
||||
},
|
||||
{
|
||||
name: 'nodeIndex',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: 'parameters.hasChildrenNodes',
|
||||
value: '{parameters.hasChildrenNodes}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const nodeName = $.step.parameters.nodeName;
|
||||
const nodeValue = $.step.parameters.nodeValue;
|
||||
const attributes = $.step.parameters.attributes;
|
||||
const childrenNodes = $.step.parameters.childrenNodes;
|
||||
const hasChildrenNodes = $.step.parameters.hasChildrenNodes;
|
||||
|
||||
const builder = new XMLBuilder({
|
||||
ignoreAttributes: false,
|
||||
suppressEmptyNode: true,
|
||||
preserveOrder: true,
|
||||
});
|
||||
|
||||
const computeAttributes = (attributes) =>
|
||||
attributes
|
||||
.filter((attribute) => attribute.key || attribute.value)
|
||||
.reduce(
|
||||
(result, attribute) => ({
|
||||
...result,
|
||||
[`@_${attribute.key}`]: attribute.value,
|
||||
}),
|
||||
{}
|
||||
);
|
||||
|
||||
const computeTextNode = (nodeValue) => ({
|
||||
'#text': nodeValue,
|
||||
});
|
||||
|
||||
const computedChildrenNodes = hasChildrenNodes
|
||||
? childrenNodes.map((childNode) => ({
|
||||
[childNode.nodeName]: [computeTextNode(childNode.nodeValue)],
|
||||
':@': computeAttributes(childNode.attributes),
|
||||
}))
|
||||
: [];
|
||||
|
||||
const xmlObject = {
|
||||
[nodeName]: [computeTextNode(nodeValue), ...computedChildrenNodes],
|
||||
':@': computeAttributes(attributes),
|
||||
};
|
||||
|
||||
const xmlString = builder.build([xmlObject]);
|
||||
|
||||
$.setActionItem({ raw: { stringNode: xmlString } });
|
||||
},
|
||||
});
|
||||
@@ -1,3 +1,5 @@
|
||||
import sendSms from './send-sms/index.js';
|
||||
import addVoiceXmlNode from './add-voice-xml-node/index.js';
|
||||
import respondWithVoiceXml from './respond-with-voice-xml/index.js';
|
||||
|
||||
export default [sendSms];
|
||||
export default [addVoiceXmlNode, respondWithVoiceXml, sendSms];
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
|
||||
import defineAction from '../../../../helpers/define-action.js';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Respond with voice XML',
|
||||
key: 'respondWithVoiceXml',
|
||||
description: 'Respond with defined voice XML document',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Nodes',
|
||||
key: 'nodes',
|
||||
type: 'dynamic',
|
||||
required: false,
|
||||
description: 'Add or remove nodes for the XML document as needed',
|
||||
value: [
|
||||
{
|
||||
nodeString: '',
|
||||
},
|
||||
],
|
||||
fields: [
|
||||
{
|
||||
label: 'Node',
|
||||
key: 'nodeString',
|
||||
type: 'string',
|
||||
required: true,
|
||||
variables: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const builder = new XMLBuilder({
|
||||
ignoreAttributes: false,
|
||||
suppressEmptyNode: true,
|
||||
preserveOrder: true,
|
||||
});
|
||||
|
||||
const parser = new XMLParser({
|
||||
ignoreAttributes: false,
|
||||
preserveOrder: true,
|
||||
parseTagValue: false,
|
||||
});
|
||||
|
||||
const nodes = $.step.parameters.nodes;
|
||||
const computedNodes = nodes.map((node) => node.nodeString);
|
||||
const parsedNodes = computedNodes.flatMap((computedNode) =>
|
||||
parser.parse(computedNode)
|
||||
);
|
||||
|
||||
const xmlString = builder.build([
|
||||
{
|
||||
Response: parsedNodes,
|
||||
},
|
||||
]);
|
||||
|
||||
$.setActionItem({
|
||||
raw: {
|
||||
body: xmlString,
|
||||
statusCode: 200,
|
||||
headers: { 'content-type': 'text/xml' },
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,3 @@
|
||||
import listNodeFields from './list-node-fields/index.js';
|
||||
|
||||
export default [listNodeFields];
|
||||
@@ -0,0 +1,75 @@
|
||||
export default {
|
||||
name: 'List node fields',
|
||||
key: 'listNodeFields',
|
||||
|
||||
async run($) {
|
||||
const hasChildrenNodes = $.step.parameters.hasChildrenNodes;
|
||||
|
||||
if (!hasChildrenNodes) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
label: 'Children nodes',
|
||||
key: 'childrenNodes',
|
||||
type: 'dynamic',
|
||||
required: false,
|
||||
description: 'Add or remove nested node as needed',
|
||||
value: [
|
||||
{
|
||||
key: 'Content-Type',
|
||||
value: 'application/json',
|
||||
},
|
||||
],
|
||||
fields: [
|
||||
{
|
||||
label: 'Node name',
|
||||
key: 'nodeName',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'The name of the node to be added.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Node value',
|
||||
key: 'nodeValue',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'The value of the node to be added.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Attributes',
|
||||
key: 'attributes',
|
||||
type: 'dynamic',
|
||||
required: false,
|
||||
description: 'Add or remove attributes for the node as needed',
|
||||
value: [
|
||||
{
|
||||
key: '',
|
||||
value: '',
|
||||
},
|
||||
],
|
||||
fields: [
|
||||
{
|
||||
label: 'Attribute name',
|
||||
key: 'key',
|
||||
type: 'string',
|
||||
required: false,
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Attribute value',
|
||||
key: 'value',
|
||||
type: 'string',
|
||||
required: false,
|
||||
variables: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
},
|
||||
};
|
||||
@@ -4,6 +4,7 @@ import auth from './auth/index.js';
|
||||
import triggers from './triggers/index.js';
|
||||
import actions from './actions/index.js';
|
||||
import dynamicData from './dynamic-data/index.js';
|
||||
import dynamicFields from './dynamic-fields/index.js';
|
||||
|
||||
export default defineApp({
|
||||
name: 'SignalWire',
|
||||
@@ -19,4 +20,5 @@ export default defineApp({
|
||||
triggers,
|
||||
actions,
|
||||
dynamicData,
|
||||
dynamicFields,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user