2018-04-21 02:59:30 -03:00
|
|
|
/*****************************************************************************\
|
|
|
|
| ( )_ _ |
|
|
|
|
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
|
|
|
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
|
|
|
|
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
|
|
|
|
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
|
|
|
| | | ( )_) | |
|
|
|
|
| (_) \___/' |
|
|
|
|
| |
|
|
|
|
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
|
|
|
|
| Licensed under the AGPL-3.0. |
|
|
|
|
| |
|
|
|
|
| According to our dual licensing model, this program can be used either |
|
|
|
|
| under the terms of the GNU Affero General Public License, version 3, |
|
|
|
|
| or under a proprietary license. |
|
|
|
|
| |
|
|
|
|
| The texts of the GNU Affero General Public License with an additional |
|
|
|
|
| permission and of our proprietary license can be found at and |
|
|
|
|
| in the LICENSE file you have received along with this program. |
|
|
|
|
| |
|
|
|
|
| This program is distributed in the hope that it will be useful, |
|
2018-09-09 18:11:41 -03:00
|
|
|
| but WITHOUT ANY WARRANTY without even the implied warranty of |
|
2018-04-21 02:59:30 -03:00
|
|
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
|
| GNU Affero General Public License for more details. |
|
|
|
|
| |
|
|
|
|
| "General Bots" is a registered trademark of Pragmatismo.io. |
|
|
|
|
| The licensing of the program under the AGPLv3 does not imply a |
|
|
|
|
| trademark license. Therefore any rights, title and interest in |
|
|
|
|
| our trademarks remain entirely with us. |
|
|
|
|
| |
|
|
|
|
\*****************************************************************************/
|
|
|
|
|
2018-09-09 18:11:41 -03:00
|
|
|
const logger = require("../../../src/logger")
|
|
|
|
const Path = require("path")
|
|
|
|
const Fs = require("fs")
|
|
|
|
const promise = require('bluebird')
|
|
|
|
const parse = promise.promisify(require('csv-parse'))
|
|
|
|
const UrlJoin = require("url-join")
|
|
|
|
const marked = require("marked")
|
|
|
|
const path = require("path")
|
|
|
|
const asyncPromise = require('async-promises')
|
|
|
|
const walkPromise = require('walk-promise')
|
|
|
|
|
|
|
|
import { GBConfigService } from './../../core.gbapp/services/GBConfigService'
|
|
|
|
import { GuaribasQuestion, GuaribasAnswer, GuaribasSubject } from "../models"
|
|
|
|
import { IGBCoreService, IGBConversationalService, IGBInstance } from "botlib"
|
|
|
|
import { AzureSearch } from "pragmatismo-io-framework"
|
|
|
|
import { GBDeployer } from "../../core.gbapp/services/GBDeployer"
|
|
|
|
import { GuaribasPackage } from "../../core.gbapp/models/GBModel"
|
2018-04-21 02:59:30 -03:00
|
|
|
|
2018-08-28 19:16:29 -03:00
|
|
|
export class KBServiceSearchResults {
|
2018-09-09 18:11:41 -03:00
|
|
|
answer: GuaribasAnswer
|
|
|
|
questionId: number
|
2018-08-28 19:16:29 -03:00
|
|
|
}
|
|
|
|
|
2018-04-21 02:59:30 -03:00
|
|
|
export class KBService {
|
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
async getAnswerById(
|
2018-04-21 02:59:30 -03:00
|
|
|
instanceId: number,
|
2018-09-09 14:39:37 -03:00
|
|
|
answerId: number
|
|
|
|
): Promise<GuaribasAnswer> {
|
|
|
|
return new Promise<GuaribasAnswer>(
|
|
|
|
(resolve, reject) => {
|
|
|
|
GuaribasAnswer.findAll({
|
|
|
|
where: {
|
|
|
|
instanceId: instanceId,
|
|
|
|
answerId: answerId
|
|
|
|
}
|
|
|
|
}).then((item: GuaribasAnswer[]) => {
|
2018-09-09 18:11:41 -03:00
|
|
|
resolve(item[0])
|
2018-09-09 14:39:37 -03:00
|
|
|
}).error((reason) => {
|
2018-09-09 18:11:41 -03:00
|
|
|
reject(reason)
|
|
|
|
})
|
|
|
|
})
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
async getAnswerByText(
|
2018-04-21 02:59:30 -03:00
|
|
|
instanceId: number,
|
2018-09-09 14:39:37 -03:00
|
|
|
text: string
|
|
|
|
): Promise<any> {
|
|
|
|
return new Promise(
|
|
|
|
(resolve, reject) => {
|
|
|
|
|
|
|
|
GuaribasQuestion.findOne({
|
2018-05-13 16:35:57 -03:00
|
|
|
where: {
|
|
|
|
instanceId: instanceId,
|
2018-09-09 14:39:37 -03:00
|
|
|
content: `%${text.trim()}%`
|
2018-05-13 16:35:57 -03:00
|
|
|
}
|
2018-09-09 14:39:37 -03:00
|
|
|
}).then((question: GuaribasQuestion) => {
|
|
|
|
if (question) {
|
|
|
|
GuaribasAnswer.findAll({
|
|
|
|
where: {
|
|
|
|
instanceId: instanceId,
|
|
|
|
answerId: question.answerId
|
|
|
|
}
|
|
|
|
}).then((answer: GuaribasAnswer[]) => {
|
2018-09-09 18:11:41 -03:00
|
|
|
resolve({ question: question, answer: answer[0] })
|
|
|
|
})
|
2018-09-09 14:39:37 -03:00
|
|
|
}
|
|
|
|
else {
|
2018-09-09 18:11:41 -03:00
|
|
|
resolve(null)
|
2018-09-09 14:39:37 -03:00
|
|
|
}
|
|
|
|
}).error((reason) => {
|
2018-09-09 18:11:41 -03:00
|
|
|
reject(reason)
|
|
|
|
})
|
|
|
|
})
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
async addAnswer(obj: GuaribasAnswer): Promise<GuaribasAnswer> {
|
|
|
|
return new Promise<GuaribasAnswer>(
|
|
|
|
(resolve, reject) => {
|
|
|
|
GuaribasAnswer.create(obj).then(item => {
|
2018-09-09 18:11:41 -03:00
|
|
|
resolve(item)
|
2018-09-09 14:39:37 -03:00
|
|
|
}).error((reason) => {
|
2018-09-09 18:11:41 -03:00
|
|
|
reject(reason)
|
|
|
|
})
|
|
|
|
})
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
2018-08-28 19:16:29 -03:00
|
|
|
async ask(
|
2018-04-21 02:59:30 -03:00
|
|
|
instance: IGBInstance,
|
|
|
|
what: string,
|
|
|
|
searchScore: number,
|
2018-08-28 19:16:29 -03:00
|
|
|
subjects: GuaribasSubject[]
|
|
|
|
): Promise<KBServiceSearchResults> {
|
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
// Builds search query.
|
2018-08-28 19:16:29 -03:00
|
|
|
|
2018-09-09 18:11:41 -03:00
|
|
|
what = what.toLowerCase()
|
|
|
|
what = what.replace("?", " ")
|
|
|
|
what = what.replace("!", " ")
|
|
|
|
what = what.replace(".", " ")
|
|
|
|
what = what.replace("/", " ")
|
|
|
|
what = what.replace("\\", " ")
|
2018-08-28 19:16:29 -03:00
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
if (subjects) {
|
|
|
|
let text = KBService.getSubjectItemsSeparatedBySpaces(
|
|
|
|
subjects
|
2018-09-09 18:11:41 -03:00
|
|
|
)
|
2018-09-09 14:39:37 -03:00
|
|
|
if (text) {
|
2018-09-09 18:11:41 -03:00
|
|
|
what = `${what} ${text}`
|
2018-05-18 11:39:17 -03:00
|
|
|
}
|
2018-09-09 14:39:37 -03:00
|
|
|
}
|
2018-09-09 18:11:41 -03:00
|
|
|
// TODO: Filter by instance. what = `${what}&$filter=instanceId eq ${instanceId}`
|
2018-09-09 14:39:37 -03:00
|
|
|
try {
|
2018-08-28 19:16:29 -03:00
|
|
|
if (instance.searchKey && GBConfigService.get("DATABASE_DIALECT") == "mssql") {
|
|
|
|
let service = new AzureSearch(
|
|
|
|
instance.searchKey,
|
|
|
|
instance.searchHost,
|
|
|
|
instance.searchIndex,
|
|
|
|
instance.searchIndexer
|
2018-09-09 18:11:41 -03:00
|
|
|
)
|
|
|
|
let results = await service.search(what)
|
2018-09-09 14:39:37 -03:00
|
|
|
if (results && results.length > 0 &&
|
|
|
|
results[0]["@search.score"] >= searchScore) {
|
|
|
|
let value = await this.getAnswerById(
|
|
|
|
instance.instanceId,
|
2018-09-09 18:11:41 -03:00
|
|
|
results[0].answerId)
|
|
|
|
return Promise.resolve({ answer: value, questionId: results[0].questionId })
|
2018-09-09 14:39:37 -03:00
|
|
|
}
|
2018-08-28 19:16:29 -03:00
|
|
|
} else {
|
2018-09-09 18:11:41 -03:00
|
|
|
let data = await this.getAnswerByText(instance.instanceId, what)
|
2018-09-09 14:39:37 -03:00
|
|
|
return Promise.resolve(
|
|
|
|
{ answer: data.answer, questionId: data.question.questionId }
|
2018-09-09 18:11:41 -03:00
|
|
|
)
|
2018-08-28 19:16:29 -03:00
|
|
|
}
|
2018-09-09 14:39:37 -03:00
|
|
|
}
|
|
|
|
catch (reason) {
|
2018-09-09 18:11:41 -03:00
|
|
|
return Promise.reject(reason)
|
2018-09-09 14:39:37 -03:00
|
|
|
}
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
2018-04-25 00:58:34 -03:00
|
|
|
getSearchSchema(indexName) {
|
|
|
|
return {
|
|
|
|
name: indexName,
|
2018-04-21 02:59:30 -03:00
|
|
|
fields: [
|
|
|
|
{
|
|
|
|
name: "questionId",
|
|
|
|
type: "Edm.String",
|
|
|
|
searchable: false,
|
|
|
|
filterable: false,
|
|
|
|
retrievable: true,
|
|
|
|
sortable: false,
|
|
|
|
facetable: false,
|
|
|
|
key: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "subject1",
|
|
|
|
type: "Edm.String",
|
|
|
|
searchable: true,
|
|
|
|
filterable: false,
|
|
|
|
retrievable: false,
|
|
|
|
sortable: false,
|
|
|
|
facetable: false,
|
|
|
|
key: false
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "subject2",
|
|
|
|
type: "Edm.String",
|
|
|
|
searchable: true,
|
|
|
|
filterable: false,
|
|
|
|
retrievable: false,
|
|
|
|
sortable: false,
|
|
|
|
facetable: false,
|
|
|
|
key: false
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "subject3",
|
|
|
|
type: "Edm.String",
|
|
|
|
searchable: true,
|
|
|
|
filterable: false,
|
|
|
|
retrievable: false,
|
|
|
|
sortable: false,
|
|
|
|
facetable: false,
|
|
|
|
key: false
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "subject4",
|
|
|
|
type: "Edm.String",
|
|
|
|
searchable: true,
|
|
|
|
filterable: false,
|
|
|
|
retrievable: false,
|
|
|
|
sortable: false,
|
|
|
|
facetable: false,
|
|
|
|
key: false
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "content",
|
|
|
|
type: "Edm.String",
|
|
|
|
searchable: true,
|
|
|
|
filterable: false,
|
|
|
|
retrievable: false,
|
|
|
|
sortable: false,
|
|
|
|
facetable: false,
|
|
|
|
key: false
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "answerId",
|
|
|
|
type: "Edm.Int32",
|
|
|
|
searchable: false,
|
|
|
|
filterable: false,
|
|
|
|
retrievable: true,
|
|
|
|
sortable: false,
|
|
|
|
facetable: false,
|
|
|
|
key: false
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "instanceId",
|
|
|
|
type: "Edm.Int32",
|
|
|
|
searchable: false,
|
|
|
|
filterable: true,
|
|
|
|
retrievable: true,
|
|
|
|
sortable: false,
|
|
|
|
facetable: false,
|
|
|
|
key: false
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "packageId",
|
|
|
|
type: "Edm.Int32",
|
|
|
|
searchable: false,
|
|
|
|
filterable: true,
|
|
|
|
retrievable: true,
|
|
|
|
sortable: false,
|
|
|
|
facetable: false,
|
|
|
|
key: false
|
|
|
|
}
|
|
|
|
],
|
|
|
|
scoringProfiles: [],
|
|
|
|
defaultScoringProfile: null,
|
|
|
|
corsOptions: null
|
2018-09-09 18:11:41 -03:00
|
|
|
}
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
static getFormattedSubjectItems(subjects: GuaribasSubject[]) {
|
2018-09-09 18:11:41 -03:00
|
|
|
if (!subjects) return ""
|
|
|
|
let out = []
|
2018-04-21 02:59:30 -03:00
|
|
|
subjects.forEach(subject => {
|
2018-09-09 18:11:41 -03:00
|
|
|
out.push(subject.title)
|
|
|
|
})
|
|
|
|
return out.join(", ")
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
static getSubjectItemsSeparatedBySpaces(subjects: GuaribasSubject[]) {
|
2018-09-09 18:11:41 -03:00
|
|
|
let out = []
|
2018-04-21 02:59:30 -03:00
|
|
|
subjects.forEach(subject => {
|
2018-09-09 18:11:41 -03:00
|
|
|
out.push(subject.title)
|
|
|
|
})
|
|
|
|
return out.join(" ")
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
async getSubjectItems(
|
2018-04-21 02:59:30 -03:00
|
|
|
instanceId: number,
|
2018-09-09 14:39:37 -03:00
|
|
|
parentId: number
|
|
|
|
): Promise<GuaribasSubject[]> {
|
|
|
|
return new Promise<GuaribasSubject[]>(
|
|
|
|
(resolve, reject) => {
|
2018-09-09 18:11:41 -03:00
|
|
|
var where = { parentSubjectId: parentId, instanceId: instanceId }
|
2018-09-09 14:39:37 -03:00
|
|
|
GuaribasSubject.findAll({
|
|
|
|
where: where
|
|
|
|
})
|
|
|
|
.then((values: GuaribasSubject[]) => {
|
2018-09-09 18:11:41 -03:00
|
|
|
resolve(values)
|
2018-09-09 14:39:37 -03:00
|
|
|
})
|
|
|
|
.error(reason => {
|
2018-09-09 18:11:41 -03:00
|
|
|
reject(reason)
|
|
|
|
})
|
|
|
|
})
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
async getFaqBySubjectArray(from: string, subjects: any): Promise<GuaribasQuestion[]> {
|
|
|
|
return new Promise<GuaribasQuestion[]>(
|
|
|
|
(resolve, reject) => {
|
2018-04-21 02:59:30 -03:00
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
let where = {
|
|
|
|
from: from
|
2018-09-09 18:11:41 -03:00
|
|
|
}
|
2018-04-21 02:59:30 -03:00
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
if (subjects) {
|
|
|
|
if (subjects[0]) {
|
2018-09-09 18:11:41 -03:00
|
|
|
where["subject1"] = subjects[0].title
|
2018-09-09 14:39:37 -03:00
|
|
|
}
|
2018-04-21 02:59:30 -03:00
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
if (subjects[1]) {
|
2018-09-09 18:11:41 -03:00
|
|
|
where["subject2"] = subjects[1].title
|
2018-09-09 14:39:37 -03:00
|
|
|
}
|
2018-04-21 02:59:30 -03:00
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
if (subjects[2]) {
|
2018-09-09 18:11:41 -03:00
|
|
|
where["subject3"] = subjects[2].title
|
2018-09-09 14:39:37 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (subjects[3]) {
|
2018-09-09 18:11:41 -03:00
|
|
|
where["subject4"] = subjects[3].title
|
2018-09-09 14:39:37 -03:00
|
|
|
}
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
2018-09-09 14:39:37 -03:00
|
|
|
GuaribasQuestion.findAll({
|
|
|
|
where: where
|
|
|
|
})
|
|
|
|
.then((items: GuaribasQuestion[]) => {
|
2018-09-09 18:11:41 -03:00
|
|
|
if (!items) items = []
|
2018-09-09 14:39:37 -03:00
|
|
|
if (items.length == 0) {
|
2018-09-09 18:11:41 -03:00
|
|
|
resolve([])
|
2018-09-09 14:39:37 -03:00
|
|
|
} else {
|
2018-09-09 18:11:41 -03:00
|
|
|
resolve(items)
|
2018-09-09 14:39:37 -03:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(reason => {
|
|
|
|
if (reason.message.indexOf("no such table: IGBInstance") != -1) {
|
2018-09-09 18:11:41 -03:00
|
|
|
resolve([])
|
2018-09-09 14:39:37 -03:00
|
|
|
} else {
|
2018-09-09 18:11:41 -03:00
|
|
|
reject(reason)
|
|
|
|
logger.info(`GuaribasServiceError: ${reason}`)
|
2018-09-09 14:39:37 -03:00
|
|
|
}
|
2018-09-09 18:11:41 -03:00
|
|
|
})
|
|
|
|
})
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
async importKbTabularFile(
|
|
|
|
filePath: string,
|
2018-04-21 02:59:30 -03:00
|
|
|
instanceId: number,
|
2018-09-09 14:39:37 -03:00
|
|
|
packageId: number
|
|
|
|
): Promise<GuaribasQuestion[]> {
|
|
|
|
|
2018-09-09 20:09:07 -03:00
|
|
|
let file = Fs.readFileSync(filePath, "UCS-2")
|
|
|
|
let opts = {
|
|
|
|
delimiter: "\t"
|
|
|
|
}
|
|
|
|
|
|
|
|
let data = await parse(file, opts);
|
|
|
|
return asyncPromise.eachSeries(data, async line => {
|
|
|
|
|
|
|
|
// Extracts values from columns in the current line.
|
|
|
|
|
|
|
|
let subjectsText = line[0]
|
|
|
|
var from = line[1]
|
|
|
|
var to = line[2]
|
|
|
|
var question = line[3]
|
|
|
|
var answer = line[4]
|
|
|
|
|
|
|
|
// Skips the first line.
|
|
|
|
|
|
|
|
if (!(subjectsText === "subjects" && from == "from")) {
|
|
|
|
let format = ".txt"
|
|
|
|
|
|
|
|
// Extracts answer from external media if any.
|
|
|
|
|
|
|
|
if (answer.indexOf(".md") > -1) {
|
|
|
|
let mediaFilename = UrlJoin(path.dirname(filePath), "..", "articles", answer)
|
|
|
|
if (Fs.existsSync(mediaFilename)) {
|
|
|
|
answer = Fs.readFileSync(mediaFilename, "utf8")
|
|
|
|
format = ".md"
|
|
|
|
} else {
|
|
|
|
logger.info(`[GBImporter] File not found: ${mediaFilename}.`)
|
|
|
|
answer =
|
|
|
|
"Por favor, contate a administração para rever esta pergunta."
|
|
|
|
}
|
2018-09-09 18:11:41 -03:00
|
|
|
}
|
2018-09-09 14:39:37 -03:00
|
|
|
|
2018-09-09 20:09:07 -03:00
|
|
|
// Processes subjects hierarchy splitting by dots.
|
|
|
|
|
|
|
|
let subjectArray = subjectsText.split(".")
|
|
|
|
let subject1: string, subject2: string, subject3: string,
|
|
|
|
subject4: string
|
|
|
|
var indexer = 0
|
|
|
|
|
|
|
|
subjectArray.forEach(element => {
|
|
|
|
if (indexer == 0) {
|
|
|
|
subject1 = subjectArray[indexer].substring(0, 63)
|
|
|
|
} else if (indexer == 1) {
|
|
|
|
subject2 = subjectArray[indexer].substring(0, 63)
|
|
|
|
} else if (indexer == 2) {
|
|
|
|
subject3 = subjectArray[indexer].substring(0, 63)
|
|
|
|
} else if (indexer == 3) {
|
|
|
|
subject4 = subjectArray[indexer].substring(0, 63)
|
|
|
|
}
|
|
|
|
indexer++
|
|
|
|
})
|
2018-09-09 18:11:41 -03:00
|
|
|
|
2018-09-09 20:09:07 -03:00
|
|
|
// Now with all the data ready, creates entities in the store.
|
|
|
|
|
|
|
|
let answer1 = await GuaribasAnswer.create({
|
|
|
|
instanceId: instanceId,
|
|
|
|
content: answer,
|
|
|
|
format: format,
|
|
|
|
packageId: packageId
|
|
|
|
});
|
|
|
|
await GuaribasQuestion.create({
|
|
|
|
from: from,
|
|
|
|
to: to,
|
|
|
|
subject1: subject1,
|
|
|
|
subject2: subject2,
|
|
|
|
subject3: subject3,
|
|
|
|
subject4: subject4,
|
|
|
|
content: question,
|
|
|
|
instanceId: instanceId,
|
|
|
|
answerId: answer1.answerId,
|
|
|
|
packageId: packageId
|
|
|
|
});
|
2018-09-10 12:09:48 -03:00
|
|
|
|
2018-09-09 20:09:07 -03:00
|
|
|
return Promise.resolve(question)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// Skips the header.
|
|
|
|
|
|
|
|
return Promise.resolve(null)
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
sendAnswer(conversationalService: IGBConversationalService,
|
|
|
|
dc: any, answer: GuaribasAnswer) {
|
2018-04-21 02:59:30 -03:00
|
|
|
|
|
|
|
if (answer.content.endsWith('.mp4')) {
|
2018-06-04 05:33:37 -03:00
|
|
|
conversationalService.sendEvent(dc, "play", {
|
2018-04-21 02:59:30 -03:00
|
|
|
playerType: "video",
|
|
|
|
data: answer.content
|
2018-09-09 18:11:41 -03:00
|
|
|
})
|
2018-09-09 14:39:37 -03:00
|
|
|
} else if (answer.content.length > 140 &&
|
|
|
|
dc.message.source != "directline") {
|
2018-06-04 05:33:37 -03:00
|
|
|
let messages = [
|
2018-04-21 02:59:30 -03:00
|
|
|
"Vou te responder na tela para melhor visualização...",
|
|
|
|
"A resposta está na tela...",
|
|
|
|
"Veja a resposta na tela..."
|
2018-09-09 18:11:41 -03:00
|
|
|
]
|
|
|
|
dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
|
|
|
|
var html = answer.content
|
2018-04-21 02:59:30 -03:00
|
|
|
if (answer.format === ".md") {
|
|
|
|
marked.setOptions({
|
|
|
|
renderer: new marked.Renderer(),
|
|
|
|
gfm: true,
|
|
|
|
tables: true,
|
|
|
|
breaks: false,
|
|
|
|
pedantic: false,
|
|
|
|
sanitize: false,
|
|
|
|
smartLists: true,
|
|
|
|
smartypants: false,
|
|
|
|
xhtml: false
|
2018-09-09 18:11:41 -03:00
|
|
|
})
|
|
|
|
html = marked(answer.content)
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
2018-09-09 18:11:41 -03:00
|
|
|
conversationalService.sendEvent(dc, "play", { playerType: "markdown", data: html })
|
2018-04-21 02:59:30 -03:00
|
|
|
} else {
|
2018-09-09 18:11:41 -03:00
|
|
|
dc.context.sendActivity(answer.content)
|
|
|
|
conversationalService.sendEvent(dc, "stop", null)
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
async importKbPackage(
|
2018-04-21 02:59:30 -03:00
|
|
|
localPath: string,
|
|
|
|
packageStorage: GuaribasPackage,
|
|
|
|
instance: IGBInstance
|
2018-09-09 14:39:37 -03:00
|
|
|
): Promise<GuaribasQuestion[]> {
|
|
|
|
|
2018-09-09 18:11:41 -03:00
|
|
|
// Imports subjects tree into database and return it.
|
2018-09-09 14:39:37 -03:00
|
|
|
|
2018-09-09 18:11:41 -03:00
|
|
|
return this.importSubjectFile(
|
|
|
|
packageStorage.packageId,
|
|
|
|
UrlJoin(localPath, "subjects.json"),
|
|
|
|
instance
|
|
|
|
).then((value: GuaribasQuestion[]) => {
|
2018-09-09 14:39:37 -03:00
|
|
|
|
2018-09-09 18:11:41 -03:00
|
|
|
// Import all .tsv files in the tabular directory.
|
2018-09-09 14:39:37 -03:00
|
|
|
|
2018-09-09 18:11:41 -03:00
|
|
|
return this.importKbTabularDirectory(
|
|
|
|
localPath,
|
|
|
|
instance,
|
|
|
|
packageStorage.packageId
|
|
|
|
)
|
|
|
|
})
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
2018-09-09 18:11:41 -03:00
|
|
|
async importKbTabularDirectory(
|
2018-04-21 02:59:30 -03:00
|
|
|
localPath: string,
|
|
|
|
instance: IGBInstance,
|
|
|
|
packageId: number
|
2018-09-09 18:11:41 -03:00
|
|
|
): Promise<any> {
|
|
|
|
|
|
|
|
let files = await walkPromise(UrlJoin(localPath, "tabular"))
|
|
|
|
|
|
|
|
return Promise.all(files.map(async file => {
|
|
|
|
if (file.name.endsWith(".tsv")) {
|
|
|
|
return this.importKbTabularFile(
|
|
|
|
UrlJoin(file.root, file.name),
|
|
|
|
instance.instanceId,
|
|
|
|
packageId);
|
|
|
|
}
|
|
|
|
}));
|
2018-09-09 14:39:37 -03:00
|
|
|
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
2018-09-09 14:39:37 -03:00
|
|
|
async importSubjectFile(
|
2018-04-21 02:59:30 -03:00
|
|
|
packageId: number,
|
|
|
|
filename: string,
|
|
|
|
instance: IGBInstance
|
2018-09-09 20:09:07 -03:00
|
|
|
): Promise<any> {
|
|
|
|
var subjects = JSON.parse(Fs.readFileSync(filename, "utf8"))
|
|
|
|
|
|
|
|
const doIt = async (subjects: GuaribasSubject[], parentSubjectId: number) => {
|
|
|
|
return asyncPromise.eachSeries(subjects, async item => {
|
|
|
|
let mediaFilename = item.id + ".png"
|
|
|
|
|
|
|
|
let value = await GuaribasSubject.create({
|
|
|
|
internalId: item.id,
|
|
|
|
parentSubjectId: parentSubjectId,
|
|
|
|
instanceId: instance.instanceId,
|
|
|
|
from: item.from,
|
|
|
|
to: item.to,
|
|
|
|
title: item.title,
|
|
|
|
description: item.description,
|
|
|
|
packageId: packageId
|
|
|
|
});
|
|
|
|
|
|
|
|
if (item.children) {
|
|
|
|
return Promise.resolve(doIt(item.children, value.subjectId))
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return Promise.resolve(item);
|
|
|
|
}
|
2018-09-09 14:39:37 -03:00
|
|
|
|
2018-09-09 18:11:41 -03:00
|
|
|
})
|
2018-09-09 20:09:07 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
return doIt(subjects.children, null)
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
undeployKbFromStorage(
|
|
|
|
instance: IGBInstance,
|
2018-09-09 14:39:37 -03:00
|
|
|
packageId: number
|
2018-04-21 02:59:30 -03:00
|
|
|
) {
|
2018-09-09 14:39:37 -03:00
|
|
|
// TODO: call reject.
|
|
|
|
return new Promise(
|
|
|
|
(resolve, reject) => {
|
|
|
|
GuaribasQuestion.destroy({
|
2018-04-21 02:59:30 -03:00
|
|
|
where: { instanceId: instance.instanceId, packageId: packageId }
|
|
|
|
}).then(value => {
|
2018-09-09 14:39:37 -03:00
|
|
|
GuaribasAnswer.destroy({
|
2018-04-21 02:59:30 -03:00
|
|
|
where: { instanceId: instance.instanceId, packageId: packageId }
|
|
|
|
}).then(value => {
|
2018-09-09 14:39:37 -03:00
|
|
|
GuaribasSubject.destroy({
|
|
|
|
where: { instanceId: instance.instanceId, packageId: packageId }
|
|
|
|
}).then(value => {
|
|
|
|
GuaribasPackage.destroy({
|
|
|
|
where: { instanceId: instance.instanceId, packageId: packageId }
|
|
|
|
}).then(value => {
|
2018-09-09 18:11:41 -03:00
|
|
|
resolve(null)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-09-09 14:39:37 -03:00
|
|
|
* Deploys a knowledge base to the storage using the .gbkb format.
|
|
|
|
*
|
|
|
|
* @param localPath Path to the .gbkb folder.
|
|
|
|
*/
|
|
|
|
async deployKb(core: IGBCoreService, deployer: GBDeployer, localPath: string) {
|
2018-09-09 18:11:41 -03:00
|
|
|
let packageType = Path.extname(localPath)
|
|
|
|
let packageName = Path.basename(localPath)
|
2018-09-09 20:09:07 -03:00
|
|
|
logger.info("[GBDeployer] Opening package: ", localPath)
|
2018-04-21 02:59:30 -03:00
|
|
|
let packageObject = JSON.parse(
|
|
|
|
Fs.readFileSync(UrlJoin(localPath, "package.json"), "utf8")
|
2018-09-09 18:11:41 -03:00
|
|
|
)
|
2018-04-21 02:59:30 -03:00
|
|
|
|
2018-09-09 18:11:41 -03:00
|
|
|
let instance = await core.loadInstance(packageObject.botId)
|
2018-09-09 14:39:37 -03:00
|
|
|
let p = await deployer.deployPackageToStorage(
|
|
|
|
instance.instanceId,
|
2018-09-09 18:11:41 -03:00
|
|
|
packageName)
|
|
|
|
await this.importKbPackage(localPath, p, instance)
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
|
|
|
}
|