botium-core 1.11.13 → 1.12.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/dist/botium-cjs.js +692 -524
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +323 -155
- package/dist/botium-es.js.map +1 -1
- package/package.json +30 -29
- package/samples/connectors/custom/botium-connector-myapi.js +3 -3
- package/samples/extensions/asserterHooks/DummyAsserter.js +3 -3
- package/src/Capabilities.js +7 -1
- package/src/Defaults.js +1 -0
- package/src/containers/plugins/SimpleRestContainer.js +129 -52
- package/src/scripting/CompilerCsv.js +1 -1
- package/src/scripting/MatchFunctions.js +21 -0
- package/src/scripting/ScriptingProvider.js +49 -40
- package/src/scripting/helper.js +3 -3
- package/src/scripting/logichook/LogicHookConsts.js +4 -0
- package/src/scripting/logichook/LogicHookUtils.js +2 -0
- package/src/scripting/logichook/asserter/JsonPathAsserter.js +1 -1
- package/src/scripting/logichook/asserter/TextWildcardExactAllAsserter.js +8 -0
- package/src/scripting/logichook/asserter/TextWildcardExactAllICAsserter.js +8 -0
- package/src/scripting/logichook/asserter/TextWildcardExactAnyAsserter.js +8 -0
- package/src/scripting/logichook/asserter/TextWildcardExactAnyICAsserter.js +8 -0
- package/src/scripting/logichook/logichooks/UpdateCustomLogicHook.js +3 -4
- package/test/connectors/convos/hello.convo.txt +6 -0
- package/test/connectors/simplerest.spec.js +129 -2
- package/test/scripting/asserters/convos/text_wildcardexact_all_nok.yml +7 -0
- package/test/scripting/asserters/convos/text_wildcardexact_all_ok.yml +7 -0
- package/test/scripting/asserters/convos/text_wildcardexact_any_nok.yml +7 -0
- package/test/scripting/asserters/convos/text_wildcardexact_any_ok.yml +7 -0
- package/test/scripting/asserters/textWildcardExactAllAsserter.spec.js +51 -0
- package/test/scripting/asserters/textWildcardExactAnyAsserter.spec.js +51 -0
- package/test/scripting/matching/matchingmode.spec.js +43 -0
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "botium-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
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,65 +32,66 @@
|
|
|
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.16.5",
|
|
36
|
+
"async": "^3.2.2",
|
|
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.3",
|
|
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.
|
|
45
|
+
"ioredis": "^4.28.2",
|
|
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.
|
|
51
|
-
"mime-types": "^2.1.
|
|
50
|
+
"markdown-it": "^12.3.0",
|
|
51
|
+
"mime-types": "^2.1.34",
|
|
52
52
|
"mkdirp": "^1.0.4",
|
|
53
53
|
"moment": "^2.29.1",
|
|
54
54
|
"mustache": "^4.2.0",
|
|
55
55
|
"promise-retry": "^2.0.1",
|
|
56
|
-
"promise.allsettled": "^1.0.
|
|
56
|
+
"promise.allsettled": "^1.0.5",
|
|
57
57
|
"randomatic": "^3.1.1",
|
|
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.4",
|
|
62
|
+
"socket.io": "^4.4.0",
|
|
63
|
+
"socket.io-client": "^4.4.0",
|
|
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.5",
|
|
69
69
|
"write-yaml": "^1.0.0",
|
|
70
|
-
"xlsx": "^0.17.
|
|
70
|
+
"xlsx": "^0.17.4",
|
|
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.
|
|
77
|
-
"@babel/plugin-transform-runtime": "^7.
|
|
78
|
-
"@babel/preset-env": "^7.
|
|
75
|
+
"@babel/core": "^7.16.5",
|
|
76
|
+
"@babel/node": "^7.16.5",
|
|
77
|
+
"@babel/plugin-transform-runtime": "^7.16.5",
|
|
78
|
+
"@babel/preset-env": "^7.16.5",
|
|
79
79
|
"chai": "^4.3.4",
|
|
80
80
|
"chai-as-promised": "^7.1.1",
|
|
81
81
|
"cross-env": "^7.0.3",
|
|
82
|
-
"eslint": "^
|
|
82
|
+
"eslint": "^8.4.1",
|
|
83
83
|
"eslint-config-standard": "^16.0.3",
|
|
84
|
-
"eslint-plugin-import": "^2.
|
|
84
|
+
"eslint-plugin-import": "^2.25.3",
|
|
85
85
|
"eslint-plugin-node": "^11.1.0",
|
|
86
|
-
"eslint-plugin-promise": "^5.
|
|
86
|
+
"eslint-plugin-promise": "^5.2.0",
|
|
87
87
|
"eslint-plugin-standard": "^4.1.0",
|
|
88
88
|
"license-checker": "^25.0.1",
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
89
|
+
"license-compatibility-checker": "^0.3.5",
|
|
90
|
+
"mocha": "^9.1.3",
|
|
91
|
+
"nock": "^13.2.1",
|
|
92
|
+
"npm-check-updates": "^12.0.5",
|
|
92
93
|
"nyc": "^15.1.0",
|
|
93
|
-
"rollup": "^2.
|
|
94
|
+
"rollup": "^2.61.1",
|
|
94
95
|
"rollup-plugin-babel": "^4.4.0",
|
|
95
96
|
"rollup-plugin-commonjs": "^10.1.0",
|
|
96
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/Capabilities.js
CHANGED
|
@@ -18,6 +18,7 @@ module.exports = {
|
|
|
18
18
|
SIMPLEREST_PING_BODY: 'SIMPLEREST_PING_BODY',
|
|
19
19
|
SIMPLEREST_PING_BODY_RAW: 'SIMPLEREST_PING_BODY_RAW',
|
|
20
20
|
SIMPLEREST_PING_HEADERS: 'SIMPLEREST_PING_HEADERS',
|
|
21
|
+
SIMPLEREST_PING_REQUEST_HOOK: 'SIMPLEREST_PING_REQUEST_HOOK',
|
|
21
22
|
SIMPLEREST_PING_RETRIES: 'SIMPLEREST_PING_RETRIES',
|
|
22
23
|
SIMPLEREST_PING_TIMEOUT: 'SIMPLEREST_PING_TIMEOUT',
|
|
23
24
|
SIMPLEREST_PING_UPDATE_CONTEXT: 'SIMPLEREST_PING_UPDATE_CONTEXT',
|
|
@@ -27,6 +28,7 @@ module.exports = {
|
|
|
27
28
|
SIMPLEREST_START_BODY: 'SIMPLEREST_START_BODY',
|
|
28
29
|
SIMPLEREST_START_BODY_RAW: 'SIMPLEREST_START_BODY_RAW',
|
|
29
30
|
SIMPLEREST_START_HEADERS: 'SIMPLEREST_START_HEADERS',
|
|
31
|
+
SIMPLEREST_START_REQUEST_HOOK: 'SIMPLEREST_START_REQUEST_HOOK',
|
|
30
32
|
SIMPLEREST_START_RETRIES: 'SIMPLEREST_START_RETRIES',
|
|
31
33
|
SIMPLEREST_START_TIMEOUT: 'SIMPLEREST_START_TIMEOUT',
|
|
32
34
|
SIMPLEREST_START_UPDATE_CONTEXT: 'SIMPLEREST_START_UPDATE_CONTEXT',
|
|
@@ -36,10 +38,12 @@ module.exports = {
|
|
|
36
38
|
SIMPLEREST_STOP_BODY: 'SIMPLEREST_STOP_BODY',
|
|
37
39
|
SIMPLEREST_STOP_BODY_RAW: 'SIMPLEREST_STOP_BODY_RAW',
|
|
38
40
|
SIMPLEREST_STOP_HEADERS: 'SIMPLEREST_STOP_HEADERS',
|
|
41
|
+
SIMPLEREST_STOP_REQUEST_HOOK: 'SIMPLEREST_STOP_REQUEST_HOOK',
|
|
39
42
|
SIMPLEREST_STOP_RETRIES: 'SIMPLEREST_STOP_RETRIES',
|
|
40
43
|
SIMPLEREST_STOP_TIMEOUT: 'SIMPLEREST_STOP_TIMEOUT',
|
|
41
44
|
SIMPLEREST_INIT_CONTEXT: 'SIMPLEREST_INIT_CONTEXT',
|
|
42
45
|
SIMPLEREST_INIT_TEXT: 'SIMPLEREST_INIT_TEXT',
|
|
46
|
+
SIMPLEREST_INIT_PROCESS_RESPONSE: 'SIMPLEREST_INIT_PROCESS_RESPONSE',
|
|
43
47
|
SIMPLEREST_PROXY_URL: 'SIMPLEREST_PROXY_URL',
|
|
44
48
|
SIMPLEREST_STRICT_SSL: 'SIMPLEREST_STRICT_SSL',
|
|
45
49
|
SIMPLEREST_URL: 'SIMPLEREST_URL',
|
|
@@ -54,11 +58,13 @@ module.exports = {
|
|
|
54
58
|
SIMPLEREST_START_HOOK: 'SIMPLEREST_START_HOOK',
|
|
55
59
|
SIMPLEREST_STOP_HOOK: 'SIMPLEREST_STOP_HOOK',
|
|
56
60
|
SIMPLEREST_REQUEST_HOOK: 'SIMPLEREST_REQUEST_HOOK',
|
|
61
|
+
SIMPLEREST_PARSER_HOOK: 'SIMPLEREST_PARSER_HOOK',
|
|
57
62
|
SIMPLEREST_POLL_URL: 'SIMPLEREST_POLL_URL',
|
|
58
63
|
SIMPLEREST_POLL_VERB: 'SIMPLEREST_POLL_VERB',
|
|
59
64
|
SIMPLEREST_POLL_BODY: 'SIMPLEREST_POLL_BODY',
|
|
60
65
|
SIMPLEREST_POLL_BODY_RAW: 'SIMPLEREST_POLL_BODY_RAW',
|
|
61
66
|
SIMPLEREST_POLL_HEADERS: 'SIMPLEREST_POLL_HEADERS',
|
|
67
|
+
SIMPLEREST_POLL_REQUEST_HOOK: 'SIMPLEREST_POLL_REQUEST_HOOK',
|
|
62
68
|
SIMPLEREST_POLL_INTERVAL: 'SIMPLEREST_POLL_INTERVAL',
|
|
63
69
|
SIMPLEREST_POLL_TIMEOUT: 'SIMPLEREST_PING_TIMEOUT',
|
|
64
70
|
SIMPLEREST_POLL_UPDATE_CONTEXT: 'SIMPLEREST_POLL_UPDATE_CONTEXT',
|
|
@@ -106,7 +112,7 @@ module.exports = {
|
|
|
106
112
|
SCRIPTING_ENABLE_MEMORY: 'SCRIPTING_ENABLE_MEMORY',
|
|
107
113
|
SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS: 'SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS',
|
|
108
114
|
SCRIPTING_FORCE_BOT_CONSUMED: 'SCRIPTING_FORCE_BOT_CONSUMED',
|
|
109
|
-
// regexp, regexpIgnoreCase, wildcard, wildcardIgnoreCase, include, includeIgnoreCase, equals, equalsIgnoreCase
|
|
115
|
+
// regexp, regexpIgnoreCase, wildcard, wildcardIgnoreCase, wildcardExact, wildcardExactIgnoreCase, include, includeIgnoreCase, equals, equalsIgnoreCase
|
|
110
116
|
SCRIPTING_MATCHING_MODE: 'SCRIPTING_MATCHING_MODE',
|
|
111
117
|
// all, first, random
|
|
112
118
|
SCRIPTING_UTTEXPANSION_MODE: 'SCRIPTING_UTTEXPANSION_MODE',
|
package/src/Defaults.js
CHANGED
|
@@ -15,6 +15,7 @@ module.exports = {
|
|
|
15
15
|
[Capabilities.SIMPLEREST_PING_VERB]: 'GET',
|
|
16
16
|
[Capabilities.SIMPLEREST_PING_UPDATE_CONTEXT]: true,
|
|
17
17
|
[Capabilities.SIMPLEREST_PING_PROCESS_RESPONSE]: false,
|
|
18
|
+
[Capabilities.SIMPLEREST_INIT_PROCESS_RESPONSE]: false,
|
|
18
19
|
[Capabilities.SIMPLEREST_STOP_RETRIES]: 6,
|
|
19
20
|
[Capabilities.SIMPLEREST_STOP_TIMEOUT]: 10000,
|
|
20
21
|
[Capabilities.SIMPLEREST_STOP_VERB]: 'GET',
|
|
@@ -17,6 +17,7 @@ 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
|
|
|
@@ -57,7 +58,20 @@ module.exports = class SimpleRestContainer {
|
|
|
57
58
|
this.startHook = getHook(this.caps, this.caps[Capabilities.SIMPLEREST_START_HOOK])
|
|
58
59
|
this.stopHook = getHook(this.caps, this.caps[Capabilities.SIMPLEREST_STOP_HOOK])
|
|
59
60
|
this.requestHook = getHook(this.caps, this.caps[Capabilities.SIMPLEREST_REQUEST_HOOK])
|
|
61
|
+
this.parserHook = getHook(this.caps, this.caps[Capabilities.SIMPLEREST_PARSER_HOOK])
|
|
60
62
|
this.responseHook = getHook(this.caps, this.caps[Capabilities.SIMPLEREST_RESPONSE_HOOK])
|
|
63
|
+
this.pollRequestHook = getHook(this.caps, this.caps[Capabilities.SIMPLEREST_POLL_REQUEST_HOOK])
|
|
64
|
+
|
|
65
|
+
this.requestHooks = {}
|
|
66
|
+
if (this.caps[Capabilities.SIMPLEREST_PING_REQUEST_HOOK]) {
|
|
67
|
+
this.requestHooks.SIMPLEREST_PING = getHook(this.caps, this.caps[Capabilities.SIMPLEREST_PING_REQUEST_HOOK])
|
|
68
|
+
}
|
|
69
|
+
if (this.caps[Capabilities.SIMPLEREST_START_REQUEST_HOOK]) {
|
|
70
|
+
this.requestHooks.SIMPLEREST_START = getHook(this.caps, this.caps[Capabilities.SIMPLEREST_START_REQUEST_HOOK])
|
|
71
|
+
}
|
|
72
|
+
if (this.caps[Capabilities.SIMPLEREST_STOP_REQUEST_HOOK]) {
|
|
73
|
+
this.requestHooks.SIMPLEREST_STOP = getHook(this.caps, this.caps[Capabilities.SIMPLEREST_STOP_REQUEST_HOOK])
|
|
74
|
+
}
|
|
61
75
|
}
|
|
62
76
|
|
|
63
77
|
Build () {
|
|
@@ -111,18 +125,34 @@ module.exports = class SimpleRestContainer {
|
|
|
111
125
|
executeHook(this.caps, this.startHook, this.view).then(() => startHookComplete()).catch(startHookComplete)
|
|
112
126
|
},
|
|
113
127
|
|
|
128
|
+
(inboundListenerComplete) => {
|
|
129
|
+
this._subscribeInbound()
|
|
130
|
+
.then(() => inboundListenerComplete())
|
|
131
|
+
.catch(inboundListenerComplete)
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
(startPollingComplete) => {
|
|
135
|
+
this._startPolling()
|
|
136
|
+
.then(() => startPollingComplete())
|
|
137
|
+
.catch(startPollingComplete)
|
|
138
|
+
},
|
|
139
|
+
|
|
114
140
|
(pingComplete) => {
|
|
115
141
|
if (this.caps[Capabilities.SIMPLEREST_PING_URL]) {
|
|
116
142
|
this._makeCall('SIMPLEREST_PING')
|
|
117
|
-
.then(
|
|
143
|
+
.then(body => {
|
|
118
144
|
if (this.caps[Capabilities.SIMPLEREST_PING_UPDATE_CONTEXT] || this.caps[Capabilities.SIMPLEREST_PING_PROCESS_RESPONSE]) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
145
|
+
return this._parseResponseBody(body)
|
|
146
|
+
.then(body => {
|
|
147
|
+
if (body) {
|
|
148
|
+
debug(`Ping Uri ${this.caps[Capabilities.SIMPLEREST_PING_URL]} returned JSON response: ${botiumUtils.shortenJsonString(body)}`)
|
|
149
|
+
return this._processBodyAsync(body, !!this.caps[Capabilities.SIMPLEREST_PING_PROCESS_RESPONSE], !!this.caps[Capabilities.SIMPLEREST_PING_UPDATE_CONTEXT])
|
|
150
|
+
} else {
|
|
151
|
+
debug(`Ping Uri ${this.caps[Capabilities.SIMPLEREST_PING_URL]} didn't return JSON response, ignoring it.`)
|
|
152
|
+
}
|
|
153
|
+
}).catch(err => {
|
|
154
|
+
debug(`Ping Uri ${this.caps[Capabilities.SIMPLEREST_PING_URL]} didn't return JSON response, ignoring it (${err.message})`)
|
|
155
|
+
})
|
|
126
156
|
}
|
|
127
157
|
}).then(() => {
|
|
128
158
|
pingComplete()
|
|
@@ -136,37 +166,29 @@ module.exports = class SimpleRestContainer {
|
|
|
136
166
|
|
|
137
167
|
(initComplete) => {
|
|
138
168
|
if (_.isString(this.caps[Capabilities.SIMPLEREST_INIT_TEXT])) {
|
|
139
|
-
this._doRequest({ messageText: this.caps[Capabilities.SIMPLEREST_INIT_TEXT] },
|
|
169
|
+
this._doRequest({ messageText: this.caps[Capabilities.SIMPLEREST_INIT_TEXT] }, !!this.caps[Capabilities.SIMPLEREST_INIT_PROCESS_RESPONSE], true).then(() => initComplete()).catch(initComplete)
|
|
140
170
|
} else {
|
|
141
171
|
initComplete()
|
|
142
172
|
}
|
|
143
173
|
},
|
|
144
174
|
|
|
145
|
-
(inboundListenerComplete) => {
|
|
146
|
-
this._subscribeInbound()
|
|
147
|
-
.then(() => inboundListenerComplete())
|
|
148
|
-
.catch(inboundListenerComplete)
|
|
149
|
-
},
|
|
150
|
-
|
|
151
|
-
(startPollingComplete) => {
|
|
152
|
-
this._startPolling()
|
|
153
|
-
.then(() => startPollingComplete())
|
|
154
|
-
.catch(startPollingComplete)
|
|
155
|
-
},
|
|
156
|
-
|
|
157
175
|
(startCallComplete) => {
|
|
158
176
|
this.processInbound = true
|
|
159
177
|
if (this.caps[Capabilities.SIMPLEREST_START_URL]) {
|
|
160
178
|
this._makeCall('SIMPLEREST_START')
|
|
161
|
-
.then(
|
|
179
|
+
.then(body => {
|
|
162
180
|
if (this.caps[Capabilities.SIMPLEREST_START_UPDATE_CONTEXT] || this.caps[Capabilities.SIMPLEREST_START_PROCESS_RESPONSE]) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
181
|
+
return this._parseResponseBody(body)
|
|
182
|
+
.then(body => {
|
|
183
|
+
if (body) {
|
|
184
|
+
debug(`Start Uri ${this.caps[Capabilities.SIMPLEREST_START_URL]} returned JSON response: ${botiumUtils.shortenJsonString(body)}`)
|
|
185
|
+
return this._processBodyAsync(body, !!this.caps[Capabilities.SIMPLEREST_START_PROCESS_RESPONSE], !!this.caps[Capabilities.SIMPLEREST_START_UPDATE_CONTEXT])
|
|
186
|
+
} else {
|
|
187
|
+
debug(`Start Uri ${this.caps[Capabilities.SIMPLEREST_START_URL]} didn't return JSON response, ignoring it.`)
|
|
188
|
+
}
|
|
189
|
+
}).catch(err => {
|
|
190
|
+
debug(`Start Uri ${this.caps[Capabilities.SIMPLEREST_START_URL]} didn't return JSON response, ignoring it (${err.message})`)
|
|
191
|
+
})
|
|
170
192
|
}
|
|
171
193
|
}).then(() => {
|
|
172
194
|
startCallComplete()
|
|
@@ -357,27 +379,40 @@ module.exports = class SimpleRestContainer {
|
|
|
357
379
|
|
|
358
380
|
this.waitProcessQueue = []
|
|
359
381
|
|
|
360
|
-
request(requestOptions, (err, response, body) => {
|
|
382
|
+
request(requestOptions, async (err, response, body) => {
|
|
361
383
|
if (err) {
|
|
362
|
-
reject(new Error(`rest request failed: ${err.message}`))
|
|
384
|
+
return reject(new Error(`rest request failed: ${err.message}`))
|
|
363
385
|
} else {
|
|
364
386
|
if (response.statusCode >= 400) {
|
|
365
387
|
debug(`got error response: ${response.statusCode}/${response.statusMessage}`)
|
|
388
|
+
if (debug.enabled && body) {
|
|
389
|
+
debug(botiumUtils.shortenJsonString(body))
|
|
390
|
+
}
|
|
391
|
+
if (body) {
|
|
392
|
+
const jsonBody = botiumUtils.toJsonWeak(body)
|
|
393
|
+
const errKey = Object.keys(jsonBody).find(k => k.startsWith('err') || k.startsWith('fail'))
|
|
394
|
+
if (errKey) {
|
|
395
|
+
return reject(new BotiumError(`got error response: ${response.statusCode}/${response.statusMessage} - ${jsonBody[errKey]}`, {
|
|
396
|
+
message: botiumUtils.shortenJsonString(body)
|
|
397
|
+
}))
|
|
398
|
+
}
|
|
399
|
+
}
|
|
366
400
|
return reject(new Error(`got error response: ${response.statusCode}/${response.statusMessage}`))
|
|
367
401
|
}
|
|
368
402
|
|
|
369
403
|
if (body) {
|
|
370
404
|
debug(`got response code: ${response.statusCode}, body: ${botiumUtils.shortenJsonString(body)}`)
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
405
|
+
|
|
406
|
+
try {
|
|
407
|
+
body = await this._parseResponseBody(body)
|
|
408
|
+
} catch (err) {
|
|
409
|
+
debug(`ignoring not JSON formatted response body: ${err.message}`)
|
|
410
|
+
resolve(this)
|
|
411
|
+
this._emptyWaitProcessQueue()
|
|
412
|
+
return
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (body) {
|
|
381
416
|
this._processBodyAsync(body, isFromUser, updateContext).then(() => resolve(this)).then(() => this._emptyWaitProcessQueue())
|
|
382
417
|
} else {
|
|
383
418
|
debug('ignoring response body (no string and no JSON object)')
|
|
@@ -453,6 +488,15 @@ module.exports = class SimpleRestContainer {
|
|
|
453
488
|
requestOptions.uri = `${requestOptions.uri}?${appendToUri}`
|
|
454
489
|
}
|
|
455
490
|
}
|
|
491
|
+
if (msg.ADD_FORM_PARAM && Object.keys(msg.ADD_FORM_PARAM).length > 0) {
|
|
492
|
+
requestOptions.form = {}
|
|
493
|
+
for (const formKey of Object.keys(msg.ADD_FORM_PARAM)) {
|
|
494
|
+
const formValue = this._getMustachedVal(
|
|
495
|
+
_.isString(msg.ADD_FORM_PARAM[formKey]) ? msg.ADD_FORM_PARAM[formKey] : JSON.stringify(msg.ADD_FORM_PARAM[formKey]),
|
|
496
|
+
false)
|
|
497
|
+
requestOptions.form[formKey] = formValue
|
|
498
|
+
}
|
|
499
|
+
}
|
|
456
500
|
if (msg.ADD_HEADER && Object.keys(msg.ADD_HEADER).length > 0) {
|
|
457
501
|
requestOptions.headers = requestOptions.headers || {}
|
|
458
502
|
|
|
@@ -494,14 +538,36 @@ module.exports = class SimpleRestContainer {
|
|
|
494
538
|
await timeout(pingConfig.timeout)
|
|
495
539
|
} else if (response.statusCode >= 400) {
|
|
496
540
|
debug(`_waitForUrlResponse on url check ${pingConfig.uri} got error response: ${response.statusCode}/${response.statusMessage}`)
|
|
541
|
+
if (debug.enabled && body) {
|
|
542
|
+
debug(botiumUtils.shortenJsonString(body))
|
|
543
|
+
}
|
|
497
544
|
await timeout(pingConfig.timeout)
|
|
498
545
|
} else {
|
|
499
|
-
debug(`_waitForUrlResponse success on url check ${pingConfig.uri}`)
|
|
546
|
+
debug(`_waitForUrlResponse success on url check ${pingConfig.uri}: ${response.statusCode}/${response.statusMessage}`)
|
|
547
|
+
if (debug.enabled && body) {
|
|
548
|
+
debug(botiumUtils.shortenJsonString(body))
|
|
549
|
+
}
|
|
500
550
|
return body
|
|
501
551
|
}
|
|
502
552
|
}
|
|
503
553
|
}
|
|
504
554
|
|
|
555
|
+
async _parseResponseBody (body) {
|
|
556
|
+
if (!_.isObject(body) && _.isString(body)) {
|
|
557
|
+
try {
|
|
558
|
+
body = JSON.parse(body)
|
|
559
|
+
} catch (err) {
|
|
560
|
+
if (!this.parserHook) throw err
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (this.parserHook) {
|
|
564
|
+
await executeHook(this.caps, this.parserHook, Object.assign({ body, changeBody: (b) => { body = b } }, this.view))
|
|
565
|
+
}
|
|
566
|
+
if (_.isObject(body)) return body
|
|
567
|
+
else if (_.isString(body)) return JSON.parse(body)
|
|
568
|
+
else return null
|
|
569
|
+
}
|
|
570
|
+
|
|
505
571
|
_getCapValue (capName) {
|
|
506
572
|
return _.isFunction(this.caps[capName]) ? (this.caps[capName])() : this.caps[capName]
|
|
507
573
|
}
|
|
@@ -629,7 +695,7 @@ module.exports = class SimpleRestContainer {
|
|
|
629
695
|
}
|
|
630
696
|
}
|
|
631
697
|
|
|
632
|
-
_runPolling () {
|
|
698
|
+
async _runPolling () {
|
|
633
699
|
if (!this.processInbound) return
|
|
634
700
|
|
|
635
701
|
if (this.caps[Capabilities.SIMPLEREST_POLL_URL]) {
|
|
@@ -662,22 +728,31 @@ module.exports = class SimpleRestContainer {
|
|
|
662
728
|
}
|
|
663
729
|
this._addRequestOptions(pollConfig)
|
|
664
730
|
|
|
665
|
-
|
|
731
|
+
try {
|
|
732
|
+
await executeHook(this.caps, this.pollRequestHook, Object.assign({ requestOptions: pollConfig }, this.view))
|
|
733
|
+
} catch (err) {
|
|
734
|
+
debug(`_runPolling: exeucting request hook failed - (${err.message})`)
|
|
735
|
+
return
|
|
736
|
+
}
|
|
737
|
+
request(pollConfig, async (err, response, body) => {
|
|
666
738
|
if (err) {
|
|
667
739
|
debug(`_runPolling: rest request failed: ${err.message}, request: ${JSON.stringify(pollConfig)}`)
|
|
668
740
|
} else {
|
|
669
741
|
if (response.statusCode >= 400) {
|
|
670
742
|
debug(`_runPolling: got error response: ${response.statusCode}/${response.statusMessage}, request: ${JSON.stringify(pollConfig)}`)
|
|
743
|
+
if (debug.enabled && body) {
|
|
744
|
+
debug(botiumUtils.shortenJsonString(body))
|
|
745
|
+
}
|
|
671
746
|
} else if (body) {
|
|
672
747
|
debug(`_runPolling: got response code: ${response.statusCode}, body: ${botiumUtils.shortenJsonString(body)}`)
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
748
|
+
|
|
749
|
+
try {
|
|
750
|
+
body = await this._parseResponseBody(body)
|
|
751
|
+
} catch (err) {
|
|
752
|
+
debug(`_runPolling: ignoring not JSON formatted response body: ${err.message}`)
|
|
753
|
+
return
|
|
754
|
+
}
|
|
755
|
+
if (body) {
|
|
681
756
|
setTimeout(() => this._processBodyAsync(body, true, !!this.caps[Capabilities.SIMPLEREST_POLL_UPDATE_CONTEXT]), 0)
|
|
682
757
|
} else {
|
|
683
758
|
debug('_runPolling: ignoring response body (no string and no JSON object)')
|
|
@@ -733,6 +808,8 @@ module.exports = class SimpleRestContainer {
|
|
|
733
808
|
}
|
|
734
809
|
this._addRequestOptions(httpConfig)
|
|
735
810
|
|
|
811
|
+
await executeHook(this.caps, this.requestHooks[capPrefix], Object.assign({ requestOptions: httpConfig }, this.view))
|
|
812
|
+
|
|
736
813
|
const retries = this._getCapValue(`${capPrefix}_RETRIES`)
|
|
737
814
|
debug(`_makeCall(${capPrefix}): rest request: ${JSON.stringify(httpConfig)}`)
|
|
738
815
|
const response = await this._waitForUrlResponse(httpConfig, retries)
|
|
@@ -37,6 +37,24 @@ const wildcard = (ignoreCase) => (botresponse, utterance) => {
|
|
|
37
37
|
return regexp.test(botresponse)
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
const wildcardExact = (ignoreCase) => (botresponse, utterance) => {
|
|
41
|
+
if (_.isUndefined(botresponse)) {
|
|
42
|
+
if (utterance.trim() === '*') return true
|
|
43
|
+
else return false
|
|
44
|
+
}
|
|
45
|
+
utterance = toString(utterance)
|
|
46
|
+
botresponse = _normalize(botresponse)
|
|
47
|
+
|
|
48
|
+
const numWildcards = utterance.split('*').length - 1
|
|
49
|
+
if (numWildcards > 10) {
|
|
50
|
+
throw new Error('Maximum number of 10 wildcards supported.')
|
|
51
|
+
}
|
|
52
|
+
const utteranceRe = '^' + quoteRegexpString(utterance).replace(/\\\*/g, '(.*)') + '$'
|
|
53
|
+
|
|
54
|
+
const regexp = ignoreCase ? (new RegExp(utteranceRe, 'i')) : (new RegExp(utteranceRe, ''))
|
|
55
|
+
return regexp.test(botresponse)
|
|
56
|
+
}
|
|
57
|
+
|
|
40
58
|
const include = (ignoreCase) => (botresponse, utterance) => {
|
|
41
59
|
if (_.isUndefined(botresponse)) return false
|
|
42
60
|
utterance = toString(utterance)
|
|
@@ -66,6 +84,8 @@ const getMatchFunction = (matchingMode) => {
|
|
|
66
84
|
return regexp(matchingMode === 'regexpIgnoreCase')
|
|
67
85
|
} else if (matchingMode === 'wildcard' || matchingMode === 'wildcardIgnoreCase' || matchingMode === 'wildcardLowerCase') {
|
|
68
86
|
return wildcard(matchingMode === 'wildcardIgnoreCase' || matchingMode === 'wildcardLowerCase')
|
|
87
|
+
} else if (matchingMode === 'wildcardExact' || matchingMode === 'wildcardExactIgnoreCase') {
|
|
88
|
+
return wildcardExact(matchingMode === 'wildcardExactIgnoreCase')
|
|
69
89
|
} else if (matchingMode === 'include' || matchingMode === 'includeIgnoreCase' || matchingMode === 'includeLowerCase') {
|
|
70
90
|
return include(matchingMode === 'includeIgnoreCase' || matchingMode === 'includeLowerCase')
|
|
71
91
|
} else if (matchingMode === 'equals' || matchingMode === 'equalsIgnoreCase') {
|
|
@@ -78,6 +98,7 @@ const getMatchFunction = (matchingMode) => {
|
|
|
78
98
|
module.exports = {
|
|
79
99
|
regexp,
|
|
80
100
|
wildcard,
|
|
101
|
+
wildcardExact,
|
|
81
102
|
include,
|
|
82
103
|
equals,
|
|
83
104
|
getMatchFunction
|