botium-core 1.11.16 → 1.12.3
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/dist/botium-cjs.js +493 -202
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +484 -194
- package/dist/botium-es.js.map +1 -1
- package/index.js +1 -0
- package/package.json +29 -29
- package/samples/connectors/custom/botium-connector-myapi.js +3 -3
- package/samples/extensions/asserterHooks/DummyAsserter.js +3 -3
- package/src/BotDriver.js +3 -3
- package/src/Capabilities.js +9 -0
- package/src/Defaults.js +1 -1
- package/src/Enums.js +6 -0
- package/src/containers/BaseContainer.js +20 -10
- package/src/containers/PluginConnectorContainer.js +1 -0
- package/src/containers/plugins/SimpleRestContainer.js +98 -30
- package/src/scripting/BotiumError.js +21 -0
- package/src/scripting/CompilerCsv.js +1 -1
- package/src/scripting/CompilerObjectBase.js +4 -14
- package/src/scripting/CompilerTxt.js +4 -15
- package/src/scripting/CompilerXlsx.js +81 -25
- package/src/scripting/Convo.js +16 -4
- package/src/scripting/ScriptingProvider.js +6 -0
- package/src/scripting/helper.js +54 -1
- package/src/scripting/logichook/LogicHookUtils.js +2 -0
- package/src/scripting/logichook/asserter/JsonPathAsserter.js +1 -1
- package/src/scripting/logichook/logichooks/ClearQueueLogicHook.js +1 -1
- package/src/scripting/logichook/userinput/MediaInput.js +14 -2
- package/test/connectors/convos/hello.convo.txt +6 -0
- package/test/connectors/simplerest.spec.js +106 -2
- package/test/convo/convos/continuefailing.convo.txt +19 -0
- package/test/convo/transcript.spec.js +34 -0
- package/test/scripting/scriptingProvider.spec.js +4 -4
- package/test/scripting/scriptingmemory/convosMultiMemorySameCols/buy.convo.txt +6 -0
- package/test/scripting/scriptingmemory/convosMultiMemorySameCols/products1.scriptingmemory.txt +2 -0
- package/test/scripting/scriptingmemory/convosMultiMemorySameCols/products2.scriptingmemory.txt +2 -0
- package/test/scripting/scriptingmemory/convosSimpleCols/buy.convo.txt +8 -0
- package/test/scripting/scriptingmemory/convosSimpleCols/product.scriptingmemory.txt +3 -0
- package/test/scripting/scriptingmemory/convosTwoTablesCols/buy.convo.txt +6 -0
- package/test/scripting/scriptingmemory/convosTwoTablesCols/customer.xlsx +0 -0
- package/test/scripting/scriptingmemory/convosTwoTablesCols/product.xlsx +0 -0
- package/test/scripting/scriptingmemory/fillScriptingMemoryFromFile.spec.js +45 -0
- package/test/scripting/userinputs/mediaInputConvos.spec.js +53 -2
package/index.js
CHANGED
|
@@ -4,6 +4,7 @@ module.exports = {
|
|
|
4
4
|
ScriptingConstants: require('./src/scripting/Constants'),
|
|
5
5
|
Capabilities: require('./src/Capabilities'),
|
|
6
6
|
Defaults: require('./src/Defaults'),
|
|
7
|
+
Enums: require('./src/Enums'),
|
|
7
8
|
Source: require('./src/Source'),
|
|
8
9
|
Events: require('./src/Events'),
|
|
9
10
|
Plugins: require('./src/Plugins'),
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "botium-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.3",
|
|
4
4
|
"description": "The Selenium for Chatbots",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/botium-es.js",
|
|
7
7
|
"engines": {
|
|
8
|
-
"node": ">=
|
|
8
|
+
"node": ">=14.0.0"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"postinstall": "node ./report.js",
|
|
@@ -32,23 +32,23 @@
|
|
|
32
32
|
},
|
|
33
33
|
"homepage": "https://www.botium.ai",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@babel/runtime": "^7.
|
|
36
|
-
"async": "^3.2.
|
|
37
|
-
"body-parser": "^1.19.
|
|
35
|
+
"@babel/runtime": "^7.17.2",
|
|
36
|
+
"async": "^3.2.3",
|
|
37
|
+
"body-parser": "^1.19.1",
|
|
38
38
|
"boolean": "^3.1.4",
|
|
39
39
|
"bottleneck": "^2.19.5",
|
|
40
|
-
"csv-parse": "^
|
|
41
|
-
"debug": "^4.3.
|
|
40
|
+
"csv-parse": "^5.0.4",
|
|
41
|
+
"debug": "^4.3.3",
|
|
42
42
|
"esprima": "^4.0.1",
|
|
43
|
-
"express": "^4.17.
|
|
43
|
+
"express": "^4.17.2",
|
|
44
44
|
"globby": "11.0.4",
|
|
45
|
-
"ioredis": "^4.28.
|
|
45
|
+
"ioredis": "^4.28.5",
|
|
46
46
|
"is-class": "^0.0.9",
|
|
47
47
|
"is-json": "^2.0.1",
|
|
48
48
|
"jsonpath": "^1.1.1",
|
|
49
49
|
"lodash": "^4.17.21",
|
|
50
|
-
"markdown-it": "^12.2
|
|
51
|
-
"mime-types": "^2.1.
|
|
50
|
+
"markdown-it": "^12.3.2",
|
|
51
|
+
"mime-types": "^2.1.34",
|
|
52
52
|
"mkdirp": "^1.0.4",
|
|
53
53
|
"moment": "^2.29.1",
|
|
54
54
|
"mustache": "^4.2.0",
|
|
@@ -58,40 +58,40 @@
|
|
|
58
58
|
"request": "^2.88.2",
|
|
59
59
|
"rimraf": "^3.0.2",
|
|
60
60
|
"sanitize-filename": "^1.6.3",
|
|
61
|
-
"slugify": "^1.6.
|
|
62
|
-
"socket.io": "^4.
|
|
63
|
-
"socket.io-client": "^4.
|
|
61
|
+
"slugify": "^1.6.5",
|
|
62
|
+
"socket.io": "^4.4.1",
|
|
63
|
+
"socket.io-client": "^4.4.1",
|
|
64
64
|
"socketio-auth": "^0.1.1",
|
|
65
65
|
"swagger-jsdoc": "^6.1.0",
|
|
66
|
-
"swagger-ui-express": "^4.
|
|
66
|
+
"swagger-ui-express": "^4.3.0",
|
|
67
67
|
"uuid": "^8.3.2",
|
|
68
|
-
"vm2": "^3.9.
|
|
68
|
+
"vm2": "^3.9.7",
|
|
69
69
|
"write-yaml": "^1.0.0",
|
|
70
|
-
"xlsx": "^0.
|
|
70
|
+
"xlsx": "^0.18.2",
|
|
71
71
|
"xregexp": "^5.1.0",
|
|
72
72
|
"yaml": "^1.10.2"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
|
-
"@babel/core": "^7.
|
|
76
|
-
"@babel/node": "^7.16.
|
|
77
|
-
"@babel/plugin-transform-runtime": "^7.
|
|
78
|
-
"@babel/preset-env": "^7.16.
|
|
79
|
-
"chai": "^4.3.
|
|
75
|
+
"@babel/core": "^7.17.2",
|
|
76
|
+
"@babel/node": "^7.16.8",
|
|
77
|
+
"@babel/plugin-transform-runtime": "^7.17.0",
|
|
78
|
+
"@babel/preset-env": "^7.16.11",
|
|
79
|
+
"chai": "^4.3.6",
|
|
80
80
|
"chai-as-promised": "^7.1.1",
|
|
81
81
|
"cross-env": "^7.0.3",
|
|
82
|
-
"eslint": "^8.
|
|
82
|
+
"eslint": "^8.9.0",
|
|
83
83
|
"eslint-config-standard": "^16.0.3",
|
|
84
|
-
"eslint-plugin-import": "^2.25.
|
|
84
|
+
"eslint-plugin-import": "^2.25.4",
|
|
85
85
|
"eslint-plugin-node": "^11.1.0",
|
|
86
|
-
"eslint-plugin-promise": "^
|
|
86
|
+
"eslint-plugin-promise": "^6.0.0",
|
|
87
87
|
"eslint-plugin-standard": "^4.1.0",
|
|
88
88
|
"license-checker": "^25.0.1",
|
|
89
89
|
"license-compatibility-checker": "^0.3.5",
|
|
90
|
-
"mocha": "^9.
|
|
91
|
-
"nock": "^13.
|
|
92
|
-
"npm-check-updates": "^12.
|
|
90
|
+
"mocha": "^9.2.0",
|
|
91
|
+
"nock": "^13.2.4",
|
|
92
|
+
"npm-check-updates": "^12.3.0",
|
|
93
93
|
"nyc": "^15.1.0",
|
|
94
|
-
"rollup": "^2.
|
|
94
|
+
"rollup": "^2.67.2",
|
|
95
95
|
"rollup-plugin-babel": "^4.4.0",
|
|
96
96
|
"rollup-plugin-commonjs": "^10.1.0",
|
|
97
97
|
"rollup-plugin-json": "^4.0.0",
|
|
@@ -23,13 +23,13 @@ class BotiumConnectorMyApi {
|
|
|
23
23
|
[CoreCapabilities.SIMPLEREST_URL]: this.caps[Capabilities.MYAPI_URL],
|
|
24
24
|
[CoreCapabilities.SIMPLEREST_METHOD]: 'POST',
|
|
25
25
|
[CoreCapabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$.reply',
|
|
26
|
-
[CoreCapabilities.SIMPLEREST_BODY_TEMPLATE]: JSON.stringify({
|
|
26
|
+
[CoreCapabilities.SIMPLEREST_BODY_TEMPLATE]: JSON.stringify({
|
|
27
27
|
username: 'botium',
|
|
28
28
|
message: '{{msg.messageText}}',
|
|
29
29
|
session: '{{botium.conversationId}}',
|
|
30
30
|
startsession: false,
|
|
31
31
|
quickreply: null
|
|
32
|
-
|
|
32
|
+
})
|
|
33
33
|
}
|
|
34
34
|
if (this.caps[Capabilities.MYAPI_TOKEN]) {
|
|
35
35
|
this.delegateCaps[CoreCapabilities.SIMPLEREST_HEADERS_TEMPLATE] = `{ "Authorization": "Token ${this.caps[Capabilities.MYAPI_TOKEN]}"}`
|
|
@@ -104,4 +104,4 @@ module.exports = {
|
|
|
104
104
|
}
|
|
105
105
|
]
|
|
106
106
|
}
|
|
107
|
-
}
|
|
107
|
+
}
|
|
@@ -6,17 +6,17 @@ module.exports = class DummyAsserter {
|
|
|
6
6
|
this.caps = caps
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
assertConvoBegin ({convo, container, args}) {
|
|
9
|
+
assertConvoBegin ({ convo, container, args }) {
|
|
10
10
|
console.log(`Dummy asserter Begin started with those args: ${utils.inspect(args)}`)
|
|
11
11
|
return Promise.resolve()
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
assertConvoStep ({convo, convoStep, args, botMsg}) {
|
|
14
|
+
assertConvoStep ({ convo, convoStep, args, botMsg }) {
|
|
15
15
|
console.log(`ConvoStep dummy assertion with those args: ${utils.inspect(args)}, botMessage: ${utils.inspect(botMsg)} ...`)
|
|
16
16
|
return Promise.resolve()
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
assertConvoEnd ({convo, container, transcript, args}) {
|
|
19
|
+
assertConvoEnd ({ convo, container, transcript, args }) {
|
|
20
20
|
console.log(`ConvoEnd dummy assertion with those args: ${utils.inspect(args)}, transcript: ${utils.inspect(transcript)} ...`)
|
|
21
21
|
return Promise.resolve()
|
|
22
22
|
}
|
package/src/BotDriver.js
CHANGED
|
@@ -109,9 +109,9 @@ module.exports = class BotDriver {
|
|
|
109
109
|
|
|
110
110
|
Build () {
|
|
111
111
|
debug(`Build - Botium Core Version: ${version}`)
|
|
112
|
-
debug(`Build - Capabilites: ${
|
|
113
|
-
debug(`Build - Sources
|
|
114
|
-
debug(`Build - Envs
|
|
112
|
+
debug(`Build - Capabilites: ${JSON.stringify(_.pickBy(this.caps, (value, key) => Defaults.Capabilities[key] !== value), null, 2)}`)
|
|
113
|
+
debug(`Build - Sources: ${JSON.stringify(_.pickBy(this.sources, (value, key) => Defaults.Sources[key] !== value), null, 2)}`)
|
|
114
|
+
debug(`Build - Envs: ${JSON.stringify(_.pickBy(this.envs, (value, key) => Defaults.Envs[key] !== value), null, 2)}`)
|
|
115
115
|
this.eventEmitter.emit(Events.CONTAINER_BUILDING)
|
|
116
116
|
|
|
117
117
|
return new Promise((resolve, reject) => {
|
package/src/Capabilities.js
CHANGED
|
@@ -73,6 +73,11 @@ module.exports = {
|
|
|
73
73
|
SIMPLEREST_RESPONSE_HOOK: 'SIMPLEREST_RESPONSE_HOOK',
|
|
74
74
|
SIMPLEREST_MEDIA_JSONPATH: 'SIMPLEREST_MEDIA_JSONPATH',
|
|
75
75
|
SIMPLEREST_BUTTONS_JSONPATH: 'SIMPLEREST_BUTTONS_JSONPATH',
|
|
76
|
+
SIMPLEREST_CARDS_JSONPATH: 'SIMPLEREST_CARDS_JSONPATH',
|
|
77
|
+
SIMPLEREST_CARD_TEXT_JSONPATH: 'SIMPLEREST_CARD_TEXT_JSONPATH',
|
|
78
|
+
SIMPLEREST_CARD_SUBTEXT_JSONPATH: 'SIMPLEREST_CARD_SUBTEXT_JSONPATH',
|
|
79
|
+
SIMPLEREST_CARD_BUTTONS_JSONPATH: 'SIMPLEREST_CARD_BUTTONS_JSONPATH',
|
|
80
|
+
SIMPLEREST_CARD_ATTACHMENTS_JSONPATH: 'SIMPLEREST_CARD_ATTACHMENTS_JSONPATH',
|
|
76
81
|
SIMPLEREST_CONTEXT_JSONPATH: 'SIMPLEREST_CONTEXT_JSONPATH',
|
|
77
82
|
SIMPLEREST_CONTEXT_MERGE_OR_REPLACE: 'SIMPLEREST_CONTEXT_MERGE_OR_REPLACE',
|
|
78
83
|
SIMPLEREST_CONVERSATION_ID_TEMPLATE: 'SIMPLEREST_CONVERSATION_ID_TEMPLATE',
|
|
@@ -111,6 +116,7 @@ module.exports = {
|
|
|
111
116
|
SCRIPTING_NORMALIZE_TEXT: 'SCRIPTING_NORMALIZE_TEXT',
|
|
112
117
|
SCRIPTING_ENABLE_MEMORY: 'SCRIPTING_ENABLE_MEMORY',
|
|
113
118
|
SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS: 'SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS',
|
|
119
|
+
SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS: 'SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS',
|
|
114
120
|
SCRIPTING_FORCE_BOT_CONSUMED: 'SCRIPTING_FORCE_BOT_CONSUMED',
|
|
115
121
|
// regexp, regexpIgnoreCase, wildcard, wildcardIgnoreCase, wildcardExact, wildcardExactIgnoreCase, include, includeIgnoreCase, equals, equalsIgnoreCase
|
|
116
122
|
SCRIPTING_MATCHING_MODE: 'SCRIPTING_MATCHING_MODE',
|
|
@@ -126,6 +132,8 @@ module.exports = {
|
|
|
126
132
|
SCRIPTING_MEMORYEXPANSION_KEEP_ORIG: 'SCRIPTING_MEMORYEXPANSION_KEEP_ORIG',
|
|
127
133
|
// word, non_whitespace, joker
|
|
128
134
|
SCRIPTING_MEMORY_MATCHING_MODE: 'SCRIPTING_MEMORY_MATCHING_MODE',
|
|
135
|
+
// varnames, testcasenames
|
|
136
|
+
SCRIPTING_MEMORY_COLUMN_MODE: 'SCRIPTING_MEMORY_COLUMN_MODE',
|
|
129
137
|
// Botium Lifecycle Hooks
|
|
130
138
|
CUSTOMHOOK_ONBUILD: 'CUSTOMHOOK_ONBUILD',
|
|
131
139
|
CUSTOMHOOK_ONSTART: 'CUSTOMHOOK_ONSTART',
|
|
@@ -140,6 +148,7 @@ module.exports = {
|
|
|
140
148
|
// API Calls Rate Limiting
|
|
141
149
|
RATELIMIT_USERSAYS_MAXCONCURRENT: 'RATELIMIT_USERSAYS_MAXCONCURRENT',
|
|
142
150
|
RATELIMIT_USERSAYS_MINTIME: 'RATELIMIT_USERSAYS_MINTIME',
|
|
151
|
+
RATELIMIT_BOTTLENECK_FN: 'RATELIMIT_BOTTLENECK_FN',
|
|
143
152
|
SECURITY_ALLOW_UNSAFE: 'SECURITY_ALLOW_UNSAFE',
|
|
144
153
|
PRECOMPILERS: 'PRECOMPILERS'
|
|
145
154
|
}
|
package/src/Defaults.js
CHANGED
|
@@ -31,7 +31,6 @@ module.exports = {
|
|
|
31
31
|
[Capabilities.SIMPLEREST_METHOD]: 'GET',
|
|
32
32
|
[Capabilities.SIMPLEREST_IGNORE_EMPTY]: true,
|
|
33
33
|
[Capabilities.SIMPLEREST_TIMEOUT]: 10000,
|
|
34
|
-
[Capabilities.SIMPLEREST_EXTRA_OPTIONS]: {},
|
|
35
34
|
[Capabilities.SIMPLEREST_STRICT_SSL]: true,
|
|
36
35
|
[Capabilities.SIMPLEREST_INBOUND_UPDATE_CONTEXT]: true,
|
|
37
36
|
[Capabilities.SIMPLEREST_CONTEXT_MERGE_OR_REPLACE]: 'MERGE',
|
|
@@ -50,6 +49,7 @@ module.exports = {
|
|
|
50
49
|
[Capabilities.SCRIPTING_UTTEXPANSION_NAMING_MODE]: 'justLineTag',
|
|
51
50
|
[Capabilities.SCRIPTING_UTTEXPANSION_NAMING_UTTERANCE_MAX]: '16',
|
|
52
51
|
[Capabilities.SCRIPTING_MEMORYEXPANSION_KEEP_ORIG]: false,
|
|
52
|
+
[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]: false,
|
|
53
53
|
[Capabilities.SCRIPTING_FORCE_BOT_CONSUMED]: false,
|
|
54
54
|
[Capabilities.ASSERTERS]: [],
|
|
55
55
|
[Capabilities.LOGIC_HOOKS]: [],
|
package/src/Enums.js
ADDED
|
@@ -21,7 +21,7 @@ module.exports = class BaseContainer {
|
|
|
21
21
|
this.tempDirectory = tempDirectory
|
|
22
22
|
this.cleanupTasks = []
|
|
23
23
|
this.queues = {}
|
|
24
|
-
this.
|
|
24
|
+
this.bottleneck = null
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
Validate () {
|
|
@@ -32,18 +32,28 @@ module.exports = class BaseContainer {
|
|
|
32
32
|
this.onStopHook = getHook(this.caps, this.caps[Capabilities.CUSTOMHOOK_ONSTOP])
|
|
33
33
|
this.onCleanHook = getHook(this.caps, this.caps[Capabilities.CUSTOMHOOK_ONCLEAN])
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
if (this.caps[Capabilities.RATELIMIT_BOTTLENECK_FN]) {
|
|
36
|
+
if (_.isFunction(this.caps[Capabilities.RATELIMIT_BOTTLENECK_FN])) {
|
|
37
|
+
this.bottleneck = this.caps[Capabilities.RATELIMIT_BOTTLENECK_FN]
|
|
38
|
+
debug('Validate: Applying userSays rate limits from capability')
|
|
39
|
+
} else {
|
|
40
|
+
const limiter = new Bottleneck(this.caps[Capabilities.RATELIMIT_BOTTLENECK_FN])
|
|
41
|
+
this.bottleneck = (fn) => limiter.schedule(fn)
|
|
42
|
+
debug(`Validate: Applying userSays rate limits ${util.inspect(this.caps[Capabilities.RATELIMIT_BOTTLENECK_FN])}`)
|
|
43
|
+
}
|
|
44
|
+
} else if (this.caps[Capabilities.RATELIMIT_USERSAYS_MAXCONCURRENT] || this.caps[Capabilities.RATELIMIT_USERSAYS_MINTIME]) {
|
|
40
45
|
const opts = {}
|
|
41
46
|
if (this.caps[Capabilities.RATELIMIT_USERSAYS_MAXCONCURRENT]) opts.maxConcurrent = this.caps[Capabilities.RATELIMIT_USERSAYS_MAXCONCURRENT]
|
|
42
47
|
if (this.caps[Capabilities.RATELIMIT_USERSAYS_MINTIME]) opts.minTime = this.caps[Capabilities.RATELIMIT_USERSAYS_MINTIME]
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
const limiter = new Bottleneck(opts)
|
|
49
|
+
this.bottleneck = (fn) => limiter.schedule(fn)
|
|
50
|
+
debug(`Validate: Applying userSays rate limits ${util.inspect(opts)}`)
|
|
45
51
|
}
|
|
46
52
|
|
|
53
|
+
return Promise.resolve()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
Build () {
|
|
47
57
|
return new Promise((resolve, reject) => {
|
|
48
58
|
this._RunCustomHook('onBuild', this.onBuildHook)
|
|
49
59
|
.then(() => resolve(this))
|
|
@@ -69,8 +79,8 @@ module.exports = class BaseContainer {
|
|
|
69
79
|
const run = () => this._RunCustomHook('onUserSays', this.onUserSaysHook, { meMsg })
|
|
70
80
|
.then(() => this.UserSaysImpl(meMsg))
|
|
71
81
|
|
|
72
|
-
if (this.
|
|
73
|
-
return this.
|
|
82
|
+
if (this.bottleneck) {
|
|
83
|
+
return this.bottleneck(run)
|
|
74
84
|
} else {
|
|
75
85
|
return run()
|
|
76
86
|
}
|
|
@@ -17,13 +17,15 @@ const Defaults = require('../../Defaults').Capabilities
|
|
|
17
17
|
const { SCRIPTING_FUNCTIONS } = require('../../scripting/ScriptingMemory')
|
|
18
18
|
const { getHook, executeHook } = require('../../helpers/HookUtils')
|
|
19
19
|
const { escapeJSONString } = require('../../helpers/Utils')
|
|
20
|
+
const { BotiumError } = require('../../scripting/BotiumError')
|
|
20
21
|
|
|
21
22
|
Mustache.escape = s => s
|
|
22
23
|
|
|
23
24
|
module.exports = class SimpleRestContainer {
|
|
24
|
-
constructor ({ queueBotSays, caps }) {
|
|
25
|
+
constructor ({ queueBotSays, caps, bottleneck }) {
|
|
25
26
|
this.queueBotSays = queueBotSays
|
|
26
27
|
this.caps = Object.assign({}, Defaults, caps)
|
|
28
|
+
this.bottleneck = bottleneck || ((fn) => fn())
|
|
27
29
|
this.processInbound = false
|
|
28
30
|
this.redisTopic = this.caps[Capabilities.SIMPLEREST_REDIS_TOPIC] || 'SIMPLEREST_INBOUND_SUBSCRIPTION'
|
|
29
31
|
|
|
@@ -307,34 +309,82 @@ module.exports = class SimpleRestContainer {
|
|
|
307
309
|
}
|
|
308
310
|
|
|
309
311
|
for (const jsonPathRoot of jsonPathRoots) {
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
312
|
+
const _retrieveMedia = (jsonPathMediaRoot, jsonPathsMedia) => {
|
|
313
|
+
const retrievedMedia = []
|
|
314
|
+
jsonPathsMedia.forEach(jsonPath => {
|
|
315
|
+
const responseMedia = jp.query(jsonPathMediaRoot, jsonPath)
|
|
316
|
+
if (responseMedia) {
|
|
317
|
+
(_.isArray(responseMedia) ? _.flattenDeep(responseMedia) : [responseMedia]).forEach(m =>
|
|
318
|
+
retrievedMedia.push({
|
|
319
|
+
mediaUri: m,
|
|
320
|
+
mimeType: mime.lookup(m) || 'application/unknown'
|
|
321
|
+
})
|
|
322
|
+
)
|
|
323
|
+
}
|
|
324
|
+
})
|
|
325
|
+
return retrievedMedia
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const _retrieveButtons = (jsonPathButtonRoot, jsonPathsButtons) => {
|
|
329
|
+
const retrievedButtons = []
|
|
330
|
+
jsonPathsButtons.forEach(jsonPath => {
|
|
331
|
+
const responseButtons = jp.query(jsonPathButtonRoot, jsonPath)
|
|
332
|
+
if (responseButtons) {
|
|
333
|
+
(_.isArray(responseButtons) ? _.flattenDeep(responseButtons) : [responseButtons]).forEach(b =>
|
|
334
|
+
retrievedButtons.push({
|
|
335
|
+
text: b
|
|
336
|
+
})
|
|
337
|
+
)
|
|
338
|
+
}
|
|
339
|
+
})
|
|
340
|
+
return retrievedButtons
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const _getCardText = (responseCardText) => {
|
|
344
|
+
if (responseCardText) {
|
|
345
|
+
const texts = _.isArray(responseCardText) ? _.flattenDeep(responseCardText) : [responseCardText]
|
|
346
|
+
if (texts.length > 1) {
|
|
347
|
+
debug(`more than one text found for card: ${util.inspect(texts)}`)
|
|
348
|
+
}
|
|
349
|
+
if (texts.length > 0) {
|
|
350
|
+
return texts[0]
|
|
351
|
+
}
|
|
324
352
|
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const media = _retrieveMedia(jsonPathRoot, getAllCapValues(Capabilities.SIMPLEREST_MEDIA_JSONPATH, this.caps))
|
|
356
|
+
debug(`found response media: ${util.inspect(media)}`)
|
|
357
|
+
const buttons = _retrieveButtons(jsonPathRoot, getAllCapValues(Capabilities.SIMPLEREST_BUTTONS_JSONPATH, this.caps))
|
|
358
|
+
debug(`found response buttons: ${util.inspect(buttons)}`)
|
|
359
|
+
const cards = []
|
|
360
|
+
|
|
361
|
+
const jsonPathsCards = getAllCapValues(Capabilities.SIMPLEREST_CARDS_JSONPATH, this.caps)
|
|
362
|
+
jsonPathsCards.forEach(jsonPath => {
|
|
363
|
+
const responseCards = jp.query(jsonPathRoot, jsonPath)
|
|
364
|
+
if (responseCards) {
|
|
365
|
+
(_.isArray(responseCards) ? _.flattenDeep(responseCards) : [responseCards]).forEach(c => {
|
|
366
|
+
const card = {}
|
|
367
|
+
|
|
368
|
+
const jsonPathsCardText = getAllCapValues(Capabilities.SIMPLEREST_CARD_TEXT_JSONPATH, this.caps)
|
|
369
|
+
jsonPathsCardText.forEach(jsonPath => {
|
|
370
|
+
card.text = _getCardText(jp.query(c, jsonPath))
|
|
333
371
|
})
|
|
334
|
-
|
|
335
|
-
|
|
372
|
+
|
|
373
|
+
const jsonPathsCardSubText = getAllCapValues(Capabilities.SIMPLEREST_CARD_SUBTEXT_JSONPATH, this.caps)
|
|
374
|
+
jsonPathsCardSubText.forEach(jsonPath => {
|
|
375
|
+
card.subtext = _getCardText(jp.query(c, jsonPath))
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
card.buttons = _retrieveButtons(c, getAllCapValues(Capabilities.SIMPLEREST_CARD_BUTTONS_JSONPATH, this.caps))
|
|
379
|
+
card.media = _retrieveMedia(c, getAllCapValues(Capabilities.SIMPLEREST_CARD_ATTACHMENTS_JSONPATH, this.caps))
|
|
380
|
+
|
|
381
|
+
if (_.keys(card).length > 0) {
|
|
382
|
+
cards.push(card)
|
|
383
|
+
}
|
|
384
|
+
})
|
|
336
385
|
}
|
|
337
386
|
})
|
|
387
|
+
debug(`found response cards: ${util.inspect(cards)}`)
|
|
338
388
|
|
|
339
389
|
let hasMessageText = false
|
|
340
390
|
const jsonPathsTexts = getAllCapValues(Capabilities.SIMPLEREST_RESPONSE_JSONPATH, this.caps)
|
|
@@ -349,18 +399,18 @@ module.exports = class SimpleRestContainer {
|
|
|
349
399
|
if (!messageText) continue
|
|
350
400
|
|
|
351
401
|
hasMessageText = true
|
|
352
|
-
const botMsg = { sourceData: body, messageText, media, buttons }
|
|
402
|
+
const botMsg = { sourceData: body, messageText, media, buttons, cards }
|
|
353
403
|
await executeHook(this.caps, this.responseHook, Object.assign({ botMsg, botMsgRoot: jsonPathRoot, messageTextIndex }, this.view))
|
|
354
404
|
result.push(botMsg)
|
|
355
405
|
}
|
|
356
406
|
}
|
|
357
407
|
|
|
358
408
|
if (!hasMessageText) {
|
|
359
|
-
const botMsg = { messageText: '', sourceData: body, media, buttons }
|
|
409
|
+
const botMsg = { messageText: '', sourceData: body, media, buttons, cards }
|
|
360
410
|
const beforeHookKeys = Object.keys(botMsg)
|
|
361
411
|
await executeHook(this.caps, this.responseHook, Object.assign({ botMsg, botMsgRoot: jsonPathRoot }, this.view))
|
|
362
412
|
const afterHookKeys = Object.keys(botMsg)
|
|
363
|
-
if (beforeHookKeys.length !== afterHookKeys.length || !!(botMsg.messageText && botMsg.messageText.length > 0) || botMsg.media.length > 0 || botMsg.buttons.length > 0 || !this.caps[Capabilities.SIMPLEREST_IGNORE_EMPTY]) {
|
|
413
|
+
if (beforeHookKeys.length !== afterHookKeys.length || !!(botMsg.messageText && botMsg.messageText.length > 0) || botMsg.media.length > 0 || botMsg.buttons.length > 0 || botMsg.cards.length > 0 || !this.caps[Capabilities.SIMPLEREST_IGNORE_EMPTY]) {
|
|
364
414
|
result.push(botMsg)
|
|
365
415
|
}
|
|
366
416
|
}
|
|
@@ -387,6 +437,15 @@ module.exports = class SimpleRestContainer {
|
|
|
387
437
|
if (debug.enabled && body) {
|
|
388
438
|
debug(botiumUtils.shortenJsonString(body))
|
|
389
439
|
}
|
|
440
|
+
if (body) {
|
|
441
|
+
const jsonBody = botiumUtils.toJsonWeak(body)
|
|
442
|
+
const errKey = Object.keys(jsonBody).find(k => k.startsWith('err') || k.startsWith('fail'))
|
|
443
|
+
if (errKey) {
|
|
444
|
+
return reject(new BotiumError(`got error response: ${response.statusCode}/${response.statusMessage} - ${jsonBody[errKey]}`, {
|
|
445
|
+
message: botiumUtils.shortenJsonString(body)
|
|
446
|
+
}))
|
|
447
|
+
}
|
|
448
|
+
}
|
|
390
449
|
return reject(new Error(`got error response: ${response.statusCode}/${response.statusMessage}`))
|
|
391
450
|
}
|
|
392
451
|
|
|
@@ -478,6 +537,15 @@ module.exports = class SimpleRestContainer {
|
|
|
478
537
|
requestOptions.uri = `${requestOptions.uri}?${appendToUri}`
|
|
479
538
|
}
|
|
480
539
|
}
|
|
540
|
+
if (msg.ADD_FORM_PARAM && Object.keys(msg.ADD_FORM_PARAM).length > 0) {
|
|
541
|
+
requestOptions.form = {}
|
|
542
|
+
for (const formKey of Object.keys(msg.ADD_FORM_PARAM)) {
|
|
543
|
+
const formValue = this._getMustachedVal(
|
|
544
|
+
_.isString(msg.ADD_FORM_PARAM[formKey]) ? msg.ADD_FORM_PARAM[formKey] : JSON.stringify(msg.ADD_FORM_PARAM[formKey]),
|
|
545
|
+
false)
|
|
546
|
+
requestOptions.form[formKey] = formValue
|
|
547
|
+
}
|
|
548
|
+
}
|
|
481
549
|
if (msg.ADD_HEADER && Object.keys(msg.ADD_HEADER).length > 0) {
|
|
482
550
|
requestOptions.headers = requestOptions.headers || {}
|
|
483
551
|
|
|
@@ -509,11 +577,11 @@ module.exports = class SimpleRestContainer {
|
|
|
509
577
|
throw new Error(`Failed to ping bot after ${retries} retries`)
|
|
510
578
|
}
|
|
511
579
|
tries++
|
|
512
|
-
const { err, response, body } = await new Promise((resolve) => {
|
|
580
|
+
const { err, response, body } = await this.bottleneck(() => new Promise((resolve) => {
|
|
513
581
|
request(pingConfig, (err, response, body) => {
|
|
514
582
|
resolve({ err, response, body })
|
|
515
583
|
})
|
|
516
|
-
})
|
|
584
|
+
}))
|
|
517
585
|
if (err) {
|
|
518
586
|
debug(`_waitForUrlResponse error on url check ${pingConfig.uri}: ${err}`)
|
|
519
587
|
await timeout(pingConfig.timeout)
|
|
@@ -26,6 +26,27 @@ const BotiumError = class BotiumError extends Error {
|
|
|
26
26
|
this.context.message = message.message || message
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
isAsserterError () {
|
|
30
|
+
if (this.context) {
|
|
31
|
+
const errArr = _.isArray(this.context) ? this.context : [this.context]
|
|
32
|
+
const hasNotAsserterError = errArr.findIndex(errDetail => {
|
|
33
|
+
if (errDetail.type === 'list') {
|
|
34
|
+
if (errDetail.errors) {
|
|
35
|
+
return errDetail.errors.findIndex(e => e.type !== 'asserter') >= 0
|
|
36
|
+
} else {
|
|
37
|
+
return true
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
return errDetail.type !== 'asserter'
|
|
41
|
+
}
|
|
42
|
+
}) >= 0
|
|
43
|
+
if (hasNotAsserterError) return false
|
|
44
|
+
return true
|
|
45
|
+
} else {
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
29
50
|
prettify (includeJson) {
|
|
30
51
|
const lines = []
|
|
31
52
|
if (this.context) {
|
|
@@ -6,7 +6,7 @@ const CompilerBase = require('./CompilerBase')
|
|
|
6
6
|
const Constants = require('./Constants')
|
|
7
7
|
const Utterance = require('./Utterance')
|
|
8
8
|
const { Convo } = require('./Convo')
|
|
9
|
-
const { linesToConvoStep, validSenders } = require('./helper')
|
|
9
|
+
const { linesToConvoStep, validSenders, linesToScriptingMemories } = require('./helper')
|
|
10
10
|
|
|
11
11
|
module.exports = class CompilerObjectBase extends CompilerBase {
|
|
12
12
|
constructor (context, caps = {}) {
|
|
@@ -109,20 +109,10 @@ module.exports = class CompilerObjectBase extends CompilerBase {
|
|
|
109
109
|
if (lines && lines.length > 0) {
|
|
110
110
|
if (_.isString(lines[0])) {
|
|
111
111
|
if (lines.length > 1) {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const rawRow = lines[row].split('|').map((name) => name.trim())
|
|
116
|
-
const caseName = rawRow[0]
|
|
117
|
-
const values = rawRow.slice(1)
|
|
118
|
-
const json = {}
|
|
119
|
-
for (let col = 0; col < names.length; col++) {
|
|
120
|
-
json[names[col]] = values[col]
|
|
121
|
-
}
|
|
122
|
-
const scriptingMemory = { header: { name: caseName }, values: json }
|
|
123
|
-
scriptingMemories.push(scriptingMemory)
|
|
112
|
+
const scriptingMemories = linesToScriptingMemories(lines, this.caps[Capabilities.SCRIPTING_MEMORY_COLUMN_MODE])
|
|
113
|
+
if (scriptingMemories && scriptingMemories.length > 0) {
|
|
114
|
+
this.context.AddScriptingMemories(scriptingMemories)
|
|
124
115
|
}
|
|
125
|
-
this.context.AddScriptingMemories(scriptingMemories)
|
|
126
116
|
return scriptingMemories
|
|
127
117
|
}
|
|
128
118
|
} else {
|
|
@@ -5,7 +5,7 @@ const Constants = require('./Constants')
|
|
|
5
5
|
const CompilerBase = require('./CompilerBase')
|
|
6
6
|
const Utterance = require('./Utterance')
|
|
7
7
|
const { ConvoHeader, Convo } = require('./Convo')
|
|
8
|
-
const { linesToConvoStep, convoStepToLines, validateConvo, validSenders } = require('./helper')
|
|
8
|
+
const { linesToConvoStep, convoStepToLines, validateConvo, validSenders, linesToScriptingMemories } = require('./helper')
|
|
9
9
|
|
|
10
10
|
module.exports = class CompilerTxt extends CompilerBase {
|
|
11
11
|
constructor (context, caps = {}) {
|
|
@@ -131,21 +131,10 @@ module.exports = class CompilerTxt extends CompilerBase {
|
|
|
131
131
|
|
|
132
132
|
_compileScriptingMemory (lines) {
|
|
133
133
|
if (lines && lines.length > 1) {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if (!lines[row] || lines[row].length === 0) continue
|
|
138
|
-
const rawRow = lines[row].split('|').map((name) => name.trim())
|
|
139
|
-
const caseName = rawRow[0]
|
|
140
|
-
const values = rawRow.slice(1)
|
|
141
|
-
const json = {}
|
|
142
|
-
for (let col = 0; col < names.length; col++) {
|
|
143
|
-
json[names[col]] = values[col]
|
|
144
|
-
}
|
|
145
|
-
const scriptingMemory = { header: { name: caseName }, values: json }
|
|
146
|
-
scriptingMemories.push(scriptingMemory)
|
|
134
|
+
const scriptingMemories = linesToScriptingMemories(lines, this.caps[Capabilities.SCRIPTING_MEMORY_COLUMN_MODE])
|
|
135
|
+
if (scriptingMemories && scriptingMemories.length > 0) {
|
|
136
|
+
this.context.AddScriptingMemories(scriptingMemories)
|
|
147
137
|
}
|
|
148
|
-
this.context.AddScriptingMemories(scriptingMemories)
|
|
149
138
|
return scriptingMemories
|
|
150
139
|
}
|
|
151
140
|
}
|