wingbot 3.46.0-alpha.8 → 3.46.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/index.js +11 -1
- package/package.json +1 -1
- package/src/BotApp.js +40 -12
- package/src/Processor.js +2 -0
- package/src/ReturnSender.js +23 -2
- package/src/analytics/onInteractionHandler.js +9 -15
- package/src/tools/MemoryChatLogStorage.js +70 -0
- package/src/transcript/extractText.js +54 -0
- package/src/transcript/htmlBodyFromTranscript.js +21 -0
- package/src/transcript/textBodyFromTranscript.js +21 -0
- package/src/transcript/transcriptFromHistory.js +52 -0
package/index.js
CHANGED
|
@@ -48,6 +48,10 @@ const compileWithState = require('./src/utils/compileWithState');
|
|
|
48
48
|
const onInteractionHandler = require('./src/analytics/onInteractionHandler');
|
|
49
49
|
const GA4 = require('./src/analytics/GA4');
|
|
50
50
|
const plugins = require('./plugins/plugins.json');
|
|
51
|
+
const extractText = require('./src/transcript/extractText');
|
|
52
|
+
const htmlBodyFromTranscript = require('./src/transcript/htmlBodyFromTranscript');
|
|
53
|
+
const textBodyFromTranscript = require('./src/transcript/textBodyFromTranscript');
|
|
54
|
+
const transcriptFromHistory = require('./src/transcript/transcriptFromHistory');
|
|
51
55
|
const {
|
|
52
56
|
bufferloader,
|
|
53
57
|
MemoryStateStorage
|
|
@@ -135,5 +139,11 @@ module.exports = {
|
|
|
135
139
|
|
|
136
140
|
// ANALYTICS
|
|
137
141
|
onInteractionHandler,
|
|
138
|
-
GA4
|
|
142
|
+
GA4,
|
|
143
|
+
|
|
144
|
+
// TRANSCRIPTS
|
|
145
|
+
extractText,
|
|
146
|
+
htmlBodyFromTranscript,
|
|
147
|
+
textBodyFromTranscript,
|
|
148
|
+
transcriptFromHistory
|
|
139
149
|
};
|
package/package.json
CHANGED
package/src/BotApp.js
CHANGED
|
@@ -104,6 +104,14 @@ class BotApp {
|
|
|
104
104
|
this._logger = options.log || console;
|
|
105
105
|
this._textFilter = options.textFilter;
|
|
106
106
|
|
|
107
|
+
this._preHeatCalled = false;
|
|
108
|
+
this._preHeat = [
|
|
109
|
+
this._logger,
|
|
110
|
+
chatLogStorage,
|
|
111
|
+
processorOptions.stateStorage,
|
|
112
|
+
processorOptions.tokenStorage
|
|
113
|
+
].filter((s) => s && typeof s.preHeat === 'function');
|
|
114
|
+
|
|
107
115
|
let { apiUrl } = options;
|
|
108
116
|
|
|
109
117
|
if (!apiUrl) apiUrl = DEFAULT_API_URL;
|
|
@@ -204,6 +212,10 @@ class BotApp {
|
|
|
204
212
|
analyticsStorage.setDefaultLogger(log);
|
|
205
213
|
}
|
|
206
214
|
|
|
215
|
+
if (typeof analyticsStorage.preHeat === 'function') {
|
|
216
|
+
this._preHeat.push(analyticsStorage);
|
|
217
|
+
}
|
|
218
|
+
|
|
207
219
|
// @ts-ignore
|
|
208
220
|
const { snapshot = null, botId = null } = this._bot;
|
|
209
221
|
|
|
@@ -440,6 +452,15 @@ class BotApp {
|
|
|
440
452
|
return this._errorResponse('Missing authentication header', 401);
|
|
441
453
|
}
|
|
442
454
|
|
|
455
|
+
let preHeatPromise = null;
|
|
456
|
+
if (!this._preHeatCalled) {
|
|
457
|
+
preHeatPromise = Promise.all(
|
|
458
|
+
this._preHeat.map((p) => Promise.resolve(p.preHeat())
|
|
459
|
+
.catch((e) => this._logger.error('BotApp: preHeat failed', e)))
|
|
460
|
+
);
|
|
461
|
+
this._preHeatCalled = true;
|
|
462
|
+
}
|
|
463
|
+
|
|
443
464
|
let sha1;
|
|
444
465
|
let appId;
|
|
445
466
|
let secret;
|
|
@@ -449,6 +470,7 @@ class BotApp {
|
|
|
449
470
|
// @ts-ignore
|
|
450
471
|
({ sha1, appId } = await this._verify(token, secret));
|
|
451
472
|
} catch (e) {
|
|
473
|
+
await Promise.resolve(preHeatPromise);
|
|
452
474
|
return this._errorResponse(`Failed to verify token: ${e.message}`, 403);
|
|
453
475
|
}
|
|
454
476
|
|
|
@@ -457,22 +479,28 @@ class BotApp {
|
|
|
457
479
|
.digest('hex');
|
|
458
480
|
|
|
459
481
|
if (sha1 !== bodySha1) {
|
|
482
|
+
await Promise.resolve(preHeatPromise);
|
|
460
483
|
return this._errorResponse(`SHA1 does not match. Got in token: '${sha1}'`, 403);
|
|
461
484
|
}
|
|
462
485
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
const entry = await this._processEntries(appId, secret, body.entry, rawHeaders);
|
|
486
|
+
try {
|
|
487
|
+
const body = JSON.parse(rawBody);
|
|
466
488
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
489
|
+
const entry = await this._processEntries(appId, secret, body.entry, rawHeaders);
|
|
490
|
+
await Promise.resolve(preHeatPromise);
|
|
491
|
+
return {
|
|
492
|
+
statusCode: 200,
|
|
493
|
+
body: JSON.stringify({
|
|
494
|
+
entry
|
|
495
|
+
}),
|
|
496
|
+
headers: {
|
|
497
|
+
'Content-Type': 'application/json'
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
} catch (e) {
|
|
501
|
+
await Promise.resolve(preHeatPromise);
|
|
502
|
+
throw e;
|
|
503
|
+
}
|
|
476
504
|
}
|
|
477
505
|
|
|
478
506
|
async _processEntries (appId, secret, entry = [], headers = {}) {
|
package/src/Processor.js
CHANGED
|
@@ -62,6 +62,7 @@ const { mergeState, isUserInteraction } = require('./utils/stateVariables');
|
|
|
62
62
|
* @prop {TrackingEvent[]} events
|
|
63
63
|
* @prop {ResponseFlag|null} flag
|
|
64
64
|
* @prop {boolean} nonInteractive
|
|
65
|
+
* @prop {string[]} responseTexts
|
|
65
66
|
*/
|
|
66
67
|
|
|
67
68
|
/**
|
|
@@ -434,6 +435,7 @@ class Processor extends EventEmitter {
|
|
|
434
435
|
const { events = [] } = messageSender.tracking;
|
|
435
436
|
|
|
436
437
|
const event = {
|
|
438
|
+
responseTexts: messageSender.responseTexts,
|
|
437
439
|
req,
|
|
438
440
|
actions,
|
|
439
441
|
lastAction,
|
package/src/ReturnSender.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
const ai = require('./Ai');
|
|
7
7
|
const { FEATURE_PHRASES, FEATURE_TRACKING } = require('./features');
|
|
8
8
|
const { ResponseFlag } = require('./analytics/consts');
|
|
9
|
+
const extractText = require('./transcript/extractText');
|
|
9
10
|
|
|
10
11
|
/** @typedef {import('./Request')} Request */
|
|
11
12
|
/** @typedef {import('./Responder')} Responder */
|
|
@@ -122,8 +123,12 @@ class ReturnSender {
|
|
|
122
123
|
events: []
|
|
123
124
|
};
|
|
124
125
|
|
|
126
|
+
this._responseTexts = [];
|
|
127
|
+
|
|
125
128
|
this._intentsAndEntities = [];
|
|
126
129
|
|
|
130
|
+
this._confidentInput = false;
|
|
131
|
+
|
|
127
132
|
/**
|
|
128
133
|
* @type {Function}
|
|
129
134
|
* @private
|
|
@@ -147,6 +152,18 @@ class ReturnSender {
|
|
|
147
152
|
return this._simulatesOptIn;
|
|
148
153
|
}
|
|
149
154
|
|
|
155
|
+
/**
|
|
156
|
+
* @returns {string[]}
|
|
157
|
+
*/
|
|
158
|
+
get responseTexts () {
|
|
159
|
+
const filter = this._confidentInput
|
|
160
|
+
? this.confidentInputFilter
|
|
161
|
+
: this.textFilter;
|
|
162
|
+
|
|
163
|
+
return this._responseTexts
|
|
164
|
+
.map((t) => filter(t));
|
|
165
|
+
}
|
|
166
|
+
|
|
150
167
|
_gotAnotherEvent () {
|
|
151
168
|
if (this._gotAnotherEventDefer) {
|
|
152
169
|
this._gotAnotherEventDefer();
|
|
@@ -379,6 +396,10 @@ class ReturnSender {
|
|
|
379
396
|
return;
|
|
380
397
|
}
|
|
381
398
|
|
|
399
|
+
const text = extractText(payload);
|
|
400
|
+
if (text) {
|
|
401
|
+
this._responseTexts.push(text);
|
|
402
|
+
}
|
|
382
403
|
this._queue.push(payload);
|
|
383
404
|
this._gotAnotherEvent();
|
|
384
405
|
|
|
@@ -509,7 +530,7 @@ class ReturnSender {
|
|
|
509
530
|
async finished (req = null, res = null, err = null, reportError = console.error) {
|
|
510
531
|
this._finish(req);
|
|
511
532
|
const meta = this._createMeta(req, res);
|
|
512
|
-
|
|
533
|
+
this._confidentInput = !!req && req.isConfidentInput();
|
|
513
534
|
let error = err;
|
|
514
535
|
try {
|
|
515
536
|
await this._promise;
|
|
@@ -526,7 +547,7 @@ class ReturnSender {
|
|
|
526
547
|
const processedEvent = req
|
|
527
548
|
? req.event
|
|
528
549
|
: this._incommingMessage;
|
|
529
|
-
let incomming = this._filterMessage(processedEvent,
|
|
550
|
+
let incomming = this._filterMessage(processedEvent, this._confidentInput, req);
|
|
530
551
|
|
|
531
552
|
if (processedEvent !== this._incommingMessage) {
|
|
532
553
|
incomming = {
|
|
@@ -32,7 +32,6 @@ const {
|
|
|
32
32
|
* @prop {string} [label]
|
|
33
33
|
* @prop {number} [value]
|
|
34
34
|
* @prop {string} [lang]
|
|
35
|
-
* @prop {number} [sessionStart]
|
|
36
35
|
*/
|
|
37
36
|
|
|
38
37
|
/**
|
|
@@ -53,7 +52,6 @@ const {
|
|
|
53
52
|
* @prop {boolean} withUser
|
|
54
53
|
* @prop {string} [userId]
|
|
55
54
|
* @prop {number} [feedback]
|
|
56
|
-
* @prop {number} sessionDuration
|
|
57
55
|
* @prop {string} [winnerAction]
|
|
58
56
|
* @prop {string} [winnerIntent]
|
|
59
57
|
* @prop {string[]|string} [winnerEntities]
|
|
@@ -64,8 +62,6 @@ const {
|
|
|
64
62
|
* @prop {string[]|string} [entities]
|
|
65
63
|
* @prop {string[]|string} allActions
|
|
66
64
|
* @prop {boolean} nonInteractive
|
|
67
|
-
* @prop {string} [snapshot]
|
|
68
|
-
* @prop {string} [botId]
|
|
69
65
|
*
|
|
70
66
|
* @typedef {Event & ConversationEventExtension} ConversationEvent
|
|
71
67
|
*/
|
|
@@ -75,13 +71,10 @@ const {
|
|
|
75
71
|
* @prop {string} [lastAction]
|
|
76
72
|
* @prop {string} [prevAction]
|
|
77
73
|
* @prop {string} [skill]
|
|
78
|
-
* @prop {number} sessionDuration
|
|
79
74
|
* @prop {string[]|string} allActions
|
|
80
75
|
* @prop {boolean} nonInteractive
|
|
81
76
|
* @prop {boolean} isGoto
|
|
82
77
|
* @prop {boolean} withUser
|
|
83
|
-
* @prop {string} [snapshot]
|
|
84
|
-
* @prop {string} [botId]
|
|
85
78
|
*
|
|
86
79
|
* @typedef {Event & PageViewEventExtension} PageViewEvent
|
|
87
80
|
*/
|
|
@@ -101,6 +94,8 @@ const {
|
|
|
101
94
|
* @prop {number|null} [feedback]
|
|
102
95
|
* @prop {string} [timeZone]
|
|
103
96
|
* @prop {number} [sessionStart]
|
|
97
|
+
* @prop {number} [sessionDuration]
|
|
98
|
+
* @prop {string[]} [responseTexts]
|
|
104
99
|
*/
|
|
105
100
|
|
|
106
101
|
/**
|
|
@@ -143,6 +138,7 @@ const {
|
|
|
143
138
|
* @prop {boolean} [useDescriptiveCategories]
|
|
144
139
|
* @prop {boolean} [useExtendedScalars]
|
|
145
140
|
* @prop {boolean} [parallelSessionInsert]
|
|
141
|
+
* @prop {Function} [preHeat]
|
|
146
142
|
*/
|
|
147
143
|
|
|
148
144
|
/**
|
|
@@ -242,7 +238,8 @@ function onInteractionHandler (
|
|
|
242
238
|
skill,
|
|
243
239
|
events,
|
|
244
240
|
flag,
|
|
245
|
-
nonInteractive
|
|
241
|
+
nonInteractive,
|
|
242
|
+
responseTexts
|
|
246
243
|
}) {
|
|
247
244
|
if (!enabled) {
|
|
248
245
|
return;
|
|
@@ -297,7 +294,9 @@ function onInteractionHandler (
|
|
|
297
294
|
didHandover,
|
|
298
295
|
feedback,
|
|
299
296
|
timeZone,
|
|
300
|
-
sessionStart
|
|
297
|
+
sessionStart,
|
|
298
|
+
responseTexts,
|
|
299
|
+
sessionDuration: sessionTs - sessionStart
|
|
301
300
|
};
|
|
302
301
|
|
|
303
302
|
let sessionPromise;
|
|
@@ -380,12 +379,8 @@ function onInteractionHandler (
|
|
|
380
379
|
isPostback,
|
|
381
380
|
didHandover,
|
|
382
381
|
withUser,
|
|
383
|
-
sessionStart,
|
|
384
|
-
sessionDuration: sessionTs - sessionStart,
|
|
385
382
|
feedback,
|
|
386
383
|
skill: useSkill,
|
|
387
|
-
snapshot,
|
|
388
|
-
botId,
|
|
389
384
|
winnerAction,
|
|
390
385
|
winnerIntent,
|
|
391
386
|
winnerEntities: asArray(winnerEntities.map((e) => e.entity)),
|
|
@@ -414,7 +409,6 @@ function onInteractionHandler (
|
|
|
414
409
|
prevAction: lastAction,
|
|
415
410
|
skill: useSkill,
|
|
416
411
|
isGoto: false,
|
|
417
|
-
sessionDuration: timestamp - sessionStart,
|
|
418
412
|
withUser,
|
|
419
413
|
...langsExtension,
|
|
420
414
|
...(hasExtendedEvents ? {} : actionMeta)
|
|
@@ -435,7 +429,7 @@ function onInteractionHandler (
|
|
|
435
429
|
prevAction,
|
|
436
430
|
skill: useSkill,
|
|
437
431
|
isGoto: true,
|
|
438
|
-
|
|
432
|
+
withUser,
|
|
439
433
|
...langsExtension
|
|
440
434
|
};
|
|
441
435
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author David Menger
|
|
3
|
+
*/
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @class MemoryChatLogStorage
|
|
8
|
+
*/
|
|
9
|
+
class MemoryChatLogStorage {
|
|
10
|
+
|
|
11
|
+
constructor () {
|
|
12
|
+
this._logs = new Map();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Interate history
|
|
17
|
+
* all limits are inclusive
|
|
18
|
+
*
|
|
19
|
+
* @param {string} senderId
|
|
20
|
+
* @param {string} pageId
|
|
21
|
+
* @param {number} [limit]
|
|
22
|
+
* @param {number} [endAt] - iterate backwards to history
|
|
23
|
+
* @param {number} [startAt] - iterate forward to last interaction
|
|
24
|
+
* @returns {Promise<object[]>}
|
|
25
|
+
*/
|
|
26
|
+
async getInteractions (senderId, pageId, limit = 10, endAt = null, startAt = null) { // eslint-disable-line max-len,no-unused-vars
|
|
27
|
+
const events = this._getEvents(senderId);
|
|
28
|
+
return events.slice(-limit);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @param {string} senderId
|
|
34
|
+
* @returns {object[]}
|
|
35
|
+
*/
|
|
36
|
+
_getEvents (senderId) {
|
|
37
|
+
let events = this._logs.get(senderId);
|
|
38
|
+
if (!events) {
|
|
39
|
+
events = [];
|
|
40
|
+
this._logs.set(senderId, events);
|
|
41
|
+
}
|
|
42
|
+
return events;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Log single event
|
|
47
|
+
*
|
|
48
|
+
* @param {string} senderId
|
|
49
|
+
* @param {object[]} responses - list of sent responses
|
|
50
|
+
* @param {object} request - event request
|
|
51
|
+
* @param {object} [metadata] - request metadata
|
|
52
|
+
* @returns {void}
|
|
53
|
+
*/
|
|
54
|
+
log (senderId, responses = [], request = {}, metadata = {}) {
|
|
55
|
+
const events = this._getEvents(senderId);
|
|
56
|
+
events.push({
|
|
57
|
+
senderId,
|
|
58
|
+
request,
|
|
59
|
+
responses,
|
|
60
|
+
...metadata
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
error (error, senderId, sent, incomming, meta) {
|
|
65
|
+
return this.log(senderId, sent, incomming, { ...meta, error });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = MemoryChatLogStorage;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author David Menger
|
|
3
|
+
*/
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Extracts text from conversational event
|
|
8
|
+
*
|
|
9
|
+
* @param {object} payload
|
|
10
|
+
* @returns {string|null}
|
|
11
|
+
*/
|
|
12
|
+
function extractText (payload) {
|
|
13
|
+
|
|
14
|
+
// text message
|
|
15
|
+
if (payload.message && payload.message.text) {
|
|
16
|
+
return payload.message.text;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// button message
|
|
20
|
+
if (payload.message && payload.message.attachment
|
|
21
|
+
&& payload.message.attachment.type === 'template'
|
|
22
|
+
&& payload.message.attachment.payload
|
|
23
|
+
&& payload.message.attachment.payload.text) {
|
|
24
|
+
|
|
25
|
+
return payload.message.attachment.payload.text;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!payload.postback) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// postback with title
|
|
33
|
+
if (payload.postback.title) {
|
|
34
|
+
return payload.postback.title;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (payload.postback.payload && payload.postback.payload.action) {
|
|
38
|
+
return payload.postback.payload.action;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (typeof payload.postback.payload !== 'string') {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (payload.postback.payload[0] === '{') {
|
|
46
|
+
const pl = JSON.parse(payload.postback.payload);
|
|
47
|
+
|
|
48
|
+
return pl.action;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return payload.postback.payload;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = extractText;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author David Menger
|
|
3
|
+
*/
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
/** @typedef {import('./transcriptFromHistory').Transcript} Transcript */
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {Transcript[]} transcript
|
|
10
|
+
* @param {string} [userSide]
|
|
11
|
+
* @param {string} [botSide]
|
|
12
|
+
* @returns {string}
|
|
13
|
+
*/
|
|
14
|
+
function htmlBodyFromTranscript (transcript, userSide = 'User', botSide = 'Bot') {
|
|
15
|
+
|
|
16
|
+
return transcript
|
|
17
|
+
.map((msg) => `<b>${msg.fromBot ? botSide : userSide}:</b> ${msg.text}`)
|
|
18
|
+
.join('<br />');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = htmlBodyFromTranscript;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author David Menger
|
|
3
|
+
*/
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
/** @typedef {import('./transcriptFromHistory').Transcript} Transcript */
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {Transcript[]} transcript
|
|
10
|
+
* @param {string} [userSide]
|
|
11
|
+
* @param {string} [botSide]
|
|
12
|
+
* @returns {string}
|
|
13
|
+
*/
|
|
14
|
+
function textBodyFromTranscript (transcript, userSide = 'User', botSide = 'Bot') {
|
|
15
|
+
|
|
16
|
+
return transcript
|
|
17
|
+
.map((msg, i) => `${msg.fromBot ? ' <' : `${i > 0 ? '\n' : ''}# >`} ${msg.fromBot ? botSide : userSide}: ${msg.text}`)
|
|
18
|
+
.join('\n');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = textBodyFromTranscript;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author David Menger
|
|
3
|
+
*/
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const extractText = require('./extractText');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @callback GetInteractions
|
|
10
|
+
* @param {string} senderId
|
|
11
|
+
* @param {string} pageId
|
|
12
|
+
* @param {number} limit
|
|
13
|
+
* @returns {Promise<object[]>}
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {object} IChatStorage
|
|
18
|
+
* @prop {GetInteractions} getInteractions
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {object} Transcript
|
|
23
|
+
* @prop {string} text
|
|
24
|
+
* @prop {boolean} fromBot
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param {IChatStorage} chatLogStorage
|
|
30
|
+
* @param {string} senderId
|
|
31
|
+
* @param {string} pageId
|
|
32
|
+
* @param {number} limit
|
|
33
|
+
* @returns {Promise<Transcript[]>}
|
|
34
|
+
*/
|
|
35
|
+
async function transcriptFromHistory (chatLogStorage, senderId, pageId, limit = 20) {
|
|
36
|
+
const data = await chatLogStorage.getInteractions(senderId, pageId, limit);
|
|
37
|
+
|
|
38
|
+
return data
|
|
39
|
+
.map((turn) => {
|
|
40
|
+
const { request, responses = [] } = turn;
|
|
41
|
+
|
|
42
|
+
return [
|
|
43
|
+
{ fromBot: false, text: extractText(request) },
|
|
44
|
+
...responses
|
|
45
|
+
.map((response) => ({ fromBot: true, text: extractText(response) }))
|
|
46
|
+
];
|
|
47
|
+
})
|
|
48
|
+
.reduce((ret, arr) => [...ret, ...arr], [])
|
|
49
|
+
.filter((ret) => !!ret.text);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = transcriptFromHistory;
|