General Bots in now almost globalized.

This commit is contained in:
Rodrigo Rodriguez 2018-09-14 12:56:54 -03:00
parent c573e33754
commit 7a33f6942e
19 changed files with 359 additions and 371 deletions

View file

@ -41,6 +41,7 @@ import { GBImporter } from '../../core.gbapp/services/GBImporter'
import { GBConfigService } from '../../core.gbapp/services/GBConfigService'
import { KBService } from './../../kb.gbapp/services/KBService'
import { BotAdapter } from "botbuilder"
import {messages} from "./Strings"
import { reject } from "async"
/**

View file

@ -30,12 +30,12 @@
| |
\*****************************************************************************/
"use strict"
"use strict";
import { IGBDialog } from "botlib"
import { GBMinInstance } from "botlib"
import { BotAdapter } from "botbuilder"
const messages = require("./strings.json").messages
import { IGBDialog } from "botlib";
import { GBMinInstance } from "botlib";
import { BotAdapter } from "botbuilder";
import { Messages } from "../strings";
export class WelcomeDialog extends IGBDialog {
/**
@ -45,31 +45,33 @@ export class WelcomeDialog extends IGBDialog {
* @param min The minimal bot instance data.
*/
static setup(bot: BotAdapter, min: GBMinInstance) {
min.dialogs.add("/", [
async (dc, args) => {
const user = min.userState.get(dc.context)
let loc = dc.context.activity.locale;
const user = min.userState.get(dc.context);
const locale = dc.context.activity.locale;
if (!user.once) {
user.once = true
var a = new Date()
const date = a.getHours()
var msg =
date < 12 ? messages[loc].good_morning : date < 18 ?
messages[loc].good_evening : messages[loc].good_night
user.once = true;
var a = new Date();
const date = a.getHours();
var msg = 4;
date < 12
? Messages[locale].good_morning
: date < 18
? Messages[locale].good_evening
: Messages[locale].good_night;
let messages1 = [`Oi, ${msg}.`, `Oi!`, `Olá, ${msg}`, `Olá!`]
await dc.context.sendActivity(messages1[0])
await dc.context.sendActivity(Messages[locale].hi(msg));
if (dc.context.activity && dc.context.activity.type == "message" &&
dc.context.activity.text != "") {
await dc.replace("/answer", { query: dc.context.activity.text })
if (
dc.context.activity &&
dc.context.activity.type == "message" &&
dc.context.activity.text != ""
) {
await dc.replace("/answer", { query: dc.context.activity.text });
}
}
}
])
]);
}
}

View file

@ -30,15 +30,14 @@
| |
\*****************************************************************************/
"use strict"
import { IGBDialog } from "botlib"
import { GBMinInstance } from "botlib"
import { BotAdapter } from "botbuilder"
"use strict";
import { IGBDialog } from "botlib";
import { GBMinInstance } from "botlib";
import { BotAdapter } from "botbuilder";
import { Messages } from "../strings";
export class WhoAmIDialog extends IGBDialog {
/**
* Setup dialogs flows and define services call.
*
@ -46,21 +45,21 @@ export class WhoAmIDialog extends IGBDialog {
* @param min The minimal bot instance data.
*/
static setup(bot: BotAdapter, min: GBMinInstance) {
min.dialogs.add("/whoAmI", [
async (dc, args) => {
await dc.context.sendActivity(`${min.instance.description}`)
async dc => {
let locale = dc.context.activity.locale;
await dc.context.sendActivity(`${min.instance.description}`);
if (min.instance.whoAmIVideo) {
await dc.context.sendActivity("show_video")
await dc.context.sendActivity(Messages[locale].show_video);
await min.conversationalService.sendEvent(dc, "play", {
playerType: "video",
data: min.instance.whoAmIVideo.trim()
})
});
}
await dc.replace('/ask', { isReturning: true })
await dc.replace("/ask", { isReturning: true });
}
])
]);
}
}

View file

