botium-core 1.14.9 → 1.15.2
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/README.md +0 -4
- package/dist/botium-cjs.js +278 -133
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +277 -132
- package/dist/botium-es.js.map +1 -1
- package/package.json +5 -4
- package/samples/connectors/simplerest-async/jokebot.js +24 -18
- package/src/Capabilities.js +3 -0
- package/src/containers/BaseContainer.js +1 -2
- package/src/containers/plugins/SimpleRestContainer.js +158 -89
- package/src/scripting/Convo.js +40 -4
- package/src/scripting/ScriptingProvider.js +18 -11
- package/src/scripting/helper.js +59 -22
- package/src/scripting/logichook/LogicHookUtils.js +8 -10
- package/src/scripting/logichook/asserter/BaseTextAsserter.js +1 -2
- package/src/scripting/logichook/asserter/ButtonsAsserter.js +3 -4
- package/src/scripting/logichook/userinput/MediaInput.js +16 -19
- package/test/compiler/compilertxt.spec.js +18 -0
- package/test/compiler/convos/txt/convos_jsonmessage.convo.txt +10 -0
- package/test/connectors/simplerest.spec.js +290 -42
- package/test/convo/transcript.spec.js +93 -1
- package/test/hooks/customhooks.spec.js +3 -5
- package/test/scripting/helper.spec.js +21 -0
- package/test/scripting/logichooks/localvsglobal.spec.js +105 -0
- package/test/scripting/scriptingProvider.spec.js +34 -0
package/src/scripting/Convo.js
CHANGED
|
@@ -277,6 +277,10 @@ class Convo {
|
|
|
277
277
|
let skipTranscriptStep = false
|
|
278
278
|
let conditionalGroupId = null
|
|
279
279
|
let conditionMetInGroup = false
|
|
280
|
+
let skipOptionalStep = false
|
|
281
|
+
// If there are optional step(s) in the conversation, and the message from the bot fails on each optional bot step(s) and/or mandatory bot step, then we have an unexpected message.
|
|
282
|
+
// So in this case an unexpected error should be shown instead of the latest assertion error.
|
|
283
|
+
let optionalStepAssertionError = false
|
|
280
284
|
let globalConvoStepParameters = container.caps[Capabilities.SCRIPTING_CONVO_STEP_PARAMETERS] || {}
|
|
281
285
|
let retryBotMessageTimeoutEnd = null
|
|
282
286
|
let retryBotMessageConvoId = null
|
|
@@ -284,6 +288,13 @@ class Convo {
|
|
|
284
288
|
for (let i = 0; i < this.conversation.length; i = (retryBotMessageDropBotResponse ? i : i + 1)) {
|
|
285
289
|
retryBotMessageDropBotResponse = false
|
|
286
290
|
const convoStep = this.conversation[i]
|
|
291
|
+
if (!convoStep.optional) {
|
|
292
|
+
skipOptionalStep = false
|
|
293
|
+
}
|
|
294
|
+
if (convoStep.optional && skipOptionalStep) {
|
|
295
|
+
// If there are multiple optional steps, and the previous optional step was timeout, then the next optional step should be skipped to prevent too long convo run with multiple timeout.
|
|
296
|
+
continue
|
|
297
|
+
}
|
|
287
298
|
const rawConvoStepParameters = convoStep.logicHooks.find(lh => lh.name === 'CONVO_STEP_PARAMETERS')?.args
|
|
288
299
|
let convoStepParameters = {}
|
|
289
300
|
if (rawConvoStepParameters && rawConvoStepParameters.length) {
|
|
@@ -426,7 +437,8 @@ class Convo {
|
|
|
426
437
|
} catch (err) {
|
|
427
438
|
transcriptStep.botEnd = new Date()
|
|
428
439
|
|
|
429
|
-
if (convoStep.optional) {
|
|
440
|
+
if (!(err.message.indexOf('Bot did not respond within') < 0) && convoStep.optional) {
|
|
441
|
+
skipOptionalStep = true
|
|
430
442
|
continue
|
|
431
443
|
}
|
|
432
444
|
|
|
@@ -512,6 +524,7 @@ class Convo {
|
|
|
512
524
|
}
|
|
513
525
|
waitForBotSays = false
|
|
514
526
|
skipTranscriptStep = true
|
|
527
|
+
optionalStepAssertionError = true
|
|
515
528
|
return true
|
|
516
529
|
} else if (retryOn) {
|
|
517
530
|
if (!retryBotMessageTimeoutEnd || retryBotMessageConvoId !== convoStep.stepTag) {
|
|
@@ -531,9 +544,18 @@ class Convo {
|
|
|
531
544
|
}
|
|
532
545
|
|
|
533
546
|
if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS]) {
|
|
534
|
-
|
|
547
|
+
if (optionalStepAssertionError) {
|
|
548
|
+
optionalStepAssertionError = false
|
|
549
|
+
assertErrors.push(new BotiumError(`${this.header.name}: Unexpected message.`))
|
|
550
|
+
} else {
|
|
551
|
+
assertErrors.push(err)
|
|
552
|
+
}
|
|
535
553
|
return false
|
|
536
554
|
} else {
|
|
555
|
+
if (optionalStepAssertionError) {
|
|
556
|
+
optionalStepAssertionError = false
|
|
557
|
+
throw new BotiumError(`${this.header.name}: Unexpected message.`)
|
|
558
|
+
}
|
|
537
559
|
throw err
|
|
538
560
|
}
|
|
539
561
|
}
|
|
@@ -547,6 +569,7 @@ class Convo {
|
|
|
547
569
|
if (convoStep.not) {
|
|
548
570
|
try {
|
|
549
571
|
this.scriptingEvents.assertBotNotResponse(response, tomatch, `${this.header.name}/${convoStep.stepTag}`, lastMeConvoStep, convoStepParameters)
|
|
572
|
+
optionalStepAssertionError = false
|
|
550
573
|
} catch (err) {
|
|
551
574
|
if (isErrorHandledWithOptionConvoStep(err)) {
|
|
552
575
|
continue
|
|
@@ -555,6 +578,7 @@ class Convo {
|
|
|
555
578
|
} else {
|
|
556
579
|
try {
|
|
557
580
|
this.scriptingEvents.assertBotResponse(response, tomatch, `${this.header.name}/${convoStep.stepTag}`, lastMeConvoStep, convoStepParameters)
|
|
581
|
+
optionalStepAssertionError = false
|
|
558
582
|
} catch (err) {
|
|
559
583
|
if (isErrorHandledWithOptionConvoStep(err)) {
|
|
560
584
|
continue
|
|
@@ -564,6 +588,7 @@ class Convo {
|
|
|
564
588
|
} else if (convoStep.sourceData) {
|
|
565
589
|
try {
|
|
566
590
|
this._compareObject(container, scriptingMemory, convoStep, botMsg.sourceData, convoStep.sourceData, botMsg, convoStepParameters)
|
|
591
|
+
optionalStepAssertionError = false
|
|
567
592
|
} catch (err) {
|
|
568
593
|
if (isErrorHandledWithOptionConvoStep(err)) {
|
|
569
594
|
continue
|
|
@@ -574,11 +599,13 @@ class Convo {
|
|
|
574
599
|
try {
|
|
575
600
|
await this.scriptingEvents.assertConvoStep({ convo: this, convoStep, container, scriptingMemory, botMsg, transcript, transcriptStep })
|
|
576
601
|
await this.scriptingEvents.onBotEnd({ convo: this, convoStep, container, scriptingMemory, botMsg, transcript, transcriptStep })
|
|
602
|
+
optionalStepAssertionError = false
|
|
577
603
|
} catch (err) {
|
|
578
604
|
const nextConvoStep = this.conversation[i + 1]
|
|
579
605
|
if (convoStep.optional && nextConvoStep && nextConvoStep.sender === 'bot') {
|
|
580
606
|
waitForBotSays = false
|
|
581
607
|
skipTranscriptStep = true
|
|
608
|
+
optionalStepAssertionError = true
|
|
582
609
|
continue
|
|
583
610
|
}
|
|
584
611
|
|
|
@@ -611,8 +638,17 @@ class Convo {
|
|
|
611
638
|
} catch (failErr) {
|
|
612
639
|
}
|
|
613
640
|
if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS] && err instanceof BotiumError) {
|
|
614
|
-
|
|
641
|
+
if (optionalStepAssertionError) {
|
|
642
|
+
optionalStepAssertionError = false
|
|
643
|
+
assertErrors.push(new BotiumError(`${this.header.name}: Unexpected message.`))
|
|
644
|
+
} else {
|
|
645
|
+
assertErrors.push(err)
|
|
646
|
+
}
|
|
615
647
|
} else {
|
|
648
|
+
if (optionalStepAssertionError) {
|
|
649
|
+
optionalStepAssertionError = false
|
|
650
|
+
throw new BotiumError(`${this.header.name}: Unexpected message.`)
|
|
651
|
+
}
|
|
616
652
|
throw failErr
|
|
617
653
|
}
|
|
618
654
|
}
|
|
@@ -789,7 +825,7 @@ class Convo {
|
|
|
789
825
|
}
|
|
790
826
|
|
|
791
827
|
_checkNormalizeText (container, str) {
|
|
792
|
-
return normalizeText(str,
|
|
828
|
+
return normalizeText(str, container.caps)
|
|
793
829
|
}
|
|
794
830
|
|
|
795
831
|
expandPartialConvos () {
|
|
@@ -83,9 +83,9 @@ module.exports = class ScriptingProvider {
|
|
|
83
83
|
this.utterances = {}
|
|
84
84
|
this.matchFn = null
|
|
85
85
|
this.asserters = {}
|
|
86
|
-
this.
|
|
86
|
+
this.globalAsserters = {}
|
|
87
87
|
this.logicHooks = {}
|
|
88
|
-
this.
|
|
88
|
+
this.globalLogicHooks = {}
|
|
89
89
|
this.userInputs = {}
|
|
90
90
|
this.partialConvos = {}
|
|
91
91
|
this.scriptingMemories = []
|
|
@@ -319,8 +319,9 @@ module.exports = class ScriptingProvider {
|
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
-
const
|
|
323
|
-
|
|
322
|
+
const localAsserters = (asserters || []).filter(a => this.asserters[a.name][asserterType])
|
|
323
|
+
|
|
324
|
+
const convoStepPromises = localAsserters
|
|
324
325
|
.map(a => ({
|
|
325
326
|
asserter: a,
|
|
326
327
|
promise: callAsserter(a, this.asserters[a.name], {
|
|
@@ -335,8 +336,12 @@ module.exports = class ScriptingProvider {
|
|
|
335
336
|
}))
|
|
336
337
|
.map(({ promise, asserter }) => updateExceptionContext(promise, asserter))
|
|
337
338
|
|
|
338
|
-
const
|
|
339
|
+
const globalAsserters = Object.keys(this.globalAsserters)
|
|
340
|
+
.filter(name => localAsserters.map(a => a.name).indexOf(name) < 0)
|
|
341
|
+
.reduce((agg, name) => [...agg, this.globalAsserters[name]], [])
|
|
339
342
|
.filter(a => a[asserterType])
|
|
343
|
+
|
|
344
|
+
const globalPromises = globalAsserters
|
|
340
345
|
.map(a => ({
|
|
341
346
|
asserter: a,
|
|
342
347
|
promise: p(this.retryHelperAsserter, () => a[asserterType]({
|
|
@@ -351,7 +356,7 @@ module.exports = class ScriptingProvider {
|
|
|
351
356
|
}))
|
|
352
357
|
.map(({ promise, asserter }) => updateExceptionContext(promise, asserter))
|
|
353
358
|
|
|
354
|
-
const allPromises = [...
|
|
359
|
+
const allPromises = [...convoStepPromises, ...globalPromises]
|
|
355
360
|
if (this.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS]) {
|
|
356
361
|
return Promise.allSettled(allPromises).then((results) => {
|
|
357
362
|
const rejected = results.filter(result => result.status === 'rejected').map(result => result.reason)
|
|
@@ -372,8 +377,7 @@ module.exports = class ScriptingProvider {
|
|
|
372
377
|
throw Error(`Unknown hookType ${hookType}`)
|
|
373
378
|
}
|
|
374
379
|
|
|
375
|
-
const localHooks = (logicHooks || [])
|
|
376
|
-
.filter(l => this.logicHooks[l.name][hookType])
|
|
380
|
+
const localHooks = (logicHooks || []).filter(l => this.logicHooks[l.name][hookType])
|
|
377
381
|
|
|
378
382
|
const convoStepPromises = localHooks
|
|
379
383
|
.map(l => p(this.retryHelperLogicHook, () => this.logicHooks[l.name][hookType]({
|
|
@@ -386,7 +390,10 @@ module.exports = class ScriptingProvider {
|
|
|
386
390
|
...rest
|
|
387
391
|
})))
|
|
388
392
|
|
|
389
|
-
const globalHooks = Object.
|
|
393
|
+
const globalHooks = Object.keys(this.globalLogicHooks)
|
|
394
|
+
.filter(name => localHooks.map(l => l.name).indexOf(name) < 0)
|
|
395
|
+
.reduce((agg, name) => [...agg, this.globalLogicHooks[name]], [])
|
|
396
|
+
.filter(l => l[hookType])
|
|
390
397
|
const globalPromises = globalHooks.map(l => p(this.retryHelperLogicHook, () => l[hookType]({ convo, convoStep, scriptingMemory, container, args: [], isGlobal: true, ...rest })))
|
|
391
398
|
|
|
392
399
|
const allPromises = [...convoStepPromises, ...globalPromises]
|
|
@@ -499,9 +506,9 @@ module.exports = class ScriptingProvider {
|
|
|
499
506
|
|
|
500
507
|
const logicHookUtils = new LogicHookUtils({ buildScriptContext: this._buildScriptContext(), caps: this.caps })
|
|
501
508
|
this.asserters = logicHookUtils.asserters
|
|
502
|
-
this.
|
|
509
|
+
this.globalAsserters = logicHookUtils.getGlobalAsserters()
|
|
503
510
|
this.logicHooks = logicHookUtils.logicHooks
|
|
504
|
-
this.
|
|
511
|
+
this.globalLogicHooks = logicHookUtils.getGlobalLogicHooks()
|
|
505
512
|
this.userInputs = logicHookUtils.userInputs
|
|
506
513
|
}
|
|
507
514
|
|
package/src/scripting/helper.js
CHANGED
|
@@ -4,9 +4,35 @@ const speechScorer = require('word-error-rate')
|
|
|
4
4
|
const debug = require('debug')('botium-core-scripting-helper')
|
|
5
5
|
|
|
6
6
|
const { E_SCRIPTING_MEMORY_COLUMN_MODE } = require('../Enums')
|
|
7
|
+
const Capabilities = require('../Capabilities')
|
|
7
8
|
const WHITE_SPACES_EXCEPT_SPACE_CHAR_AT_THE_END = /[\n\t\r]+$/
|
|
8
9
|
|
|
9
|
-
const normalizeText = (str,
|
|
10
|
+
const normalizeText = (str, doCleanupOrCaps) => {
|
|
11
|
+
// TODO testlog
|
|
12
|
+
debug('yxc1', doCleanupOrCaps)
|
|
13
|
+
let basic
|
|
14
|
+
let charactersRemove = false
|
|
15
|
+
let regexpRemove = false
|
|
16
|
+
if (_.isBoolean(doCleanupOrCaps) || _.isNil(doCleanupOrCaps)) {
|
|
17
|
+
debug('Normalize text: backward compatibility mode. Use caps instead of boolean flag')
|
|
18
|
+
basic = !!doCleanupOrCaps
|
|
19
|
+
} else {
|
|
20
|
+
const caps = doCleanupOrCaps
|
|
21
|
+
basic = !!caps[Capabilities.SCRIPTING_NORMALIZE_TEXT]
|
|
22
|
+
if (caps[Capabilities.SCRIPTING_NORMALIZE_TEXT_REMOVE_CHARACTERES]) {
|
|
23
|
+
charactersRemove = caps[Capabilities.SCRIPTING_NORMALIZE_TEXT_REMOVE_CHARACTERES]
|
|
24
|
+
if (_.isString(charactersRemove)) {
|
|
25
|
+
const splitted = charactersRemove.split(/(?<!\/),/).map(e => e.trim()).map(e => e.split('/,').join(',').split('//').join('/')).filter(c => c.length > 0)
|
|
26
|
+
charactersRemove = splitted.length ? splitted : [charactersRemove]
|
|
27
|
+
} else if (!_.isArray(charactersRemove)) {
|
|
28
|
+
charactersRemove = false
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (caps[Capabilities.SCRIPTING_NORMALIZE_TEXT_REMOVE_REGEXP]) {
|
|
32
|
+
regexpRemove = new RegExp(caps[Capabilities.SCRIPTING_NORMALIZE_TEXT_REMOVE_REGEXP], 'ug')
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
10
36
|
if (str && _.isArray(str)) {
|
|
11
37
|
str = str.join(' ')
|
|
12
38
|
} else if (str && !_.isString(str)) {
|
|
@@ -16,27 +42,38 @@ const normalizeText = (str, doCleanup) => {
|
|
|
16
42
|
str = `${str}`
|
|
17
43
|
}
|
|
18
44
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
|
|
46
|
+
if (str) {
|
|
47
|
+
if (basic) {
|
|
48
|
+
// remove html tags
|
|
49
|
+
str = str.replace(/<p[^>]*>/g, ' ')
|
|
50
|
+
str = str.replace(/<\/p>/g, ' ')
|
|
51
|
+
str = str.replace(/<br[^>]*>/g, ' ')
|
|
52
|
+
str = str.replace(/<[^>]*>/g, '')
|
|
53
|
+
/* eslint-disable no-control-regex */
|
|
54
|
+
// remove not printable characters
|
|
55
|
+
str = str.replace(/[\x00-\x1F\x7F]/g, ' ')
|
|
56
|
+
/* eslint-enable no-control-regex */
|
|
57
|
+
// replace html entities
|
|
58
|
+
str = str
|
|
59
|
+
.replace(/&/g, '&')
|
|
60
|
+
.replace(/</g, '<')
|
|
61
|
+
.replace(/>/g, '>')
|
|
62
|
+
.replace(/'/g, '\'')
|
|
63
|
+
.replace(/"/g, '"')
|
|
64
|
+
// replace two spaces with one
|
|
65
|
+
str = str.replace(/\s+/g, ' ')
|
|
66
|
+
|
|
67
|
+
str = str.split('\n').map(s => s.trim()).join('\n').trim()
|
|
68
|
+
}
|
|
69
|
+
if (charactersRemove) {
|
|
70
|
+
for (const character of charactersRemove) {
|
|
71
|
+
str = str.split(character).join('')
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (regexpRemove) {
|
|
75
|
+
str = str.replace(regexpRemove, '')
|
|
76
|
+
}
|
|
40
77
|
}
|
|
41
78
|
return str
|
|
42
79
|
}
|
|
@@ -24,9 +24,9 @@ const _ = require('lodash')
|
|
|
24
24
|
module.exports = class LogicHookUtils {
|
|
25
25
|
constructor ({ buildScriptContext, caps }) {
|
|
26
26
|
this.asserters = {}
|
|
27
|
-
this.
|
|
27
|
+
this.globalAsserterNames = []
|
|
28
28
|
this.logicHooks = {}
|
|
29
|
-
this.
|
|
29
|
+
this.globalLogicHookNames = []
|
|
30
30
|
this.userInputs = {}
|
|
31
31
|
this.buildScriptContext = buildScriptContext
|
|
32
32
|
this.caps = caps
|
|
@@ -64,7 +64,7 @@ module.exports = class LogicHookUtils {
|
|
|
64
64
|
}
|
|
65
65
|
this.asserters[asserter.ref] = this._loadClass(asserter, 'asserter')
|
|
66
66
|
if (asserter.global) {
|
|
67
|
-
this.
|
|
67
|
+
this.globalAsserterNames.push(asserter.ref)
|
|
68
68
|
}
|
|
69
69
|
})
|
|
70
70
|
}
|
|
@@ -77,7 +77,7 @@ module.exports = class LogicHookUtils {
|
|
|
77
77
|
}
|
|
78
78
|
this.logicHooks[logicHook.ref] = this._loadClass(logicHook, 'logichook')
|
|
79
79
|
if (logicHook.global) {
|
|
80
|
-
this.
|
|
80
|
+
this.globalLogicHookNames.push(logicHook.ref)
|
|
81
81
|
}
|
|
82
82
|
})
|
|
83
83
|
}
|
|
@@ -92,14 +92,12 @@ module.exports = class LogicHookUtils {
|
|
|
92
92
|
})
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
return this.
|
|
97
|
-
.map(name => this.asserters[name])
|
|
95
|
+
getGlobalAsserters () {
|
|
96
|
+
return this.globalAsserterNames.reduce((agg, name) => ({ ...agg, [name]: this.asserters[name] }), {})
|
|
98
97
|
}
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
return this.
|
|
102
|
-
.map(name => this.logicHooks[name])
|
|
99
|
+
getGlobalLogicHooks () {
|
|
100
|
+
return this.globalLogicHookNames.reduce((agg, name) => ({ ...agg, [name]: this.logicHooks[name] }), {})
|
|
103
101
|
}
|
|
104
102
|
|
|
105
103
|
_loadClass ({ src, ref, args }, hookType) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const Capabilities = require('../../../Capabilities')
|
|
2
1
|
const { BotiumError } = require('../../BotiumError')
|
|
3
2
|
const { normalizeText, toString } = require('../../helper')
|
|
4
3
|
const _ = require('lodash')
|
|
@@ -16,7 +15,7 @@ module.exports = class BaseTextAsserter {
|
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
_checkNormalizeText (str) {
|
|
19
|
-
return normalizeText(str,
|
|
18
|
+
return normalizeText(str, this.caps)
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
_normalize (botresponse) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const _ = require('lodash')
|
|
2
|
-
const { SCRIPTING_NORMALIZE_TEXT } = require('../../../Capabilities')
|
|
3
2
|
const { BotiumError } = require('../../BotiumError')
|
|
4
3
|
const { buttonsFromMsg } = require('../helpers')
|
|
5
4
|
const { normalizeText } = require('../../helper')
|
|
@@ -12,7 +11,7 @@ module.exports = class ButtonsAsserter {
|
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
_evalButtons (args, botMsg) {
|
|
15
|
-
const allButtons = buttonsFromMsg(botMsg, true).map(b => ({ text: b.text, payload: b.payload })).filter(b => b).map(b => ({ text: normalizeText(b.text,
|
|
14
|
+
const allButtons = buttonsFromMsg(botMsg, true).map(b => ({ text: b.text, payload: b.payload })).filter(b => b).map(b => ({ text: normalizeText(b.text, this.caps), payload: b.payload }))
|
|
16
15
|
if (!args || args.length === 0) {
|
|
17
16
|
return { allButtons, buttonsNotFound: [], buttonsFound: allButtons.map(b => b.text) }
|
|
18
17
|
}
|
|
@@ -29,8 +28,8 @@ module.exports = class ButtonsAsserter {
|
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
30
|
for (let i = 0; i < (args || []).length; i++) {
|
|
32
|
-
const matchByText = allButtons.some(b => this.context.Match(b.text, normalizeText(args[i],
|
|
33
|
-
const matchByPayload = allButtons.some(b => this.context.Match(stringifyPayload(b.payload), normalizeText(args[i],
|
|
31
|
+
const matchByText = allButtons.some(b => this.context.Match(b.text, normalizeText(args[i], this.caps)))
|
|
32
|
+
const matchByPayload = allButtons.some(b => this.context.Match(stringifyPayload(b.payload), normalizeText(args[i], this.caps)))
|
|
34
33
|
if (matchByText || matchByPayload) {
|
|
35
34
|
buttonsFound.push(args[i])
|
|
36
35
|
} else {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const path = require('path')
|
|
3
|
-
const
|
|
4
|
-
const request = require('request')
|
|
3
|
+
const globSync = require('tinyglobby').globSync
|
|
5
4
|
const mime = require('mime-types')
|
|
6
5
|
const url = require('url')
|
|
7
6
|
const _ = require('lodash')
|
|
@@ -119,24 +118,22 @@ module.exports = class MediaInput {
|
|
|
119
118
|
throw new Error(`downloadMedia failed: ${err.message}`)
|
|
120
119
|
}
|
|
121
120
|
} else if (uri.protocol === 'http:' || uri.protocol === 'https:') {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
uri: uri.toString(),
|
|
121
|
+
try {
|
|
122
|
+
const response = await fetch(uri.toString(), {
|
|
125
123
|
method: 'GET',
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
timeout: this.globalArgs.downloadTimeout || 10000
|
|
129
|
-
}, (err, response, body) => {
|
|
130
|
-
if (err) {
|
|
131
|
-
reject(new Error(`downloadMedia failed: ${err.message}`))
|
|
132
|
-
} else {
|
|
133
|
-
if (response.statusCode >= 400) {
|
|
134
|
-
return reject(new Error(`downloadMedia failed: ${response.statusCode}/${response.statusMessage}`))
|
|
135
|
-
}
|
|
136
|
-
resolve(body)
|
|
137
|
-
}
|
|
124
|
+
redirect: 'follow', // Follows all redirects
|
|
125
|
+
timeout: this.globalArgs?.downloadTimeout || 10000
|
|
138
126
|
})
|
|
139
|
-
|
|
127
|
+
|
|
128
|
+
if (!response.ok) {
|
|
129
|
+
throw new Error(`downloadMedia failed: ${response.status}/${response.statusText}`)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const arrayBuffer = await response.arrayBuffer()
|
|
133
|
+
return Buffer.from(arrayBuffer)
|
|
134
|
+
} catch (err) {
|
|
135
|
+
throw new Error(`downloadMedia failed: ${err.message}`)
|
|
136
|
+
}
|
|
140
137
|
} else if (uri.protocol === 'data:') {
|
|
141
138
|
return Buffer.from(uri.href.split(',')[1], 'base64')
|
|
142
139
|
}
|
|
@@ -161,7 +158,7 @@ module.exports = class MediaInput {
|
|
|
161
158
|
const baseDir = this._getBaseDir(convo)
|
|
162
159
|
return args.reduce((e, arg) => {
|
|
163
160
|
if (this._isWildcard(arg)) {
|
|
164
|
-
const mediaFiles =
|
|
161
|
+
const mediaFiles = globSync(arg, { cwd: baseDir })
|
|
165
162
|
mediaFiles.forEach(mf => {
|
|
166
163
|
e.push({
|
|
167
164
|
name: 'MEDIA',
|
|
@@ -252,6 +252,24 @@ describe('compiler.compilertxt', function () {
|
|
|
252
252
|
assert.equal(convo.conversation[0].logicHooks.length, 0)
|
|
253
253
|
assert.equal(convo.conversation[1].messageText, 'Hi')
|
|
254
254
|
})
|
|
255
|
+
// connectors might handle json format differently
|
|
256
|
+
it('should read json as message', async function () {
|
|
257
|
+
const scriptBuffer = fs.readFileSync(path.resolve(__dirname, CONVOS_DIR, 'convos_jsonmessage.convo.txt'))
|
|
258
|
+
const context = buildContext()
|
|
259
|
+
|
|
260
|
+
const caps = {}
|
|
261
|
+
const compiler = new Compiler(context, Object.assign({}, DefaultCapabilities, caps))
|
|
262
|
+
|
|
263
|
+
compiler.Compile(scriptBuffer, 'SCRIPTING_TYPE_CONVO')
|
|
264
|
+
assert.deepEqual(context.convos[0].conversation[0].sourceData, {
|
|
265
|
+
sessionId: '1234567890876543',
|
|
266
|
+
text: 'Text message',
|
|
267
|
+
data: {
|
|
268
|
+
key: 'value'
|
|
269
|
+
}
|
|
270
|
+
})
|
|
271
|
+
assert.equal(!!context.convos[0].conversation[0].messageText, false)
|
|
272
|
+
})
|
|
255
273
|
|
|
256
274
|
describe('compiler.compilertxt.logichooks', function () {
|
|
257
275
|
it('should read logicHook if there is just logicHook', async function () {
|