fix(core.gbapp): Refactoring in MD fix in disabling auto-compiling of .gbapps.
This commit is contained in:
parent
e1ad711904
commit
ab5d507989
4 changed files with 134 additions and 94 deletions
|
@ -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 = '';
|
||||||
|
|
||||||
|
//
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -166,7 +264,7 @@ export class GBConversationalService implements IGBConversationalService {
|
||||||
|
|
||||||
const topIntent = LuisRecognizer.topIntent(nlp);
|
const topIntent = LuisRecognizer.topIntent(nlp);
|
||||||
if (topIntent !== undefined && nlpActive) {
|
if (topIntent !== undefined && nlpActive) {
|
||||||
|
|
||||||
const intent = topIntent;
|
const intent = topIntent;
|
||||||
// tslint:disable:no-unsafe-any
|
// tslint:disable:no-unsafe-any
|
||||||
const firstEntity = nlp.entities && nlp.entities.length > 0 ? nlp.entities[0].entity.toUpperCase() : undefined;
|
const firstEntity = nlp.entities && nlp.entities.length > 0 ? nlp.entities[0].entity.toUpperCase() : undefined;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 = {};
|
||||||
|
|
|
@ -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 = '';
|
|
||||||
|
|
||||||
//
|
|
||||||
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', {
|
||||||
|
|
Loading…
Add table
Reference in a new issue