@ -1,16 +0,0 @@
{
"messages": {
"en-US": {
"show_video": "I will show you a video, please wait...",
"good_morning": "good morning",
"good_evening": "good evening",
"good_night": "good night"
},
"pt-BR": {
"show_video": "Vou te mostrar um vídeo. Por favor, aguarde...",
"good_morning": "bom dia",
"good_evening": "boa tarde",
"good_night": "boa noite"
}
}
}

View file

@ -30,77 +30,73 @@
| |
\*****************************************************************************/
"use strict"
"use strict";
const logger = require("../../../src/logger")
const logger = require("../../../src/logger");
import { GBCoreService } from "./GBCoreService"
import { IGBConversationalService } from "botlib"
import { GBMinInstance } from "botlib"
import { LuisRecognizer } from "botbuilder-ai"
import { MessageFactory } from "botbuilder"
import { GBCoreService } from "./GBCoreService";
import { IGBConversationalService } from "botlib";
import { GBMinInstance } from "botlib";
import { LuisRecognizer } from "botbuilder-ai";
import { MessageFactory } from "botbuilder";
export interface LanguagePickerSettings {
defaultLocale?: string
supportedLocales?: string[]
defaultLocale?: string;
supportedLocales?: string[];
}
export class GBConversationalService implements IGBConversationalService {
coreService: GBCoreService
coreService: GBCoreService;
constructor(coreService: GBCoreService) {
this.coreService = coreService
this.coreService = coreService;
}
getCurrentLanguage(dc: any) {
return dc.context.activity.locale
return dc.context.activity.locale;
}
async sendEvent(dc: any, name: string, value: any): Promise<any> {
const msg = MessageFactory.text("")
msg.value = value
msg.type = "event"
msg.name = name
return dc.context.sendActivity(msg)
const msg = MessageFactory.text("");
msg.value = value;
msg.type = "event";
msg.name = name;
return dc.context.sendActivity(msg);
}
async runNLP(dc: any, min: GBMinInstance, text: string): Promise<any> {
async routeNLP(dc: any, min: GBMinInstance, text: string): Promise<boolean> {
// Invokes LUIS.
const model = new LuisRecognizer({
appId: min.instance.nlpAppId,
subscriptionKey: min.instance.nlpSubscriptionKey,
serviceEndpoint: min.instance.nlpServerUrl
})
let res = await model.recognize(dc.context)
});
let res = await model.recognize(dc.context);
// Resolves intents returned from LUIS.
let topIntent = LuisRecognizer.topIntent(res)
let topIntent = LuisRecognizer.topIntent(res);
if (topIntent) {
var intent = topIntent
var intent = topIntent;
var entity =
res.entities && res.entities.length > 0
? res.entities[0].entity.toUpperCase()
: null
logger.info("luis: intent: [" + intent + "] entity: [" + entity + "]")
: null;
logger.info("NLP called:" + intent + ", " + entity);
try {
await dc.replace("/" + intent)
await dc.replace("/" + intent, res.entities);
} catch (error) {
logger.info("error: intent: [" + intent + "] error: [" + error + "]")
await dc.context.sendActivity(
"Desculpe-me, não encontrei nada a respeito..."
)
await dc.replace("/ask", { isReturning: true })
let msg = `Error running NLP (${intent}): ${error}`;
logger.info(msg);
return Promise.reject(msg);
}
return Promise.resolve({ intent, entities: res.entities })
return Promise.resolve(true);
} else {
await dc.context.sendActivity("Lamento, não achei nada a respeito...")
await dc.replace("/ask", { isReturning: true })
return Promise.resolve(null)
return Promise.resolve(false);
}
}
}

View file

@ -182,7 +182,7 @@ export class GBMinService {
uiUrl,
express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, "build"))
)
logger.info(`Bot UI ${uiPackage} acessible at: ${uiUrl}.`)
logger.info(`Bot UI ${uiPackage} accessible at: ${uiUrl}.`)
// Setups handlers.
// send: function (context.activity, next) {

View file

@ -0,0 +1,16 @@
export const Messages = {
"en-US": {
show_video: "I will show you a video, please wait...",
good_morning: "good morning",
good_evening: "good evening",
good_night: "good night",
hi: (msg ) => `Hello, ${msg}.`
},
"pt-BR": {
show_video: "Vou te mostrar um vídeo. Por favor, aguarde...",
good_morning: "bom dia",
good_evening: "boa tarde",
good_night: "boa noite",
hi: (msg ) => `Oi, ${msg}.`
}
};

