From 7a33f6942e3933dadd36eba77f252c2f2df242cb Mon Sep 17 00:00:00 2001 From: Rodrigo Rodriguez Date: Fri, 14 Sep 2018 12:56:54 -0300 Subject: [PATCH] General Bots in now almost globalized. --- deploy/admin.gbapp/dialogs/AdminDialog.ts | 1 + deploy/core.gbapp/dialogs/WelcomeDialog.ts | 48 ++--- deploy/core.gbapp/dialogs/WhoAmIDialog.ts | 27 ++- deploy/core.gbapp/dialogs/strings.json | 16 -- .../services/GBConversationalService.ts | 68 +++---- deploy/core.gbapp/services/GBMinService.ts | 2 +- deploy/core.gbapp/strings.ts | 16 ++ deploy/core.gbapp/strings/en.ts | 5 - deploy/core.gbapp/strings/pt.ts | 4 - .../dialogs/FeedbackDialog.ts | 74 +++---- .../dialogs/QualityDialog.ts | 47 ++--- deploy/customer-satisfaction.gbapp/strings.ts | 22 ++ .../src/components/SidebarMenu.js | 8 +- deploy/kb.gbapp/dialogs/AskDialog.ts | 191 ++++++++---------- deploy/kb.gbapp/dialogs/FaqDialog.ts | 12 +- deploy/kb.gbapp/dialogs/MenuDialog.ts | 139 ++++++------- deploy/kb.gbapp/services/KBService.ts | 14 +- deploy/kb.gbapp/strings.ts | 34 ++++ tsconfig.json | 2 - 19 files changed, 359 insertions(+), 371 deletions(-) delete mode 100644 deploy/core.gbapp/dialogs/strings.json create mode 100644 deploy/core.gbapp/strings.ts delete mode 100644 deploy/core.gbapp/strings/en.ts delete mode 100644 deploy/core.gbapp/strings/pt.ts create mode 100644 deploy/customer-satisfaction.gbapp/strings.ts create mode 100644 deploy/kb.gbapp/strings.ts diff --git a/deploy/admin.gbapp/dialogs/AdminDialog.ts b/deploy/admin.gbapp/dialogs/AdminDialog.ts index e2fc25c2..ef89f6d8 100644 --- a/deploy/admin.gbapp/dialogs/AdminDialog.ts +++ b/deploy/admin.gbapp/dialogs/AdminDialog.ts @@ -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" /** diff --git a/deploy/core.gbapp/dialogs/WelcomeDialog.ts b/deploy/core.gbapp/dialogs/WelcomeDialog.ts index 80258ee4..e308c362 100644 --- a/deploy/core.gbapp/dialogs/WelcomeDialog.ts +++ b/deploy/core.gbapp/dialogs/WelcomeDialog.ts @@ -30,46 +30,48 @@ | | \*****************************************************************************/ -"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 { /** * Setup dialogs flows and define services call. - * + * * @param bot The bot adapter. * @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); + const locale = dc.context.activity.locale; - const user = min.userState.get(dc.context) - let loc = 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 }); } } } - ]) + ]); } } diff --git a/deploy/core.gbapp/dialogs/WhoAmIDialog.ts b/deploy/core.gbapp/dialogs/WhoAmIDialog.ts index f51ddefe..8bf7097d 100644 --- a/deploy/core.gbapp/dialogs/WhoAmIDialog.ts +++ b/deploy/core.gbapp/dialogs/WhoAmIDialog.ts @@ -30,37 +30,36 @@ | | \*****************************************************************************/ -"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. - * + * * @param bot The bot adapter. * @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 }); } - ]) + ]); } } diff --git a/deploy/core.gbapp/dialogs/strings.json b/deploy/core.gbapp/dialogs/strings.json deleted file mode 100644 index f2e3aecd..00000000 --- a/deploy/core.gbapp/dialogs/strings.json +++ /dev/null @@ -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" - } - } -} diff --git a/deploy/core.gbapp/services/GBConversationalService.ts b/deploy/core.gbapp/services/GBConversationalService.ts index c82cd97f..a97e23a3 100644 --- a/deploy/core.gbapp/services/GBConversationalService.ts +++ b/deploy/core.gbapp/services/GBConversationalService.ts @@ -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 { - 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 { + async routeNLP(dc: any, min: GBMinInstance, text: string): Promise { + // 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); } } } diff --git a/deploy/core.gbapp/services/GBMinService.ts b/deploy/core.gbapp/services/GBMinService.ts index 8ab4eff1..8b691ed3 100644 --- a/deploy/core.gbapp/services/GBMinService.ts +++ b/deploy/core.gbapp/services/GBMinService.ts @@ -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) { diff --git a/deploy/core.gbapp/strings.ts b/deploy/core.gbapp/strings.ts new file mode 100644 index 00000000..549b41e5 --- /dev/null +++ b/deploy/core.gbapp/strings.ts @@ -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}.` + } +}; diff --git a/deploy/core.gbapp/strings/en.ts b/deploy/core.gbapp/strings/en.ts deleted file mode 100644 index 9b74a3a0..00000000 --- a/deploy/core.gbapp/strings/en.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const messages = - { - show_video: "I will show you a video, please wait..." - } -; diff --git a/deploy/core.gbapp/strings/pt.ts b/deploy/core.gbapp/strings/pt.ts deleted file mode 100644 index 7ed9d44a..00000000 --- a/deploy/core.gbapp/strings/pt.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const messages = - { - show_video: "Vou te mostrar um vídeo. Por favor, aguarde..." - } \ No newline at end of file diff --git a/deploy/customer-satisfaction.gbapp/dialogs/FeedbackDialog.ts b/deploy/customer-satisfaction.gbapp/dialogs/FeedbackDialog.ts index 97630a9a..6e7c79d7 100644 --- a/deploy/customer-satisfaction.gbapp/dialogs/FeedbackDialog.ts +++ b/deploy/customer-satisfaction.gbapp/dialogs/FeedbackDialog.ts @@ -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" - ]) + "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 }); } - ]) + ]); } -} +} \ No newline at end of file diff --git a/deploy/customer-satisfaction.gbapp/dialogs/QualityDialog.ts b/deploy/customer-satisfaction.gbapp/dialogs/QualityDialog.ts index c0717eb4..1318d2ec 100644 --- a/deploy/customer-satisfaction.gbapp/dialogs/QualityDialog.ts +++ b/deploy/customer-satisfaction.gbapp/dialogs/QualityDialog.ts @@ -30,61 +30,50 @@ | | \*****************************************************************************/ -"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. - * + * * @param bot The bot adapter. * @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 }); } } - ]) + ]); } } diff --git a/deploy/customer-satisfaction.gbapp/strings.ts b/deploy/customer-satisfaction.gbapp/strings.ts new file mode 100644 index 00000000..35481519 --- /dev/null +++ b/deploy/customer-satisfaction.gbapp/strings.ts @@ -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." + } +}; diff --git a/deploy/default.gbui/src/components/SidebarMenu.js b/deploy/default.gbui/src/components/SidebarMenu.js index 335bea9c..42dfd898 100644 --- a/deploy/default.gbui/src/components/SidebarMenu.js +++ b/deploy/default.gbui/src/components/SidebarMenu.js @@ -61,12 +61,12 @@ class SideBarMenu extends React.Component {
this.send("showFAQ")}> - Perguntas frequentes + FAQ
this.send("whoAmI")}> - Quem é você? + Who are You?
@@ -74,7 +74,7 @@ class SideBarMenu extends React.Component { className="iconText" onClick={() => this.send("showSubjects")} > - Assuntos + Subjects
@@ -82,7 +82,7 @@ class SideBarMenu extends React.Component { className="iconText" onClick={() => this.send("giveFeedback")} > - Sugestão + Suggestions
diff --git a/deploy/kb.gbapp/dialogs/AskDialog.ts b/deploy/kb.gbapp/dialogs/AskDialog.ts index 47618d63..ba0419b4 100644 --- a/deploy/kb.gbapp/dialogs/AskDialog.ts +++ b/deploy/kb.gbapp/dialogs/AskDialog.ts @@ -30,87 +30,76 @@ | | \*****************************************************************************/ -"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 { /** * Setup dialogs flows and define services call. - * + * * @param bot The bot adapter. * @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( - 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. + let subjectText = `${KBService.getSubjectItemsSeparatedBySpaces( + user.subjects + )}`; + 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 }); } - ]) + ]); } } diff --git a/deploy/kb.gbapp/dialogs/FaqDialog.ts b/deploy/kb.gbapp/dialogs/FaqDialog.ts index d4167483..94961182 100644 --- a/deploy/kb.gbapp/dialogs/FaqDialog.ts +++ b/deploy/kb.gbapp/dialogs/FaqDialog.ts @@ -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() } } diff --git a/deploy/kb.gbapp/dialogs/MenuDialog.ts b/deploy/kb.gbapp/dialogs/MenuDialog.ts index c5beee6b..ba0a315e 100644 --- a/deploy/kb.gbapp/dialogs/MenuDialog.ts +++ b/deploy/kb.gbapp/dialogs/MenuDialog.ts @@ -30,137 +30,138 @@ | | \*****************************************************************************/ -"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. - * + * * @param bot The bot adapter. * @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 + data.forEach(function(item: GuaribasSubject) { + var subject = item; var card = CardFactory.heroCard( subject.title, - CardFactory.images([UrlJoin( - "/kb", - min.instance.kb, - "subjects", - subject.internalId + ".png" // TODO: or fallback to subject.png - )]), + 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"); } } - ]) + ]); } -} +} \ No newline at end of file diff --git a/deploy/kb.gbapp/services/KBService.ts b/deploy/kb.gbapp/services/KBService.ts index 294c55a8..1403d839 100644 --- a/deploy/kb.gbapp/services/KBService.ts +++ b/deploy/kb.gbapp/services/KBService.ts @@ -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..." - ] - - await dc.context.sendActivity(messages[0]) // TODO: Handle rnd. + const locale = dc.context.activity.locale; + + await dc.context.sendActivity(Messages[locale].will_answer_projector) // TODO: Handle rnd. var html = answer.content if (answer.format === ".md") { diff --git a/deploy/kb.gbapp/strings.ts b/deploy/kb.gbapp/strings.ts new file mode 100644 index 00000000..3747bf97 --- /dev/null +++ b/deploy/kb.gbapp/strings.ts @@ -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..." + } +}; diff --git a/tsconfig.json b/tsconfig.json index f1eea6e8..68925c5c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,8 +3,6 @@ "allowJs": false, "baseUrl": "./", "declaration": false, - "allowSyntheticDefaultImports": true, - "esModuleInterop" : true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "skipLibCheck": true,