Skip to content

Commit

Permalink
Merge pull request #614 from codeforequity-at/develop
Browse files Browse the repository at this point in the history
Botium Core 1.11.2
  • Loading branch information
Botium authored Apr 10, 2021
2 parents 555ff88 + 29feb79 commit ecdc2f8
Show file tree
Hide file tree
Showing 47 changed files with 2,797 additions and 1,753 deletions.
7 changes: 6 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module.exports = {
BotDriver: require('./src/BotDriver'),
ScriptingProvider: require('./src/scripting/ScriptingProvider'),
ScriptingConstants: require('./src/scripting/Constants'),
Capabilities: require('./src/Capabilities'),
Defaults: require('./src/Defaults'),
Source: require('./src/Source'),
Expand All @@ -8,8 +10,11 @@ module.exports = {
BotiumError: require('./src/scripting/BotiumError').BotiumError,
ScriptingMemory: require('./src/scripting/ScriptingMemory'),
HookUtils: require('./src/helpers/HookUtils'),
LogicHookConstants: require('./src/scripting/logichook/LogicHookConsts'),
Lib: {
tryLoadPlugin: require('./src/containers/plugins/index').tryLoadPlugin
tryLoadPlugin: require('./src/containers/plugins/index').tryLoadPlugin,
SimpleRestContainer: require('./src/containers/plugins/SimpleRestContainer')
},
InboundProxy: require('./src/grid/inbound/proxy'),
BotiumMockRichMessageTypes: require('./src/mocks/BotiumMockRichMessageTypes')
}
3,530 changes: 1,950 additions & 1,580 deletions package-lock.json

Large diffs are not rendered by default.

72 changes: 36 additions & 36 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "botium-core",
"version": "1.11.1",
"version": "1.11.2",
"description": "The Selenium for Chatbots",
"main": "index.js",
"module": "dist/botium-es.js",
Expand Down Expand Up @@ -32,65 +32,65 @@
},
"homepage": "https://www.botium.ai",
"dependencies": {
"@babel/runtime": "^7.12.5",
"@babel/runtime": "^7.13.10",
"async": "^3.2.0",
"body-parser": "^1.19.0",
"boolean": "^3.0.2",
"boolean": "^3.0.3",
"bottleneck": "^2.19.5",
"csv-parse": "^4.14.0",
"debug": "^4.2.0",
"csv-parse": "^4.15.3",
"debug": "^4.3.1",
"esprima": "^4.0.1",
"express": "^4.17.1",
"globby": "^11.0.1",
"ioredis": "^4.19.2",
"globby": "^11.0.3",
"ioredis": "^4.26.0",
"is-class": "^0.0.9",
"is-json": "^2.0.1",
"jsonpath": "^1.0.2",
"lodash": "^4.17.20",
"markdown-it": "^12.0.2",
"mime-types": "^2.1.27",
"jsonpath": "^1.1.1",
"lodash": "^4.17.21",
"markdown-it": "^12.0.4",
"mime-types": "^2.1.30",
"mkdirp": "^1.0.4",
"moment": "^2.29.1",
"mustache": "^4.0.1",
"mustache": "^4.2.0",
"promise-retry": "^2.0.1",
"promise.allsettled": "^1.0.2",
"promise.allsettled": "^1.0.4",
"randomatic": "^3.1.1",
"request": "^2.88.2",
"rimraf": "^3.0.2",
"sanitize-filename": "^1.6.3",
"slugify": "^1.4.6",
"socket.io": "^3.0.1",
"socket.io-client": "^3.0.1",
"slugify": "^1.5.0",
"socket.io": "^4.0.1",
"socket.io-client": "^4.0.1",
"socketio-auth": "^0.1.1",
"swagger-jsdoc": "^5.0.1",
"swagger-ui-express": "^4.1.4",
"uuid": "^8.3.1",
"vm2": "^3.9.2",
"swagger-jsdoc": "^6.1.0",
"swagger-ui-express": "^4.1.6",
"uuid": "^8.3.2",
"vm2": "^3.9.3",
"write-yaml": "^1.0.0",
"xlsx": "^0.16.8",
"xregexp": "^4.4.0",
"yaml": "^1.10.0"
"xlsx": "^0.16.9",
"xregexp": "^5.0.2",
"yaml": "^1.10.2"
},
"devDependencies": {
"@babel/core": "^7.12.3",
"@babel/node": "^7.12.6",
"@babel/plugin-transform-runtime": "^7.12.1",
"@babel/preset-env": "^7.12.1",
"chai": "^4.2.0",
"@babel/core": "^7.13.15",
"@babel/node": "^7.13.13",
"@babel/plugin-transform-runtime": "^7.13.15",
"@babel/preset-env": "^7.13.15",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"cross-env": "^7.0.2",
"eslint": "^7.13.0",
"eslint-config-standard": "^16.0.1",
"cross-env": "^7.0.3",
"eslint": "^7.24.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-standard": "^4.1.0",
"license-checker": "^25.0.1",
"mocha": "^8.2.1",
"npm-check-updates": "^10.0.0",
"nock": "^13.0.5",
"mocha": "^8.3.2",
"npm-check-updates": "^11.4.1",
"nock": "^13.0.11",
"nyc": "^15.1.0",
"rollup": "^2.33.2",
"rollup": "^2.45.1",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-json": "^4.0.0",
Expand Down
3 changes: 3 additions & 0 deletions src/BotDriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,9 @@ module.exports = class BotDriver {
if (_.isString(newCaps[capKey])) {
try {
caps[capKey] = JSON.parse(newCaps[capKey])
if (_.isFinite(caps[capKey])) {
caps[capKey] = caps[capKey].toString()
}
} catch (err) {
caps[capKey] = newCaps[capKey]
}
Expand Down
4 changes: 2 additions & 2 deletions src/containers/plugins/SimpleRestContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ module.exports = class SimpleRestContainer {
const beforeHookKeys = Object.keys(botMsg)
await executeHook(this.caps, this.responseHook, Object.assign({ botMsg, botMsgRoot: jsonPathRoot }, this.view))
const afterHookKeys = Object.keys(botMsg)
if (beforeHookKeys.length !== afterHookKeys.length || !!(botMsg.messageText && botMsg.messageText.length > 0) || media.length > 0 || buttons.length > 0 || !this.caps[Capabilities.SIMPLEREST_IGNORE_EMPTY]) {
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]) {
result.push(botMsg)
}
}
Expand Down Expand Up @@ -525,7 +525,7 @@ module.exports = class SimpleRestContainer {
if (hasResult && hasResult.length > 0) {
const check = jsonPathValue && this._getMustachedVal(jsonPathValue, false)
if (check) {
if (hasResult[0] === check) {
if (`${hasResult[0]}` === `${check}`) {
isSelected = true
break
}
Expand Down
2 changes: 1 addition & 1 deletion src/grid/inbound/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const setupEndpoints = ({ app, endpoint, middleware, processEvent }) => {
originalMethod: req.method,
body: req.body
})
res.status(200).end()
res.status(200).json({}).end()
} else {
res.status(500).sendResponse('No body detected')
}
Expand Down
15 changes: 10 additions & 5 deletions src/scripting/CompilerMarkdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const CompilerBase = require('./CompilerBase')
const Constants = require('./Constants')
const { Convo } = require('./Convo')
const Utterance = require('./Utterance')
const { linesToConvoStep } = require('./helper')
const { linesToConvoStep, validSenders, validateSender } = require('./helper')

module.exports = class CompilerMarkdown extends CompilerBase {
constructor (context, caps = {}) {
Expand Down Expand Up @@ -69,13 +69,14 @@ module.exports = class CompilerMarkdown extends CompilerBase {

const structured = _toStructuredMarkdown(parsed)
for (const convosOrUtterances of structured.children) {
if (convosOrUtterances.content === 'Convos' && scriptType === Constants.SCRIPTING_TYPE_CONVO) {
if ((convosOrUtterances.content === 'Convos' && scriptType === Constants.SCRIPTING_TYPE_CONVO) ||
(convosOrUtterances.content === 'PartialConvos' && scriptType === Constants.SCRIPTING_TYPE_PCONVO)) {
const convosBotium = []
for (const convo of convosOrUtterances.children) {
const conversation = []
for (const step of convo.children) {
const sender = step.content.toLowerCase()
if (['me', 'bot'].includes(sender)) {
if (validateSender(sender)) {
// handle both:
// - BUTTONS checkbutton|checkbutton2
// and
Expand All @@ -91,7 +92,7 @@ module.exports = class CompilerMarkdown extends CompilerBase {
(child.children ? ' ' + child.children.map(child => child.content).join('|') : '')), sender, this.context, this.eol)
))
} else {
debug(`Expected "me" or "bot" but found ${sender}`)
debug(`Expected sender ${validSenders.map(s => `'${s}'`).join(' or ')} but found ${sender}`)
}
}
convosBotium.push(new Convo(this.context, {
Expand All @@ -101,7 +102,11 @@ module.exports = class CompilerMarkdown extends CompilerBase {
conversation
}))
}
this.context.AddConvos(convosBotium)
if (scriptType === Constants.SCRIPTING_TYPE_CONVO) {
this.context.AddConvos(convosBotium)
} else if (scriptType === Constants.SCRIPTING_TYPE_PCONVO) {
this.context.AddPartialConvos(convosBotium)
}
} else if (convosOrUtterances.content === 'Utterances' && scriptType === Constants.SCRIPTING_TYPE_UTTERANCES) {
const utterancesBotium = []
for (const utteranceStruct of convosOrUtterances.children) {
Expand Down
8 changes: 4 additions & 4 deletions src/scripting/CompilerObjectBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const CompilerBase = require('./CompilerBase')
const Constants = require('./Constants')
const Utterance = require('./Utterance')
const { Convo } = require('./Convo')
const { linesToConvoStep } = require('./helper')
const { linesToConvoStep, validSenders } = require('./helper')

module.exports = class CompilerObjectBase extends CompilerBase {
constructor (context, caps = {}) {
Expand Down Expand Up @@ -54,10 +54,10 @@ module.exports = class CompilerObjectBase extends CompilerBase {
const lineTag = `${convoStepLineIndex + 1}`.padStart(`${convoRaw.steps.length}`.length, '0')

if (Object.keys(convoStepRaw).length > 1) {
throw new Error(`Use just one from 'begin', 'me','bot' and 'end' fields in step ${JSON.stringify(convoStepRaw)}`)
throw new Error(`Use just one from ${validSenders.join(',')} fields in step ${JSON.stringify(convoStepRaw)}`)
}
if (!convoStepRaw.begin && !convoStepRaw.me && !convoStepRaw.bot && !convoStepRaw.end) {
throw new Error(`Use 'begin' or 'me' or 'bot' or 'end' field in step ${JSON.stringify(convoStepRaw)}`)
if (validSenders.findIndex(sender => convoStepRaw[sender]) < 0) {
throw new Error(`Use ${validSenders.map(s => `'${s}'`).join(' or ')} field in step ${JSON.stringify(convoStepRaw)}`)
}

const convoStepSender = Object.keys(convoStepRaw)[0]
Expand Down
59 changes: 27 additions & 32 deletions src/scripting/Convo.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const Capabilities = require('../Capabilities')
const Events = require('../Events')
const ScriptingMemory = require('./ScriptingMemory')
const { BotiumError, botiumErrorFromErr, botiumErrorFromList } = require('./BotiumError')
const { normalizeText, toString, removeBuffers } = require('./helper')
const { normalizeText, toString, removeBuffers, splitStringInNonEmptyLines } = require('./helper')

const { LOGIC_HOOK_INCLUDE } = require('./logichook/LogicHookConsts')

Expand Down Expand Up @@ -85,8 +85,8 @@ class ConvoStep {
}

toString () {
return this.stepTag +
': #' + this.sender +
return (this.stepTag ? this.stepTag + ': ' : '') +
'#' + this.sender +
' - ' + (this.optional ? '?' : '') + (this.not ? '!' : '') +
(this.messageText || '') +
(this.asserters && this.asserters.length > 0 ? ' ' + this.asserters.map(a => a.toString()).join(' ASS: ') : '') +
Expand Down Expand Up @@ -221,16 +221,6 @@ class Convo {
}
container.caps[Capabilities.TESTCASENAME] = this.header.name
try {
try {
const effectiveConversation = this._getEffectiveConversation()
this.originConversation = this.conversation
this.conversation = effectiveConversation
} catch (err) {
transcript.err = err
transcript.scriptingMemory = scriptingMemory
transcript.convoEnd = new Date()
throw new TranscriptError(err, transcript)
}
try {
// onConvoBegin first or assertConvoBegin? If onConvoBegin, then it is possible to assert it too
await this.scriptingEvents.onConvoBegin({ convo: this, container, transcript, scriptingMemory })
Expand Down Expand Up @@ -325,7 +315,7 @@ class Convo {
})
lastMeConvoStep = convoStep
transcriptStep.botBegin = new Date()
if (!_.isNull(meMsg.messageText) || meMsg.sourceData || (meMsg.userInputs && meMsg.userInputs.length)) {
if (!_.isNull(meMsg.messageText) || meMsg.sourceData || (meMsg.userInputs && meMsg.userInputs.length) || (meMsg.logicHooks && meMsg.logicHooks.length)) {
try {
Object.assign(meMsg, { header: this.header, conversation: this.conversation, currentStepIndex, scriptingMemory })
await container.UserSays(meMsg)
Expand Down Expand Up @@ -591,11 +581,7 @@ class Convo {
return normalizeText(str, !!container.caps[Capabilities.SCRIPTING_NORMALIZE_TEXT])
}

_getEffectiveConversation () {
if (this.effectiveConversation) {
return this.effectiveConversation
}

expandPartialConvos () {
const _getIncludeLogicHookNames = (convoStep) => {
if (!convoStep.logicHooks) {
return []
Expand All @@ -614,41 +600,50 @@ class Convo {
return result.map((hook) => hook.args[0])
}

const _getEffectiveConversationRecursive = (conversation, parentPConvos = [], result = []) => {
conversation.forEach((convoStep) => {
const includeLogicHooks = _getIncludeLogicHookNames(convoStep)
const partialConvos = this.context.GetPartialConvos()

if (includeLogicHooks.length === 0 || convoStep.hasInteraction()) {
// dont put convo name for ConvoSteps on the root.
const steptagPath = parentPConvos.length === 0 ? '' : parentPConvos.join('/') + '/'
result.push(Object.assign(new ConvoStep(), convoStep, { stepTag: `${steptagPath}${convoStep.stepTag}` }))
const _getEffectiveConversationRecursive = (conversation, parentPConvos = [], result = [], ignoreBeginEnd = true) => {
conversation.forEach((convoStep) => {
let includeLogicHooks = []
if (convoStep.sender === 'include') {
if (convoStep.channel) {
includeLogicHooks.push(convoStep.channel)
}
if (convoStep.messageText) {
includeLogicHooks = includeLogicHooks.concat(splitStringInNonEmptyLines(convoStep.messageText))
}
} else {
includeLogicHooks = _getIncludeLogicHookNames(convoStep)
if (includeLogicHooks.length === 0 || convoStep.hasInteraction()) {
if (!ignoreBeginEnd || (convoStep.sender !== 'begin' && convoStep.sender !== 'end')) {
// dont put convo name for ConvoSteps on the root.
const steptagPath = parentPConvos.length === 0 ? '' : parentPConvos.join('/') + '/'
result.push(Object.assign(new ConvoStep(), convoStep, { stepTag: `${steptagPath}${convoStep.stepTag}` }))
}
}
}

includeLogicHooks.forEach((includeLogicHook) => {
const alreadyThereAt = parentPConvos.indexOf(includeLogicHook)
if (alreadyThereAt >= 0) {
throw new BotiumError(`Partial convos are included circular. "${includeLogicHook}" is referenced by "/${parentPConvos.slice(0, alreadyThereAt).join('/')}" and by "/${parentPConvos.join('/')}" `)
}
const partialConvos = this.context.GetPartialConvos()
if (!partialConvos || Object.keys(partialConvos).length === 0) {
throw new BotiumError(`Cant find partial convo with name ${includeLogicHook} (There are no partial convos)`)
}
const partialConvo = partialConvos[includeLogicHook]
if (!partialConvo) {
throw new BotiumError(`Cant find partial convo with name ${includeLogicHook} (available partial convos: ${Object.keys(partialConvos).join(',')})`)
}

_getEffectiveConversationRecursive(partialConvo.conversation, [...parentPConvos, includeLogicHook], result)
_getEffectiveConversationRecursive(partialConvo.conversation, [...parentPConvos, includeLogicHook], result, true)
debug(`Partial convo ${includeLogicHook} included`)
})
})

return result
}

this.effectiveConversation = _getEffectiveConversationRecursive(this.conversation)

return this.effectiveConversation
this.conversation = _getEffectiveConversationRecursive(this.conversation, [], [], false)
}
}

Expand Down
Loading

0 comments on commit ecdc2f8

Please sign in to comment.