View file

@ -1,5 +0,0 @@
export const messages =
{
show_video: "I will show you a video, please wait..."
}
;

View file

@ -1,4 +0,0 @@
export const messages =
{
show_video: "Vou te mostrar um vídeo. Por favor, aguarde..."
}

View file

@ -30,13 +30,14 @@
| |
\*****************************************************************************/
"use strict"
"use strict";
import { CSService } from "../services/CSService"
import { AzureText } from "pragmatismo-io-framework"
import { GBMinInstance } from "botlib"
import { IGBDialog } from "botlib"
import { BotAdapter } from "botbuilder"
import { CSService } from "../services/CSService";
import { AzureText } from "pragmatismo-io-framework";
import { GBMinInstance } from "botlib";
import { IGBDialog } from "botlib";
import { BotAdapter } from "botbuilder";
import { Messages } from "../strings";
export class FeedbackDialog extends IGBDialog {
/**
@ -46,70 +47,55 @@ export class FeedbackDialog extends IGBDialog {
* @param min The minimal bot instance data.
*/
static setup(bot: BotAdapter, min: GBMinInstance) {
const service = new CSService()
const service = new CSService();
min.dialogs.add("/feedbackNumber", [
async dc => {
let messages = [
"O que achou do meu atendimento, de 1 a 5?",
"Qual a nota do meu atendimento?",
"Como define meu atendimento numa escala de 1 a 5?"
]
await dc.prompt("choicePrompt", messages[0], [
let locale = dc.context.activity.locale;
await dc.prompt("choicePrompt", Messages[locale].what_about_me, [
"1",
"2",
"3",
"4",
"5"
])
]);
},
async (dc, value) => {
let rate = value.entity
const user = min.userState.get(dc.context)
await service.updateConversationRate(user.conversation, rate)
let messages = ["Obrigado!", "Obrigado por responder."]
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
let locale = dc.context.activity.locale;
let rate = value.entity;
const user = min.userState.get(dc.context);
await service.updateConversationRate(user.conversation, rate);
await dc.context.sendActivity(Messages[locale].thanks);
}
])
]);
min.dialogs.add("/feedback", [
async (dc, args) => {
let locale = dc.context.activity.locale;
if (args && args.fromMenu) {
let messages = [
"Sugestões melhoram muito minha qualidade...",
"Obrigado pela sua iniciativa de sugestão."
]
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
await dc.context.sendActivity(Messages[locale].about_suggestions);
}
let messages = [
"O que achou do meu atendimento?",
"Como foi meu atendimento?",
"Gostaria de dizer algo sobre meu atendimento?"
]
await dc.prompt("textPrompt", messages[0])
await dc.prompt("textPrompt", Messages[locale].what_about_service);
},
async (dc, value) => {
let locale = dc.context.activity.locale;
let rate = await AzureText.getSentiment(
min.instance.textAnalyticsKey,
min.instance.textAnalyticsServerUrl,
min.conversationalService.getCurrentLanguage(dc),
value
)
);
if (rate > 0.50) {
await dc.context.sendActivity(
"Bom saber que você gostou. Conte comigo."
)
if (rate > 0.5) {
await dc.context.sendActivity(Messages[locale].glad_you_liked);
} else {
await dc.context.sendActivity(
"Vamos registrar sua questão, obrigado pela sinceridade."
)
await dc.context.sendActivity(Messages[locale].we_will_improve);
// TODO: Record.
}
await dc.replace("/ask", { isReturning: true })
await dc.replace("/ask", { isReturning: true });
}
])
]);
}
}

View file

