General Bots in now almost globalized.
This commit is contained in:
		
							parent
							
								
									c573e33754
								
							
						
					
					
						commit
						7a33f6942e
					
				
					 19 changed files with 359 additions and 371 deletions
				
			
		| 
						 | 
				
			
			@ -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"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 });
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ])
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 });
 | 
			
		||||
      }
 | 
			
		||||
    ])
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								deploy/core.gbapp/strings.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								deploy/core.gbapp/strings.ts
									
										
									
									
									
										Normal 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}.`
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +0,0 @@
 | 
			
		|||
export const messages = 
 | 
			
		||||
  {
 | 
			
		||||
    show_video: "I will show you a video, please wait..."
 | 
			
		||||
  }
 | 
			
		||||
;
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +0,0 @@
 | 
			
		|||
export const messages = 
 | 
			
		||||
  {
 | 
			
		||||
    show_video: "Vou te mostrar um vídeo. Por favor, aguarde..."
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -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 });
 | 
			
		||||
      }
 | 
			
		||||
    ])
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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 });
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ])
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										22
									
								
								deploy/customer-satisfaction.gbapp/strings.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								deploy/customer-satisfaction.gbapp/strings.ts
									
										
									
									
									
										Normal 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."
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 });
 | 
			
		||||
      }
 | 
			
		||||
    ])
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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()
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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");
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ])
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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") {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										34
									
								
								deploy/kb.gbapp/strings.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								deploy/kb.gbapp/strings.ts
									
										
									
									
									
										Normal 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..."
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -3,8 +3,6 @@
 | 
			
		|||
    "allowJs": false,
 | 
			
		||||
    "baseUrl": "./",
 | 
			
		||||
    "declaration": false,
 | 
			
		||||
    "allowSyntheticDefaultImports": true,
 | 
			
		||||
    "esModuleInterop"             : true,
 | 
			
		||||
    "emitDecoratorMetadata": true,
 | 
			
		||||
    "experimentalDecorators": true,
 | 
			
		||||
    "skipLibCheck": true,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue