UNPKG

botium-core

Version:
178 lines (148 loc) 5.28 kB
const _ = require('lodash') const Capabilities = require('../Capabilities') const Constants = require('./Constants') const CompilerBase = require('./CompilerBase') const Utterance = require('./Utterance') const { ConvoHeader, Convo } = require('./Convo') const { linesToConvoStep, convoStepToLines, validateConvo, validSenders, linesToScriptingMemories } = require('./helper') module.exports = class CompilerTxt extends CompilerBase { constructor (context, caps = {}) { super(context, caps) this.eol = caps[Capabilities.SCRIPTING_TXT_EOL] } Validate () { super.Validate() this._AssertCapabilityExists(Capabilities.SCRIPTING_TXT_EOL) } GetHeaders (scriptBuffer) { let scriptData = scriptBuffer if (Buffer.isBuffer(scriptBuffer)) scriptData = scriptData.toString() const lines = scriptData.split(this.eol) const header = { } if (lines && !lines[0].startsWith('#')) { header.name = lines[0] } return new ConvoHeader(header) } Compile (scriptBuffer, scriptType = Constants.SCRIPTING_TYPE_CONVO) { let scriptData = scriptBuffer if (Buffer.isBuffer(scriptBuffer)) scriptData = scriptData.toString() const lines = _.map(scriptData.split(this.eol), (line) => line.trim()) if (scriptType === Constants.SCRIPTING_TYPE_CONVO) { return this._compileConvo(lines, false) } else if (scriptType === Constants.SCRIPTING_TYPE_PCONVO) { return this._compileConvo(lines, true) } else if (scriptType === Constants.SCRIPTING_TYPE_UTTERANCES) { return this._compileUtterances(lines) } else if (scriptType === Constants.SCRIPTING_TYPE_SCRIPTING_MEMORY) { return this._compileScriptingMemory(lines) } else { throw Error(`Invalid script type ${scriptType}`) } } _compileConvo (lines, isPartial = false) { const convo = { header: {}, conversation: [] } let currentLineIndex = 0 let currentLines = [] let convoStepSender = null let convoStepChannel = null let convoStepLineIndex = null const parseMsg = (lines) => { lines = lines || [] return linesToConvoStep(lines, convoStepSender, this.context, this.eol) } const pushPrev = () => { if (convoStepSender && currentLines) { const convoStep = { sender: convoStepSender, channel: convoStepChannel, stepTag: 'Line ' + convoStepLineIndex } Object.assign(convoStep, parseMsg(currentLines)) convo.conversation.push(convoStep) } else if (!convoStepSender && currentLines) { convo.header.name = currentLines[0] if (currentLines.length > 1) { convo.header.description = currentLines.slice(1).join(this.eol) } } } const isValidTagLine = (line) => { if (!line || !line.startsWith('#')) return false const sender = line.substr(1).split(' ')[0] return validSenders.includes(sender) } lines.forEach((line) => { currentLineIndex++ line = line.trim() if (isValidTagLine(line)) { pushPrev() convoStepSender = line.substr(1).trim() convoStepChannel = null convoStepLineIndex = currentLineIndex if (convoStepSender.indexOf(' ') > 0) { convoStepChannel = convoStepSender.substr(convoStepSender.indexOf(' ') + 1).trim() convoStepSender = convoStepSender.substr(0, convoStepSender.indexOf(' ')).trim() } currentLines = [] } else { currentLines.push(line) } }) pushPrev() const result = [new Convo(this.context, convo)] if (isPartial) { this.context.AddPartialConvos(result) } else { this.context.AddConvos(result) } return result } _compileUtterances (lines) { if (lines && lines.length > 0) { const result = [new Utterance({ name: lines[0], utterances: lines.length > 1 ? lines.slice(1) : [] })] this.context.AddUtterances(result) return result } } _compileScriptingMemory (lines) { if (lines && lines.length > 1) { const scriptingMemories = linesToScriptingMemories(lines, this.caps[Capabilities.SCRIPTING_MEMORY_COLUMN_MODE]) if (scriptingMemories && scriptingMemories.length > 0) { this.context.AddScriptingMemories(scriptingMemories) } return scriptingMemories } } Decompile (convos) { if (convos.length > 1) { throw new Error('only one convo per script') } const convo = convos[0] const validationResult = validateConvo(convo) if (validationResult.errors.length > 0) { throw new Error(validationResult.errors.map(e => e.message).join(' - ')) } let script = '' if (convo.header.name) { script += convo.header.name + this.eol } if (convo.header.description) { script += convo.header.description + this.eol } convo.conversation.forEach((step) => { script += this.eol script += '#' + step.sender if (step.channel && step.channel !== 'default') { script += ' ' + step.channel } script += this.eol const stepLines = convoStepToLines(step) if (stepLines && stepLines.length > 0) script += stepLines.join(this.eol) + this.eol }) return script } }