@ -30,17 +30,17 @@
| |
\*****************************************************************************/
"use strict"
"use strict";
import { IGBDialog } from "botlib"
import { IGBDialog } from "botlib";
import { GBMinInstance } from "botlib"
import { CSService } from "../services/CSService"
import { BotAdapter } from "botbuilder"
const logger = require("../../../src/logger")
import { GBMinInstance } from "botlib";
import { CSService } from "../services/CSService";
import { BotAdapter } from "botbuilder";
import { Messages } from "../strings";
const logger = require("../../../src/logger");
export class QualityDialog extends IGBDialog {
/**
* Setup dialogs flows and define services call.
*
@ -48,43 +48,32 @@ export class QualityDialog extends IGBDialog {
* @param min The minimal bot instance data.
*/
static setup(bot: BotAdapter, min: GBMinInstance) {
const service = new CSService()
const service = new CSService();
min.dialogs.add("/quality", [
async (dc, args) => {
const user = min.userState.get(dc.context)
var score = args.score
const locale = dc.context.activity.locale;
const user = min.userState.get(dc.context);
var score = args.score;
setTimeout(
() => min.conversationalService.sendEvent(dc, "stop", null),
400
)
);
if (score == 0) {
let msg = [
"Desculpe-me, vamos tentar novamente.",
"Lamento... Vamos tentar novamente!",
"Desculpe-me. Por favor, tente escrever de outra forma?"
]
await dc.context.sendActivity(msg[0])
await dc.context.sendActivity(Messages[locale].im_sorry_lets_try);
} else {
let msg = [
"Ótimo, obrigado por contribuir com sua resposta.",
"Certo, obrigado pela informação.",
"Obrigado pela contribuição."
]
await dc.context.sendActivity(msg[0])
await dc.context.sendActivity(Messages[locale].great_thanks);
await service.insertQuestionAlternate(
min.instance.instanceId,
user.lastQuestion,
user.lastQuestionId
)
await dc.replace('/ask', {isReturning: true})
);
await dc.replace("/ask", { isReturning: true });
}
}
])
]);
}
}

View file

@ -0,0 +1,22 @@
export const Messages = {
"en-US": {
about_suggestions: "Suggestions are welcomed and improve my quality...",
what_about_service: "What about my service?",
glad_you_liked: "I'm glad you liked. I'm here for you.",
we_will_improve: "Let's take note of that, thanks for sharing.",
what_about_me: "What about the service, please rate between 1 and 5.",
thanks: "Thanks!",
im_sorry_lets_try: "I'm sorry. Let's try again...",
great_thanks: "Great, thanks for sharing your thoughts."
},
"pt-BR": {
about_suggestions: "Sugestões melhoram muito minha qualidade...",
what_about_service:"O que achou do meu atendimento?",
glad_you_liked: "Bom saber que você gostou. Conte comigo.",
we_will_improve: "Vamos registrar sua questão, obrigado pela sinceridade.",
what_about_me: "O que achou do meu atendimento, de 1 a 5?",
thanks: "Obrigado!",
im_sorry_lets_try: "Desculpe-me, vamos tentar novamente.",
great_thanks: "Ótimo, obrigado por contribuir com sua resposta."
}
};

View file

