diff --git a/packages/basic.gblib/services/GBVMService.ts b/packages/basic.gblib/services/GBVMService.ts index 8558ec2a..34a77f2f 100644 --- a/packages/basic.gblib/services/GBVMService.ts +++ b/packages/basic.gblib/services/GBVMService.ts @@ -74,41 +74,46 @@ export class GBVMService extends GBService { let filename: string = file.name; if (filename.endsWith('.docx')) { - const wordFile = filename; - const vbsFile = filename.substr(0, filename.indexOf('docx')) + 'vbs'; - const fullVbsFile = urlJoin(folder, vbsFile); - const docxStat = Fs.statSync(urlJoin(folder, wordFile)); - const interval = 3000; // If compiled is older 30 seconds, then recompile. - let writeVBS = true; - if (Fs.existsSync(fullVbsFile)) { - const vbsStat = Fs.statSync(fullVbsFile); - if (docxStat['mtimeMs'] < vbsStat['mtimeMs'] + interval) { - writeVBS = false; - } - } - filename = vbsFile; - let mainName = GBVMService.getMethodNameFromVBSFilename(filename); - min.scriptMap[filename] = mainName; + filename = await this.loadDialog(filename, folder, min); + } + }); + } - if (writeVBS) { - let text = await this.getTextFromWord(folder, wordFile); + public async loadDialog(filename: string, folder: string, min: GBMinInstance) { + const wordFile = filename; + const vbsFile = filename.substr(0, filename.indexOf('docx')) + 'vbs'; + const fullVbsFile = urlJoin(folder, vbsFile); + const docxStat = Fs.statSync(urlJoin(folder, wordFile)); + const interval = 3000; // If compiled is older 30 seconds, then recompile. + let writeVBS = true; + if (Fs.existsSync(fullVbsFile)) { + const vbsStat = Fs.statSync(fullVbsFile); + if (docxStat['mtimeMs'] < vbsStat['mtimeMs'] + interval) { + writeVBS = false; + } + } + filename = vbsFile; + let mainName = GBVMService.getMethodNameFromVBSFilename(filename); + min.scriptMap[filename] = mainName; - const schedule = GBVMService.getSetScheduleKeywordArgs(text); - const s = new ScheduleServices(); - if (schedule) { - await s.createOrUpdateSchedule(min, schedule, mainName); - } else { - await s.deleteScheduleIfAny(min, mainName); - } - text = text.replace(/^\s*SET SCHEDULE (.*)/gim, ''); - Fs.writeFileSync(urlJoin(folder, vbsFile), text); - } + if (writeVBS) { + let text = await this.getTextFromWord(folder, wordFile); - // Process node_modules install. + const schedule = GBVMService.getSetScheduleKeywordArgs(text); + const s = new ScheduleServices(); + if (schedule) { + await s.createOrUpdateSchedule(min, schedule, mainName); + } else { + await s.deleteScheduleIfAny(min, mainName); + } + text = text.replace(/^\s*SET SCHEDULE (.*)/gim, ''); + Fs.writeFileSync(urlJoin(folder, vbsFile), text); + } - const node_modules = urlJoin(folder, 'node_modules'); - if (!Fs.existsSync(node_modules)) { - const packageJson = ` + // Process node_modules install. + const node_modules = urlJoin(folder, 'node_modules'); + if (!Fs.existsSync(node_modules)) { + const packageJson = ` { "name": "${min.botId}.gbdialog", "version": "1.0.0", @@ -123,40 +128,38 @@ export class GBVMService extends GBService { "vm2": "3.9.11" } }`; - Fs.writeFileSync(urlJoin(folder, 'package.json'), packageJson); + Fs.writeFileSync(urlJoin(folder, 'package.json'), packageJson); - GBLogEx.info(min, `BASIC: Installing .gbdialog node_modules for ${min.botId}...`); - const npmPath = urlJoin(process.env.PWD, 'node_modules', '.bin', 'npm'); - child_process.execSync(`${npmPath} install`, { cwd: folder }); - } + GBLogEx.info(min, `BASIC: Installing .gbdialog node_modules for ${min.botId}...`); + const npmPath = urlJoin(process.env.PWD, 'node_modules', '.bin', 'npm'); + child_process.execSync(`${npmPath} install`, { cwd: folder }); + } - // Hot swap for .vbs files. - - const fullFilename = urlJoin(folder, filename); - if (process.env.GBDIALOG_HOTSWAP) { - Fs.watchFile(fullFilename, async () => { - await this.translateBASIC(fullFilename, mainName, min); - const parsedCode: string = Fs.readFileSync(jsfile, 'utf8'); - min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode; - }); - } - - const compiledAt = Fs.statSync(fullFilename); - const jsfile = urlJoin(folder, `${filename}.js`); - - if (Fs.existsSync(jsfile)) { - const jsStat = Fs.statSync(jsfile); - const interval = 30000; // If compiled is older 30 seconds, then recompile. - if (compiledAt.isFile() && compiledAt['mtimeMs'] > jsStat['mtimeMs'] + interval) { - await this.translateBASIC(fullFilename, mainName, min); - } - } else { - await this.translateBASIC(fullFilename, mainName, min); - } + // Hot swap for .vbs files. + const fullFilename = urlJoin(folder, filename); + if (process.env.GBDIALOG_HOTSWAP) { + Fs.watchFile(fullFilename, async () => { + await this.translateBASIC(fullFilename, mainName, min); const parsedCode: string = Fs.readFileSync(jsfile, 'utf8'); min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode; + }); + } + + const compiledAt = Fs.statSync(fullFilename); + const jsfile = urlJoin(folder, `${filename}.js`); + + if (Fs.existsSync(jsfile)) { + const jsStat = Fs.statSync(jsfile); + const interval = 30000; // If compiled is older 30 seconds, then recompile. + if (compiledAt.isFile() && compiledAt['mtimeMs'] > jsStat['mtimeMs'] + interval) { + await this.translateBASIC(fullFilename, mainName, min); } - }); + } else { + await this.translateBASIC(fullFilename, mainName, min); + } + const parsedCode: string = Fs.readFileSync(jsfile, 'utf8'); + min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode; + return filename; } public async translateBASIC(filename: any, mainName: string, min: GBMinInstance) { @@ -260,18 +263,24 @@ export class GBVMService extends GBService { private async getTextFromWord(folder: string, filename: string) { return new Promise(async (resolve, reject) => { - textract.fromFileWithPath(urlJoin(folder, filename), { preserveLineBreaks: true }, (error, text) => { + const path = urlJoin(folder, filename); + textract.fromFileWithPath(path, { preserveLineBreaks: true }, (error, text) => { if (error) { - reject(error); - } else { + if (error.message.startsWith('File not correctly recognized as zip file')) { + text = Fs.readFileSync(path, 'utf8'); + } else { + reject(error); + } + } + + if (text) { text = text.replace('¨', '"'); text = text.replace('“', '"'); text = text.replace('”', '"'); text = text.replace('‘', "'"); text = text.replace('’', "'"); - - resolve(text); } + resolve(text); }); }); } @@ -407,8 +416,6 @@ export class GBVMService extends GBService { } catch (error) { throw new Error(`BASIC RUNTIME ERR: ${error.message ? error.message : error}\n Stack:${error.stack}`); } finally { - - } return result; diff --git a/packages/kb.gbapp/services/KBService.ts b/packages/kb.gbapp/services/KBService.ts index f413863a..c7e14799 100644 --- a/packages/kb.gbapp/services/KBService.ts +++ b/packages/kb.gbapp/services/KBService.ts @@ -72,6 +72,7 @@ import { url } from 'inspector'; import { min } from 'lodash'; import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js'; import { text } from 'body-parser'; +import { GBVMService } from '../../basic.gblib/services/GBVMService.js'; /** * Result for quey on KB data. @@ -410,7 +411,7 @@ export class KBService implements IGBKBService { public async importKbTabularFile( filePath: string, - instanceId: number, + min: GBMinInstance, packageId: number ): Promise { GBLog.info(`Now reading file ${filePath}...`); @@ -522,10 +523,26 @@ export class KBService implements IGBKBService { return false; } + // In case of code cell, compiles it and associate with the answer. + + if (answer.toLowerCase().startsWith ('/basic') ){ + const code = answer.substr(6); + const gbaiName = `${min.instance.botId}.gbai`; + const gbdialogName = `${min.instance.botId}.gbdialog`; + const scriptName = `tmp${GBAdminService.getRndReadableIdentifier()}.docx`; + const localName = Path.join('work', gbaiName, gbdialogName, `${scriptName}`); + Fs.writeFileSync(localName, code, { encoding: null }); + answer = scriptName; + + const vm = new GBVMService(); + await vm.loadDialog(Path.basename(localName), Path.dirname(localName), min); + } + + // Now with all the data ready, creates entities in the store. const answer1 = { - instanceId: instanceId, + instanceId: min.instance.instanceId, content: answer, format: format, media: media, @@ -543,7 +560,7 @@ export class KBService implements IGBKBService { subject3: subject3, subject4: subject4, content: question.replace(/["]+/g, ''), - instanceId: instanceId, + instanceId: min.instance.instanceId, skipIndex: question.charAt(0) === '"', packageId: packageId }; @@ -625,7 +642,7 @@ export class KBService implements IGBKBService { // Import tabular files in the tabular directory. - await this.importKbTabularDirectory(localPath, instance, packageStorage.packageId); + await this.importKbTabularDirectory(localPath, min, packageStorage.packageId); // Import remaining .md files in articles directory. @@ -803,12 +820,12 @@ export class KBService implements IGBKBService { } } - public async importKbTabularDirectory(localPath: string, instance: IGBInstance, packageId: number): Promise { + public async importKbTabularDirectory(localPath: string, min: GBMinInstance, packageId: number): Promise { const files = await walkPromise(localPath); await CollectionUtil.asyncForEach(files, async file => { if (file !== null && file.name.endsWith('.xlsx')) { - return await this.importKbTabularFile(urlJoin(file.root, file.name), instance.instanceId, packageId); + return await this.importKbTabularFile(urlJoin(file.root, file.name), min, packageId); } }); }