botium-core 1.14.10 → 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/dist/botium-cjs.js +214 -114
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +213 -113
- package/dist/botium-es.js.map +1 -1
- package/package.json +4 -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 +1 -1
- package/src/scripting/helper.js +59 -22
- 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 +14 -17
- 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/hooks/customhooks.spec.js +3 -5
- package/test/scripting/helper.spec.js +21 -0
- package/test/scripting/scriptingProvider.spec.js +34 -0
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
|
}
|
|
@@ -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
3
|
const globSync = require('tinyglobby').globSync
|
|
4
|
-
const request = require('request')
|
|
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
|
}
|
|
@@ -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 () {
|