@jambonz/node-red-contrib-jambonz 2.2.73 → 2.3.1
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.
- package/examples/Authenticating sip devices.json +1 -0
- package/examples/Conference with LCC.json +1 -0
- package/{src/examples → examples}/Connecting to a dialogflow bot.json +0 -0
- package/examples/Create Call and Send DTMF.json +1 -0
- package/examples/Get Log Data.json +1 -0
- package/examples/Leave Queue.json +1 -0
- package/examples/SIP Responses.json +1 -0
- package/{src/examples → examples}/SIP trunking outbound call.json +0 -0
- package/examples/Simple IVR.json +1 -0
- package/examples/Simple Queue.json +1 -0
- package/examples/Using Redirect.json +1 -0
- package/examples/Voicemail using Listen into S3 bucket.json +130 -0
- package/examples/config.json +1 -0
- package/examples/gather.json +1 -0
- package/examples/lex.json +1 -0
- package/examples/messages.json +1 -0
- package/examples/rasa.json +1 -0
- package/examples/tag a call.json +1 -0
- package/package.json +52 -14
- package/resources/editor.js +414 -0
- package/src/data/recognizer.json +685 -1
- package/src/data/tts.json +2970 -1
- package/src/nodes/auth.html +108 -0
- package/src/nodes/auth.js +43 -0
- package/src/nodes/conference.html +121 -0
- package/src/nodes/conference.js +31 -0
- package/src/nodes/config.html +484 -0
- package/src/nodes/config.js +74 -0
- package/src/nodes/create_call.html +287 -0
- package/src/nodes/create_call.js +104 -0
- package/src/nodes/create_sms.html +106 -0
- package/src/nodes/create_sms.js +65 -0
- package/src/nodes/dequeue.html +102 -0
- package/src/nodes/dequeue.js +25 -0
- package/src/nodes/dial.html +629 -0
- package/src/nodes/dial.js +141 -0
- package/src/nodes/dialogflow.html +260 -0
- package/src/nodes/dialogflow.js +53 -0
- package/src/nodes/dtmf.html +74 -0
- package/src/nodes/dtmf.js +22 -0
- package/src/nodes/enqueue.html +90 -0
- package/src/nodes/enqueue.js +25 -0
- package/src/nodes/gather.html +326 -0
- package/src/nodes/gather.js +83 -0
- package/src/nodes/get_alerts.html +94 -0
- package/src/nodes/get_alerts.js +47 -0
- package/src/nodes/get_calls.html +59 -0
- package/src/nodes/get_calls.js +38 -0
- package/src/nodes/get_recent_calls.html +95 -0
- package/src/nodes/get_recent_calls.js +47 -0
- package/src/nodes/hangup.html +46 -0
- package/src/nodes/hangup.js +20 -0
- package/src/nodes/jambonz.html +63 -38
- package/src/nodes/lcc.html +256 -0
- package/src/nodes/lcc.js +102 -0
- package/src/nodes/leave.html +40 -0
- package/src/nodes/leave.js +21 -0
- package/src/nodes/lex.html +264 -0
- package/src/nodes/lex.js +75 -0
- package/src/nodes/libs.js +100 -0
- package/src/nodes/listen.html +341 -0
- package/src/nodes/listen.js +82 -0
- package/src/nodes/message.html +95 -0
- package/src/nodes/message.js +32 -0
- package/src/nodes/pause.html +62 -0
- package/src/nodes/pause.js +25 -0
- package/src/nodes/play.html +76 -0
- package/src/nodes/play.js +23 -0
- package/src/nodes/rasa.html +106 -0
- package/src/nodes/rasa.js +22 -0
- package/src/nodes/redirect.html +64 -0
- package/src/nodes/redirect.js +24 -0
- package/src/nodes/s3-upload.html +29 -14
- package/src/nodes/s3-upload.js +24 -9
- package/src/nodes/say.html +119 -0
- package/src/nodes/say.js +38 -0
- package/src/nodes/sip-decline.html +76 -0
- package/src/nodes/sip-decline.js +25 -0
- package/src/nodes/sip-refer.html +116 -0
- package/src/nodes/sip-refer.js +33 -0
- package/src/nodes/sip-request.html +96 -0
- package/src/nodes/sip-request.js +36 -0
- package/src/nodes/tag.html +60 -0
- package/src/nodes/tag.js +22 -0
- package/src/nodes/template.html +63 -0
- package/src/nodes/template.js +9 -0
- package/src/nodes/userauth.html +85 -0
- package/src/nodes/userauth.js +70 -0
- package/src/nodes/webhooks.js +0 -16
- package/src/utils/http-helpers.js +68 -0
- package/src/examples/Authenticating sip devices.json +0 -10
- package/src/nodes/http-helpers.js +0 -26
- package/src/nodes/jambonz.js +0 -1044
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
var {createHash} = require('crypto');
|
|
2
|
+
const bent = require('bent');
|
|
3
|
+
var {appendVerb, v_resolve} = require('./libs')
|
|
4
|
+
|
|
5
|
+
module.exports = function(RED) {
|
|
6
|
+
function dial(config) {
|
|
7
|
+
RED.nodes.createNode(this, config);
|
|
8
|
+
var node = this;
|
|
9
|
+
|
|
10
|
+
node.on('input', function(msg) {
|
|
11
|
+
|
|
12
|
+
node.log(`dial config: ${JSON.stringify(config)}, msg.call: ${JSON.stringify(msg.call)}`);
|
|
13
|
+
var target = config.targets.map((t) => {
|
|
14
|
+
const obj = Object.assign({}, t);
|
|
15
|
+
var dest = v_resolve(obj.dest, obj.varType, this.context(), msg);
|
|
16
|
+
var trunk = v_resolve(obj.trunk, obj.trunkType, this.context(), msg);
|
|
17
|
+
node.log(`dial: dest ${t.varType}:${t.dest} resolved to ${dest}`);
|
|
18
|
+
switch (t.type) {
|
|
19
|
+
case 'phone':
|
|
20
|
+
obj.number = dest;
|
|
21
|
+
obj.trunk = trunk;
|
|
22
|
+
break;
|
|
23
|
+
case 'user':
|
|
24
|
+
obj.name = dest;
|
|
25
|
+
break;
|
|
26
|
+
case 'sip':
|
|
27
|
+
obj.sipUri = dest;
|
|
28
|
+
if (t.user) {
|
|
29
|
+
obj.auth = {
|
|
30
|
+
username: t.user,
|
|
31
|
+
password: t.pass
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
delete obj.user;
|
|
35
|
+
delete obj.pass;
|
|
36
|
+
break;
|
|
37
|
+
case 'teams':
|
|
38
|
+
obj.number = dest;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
delete obj.varType;
|
|
42
|
+
delete obj.trunkType;
|
|
43
|
+
delete obj.dest;
|
|
44
|
+
return obj;
|
|
45
|
+
});
|
|
46
|
+
var data = {
|
|
47
|
+
verb: 'dial',
|
|
48
|
+
target,
|
|
49
|
+
answerOnBridge: config.answeronbridge,
|
|
50
|
+
timeLimit: config.timelimit ? parseInt(config.timelimit) : null,
|
|
51
|
+
timeout: config.timeout ? parseInt(config.timeout) : null,
|
|
52
|
+
callerId: v_resolve(config.callerid, config.calleridType, this.context(), msg),
|
|
53
|
+
actionHook: v_resolve(config.actionhook, config.actionhookType, this.context(), msg),
|
|
54
|
+
confirmHook: v_resolve(config.confirmhook, config.confirmhookType, this.context(), msg),
|
|
55
|
+
dialMusic: v_resolve(config.dialmusic, config.dialmusicType, this.context(), msg),
|
|
56
|
+
dtmfHook: v_resolve(config.dtmfhook, config.dtmfhookType, this.context(), msg)
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
// headers
|
|
61
|
+
var headers = {};
|
|
62
|
+
config.headers.forEach(function(h) {
|
|
63
|
+
if (h.h.length && h.v.length) headers[h.h] = h.v;
|
|
64
|
+
});
|
|
65
|
+
Object.assign(data, {headers});
|
|
66
|
+
|
|
67
|
+
// nested listen
|
|
68
|
+
if (config.listenurl && config.listenurl.length > 0) {
|
|
69
|
+
data.listen = {
|
|
70
|
+
url: v_resolve(config.listenurl, config.listenurlType, this.context(), msg),
|
|
71
|
+
mixType: 'stereo'
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// nested transcribe
|
|
76
|
+
if (config.transcriptionhook) {
|
|
77
|
+
const recognizer = {
|
|
78
|
+
vendor: config.transcriptionvendor,
|
|
79
|
+
language: config.recognizerlang,
|
|
80
|
+
interim: config.interim,
|
|
81
|
+
separateRecognitionPerChannel: config.mixtype === 'stereo' && config.separaterecog,
|
|
82
|
+
diarization: config.diarization
|
|
83
|
+
};
|
|
84
|
+
if (recognizer.vendor === 'google') {
|
|
85
|
+
var diarizationMin = v_resolve(config.diarizationmin, config.diarizationminType, this.context(), msg);
|
|
86
|
+
var diarizationMax = v_resolve(config.diarizationmax, config.diarizationmaxType, this.context(), msg);
|
|
87
|
+
var hints = v_resolve(config.transcriptionhints, config.transcriptionhintsType, this.context(), msg);
|
|
88
|
+
var altlangs = v_resolve(config.recognizeraltlang, config.recognizeraltlangType, this.context(), msg);
|
|
89
|
+
var naics = v_resolve(config.naics, config.naicsType, this.context(), msg);
|
|
90
|
+
Object.assign(recognizer, {
|
|
91
|
+
profanityFilter: config.profanityfilter,
|
|
92
|
+
hints: hints.length > 0 ?
|
|
93
|
+
hints.split(',').map((w) => w.trim()) :
|
|
94
|
+
[],
|
|
95
|
+
punctuation: config.punctuation,
|
|
96
|
+
enhancedModel: config.useenhanced,
|
|
97
|
+
words: config.words,
|
|
98
|
+
interactionType: config.interactiontype,
|
|
99
|
+
});
|
|
100
|
+
if (recognizer.diarization) {
|
|
101
|
+
if (diarizationMin) recognizer.diarizationMinSpeakers = parseInt(diarizationMin) || 0;
|
|
102
|
+
if (diarizationMax) recognizer.diarizationMaxSpeakers = parseInt(diarizationMax) || 0;
|
|
103
|
+
}
|
|
104
|
+
if (naics) recognizer.naicsCode = parseInt(naics) || 0;
|
|
105
|
+
if (altlangs) {
|
|
106
|
+
recognizer.altLanguages = altlangs.split(',').map((e) => e.trim());
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else if (recognizer.vendor === 'aws') {
|
|
110
|
+
var vocab = v_resolve(config.vocabularyname, config.vocabularynameType, this.context(), msg);
|
|
111
|
+
var vocabFilter = v_resolve(config.vocabularyfiltername, config.vocabularynameType, this.context(), msg);
|
|
112
|
+
Object.assign(recognizer, {
|
|
113
|
+
vocabularyName: vocab,
|
|
114
|
+
vocabularyFilterName: vocabFilter,
|
|
115
|
+
filterMethod: config.vocabularyfiltermethod
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
data.transcribe = {
|
|
119
|
+
transcriptionHook: v_resolve(config.transcriptionhook, config.transcriptionhookType, this.context(), msg),
|
|
120
|
+
recognizer
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// dtmf capture
|
|
124
|
+
const dtmfCapture = v_resolve(config.dtmfcapture, config.dtmfcaptureType, this.context(), msg);
|
|
125
|
+
if (dtmfCapture && dtmfCapture.length) {
|
|
126
|
+
data.dtmfCapture = dtmfCapture.split(',').map((i) => i.trim());
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
delete data.dtmfHook;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
node.log(`dial verb: ${JSON.stringify(data)}`);
|
|
134
|
+
|
|
135
|
+
appendVerb(msg, data);
|
|
136
|
+
node.log(`dial jambonz: ${JSON.stringify(msg.jambonz)}`);
|
|
137
|
+
node.send(msg);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
RED.nodes.registerType('dial', dial);
|
|
141
|
+
}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
<!-- Javascript -->
|
|
2
|
+
<script type="text/javascript">
|
|
3
|
+
RED.nodes.registerType('dialogflow',{
|
|
4
|
+
category: 'jambonz',
|
|
5
|
+
color: '#bbabaa',
|
|
6
|
+
defaults: {
|
|
7
|
+
name: {value: ''},
|
|
8
|
+
recognizerlang: {value: 'en-US'},
|
|
9
|
+
serviceAccountCredentials: {required: true, value: ''},
|
|
10
|
+
serviceAccountCredentialsType: {value: 'msg'},
|
|
11
|
+
project: {required: true, value: ''},
|
|
12
|
+
projectType: {value: 'str'},
|
|
13
|
+
environment: {value: ''},
|
|
14
|
+
environmentType: {value: 'str'},
|
|
15
|
+
welcomeEvent: {},
|
|
16
|
+
welcomeEventType: {value: 'str'},
|
|
17
|
+
welcomeEventParams: {},
|
|
18
|
+
welcomeEventParamsType: {value: 'json'},
|
|
19
|
+
passDtmf: {value: false},
|
|
20
|
+
inputTimeout: {},
|
|
21
|
+
inputTimeoutType: {value: 'num'},
|
|
22
|
+
noInputEvent: {},
|
|
23
|
+
noInputEventType: {value: 'str'},
|
|
24
|
+
bargein: {value: false},
|
|
25
|
+
eventHook: {},
|
|
26
|
+
eventHookType: {value: 'str'},
|
|
27
|
+
actionHook: {},
|
|
28
|
+
actionHookType: {value: 'str'},
|
|
29
|
+
evtAll: {value: true},
|
|
30
|
+
evtIntent: {value: false},
|
|
31
|
+
evtTranscript: {value: false},
|
|
32
|
+
evtInterimTranscript: {value: false},
|
|
33
|
+
evtDtmf: {value: false},
|
|
34
|
+
evtEndUtterance: {value: false},
|
|
35
|
+
evtStartPlay: {value: false},
|
|
36
|
+
evtEndPlay: {value: false},
|
|
37
|
+
evtNoInput: {value: false},
|
|
38
|
+
prompt: {value: 'dialogflow', required: true},
|
|
39
|
+
vendor: {value: 'default'},
|
|
40
|
+
lang: {value: 'default'},
|
|
41
|
+
voice: {value: 'default'},
|
|
42
|
+
xlang: {},
|
|
43
|
+
xvoice: {}
|
|
44
|
+
},
|
|
45
|
+
inputs:1,
|
|
46
|
+
outputs:1,
|
|
47
|
+
icon: "font-awesome/fa-cubes",
|
|
48
|
+
label: function() { return this.name || 'dialogflow';},
|
|
49
|
+
oneditprepare: function() {
|
|
50
|
+
var node = this;
|
|
51
|
+
$('#node-input-serviceAccountCredentials').typedInput({
|
|
52
|
+
typeField: $('#node-input-serviceAccountCredentialsType'),
|
|
53
|
+
types: ['json', 'msg', 'flow', 'global', 'jsonata', 'env']
|
|
54
|
+
});
|
|
55
|
+
$('#node-input-project').typedInput({
|
|
56
|
+
typeField: $('#node-input-projectType'),
|
|
57
|
+
types: ['str','msg', 'flow', 'global', 'jsonata', 'env']
|
|
58
|
+
});
|
|
59
|
+
$('#node-input-environment').typedInput({
|
|
60
|
+
typeField: $('#node-input-environmentType'),
|
|
61
|
+
types: ['str','msg', 'flow', 'global', 'jsonata', 'env']
|
|
62
|
+
});
|
|
63
|
+
$('#node-input-welcomeEvent').typedInput({
|
|
64
|
+
typeField: $('#node-input-welcomeEventType'),
|
|
65
|
+
types: ['str','msg', 'flow', 'global', 'jsonata', 'env']
|
|
66
|
+
});
|
|
67
|
+
$('#node-input-welcomeEventParams').typedInput({
|
|
68
|
+
typeField: $('#node-input-welcomeEventParamsType'),
|
|
69
|
+
types: ['json', 'msg', 'flow', 'global', 'jsonata', 'env']
|
|
70
|
+
});
|
|
71
|
+
$('#node-input-eventHook').typedInput({
|
|
72
|
+
typeField: $('#node-input-eventHookType'),
|
|
73
|
+
types: ['str','msg', 'flow', 'global', 'jsonata', 'env']
|
|
74
|
+
});
|
|
75
|
+
$('#node-input-actionHook').typedInput({
|
|
76
|
+
typeField: $('#node-input-actionHookType'),
|
|
77
|
+
types: ['str','msg', 'flow', 'global', 'jsonata', 'env']
|
|
78
|
+
});
|
|
79
|
+
$('#node-input-inputTimeout').typedInput({
|
|
80
|
+
typeField: $('#node-input-inputTimeout'),
|
|
81
|
+
types: ['num','msg', 'flow', 'global', 'jsonata', 'env']
|
|
82
|
+
});
|
|
83
|
+
$('#node-input-noinputEvent').typedInput({
|
|
84
|
+
typeField: $('#node-input-noinputEventType'),
|
|
85
|
+
types: ['str','msg', 'flow', 'global', 'jsonata', 'env']
|
|
86
|
+
});
|
|
87
|
+
var promptElem = $('#node-input-prompt');
|
|
88
|
+
var ttsDiv = $('#tts-options');
|
|
89
|
+
var recLangElem = $('#node-input-recognizerlang');
|
|
90
|
+
|
|
91
|
+
prepareTtsControls(node);
|
|
92
|
+
var onPromptChanged = function () {
|
|
93
|
+
node.action = promptElem.find(':selected').val();
|
|
94
|
+
if ('tts' === node.action) ttsDiv.show();
|
|
95
|
+
else ttsDiv.hide();
|
|
96
|
+
}
|
|
97
|
+
promptElem.change(onPromptChanged);
|
|
98
|
+
|
|
99
|
+
var setTranscriptionLanguage = function() {
|
|
100
|
+
console.log(`setting transcription languages: ${dialogFlowOptions}`);
|
|
101
|
+
recLangElem.find('option').remove();
|
|
102
|
+
recLangElem.append(dialogFlowOptions);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
setTranscriptionLanguage();
|
|
106
|
+
console.log(`setting lang to ${node.recognizerlang}`);
|
|
107
|
+
recLangElem.val(node.recognizerlang);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
<!-- HTML -->
|
|
115
|
+
<script type="text/html" data-template-name="dialogflow">
|
|
116
|
+
<div class="form-row">
|
|
117
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
118
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
119
|
+
</div>
|
|
120
|
+
<div class="form-row">
|
|
121
|
+
<label for="node-input-project">Dialogflow project ID</label>
|
|
122
|
+
<input type="text" id="node-input-project">
|
|
123
|
+
<input type="hidden" id="node-input-projectType">
|
|
124
|
+
</div>
|
|
125
|
+
<div class="form-row">
|
|
126
|
+
<label for="node-input-project">Environment</label>
|
|
127
|
+
<input type="text" id="node-input-environment">
|
|
128
|
+
<input type="hidden" id="node-input-enviromentType">
|
|
129
|
+
</div>
|
|
130
|
+
<div class="form-row">
|
|
131
|
+
<label for="node-input-recognizerlang">Speaker language</label>
|
|
132
|
+
<select id="node-input-recognizerlang">
|
|
133
|
+
<option value="placeholder"></option>
|
|
134
|
+
</select>
|
|
135
|
+
</div>
|
|
136
|
+
<div class="form-row">
|
|
137
|
+
<label for="node-input-serviceAccountCredentials">Service account key</label>
|
|
138
|
+
<input type="text" id="node-input-serviceAccountCredentials">
|
|
139
|
+
<input type="hidden" id="node-input-serviceAccountCredentialsType">
|
|
140
|
+
</div>
|
|
141
|
+
<div class="form-row">
|
|
142
|
+
<label for="node-input-welcomeEvent">Welcome intent</label>
|
|
143
|
+
<input type="text" id="node-input-welcomeEvent" placeholder="event to send on connect">
|
|
144
|
+
<input type="hidden" id="node-input-welcomeEventType">
|
|
145
|
+
</div>
|
|
146
|
+
<div class="form-row">
|
|
147
|
+
<label for="node-input-welcomeEventParams">Welcome intent parameters</label>
|
|
148
|
+
<input type="text" id="node-input-welcomeEventParams">
|
|
149
|
+
<input type="hidden" id="node-input-welcomeEventParamsType">
|
|
150
|
+
</div>
|
|
151
|
+
<div class="form-row">
|
|
152
|
+
<label for="node-input-inputTimeout">Input timeout</label>
|
|
153
|
+
<input type="text" id="node-input-inputTimeout" placeholder="seconds to wait for a response">
|
|
154
|
+
<input type="hidden" id="node-input-inputTimeoutType">
|
|
155
|
+
</div>
|
|
156
|
+
<div class="form-row">
|
|
157
|
+
<label for="node-input-noInputEvent">Input timeout intent</label>
|
|
158
|
+
<input type="text" id="node-input-noInputEvent" placeholder="event to send on input timeout">
|
|
159
|
+
<input type="hidden" id="node-input-noInputEventType">
|
|
160
|
+
</div>
|
|
161
|
+
<div class="form-row">
|
|
162
|
+
<label for="node-input-bargein">Barge in on speech?</label>
|
|
163
|
+
<input type="checkbox" id="node-input-bargein">
|
|
164
|
+
</div>
|
|
165
|
+
<div class="form-row">
|
|
166
|
+
<label for="node-input-eventHook">Event Hook</label>
|
|
167
|
+
<input type="text" id="node-input-eventHook">
|
|
168
|
+
<input type="hidden" id="node-input-eventHookType">
|
|
169
|
+
</div>
|
|
170
|
+
<div class="form-row">
|
|
171
|
+
<label for="node-input-actionHook">Action Hook</label>
|
|
172
|
+
<input type="text" id="node-input-actionHook">
|
|
173
|
+
<input type="hidden" id="node-input-actionHookType">
|
|
174
|
+
</div>
|
|
175
|
+
<div class="form-row">
|
|
176
|
+
<label for="node-input-prompt">Prompt audio</label>
|
|
177
|
+
<select id="node-input-prompt" style="width:250px;">
|
|
178
|
+
<option value="dialogflow">Use dialogflow-provided audio</option>
|
|
179
|
+
<option value="tts">Use text to speech</option>
|
|
180
|
+
</select>
|
|
181
|
+
</div>
|
|
182
|
+
<div id="tts-options">
|
|
183
|
+
<div class="form-row">
|
|
184
|
+
<label for="node-input-vendor"> Vendor</label>
|
|
185
|
+
<select id="node-input-vendor">
|
|
186
|
+
<option value="default" selected>--application default--</option>
|
|
187
|
+
<option value="google">google</option>
|
|
188
|
+
<option value="aws">aws/polly</option>
|
|
189
|
+
<option value="microsoft">microsoft</option>
|
|
190
|
+
<option value="ibm">ibm</option>
|
|
191
|
+
<option value="nuance">nuance</option>
|
|
192
|
+
</select>
|
|
193
|
+
</div>
|
|
194
|
+
<div class="form-row" style="display: none;">
|
|
195
|
+
<label for="node-input-lang"> Lang</label>
|
|
196
|
+
<input type="text" id="node-input-lang">
|
|
197
|
+
</div>
|
|
198
|
+
<div class="form-row">
|
|
199
|
+
<label for="node-input-xlang">Language</label>
|
|
200
|
+
<select id="node-input-xlang">
|
|
201
|
+
<option value="default" selected>--application default--</option>
|
|
202
|
+
</select>
|
|
203
|
+
</div>
|
|
204
|
+
<div class="form-row" style="display: none;">
|
|
205
|
+
<label for="node-input-voice"> Voice</label>
|
|
206
|
+
<input type="text" id="node-input-voice">
|
|
207
|
+
</div>
|
|
208
|
+
<div class="form-row">
|
|
209
|
+
<label for="node-input-xvoice">Voice</label>
|
|
210
|
+
<select id="node-input-xvoice">
|
|
211
|
+
<option value="default" selected>--application default--</option>
|
|
212
|
+
</select>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
</script>
|
|
216
|
+
|
|
217
|
+
<!-- Help Text -->
|
|
218
|
+
|
|
219
|
+
<script type="text/html" data-help-name="audio in">
|
|
220
|
+
<script type="text/html" data-help-name="dialogflow">
|
|
221
|
+
<p>Run a Google dialogflow bot on the call</p>
|
|
222
|
+
<h3>Properties</h3>
|
|
223
|
+
<p><code>Dialogflow Project ID</code> -
|
|
224
|
+
The name of the dialogflow project to execute. Required.</p>
|
|
225
|
+
<p><code>Service Account Key</code> -
|
|
226
|
+
A Google service account key in JSON format is used to authenticate to dialogflow. Required.</p>
|
|
227
|
+
<p><code>Language</code> -
|
|
228
|
+
The ISO language code to use for speech recognition. Required.</p>
|
|
229
|
+
<p><code>Welcome Intent</code> -
|
|
230
|
+
The name of a dialogflow intent to send when the call is first connected. Optional.</p>
|
|
231
|
+
<p><code>Welcome Intent Parameters</code> -
|
|
232
|
+
A JSON object containing parameters to send along with the welcome intent. Optional.</p>
|
|
233
|
+
<p><code>Input Timeout</code> -
|
|
234
|
+
Number of seconds to wait for no response. Optional.</p>
|
|
235
|
+
<p><code>Event Hook</code> -
|
|
236
|
+
Webhook to call when an intent, transcription or other dialogflow event is received. Optional.</p>
|
|
237
|
+
<p><code>Action Hook</code> -
|
|
238
|
+
Webhook to call when the dialogflow bot interaction concludes. Optional.</p>
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
<h3>Outputs</h3>
|
|
242
|
+
<dl class="message-properties">
|
|
243
|
+
<dt>jambonz<span class="property-type">object</span></dt>
|
|
244
|
+
<dd> <code>msg.jambonz</code> will contain any previous actions provided to the input with the new <code>dialogflow</code> action appended </dd>
|
|
245
|
+
</dl>
|
|
246
|
+
|
|
247
|
+
<h3>Details</h3>
|
|
248
|
+
The dialogflow action connects the call to a Google dialogflow voicebot.
|
|
249
|
+
The action completes either when a new application is returned in a response to an eventHook, or the call is terminated from the dialogflow side.
|
|
250
|
+
|
|
251
|
+
<h3>References</h3>
|
|
252
|
+
<ul>
|
|
253
|
+
<li><a href="https://docs.jambonz.org/jambonz/#dialogflow">Jambonz dialogflow reference</a></li>
|
|
254
|
+
</ul>
|
|
255
|
+
</script>
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
</script>
|
|
@@ -0,0 +1,53 @@
|
|
|
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
|
+
function dialogflow(config) {
|
|
9
|
+
RED.nodes.createNode(this, config);
|
|
10
|
+
var node = this;
|
|
11
|
+
node.on('input', function(msg) {
|
|
12
|
+
var val = v_resolve(config.inputTimeout, config.inputTimeoutType, this.context(), msg);
|
|
13
|
+
var timeout = /^\d+$/.test(val) ? parseInt(val) : 0;
|
|
14
|
+
var eventHook = v_resolve(config.eventHook, config.eventHookType, this.context(), msg);
|
|
15
|
+
var actionHook = v_resolve(config.actionHook, config.actionHookType, this.context(), msg);
|
|
16
|
+
var welcomeEvent = v_resolve(config.welcomeEvent, config.welcomeEventType, this.context(), msg);
|
|
17
|
+
var environment = v_resolve(config.environment, config.environmentType, this.context(), msg);
|
|
18
|
+
var welcomeEventParams;
|
|
19
|
+
if (welcomeEvent && welcomeEvent.length > 0) {
|
|
20
|
+
welcomeEventParams = v_resolve(config.welcomeEventParams, config.welcomeEventParamsType, this.context(), msg);
|
|
21
|
+
}
|
|
22
|
+
var noInputEvent = v_resolve(config.noInputEvent, config.noInputEventType, this.context(), msg);
|
|
23
|
+
const obj = {
|
|
24
|
+
verb: 'dialogflow',
|
|
25
|
+
credentials: v_resolve(config.serviceAccountCredentials,
|
|
26
|
+
config.serviceAccountCredentialsType, this.context(), msg),
|
|
27
|
+
project: v_resolve(config.project, config.projectType, this.context(), msg),
|
|
28
|
+
lang: config.recognizerlang,
|
|
29
|
+
bargein: config.bargein
|
|
30
|
+
};
|
|
31
|
+
if (welcomeEvent) {
|
|
32
|
+
obj.welcomeEvent = welcomeEvent;
|
|
33
|
+
if (welcomeEventParams) obj.welcomeEventParams = welcomeEventParams;
|
|
34
|
+
}
|
|
35
|
+
if (environment && environment.length > 0) obj.environment = environment;
|
|
36
|
+
if (eventHook && eventHook.length > 0) obj.eventHook = eventHook;
|
|
37
|
+
if (actionHook && actionHook.length > 0) obj.actionHook = actionHook;
|
|
38
|
+
if (timeout) obj.noInputTimeout = timeout;
|
|
39
|
+
if (timeout && noInputEvent) obj.noInputEvent = noInputEvent;
|
|
40
|
+
if (config.prompt === 'tts') {
|
|
41
|
+
obj.tts = {
|
|
42
|
+
vendor: config.vendor,
|
|
43
|
+
language: config.lang,
|
|
44
|
+
voice: config.voice
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
appendVerb(msg, obj);
|
|
49
|
+
node.send(msg);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
RED.nodes.registerType('dialogflow', dialogflow);
|
|
53
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<!-- Javascript -->
|
|
2
|
+
<script type="text/javascript">
|
|
3
|
+
RED.nodes.registerType('dtmf',{
|
|
4
|
+
category: 'jambonz',
|
|
5
|
+
color: '#bbabaa',
|
|
6
|
+
defaults: {
|
|
7
|
+
name: {value: ''},
|
|
8
|
+
dtmf: {required: true},
|
|
9
|
+
duration: {value: '500'}
|
|
10
|
+
},
|
|
11
|
+
inputs:1,
|
|
12
|
+
outputs:1,
|
|
13
|
+
icon: "font-awesome/fa-cubes",
|
|
14
|
+
label: function() { return this.name || 'dtmf';},
|
|
15
|
+
oneditprepare: function() {
|
|
16
|
+
|
|
17
|
+
$('#node-input-dtmf').typedInput({
|
|
18
|
+
default: $('#node-input-dtmfType').val(),
|
|
19
|
+
types: ['str','msg', 'flow', 'global', 'jsonata', 'env'],
|
|
20
|
+
typeField: $('#node-input-dtmfType')
|
|
21
|
+
})
|
|
22
|
+
$('#node-input-duration').typedInput({
|
|
23
|
+
default: $('#node-input-durationType').val(),
|
|
24
|
+
types: ['num','msg', 'flow', 'global', 'jsonata', 'env'],
|
|
25
|
+
typeField: $('#node-input-durationType')
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
<!-- HTML -->
|
|
34
|
+
<script type="text/html" data-template-name="dtmf">
|
|
35
|
+
<div class="form-row">
|
|
36
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
37
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
38
|
+
</div>
|
|
39
|
+
<div class="form-row">
|
|
40
|
+
<label for="node-input-dtmf">DTMF</label>
|
|
41
|
+
<input type="text" id="node-input-dtmf" placeholder="0-9 * #">
|
|
42
|
+
<input type="hidden" id="node-input-dtmfType">
|
|
43
|
+
</div>
|
|
44
|
+
<div class="form-row">
|
|
45
|
+
<label for="node-input-duration">Duration</label>
|
|
46
|
+
<input type="text" id="node-input-duration" placeholder="500">
|
|
47
|
+
<input type="hidden" id="node-input-durationType">
|
|
48
|
+
</div>
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<!-- Help Text -->
|
|
52
|
+
<script type="text/html" data-help-name="play">
|
|
53
|
+
<p>generates a string of dtmf digit signals</p>
|
|
54
|
+
<h3>Properties</h3>
|
|
55
|
+
<p><code>DTMF</code> - a string containing a sequence of dtmf digits (0-9,*,#)</p>
|
|
56
|
+
<p><code>Duration</code> - the length of each digit, in milliseconds, Defaults to 500</p>
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
<h3>Outputs</h3>
|
|
60
|
+
<dl class="message-properties">
|
|
61
|
+
<dt>jambonz<span class="property-type">object</span></dt>
|
|
62
|
+
<dd> <code>msg.jambonz</code> will contain any previous actions provided to the input with the new <code>play</code> action appended </dd>
|
|
63
|
+
</dl>
|
|
64
|
+
|
|
65
|
+
<h3>Details</h3>
|
|
66
|
+
The dtmf action generates a string of dtmf digit signals. These are sent as RTP payloads using RFC 2833.
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
<h3>References</h3>
|
|
71
|
+
<ul>
|
|
72
|
+
<li><a href="https://www.jambonz.org/docs/webhooks/dtmf/">Jambonz play reference</a></li>
|
|
73
|
+
</ul>
|
|
74
|
+
</script>
|
|
@@ -0,0 +1,22 @@
|
|
|
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} = require('./libs')
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
module.exports = function(RED) {
|
|
9
|
+
function dtmf(config) {
|
|
10
|
+
RED.nodes.createNode(this, config);
|
|
11
|
+
var node = this;
|
|
12
|
+
node.on('input', function(msg) {
|
|
13
|
+
appendVerb(msg, {
|
|
14
|
+
verb: 'dtmf',
|
|
15
|
+
dtmf: config.dtmf,
|
|
16
|
+
duration: parseInt(config.duration)
|
|
17
|
+
});
|
|
18
|
+
node.send(msg);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
RED.nodes.registerType('dtmf', dtmf);
|
|
22
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<!-- Javascript -->
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
<script type="text/javascript">
|
|
5
|
+
RED.nodes.registerType('enqueue',{
|
|
6
|
+
category: 'jambonz',
|
|
7
|
+
color: '#bbabaa',
|
|
8
|
+
defaults: {
|
|
9
|
+
name: {value: ''},
|
|
10
|
+
queue: {required: true, value: ''},
|
|
11
|
+
queueType: {value: 'str'},
|
|
12
|
+
actionHook: {},
|
|
13
|
+
actionHookType: {value: 'str'},
|
|
14
|
+
waitHook: {},
|
|
15
|
+
waitHookType: {value: 'str'}
|
|
16
|
+
},
|
|
17
|
+
inputs:1,
|
|
18
|
+
outputs:1,
|
|
19
|
+
icon: "font-awesome/fa-cubes",
|
|
20
|
+
label: function() {
|
|
21
|
+
return this.name || 'enqueue';
|
|
22
|
+
},
|
|
23
|
+
oneditprepare: function() {
|
|
24
|
+
$('#node-input-queue').typedInput({
|
|
25
|
+
types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
|
|
26
|
+
typeField: $('#node-input-queueType')
|
|
27
|
+
});
|
|
28
|
+
$('#node-input-actionHook').typedInput({
|
|
29
|
+
types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
|
|
30
|
+
typeField: $('#node-input-actionHookType')
|
|
31
|
+
});
|
|
32
|
+
$('#node-input-waitHook').typedInput({
|
|
33
|
+
types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env'],
|
|
34
|
+
typeField: $('#node-input-waitHookType')
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
<!-- HTML -->
|
|
43
|
+
|
|
44
|
+
<script type="text/html" data-template-name="enqueue">
|
|
45
|
+
<div class="form-row">
|
|
46
|
+
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
|
47
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
48
|
+
</div>
|
|
49
|
+
<div class="form-row">
|
|
50
|
+
<label for="node-input-queue">Queue name</label>
|
|
51
|
+
<input type="text" id="node-input-queue" placeholder="name of queue">
|
|
52
|
+
<input type="hidden" id="node-input-queueType">
|
|
53
|
+
</div>
|
|
54
|
+
<div class="form-row">
|
|
55
|
+
<label for="node-input-actionHook">Action hook</label>
|
|
56
|
+
<input type="text" id="node-input-actionHook" placeholder="webhook url">
|
|
57
|
+
<input type="hidden" id="node-input-actionHookType">
|
|
58
|
+
</div>
|
|
59
|
+
<div class="form-row">
|
|
60
|
+
<label for="node-input-waitHook">Wait hook</label>
|
|
61
|
+
<input type="text" id="node-input-waitHook" placeholder="webhook url">
|
|
62
|
+
<input type="hidden" id="node-input-waitHookType">
|
|
63
|
+
</div>
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<!-- Help Text -->
|
|
67
|
+
|
|
68
|
+
<script type="text/html" data-help-name="enqueue">
|
|
69
|
+
<p>places a caller in a queue.</p>
|
|
70
|
+
<h3>Properties</h3>
|
|
71
|
+
<p><code>Queue name</code> -
|
|
72
|
+
The name of the queue</p>
|
|
73
|
+
<p><code>Action hook</code> -
|
|
74
|
+
A webhook invoke when operation completes.</p>
|
|
75
|
+
<p><code>Wait hook</code> -
|
|
76
|
+
A webhook to invoke while the caller is in queue. The only allowed verbs in the application returned from this webhook are say, play, pause, and leave,.</p>
|
|
77
|
+
|
|
78
|
+
<h3>Outputs</h3>
|
|
79
|
+
<dl class="message-properties">
|
|
80
|
+
<dt>jambonz<span class="property-type">object</span></dt>
|
|
81
|
+
<dd> <code>msg.jambonz</code> will contain any previous actions provided to the input with the new <code>enqueue</code> action appended </dd>
|
|
82
|
+
</dl>
|
|
83
|
+
|
|
84
|
+
<h3>Details</h3>
|
|
85
|
+
The enqueue command is used to place a caller in a queue.
|
|
86
|
+
<h3>References</h3>
|
|
87
|
+
<ul>
|
|
88
|
+
<li><a href="https://docs.jambonz.org/jambonz/#enqueue">Jambonz enqueue reference</a></li>
|
|
89
|
+
</ul>
|
|
90
|
+
</script>
|
|
@@ -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
|
+
|
|
8
|
+
module.exports = function(RED) {
|
|
9
|
+
/** enqueue */
|
|
10
|
+
function enqueue(config) {
|
|
11
|
+
RED.nodes.createNode(this, config);
|
|
12
|
+
var node = this;
|
|
13
|
+
node.on('input', function(msg, send, done) {
|
|
14
|
+
appendVerb(msg, {
|
|
15
|
+
verb: 'enqueue',
|
|
16
|
+
name: v_resolve(config.queue, config.queueType, this.context(), msg),
|
|
17
|
+
actionHook: v_resolve(config.actionHook, config.actionHookType, this.context(), msg),
|
|
18
|
+
waitHook: v_resolve(config.waitHook, config.waitHookType, this.context(), msg)
|
|
19
|
+
});
|
|
20
|
+
node.send(msg);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
RED.nodes.registerType('enqueue', enqueue);
|
|
24
|
+
|
|
25
|
+
}
|