From ab5d5079896a7ac2d627fa1d431e1e0d97e236ae Mon Sep 17 00:00:00 2001 From: Rodrigo Rodriguez Date: Mon, 30 Mar 2020 14:03:12 -0300 Subject: [PATCH] fix(core.gbapp): Refactoring in MD fix in disabling auto-compiling of .gbapps. --- .../services/GBConversationalService.ts | 106 +++++++++++++++++- packages/core.gbapp/services/GBDeployer.ts | 16 ++- packages/core.gbapp/services/GBMinService.ts | 3 + packages/kb.gbapp/services/KBService.ts | 103 ++++------------- 4 files changed, 134 insertions(+), 94 deletions(-) diff --git a/packages/core.gbapp/services/GBConversationalService.ts b/packages/core.gbapp/services/GBConversationalService.ts index bf1a3edb..67806d21 100644 --- a/packages/core.gbapp/services/GBConversationalService.ts +++ b/packages/core.gbapp/services/GBConversationalService.ts @@ -41,6 +41,8 @@ import { LuisRecognizer } from 'botbuilder-ai'; import { GBDialogStep, GBLog, GBMinInstance, IGBConversationalService, IGBCoreService } from 'botlib'; import { AzureText } from 'pragmatismo-io-framework'; import { Messages } from '../strings'; +import { GBServer } from '../../../src/app'; +const urlJoin = require('url-join'); const PasswordGenerator = require("strict-password-generator").default; const Nexmo = require('nexmo'); @@ -80,7 +82,7 @@ export class GBConversationalService implements IGBConversationalService { public async sendFile(min: GBMinInstance, step: GBDialogStep, url: string): Promise { const mobile = step.context.activity.from.id; - const filename = url.substring(url.lastIndexOf('/')+1); + const filename = url.substring(url.lastIndexOf('/') + 1); await min.whatsAppDirectLine.sendFileToDevice(mobile, url, filename); } @@ -120,11 +122,107 @@ export class GBConversationalService implements IGBConversationalService { } ); } + + public async sendToMobile(min: GBMinInstance, mobile: string, message: string) { + + // HACK: Gets the sendToDevice method of whatsapp.gblib and setups scheduler. + + const whatsappChannel = (min.packages[6] as any).getChannel(); + const sendToDevice = whatsappChannel.sendToDevice.bind(whatsappChannel); + sendToDevice(mobile, message); + } + // tslint:enable:no-unsafe-any + public async sendMarkdownToMobile(min: GBMinInstance, step: GBDialogStep, mobile: string, text: string) { + + let sleep = (ms) => { + return new Promise(resolve => { + setTimeout(resolve, ms) + }) + } + enum State { + InText, + InImage, + InImageBegin, + InImageCaption, + InImageAddressBegin, + InImageAddressBody + }; + let state = State.InText; + let currentImage = ''; + let currentText = ''; + + //![General Bots](/instance/images/gb.png) + for (var i = 0; i < text.length; i++) { + const c = text.charAt(i); + + switch (state) { + case State.InText: + if (c === '!') { + state = State.InImageBegin; + } + else { + currentText = currentText.concat(c); + } + break; + case State.InImageBegin: + if (c === '[') { + if (currentText !== '') { + if (mobile === null) { + await step.context.sendActivity(currentText); + } + else{ + this.sendToMobile(min, mobile, currentText); + } + await sleep(3000); + } + currentText = ''; + state = State.InImageCaption; + } + else { + state = State.InText; + currentText = currentText.concat('!').concat(c); + } + break; + case State.InImageCaption: + if (c === ']') { + state = State.InImageAddressBegin; + } + break; + case State.InImageAddressBegin: + if (c === '(') { + state = State.InImageAddressBody; + } + break; + case State.InImageAddressBody: + if (c === ')') { + state = State.InText; + let url = urlJoin(GBServer.globals.publicAddress, currentImage); + await this.sendFile(min, step, url); + await sleep(5000); + currentImage = ''; + } + else { + currentImage = currentImage.concat(c); + } + break; + } + + } + if (currentText !== '') { + if (mobile === null) { + await step.context.sendActivity(currentText); + } + else{ + this.sendToMobile(min, mobile, currentText); + } + } + } + public async routeNLP(step: GBDialogStep, min: GBMinInstance, text: string): Promise { - if (min.instance.nlpAppId === null){ + if (min.instance.nlpAppId === null) { return false; } @@ -157,7 +255,7 @@ export class GBConversationalService implements IGBConversationalService { Object.keys(nlp.intents).forEach((name) => { const score = nlp.intents[name].score; - if (score > min.instance.nlpScore){ + if (score > min.instance.nlpScore) { nlpActive = true; } }); @@ -166,7 +264,7 @@ export class GBConversationalService implements IGBConversationalService { const topIntent = LuisRecognizer.topIntent(nlp); if (topIntent !== undefined && nlpActive) { - + const intent = topIntent; // tslint:disable:no-unsafe-any const firstEntity = nlp.entities && nlp.entities.length > 0 ? nlp.entities[0].entity.toUpperCase() : undefined; diff --git a/packages/core.gbapp/services/GBDeployer.ts b/packages/core.gbapp/services/GBDeployer.ts index 47e38ef6..1b1ad233 100644 --- a/packages/core.gbapp/services/GBDeployer.ts +++ b/packages/core.gbapp/services/GBDeployer.ts @@ -508,18 +508,22 @@ export class GBDeployer { if (this.isSystemPackage(filenameOnly) === false) { GBLog.info(`Deploying app: ${e}...`); - let folder = Path.join(e, 'node_modules'); - if (!Fs.existsSync(folder)) { - GBLog.info(`Installing modules for ${e}...`); - child_process.execSync('npm install', { cwd: e }); - } + let folder = Path.join(e, 'node_modules'); + if (process.env.GBAPP_DISABLE_COMPILE !== "true") { + if (!Fs.existsSync(folder)) { + GBLog.info(`Installing modules for ${e}...`); + child_process.execSync('npm install', { cwd: e }); + } + } folder = Path.join(e, 'dist'); if (!Fs.existsSync()) { GBLog.info(`Compiling ${e}...`); try { - child_process.execSync(Path.join(process.env.PWD, 'node_modules/.bin/tsc'), { cwd: e }); + if (process.env.GBAPP_DISABLE_COMPILE !== "true") { + child_process.execSync(Path.join(process.env.PWD, 'node_modules/.bin/tsc'), { cwd: e }); + } const m = await import(e); const p = new m.Package(); p.loadPackage(core, core.sequelize); diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index f83fdd34..51e2640a 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -59,6 +59,7 @@ import { import { MicrosoftAppCredentials } from 'botframework-connector'; import { GBServer } from '../../../src/app'; import { AskDialogArgs } from '../../kb.gbapp/dialogs/AskDialog'; +import { KBService } from '../../kb.gbapp/services/KBService'; import { Messages } from '../strings'; import { GBConfigService } from './GBConfigService'; import { GBDeployer } from './GBDeployer'; @@ -73,6 +74,7 @@ export class GBMinService { public conversationalService: IGBConversationalService; public adminService: IGBAdminService; public deployer: GBDeployer; + private static uiPackage = 'default.gbui'; public corePackage = 'core.gbai'; @@ -387,6 +389,7 @@ export class GBMinService { min.conversationalService = this.conversationalService; min.adminService = this.adminService; min.deployService = this.deployer; + min.kbService = new KBService(this.core.sequelize); min.instance = await this.core.loadInstance(min.botId); min.cbMap = {}; min.scriptMap = {}; diff --git a/packages/kb.gbapp/services/KBService.ts b/packages/kb.gbapp/services/KBService.ts index ccbed0f4..03b41e13 100644 --- a/packages/kb.gbapp/services/KBService.ts +++ b/packages/kb.gbapp/services/KBService.ts @@ -37,7 +37,7 @@ var Excel = require('exceljs'); const Path = require('path'); const Fs = require('fs'); -import urlJoin = require('url-join'); +const urlJoin = require('url-join'); const marked = require('marked'); const path = require('path'); const asyncPromise = require('async-promises'); @@ -46,7 +46,7 @@ const walkPromise = require('walk-promise'); const parse = require('bluebird').promisify(require('csv-parse')); const { SearchService } = require('azure-search-client'); -import { GBDialogStep, GBLog, IGBConversationalService, IGBCoreService, IGBInstance, GBMinInstance } from 'botlib'; +import { IGBKBService, GBDialogStep, GBLog, IGBConversationalService, IGBCoreService, IGBInstance, GBMinInstance } from 'botlib'; import { Op } from 'sequelize'; import { Sequelize } from 'sequelize-typescript'; import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService'; @@ -55,7 +55,6 @@ import { GBDeployer } from '../../core.gbapp/services/GBDeployer'; import { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from '../models'; import { Messages } from '../strings'; import { GBConfigService } from './../../core.gbapp/services/GBConfigService'; -import { GBServer } from '../../../src/app'; import { CSService } from '../../customer-satisfaction.gbapp/services/CSService'; @@ -70,7 +69,7 @@ export class KBServiceSearchResults { /** * All services related to knowledge base management. */ -export class KBService { +export class KBService implements IGBKBService { public sequelize: Sequelize; constructor(sequelize: Sequelize) { @@ -99,6 +98,17 @@ export class KBService { return out.join(' '); } + public async getAnswerTextByMediaName(instanceId: number, answerMediaName: string): Promise{ + const answer = await GuaribasAnswer.findOne({ + where: { + instanceId: instanceId, + media: answerMediaName + } + }); + + return answer.content; + } + public async getQuestionById(instanceId: number, questionId: number): Promise { return GuaribasQuestion.findOne({ where: { @@ -279,11 +289,14 @@ export class KBService { // Extracts answer from external media if any. + let media = null; + if (answer.indexOf('.md') > -1) { const mediaFilename = urlJoin(path.dirname(filePath), '..', 'articles', answer); if (Fs.existsSync(mediaFilename)) { answer = Fs.readFileSync(mediaFilename, 'utf8'); format = '.md'; + media = path.basename(mediaFilename); } else { GBLog.info(`[GBImporter] File not found: ${mediaFilename}.`); answer = ''; @@ -318,6 +331,7 @@ export class KBService { instanceId: instanceId, content: answer, format: format, + media: media, packageId: packageId, prevId: lastQuestionId !== null ? lastQuestionId : 0 }); @@ -390,7 +404,7 @@ export class KBService { await this.sendMarkdownToWeb(step, conversationalService, html, answer); } else if (channel === 'whatsapp') { - await this.sendMarkdownToMobile(step, answer, conversationalService, min); + await conversationalService.sendMarkdownToMobile(min, step, null, answer.content); } else { @@ -413,85 +427,6 @@ export class KBService { }); } - private async sendMarkdownToMobile(step: GBDialogStep, answer: GuaribasAnswer, conversationalService: IGBConversationalService, min: GBMinInstance) { - - let text = answer.content; - - let sleep = (ms) => { - return new Promise(resolve => { - setTimeout(resolve, ms) - }) - } - - enum State { - InText, - InImage, - InImageBegin, - InImageCaption, - InImageAddressBegin, - InImageAddressBody - }; - let state = State.InText; - let currentImage = ''; - let currentText = ''; - - //![General Bots](/instance/images/gb.png) - for (var i = 0; i < text.length; i++) { - const c = text.charAt(i); - - switch (state) { - case State.InText: - if (c === '!') { - state = State.InImageBegin; - } - else { - currentText = currentText.concat(c); - } - break; - case State.InImageBegin: - if (c === '[') { - if (currentText !== '') { - await step.context.sendActivity(currentText); - await sleep(3000); - } - - currentText = ''; - state = State.InImageCaption; - } - else { - state = State.InText; - currentText = currentText.concat('!').concat(c); - } - break; - case State.InImageCaption: - if (c === ']') { - state = State.InImageAddressBegin; - } - break; - case State.InImageAddressBegin: - if (c === '(') { - state = State.InImageAddressBody; - } - break; - case State.InImageAddressBody: - if (c === ')') { - state = State.InText; - let url = urlJoin(GBServer.globals.publicAddress, currentImage); - await conversationalService.sendFile(min, step, url); - await sleep(5000); - currentImage = ''; - } - else { - currentImage = currentImage.concat(c); - } - break; - } - - } - if (currentText !== '') { - await step.context.sendActivity(currentText); - } - } private async playVideo(conversationalService: IGBConversationalService, step: GBDialogStep, answer: GuaribasAnswer) { await conversationalService.sendEvent(step, 'play', {