@jambonz/node-red-contrib-jambonz 2.2.73 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/examples/Authenticating sip devices.json +1 -0
  2. package/examples/Conference with LCC.json +1 -0
  3. package/{src/examples → examples}/Connecting to a dialogflow bot.json +0 -0
  4. package/examples/Create Call and Send DTMF.json +1 -0
  5. package/examples/Get Log Data.json +1 -0
  6. package/examples/Leave Queue.json +1 -0
  7. package/examples/SIP Responses.json +1 -0
  8. package/{src/examples → examples}/SIP trunking outbound call.json +0 -0
  9. package/examples/Simple IVR.json +1 -0
  10. package/examples/Simple Queue.json +1 -0
  11. package/examples/Using Redirect.json +1 -0
  12. package/examples/Voicemail using Listen into S3 bucket.json +130 -0
  13. package/examples/config.json +1 -0
  14. package/examples/gather.json +1 -0
  15. package/examples/lex.json +1 -0
  16. package/examples/messages.json +1 -0
  17. package/examples/rasa.json +1 -0
  18. package/examples/tag a call.json +1 -0
  19. package/package.json +52 -14
  20. package/resources/editor.js +414 -0
  21. package/src/data/recognizer.json +685 -1
  22. package/src/data/tts.json +2970 -1
  23. package/src/nodes/auth.html +108 -0
  24. package/src/nodes/auth.js +43 -0
  25. package/src/nodes/conference.html +121 -0
  26. package/src/nodes/conference.js +31 -0
  27. package/src/nodes/config.html +484 -0
  28. package/src/nodes/config.js +74 -0
  29. package/src/nodes/create_call.html +287 -0
  30. package/src/nodes/create_call.js +104 -0
  31. package/src/nodes/create_sms.html +106 -0
  32. package/src/nodes/create_sms.js +65 -0
  33. package/src/nodes/dequeue.html +102 -0
  34. package/src/nodes/dequeue.js +25 -0
  35. package/src/nodes/dial.html +619 -0
  36. package/src/nodes/dial.js +138 -0
  37. package/src/nodes/dialogflow.html +260 -0
  38. package/src/nodes/dialogflow.js +53 -0
  39. package/src/nodes/dtmf.html +74 -0
  40. package/src/nodes/dtmf.js +22 -0
  41. package/src/nodes/enqueue.html +90 -0
  42. package/src/nodes/enqueue.js +25 -0
  43. package/src/nodes/gather.html +322 -0
  44. package/src/nodes/gather.js +83 -0
  45. package/src/nodes/get_alerts.html +94 -0
  46. package/src/nodes/get_alerts.js +47 -0
  47. package/src/nodes/get_calls.html +59 -0
  48. package/src/nodes/get_calls.js +38 -0
  49. package/src/nodes/get_recent_calls.html +95 -0
  50. package/src/nodes/get_recent_calls.js +47 -0
  51. package/src/nodes/hangup.html +46 -0
  52. package/src/nodes/hangup.js +20 -0
  53. package/src/nodes/jambonz.html +63 -38
  54. package/src/nodes/lcc.html +256 -0
  55. package/src/nodes/lcc.js +102 -0
  56. package/src/nodes/leave.html +40 -0
  57. package/src/nodes/leave.js +21 -0
  58. package/src/nodes/lex.html +264 -0
  59. package/src/nodes/lex.js +75 -0
  60. package/src/nodes/libs.js +99 -0
  61. package/src/nodes/listen.html +341 -0
  62. package/src/nodes/listen.js +82 -0
  63. package/src/nodes/message.html +95 -0
  64. package/src/nodes/message.js +32 -0
  65. package/src/nodes/pause.html +62 -0
  66. package/src/nodes/pause.js +25 -0
  67. package/src/nodes/play.html +76 -0
  68. package/src/nodes/play.js +23 -0
  69. package/src/nodes/rasa.html +106 -0
  70. package/src/nodes/rasa.js +22 -0
  71. package/src/nodes/redirect.html +64 -0
  72. package/src/nodes/redirect.js +24 -0
  73. package/src/nodes/s3-upload.html +29 -14
  74. package/src/nodes/s3-upload.js +24 -9
  75. package/src/nodes/say.html +115 -0
  76. package/src/nodes/say.js +38 -0
  77. package/src/nodes/sip-decline.html +76 -0
  78. package/src/nodes/sip-decline.js +25 -0
  79. package/src/nodes/sip-refer.html +116 -0
  80. package/src/nodes/sip-refer.js +33 -0
  81. package/src/nodes/sip-request.html +96 -0
  82. package/src/nodes/sip-request.js +36 -0
  83. package/src/nodes/tag.html +60 -0
  84. package/src/nodes/tag.js +22 -0
  85. package/src/nodes/template.html +63 -0
  86. package/src/nodes/template.js +9 -0
  87. package/src/nodes/userauth.html +85 -0
  88. package/src/nodes/userauth.js +70 -0
  89. package/src/nodes/webhooks.js +0 -16
  90. package/src/utils/http-helpers.js +68 -0
  91. package/src/examples/Authenticating sip devices.json +0 -10
  92. package/src/nodes/http-helpers.js +0 -26
  93. package/src/nodes/jambonz.js +0 -1044
