wingbot 3.67.30 → 3.67.31
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 +3 -3
- package/src/Responder.js +22 -1
- package/src/ReturnSender.js +91 -26
- package/src/graphApi/conversationsApi.js +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wingbot",
|
|
3
|
-
"version": "3.67.
|
|
3
|
+
"version": "3.67.31",
|
|
4
4
|
"description": "Enterprise Messaging Bot Conversation Engine",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
"doc": "npm run doc:gql && node ./bin/makeApiDoc.js && cpy ./CHANGELOG.md ./doc && gitbook install ./doc && gitbook build ./doc && rimraf -rf ./docs && rimraf --rf ./doc/CHANGELOG.md && move-cli ./doc/_book ./docs",
|
|
11
11
|
"test": "npm run test:lint && npm run test:coverage && npm run test:coverage:threshold",
|
|
12
12
|
"test:coverage": "nyc --reporter=html mocha ./test && nyc report",
|
|
13
|
-
"test:coverage:threshold": "nyc check-coverage --lines 89 --functions
|
|
13
|
+
"test:coverage:threshold": "nyc check-coverage --lines 89 --functions 89 --branches 80",
|
|
14
14
|
"test:backend": "mocha ./test",
|
|
15
15
|
"test:lint": "eslint --ext .js src test *.js plugins"
|
|
16
16
|
},
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
19
|
-
"url": "git+ssh://git@github.com/wingbotai/
|
|
19
|
+
"url": "git+ssh://git@github.com/wingbotai/wingnpbot.git"
|
|
20
20
|
},
|
|
21
21
|
"keywords": [
|
|
22
22
|
"Enterprise",
|
package/src/Responder.js
CHANGED
|
@@ -25,6 +25,8 @@ const EXCEPTION_HOPCOUNT_THRESHOLD = 5;
|
|
|
25
25
|
|
|
26
26
|
/** @typedef {import('./Request')} Request */
|
|
27
27
|
/** @typedef {import('./ReturnSender').UploadResult} UploadResult */
|
|
28
|
+
/** @typedef {import('./ReturnSender').SendOptions} SendOptions */
|
|
29
|
+
/** @typedef {import('./ReturnSender').TextFilter} TextFilter */
|
|
28
30
|
/** @typedef {import('./analytics/consts').TrackingCategory} TrackingCategory */
|
|
29
31
|
/** @typedef {import('./analytics/consts').TrackingType} TrackingType */
|
|
30
32
|
/** @typedef {import('./transcript/transcriptFromHistory').Transcript} Transcript */
|
|
@@ -200,6 +202,9 @@ class Responder {
|
|
|
200
202
|
this._textResponses = [];
|
|
201
203
|
|
|
202
204
|
this._typingSent = false;
|
|
205
|
+
|
|
206
|
+
/** @type {SendOptions} */
|
|
207
|
+
this._nextMessageSendOptions = null;
|
|
203
208
|
}
|
|
204
209
|
|
|
205
210
|
_findPersonaConfiguration (name) {
|
|
@@ -369,7 +374,12 @@ class Responder {
|
|
|
369
374
|
}
|
|
370
375
|
this.startedOutput = true;
|
|
371
376
|
this._typingSent = data.sender_action === 'typing_on';
|
|
372
|
-
|
|
377
|
+
let opts;
|
|
378
|
+
if (!data.sender_action && this._nextMessageSendOptions) {
|
|
379
|
+
opts = this._nextMessageSendOptions;
|
|
380
|
+
this._nextMessageSendOptions = null;
|
|
381
|
+
}
|
|
382
|
+
this._messageSender.send(data, opts);
|
|
373
383
|
return this;
|
|
374
384
|
}
|
|
375
385
|
|
|
@@ -1311,6 +1321,17 @@ class Responder {
|
|
|
1311
1321
|
);
|
|
1312
1322
|
}
|
|
1313
1323
|
|
|
1324
|
+
/**
|
|
1325
|
+
* Set next message as confident
|
|
1326
|
+
*
|
|
1327
|
+
* @param {TextFilter} anonymizer
|
|
1328
|
+
*/
|
|
1329
|
+
nextOutputConfident (anonymizer) {
|
|
1330
|
+
this._nextMessageSendOptions = {
|
|
1331
|
+
anonymizer
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1314
1335
|
/**
|
|
1315
1336
|
* Override action tracking
|
|
1316
1337
|
*
|
package/src/ReturnSender.js
CHANGED
|
@@ -32,9 +32,9 @@ const extractText = require('./transcript/extractText');
|
|
|
32
32
|
/**
|
|
33
33
|
* @typedef {object} ReturnSenderOptions
|
|
34
34
|
* @prop {boolean} [dontWaitForDeferredOps]
|
|
35
|
-
* @prop {
|
|
35
|
+
* @prop {TextFilter} [textFilter] - filter for saving the texts
|
|
36
36
|
* @prop {boolean} [logStandbyEvents] - log the standby events
|
|
37
|
-
* @prop {
|
|
37
|
+
* @prop {TextFilter} [confidentInputFilter] - filter for confident input (@CONFIDENT)
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
40
|
/**
|
|
@@ -53,11 +53,17 @@ const extractText = require('./transcript/extractText');
|
|
|
53
53
|
* @prop {Function} error
|
|
54
54
|
*/
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* @typedef {object} SendOptions
|
|
58
|
+
* @prop {TextFilter} [anonymizer]
|
|
59
|
+
*/
|
|
60
|
+
|
|
56
61
|
/**
|
|
57
62
|
* Text filter function
|
|
58
63
|
*
|
|
59
|
-
* @callback
|
|
64
|
+
* @callback TextFilter
|
|
60
65
|
* @param {string} text - input text
|
|
66
|
+
* @param {'text'|'title'|'url'|'content'} key
|
|
61
67
|
* @returns {string} - filtered text
|
|
62
68
|
*/
|
|
63
69
|
|
|
@@ -73,10 +79,11 @@ class ReturnSender {
|
|
|
73
79
|
constructor (options, senderId, incommingMessage, logger = null) {
|
|
74
80
|
this._queue = [];
|
|
75
81
|
|
|
76
|
-
/**
|
|
77
|
-
* @type {object[]}
|
|
78
|
-
*/
|
|
82
|
+
/** @type {object[]} */
|
|
79
83
|
this.responses = [];
|
|
84
|
+
|
|
85
|
+
/** @type {SendOptions[]} */
|
|
86
|
+
this._responseOptions = [];
|
|
80
87
|
this._results = [];
|
|
81
88
|
|
|
82
89
|
this._promise = null;
|
|
@@ -131,7 +138,7 @@ class ReturnSender {
|
|
|
131
138
|
* For example to remove any confidential data
|
|
132
139
|
*
|
|
133
140
|
* @param {string} text
|
|
134
|
-
* @type {
|
|
141
|
+
* @type {TextFilter}
|
|
135
142
|
*/
|
|
136
143
|
this.textFilter = options.textFilter || ((text) => text);
|
|
137
144
|
|
|
@@ -227,7 +234,7 @@ class ReturnSender {
|
|
|
227
234
|
: this.textFilter;
|
|
228
235
|
|
|
229
236
|
return [
|
|
230
|
-
filter(text).trim()
|
|
237
|
+
filter(text, null).trim()
|
|
231
238
|
];
|
|
232
239
|
}
|
|
233
240
|
|
|
@@ -240,7 +247,7 @@ class ReturnSender {
|
|
|
240
247
|
: this.textFilter;
|
|
241
248
|
|
|
242
249
|
return this._responseTexts
|
|
243
|
-
.map((t) => filter(t))
|
|
250
|
+
.map((t) => filter(t, null))
|
|
244
251
|
.filter((t) => t && `${t}`.trim());
|
|
245
252
|
}
|
|
246
253
|
|
|
@@ -300,11 +307,18 @@ class ReturnSender {
|
|
|
300
307
|
return new Promise((r) => setTimeout(r, nextWait));
|
|
301
308
|
}
|
|
302
309
|
|
|
303
|
-
_filterMessage (payload, confidentInput =
|
|
310
|
+
_filterMessage (payload, confidentInput = null, req = null) {
|
|
304
311
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
312
|
+
let filter;
|
|
313
|
+
const processButtons = typeof confidentInput === 'function';
|
|
314
|
+
|
|
315
|
+
if (processButtons) {
|
|
316
|
+
filter = confidentInput;
|
|
317
|
+
} else if (confidentInput) {
|
|
318
|
+
filter = this.confidentInputFilter;
|
|
319
|
+
} else {
|
|
320
|
+
filter = this.textFilter;
|
|
321
|
+
}
|
|
308
322
|
|
|
309
323
|
let { message } = payload;
|
|
310
324
|
|
|
@@ -314,7 +328,7 @@ class ReturnSender {
|
|
|
314
328
|
text: message.text ? message.text : message.voice.ssml,
|
|
315
329
|
voice: {
|
|
316
330
|
...message.voice,
|
|
317
|
-
ssml: filter(message.voice.ssml)
|
|
331
|
+
ssml: filter(message.voice.ssml, 'ssml')
|
|
318
332
|
}
|
|
319
333
|
};
|
|
320
334
|
}
|
|
@@ -331,7 +345,7 @@ class ReturnSender {
|
|
|
331
345
|
...payload,
|
|
332
346
|
message: {
|
|
333
347
|
...message,
|
|
334
|
-
text: filter(text)
|
|
348
|
+
text: filter(text, 'text')
|
|
335
349
|
}
|
|
336
350
|
};
|
|
337
351
|
}
|
|
@@ -342,6 +356,8 @@ class ReturnSender {
|
|
|
342
356
|
&& message.attachment.payload
|
|
343
357
|
&& message.attachment.payload.text) {
|
|
344
358
|
|
|
359
|
+
const { payload: p } = message.attachment;
|
|
360
|
+
|
|
345
361
|
return {
|
|
346
362
|
...payload,
|
|
347
363
|
message: {
|
|
@@ -349,8 +365,46 @@ class ReturnSender {
|
|
|
349
365
|
attachment: {
|
|
350
366
|
...message.attachment,
|
|
351
367
|
payload: {
|
|
352
|
-
...
|
|
353
|
-
text: filter(
|
|
368
|
+
...p,
|
|
369
|
+
text: filter(p.text, 'text'),
|
|
370
|
+
...(processButtons && Array.isArray(p.buttons)
|
|
371
|
+
? {
|
|
372
|
+
buttons: p.buttons.map((btn) => {
|
|
373
|
+
switch (btn.type) {
|
|
374
|
+
case 'attachment':
|
|
375
|
+
return {
|
|
376
|
+
...btn,
|
|
377
|
+
title: filter(btn.title, 'title'),
|
|
378
|
+
...(btn.payload && btn.payload.content
|
|
379
|
+
? {
|
|
380
|
+
payload: {
|
|
381
|
+
...btn.payload,
|
|
382
|
+
content: filter(btn.payload.content, 'content')
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
: {}
|
|
386
|
+
)
|
|
387
|
+
};
|
|
388
|
+
case 'web_url':
|
|
389
|
+
return {
|
|
390
|
+
...btn,
|
|
391
|
+
url: filter(btn.url, 'url'),
|
|
392
|
+
title: filter(btn.title, 'title')
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
case 'postback':
|
|
396
|
+
return {
|
|
397
|
+
...btn,
|
|
398
|
+
title: filter(btn.title, 'title')
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
default:
|
|
402
|
+
return btn;
|
|
403
|
+
}
|
|
404
|
+
})
|
|
405
|
+
}
|
|
406
|
+
: {}
|
|
407
|
+
)
|
|
354
408
|
}
|
|
355
409
|
}
|
|
356
410
|
}
|
|
@@ -363,10 +417,11 @@ class ReturnSender {
|
|
|
363
417
|
async _work () {
|
|
364
418
|
this._isWorking = true;
|
|
365
419
|
let payload;
|
|
420
|
+
let options;
|
|
366
421
|
let req;
|
|
367
422
|
let previousResponse = null;
|
|
368
423
|
while (this._queue.length > 0) {
|
|
369
|
-
payload = this._queue.shift();
|
|
424
|
+
({ payload, options } = this._queue.shift());
|
|
370
425
|
|
|
371
426
|
let lastInQueueForNow = this._queue.length === 0;
|
|
372
427
|
if (this._queue.length === 0 && this._sendLastMessageWithFinish) {
|
|
@@ -392,6 +447,7 @@ class ReturnSender {
|
|
|
392
447
|
} else {
|
|
393
448
|
await this._enrichPayload(payload, req, lastInQueueForNow);
|
|
394
449
|
this.responses.push(payload);
|
|
450
|
+
this._responseOptions.push(options);
|
|
395
451
|
previousResponse = await this._send(payload);
|
|
396
452
|
this._results.push(previousResponse);
|
|
397
453
|
}
|
|
@@ -487,7 +543,13 @@ class ReturnSender {
|
|
|
487
543
|
return false;
|
|
488
544
|
}
|
|
489
545
|
|
|
490
|
-
|
|
546
|
+
/**
|
|
547
|
+
*
|
|
548
|
+
* @param {object} payload
|
|
549
|
+
* @param {SendOptions} options
|
|
550
|
+
* @returns {void}
|
|
551
|
+
*/
|
|
552
|
+
send (payload, options = {}) {
|
|
491
553
|
if (this._finished) {
|
|
492
554
|
throw new Error('Cannot send message after sender is finished');
|
|
493
555
|
}
|
|
@@ -510,17 +572,17 @@ class ReturnSender {
|
|
|
510
572
|
if (payload.set_context
|
|
511
573
|
&& !this._isVisibleMessage(payload, false)
|
|
512
574
|
&& lastInQueue
|
|
513
|
-
&& this._isVisibleMessage(lastInQueue)) {
|
|
575
|
+
&& this._isVisibleMessage(lastInQueue.payload)) {
|
|
514
576
|
|
|
515
577
|
const { set_context: setContext, ...rest } = payload;
|
|
516
578
|
|
|
517
579
|
Object.assign(
|
|
518
|
-
lastInQueue,
|
|
580
|
+
lastInQueue.payload,
|
|
519
581
|
rest,
|
|
520
|
-
lastInQueue,
|
|
582
|
+
lastInQueue.payload,
|
|
521
583
|
{
|
|
522
584
|
set_context: {
|
|
523
|
-
...lastInQueue.set_context,
|
|
585
|
+
...lastInQueue.payload.set_context,
|
|
524
586
|
...setContext
|
|
525
587
|
}
|
|
526
588
|
}
|
|
@@ -532,7 +594,7 @@ class ReturnSender {
|
|
|
532
594
|
if (text) {
|
|
533
595
|
this._responseTexts.push(text);
|
|
534
596
|
}
|
|
535
|
-
this._queue.push(payload);
|
|
597
|
+
this._queue.push({ payload, options });
|
|
536
598
|
this._gotAnotherEvent();
|
|
537
599
|
|
|
538
600
|
if (this._catchedBeforeFinish) {
|
|
@@ -620,7 +682,7 @@ class ReturnSender {
|
|
|
620
682
|
let text = req.text();
|
|
621
683
|
|
|
622
684
|
if (text) {
|
|
623
|
-
text = this.textFilter(text);
|
|
685
|
+
text = this.textFilter(text, null);
|
|
624
686
|
}
|
|
625
687
|
|
|
626
688
|
const expected = req.expected();
|
|
@@ -675,7 +737,10 @@ class ReturnSender {
|
|
|
675
737
|
}
|
|
676
738
|
|
|
677
739
|
try {
|
|
678
|
-
const sent = this.responses.map((s) =>
|
|
740
|
+
const sent = this.responses.map((s, i) => {
|
|
741
|
+
const opts = this._responseOptions[i];
|
|
742
|
+
return this._filterMessage(s, opts.anonymizer);
|
|
743
|
+
});
|
|
679
744
|
const processedEvent = req
|
|
680
745
|
? req.event
|
|
681
746
|
: this._incommingMessage;
|
|
@@ -33,7 +33,7 @@ const { apiTextOutputFilter, mapObject, defaultMapperFactory } = require('../uti
|
|
|
33
33
|
/**
|
|
34
34
|
* Function for filtration of string output
|
|
35
35
|
*
|
|
36
|
-
* @callback
|
|
36
|
+
* @callback TextFilter
|
|
37
37
|
* @param {string} value
|
|
38
38
|
* @param {string} key
|
|
39
39
|
* @returns {any}
|
|
@@ -48,7 +48,7 @@ const { apiTextOutputFilter, mapObject, defaultMapperFactory } = require('../uti
|
|
|
48
48
|
* @param {Notifications} notifications
|
|
49
49
|
* @param {string[]|Function} [acl] - limit api to array of groups or use auth function
|
|
50
50
|
* @param {object} options
|
|
51
|
-
* @param {
|
|
51
|
+
* @param {TextFilter} [options.stateTextFilter] - optional funcion for filtering data in states
|
|
52
52
|
* @param {Mapper} [options.mapper] - mapper for state values
|
|
53
53
|
* @returns {ConversationsAPI}
|
|
54
54
|
* @example
|