@jambonz/node-red-contrib-jambonz 2.4.31 → 2.5.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.
- package/package.json +8 -7
- package/resources/editor.js +5 -0
- package/src/nodes/alert.html +75 -0
- package/src/nodes/alert.js +23 -0
- package/src/nodes/auth.html +15 -3
- package/src/nodes/auth.js +10 -9
- package/src/nodes/create_call.html +126 -13
- package/src/nodes/create_call.js +39 -4
- package/src/nodes/dial.html +42 -2
- package/src/nodes/dial.js +14 -2
- package/src/nodes/get_alerts.js +13 -2
- package/src/nodes/get_call.js +13 -2
- package/src/nodes/get_calls.js +12 -2
- package/src/nodes/get_recent_calls.js +12 -2
- package/src/nodes/lcc.html +2 -1
- package/src/nodes/lcc.js +7 -2
- package/src/nodes/s3-upload.html +8 -0
- package/src/nodes/s3-upload.js +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jambonz/node-red-contrib-jambonz",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Node-RED nodes for jambonz platform",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node-red"
|
|
@@ -41,6 +41,10 @@
|
|
|
41
41
|
"dialogflow": "src/nodes/dialogflow.js",
|
|
42
42
|
"leave": "src/nodes/leave.js",
|
|
43
43
|
"rasa": "src/nodes/rasa.js",
|
|
44
|
+
"answer": "src/nodes/answer.js",
|
|
45
|
+
"dub": "src/nodes/dub.js",
|
|
46
|
+
"generic": "src/nodes/generic-verb.js",
|
|
47
|
+
"alert": "src/nodes/alert.js",
|
|
44
48
|
"userauth": "src/nodes/userauth.js",
|
|
45
49
|
"create call": "src/nodes/create_call.js",
|
|
46
50
|
"create sms": "src/nodes/create_sms.js",
|
|
@@ -48,10 +52,7 @@
|
|
|
48
52
|
"get_alerts": "src/nodes/get_alerts.js",
|
|
49
53
|
"get_call": "src/nodes/get_call.js",
|
|
50
54
|
"get_calls": "src/nodes/get_calls.js",
|
|
51
|
-
"get_recent_calls": "src/nodes/get_recent_calls.js"
|
|
52
|
-
"answer": "src/nodes/answer.js",
|
|
53
|
-
"dub": "src/nodes/dub.js",
|
|
54
|
-
"generic": "src/nodes/generic-verb.js"
|
|
55
|
+
"get_recent_calls": "src/nodes/get_recent_calls.js"
|
|
55
56
|
}
|
|
56
57
|
},
|
|
57
58
|
"author": "Dave Horton",
|
|
@@ -64,9 +65,9 @@
|
|
|
64
65
|
"hash-sum": "^2.0.0",
|
|
65
66
|
"is-utf8": "^0.2.1",
|
|
66
67
|
"media-typer": "^1.1.0",
|
|
67
|
-
"multer": "^
|
|
68
|
+
"multer": "^2.0.2",
|
|
68
69
|
"mustache": "^4.2.0",
|
|
69
|
-
"on-headers": "^1.0
|
|
70
|
+
"on-headers": "^1.1.0",
|
|
70
71
|
"raw-body": "^2.5.2",
|
|
71
72
|
"s3-upload-stream": "^1.0.7",
|
|
72
73
|
"undici": "^5.28.5",
|
package/resources/editor.js
CHANGED
|
@@ -123,9 +123,14 @@
|
|
|
123
123
|
|
|
124
124
|
function testCredentials() {
|
|
125
125
|
let baseUrl
|
|
126
|
+
|
|
126
127
|
const accountSid = $("#node-config-input-accountSid").val();
|
|
127
128
|
const token = $("#node-config-input-apiToken").val();
|
|
128
129
|
const status = $("#node-config-test-status");
|
|
130
|
+
if (!['str', 'https://api.jambonz.cloud'].includes($("#node-config-input-urlType").val()) || ($("#node-config-input-apiTokenType").val() != 'str') || ($("#node-config-input-accountSidType").val() != 'str')){
|
|
131
|
+
status.text('Cannot test credentials using TypedInputs');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
129
134
|
status.text('');
|
|
130
135
|
if ($("#node-config-input-urlType").val() == 'str'){
|
|
131
136
|
baseUrl = $("#node-config-input-url").val();
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<!-- Javascript -->
|
|
2
|
+
<script type="text/javascript">
|
|
3
|
+
var mustacheType = {
|
|
4
|
+
value: "mustache",
|
|
5
|
+
label: "mustache",
|
|
6
|
+
hasvalue: true,
|
|
7
|
+
icon: "resources/@jambonz/node-red-contrib-jambonz/icons/mustache.svg",
|
|
8
|
+
};
|
|
9
|
+
RED.nodes.registerType("alert", {
|
|
10
|
+
category: "jambonz",
|
|
11
|
+
color: "#bbabaa",
|
|
12
|
+
defaults: {
|
|
13
|
+
name: { value: "" },
|
|
14
|
+
message: { value: "" },
|
|
15
|
+
messageType: { value: "str" },
|
|
16
|
+
},
|
|
17
|
+
inputs: 1,
|
|
18
|
+
outputs: 1,
|
|
19
|
+
icon: "font-awesome/fa-cubes",
|
|
20
|
+
label: function () {
|
|
21
|
+
return this.name || "alert";
|
|
22
|
+
},
|
|
23
|
+
oneditprepare: function () {
|
|
24
|
+
$("#node-input-message").typedInput({
|
|
25
|
+
default: $("#node-input-messageType").val(),
|
|
26
|
+
types: ["str", "msg", "flow", "global", mustacheType],
|
|
27
|
+
typeField: $("#node-input-messageType"),
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<!-- HTML -->
|
|
34
|
+
<script type="text/html" data-template-name="alert">
|
|
35
|
+
<div class="form-row">
|
|
36
|
+
<label for="node-input-name"><i class="icon-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-message">Message</label>
|
|
41
|
+
<input
|
|
42
|
+
type="text"
|
|
43
|
+
id="node-input-message"
|
|
44
|
+
placeholder="Alert message"
|
|
45
|
+
/>
|
|
46
|
+
<input type="hidden" id="node-input-messageType" />
|
|
47
|
+
</div>
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<!-- Help Text -->
|
|
51
|
+
<script type="text/html" data-help-name="alert">
|
|
52
|
+
<p>Raise an alert in the jambonz platform.</p>
|
|
53
|
+
<h3>Properties</h3>
|
|
54
|
+
<p><code>Message</code> - an alert message</p>
|
|
55
|
+
|
|
56
|
+
<h3>Outputs</h3>
|
|
57
|
+
<dl class="message-properties">
|
|
58
|
+
<dt>jambonz<span class="property-type">object</span></dt>
|
|
59
|
+
<dd>
|
|
60
|
+
<code>msg.jambonz</code> will contain any previous actions provided
|
|
61
|
+
to the input with the new <code>alert</code> action appended
|
|
62
|
+
</dd>
|
|
63
|
+
</dl>
|
|
64
|
+
|
|
65
|
+
<h3>Details</h3>
|
|
66
|
+
The alert verb raises an alert in the jambonz platform
|
|
67
|
+
<h3>References</h3>
|
|
68
|
+
<ul>
|
|
69
|
+
<li>
|
|
70
|
+
<a href="https://docs.jambonz.org/verbs/verbs/alert"
|
|
71
|
+
>Jambonz alert reference</a
|
|
72
|
+
>
|
|
73
|
+
</li>
|
|
74
|
+
</ul>
|
|
75
|
+
</script>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
var { appendVerb, new_resolve } = require("./libs");
|
|
2
|
+
|
|
3
|
+
module.exports = function (RED) {
|
|
4
|
+
/** alert */
|
|
5
|
+
function alert(config) {
|
|
6
|
+
RED.nodes.createNode(this, config);
|
|
7
|
+
var node = this;
|
|
8
|
+
node.on("input", async function (msg) {
|
|
9
|
+
appendVerb(msg, {
|
|
10
|
+
verb: "alert",
|
|
11
|
+
message: await new_resolve(
|
|
12
|
+
RED,
|
|
13
|
+
config.message,
|
|
14
|
+
config.messageType,
|
|
15
|
+
node,
|
|
16
|
+
msg
|
|
17
|
+
),
|
|
18
|
+
});
|
|
19
|
+
node.send(msg);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
RED.nodes.registerType("alert", alert);
|
|
23
|
+
};
|
package/src/nodes/auth.html
CHANGED
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
defaults: {
|
|
6
6
|
name: {},
|
|
7
7
|
urlType: {},
|
|
8
|
-
url: {type: 'text'}
|
|
8
|
+
url: {type: 'text'},
|
|
9
|
+
accountSidType: {value: 'str'},
|
|
10
|
+
apiTokenType: {value: 'str'}
|
|
9
11
|
},
|
|
10
12
|
credentials: {
|
|
11
13
|
accountSid: {type: 'text'},
|
|
@@ -15,10 +17,17 @@
|
|
|
15
17
|
oneditprepare: function() {
|
|
16
18
|
$('#btn-test-credentials').on('click', testCredentials);
|
|
17
19
|
$('#node-config-input-url').typedInput({
|
|
18
|
-
types: ['str',
|
|
19
|
-
{value: 'https://api.jambonz.cloud', label : 'jambonz.cloud', hasValue: false}],
|
|
20
|
+
types: ['str', 'env', 'msg', 'flow', 'global', {value: 'https://api.jambonz.cloud', label : 'jambonz.cloud', hasValue: false}],
|
|
20
21
|
typeField: $('#node-config-input-urlType')
|
|
21
22
|
});
|
|
23
|
+
$('#node-config-input-accountSid').typedInput({
|
|
24
|
+
types: ['str', 'env', 'msg', 'flow', 'global'],
|
|
25
|
+
typeField: $('#node-config-input-accountSidType')
|
|
26
|
+
});
|
|
27
|
+
$('#node-config-input-apiToken').typedInput({
|
|
28
|
+
types: ['str', 'env', 'msg', 'flow', 'global'],
|
|
29
|
+
typeField: $('#node-config-input-apiTokenType')
|
|
30
|
+
});
|
|
22
31
|
},
|
|
23
32
|
oneditsave: function() {
|
|
24
33
|
const baseUrl = $('#node-config-input-url').val();
|
|
@@ -72,10 +81,13 @@
|
|
|
72
81
|
<div class="form-row">
|
|
73
82
|
<label for="node-config-input-accountSid">Account SID</label>
|
|
74
83
|
<input type="text" id="node-config-input-accountSid">
|
|
84
|
+
<input type="hidden" id="node-config-input-accountSidType">
|
|
75
85
|
</div>
|
|
76
86
|
<div class="form-row">
|
|
77
87
|
<label for="node-config-input-apiToken">API token</label>
|
|
78
88
|
<input type="text" id="node-config-input-apiToken">
|
|
89
|
+
<input type="hidden" id="node-config-input-apiTokenType">
|
|
90
|
+
|
|
79
91
|
</div>
|
|
80
92
|
<div class="form-row">
|
|
81
93
|
<button id="btn-test-credentials"><i class="fa fa-lock"></i> Test Credentials</button>
|
package/src/nodes/auth.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
module.exports = function(RED) {
|
|
2
2
|
function jambonz_auth(config) {
|
|
3
3
|
RED.nodes.createNode(this, config);
|
|
4
|
-
|
|
5
|
-
this.apiKey = config.apiKey;
|
|
4
|
+
var node = this;
|
|
6
5
|
this.name = config.name;
|
|
7
|
-
this.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
this.url = config.url;
|
|
7
|
+
this.urlType = config.urlType;
|
|
8
|
+
this.accountSid = config.accountSid;
|
|
9
|
+
this.accountSidType = config.accountSidType;
|
|
10
|
+
this.apiToken = config.apiToken;
|
|
11
|
+
this.apiTokenType = config.apiTokenType;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
RED.nodes.registerType('jambonz_auth', jambonz_auth, {
|
|
@@ -17,7 +16,9 @@ module.exports = function(RED) {
|
|
|
17
16
|
url: {type: 'text'},
|
|
18
17
|
urlType: {},
|
|
19
18
|
accountSid: {type: 'text'},
|
|
20
|
-
|
|
19
|
+
accountSidType: {},
|
|
20
|
+
apiToken: {type: 'text'},
|
|
21
|
+
apiTokenType: {}
|
|
21
22
|
}
|
|
22
23
|
});
|
|
23
24
|
|
|
@@ -19,9 +19,16 @@
|
|
|
19
19
|
toType: {value: ''},
|
|
20
20
|
trunk: {value: ''},
|
|
21
21
|
trunkType: {value: 'str'},
|
|
22
|
+
sipauth_user: {value: ''},
|
|
23
|
+
sipauth_userType: {value: 'str'},
|
|
24
|
+
sipauth_password: {value: ''},
|
|
25
|
+
sipauth_passwordType: {value: 'str'},
|
|
26
|
+
sip_proxy: {value: ''},
|
|
27
|
+
sip_proxyType: {value: 'str'},
|
|
22
28
|
dest: {value: 'phone', required: true},
|
|
23
|
-
timeout: {
|
|
24
|
-
|
|
29
|
+
timeout: {value: '' },
|
|
30
|
+
timeoutType: {value: 'num'},
|
|
31
|
+
tag: {value: '{}'},
|
|
25
32
|
tagType: {value: 'json'},
|
|
26
33
|
application: {value: ''},
|
|
27
34
|
appName: {},
|
|
@@ -55,7 +62,17 @@
|
|
|
55
62
|
return(true)
|
|
56
63
|
}
|
|
57
64
|
}},
|
|
58
|
-
recognizerlang: {value: 'default'}
|
|
65
|
+
recognizerlang: {value: 'default'},
|
|
66
|
+
amd_actionHook : {},
|
|
67
|
+
amd_actionHookType: {value: 'str'},
|
|
68
|
+
amd_recognizer_vendor: {value: 'default'},
|
|
69
|
+
amd_recognizer_lang: {value: 'default'},
|
|
70
|
+
amd_thresholdWordCount: {},
|
|
71
|
+
amd_timers_decisionTimeoutMs: {},
|
|
72
|
+
amd_timers_greetingCompletionTimeoutMs:{},
|
|
73
|
+
amd_timers_noSpeechTimeoutMs: {},
|
|
74
|
+
amd_timers_toneTimeoutMs: {},
|
|
75
|
+
amd_digitCount: {}
|
|
59
76
|
},
|
|
60
77
|
inputs:1,
|
|
61
78
|
outputs:1,
|
|
@@ -69,6 +86,7 @@
|
|
|
69
86
|
var serverElem = $('#node-input-server');
|
|
70
87
|
var applicationElem = $('#node-input-application');
|
|
71
88
|
var trunkDiv = $('#trunk');
|
|
89
|
+
var sipDiv = $('#sip');
|
|
72
90
|
prepareTtsControls(node);
|
|
73
91
|
prepareSttControls(node);
|
|
74
92
|
|
|
@@ -76,6 +94,8 @@
|
|
|
76
94
|
var selectedDest = destElem.find(':selected').val();
|
|
77
95
|
if ('phone' === selectedDest) trunkDiv.show();
|
|
78
96
|
else trunkDiv.hide();
|
|
97
|
+
if ('sip' === selectedDest) sipDiv.show();
|
|
98
|
+
else sipDiv.hide();
|
|
79
99
|
}
|
|
80
100
|
|
|
81
101
|
destElem.change(onDestChanged);
|
|
@@ -113,15 +133,40 @@
|
|
|
113
133
|
default: $('#node-input-trunkType').val(),
|
|
114
134
|
types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env', mustacheType],
|
|
115
135
|
typeField: $('#node-input-trunkType')
|
|
136
|
+
});
|
|
137
|
+
$('#node-input-timeout').typedInput({
|
|
138
|
+
default: $('#node-input-timeoutType').val(),
|
|
139
|
+
types: ['num', 'msg', 'flow', 'global', 'jsonata', 'env'],
|
|
140
|
+
typeField: $('#node-input-timeoutType')
|
|
141
|
+
});
|
|
142
|
+
$('#node-input-amd_actionHook').typedInput({
|
|
143
|
+
default: $('#node-input-amd_actionHookType').val(),
|
|
144
|
+
types: ['str','msg', 'flow', 'global', 'jsonata', 'env', mustacheType],
|
|
145
|
+
typeField: $('#node-input-amd_actionHookType')
|
|
146
|
+
});
|
|
147
|
+
$('#node-input-sipauth_user').typedInput({
|
|
148
|
+
default: $('#node-input-sipauth_userType').val(),
|
|
149
|
+
types: ['str','msg', 'flow', 'global', 'jsonata', 'env', mustacheType],
|
|
150
|
+
typeField: $('#node-input-sipauth_userType')
|
|
151
|
+
});
|
|
152
|
+
$('#node-input-sipauth_password').typedInput({
|
|
153
|
+
default: $('#node-input-sipauth_passwordType').val(),
|
|
154
|
+
types: ['str','msg', 'flow', 'global', 'jsonata', 'env', mustacheType],
|
|
155
|
+
typeField: $('#node-input-sipauth_passwordType')
|
|
156
|
+
});
|
|
157
|
+
$('#node-input-sip_proxy').typedInput({
|
|
158
|
+
default: $('#node-input-sip_proxyType').val(),
|
|
159
|
+
types: ['str','msg', 'flow', 'global', 'jsonata', 'env', mustacheType],
|
|
160
|
+
typeField: $('#node-input-sip_proxyType')
|
|
116
161
|
});
|
|
117
162
|
var populateApplications = function() {
|
|
118
163
|
var serverId = $('#node-input-server option:selected').val();
|
|
119
164
|
$.ajax({
|
|
120
165
|
url: `_jambonz/applications/${serverId}`,
|
|
121
166
|
dataType: 'json',
|
|
122
|
-
timeout:
|
|
167
|
+
timeout: 5000,
|
|
123
168
|
error: (err) => {
|
|
124
|
-
console.
|
|
169
|
+
console.error(`Unable to get application list ${err.statusText}`);
|
|
125
170
|
},
|
|
126
171
|
success: (res) => {
|
|
127
172
|
applicationElem.find('option').remove();
|
|
@@ -234,9 +279,18 @@
|
|
|
234
279
|
<input type="text" id="node-input-callername" placeholder="calling party name">
|
|
235
280
|
<input type="hidden" id="node-input-callernameType">
|
|
236
281
|
</div>
|
|
282
|
+
<div class="form-row">
|
|
283
|
+
<label for="node-input-dest">Dest Type</label>
|
|
284
|
+
<select id="node-input-dest">
|
|
285
|
+
<option value="phone">phone number</option>
|
|
286
|
+
<option value="user">registered sip device/user</option>
|
|
287
|
+
<option value="sip">sip endpoint</option>
|
|
288
|
+
<option value="ms-teams">Microsoft teams</option>
|
|
289
|
+
</select>
|
|
290
|
+
</div>
|
|
237
291
|
<div class="form-row">
|
|
238
292
|
<label for="node-input-to">To</label>
|
|
239
|
-
<input type="text" id="node-input-to" placeholder="
|
|
293
|
+
<input type="text" id="node-input-to" placeholder="destination">
|
|
240
294
|
<input type="hidden" id="node-input-toType">
|
|
241
295
|
</div>
|
|
242
296
|
<div class="form-row" id ="trunk">
|
|
@@ -244,18 +298,28 @@
|
|
|
244
298
|
<input type="text" id="node-input-trunk" placeholder="Specify the name of the trunk used for this outbound call">
|
|
245
299
|
<input type="hidden" id="node-input-trunkType">
|
|
246
300
|
</div>
|
|
301
|
+
<div id="sip">
|
|
247
302
|
<div class="form-row">
|
|
248
|
-
<label for="node-input-
|
|
249
|
-
<
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
303
|
+
<label for="node-input-sipauth_user">SIP Auth Username</label>
|
|
304
|
+
<input type="text" id="node-input-sipauth_user" placeholder="Username for SIP Authentication">
|
|
305
|
+
<input type="hidden" id="node-input-sipauth_userType">
|
|
306
|
+
</div>
|
|
307
|
+
<div class="form-row">
|
|
308
|
+
<label for="node-input-sipauth_password">SIP Auth Password</label>
|
|
309
|
+
<input type="text" id="node-input-sipauth_password" placeholder="Passwrd for SIP Authentication">
|
|
310
|
+
<input type="hidden" id="node-input-sipauth_passwordType">
|
|
311
|
+
</div>
|
|
312
|
+
<div class="form-row">
|
|
313
|
+
<label for="node-input-sip_proxy">SIP Proxy</label>
|
|
314
|
+
<input type="text" id="node-input-sip_proxy" placeholder="SIP Proxy">
|
|
315
|
+
<input type="hidden" id="node-input-sip_proxyType">
|
|
255
316
|
</div>
|
|
317
|
+
</div>
|
|
318
|
+
|
|
256
319
|
<div class="form-row">
|
|
257
320
|
<label for="node-input-timeout">Ring timeout</label>
|
|
258
321
|
<input type="text" id="node-input-timeout" placeholder="ring no answer timeout in secs (default: 60)">
|
|
322
|
+
<input type="hidden" id="node-input-timeoutType">
|
|
259
323
|
</div>
|
|
260
324
|
<div class="form-row">
|
|
261
325
|
<label for="node-input-tag">Tag data</label>
|
|
@@ -285,6 +349,55 @@
|
|
|
285
349
|
<ol id="node-input-headers-container"></ol>
|
|
286
350
|
</div>
|
|
287
351
|
</fieldset>
|
|
352
|
+
<fieldset>
|
|
353
|
+
<legend>Answering Machine Detection</legend>
|
|
354
|
+
<div class="form-row">
|
|
355
|
+
<label for="node-input-amd_actionHook">actionHook</label>
|
|
356
|
+
<input type="text" id="node-input-amd_actionHook">
|
|
357
|
+
<input type="hidden" id="node-input-amd_actionHookType">
|
|
358
|
+
</div>
|
|
359
|
+
<div class="form-row">
|
|
360
|
+
<label for="node-input-amd_recognizer_vendor">Vendor</label>
|
|
361
|
+
<select id="node-input-amd_recognizer_vendor">
|
|
362
|
+
<option value="default" selected>--application default--</option>
|
|
363
|
+
<option value="google">Google</option>
|
|
364
|
+
<option value="aws">AWS</option>
|
|
365
|
+
<option value="deepgram">deepgram</option>
|
|
366
|
+
<option value="microsoft">microsoft</option>
|
|
367
|
+
<option value="ibm">ibm</option>
|
|
368
|
+
<option value="nuance">nuance</option>
|
|
369
|
+
</select>
|
|
370
|
+
</div>
|
|
371
|
+
<div class="form-row">
|
|
372
|
+
<label for="node-input-amd_recognizer_lang">Language</label>
|
|
373
|
+
<select id="node-input-amd_recognizer_lang">
|
|
374
|
+
</select>
|
|
375
|
+
</div>
|
|
376
|
+
<div class="form-row">
|
|
377
|
+
<label for="node-input-amd_thresholdWordCount">Threshold Word Count</label>
|
|
378
|
+
<input type="text" id="node-input-amd_thresholdWordCount">
|
|
379
|
+
</div>
|
|
380
|
+
<div class="form-row">
|
|
381
|
+
<label for="node-input-amd_digitCount">Digit Count</label>
|
|
382
|
+
<input type="text" id="node-input-amd_digitCount">
|
|
383
|
+
</div>
|
|
384
|
+
<div class="form-row">
|
|
385
|
+
<label for="node-input-amd_timers_decisionTimeoutMs">Decision Timeout</label>
|
|
386
|
+
<input type="text" id="node-input-amd_timers_decisionTimeoutMs">
|
|
387
|
+
</div>
|
|
388
|
+
<div class="form-row">
|
|
389
|
+
<label for="node-input-amd_timers_greetingCompletionTimeoutMs">Greeting Completion Timeout</label>
|
|
390
|
+
<input type="text" id="node-input-amd_timers_greetingCompletionTimeoutMs">
|
|
391
|
+
</div>
|
|
392
|
+
<div class="form-row">
|
|
393
|
+
<label for="node-input-amd_timers_noSpeechTimeoutMs">No-Speech Timeout</label>
|
|
394
|
+
<input type="text" id="node-input-amd_timers_noSpeechTimeoutMs">
|
|
395
|
+
</div>
|
|
396
|
+
<div class="form-row">
|
|
397
|
+
<label for="node-input-amd_timers_toneTimeoutMs">Tone Timeout</label>
|
|
398
|
+
<input type="text" id="node-input-amd_timers_toneTimeoutMs">
|
|
399
|
+
</div>
|
|
400
|
+
</fieldset>
|
|
288
401
|
<div id="url-options">
|
|
289
402
|
<fieldset>
|
|
290
403
|
<legend>Webhook options</legend>
|
package/src/nodes/create_call.js
CHANGED
|
@@ -10,8 +10,10 @@ module.exports = function(RED) {
|
|
|
10
10
|
node.on('input', async (msg, send, done) => {
|
|
11
11
|
send = send || function() { node.send.apply(node, arguments);};
|
|
12
12
|
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const url = await new_resolve(RED, server.url, server.urlType, node, msg);
|
|
14
|
+
const accountSid = await new_resolve(RED, server.credentials.accountSid, server.accountSidType, node, msg);
|
|
15
|
+
const apiToken = await new_resolve(RED, server.credentials.apiToken, server.apiTokenType, node, msg);
|
|
16
|
+
|
|
15
17
|
if (!url || !accountSid || !apiToken) {
|
|
16
18
|
node.error(`invalid / missing credentials, skipping create-call node: ${JSON.stringify(server.credentials)}`);
|
|
17
19
|
send(msg);
|
|
@@ -22,6 +24,7 @@ module.exports = function(RED) {
|
|
|
22
24
|
var from = await new_resolve(RED, config.from, config.fromType, node, msg);
|
|
23
25
|
var to = await new_resolve(RED, config.to, config.toType, node, msg);
|
|
24
26
|
var tag = await new_resolve(RED, config.tag, config.tagType, node, msg);
|
|
27
|
+
var timeout = await new_resolve(RED, config.timeout, config.timeoutType, node, msg);
|
|
25
28
|
|
|
26
29
|
const opts = {
|
|
27
30
|
from,
|
|
@@ -64,8 +67,8 @@ module.exports = function(RED) {
|
|
|
64
67
|
break;
|
|
65
68
|
}
|
|
66
69
|
|
|
67
|
-
if (
|
|
68
|
-
|
|
70
|
+
if (timeout) {
|
|
71
|
+
timeout = parseInt(timeout);
|
|
69
72
|
if (timeout > 0) opts.timeout = timeout;
|
|
70
73
|
}
|
|
71
74
|
|
|
@@ -81,7 +84,12 @@ module.exports = function(RED) {
|
|
|
81
84
|
opts.to.name = to;
|
|
82
85
|
break;
|
|
83
86
|
case 'sip':
|
|
87
|
+
var sipauth_user = await new_resolve(RED, config.sipauth_user, config.sipauth_userType, node, msg);
|
|
88
|
+
var sipauth_password = await new_resolve(RED, config.sipauth_password, config.sipauth_passwordType, node, msg);
|
|
89
|
+
var sip_proxy = await new_resolve(RED, config.sip_proxy, config.sip_proxyType, node, msg);
|
|
84
90
|
opts.to.sipUri = to;
|
|
91
|
+
sip_proxy ? opts.to.proxy = sip_proxy : null
|
|
92
|
+
sipauth_user ? opts.to.auth = { username :sipauth_user, password: sipauth_password} : null
|
|
85
93
|
break;
|
|
86
94
|
case 'ms-teams':
|
|
87
95
|
opts.to.user = to;
|
|
@@ -92,6 +100,33 @@ module.exports = function(RED) {
|
|
|
92
100
|
send(msg);
|
|
93
101
|
return;
|
|
94
102
|
}
|
|
103
|
+
|
|
104
|
+
// AMD
|
|
105
|
+
const _amd_actionHook = await new_resolve(RED, config.amd_actionHook, config.amd_actionHookType, node, msg)
|
|
106
|
+
if (_amd_actionHook){
|
|
107
|
+
opts.amd = {}
|
|
108
|
+
opts.amd.actionHook = _amd_actionHook;
|
|
109
|
+
config.amd_thresholdWordCount && (opts.amd.thresholdWordCount = Number(config.amd_thresholdWordCount))
|
|
110
|
+
config.amd_digitCount && (opts.amd.digitCount = Number(config.amd_digitCount))
|
|
111
|
+
opts.amd.timers = {
|
|
112
|
+
...(config.amd_timers_decisionTimeoutMs && {decisionTimeoutMs: Number(config.amd_timers_decisionTimeoutMs)}),
|
|
113
|
+
...(config.amd_timers_greetingCompletionTimeoutMs && {greetingCompletionTimeoutMs: Number(config.amd_timers_greetingCompletionTimeoutMs)}),
|
|
114
|
+
...(config.amd_timers_noSpeechTimeoutMs && {noSpeechTimeoutMs: Number(config.amd_timers_noSpeechTimeoutMs)}),
|
|
115
|
+
...(config.amd_timers_toneTimeoutMs && {toneTimeoutMs: Number(config.amd_timers_toneTimeoutMs)}),
|
|
116
|
+
}
|
|
117
|
+
//If none of the timer values are set remove the object
|
|
118
|
+
if (Object.keys(opts.amd.timers).length == 0){
|
|
119
|
+
delete(opts.amd.timers)
|
|
120
|
+
}
|
|
121
|
+
//If custom recogniser is used
|
|
122
|
+
if (config.amd_recognizer_vendor != 'default'){
|
|
123
|
+
opts.amd.recognizer = {
|
|
124
|
+
...(config.amd_recognizer_vendor && {vendor : config.amd_recognizer_vendor}),
|
|
125
|
+
...(config.amd_recognizer_lang && {language : config.amd_recognizer_lang})
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
95
130
|
try {
|
|
96
131
|
const response = await doCreateCall(node, url, accountSid, apiToken, opts);
|
|
97
132
|
msg.statusCode = 201;
|
package/src/nodes/dial.html
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
actionhookType: {value: 'str'},
|
|
18
18
|
answeronbridge: {value: false},
|
|
19
19
|
anchormedia: {value: false},
|
|
20
|
+
exitmediapath: {value: false},
|
|
20
21
|
callerid: {value: ''},
|
|
21
22
|
calleridType: {value: ''},
|
|
22
23
|
callername: {value: ''},
|
|
@@ -33,8 +34,14 @@
|
|
|
33
34
|
dtmfhookType: {value: 'str'},
|
|
34
35
|
onholdhook: {value: ''},
|
|
35
36
|
onholdhookType: {value: 'str'},
|
|
36
|
-
timelimit: {
|
|
37
|
-
|
|
37
|
+
timelimit: {},
|
|
38
|
+
timelimitType: {value: 'num'},
|
|
39
|
+
timeout: {},
|
|
40
|
+
timeoutType: {value: 'num'},
|
|
41
|
+
boostaudiosignal: { value: "" },
|
|
42
|
+
boostaudiosignalType: { value: "str" },
|
|
43
|
+
tag: {value: '{}'},
|
|
44
|
+
tagType: {value: 'json'},
|
|
38
45
|
listenurl: {value: ''},
|
|
39
46
|
listenurlType: {value: 'str'},
|
|
40
47
|
transcriptionhook: {},
|
|
@@ -123,6 +130,15 @@
|
|
|
123
130
|
types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env', mustacheType],
|
|
124
131
|
typeField: $('#node-input-onholdhookType')
|
|
125
132
|
});
|
|
133
|
+
$('#node-input-boostaudiosignal').typedInput({
|
|
134
|
+
types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env', mustacheType],
|
|
135
|
+
typeField: $('#node-input-boostaudiosignalType')
|
|
136
|
+
});
|
|
137
|
+
$('#node-input-tag').typedInput({
|
|
138
|
+
default: $('#node-input-tagType').val(),
|
|
139
|
+
types: ['json', 'msg', 'flow', 'global', 'jsonata', 'env', mustacheType],
|
|
140
|
+
typeField: $('#node-input-tagType')
|
|
141
|
+
});
|
|
126
142
|
$('#node-input-transcribeurl').typedInput({
|
|
127
143
|
types: ['str', 'msg', 'flow', 'global', 'jsonata', 'env', mustacheType],
|
|
128
144
|
typeField: $('#node-input-transcribeurlType')
|
|
@@ -155,6 +171,14 @@
|
|
|
155
171
|
types: ['num', 'msg', 'flow', 'global', 'jsonata', 'env', mustacheType],
|
|
156
172
|
typeField: $('#node-input-naicsType')
|
|
157
173
|
});
|
|
174
|
+
$('#node-input-timeout').typedInput({
|
|
175
|
+
types: ['num', 'msg', 'flow', 'global', 'jsonata', 'env'],
|
|
176
|
+
typeField: $('#node-input-timeoutType')
|
|
177
|
+
});
|
|
178
|
+
$('#node-input-timelimit').typedInput({
|
|
179
|
+
types: ['num', 'msg', 'flow', 'global', 'jsonata', 'env'],
|
|
180
|
+
typeField: $('#node-input-timelimitType')
|
|
181
|
+
});
|
|
158
182
|
|
|
159
183
|
prepareSttControls(node);
|
|
160
184
|
prepareSttControls(node, '#node-input-amd_recognizer_vendor', '#node-input-amd_recognizer_lang');
|
|
@@ -475,6 +499,10 @@
|
|
|
475
499
|
<label for="node-input-anchormedia">Anchor media</label>
|
|
476
500
|
<input type="checkbox" id="node-input-anchormedia">
|
|
477
501
|
</div>
|
|
502
|
+
<div class="form-row">
|
|
503
|
+
<label for="node-input-exitmediapath">Exit media path</label>
|
|
504
|
+
<input type="checkbox" id="node-input-exitmediapath">
|
|
505
|
+
</div>
|
|
478
506
|
<div class="form-row">
|
|
479
507
|
<label for="node-input-callerid">Caller ID</label>
|
|
480
508
|
<input type="text" id="node-input-callerid" placeholder="caller id to place on outbound call">
|
|
@@ -518,10 +546,22 @@
|
|
|
518
546
|
<div class="form-row">
|
|
519
547
|
<label for="node-input-timelimit">Time limit</label>
|
|
520
548
|
<input type="text" id="node-input-timelimit" placeholder="max duration of call in secs">
|
|
549
|
+
<input type="hidden" id="node-input-timelimitType">
|
|
521
550
|
</div>
|
|
522
551
|
<div class="form-row">
|
|
523
552
|
<label for="node-input-timeout"><i class="icon-tag"></i> Timeout</label>
|
|
524
553
|
<input type="text" id="node-input-timeout" placeholder="ring no answer timeout in secs (default: 60)">
|
|
554
|
+
<input type="hidden" id="node-input-timeoutType">
|
|
555
|
+
</div>
|
|
556
|
+
<div class="form-row">
|
|
557
|
+
<label for="node-input-boostaudiosignal">Boost audio signal</label>
|
|
558
|
+
<input type="text" id="node-input-boostaudiosignal" placeholder="boost audio volume in decibels">
|
|
559
|
+
<input type="hidden" id="node-input-boostaudiosignalType">
|
|
560
|
+
</div>
|
|
561
|
+
<div class="form-row">
|
|
562
|
+
<label for="node-input-tag">Tag data</label>
|
|
563
|
+
<input type="text" id="node-input-tag" placeholder="tag object">
|
|
564
|
+
<input type="hidden" id="node-input-tagType">
|
|
525
565
|
</div>
|
|
526
566
|
<fieldset>
|
|
527
567
|
<legend>Live audio</legend>
|
package/src/nodes/dial.js
CHANGED
|
@@ -41,8 +41,8 @@ module.exports = function(RED) {
|
|
|
41
41
|
verb: 'dial',
|
|
42
42
|
target,
|
|
43
43
|
answerOnBridge: config.answeronbridge,
|
|
44
|
-
timeLimit: config.timelimit
|
|
45
|
-
timeout: config.timeout
|
|
44
|
+
timeLimit: await new_resolve(RED, config.timelimit, config.timelimitType, node, msg),
|
|
45
|
+
timeout: await new_resolve(RED, config.timeout, config.timeoutType, node, msg),
|
|
46
46
|
callerId: await new_resolve(RED, config.callerid, config.calleridType, node, msg),
|
|
47
47
|
callerName: await new_resolve(RED, config.callername, config.callernameType, node, msg),
|
|
48
48
|
actionHook: await new_resolve(RED, config.actionhook, config.actionhookType, node, msg),
|
|
@@ -56,10 +56,22 @@ module.exports = function(RED) {
|
|
|
56
56
|
data.anchorMedia = config.anchormedia;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
if (config.hasOwnProperty('exitmediapath')) {
|
|
60
|
+
data.exitMediaPath = config.exitmediapath;
|
|
61
|
+
}
|
|
62
|
+
|
|
59
63
|
if (config.onholdhook) {
|
|
60
64
|
data.onHoldHook = await new_resolve(RED, config.onholdhook, config.onholdhookType, node, msg);
|
|
61
65
|
}
|
|
62
66
|
|
|
67
|
+
if (config.tag) {
|
|
68
|
+
data.tag = await new_resolve(RED, config.tag, config.tagType, node, msg);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (config.boostaudiosignal) {
|
|
72
|
+
data.boostAudioSignal = await new_resolve(RED, config.boostaudiosignal, config.boostaudiosignalType, node, msg)
|
|
73
|
+
}
|
|
74
|
+
|
|
63
75
|
// headers
|
|
64
76
|
const headers = {};
|
|
65
77
|
config.headers.forEach(function(h) {
|
package/src/nodes/get_alerts.js
CHANGED
|
@@ -6,8 +6,19 @@ module.exports = function(RED) {
|
|
|
6
6
|
RED.nodes.createNode(this, config);
|
|
7
7
|
var node = this;
|
|
8
8
|
const server = RED.nodes.getNode(config.server);
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
node.on('input', async (msg, send, done) => {
|
|
11
|
+
const url = await new_resolve(RED, server.url, server.urlType, node, msg);
|
|
12
|
+
const accountSid = await new_resolve(RED, server.credentials.accountSid, server.accountSidType, node, msg);
|
|
13
|
+
const apiToken = await new_resolve(RED, server.credentials.apiToken, server.apiTokenType, node, msg);
|
|
14
|
+
|
|
15
|
+
if (!url || !accountSid || !apiToken) {
|
|
16
|
+
node.error(`invalid / missing credentials ${JSON.stringify(server.credentials)}`);
|
|
17
|
+
send(msg);
|
|
18
|
+
if (done) done();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
11
22
|
const data = {
|
|
12
23
|
page: await new_resolve(RED, config.page, config.pageType, node, msg),
|
|
13
24
|
count: await new_resolve(RED, config.count, config.countType, node, msg),
|
|
@@ -16,7 +27,7 @@ module.exports = function(RED) {
|
|
|
16
27
|
Object.keys(data).forEach((k) => data[k] == null || data[k] == '' && delete data[k]);
|
|
17
28
|
const params = new URLSearchParams(data).toString()
|
|
18
29
|
try {
|
|
19
|
-
const response = await fetch(`${
|
|
30
|
+
const response = await fetch(`${url}/v1/Accounts/${accountSid}/Alerts?${params}`, {
|
|
20
31
|
method: 'GET',
|
|
21
32
|
headers: {
|
|
22
33
|
'Authorization': `Bearer ${apiToken}`
|
package/src/nodes/get_call.js
CHANGED
|
@@ -6,8 +6,19 @@ module.exports = function (RED) {
|
|
|
6
6
|
RED.nodes.createNode(this, config);
|
|
7
7
|
var node = this;
|
|
8
8
|
const server = RED.nodes.getNode(config.server);
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
node.on("input", async (msg, send, done) => {
|
|
11
|
+
const url = await new_resolve(RED, server.url, server.urlType, node, msg);
|
|
12
|
+
const accountSid = await new_resolve(RED, server.credentials.accountSid, server.accountSidType, node, msg);
|
|
13
|
+
const apiToken = await new_resolve(RED, server.credentials.apiToken, server.apiTokenType, node, msg);
|
|
14
|
+
|
|
15
|
+
if (!url || !accountSid || !apiToken) {
|
|
16
|
+
node.error(`invalid / missing credentials ${JSON.stringify(server.credentials)}`);
|
|
17
|
+
send(msg);
|
|
18
|
+
if (done) done();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
11
22
|
const callSid = await new_resolve(RED, config.callSid, config.callSidType, node, msg);
|
|
12
23
|
if (!callSid) {
|
|
13
24
|
if (done) done(new Error('CallSid empty'));
|
|
@@ -15,7 +26,7 @@ module.exports = function (RED) {
|
|
|
15
26
|
return;
|
|
16
27
|
}
|
|
17
28
|
try {
|
|
18
|
-
const response = await fetch(`${
|
|
29
|
+
const response = await fetch(`${url}/v1/Accounts/${accountSid}/Calls/${callSid}`, {
|
|
19
30
|
method: 'GET',
|
|
20
31
|
headers: {
|
|
21
32
|
'Authorization': `Bearer ${apiToken}`
|
package/src/nodes/get_calls.js
CHANGED
|
@@ -6,8 +6,18 @@ module.exports = function (RED) {
|
|
|
6
6
|
RED.nodes.createNode(this, config);
|
|
7
7
|
var node = this;
|
|
8
8
|
const server = RED.nodes.getNode(config.server);
|
|
9
|
-
const { accountSid, apiToken } = server.credentials;
|
|
10
9
|
node.on("input", async (msg, send, done) => {
|
|
10
|
+
const url = await new_resolve(RED, server.url, server.urlType, node, msg);
|
|
11
|
+
const accountSid = await new_resolve(RED, server.credentials.accountSid, server.accountSidType, node, msg);
|
|
12
|
+
const apiToken = await new_resolve(RED, server.credentials.apiToken, server.apiTokenType, node, msg);
|
|
13
|
+
|
|
14
|
+
if (!url || !accountSid || !apiToken) {
|
|
15
|
+
node.error(`invalid / missing credentials ${JSON.stringify(server.credentials)}`);
|
|
16
|
+
send(msg);
|
|
17
|
+
if (done) done();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
11
21
|
const data = {
|
|
12
22
|
direction: await new_resolve(RED, config.direction, config.directionType, node, msg),
|
|
13
23
|
from: await new_resolve(RED, config.from, config.fromType, node, msg),
|
|
@@ -19,7 +29,7 @@ module.exports = function (RED) {
|
|
|
19
29
|
);
|
|
20
30
|
const params = new URLSearchParams(data).toString();
|
|
21
31
|
try {
|
|
22
|
-
const response = await fetch(`${
|
|
32
|
+
const response = await fetch(`${url}/v1/Accounts/${accountSid}/Calls${ params ? '?' + params : ''}`, {
|
|
23
33
|
method: 'GET',
|
|
24
34
|
headers: {
|
|
25
35
|
'Authorization': `Bearer ${apiToken}`
|
|
@@ -6,8 +6,18 @@ module.exports = function(RED) {
|
|
|
6
6
|
RED.nodes.createNode(this, config);
|
|
7
7
|
var node = this;
|
|
8
8
|
const server = RED.nodes.getNode(config.server);
|
|
9
|
-
const {accountSid, apiToken} = server.credentials;
|
|
10
9
|
node.on('input', async (msg, send, done) => {
|
|
10
|
+
const url = await new_resolve(RED, server.url, server.urlType, node, msg);
|
|
11
|
+
const accountSid = await new_resolve(RED, server.credentials.accountSid, server.accountSidType, node, msg);
|
|
12
|
+
const apiToken = await new_resolve(RED, server.credentials.apiToken, server.apiTokenType, node, msg);
|
|
13
|
+
|
|
14
|
+
if (!url || !accountSid || !apiToken) {
|
|
15
|
+
node.error(`invalid / missing credentials ${JSON.stringify(server.credentials)}`);
|
|
16
|
+
send(msg);
|
|
17
|
+
if (done) done();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
11
21
|
const data = {
|
|
12
22
|
direction: await new_resolve(RED, config.direction, config.directionType, node, msg),
|
|
13
23
|
trunk: await new_resolve(RED, config.trunk, config.trunkType, node, msg),
|
|
@@ -18,7 +28,7 @@ module.exports = function(RED) {
|
|
|
18
28
|
Object.keys(data).forEach((k) => data[k] == null || data[k] == '' && delete data[k]);
|
|
19
29
|
const params = new URLSearchParams(data).toString();
|
|
20
30
|
try {
|
|
21
|
-
const response = await fetch(`${
|
|
31
|
+
const response = await fetch(`${url}/v1/Accounts/${accountSid}/RecentCalls?${params}`, {
|
|
22
32
|
method: 'GET',
|
|
23
33
|
headers: {
|
|
24
34
|
'Authorization': `Bearer ${apiToken}`
|
package/src/nodes/lcc.html
CHANGED
|
@@ -355,7 +355,8 @@
|
|
|
355
355
|
<div class="form-row">
|
|
356
356
|
<label for="node-input-action">Action</label>
|
|
357
357
|
<select id="node-input-action">
|
|
358
|
-
<option value="hangup">hangup call</option>
|
|
358
|
+
<option value="hangup">hangup answered call</option>
|
|
359
|
+
<option value="cancel">cancel call</option>
|
|
359
360
|
<option value="mute">mute caller</option>
|
|
360
361
|
<option value="unmute">unmute caller</option>
|
|
361
362
|
<option value="mute_conf">mute conference participants</option>
|
package/src/nodes/lcc.js
CHANGED
|
@@ -11,9 +11,11 @@ function lcc(config) {
|
|
|
11
11
|
node.on('input', async (msg, send, done) => {
|
|
12
12
|
send = send || function() { node.send.apply(node, arguments);};
|
|
13
13
|
|
|
14
|
-
const
|
|
15
|
-
const
|
|
14
|
+
const url = await new_resolve(RED, server.url, server.urlType, node, msg);
|
|
15
|
+
const accountSid = await new_resolve(RED, server.credentials.accountSid, server.accountSidType, node, msg);
|
|
16
|
+
const apiToken = await new_resolve(RED, server.credentials.apiToken, server.apiTokenType, node, msg);
|
|
16
17
|
const callSid = await new_resolve(RED, config.callSid, config.callSidType, node, msg);
|
|
18
|
+
|
|
17
19
|
if (!url || !accountSid || !apiToken || !callSid) {
|
|
18
20
|
node.log(`invalid / missing credentials or callSid, skipping LCC node: ${JSON.stringify(server.credentials)}`);
|
|
19
21
|
send(msg);
|
|
@@ -26,6 +28,9 @@ function lcc(config) {
|
|
|
26
28
|
case 'hangup':
|
|
27
29
|
opts.call_status = 'completed';
|
|
28
30
|
break;
|
|
31
|
+
case 'cancel':
|
|
32
|
+
opts.call_status = 'no-answer';
|
|
33
|
+
break;
|
|
29
34
|
case 'mute':
|
|
30
35
|
opts.mute_status = 'mute';
|
|
31
36
|
break;
|
package/src/nodes/s3-upload.html
CHANGED
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
</script>
|
|
17
17
|
|
|
18
18
|
<script type="text/html" data-template-name="audio in">
|
|
19
|
+
<div class="form-row ui-state-error">
|
|
20
|
+
<strong>Attention:</strong>
|
|
21
|
+
This node has been deprecated. <a href="https://github.com/jambonz/node-red-contrib-jambonz/issues/53" target="_blank">See issue #53<i class="fa fa-external-link external-link"></i></a> for more details.
|
|
22
|
+
</div>
|
|
19
23
|
<div class="form-row">
|
|
20
24
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
|
21
25
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
@@ -35,6 +39,10 @@
|
|
|
35
39
|
</script>
|
|
36
40
|
|
|
37
41
|
<script type="text/html" data-help-name="audio in">
|
|
42
|
+
<div class="ui-state-error">
|
|
43
|
+
<strong>Attention:</strong>
|
|
44
|
+
This node has been deprecated.
|
|
45
|
+
</div>
|
|
38
46
|
<p>Receives audio from jambonz and uploads to S3</p>
|
|
39
47
|
<h3>Outputs</h3>
|
|
40
48
|
<dl class="message-properties">
|
package/src/nodes/s3-upload.js
CHANGED
|
@@ -24,6 +24,8 @@ module.exports = function(RED) {
|
|
|
24
24
|
RED.nodes.createNode(this, n);
|
|
25
25
|
var node = this;
|
|
26
26
|
|
|
27
|
+
node.warn("This node has been deprecated. See https://github.com/jambonz/node-red-contrib-jambonz/issues/53");
|
|
28
|
+
|
|
27
29
|
// Get AWS Creds
|
|
28
30
|
const awsCreds = RED.nodes.getNode(n.aws);
|
|
29
31
|
if (awsCreds && awsCreds.credentials) {
|