@@ -0,0 +1,25 @@
1
+ var {createHash} = require('crypto');
2
+ const bent = require('bent');
3
+ var mustache = require('mustache');
4
+ mustache.escape = function(text) {return text;};
5
+ var {appendVerb, v_resolve} = require('./libs')
6
+
7
+ module.exports = function(RED) {
8
+ /** dequeue */
9
+ function dequeue(config) {
10
+ RED.nodes.createNode(this, config);
11
+ var node = this;
12
+ node.on('input', function(msg, send, done) {
13
+ appendVerb(msg, {
14
+ verb: 'dequeue',
15
+ name: v_resolve(config.queue, config.queueType, this.context(), msg),
16
+ beep: config.beep,
17
+ actionHook: v_resolve(config.actionHook, config.actionHookType, this.context(), msg),
18
+ confirmHook: v_resolve(config.confirmHook, config.confirmHookType, this.context(), msg),
19
+ timeout: v_resolve(config.timeout, config.timeoutType, this.context(), msg)
20
+ });
21
+ node.send(msg);
22
+ });
23
+ }
24
+ RED.nodes.registerType('dequeue', dequeue);
25
+ }
@@ -0,0 +1,619 @@
1
+ <!-- Javascript -->
2
+ <script type="text/javascript">
3
+ RED.nodes.registerType('dial',{
4
+ category: 'jambonz',
5
+ color: '#bbabaa',
6
+ defaults: {
7
+ name: {value: ''},
8
+ targets:{value:[{type: 'phone', dest: '', user: '', pass: '', varType: 'str', trunk: ''}]},
9
+ headers: {value: []},
10
+ actionhook: {value: ''},
11
+ actionhookType: {value: 'str'},
12
+ answeronbridge: {value: false},
13
+ callerid: {value: ''},
14
+ calleridType: {value: ''},
15
+ confirmhook: {value: ''},
16
+ confirmhookType: {value: 'str'},
17
+ dialmusic: {value: ''},
18
+ dialmusicType: {value: 'str'},
19
+ dtmfcapture: {value: ''},
20
+ dtmfcaptureType: {value: 'str'},
21
+ dtmfhook: {value: ''},
22
+ dtmfhookType: {value: 'str'},
23
+ timelimit: {validate:RED.validators.regex(/^\d*$/) },
24
+ timeout: {validate:RED.validators.regex(/^\d*$/) },
25
+ listenurl: {value: ''},
26
+ listenurlType: {value: 'str'},
27
+ transcriptionhook: {},
28
+ transcriptionhookType: {value: 'str'},
29
+ transcriptionvendor: {value: 'default'},
30
+ recognizerlang: {value: 'default'},
31
+ recognizeraltlang: {},
32
+ recognizeraltlangType: {val: 'str'},
33
+ interim: {value: false},
34
+ profanityfilter: {value: false},
35
+ transcriptionhints: {},
36
+ transcriptionhintsType: {val: 'str'},
37
+ separaterecog: {value: false},
38
+ useenhanced: {value: false},
39
+ words: {value: false},
40
+ punctuation: {value: false},
41
+ diarization: {value: false},
42
+ diarizationmin: {value: 2},
43
+ diarizationminType: {value: 'num'},
44
+ diarizationmax: {value: 6},
45
+ diarizationmaxType: {value: 'num'},
46
+ interactiontype: {value: 'unspecified'},
47
+ naics: {value: 0},
48
+ naicsType: {value: 'num'},
49
+ identifychannels: {value: false},
50
+ speakerlabel: {value: false},
51
+ vocabularyname: {},
52
+ vocabularynameType: {value: 'str'},
53
+ vocabularyfiltername: {},
54
+ vocabularyfilternameType: {value: 'str'},
55
+ vocabularyfiltermethod: {}
56
+ },
57
+ inputs:1,
58
+ outputs:1,
59
+ icon: "font-awesome/fa-cubes",
60
+ label: function() { return this.name || 'dial';},
61
+ oneditprepare: function() {
62
+ var node = this;
63
+ $('#node-input-callerid').typedInput({
64
+ types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
65
+ typeField: $('#node-input-calleridType')
66
+ });
67
+ $('#node-input-actionhook').typedInput({
68
+ types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
69
+ typeField: $('#node-input-actionhookType')
70
+ });
71
+ $('#node-input-confirmhook').typedInput({
72
+ types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
73
+ typeField: $('#node-input-confirmhookType')
74
+ });
75
+ $('#node-input-dialmusic').typedInput({
76
+ types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
77
+ typeField: $('#node-input-dialmusicType')
78
+ });
79
+ $('#node-input-dtmfcapture').typedInput({
80
+ types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
81
+ typeField: $('#node-input-dtmfcaptureType')
82
+ });
83
+ $('#node-input-dtmfhook').typedInput({
84
+ types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
85
+ typeField: $('#node-input-dtmfhookType')
86
+ });
87
+ $('#node-input-transcribeurl').typedInput({
88
+ types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
89
+ typeField: $('#node-input-transcribeurlType')
90
+ });
91
+ $('#node-input-listenurl').typedInput({
92
+ types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
93
+ typeField: $('#node-input-listenurlType')
94
+ });
95
+ $('#node-input-transcriptionhook').typedInput({
96
+ types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
97
+ typeField: $('#node-input-transcriptionhookType')
98
+ });
99
+ $('#node-input-transcriptionhints').typedInput({
100
+ types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
101
+ typeField: $('#node-input-transcriptionhintsType')
102
+ });
103
+ $('#node-input-recognizeraltlang').typedInput({
104
+ types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
105
+ typeField: $('#node-recognizeraltlangType')
106
+ });
107
+ $('#node-input-diarizationmin').typedInput({
108
+ types: ['num', 'msg', 'flow', 'global', 'jsonata', 'env'],
109
+ typeField: $('#node-input-diarizationminType')
110
+ });
111
+ $('#node-input-diarizationmax').typedInput({
112
+ types: ['num', 'msg', 'flow', 'global', 'jsonata', 'env'],
113
+ typeField: $('#node-input-diarizationmaxType')
114
+ });
115
+ $('#node-input-naics').typedInput({
116
+ types: ['num', 'msg', 'flow', 'global', 'jsonata', 'env'],
117
+ typeField: $('#node-input-naicsType')
118
+ });
119
+
120
+ console.log('oneditprepare - dial');
121
+ prepareSttControls(node);
122
+
123
+ $('#node-input-target-container').css('min-height','180px').css('min-width','450px').editableList({
124
+ addItem: function(container, i, opt) {
125
+ var target = opt;
126
+ console.log(`addItem: ${JSON.stringify(opt)}, keys ${Object.keys(opt).length}`);
127
+ if (!target.hasOwnProperty('type')) {
128
+ target = {
129
+ type: 'phone',
130
+ dest: '',
131
+ user: '',
132
+ pass: '',
133
+ varType: 'str'
134
+ };
135
+ }
136
+
137
+ container.css({
138
+ overflow: 'hidden',
139
+ whiteSpace: 'nowrap'
140
+ });
141
+ let fragment = document.createDocumentFragment();
142
+ var row1 = $('<div/>',{style:"display:flex;"}).appendTo(fragment);
143
+ var row2 = $('<div/>',{style:"display:flex;margin-top:8px;"}).appendTo(fragment);
144
+ var row3 = $('<div/>',{style:"margin-top:8px;"}).appendTo(fragment);
145
+ var row4 = $('<div/>',{style:"display:flex;margin-top:8px;"}).appendTo(fragment);
146
+ var row5 = $('<div/>',{style:"margin-top:8px;"}).appendTo(fragment);
147
+
148
+ var selectField = $('<select/>',{class:"node-input-target-type",style:"width:110px; margin-right:10px;"})
149
+ .appendTo(row1);
150
+ var selectOptions = ['phone', 'user', 'sip', 'teams'];
151
+ for (var i = 0; i < 4; i++) {
152
+ selectField.append($("<option></option>").val(selectOptions[i]).text(selectOptions[i]));
153
+ }
154
+ var propertyName = $('<input/>', {class:"node-input-target-property-name", type:"text"})
155
+ .appendTo(row1)
156
+ .typedInput({types: ['str', 'msg', 'flow', 'global']});
157
+
158
+ $('<label style="padding-top:8px; padding-right:20px">Auth Username:</label>')
159
+ .appendTo(row2);
160
+
161
+ $('<input/>',{
162
+ class:"node-input-target-property-authuser",
163
+ type:"text",
164
+ placeholder: '(if required by remote endpoint)'
165
+ })
166
+ .appendTo(row2);
167
+
168
+ $('<label style="padding-top:8px; padding-right:20px">Auth Password:</label>')
169
+ .appendTo(row3);
170
+ $('<input/>',{
171
+ class:"node-input-target-property-authpassword",
172
+ type:"text",
173
+ placeholder: '(if required by remote endpoint)'
174
+ })
175
+ .appendTo(row3);
176
+
177
+ $('<label style="padding-top:8px; padding-right:20px">Trunk:</label>')
178
+ .appendTo(row5);
179
+
180
+ $('<input/>',{
181
+ class:"node-input-target-property-trunk",
182
+ type:"text",
183
+ placeholder: 'Specify the name of the trunk used for this outbound call'
184
+ })
185
+ .appendTo(row5);
186
+
187
+ selectField.on('change', function() {
188
+ var type = $(this).val();
189
+ console.log(`type changed to ${type}`);
190
+ var input = $(this).parent().find('input.red-ui-typedInput-input');
191
+ input.focus();
192
+ switch (type) {
193
+ case 'phone':
194
+ input.attr('placeholder', 'E.164 number to dial');
195
+ break;
196
+ case 'teams':
197
+ input.attr('placeholder', 'Microsoft Teams phone number or extension');
198
+ break;
199
+ case 'user':
200
+ input.attr('placeholder', 'user@domain');
201
+ break;
202
+ case 'sip':
203
+ input.attr('placeholder', 'sip:number@ip-address');
204
+ break;
205
+ }
206
+ if (type !== 'sip') {
207
+ row2.hide();
208
+ row3.hide();
209
+ }
210
+ else {
211
+ row2.show();
212
+ row3.show();
213
+ }
214
+
215
+ if(type !== 'phone') {
216
+ row5.hide();
217
+ } else {
218
+ row5.show();
219
+ }
220
+ });
221
+ selectField.val(target.type);
222
+ propertyName.typedInput('value', target.dest);
223
+ propertyName.typedInput('type', target.varType);
224
+
225
+ var datafield = row1.find('.node-input-target-property-name');
226
+ var userfield = row2.find('.node-input-target-property-authuser');
227
+ var passfield = row3.find('.node-input-target-property-authpassword');
228
+ var trunkfield = row5.find('.node-input-target-property-trunk');
229
+
230
+ datafield.typedInput('type', target.varType);
231
+
232
+ switch (target.type) {
233
+ case 'phone':
234
+ trunkfield.val(target.trunk);
235
+ case 'sip':
236
+ userfield.val(target.user);
237
+ passfield.val(target.pass);
238
+ default:
239
+ datafield.typedInput('value', target.dest);
240
+ break;
241
+ }
242
+ selectField.change();
243
+ container[0].appendChild(fragment);
244
+ },
245
+ removable: true,
246
+ addButton: 'add target'
247
+ });
248
+ console.log(`oneditprepare: coming in with targets: ${JSON.stringify(this.targets)}`);
249
+ if (!this.targets) {
250
+ var target = {
251
+ type: 'phone',
252
+ dest: '',
253
+ user: '',
254
+ pass: '',
255
+ trunk: '',
256
+ varType: 'str'
257
+ }
258
+ this.targets = [target];
259
+ }
260
+
261
+ for (var i=0; i < this.targets.length; i++) {
262
+ var target = this.targets[i];
263
+ $("#node-input-target-container").editableList('addItem', target);
264
+ }
265
+ // populate headers editable list
266
+ $('#node-input-headers-container').css('min-height','120px').css('min-width','450px').editableList({
267
+ addItem: function(container, i, opt) {
268
+ var header = opt;
269
+ if (!header.hasOwnProperty('h')) {
270
+ header = {h: '', v: ''};
271
+ }
272
+ container.css({
273
+ overflow: 'hidden',
274
+ whiteSpace: 'nowrap'
275
+ });
276
+ let fragment = document.createDocumentFragment();
277
+ var row1 = $('<div/>',{style:"display:flex;"}).appendTo(fragment);
278
+ $('<input/>', {
279
+ class:"node-input-header-property-name",
280
+ type:"text",
281
+ placeholder: 'SIP Header'
282
+ })
283
+ .appendTo(row1);
284
+ $('<input/>', {
285
+ class:"node-input-value-property-name",
286
+ type:"text",
287
+ placeholder: 'value'
288
+ })
289
+ .appendTo(row1);
290
+
291
+ row1.find('.node-input-header-property-name').val(header.h);
292
+ row1.find('.node-input-value-property-name').val(header.v);
293
+
294
+ container[0].appendChild(fragment);
295
+ },
296
+ removable: true
297
+ });
298
+ console.log(`oneditprepare: coming in with headers: ${JSON.stringify(this.headers)}`);
299
+ if (!this.headers) {
300
+ var header = {
301
+ h: '',
302
+ v: '',
303
+ };
304
+ this.headers = [header];
305
+ }
306
+
307
+ for (var i=0; i < this.headers.length; i++) {
308
+ var header = this.headers[i];
309
+ $("#node-input-headers-container").editableList('addItem', header);
310
+ }
311
+ },
312
+ oneditsave: function () {
313
+ var targets = $("#node-input-target-container").editableList('items');
314
+ var node = this;
315
+ node.targets = [];
316
+ console.log(`entering oneditsave with ${targets.length} targets`);
317
+ targets.each(function(i) {
318
+ var target = $(this);
319
+ var type = target.find('.node-input-target-type').val();
320
+ var varType = target.find('.node-input-target-property-name').typedInput('type');
321
+ var dest = target.find('.node-input-target-property-name').typedInput('value');
322
+ var user = target.find('.node-input-target-property-authuser').val();
323
+ var pass = target.find('.node-input-target-property-authpassword').val();
324
+ var trunk = target.find('.node-input-target-property-trunk').val();
325
+ if (!['phone', 'user', 'sip', 'teams'].includes(type) || 0 === dest.length) return;
326
+
327
+ var t = {
328
+ type,
329
+ varType,
330
+ dest
331
+ };
332
+ if ('sip' === type && user.length > 0 && pass.length > 0) {
333
+ Object.assign(t, {user, pass});
334
+ }
335
+ if ('phone' === type && trunk.length > 0) {
336
+ t.trunk = trunk;
337
+ }
338
+ node.targets.push(t);
339
+ });
340
+ console.log(`saved targets ${JSON.stringify(node.targets)}`);
341
+ var headers = [];
342
+ $("#node-input-headers-container").editableList('items').each(function(i) {
343
+ var header = $(this);
344
+ console.log(`header: ${JSON.stringify(header)}`);
345
+ var h = header.find(".node-input-header-property-name").val();
346
+ var v = header.find(".node-input-value-property-name").val();
347
+ console.log(`added ${h}: ${v}`);
348
+ var obj = {};
349
+ obj[h] = v;
350
+ headers.push({h, v});
351
+ });
352
+ node.headers = headers;
353
+ console.log(`saved headers ${JSON.stringify(node.headers)}`);
354
+ },
355
+ });
356
+
357
+
358
+ </script>
359
+
360
+
361
+ <!-- HTML -->
362
+
363
+ <script type="text/html" data-template-name="dial">
364
+ <style>
365
+ ol#node-input-target-container .red-ui-typedInput-container {
366
+ flex:1;
367
+ }
368
+ </style>
369
+ <div class="form-row">
370
+ <label for="node-input-name"><i class="icon-tag"></i> Name</label>
371
+ <input type="text" id="node-input-name" placeholder="Name">
372
+ </div>
373
+ <div class="form-row" style="margin-bottom:0;">
374
+ <label><i class="fa fa-list"></i><span>Dial Targets</span></label>
375
+ </div>
376
+ <div class="form-row node-input-target-container-row">
377
+ <ol id="node-input-target-container"></ol>
378
+ </div>
379
+ <div class="form-row">
380
+ <label for="node-input-actionhook">Action hook</label>
381
+ <input type="text" id="node-input-actionhook" placeholder="webhook to invoke when the call ends">
382
+ <input type="hidden" id="node-input-actionhookType">
383
+ </div>
384
+ <div class="form-row">
385
+ <label for="node-input-answeronbridge">Answer on bridge</label>
386
+ <input type="checkbox" id="node-input-answeronbridge">
387
+ </div>
388
+ <div class="form-row">
389
+ <label for="node-input-callerid">Caller ID</label>
390
+ <input type="text" id="node-input-callerid" placeholder="Caller ID to place on outbound call">
391
+ <input type="hidden" id="node-input-calleridType">
392
+ </div>
393
+ <div class="form-row">
394
+ <label for="node-input-confirmhook">Confirm hook</label>
395
+ <input type="text" id="node-input-confirmhook" placeholder="webhook to run on called party after answer">
396
+ <input type="hidden" id="node-input-confirmhookType">
397
+ </div>
398
+ <div class="form-row">
399
+ <label for="node-input-dialmusic">Dial music</label>
400
+ <input type="text" id="node-input-dialmusic" placeholder="url to .wav or .mp3 file to play during dial">
401
+ <input type="hidden" id="node-input-dialMusicType">
402
+ </div>
403
+ <div class="form-row">
404
+ <label for="node-input-dtmfcapture">Dtmf capture</label>
405
+ <input type="text" id="node-input-dtmfcapture" placeholder="comma-separated list of dtmf captures">
406
+ <input type="hidden" id="node-input-dtmfcaptureType">
407
+ </div>
408
+ <div class="form-row">
409
+ <label for="node-input-dtmfhook">Dtmf hook</label>
410
+ <input type="text" id="node-input-dtmfhook" placeholder="webhook to call when dtmf is captured">
411
+ <input type="hidden" id="node-input-dtmfhookType">
412
+ </div>
413
+ <div class="form-row">
414
+ <label for="node-input-timelimit">Time limit</label>
415
+ <input type="text" id="node-input-timelimit" placeholder="max duration of call in secs">
416
+ </div>
417
+ <div class="form-row">
418
+ <label for="node-input-timeout"><i class="icon-tag"></i> Timeout</label>
419
+ <input type="text" id="node-input-timeout" placeholder="ring no answer timeout in secs (default: 60)">
420
+ </div>
421
+ <fieldset>
422
+ <legend>Live audio</legend>
423
+ <div class="form-row">
424
+ <label for="node-input-listenurl"><i class="icon-tag"></i> Websocket server url</label>
425
+ <input type="text" id="node-input-listenurl" placeholder="ws://example.com">
426
+ <input type="hidden" id="node-input-listenurlType">
427
+ </div>
428
+ </fieldset>
429
+ <fieldset>
430
+ <legend>Transcription (optional)</legend>
431
+ <div class="form-row">
432
+ <label for="node-input-transcriptionhook"><i class="icon-tag"></i> Transcription hook</label>
433
+ <input type="text" id="node-input-transcriptionhook" placeholder="transcription webhook">
434
+ <input type="hidden" id="node-input-transcriptionhookType">
435
+ </div>
436
+ <div class="form-row">
437
+ <label for="node-input-transcriptionvendor">Vendor</label>
438
+ <select id="node-input-transcriptionvendor">
439
+ <option value="default" selected>--application default--</option>
440
+ <option value="google">Google</option>
441
+ <option value="aws">AWS</option>
442
+ <option value="deepgram">deepgram</option>
443
+ <option value="microsoft">microsoft</option>
444
+ <option value="ibm">ibm</option>
445
+ <option value="nuance">nuance</option>
446
+ </select>
447
+ </div>
448
+ <div class="form-row">
449
+ <label for="node-input-recognizerlang"><i class="icon-tag"></i> Language</label>
450
+ <select id="node-input-recognizerlang">
451
+ </select>
452
+ </div>
453
+ <div id="interim" class="form-row">
454
+ <label for="node-input-interim">Interim transcriptions</label>
455
+ <input type="checkbox" id="node-input-interim">
456
+ </div>
457
+ <div id="stt-identify-channels" class="form-row">
458
+ <label for="node-input-separaterecog">Separate recognition per channel</label>
459
+ <input type="checkbox" id="node-input-separaterecog">
460
+ </div>
461
+ <div id="google-stt-options">
462
+ <legend>Google Transcription Options</legend>
463
+ <div class="form-row">
464
+ <label for="node-input-transcriptionhints">Hints</label>
465
+ <input type="text" id="node-input-transcriptionhints" placeholder="comma-separated list of phrases">
466
+ <input type="hidden" id="node-input-transcriptionhintsType">
467
+ </div>
468
+ <div class="form-row">
469
+ <label for="node-input-recognizeraltlang">Alternative languages</label>
470
+ <input type="text" id="node-input-recognizeraltlang" placeholder="comma-separated list of add'l lang codes">
471
+ <input type="hidden" id="node-input-recognizeraltlangType">
472
+ </div>
473
+ <div class="form-row">
474
+ <label for="node-input-useenhanced">Use enhanced model</label>
475
+ <input type="checkbox" id="node-input-useenhanced">
476
+ </div>
477
+ <div class="form-row">
478
+ <label for="node-input-profanityfilter">Profanity filter</label>
479
+ <input type="checkbox" id="node-input-profanityfilter">
480
+ </div>
481
+ <div class="form-row">
482
+ <label for="node-input-words">Word time offsets</label>
483
+ <input type="checkbox" id="node-input-words">
484
+ </div>
485
+ <div class="form-row">
486
+ <label for="node-input-punctuation">Automatic punctuation</label>
487
+ <input type="checkbox" id="node-input-punctuation">
488
+ </div>
489
+ <div class="form-row">
490
+ <label for="node-input-diarization">Speaker diarization</label>
491
+ <input type="checkbox" id="node-input-diarization">
492
+ </div>
493
+ <div class="form-row">
494
+ <label for="node-input-diarizationmin">Min speaker count</label>
495
+ <input type="text" id="node-input-diarizationmin" placeholder="2">
496
+ <input type="hidden" id="node-input-diarizationminType">
497
+ </div>
498
+ <div class="form-row">
499
+ <label for="node-input-diarizationmax">Max speaker count</label>
500
+ <input type="text" id="node-input-diarizationmax" placeholder="6">
501
+ <input type="hidden" id="node-input-diarizationmaxType">
502
+ </div>
503
+ <div class="form-row">
504
+ <label for="node-input-interactiontype">Type of Interaction</label>
505
+ <select id="node-input-interactiontype">
506
+ <option value="unspecified" selected>Unspecified</option>
507
+ <option value="discussion">Discusssion</option>
508
+ <option value="presentation">Presentation</option>
509
+ <option value="phone_call">Phone call</option>
510
+ <option value="voicemail">Voicemail</option>
511
+ <option value="voice_search">Voice search</option>
512
+ <option value="voice_command">Voice command</option>
513
+ <option value="dictation">Dictation</option>
514
+ </select>
515
+ </div>
516
+ <div class="form-row">
517
+ <label for="node-input-naics">Industry NAICS code</label>
518
+ <input type="text" id="node-input-naics">
519
+ <input type="hidden" id="node-input-naicsType">
520
+ </div>
521
+ </div>
522
+ <div id="aws-stt-options">
523
+ <legend>AWS Transcription Options</legend>
524
+ <div class="form-row">
525
+ <label for="node-input-identifychannels">Enable channel identification</label>
526
+ <input type="checkbox" id="node-input-identifychannels">
527
+ </div>
528
+ <div class="form-row">
529
+ <label for="node-input-speakerlabel">Show speaker labels</label>
530
+ <input type="checkbox" id="node-input-speakerlabel">
531
+ </div>
532
+ <div class="form-row">
533
+ <label for="node-input-vocabularyname">Vocabulary name</label>
534
+ <input type="text" id="node-input-vocabularyname">
535
+ <input type="hidden" id="node-input-vocabularynameType">
536
+ </div>
537
+ <div class="form-row">
538
+ <label for="node-input-vocabularyfiltername">Vocabulary filter name</label>
539
+ <input type="text" id="node-input-vocabularyfiltername">
540
+ <input type="hidden" id="node-input-vocabularyfilternameType">
541
+ </div>
542
+ <div class="form-row">
543
+ <label for="node-input-vocabularyfiltermethod">Filter method</label>
544
+ <select id="node-input-vocabularyfiltermethod">
545
+ <option value="remove" selected>Remove</option>
546
+ <option value="mask" selected>Mask</option>
547
+ <option value="tag" selected>Tag</option>
548
+ </select>
549
+ </div>
550
+ </div>
551
+ </fieldset>
552
+ <fieldset>
553
+ <legend>SIP Headers</legend>
554
+ <div class="form-row" style="margin-bottom:0;">
555
+ <label style="width:100%"><i class="fa fa-list"></i> <span>Add custom headers on outdial</span></label>
556
+ </div>
557
+ <div class="form-row node-input-headers-container-row">
558
+ <ol id="node-input-headers-container"></ol>
559
+ </div>
560
+ </fieldset>
561
+ </div>
562
+ </script>
563
+
564
+ <!-- Help Text -->
565
+ <script type="text/html" data-help-name="dial">
566
+ <p>Dial out to a phone number, registered user, sip endpoint, or Microsoft teams user</p>
567
+ <h3>Properties</h3>
568
+ <p><code>Dial target - phone</code> -
569
+ <dd>A telephone number to dial in E.164 format</p>
570
+ <p><code>Dial target - user</code> -
571
+ <dd>A registered sip user in user@domain format</p>
572
+ <p><code>Dial target - sip</code> -
573
+ <dd>A sip endpoint in sip uri format, optionally with sip username and password</p>
574
+ <p><code>Dial target - teams</code> -
575
+ <dd>A phone number that is associated with a user in the Microsoft Teams tenant associated with this account</p>
576
+ <p><code>Action hook</code> -
577
+ <dd>webhook to invoke when the call ends. </p>
578
+ <p><code>Answer on bridge</code> -
579
+ <dd>If set to true, the inbound call will ring until the number that was dialed answers the call, and at that point a 200 OK will be sent on the inbound leg. If false, the inbound call will be answered immediately as the outbound call is placed.</p>
580
+ <p><code>Action hook</code> -
581
+ <dd>webhook to invoke when the call ends. </p>
582
+ <p><code>Caller ID</code> -
583
+ <dd>Calling phone number to display on outgoing call.</p>
584
+ <p><code>Confirm hook</code> -
585
+ <dd>webhook for an application to run on the callee's end after the dialed number answers but before the call is connected.</p>
586
+ <p><code>Dial music</code> -
587
+ <dd>url that specifies a .wav or .mp3 audio file of custom audio or ringback to play to the caller while the outbound call is ringing.</p>
588
+ <p><code>Dtmf capture</code> -
589
+ <dd>an array of strings that represent dtmf sequence which, when detected, will trigger a mid-call notification to the application via the configured dtmfHook.</p>
590
+ <p><code>DTMF hook</code> -
591
+ <dd>webhook to call when a dtmfCapture entry is matched.</p>
592
+ <p><code>Time limit</code> -
593
+ <dd>max length of call in seconds.</p>
594
+ <p><code>Time limit</code> -
595
+ <dd>max length of call in seconds.</p>
596
+ <p><code>Timeout</code> -
597
+ <dd>ring no answer timeout in seconds.</p>
598
+ <p><code>Websocket server url</code> -
599
+ <dd>url of remote websocket server to send live audio to.</p>
600
+ <p><code>Transcription hook</code> -
601
+ <dd>webhook to call when a transcription is received.</p>
602
+ <p><code>Language</code> -
603
+ <dd>language to use for speech transcription.</p>
604
+ <p><code>Send interim transcriptions</code> -
605
+ <dd>if true interim transcriptions are sent.</p>
606
+
607
+
608
+ <h3>Outputs</h3>
609
+ <dl class="message-properties">
610
+ <dt>jambonz<span class="property-type">object</span></dt>
611
+ <dd> <code>msg.jambonz</code> will contain any previous actions provided to the input with the new <code>dial</code> action appended </dd>
612
+ </dl>
613
+
614
+ <h3>Details</h3>
615
+ The dial verb is used to create a new call by dialing out to a number, a registered sip user, or sip endpoint
616
+ <ul>
617
+ <li><a href="https://docs.jambonz.org/jambonz/#dial">Jambonz dial reference</a></li>
618
+ </ul>
619
+ </script>