fix(core.gbapp): Refactoring in MD fix in disabling auto-compiling of .gbapps.

This commit is contained in:
Rodrigo Rodriguez 2020-03-30 14:03:12 -03:00
parent e1ad711904
commit ab5d507989
4 changed files with 134 additions and 94 deletions

View file

@ -41,6 +41,8 @@ import { LuisRecognizer } from 'botbuilder-ai';
import { GBDialogStep, GBLog, GBMinInstance, IGBConversationalService, IGBCoreService } from 'botlib'; import { GBDialogStep, GBLog, GBMinInstance, IGBConversationalService, IGBCoreService } from 'botlib';
import { AzureText } from 'pragmatismo-io-framework'; import { AzureText } from 'pragmatismo-io-framework';
import { Messages } from '../strings'; import { Messages } from '../strings';
import { GBServer } from '../../../src/app';
const urlJoin = require('url-join');
const PasswordGenerator = require("strict-password-generator").default; const PasswordGenerator = require("strict-password-generator").default;
const Nexmo = require('nexmo'); const Nexmo = require('nexmo');
@ -80,7 +82,7 @@ export class GBConversationalService implements IGBConversationalService {
public async sendFile(min: GBMinInstance, step: GBDialogStep, url: string): Promise<any> { public async sendFile(min: GBMinInstance, step: GBDialogStep, url: string): Promise<any> {
const mobile = step.context.activity.from.id; 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); 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 // 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<boolean> { public async routeNLP(step: GBDialogStep, min: GBMinInstance, text: string): Promise<boolean> {
if (min.instance.nlpAppId === null){ if (min.instance.nlpAppId === null) {
return false; return false;
} }
@ -157,7 +255,7 @@ export class GBConversationalService implements IGBConversationalService {
Object.keys(nlp.intents).forEach((name) => { Object.keys(nlp.intents).forEach((name) => {
const score = nlp.intents[name].score; const score = nlp.intents[name].score;
if (score > min.instance.nlpScore){ if (score > min.instance.nlpScore) {
nlpActive = true; nlpActive = true;
} }
}); });

View file

@ -508,18 +508,22 @@ export class GBDeployer {
if (this.isSystemPackage(filenameOnly) === false) { if (this.isSystemPackage(filenameOnly) === false) {
GBLog.info(`Deploying app: ${e}...`); 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'); folder = Path.join(e, 'dist');
if (!Fs.existsSync()) { if (!Fs.existsSync()) {
GBLog.info(`Compiling ${e}...`); GBLog.info(`Compiling ${e}...`);
try { 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 m = await import(e);
const p = new m.Package(); const p = new m.Package();
p.loadPackage(core, core.sequelize); p.loadPackage(core, core.sequelize);

View file

@ -59,6 +59,7 @@ import {
import { MicrosoftAppCredentials } from 'botframework-connector'; import { MicrosoftAppCredentials } from 'botframework-connector';
import { GBServer } from '../../../src/app'; import { GBServer } from '../../../src/app';
import { AskDialogArgs } from '../../kb.gbapp/dialogs/AskDialog'; import { AskDialogArgs } from '../../kb.gbapp/dialogs/AskDialog';
import { KBService } from '../../kb.gbapp/services/KBService';
import { Messages } from '../strings'; import { Messages } from '../strings';
import { GBConfigService } from './GBConfigService'; import { GBConfigService } from './GBConfigService';
import { GBDeployer } from './GBDeployer'; import { GBDeployer } from './GBDeployer';
@ -73,6 +74,7 @@ export class GBMinService {
public conversationalService: IGBConversationalService; public conversationalService: IGBConversationalService;
public adminService: IGBAdminService; public adminService: IGBAdminService;
public deployer: GBDeployer; public deployer: GBDeployer;
private static uiPackage = 'default.gbui'; private static uiPackage = 'default.gbui';
public corePackage = 'core.gbai'; public corePackage = 'core.gbai';
@ -387,6 +389,7 @@ export class GBMinService {
min.conversationalService = this.conversationalService; min.conversationalService = this.conversationalService;
min.adminService = this.adminService; min.adminService = this.adminService;
min.deployService = this.deployer; min.deployService = this.deployer;
min.kbService = new KBService(this.core.sequelize);
min.instance = await this.core.loadInstance(min.botId); min.instance = await this.core.loadInstance(min.botId);
min.cbMap = {}; min.cbMap = {};
min.scriptMap = {}; min.scriptMap = {};

View file

@ -37,7 +37,7 @@
var Excel = require('exceljs'); var Excel = require('exceljs');
const Path = require('path'); const Path = require('path');
const Fs = require('fs'); const Fs = require('fs');
import urlJoin = require('url-join'); const urlJoin = require('url-join');
const marked = require('marked'); const marked = require('marked');
const path = require('path'); const path = require('path');
const asyncPromise = require('async-promises'); const asyncPromise = require('async-promises');
@ -46,7 +46,7 @@ const walkPromise = require('walk-promise');
const parse = require('bluebird').promisify(require('csv-parse')); const parse = require('bluebird').promisify(require('csv-parse'));
const { SearchService } = require('azure-search-client'); 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 { Op } from 'sequelize';
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript';
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService'; 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 { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from '../models';
import { Messages } from '../strings'; import { Messages } from '../strings';
import { GBConfigService } from './../../core.gbapp/services/GBConfigService'; import { GBConfigService } from './../../core.gbapp/services/GBConfigService';
import { GBServer } from '../../../src/app';
import { CSService } from '../../customer-satisfaction.gbapp/services/CSService'; import { CSService } from '../../customer-satisfaction.gbapp/services/CSService';
@ -70,7 +69,7 @@ export class KBServiceSearchResults {
/** /**
* All services related to knowledge base management. * All services related to knowledge base management.
*/ */
export class KBService { export class KBService implements IGBKBService {
public sequelize: Sequelize; public sequelize: Sequelize;
constructor(sequelize: Sequelize) { constructor(sequelize: Sequelize) {
@ -99,6 +98,17 @@ export class KBService {
return out.join(' '); return out.join(' ');
} }
public async getAnswerTextByMediaName(instanceId: number, answerMediaName: string): Promise<string>{
const answer = await GuaribasAnswer.findOne({
where: {
instanceId: instanceId,
media: answerMediaName
}
});
return answer.content;
}
public async getQuestionById(instanceId: number, questionId: number): Promise<GuaribasQuestion> { public async getQuestionById(instanceId: number, questionId: number): Promise<GuaribasQuestion> {
return GuaribasQuestion.findOne({ return GuaribasQuestion.findOne({
where: { where: {
@ -279,11 +289,14 @@ export class KBService {
// Extracts answer from external media if any. // Extracts answer from external media if any.
let media = null;
if (answer.indexOf('.md') > -1) { if (answer.indexOf('.md') > -1) {
const mediaFilename = urlJoin(path.dirname(filePath), '..', 'articles', answer); const mediaFilename = urlJoin(path.dirname(filePath), '..', 'articles', answer);
if (Fs.existsSync(mediaFilename)) { if (Fs.existsSync(mediaFilename)) {
answer = Fs.readFileSync(mediaFilename, 'utf8'); answer = Fs.readFileSync(mediaFilename, 'utf8');
format = '.md'; format = '.md';
media = path.basename(mediaFilename);
} else { } else {
GBLog.info(`[GBImporter] File not found: ${mediaFilename}.`); GBLog.info(`[GBImporter] File not found: ${mediaFilename}.`);
answer = ''; answer = '';
@ -318,6 +331,7 @@ export class KBService {
instanceId: instanceId, instanceId: instanceId,
content: answer, content: answer,
format: format, format: format,
media: media,
packageId: packageId, packageId: packageId,
prevId: lastQuestionId !== null ? lastQuestionId : 0 prevId: lastQuestionId !== null ? lastQuestionId : 0
}); });
@ -390,7 +404,7 @@ export class KBService {
await this.sendMarkdownToWeb(step, conversationalService, html, answer); await this.sendMarkdownToWeb(step, conversationalService, html, answer);
} }
else if (channel === 'whatsapp') { else if (channel === 'whatsapp') {
await this.sendMarkdownToMobile(step, answer, conversationalService, min); await conversationalService.sendMarkdownToMobile(min, step, null, answer.content);
} }
else 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) { private async playVideo(conversationalService: IGBConversationalService, step: GBDialogStep, answer: GuaribasAnswer) {
await conversationalService.sendEvent(step, 'play', { await conversationalService.sendEvent(step, 'play', {