KB has now all the way Promised.

This commit is contained in:
Rodrigo Rodriguez 2018-09-09 18:11:41 -03:00
parent 0fc1cddda5
commit 88c190254d
4 changed files with 200 additions and 198 deletions

View file

@ -54,7 +54,7 @@ export class AdminDialog extends IGBDialog {
let importer = new GBImporter(min.core) let importer = new GBImporter(min.core)
let deployer = new GBDeployer(min.core, importer) let deployer = new GBDeployer(min.core, importer)
dc.context.sendActivity(`Undeploying package ${packageName}...`) dc.context.sendActivity(`Undeploying package ${packageName}...`)
let data = await deployer.undeployPackageFromLocalPath( await deployer.undeployPackageFromLocalPath(
min.instance, min.instance,
UrlJoin("deploy", packageName)) UrlJoin("deploy", packageName))
dc.context.sendActivity(`Package ${packageName} undeployed...`) dc.context.sendActivity(`Package ${packageName} undeployed...`)
@ -64,17 +64,13 @@ export class AdminDialog extends IGBDialog {
text: string, text: string,
dc, dc,
deployer: GBDeployer, deployer: GBDeployer,
min: GBMinInstance, min: GBMinInstance
) { ) {
let packageName = text.split(" ")[1] let packageName = text.split(" ")[1]
dc.context.sendActivity(`Deploying package ${packageName}... (It may take a few seconds)`) await dc.context.sendActivity(`Deploying package ${packageName}... (It may take a few seconds)`)
// TODO: Find packages in all possible locations.
let additionalPath = GBConfigService.get("ADDITIONAL_DEPLOY_PATH") let additionalPath = GBConfigService.get("ADDITIONAL_DEPLOY_PATH")
await deployer.deployPackageFromLocalPath(UrlJoin(additionalPath, packageName))
let data = deployer.deployPackageFromLocalPath( await dc.context.sendActivity(`Package ${packageName} deployed... Please run rebuildIndex command.`)
UrlJoin(additionalPath, packageName))
dc.context.sendActivity(`Package ${packageName} deployed... Please run rebuildIndex command.`)
} }
static async rebuildIndexCommand(min: GBMinInstance, dc) { static async rebuildIndexCommand(min: GBMinInstance, dc) {
@ -91,8 +87,6 @@ export class AdminDialog extends IGBDialog {
await dc.context.sendActivity("Index rebuilt.") await dc.context.sendActivity("Index rebuilt.")
} }
/** /**
* Setup dialogs flows and define services call. * Setup dialogs flows and define services call.
* *
@ -108,6 +102,16 @@ export class AdminDialog extends IGBDialog {
min.dialogs.add("/admin", [ min.dialogs.add("/admin", [
async (dc) => {
await dc.context.sendActivity(`Deploying package ... (It may take a few seconds)`)
await AdminDialog.deployPackageCommand("deployPackage ProjectOnline.gbkb", dc, deployer, min)
await dc.endAll();
}]);
min.dialogs.add("/admin1", [
async (dc, args) => { async (dc, args) => {
const prompt = "Please, authenticate:" const prompt = "Please, authenticate:"
await dc.prompt('textPrompt', prompt) await dc.prompt('textPrompt', prompt)

View file

@ -51,12 +51,12 @@ export class GBConversationalService implements IGBConversationalService {
this.coreService = coreService; this.coreService = coreService;
} }
sendEvent(dc: any, name: string, value: any) { async sendEvent(dc: any, name: string, value: any) {
const msg = MessageFactory.text(''); const msg = MessageFactory.text('');
msg.value = value; msg.value = value;
msg.type = "event"; msg.type = "event";
msg.name = name; msg.name = name;
dc.context.sendActivity(msg); return dc.context.sendActivity(msg);
} }
async runNLP( async runNLP(

View file

@ -171,7 +171,7 @@ export class GBMinService {
); );
} else { } else {
let error = `Instance not found: ${botId}.`; let error = `Instance not found: ${botId}.`;
res.send(error); res.sendStatus(error);
logger.error(error); logger.error(error);
} }
})() })()
@ -231,16 +231,16 @@ export class GBMinService {
min.dialogs.add('textPrompt', new TextPrompt()); min.dialogs.add('textPrompt', new TextPrompt());
server.post(`/api/messages/${instance.botId}`, (req, res) => { server.post(`/api/messages/${instance.botId}`, async (req, res) => {
adapter.processActivity(req, res, async (context) => { return adapter.processActivity(req, res, async (context) => {
const state = conversationState.get(context); const state = conversationState.get(context);
const dc = min.dialogs.createContext(context, state); const dc = min.dialogs.createContext(context, state);
const user = min.userState.get(dc.context); const user = min.userState.get(dc.context);
if (!user.loaded) { if (!user.loaded) {
min.conversationalService.sendEvent( await min.conversationalService.sendEvent(
dc, dc,
"loadInstance", "loadInstance",
{ {
@ -281,29 +281,29 @@ export class GBMinService {
// Check to see if anyone replied. If not then start echo dialog // Check to see if anyone replied. If not then start echo dialog
if (context.activity.text === "admin") { if (context.activity.text === "admin") {
dc.begin("/admin"); await dc.begin("/admin");
} else { } else {
await dc.continue(); await dc.continue();
} }
} else if (context.activity.type === 'event') { } else if (context.activity.type === 'event') {
if (context.activity.name === "whoAmI") { if (context.activity.name === "whoAmI") {
dc.begin("/whoAmI"); await dc.begin("/whoAmI");
} else if (context.activity.name === "showSubjects") { } else if (context.activity.name === "showSubjects") {
dc.begin("/menu"); await dc.begin("/menu");
} else if (context.activity.name === "giveFeedback") { } else if (context.activity.name === "giveFeedback") {
dc.begin("/feedback", { await dc.begin("/feedback", {
fromMenu: true fromMenu: true
}); });
} else if (context.activity.name === "showFAQ") { } else if (context.activity.name === "showFAQ") {
dc.begin("/faq"); await dc.begin("/faq");
} else if (context.activity.name === "ask") { } else if (context.activity.name === "ask") {
dc.begin("/answer", { dc.begin("/answer", {
// TODO: query: context.activity.data, // TODO: query: context.activity.data,
fromFaq: true fromFaq: true
}); });
} else if (context.activity.name === "quality") { } else if (context.activity.name === "quality") {
dc.begin("/quality", { await dc.begin("/quality", {
// TODO: score: context.activity.data // TODO: score: context.activity.data
}); });
} else { } else {
@ -460,7 +460,7 @@ export class GBMinService {
"/kb/" + filenameOnly + "/subjects", "/kb/" + filenameOnly + "/subjects",
express.static(UrlJoin(filename, "subjects")) express.static(UrlJoin(filename, "subjects"))
); );
logger.info(`KB (.gbkb) assets acessible at: ${"/kb/" + filenameOnly}.`); logger.info(`KB (.gbkb) assets accessible at: ${"/kb/" + filenameOnly}.`);
} }
else if (Path.extname(filename) === ".gbui" || filename.endsWith(".git")) { else if (Path.extname(filename) === ".gbui" || filename.endsWith(".git")) {

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,27 +30,27 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
const logger = require("../../../src/logger"); const logger = require("../../../src/logger")
const Path = require("path"); const Path = require("path")
const Fs = require("fs"); const Fs = require("fs")
const promise = require('bluebird'); const promise = require('bluebird')
const parse = promise.promisify(require('csv-parse')); const parse = promise.promisify(require('csv-parse'))
const 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')
const walkPromise = require('walk-promise'); const walkPromise = require('walk-promise')
import { GBConfigService } from './../../core.gbapp/services/GBConfigService'; import { GBConfigService } from './../../core.gbapp/services/GBConfigService'
import { GuaribasQuestion, GuaribasAnswer, GuaribasSubject } from "../models"; import { GuaribasQuestion, GuaribasAnswer, GuaribasSubject } from "../models"
import { IGBCoreService, IGBConversationalService, IGBInstance } from "botlib"; import { IGBCoreService, IGBConversationalService, IGBInstance } from "botlib"
import { AzureSearch } from "pragmatismo-io-framework"; import { AzureSearch } from "pragmatismo-io-framework"
import { GBDeployer } from "../../core.gbapp/services/GBDeployer"; import { GBDeployer } from "../../core.gbapp/services/GBDeployer"
import { GuaribasPackage } from "../../core.gbapp/models/GBModel"; import { GuaribasPackage } from "../../core.gbapp/models/GBModel"
export class KBServiceSearchResults { export class KBServiceSearchResults {
answer: GuaribasAnswer; answer: GuaribasAnswer
questionId: number; questionId: number
} }
export class KBService { export class KBService {
@ -67,11 +67,11 @@ export class KBService {
answerId: answerId answerId: answerId
} }
}).then((item: GuaribasAnswer[]) => { }).then((item: GuaribasAnswer[]) => {
resolve(item[0]); resolve(item[0])
}).error((reason) => { }).error((reason) => {
reject(reason); reject(reason)
}); })
}); })
} }
async getAnswerByText( async getAnswerByText(
@ -94,27 +94,27 @@ export class KBService {
answerId: question.answerId answerId: question.answerId
} }
}).then((answer: GuaribasAnswer[]) => { }).then((answer: GuaribasAnswer[]) => {
resolve({ question: question, answer: answer[0] }); resolve({ question: question, answer: answer[0] })
}); })
} }
else { else {
resolve(null); resolve(null)
} }
}).error((reason) => { }).error((reason) => {
reject(reason); reject(reason)
}); })
}); })
} }
async addAnswer(obj: GuaribasAnswer): Promise<GuaribasAnswer> { async addAnswer(obj: GuaribasAnswer): Promise<GuaribasAnswer> {
return new Promise<GuaribasAnswer>( return new Promise<GuaribasAnswer>(
(resolve, reject) => { (resolve, reject) => {
GuaribasAnswer.create(obj).then(item => { GuaribasAnswer.create(obj).then(item => {
resolve(item); resolve(item)
}).error((reason) => { }).error((reason) => {
reject(reason); reject(reason)
}); })
}); })
} }
async ask( async ask(
@ -126,22 +126,22 @@ export class KBService {
// Builds search query. // Builds search query.
what = what.toLowerCase(); what = what.toLowerCase()
what = what.replace("?", " "); what = what.replace("?", " ")
what = what.replace("!", " "); what = what.replace("!", " ")
what = what.replace(".", " "); what = what.replace(".", " ")
what = what.replace("/", " "); what = what.replace("/", " ")
what = what.replace("\\", " "); what = what.replace("\\", " ")
if (subjects) { if (subjects) {
let text = KBService.getSubjectItemsSeparatedBySpaces( let text = KBService.getSubjectItemsSeparatedBySpaces(
subjects subjects
); )
if (text) { if (text) {
what = `${what} ${text}`; what = `${what} ${text}`
} }
} }
// TODO: Filter by instance. what = `${what}&$filter=instanceId eq ${instanceId}`; // TODO: Filter by instance. what = `${what}&$filter=instanceId eq ${instanceId}`
try { try {
if (instance.searchKey && GBConfigService.get("DATABASE_DIALECT") == "mssql") { if (instance.searchKey && GBConfigService.get("DATABASE_DIALECT") == "mssql") {
let service = new AzureSearch( let service = new AzureSearch(
@ -149,24 +149,24 @@ export class KBService {
instance.searchHost, instance.searchHost,
instance.searchIndex, instance.searchIndex,
instance.searchIndexer instance.searchIndexer
); )
let results = await service.search(what); let results = await service.search(what)
if (results && results.length > 0 && if (results && results.length > 0 &&
results[0]["@search.score"] >= searchScore) { results[0]["@search.score"] >= searchScore) {
let value = await this.getAnswerById( let value = await this.getAnswerById(
instance.instanceId, instance.instanceId,
results[0].answerId); results[0].answerId)
return Promise.resolve({ answer: value, questionId: results[0].questionId }); return Promise.resolve({ answer: value, questionId: results[0].questionId })
} }
} else { } else {
let data = await this.getAnswerByText(instance.instanceId, what); let data = await this.getAnswerByText(instance.instanceId, what)
return Promise.resolve( return Promise.resolve(
{ answer: data.answer, questionId: data.question.questionId } { answer: data.answer, questionId: data.question.questionId }
); )
} }
} }
catch (reason) { catch (reason) {
return Promise.reject(reason); return Promise.reject(reason)
} }
} }
@ -268,24 +268,24 @@ export class KBService {
scoringProfiles: [], scoringProfiles: [],
defaultScoringProfile: null, defaultScoringProfile: null,
corsOptions: null corsOptions: null
}; }
} }
static getFormattedSubjectItems(subjects: GuaribasSubject[]) { static getFormattedSubjectItems(subjects: GuaribasSubject[]) {
if (!subjects) return ""; if (!subjects) return ""
let out = []; let out = []
subjects.forEach(subject => { subjects.forEach(subject => {
out.push(subject.title); out.push(subject.title)
}); })
return out.join(", "); return out.join(", ")
} }
static getSubjectItemsSeparatedBySpaces(subjects: GuaribasSubject[]) { static getSubjectItemsSeparatedBySpaces(subjects: GuaribasSubject[]) {
let out = []; let out = []
subjects.forEach(subject => { subjects.forEach(subject => {
out.push(subject.title); out.push(subject.title)
}); })
return out.join(" "); return out.join(" ")
} }
async getSubjectItems( async getSubjectItems(
@ -294,17 +294,17 @@ export class KBService {
): Promise<GuaribasSubject[]> { ): Promise<GuaribasSubject[]> {
return new Promise<GuaribasSubject[]>( return new Promise<GuaribasSubject[]>(
(resolve, reject) => { (resolve, reject) => {
var where = { parentSubjectId: parentId, instanceId: instanceId }; var where = { parentSubjectId: parentId, instanceId: instanceId }
GuaribasSubject.findAll({ GuaribasSubject.findAll({
where: where where: where
}) })
.then((values: GuaribasSubject[]) => { .then((values: GuaribasSubject[]) => {
resolve(values); resolve(values)
}) })
.error(reason => { .error(reason => {
reject(reason); reject(reason)
}); })
}); })
} }
async getFaqBySubjectArray(from: string, subjects: any): Promise<GuaribasQuestion[]> { async getFaqBySubjectArray(from: string, subjects: any): Promise<GuaribasQuestion[]> {
@ -313,45 +313,45 @@ export class KBService {
let where = { let where = {
from: from from: from
}; }
if (subjects) { if (subjects) {
if (subjects[0]) { if (subjects[0]) {
where["subject1"] = subjects[0].title; where["subject1"] = subjects[0].title
} }
if (subjects[1]) { if (subjects[1]) {
where["subject2"] = subjects[1].title; where["subject2"] = subjects[1].title
} }
if (subjects[2]) { if (subjects[2]) {
where["subject3"] = subjects[2].title; where["subject3"] = subjects[2].title
} }
if (subjects[3]) { if (subjects[3]) {
where["subject4"] = subjects[3].title; where["subject4"] = subjects[3].title
} }
} }
GuaribasQuestion.findAll({ GuaribasQuestion.findAll({
where: where where: where
}) })
.then((items: GuaribasQuestion[]) => { .then((items: GuaribasQuestion[]) => {
if (!items) items = []; if (!items) items = []
if (items.length == 0) { if (items.length == 0) {
resolve([]); resolve([])
} else { } else {
resolve(items); resolve(items)
} }
}) })
.catch(reason => { .catch(reason => {
if (reason.message.indexOf("no such table: IGBInstance") != -1) { if (reason.message.indexOf("no such table: IGBInstance") != -1) {
resolve([]); resolve([])
} else { } else {
reject(reason); reject(reason)
logger.info(`GuaribasServiceError: ${reason}`); logger.info(`GuaribasServiceError: ${reason}`)
} }
}); })
}); })
} }
async importKbTabularFile( async importKbTabularFile(
@ -362,61 +362,61 @@ export class KBService {
return new Promise<GuaribasQuestion[]>( return new Promise<GuaribasQuestion[]>(
(resolve, reject) => { (resolve, reject) => {
let file = Fs.readFileSync(filePath, "UCS-2"); let file = Fs.readFileSync(filePath, "UCS-2")
let opts = { let opts = {
delimiter: "\t" delimiter: "\t"
}; }
var parser = parse(file, opts).then((data) => { parse(file, opts).then((data) => {
asyncPromise.eachSeries(data, (line) => { return asyncPromise.eachSeries(data, line => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Extracts values from columns in the current line. // Extracts values from columns in the current line.
let subjectsText = line[0]; let subjectsText = line[0]
var from = line[1]; var from = line[1]
var to = line[2]; var to = line[2]
var question = line[3]; var question = line[3]
var answer = line[4]; var answer = line[4]
// Skips the first line. // Skips the first line.
if (!(subjectsText === "subjects" && from == "from")) { if (!(subjectsText === "subjects" && from == "from")) {
let format = ".txt"; let format = ".txt"
// Extracts answer from external media if any. // Extracts answer from external media if any.
if (answer.indexOf(".md") > -1) { if (answer.indexOf(".md") > -1) {
let mediaFilename = UrlJoin(path.dirname(filePath), "..", "articles", answer); let 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"
} else { } else {
logger.info("[GBImporter] File not found: ", mediaFilename); logger.info(`[GBImporter] File not found: ${mediaFilename}.`)
answer = answer =
"Por favor, contate a administração para rever esta pergunta."; "Por favor, contate a administração para rever esta pergunta."
} }
} }
// Processes subjects hierarchy splitting by dots. // Processes subjects hierarchy splitting by dots.
let subjectArray = subjectsText.split("."); let subjectArray = subjectsText.split(".")
let subject1: string, subject2: string, subject3: string, let subject1: string, subject2: string, subject3: string,
subject4: string; subject4: string
var indexer = 0; var indexer = 0
subjectArray.forEach(element => { subjectArray.forEach(element => {
if (indexer == 0) { if (indexer == 0) {
subject1 = subjectArray[indexer].substring(0, 63); subject1 = subjectArray[indexer].substring(0, 63)
} else if (indexer == 1) { } else if (indexer == 1) {
subject2 = subjectArray[indexer].substring(0, 63); subject2 = subjectArray[indexer].substring(0, 63)
} else if (indexer == 2) { } else if (indexer == 2) {
subject3 = subjectArray[indexer].substring(0, 63); subject3 = subjectArray[indexer].substring(0, 63)
} else if (indexer == 3) { } else if (indexer == 3) {
subject4 = subjectArray[indexer].substring(0, 63); subject4 = subjectArray[indexer].substring(0, 63)
} }
indexer++; indexer++
}); })
// Now with all the data ready, creates entities in the store. // Now with all the data ready, creates entities in the store.
@ -426,7 +426,7 @@ export class KBService {
format: format, format: format,
packageId: packageId packageId: packageId
}).then((answer: GuaribasAnswer) => { }).then((answer: GuaribasAnswer) => {
GuaribasQuestion.create({ return GuaribasQuestion.create({
from: from, from: from,
to: to, to: to,
subject1: subject1, subject1: subject1,
@ -438,17 +438,21 @@ export class KBService {
answerId: answer.answerId, answerId: answer.answerId,
packageId: packageId packageId: packageId
}).then((question: GuaribasQuestion) => { }).then((question: GuaribasQuestion) => {
resolve(question); resolve(question)
}).error(reason => reject(reason)); }).error(reason => reject(reason))
}).error(reason => reject(reason));; }).error(reason => reject(reason))
} else { } else {
logger.warn("[GBImporter] Missing header in file: ", filePath); let msg = `[GBImporter] Missing header in file: ${filePath}`;
logger.info(msg)
resolve(null)
} }
}); })
}); })
}).error(reason => reject(reason)); }).error(reason => reject(reason))
});
resolve(null)
})
} }
sendAnswer(conversationalService: IGBConversationalService, sendAnswer(conversationalService: IGBConversationalService,
@ -458,16 +462,16 @@ export class KBService {
conversationalService.sendEvent(dc, "play", { conversationalService.sendEvent(dc, "play", {
playerType: "video", playerType: "video",
data: answer.content data: answer.content
}); })
} else if (answer.content.length > 140 && } else if (answer.content.length > 140 &&
dc.message.source != "directline") { dc.message.source != "directline") {
let messages = [ let messages = [
"Vou te responder na tela para melhor visualização...", "Vou te responder na tela para melhor visualização...",
"A resposta está na tela...", "A resposta está na tela...",
"Veja a resposta na tela..." "Veja a resposta na tela..."
]; ]
dc.context.sendActivity(messages[0]); // TODO: Handle rnd. dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
var html = answer.content; var html = answer.content
if (answer.format === ".md") { if (answer.format === ".md") {
marked.setOptions({ marked.setOptions({
renderer: new marked.Renderer(), renderer: new marked.Renderer(),
@ -479,13 +483,13 @@ export class KBService {
smartLists: true, smartLists: true,
smartypants: false, smartypants: false,
xhtml: false xhtml: false
}); })
html = marked(answer.content); html = marked(answer.content)
} }
conversationalService.sendEvent(dc, "play", { playerType: "markdown", data: html }); conversationalService.sendEvent(dc, "play", { playerType: "markdown", data: html })
} else { } else {
dc.context.sendActivity(answer.content); dc.context.sendActivity(answer.content)
conversationalService.sendEvent(dc, "stop", null); conversationalService.sendEvent(dc, "stop", null)
} }
} }
@ -494,12 +498,10 @@ export class KBService {
packageStorage: GuaribasPackage, packageStorage: GuaribasPackage,
instance: IGBInstance instance: IGBInstance
): Promise<GuaribasQuestion[]> { ): Promise<GuaribasQuestion[]> {
return new Promise<GuaribasQuestion[]>(
(resolve, reject) => {
// Imports subjects tree into database and return it. // Imports subjects tree into database and return it.
this.importSubjectFile( return this.importSubjectFile(
packageStorage.packageId, packageStorage.packageId,
UrlJoin(localPath, "subjects.json"), UrlJoin(localPath, "subjects.json"),
instance instance
@ -507,34 +509,31 @@ export class KBService {
// Import all .tsv files in the tabular directory. // Import all .tsv files in the tabular directory.
this.importKbTabularDirectory( return this.importKbTabularDirectory(
localPath, localPath,
instance, instance,
packageStorage.packageId packageStorage.packageId
); )
}); })
});
} }
importKbTabularDirectory( async importKbTabularDirectory(
localPath: string, localPath: string,
instance: IGBInstance, instance: IGBInstance,
packageId: number packageId: number
): Promise<GuaribasQuestion[]> { ): Promise<any> {
return new Promise(
(resolve, reject) => {
walkPromise(UrlJoin(localPath, "tabular")).then((files) => { let files = await walkPromise(UrlJoin(localPath, "tabular"))
files.array.forEach(file => {
if (file.endsWith(".tsv")) { return Promise.all(files.map(async file => {
this.importKbTabularFile( if (file.name.endsWith(".tsv")) {
file, return this.importKbTabularFile(
UrlJoin(file.root, file.name),
instance.instanceId, instance.instanceId,
packageId); packageId);
} }
}); }));
});
});
} }
async importSubjectFile( async importSubjectFile(
@ -545,12 +544,12 @@ export class KBService {
return new Promise<GuaribasQuestion[]>( return new Promise<GuaribasQuestion[]>(
(resolve, reject) => { (resolve, reject) => {
var subjects = JSON.parse(Fs.readFileSync(filename, "utf8")); var subjects = JSON.parse(Fs.readFileSync(filename, "utf8"))
const doIt = (subjects: GuaribasSubject[], parentSubjectId: number) => const doIt = (subjects: GuaribasSubject[], parentSubjectId: number) =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
asyncPromise.eachSeries(subjects, (item, callback) => { asyncPromise.eachSeries(subjects, item => {
let mediaFilename = item.id + ".png"; let mediaFilename = item.id + ".png"
GuaribasSubject.create({ GuaribasSubject.create({
internalId: item.id, internalId: item.id,
parentSubjectId: parentSubjectId, parentSubjectId: parentSubjectId,
@ -562,16 +561,15 @@ export class KBService {
packageId: packageId packageId: packageId
}).then((value: any) => { }).then((value: any) => {
if (item.children) { if (item.children) {
doIt(item.children, value.subjectId); doIt(item.children, value.subjectId)
} }
}); })
callback(); })
}); })
});
doIt(subjects.children, null); doIt(subjects.children, null)
resolve() resolve()
}); })
} }
undeployKbFromStorage( undeployKbFromStorage(
@ -593,12 +591,12 @@ export class KBService {
GuaribasPackage.destroy({ GuaribasPackage.destroy({
where: { instanceId: instance.instanceId, packageId: packageId } where: { instanceId: instance.instanceId, packageId: packageId }
}).then(value => { }).then(value => {
resolve(null); resolve(null)
}); })
}); })
}); })
}); })
}); })
} }
/** /**
@ -607,17 +605,17 @@ export class KBService {
* @param localPath Path to the .gbkb folder. * @param localPath Path to the .gbkb folder.
*/ */
async deployKb(core: IGBCoreService, deployer: GBDeployer, localPath: string) { async deployKb(core: IGBCoreService, deployer: GBDeployer, localPath: string) {
let packageType = Path.extname(localPath); let packageType = Path.extname(localPath)
let packageName = Path.basename(localPath); let packageName = Path.basename(localPath)
logger.info("[GBDeployer] Opening package: ", packageName); logger.info("[GBDeployer] Opening package: ", packageName)
let packageObject = JSON.parse( let packageObject = JSON.parse(
Fs.readFileSync(UrlJoin(localPath, "package.json"), "utf8") Fs.readFileSync(UrlJoin(localPath, "package.json"), "utf8")
); )
let instance = await core.loadInstance(packageObject.botId); let instance = await core.loadInstance(packageObject.botId)
let p = await deployer.deployPackageToStorage( let p = await deployer.deployPackageToStorage(
instance.instanceId, instance.instanceId,
packageName); packageName)
await this.importKbPackage(localPath, p, instance); await this.importKbPackage(localPath, p, instance)
} }
} }