@ -61,12 +61,12 @@ class SideBarMenu extends React.Component {
<div className="IconsMenu">
<div className="iconMenu">
<span className="iconText" onClick={() => this.send("showFAQ")}>
Perguntas frequentes
FAQ
</span>
</div>
<div className="iconMenu">
<span className="iconText" onClick={() => this.send("whoAmI")}>
Quem é você?
Who are You?
</span>
</div>
<div className="iconMenu">
@ -74,7 +74,7 @@ class SideBarMenu extends React.Component {
className="iconText"
onClick={() => this.send("showSubjects")}
>
Assuntos
Subjects
</span>
</div>
<div className="iconMenu">
@ -82,7 +82,7 @@ class SideBarMenu extends React.Component {
className="iconText"
onClick={() => this.send("giveFeedback")}
>
Sugestão
Suggestions
</span>
</div>
</div>

View file

@ -30,16 +30,18 @@
| |
\*****************************************************************************/
"use strict"
"use strict";
import { IGBDialog } from "botlib"
import { AzureText } from "pragmatismo-io-framework"
import { GBMinInstance } from "botlib"
import { KBService } from './../services/KBService'
import { BotAdapter } from "botbuilder"
import { LuisRecognizer } from "botbuilder-ai"
import { IGBDialog } from "botlib";
import { AzureText } from "pragmatismo-io-framework";
import { GBMinInstance } from "botlib";
import { KBService } from "./../services/KBService";
import { BotAdapter } from "botbuilder";
import { Messages } from "../strings";
import { LuisRecognizer } from "botbuilder-ai";
const logger = require("../../../src/logger")
const logger = require("../../../src/logger");
export class AskDialog extends IGBDialog {
/**
@ -49,68 +51,55 @@ export class AskDialog extends IGBDialog {
* @param min The minimal bot instance data.
*/
static setup(bot: BotAdapter, min: GBMinInstance) {
const service = new KBService(min.core.sequelize)
const service = new KBService(min.core.sequelize);
const model = new LuisRecognizer({
appId: min.instance.nlpAppId,
subscriptionKey: min.instance.nlpSubscriptionKey,
serviceEndpoint: min.instance.nlpServerUrl
})
});
min.dialogs.add("/answer", [
async (dc, args) => {
// Initialize values.
const user = min.userState.get(dc.context)
let text = args.query
const user = min.userState.get(dc.context);
let text = args.query;
if (!text) {
throw new Error(`/answer being called with no args.query text.`)
throw new Error(`/answer being called with no args.query text.`);
}
let locale = await AzureText.getLocale(min.instance.textAnalyticsKey,
min.instance.textAnalyticsServerUrl, text)
if (locale != dc.context.activity.locale.split("-")[0])
{
switch(locale)
{
let locale = await AzureText.getLocale(
min.instance.textAnalyticsKey,
min.instance.textAnalyticsServerUrl,
text
);
if (locale != dc.context.activity.locale.split("-")[0]) {
switch (locale) {
case "pt":
await dc.context.sendActivity("OK, mundando de idioma para o Português...")
dc.context.activity.locale = "pt-BR"
break
dc.context.activity.locale = "pt-BR";
await dc.context.sendActivity(Messages[locale].changing_language);
break;
case "en":
await dc.context.sendActivity("OK, changing language to English...")
dc.context.activity.locale = "en-US"
break
dc.context.activity.locale = "en-US";
await dc.context.sendActivity(Messages[locale].changing_language);
break;
default:
await dc.context.sendActivity(`Unknown language: ${locale}`)
break
await dc.context.sendActivity(`Unknown language: ${locale}`);
break;
}
}
// Stops any content on projector.
await min.conversationalService.sendEvent(dc, "stop", null)
await min.conversationalService.sendEvent(dc, "stop", null);
// Handle extra text from FAQ.
if (args && args.query) {
text = args.query
text = args.query;
} else if (args && args.fromFaq) {
let messages = [
`Ótima escolha, procurando resposta para sua questão...`,
`Pesquisando sobre o termo...`,
`Aguarde, por favor, enquanto acho sua resposta...`
]
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
await dc.context.sendActivity(Messages[locale].going_answer);
}
// Spells check the input text before sending Search or NLP.
@ -118,127 +107,115 @@ export class AskDialog extends IGBDialog {
if (min.instance.spellcheckerKey) {
let data = await AzureText.getSpelledText(
min.instance.spellcheckerKey,
text)
text
);
if (data != text) {
logger.info(`Spelling corrected: ${data}`)
text = data
logger.info(`Spelling corrected: ${data}`);
text = data;
}
}
// Searches KB for the first time.
user.lastQuestion = text
user.lastQuestion = text;
let resultsA = await service.ask(
min.instance,
text,
min.instance.searchScore,
user.subjects)
user.subjects
);
// If there is some result, answer immediately.
if (resultsA && resultsA.answer) {
// Saves some context info.
user.isAsking = false
user.lastQuestionId = resultsA.questionId
user.isAsking = false;
user.lastQuestionId = resultsA.questionId;
// Sends the answer to all outputs, including projector.
await service.sendAnswer(min.conversationalService, dc, resultsA.answer)
await service.sendAnswer(
min.conversationalService,
dc,
resultsA.answer
);
// Goes to ask loop, again.
await dc.replace("/ask", { isReturning: true })
await dc.replace("/ask", { isReturning: true });
} else {
// Second time running Search, now with no filter.
let resultsB = await service.ask(min.instance, text,
min.instance.searchScore, null)
let resultsB = await service.ask(
min.instance,
text,
min.instance.searchScore,
null
);
// If there is some result, answer immediately.
if (resultsB && resultsB.answer) {
// Saves some context info.
const user = min.userState.get(dc.context)
user.isAsking = false
user.lastQuestionId = resultsB.questionId
const user = min.userState.get(dc.context);
user.isAsking = false;
user.lastQuestionId = resultsB.questionId;
// Informs user that a broader search will be used.
if (user.subjects.length > 0) {
let subjectText =
`${KBService.getSubjectItemsSeparatedBySpaces(
let subjectText = `${KBService.getSubjectItemsSeparatedBySpaces(
user.subjects
)}`
let messages = [
`Respondendo nao apenas sobre ${subjectText}... `,
`Respondendo de modo mais abrangente...`,
`Vou te responder de modo mais abrangente...
Não apenas sobre ${subjectText}`
]
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
)}`;
await dc.context.sendActivity(Messages[locale].wider_answer);
}
// Sends the answer to all outputs, including projector.
await service.sendAnswer(min.conversationalService, dc, resultsB.answer)
await dc.replace("/ask", { isReturning: true })
await service.sendAnswer(
min.conversationalService,
dc,
resultsB.answer
);
await dc.replace("/ask", { isReturning: true });
} else {
let data = await min.conversationalService.runNLP(dc, min, text)
if (!data) {
let messages = [
"Desculpe-me, não encontrei nada a respeito.",
"Lamento... Não encontrei nada sobre isso. Vamos tentar novamente?",
"Desculpe-me, não achei nada parecido. Poderia tentar escrever de outra forma?"
]
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
await dc.replace("/ask", { isReturning: true })
if (!(await min.conversationalService.runNLP(dc, min, text))) {
await dc.context.sendActivity(Messages[locale].did_not_find);
await dc.replace("/ask", { isReturning: true });
}
}
}
}
])
]);
min.dialogs.add("/ask", [
async (dc, args) => {
const user = min.userState.get(dc.context)
user.isAsking = true
const locale = dc.context.activity.locale;
const user = min.userState.get(dc.context);
user.isAsking = true;
if (!user.subjects) {
user.subjects = []
user.subjects = [];
}
let text = []
let text = [];
if (user.subjects.length > 0) {
text = [
`Faça sua pergunta...`,
`Pode perguntar sobre o assunto em questão... `,
`Qual a pergunta?`
]
text = Messages[locale].which_question;
}
if (args && args.isReturning) {
text = [
"Sobre o que mais posso ajudar?",
"Então, posso ajudar em algo a mais?",
"Deseja fazer outra pergunta?"
]
text = Messages[locale].anything_else;
}
if (text.length > 0) {
await dc.prompt('textPrompt', text[0])
await dc.prompt("textPrompt", text[0]);
}
},
async (dc, value) => {
await dc.endAll()
await dc.begin("/answer", { query: value })
await dc.endAll();
await dc.begin("/answer", { query: value });
}
])
]);
}
}

