new(all): Profile dialog for editing user information.

This commit is contained in:
Rodrigo Rodriguez 2020-07-26 16:46:37 -03:00
parent 1c36ef0f19
commit df6c0f5c10
20 changed files with 329 additions and 87 deletions

View file

@ -227,7 +227,7 @@
### Features ### Features
* **core.gbapp:** Development options added (ngrok) ([223801d](https://github.com/pragmatismo-io/BotServer/commit/223801d)) * **core.gbapp:** Development options added (ngrok) ([223801d](https://github.com/pragmatismo-io/BotServer/commit/223801d))
* **security.gblib:** Phone field and conversation refeerence. ([46261d7](https://github.com/pragmatismo-io/BotServer/commit/46261d7)) * **security.gbapp:** Phone field and conversation refeerence. ([46261d7](https://github.com/pragmatismo-io/BotServer/commit/46261d7))
## [1.3.10](https://github.com/pragmatismo-io/BotServer/compare/1.3.9...1.3.10) (2019-06-21) ## [1.3.10](https://github.com/pragmatismo-io/BotServer/compare/1.3.9...1.3.10) (2019-06-21)

54
package-lock.json generated
View file

@ -1,6 +1,6 @@
{ {
"name": "botserver", "name": "botserver",
"version": "1.7.6", "version": "2.0.3",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -4349,9 +4349,9 @@
}, },
"dependencies": { "dependencies": {
"@types/node": { "@types/node": {
"version": "10.17.27", "version": "10.17.28",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.27.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.28.tgz",
"integrity": "sha512-J0oqm9ZfAXaPdwNXMMgAhylw5fhmXkToJd06vuDUSAgEDZ/n/69/69UmyBZbc+zT34UnShuDSBqvim3SPnozJg==" "integrity": "sha512-dzjES1Egb4c1a89C7lKwQh8pwjYmlOAG9dW1pBgxEk57tMrLnssOfEthz8kdkNaBd7lIqQx7APm5+mZ619IiCQ=="
} }
} }
}, },
@ -4473,9 +4473,9 @@
} }
}, },
"botlib": { "botlib": {
"version": "1.5.9", "version": "1.6.2",
"resolved": "https://registry.npmjs.org/botlib/-/botlib-1.5.9.tgz", "resolved": "https://registry.npmjs.org/botlib/-/botlib-1.6.2.tgz",
"integrity": "sha512-pvUdntYLTMtiLnmP+skZDf7Cxf5D0NIiOzdsDwx4QIXjBmP0BwuaLWD3X4JaPcRrzqrJE0PAy+wZuoxupSMZLA==", "integrity": "sha512-t3aDi+OK6KsKCpXt1HzzPrMqPM7TcNIB3xzOWZVv/qgPE92qCmXosbgcm1zsTEoVN39lhEEQNyQ5esk5O4c4iQ==",
"requires": { "requires": {
"async": "3.1.0", "async": "3.1.0",
"botbuilder": "4.7.0", "botbuilder": "4.7.0",
@ -4509,14 +4509,6 @@
"which": "^2.0.1" "which": "^2.0.1"
} }
}, },
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
},
"dotenv-extended": { "dotenv-extended": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/dotenv-extended/-/dotenv-extended-2.7.1.tgz", "resolved": "https://registry.npmjs.org/dotenv-extended/-/dotenv-extended-2.7.1.tgz",
@ -4542,33 +4534,6 @@
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
}, },
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
},
"sequelize": {
"version": "5.21.5",
"resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.21.5.tgz",
"integrity": "sha512-n9hR5K4uQGmBGK/Y/iqewCeSFmKVsd0TRnh0tfoLoAkmXbKC4tpeK96RhKs7d+TTMtrJlgt2TNLVBaAxEwC4iw==",
"requires": {
"bluebird": "^3.5.0",
"cls-bluebird": "^2.1.0",
"debug": "^4.1.1",
"dottie": "^2.0.0",
"inflection": "1.12.0",
"lodash": "^4.17.15",
"moment": "^2.24.0",
"moment-timezone": "^0.5.21",
"retry-as-promised": "^3.2.0",
"semver": "^6.3.0",
"sequelize-pool": "^2.3.0",
"toposort-class": "^1.0.1",
"uuid": "^3.3.3",
"validator": "^10.11.0",
"wkx": "^0.4.8"
}
},
"shebang-command": { "shebang-command": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -4587,11 +4552,6 @@
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
"integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg=="
}, },
"validator": {
"version": "10.11.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
"integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
},
"which": { "which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View file

@ -69,7 +69,7 @@
"botbuilder-ai": "4.7.0", "botbuilder-ai": "4.7.0",
"botbuilder-dialogs": "4.7.0", "botbuilder-dialogs": "4.7.0",
"botframework-connector": "4.7.0", "botframework-connector": "4.7.0",
"botlib": "1.5.9", "botlib": "1.6.2",
"cli-spinner": "0.2.10", "cli-spinner": "0.2.10",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"dotenv-extended": "2.8.0", "dotenv-extended": "2.8.0",

View file

@ -86,6 +86,21 @@ export class GBAdminService implements IGBAdminService {
public static async getADALCredentialsFromUsername(username: string, password: string) { public static async getADALCredentialsFromUsername(username: string, password: string) {
return await msRestAzure.loginWithUsernamePassword(username, password); return await msRestAzure.loginWithUsernamePassword(username, password);
} }
public static getMobileCode() {
const passwordGenerator = new PasswordGenerator();
const options = {
upperCaseAlpha: false,
lowerCaseAlpha: false,
number: true,
specialCharacter: false,
minimumLength: 6,
maximumLength: 6
};
return passwordGenerator.generatePassword(options);
}
public static getRndPassword(): string { public static getRndPassword(): string {
const passwordGenerator = new PasswordGenerator(); const passwordGenerator = new PasswordGenerator();

View file

@ -56,7 +56,7 @@ import {
import { GuaribasChannel, GuaribasInstance } from '../../core.gbapp/models/GBModel'; import { GuaribasChannel, GuaribasInstance } from '../../core.gbapp/models/GBModel';
import { GuaribasSubject } from '../../kb.gbapp/models'; import { GuaribasSubject } from '../../kb.gbapp/models';
import { GuaribasUser } from '../../security.gblib/models'; import { GuaribasUser } from '../../security.gbapp/models';
/** /**

View file

@ -34,7 +34,7 @@
* @fileoverview General Bots server core. * @fileoverview General Bots server core.
*/ */
import { GuaribasUser } from '../../security.gblib/models'; import { GuaribasUser } from '../../security.gbapp/models';
import { GuaribasConversation, GuaribasConversationMessage } from '../models'; import { GuaribasConversation, GuaribasConversationMessage } from '../models';
/** /**

View file

@ -40,7 +40,7 @@ import { BotAdapter } from 'botbuilder';
import { WaterfallDialog } from 'botbuilder-dialogs'; import { WaterfallDialog } from 'botbuilder-dialogs';
import { GBMinInstance, IGBDialog } from 'botlib'; import { GBMinInstance, IGBDialog } from 'botlib';
import { Messages } from '../strings'; import { Messages } from '../strings';
import { SecService } from '../../security.gblib/services/SecService'; import { SecService } from '../../security.gbapp/services/SecService';
import { GBServer } from '../../../src/app'; import { GBServer } from '../../../src/app';
import { GBConversationalService } from '../services/GBConversationalService'; import { GBConversationalService } from '../services/GBConversationalService';
/** /**

View file

@ -42,7 +42,7 @@ import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService } from 'botlib';
import { GBServer } from '../../../src/app'; import { GBServer } from '../../../src/app';
import { Readable } from 'stream' import { Readable } from 'stream'
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService'; import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
import { SecService } from '../../security.gblib/services/SecService'; import { SecService } from '../../security.gbapp/services/SecService';
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService'; import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
const urlJoin = require('url-join'); const urlJoin = require('url-join');
const PasswordGenerator = require("strict-password-generator").default; const PasswordGenerator = require("strict-password-generator").default;

View file

@ -48,7 +48,7 @@ import { StartDialog } from '../../azuredeployer.gbapp/dialogs/StartDialog';
import { GBCorePackage } from '../../core.gbapp'; import { GBCorePackage } from '../../core.gbapp';
import { GBCustomerSatisfactionPackage } from '../../customer-satisfaction.gbapp'; import { GBCustomerSatisfactionPackage } from '../../customer-satisfaction.gbapp';
import { GBKBPackage } from '../../kb.gbapp'; import { GBKBPackage } from '../../kb.gbapp';
import { GBSecurityPackage } from '../../security.gblib'; import { GBSecurityPackage } from '../../security.gbapp';
import { GBWhatsappPackage } from '../../whatsapp.gblib/index'; import { GBWhatsappPackage } from '../../whatsapp.gblib/index';
import { GuaribasInstance } from '../models/GBModel'; import { GuaribasInstance } from '../models/GBModel';
import { GBConfigService } from './GBConfigService'; import { GBConfigService } from './GBConfigService';
@ -211,16 +211,18 @@ export class GBCoreService implements IGBCoreService {
*/ */
public async loadInstances(): Promise<IGBInstance[]> { public async loadInstances(): Promise<IGBInstance[]> {
if (process.env.LOAD_ONLY !== undefined) { if (process.env.LOAD_ONLY !== undefined) {
const bots = process.env.LOAD_ONLY.split(`;`); const bots = process.env.LOAD_ONLY.split(`;`);
const and = []; const and = [];
await CollectionUtil.asyncForEach(bots, async e => { await CollectionUtil.asyncForEach(bots, async e => {
and.push({botId: e}); and.push({ botId: e });
}); });
const options = {where: { const options = {
[Op.or]: and where: {
}}; [Op.or]: and
}
};
return GuaribasInstance.findAll(options); return GuaribasInstance.findAll(options);
} }
else { else {
@ -593,7 +595,7 @@ STORAGE_SYNC=true
* @param name Name of param to get from instance. * @param name Name of param to get from instance.
* @param defaultValue Value returned when no param is defined in Config.xlsx. * @param defaultValue Value returned when no param is defined in Config.xlsx.
*/ */
public getParam<T>(instance:IGBInstance, name: string, defaultValue?: T): any { public getParam<T>(instance: IGBInstance, name: string, defaultValue?: T): any {
let value = null; let value = null;
if (instance.params) { if (instance.params) {
const params = JSON.parse(instance.params); const params = JSON.parse(instance.params);
@ -608,5 +610,12 @@ STORAGE_SYNC=true
if (typeof (defaultValue) === "number") { if (typeof (defaultValue) === "number") {
return new Number(value ? defaultValue : (defaultValue ? defaultValue : 0)); return new Number(value ? defaultValue : (defaultValue ? defaultValue : 0));
} }
value = instance['dataValues'][name];
if (value === null) {
const minBoot = GBServer.globals.minBoot as any;
value = minBoot.instance.datavalues[name];
}
return value;
} }
} }

View file

@ -575,7 +575,7 @@ export class GBDeployer implements IGBDeployer {
} }
private isSystemPackage(name: string): Boolean { private isSystemPackage(name: string): Boolean {
const names = ['analytics.gblib', 'console.gblib', 'security.gblib', 'whatsapp.gblib', 'sharepoint.gblib', 'core.gbapp', 'admin.gbapp', 'azuredeployer.gbapp', 'customer-satisfaction.gbapp', 'kb.gbapp']; const names = ['analytics.gblib', 'console.gblib', 'security.gbapp', 'whatsapp.gblib', 'sharepoint.gblib', 'core.gbapp', 'admin.gbapp', 'azuredeployer.gbapp', 'customer-satisfaction.gbapp', 'kb.gbapp'];
return names.indexOf(name) > -1; return names.indexOf(name) > -1;
} }

View file

@ -64,7 +64,7 @@ import { KBService } from '../../kb.gbapp/services/KBService';
import { Messages } from '../strings'; import { Messages } from '../strings';
import { GBConfigService } from './GBConfigService'; import { GBConfigService } from './GBConfigService';
import { GBDeployer } from './GBDeployer'; import { GBDeployer } from './GBDeployer';
import { SecService } from '../../security.gblib/services/SecService'; import { SecService } from '../../security.gbapp/services/SecService';
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService'; import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
import { WhatsappDirectLine } from '../../whatsapp.gblib/services/WhatsappDirectLine'; import { WhatsappDirectLine } from '../../whatsapp.gblib/services/WhatsappDirectLine';
import fs = require('fs'); import fs = require('fs');
@ -469,6 +469,17 @@ export class GBMinService {
min.packages = sysPackages; min.packages = sysPackages;
min.appPackages = appPackages; min.appPackages = appPackages;
// Create a hub of services available in .gbapps.
let handled = false;
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
let services: ConcatArray<never>;
if (services = await e.onExchangeData(min, "getServices", null)) {
min.gbappServices.concat(services);
}
});
if (min.instance.whatsappServiceKey !== null) { if (min.instance.whatsappServiceKey !== null) {
min.whatsAppDirectLine = new WhatsappDirectLine( min.whatsAppDirectLine = new WhatsappDirectLine(
min, min,
@ -517,7 +528,7 @@ export class GBMinService {
await p.loadBot(min); await p.loadBot(min);
if (p.getDialogs !== undefined) { if (p.getDialogs !== undefined) {
const dialogs = await p.getDialogs(min); const dialogs = await p.getDialogs(min);
if (dialogs!== undefined){ if (dialogs !== undefined) {
dialogs.forEach(dialog => { dialogs.forEach(dialog => {
min.dialogs.add(new WaterfallDialog(dialog.id, dialog.waterfall)); min.dialogs.add(new WaterfallDialog(dialog.id, dialog.waterfall));
}); });
@ -708,8 +719,8 @@ export class GBMinService {
let locale = 'pt'; let locale = 'pt';
if (process.env.TRANSLATOR_DISABLED !== "true" || if (process.env.TRANSLATOR_DISABLED !== "true" ||
min.core.getParam<boolean> (min.instance,'Enable Worldwide Translator') ) { min.core.getParam<boolean>(min.instance, 'Enable Worldwide Translator')) {
const minBoot = GBServer.globals.minBoot as any; // TODO: Switch keys automatically to master/per bot. const minBoot = GBServer.globals.minBoot as any; // TODO: Switch keys automatically to master/per bot.
locale = await AzureText.getLocale(minBoot.instance.textAnalyticsKey ? locale = await AzureText.getLocale(minBoot.instance.textAnalyticsKey ?
minBoot.instance.textAnalyticsKey : minBoot.instance.textAnalyticsKey, minBoot.instance.textAnalyticsKey : minBoot.instance.textAnalyticsKey,
@ -737,17 +748,19 @@ export class GBMinService {
let handled = false; let handled = false;
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => { await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
if (await e.onExchangeData(min, "handleAnswer", { query: query, step: step, if (await e.onExchangeData(min, "handleAnswer", {
query: query, step: step,
notTranslatedQuery: notTranslatedQuery, notTranslatedQuery: notTranslatedQuery,
message: message, message: message['dataValues'],
user })) { user: user['dataValues']
})) {
handled = true; handled = true;
} }
}); });
if (!handled) { if (!handled) {
await step.beginDialog('/answer', { await step.beginDialog('/answer', {
query: query query: query, message: message
}); });
} }
} }

View file

@ -42,7 +42,7 @@ import { GBMinInstance, IGBDialog } from 'botlib';
import { AzureText } from 'pragmatismo-io-framework'; import { AzureText } from 'pragmatismo-io-framework';
import { CSService } from '../services/CSService'; import { CSService } from '../services/CSService';
import { Messages } from '../strings'; import { Messages } from '../strings';
import { SecService } from '../../security.gblib/services/SecService'; import { SecService } from '../../security.gbapp/services/SecService';
import { GBServer } from '../../../src/app'; import { GBServer } from '../../../src/app';
/** /**

View file

@ -39,13 +39,13 @@
import { GBServer } from '../../../src/app'; import { GBServer } from '../../../src/app';
import { BotAdapter } from 'botbuilder'; import { BotAdapter } from 'botbuilder';
import { WaterfallDialog } from 'botbuilder-dialogs'; import { WaterfallDialog } from 'botbuilder-dialogs';
import { GBLog, GBMinInstance, IGBDialog } from 'botlib'; import { GBLog, GBMinInstance, IGBDialog, IGBPackage } from 'botlib';
import { AzureText } from 'pragmatismo-io-framework';
import { Messages } from '../strings'; import { Messages } from '../strings';
import { KBService } from './../services/KBService'; import { KBService } from './../services/KBService';
import { GuaribasAnswer } from '../models'; import { GuaribasAnswer } from '../models';
import { GBMinService } from '../../../packages/core.gbapp/services/GBMinService'; import { GBMinService } from '../../../packages/core.gbapp/services/GBMinService';
import { SecService } from '../../security.gblib/services/SecService'; import { SecService } from '../../security.gbapp/services/SecService';
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
/** /**
* Dialog arguments. * Dialog arguments.
@ -103,7 +103,7 @@ export class AskDialog extends IGBDialog {
const translatorEnabled = () => { const translatorEnabled = () => {
if (min.instance.params) { if (min.instance.params) {
const params = JSON.parse(min.instance.params); const params = JSON.parse(min.instance.params);
return params?params['Enable Worldwide Translator'] === "TRUE": false; return params ? params['Enable Worldwide Translator'] === "TRUE" : false;
} }
return false; return false;
} // TODO: Encapsulate. } // TODO: Encapsulate.
@ -126,14 +126,35 @@ export class AskDialog extends IGBDialog {
member.name, "", "web", member.name); member.name, "", "web", member.name);
user.locale = locale; user.locale = locale;
await user.save(); await user.save();
const notTranslatedQuery = query;
query = await min.conversationalService.translate(min, query = await min.conversationalService.translate(min,
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey, min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint, min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
query, query,
'pt'); 'pt');
GBLog.info(`Translated text: ${query}.`) GBLog.info(`Translated text: ${query}.`)
return await step.replaceDialog('/answer', { query: query });
let handled = false;
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
if (await e.onExchangeData(min, "handleAnswer", {
query: query, step: step,
notTranslatedQuery: notTranslatedQuery,
message: query,
user: user['dataValues']
})) {
handled = true;
}
});
if (!handled) {
return await step.beginDialog('/answer', {
query: query
});
} else {
return await step.next();
}
} else { } else {
return await step.next(); return await step.next();
} }
@ -152,7 +173,7 @@ export class AskDialog extends IGBDialog {
const userDb = await sec.ensureUser(min.instance.instanceId, member.id, const userDb = await sec.ensureUser(min.instance.instanceId, member.id,
member.name, "", "web", member.name); member.name, "", "web", member.name);
const minBoot = GBServer.globals.minBoot as any; const minBoot = GBServer.globals.minBoot as any;
text = await min.conversationalService.translate(min, text = await min.conversationalService.translate(min,
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey, min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint, min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
text, text,
@ -209,7 +230,7 @@ export class AskDialog extends IGBDialog {
user2.isAsking = false; user2.isAsking = false;
user2.lastQuestionId = resultsB.questionId; user2.lastQuestionId = resultsB.questionId;
await min.userProfile.set(step.context, user2); await min.userProfile.set(step.context, user2);
// Informs user that a broader search will be used. // Informs user that a broader search will be used.
if (user2.subjects.length > 0) { if (user2.subjects.length > 0) {
await min.conversationalService.sendText(min, step, Messages[locale].wider_answer); await min.conversationalService.sendText(min, step, Messages[locale].wider_answer);

View file

@ -58,7 +58,7 @@ import {
GuaribasInstance, GuaribasInstance,
GuaribasPackage GuaribasPackage
} from '../../core.gbapp/models/GBModel'; } from '../../core.gbapp/models/GBModel';
import { GuaribasUser } from '../../security.gblib/models'; import { GuaribasUser } from '../../security.gbapp/models';
/** /**
* Subjects to group the pair of questions and answers. * Subjects to group the pair of questions and answers.

View file

@ -55,7 +55,7 @@ import { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from '../models';
import { Messages } from '../strings'; import { Messages } from '../strings';
import { GBConfigService } from './../../core.gbapp/services/GBConfigService'; import { GBConfigService } from './../../core.gbapp/services/GBConfigService';
import { CSService } from '../../customer-satisfaction.gbapp/services/CSService'; import { CSService } from '../../customer-satisfaction.gbapp/services/CSService';
import { SecService } from '../../security.gblib/services/SecService'; import { SecService } from '../../security.gbapp/services/SecService';
import { CollectionUtil } from 'pragmatismo-io-framework'; import { CollectionUtil } from 'pragmatismo-io-framework';
/** /**

View file

@ -0,0 +1,183 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' v `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| (˅) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
/**
* @fileoverview Main dialog for kb.gbapp
*/
'use strict';
import urlJoin = require('url-join');
import { BotAdapter, CardFactory, MessageFactory } from 'botbuilder';
import { WaterfallDialog } from 'botbuilder-dialogs';
import { GBMinInstance, IGBDialog, GBLog } from 'botlib';
import { Messages } from '../strings';
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance();
const phone = require('phone');
/**
* Dialogs for handling Menu control.
*/
export class ProfileDialog extends IGBDialog {
static getNameDialog(min: GBMinInstance) {
return {
id: '/welcome_saas_name', waterfall: [
async step => {
const locale = step.context.activity.locale;
await step.prompt("textPrompt", Messages[locale].whats_name);
},
async step => {
const locale = step.context.activity.locale;
const fullName = (text) => {
return text.match(/^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$/gi);
}
const value = fullName(step.result);
if (value === null) {
await step.context.sendActivity(Messages[locale].validation_enter_name);
await step.replaceDialog('/welcome_saas_name', step.activeDialog.state.options);
}
else {
step.activeDialog.state.options.name = value[0];
return await step.replaceDialog('/welcome_saas_mobile', step.activeDialog.state.options);
}
}]
}
}
static getMobileDialog(min: GBMinInstance) {
return {
id: '/store_mobile', waterfall: [
async step => {
const locale = step.context.activity.locale;
await step.prompt("textPrompt", Messages[locale].whats_mobile);
},
async step => {
const locale = step.context.activity.locale;
let phoneNumber;
try {
phoneNumber = phone(step.result, 'BRA')[0]; // TODO: Use accordingly to the person.
phoneNumber = phoneUtil.parse(phoneNumber);
} catch (error) {
await step.context.sendActivity(Messages[locale].validation_enter_valid_mobile);
return await step.replaceDialog('/store_mobile', step.activeDialog.state.options);
}
if (!phoneUtil.isPossibleNumber(phoneNumber)) {
await step.context.sendActivity(Messages[locale].validation_enter_valid_mobile);
return await step.replaceDialog('/store_mobile', step.activeDialog.state.options);
}
else {
step.activeDialog.state.options.mobile = `${phoneNumber.values_['1']}${phoneNumber.values_['2']}`;
step.activeDialog.state.options.mobileCode = GBAdminService.getMobileCode();
return await step.replaceDialog('/store_mobile_confirm', step.activeDialog.state.options);
}
}]
}
}
static getMobileConfirmDialog(min: GBMinInstance) {
return {
id: '/store_mobile_confirm', waterfall: [
async step => {
const locale = step.context.activity.locale;
let from = step.activeDialog.state.options.mobile;
if (min.whatsAppDirectLine) {
await min.whatsAppDirectLine.sendToDevice(from, `${step.activeDialog.state.options.mobileCode} is your General Bots creation code.`);
} else {
GBLog.info(`WhatsApp not configured. Here is the code: ${step.activeDialog.state.options.mobileCode}.`);
}
await step.prompt("textPrompt", Messages[locale].confirm_mobile);
},
async step => {
const locale = step.context.activity.locale;
if (step.result !== step.activeDialog.state.options.mobileCode) {
await step.context.sendActivity(Messages[locale].confirm_mobile_again);
return await step.replaceDialog('/store_mobile_confirm', step.activeDialog.state.options);
}
else {
await step.replaceDialog('/store_botxxxxxxxxxxxxxxxxxxxxxxxxxx', step.activeDialog.state.options);
}
}]
}
}
static getEmailDialog(min: GBMinInstance) {
return {
id: '/store_email', waterfall: [
async step => {
const locale = step.context.activity.locale;
await step.prompt("textPrompt", Messages[locale].whats_email);
},
async step => {
const locale = step.context.activity.locale;
const extractEntity = (text) => {
return text.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/gi);
}
const value = extractEntity(step.result);
if (value === null) {
await step.context.sendActivity(Messages[locale].validation_enter_valid_email);
await step.replaceDialog('/store_email', step.activeDialog.state.options);
}
else {
step.activeDialog.state.options.email = value[0];
}
}]
}
}
}

View file

@ -39,7 +39,7 @@
import urlJoin = require('url-join'); import urlJoin = require('url-join');
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib'; import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
import {ProfileDialog} from './dialogs/ProfileDialog'
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript';
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from './models'; import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from './models';
@ -49,6 +49,12 @@ import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from './models';
export class GBSecurityPackage implements IGBPackage { export class GBSecurityPackage implements IGBPackage {
public sysPackages: IGBPackage[]; public sysPackages: IGBPackage[];
public async getDialogs(min: GBMinInstance) { public async getDialogs(min: GBMinInstance) {
return [
ProfileDialog.getNameDialog(min),
ProfileDialog.getEmailDialog(min),
ProfileDialog.getMobileDialog(min),
ProfileDialog.getMobileConfirmDialog(min),
];
GBLog.verbose(`getDialogs called.`); GBLog.verbose(`getDialogs called.`);
} }
public async unloadPackage(core: IGBCoreService): Promise<void> { public async unloadPackage(core: IGBCoreService): Promise<void> {

View file

@ -0,0 +1,35 @@
export const Messages = {
'en-US': {
did_not_find: 'I\'m sorry I didn\'t find anything.',
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 =>
`Lets search for ${query}... What do you want to know?`,
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...',
ask_first_time: 'What are you looking for?'
},
'pt-BR': {
did_not_find: 'Desculpe-me, não encontrei nada a respeito.',
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 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...',
ask_first_time: 'Como eu posso ajudar?'
}
};

View file

@ -39,7 +39,7 @@ import { GBLog, GBService, GBMinInstance, IGBPackage } from 'botlib';
import * as request from 'request-promise-native'; import * as request from 'request-promise-native';
import { GBServer } from '../../../src/app'; import { GBServer } from '../../../src/app';
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService'; import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
import { SecService } from '../../security.gblib/services/SecService'; import { SecService } from '../../security.gbapp/services/SecService';
import { Messages } from '../strings'; import { Messages } from '../strings';
import { CollectionUtil } from 'pragmatismo-io-framework'; import { CollectionUtil } from 'pragmatismo-io-framework';

View file

@ -134,7 +134,7 @@ export class GBServer {
GBLog.info(`Defining server address at ${serverAddress}...`); GBLog.info(`Defining server address at ${serverAddress}...`);
GBServer.globals.publicAddress = serverAddress; GBServer.globals.publicAddress = serverAddress;
} }
// Creates a boot instance or load it from storage. // Creates a boot instance or load it from storage.
try { try {
@ -189,12 +189,12 @@ export class GBServer {
} }
GBLog.info(`The Bot Server is in RUNNING mode...`); GBLog.info(`The Bot Server is in RUNNING mode...`);
// Opens Navigator. // Opens Navigator.
// TODO: Config: core.openBrowserInDevelopment(); // TODO: Config: core.openBrowserInDevelopment();
} catch (err) { } catch (err) {
GBLog.error(`STOP: ${err} ${err.stack ? err.stack : ''}`); GBLog.error(`STOP: ${err.message ? err.message : err} ${err.stack ? err.stack : ''}`);
process.exit(1); process.exit(1);
} }
})(); })();