View file

@ -35,6 +35,7 @@
import { KBService } from './../services/KBService'
import { IGBDialog } from "botlib"
import { BotAdapter } from "botbuilder"
import { Messages } from "../strings";
import { GBMinInstance } from "botlib"
export class FaqDialog extends IGBDialog {
@ -51,19 +52,14 @@ export class FaqDialog extends IGBDialog {
min.dialogs.add("/faq", [
async (dc, args) => {
let data = await service.getFaqBySubjectArray("faq", null)
const locale = dc.context.activity.locale;
if (data) {
await min.conversationalService.sendEvent(dc, "play", {
playerType: "bullet",
data: data.slice(0, 10)
})
let messages = [
"Veja algumas perguntas mais frequentes logo na tela. Clique numa delas para eu responder.",
"Você pode clicar em alguma destas perguntas da tela que eu te respondo de imediato.",
"Veja a lista que eu preparei logo aí na tela..."
]
await dc.context.sendActivity(messages[0]) // TODO: RND messages.
await dc.context.sendActivity(Messages[locale].see_faq) // TODO: RND messages.
await dc.endAll()
}
}

View file

@ -30,18 +30,19 @@
| |
\*****************************************************************************/
"use strict"
"use strict";
const UrlJoin = require("url-join")
const UrlJoin = require("url-join");
import { BotAdapter, CardFactory, MessageFactory } from "botbuilder"
import { IGBDialog } from "botlib"
import { GBMinInstance } from "botlib"
import { GuaribasSubject } from '../models'
import { KBService } from "../services/KBService"
import { BotAdapter, CardFactory, MessageFactory } from "botbuilder";
import { IGBDialog } from "botlib";
import { GBMinInstance } from "botlib";
import { GuaribasSubject } from "../models";
import { KBService } from "../services/KBService";
import { Messages } from "../strings";
import { AzureText } from "pragmatismo-io-framework";
export class MenuDialog extends IGBDialog {
/**
* Setup dialogs flows and define services call.
*
@ -49,118 +50,118 @@ export class MenuDialog extends IGBDialog {
* @param min The minimal bot instance data.
*/
static setup(bot: BotAdapter, min: GBMinInstance) {
var service = new KBService(min.core.sequelize);
var service = new KBService(min.core.sequelize)
bot
min.dialogs.add("/menu", [
async (dc, args) => {
var rootSubjectId = null
const locale = dc.context.activity.locale;
var rootSubjectId = null;
if (args && args.data) {
var subject = args.data
var subject = args.data;
// If there is a shortcut specified as subject destination, go there.
if (subject.to) {
let dialog = subject.to.split(":")[1]
await dc.replace("/" + dialog)
await dc.end()
return
let dialog = subject.to.split(":")[1];
await dc.replace("/" + dialog);
await dc.end();
return;
}
// Adds to bot a perception of a new subject.
const user = min.userState.get(dc.context)
user.subjects.push(subject)
rootSubjectId = subject.subjectId
const user = min.userState.get(dc.context);
user.subjects.push(subject);
rootSubjectId = subject.subjectId;
// Whenever a subject is selected, shows a faq about it.
if (user.subjects.length > 0) {
let data = await service.getFaqBySubjectArray("menu", user.subjects)
let data = await service.getFaqBySubjectArray(
"menu",
user.subjects
);
await min.conversationalService.sendEvent(dc, "play", {
playerType: "bullet",
data: data.slice(0, 6)
})
});
}
} else {
const user = min.userState.get(dc.context)
user.subjects = []
const user = min.userState.get(dc.context);
user.subjects = [];
let messages = [
"Aqui estão algumas categorias de assuntos...",
"Selecionando o assunto você pode me ajudar a encontrar a resposta certa...",
"Você pode selecionar algum dos assuntos abaixo e perguntar algo..."
]
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
user.isAsking = false
await dc.context.sendActivity(Messages[locale].here_is_subjects); // TODO: Handle rnd.
user.isAsking = false;
}
const msg = MessageFactory.text('')
var attachments = []
const msg = MessageFactory.text("");
var attachments = [];
let data = await service.getSubjectItems(
min.instance.instanceId,
rootSubjectId)
rootSubjectId
);
msg.attachmentLayout = 'carousel'
msg.attachmentLayout = "carousel";
data.forEach(function(item: GuaribasSubject) {
var subject = item
var subject = item;
var card = CardFactory.heroCard(
subject.title,
CardFactory.images([UrlJoin(
CardFactory.images([
UrlJoin(
"/kb",
min.instance.kb,
"subjects",
subject.internalId + ".png" // TODO: or fallback to subject.png
)]),
)
]),
CardFactory.actions([
{
type: 'postBack',
title: 'Selecionar',
type: "postBack",
title: Messages[locale].menu_select,
value: JSON.stringify({
title: subject.title,
subjectId: subject.subjectId,
to: subject.to
})
}]))
}
])
);
attachments.push(card)
})
attachments.push(card);
});
if (attachments.length == 0) {
const user = min.userState.get(dc.context)
const user = min.userState.get(dc.context);
if (user.subjects && user.subjects.length > 0) {
await dc.context.sendActivity(
`Vamos pesquisar sobre ${KBService.getFormattedSubjectItems(
user.subjects
)}?`
Messages[locale].lets_search(
KBService.getFormattedSubjectItems(user.subjects)
)
);
}
await dc.replace("/ask", {})
await dc.replace("/ask", {});
} else {
msg.attachments = attachments
await dc.context.sendActivity(msg)
msg.attachments = attachments;
await dc.context.sendActivity(msg);
}
const user = min.userState.get(dc.context)
user.isAsking = true
const user = min.userState.get(dc.context);
user.isAsking = true;
},
async (dc, value) => {
var text = value
if (text === "no" || text === "n") { // TODO: Migrate to a common.
await dc.replace("/feedback")
var text = value;
const locale = dc.context.activity.locale;
if (AzureText.isIntentNo(locale, text)) {
await dc.replace("/feedback");
} else {
await dc.replace("/ask")
await dc.replace("/ask");
}
}
])
]);
}
}

View file

@ -40,6 +40,7 @@ const marked = require("marked")
const path = require("path")
const asyncPromise = require('async-promises')
const walkPromise = require('walk-promise')
import { Messages } from "../strings";
import { Sequelize } from 'sequelize-typescript'
import { GBConfigService } from './../../core.gbapp/services/GBConfigService'
@ -397,8 +398,7 @@ export class KBService {
format = ".md"
} else {
logger.info(`[GBImporter] File not found: ${mediaFilename}.`)
answer =
"Por favor, contate a administração para rever esta pergunta."
answer = ""
}
}
@ -464,13 +464,9 @@ export class KBService {
})
} else if (answer.content.length > 140 &&
dc.context._activity.channelId === "webchat") {
let messages = [
"Vou te responder na tela para melhor visualização...",
"A resposta está na tela...",
"Veja a resposta na tela..."
]
const locale = dc.context.activity.locale;
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
await dc.context.sendActivity(Messages[locale].will_answer_projector) // TODO: Handle rnd.
var html = answer.content
if (answer.format === ".md") {

View file

@ -0,0 +1,34 @@
export const Messages = {
"en-US": {
did_not_find: "I'm sorry I didn't find anything.",
changing_language: "OK, changing language to English...",
going_answer: "Great choice, now looking for your answer...",
wider_answer: subjectText =>
`Answering to you in a broader way... Not just about ${subjectText}.`,
which_question: "What's your question?",
anything_else: "So, may I help with anything else?",
here_is_subjects: "Here are some subjects to choose from...",
menu_select: "Select",
lets_search: query =>
`Vamos pesquisar sobre ${query}... O que deseja saber?`,
see_faq:
"Please take a look at the FAQ I've prepared for you. You can click on them to get the answer.",
will_answer_projector:"I'll answer on the projector to a better experience..."
},
"pt-BR": {
did_not_find: "Desculpe-me, não encontrei nada a respeito.",
changing_language: "OK, mundando de idioma para o Português...",
going_answer: "Ótima escolha, procurando resposta para sua questão...",
wider_answer: subjectText =>
`Vou te responder de modo mais abrangente... Não apenas sobre ${subjectText}`,
which_question: "Qual a pergunta?",
anything_else: "Então, posso ajudar em algo a mais?",
here_is_subjects: "Aqui estão algumas categorias de assuntos...",
menu_select: "Selecionar",
lets_search: query =>
`Let's search about ${query}... What do you want to know?`,
see_faq:
"Veja algumas perguntas mais frequentes logo na tela. Clique numa delas para eu responder.",
will_answer_projector:"Vou te responder na tela para melhor visualização..."
}
};

View file

@ -3,8 +3,6 @@
"allowJs": false,
"baseUrl": "./",
"declaration": false,
"allowSyntheticDefaultImports": true,
"esModuleInterop" : true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"skipLibCheck": true,