feat(whatsapp.gblib): Switch from Whatsapp channel which bot to talk to with the same number.
This commit is contained in:
parent
b2da413f0f
commit
cb3d241fbc
7 changed files with 147 additions and 31 deletions
|
@ -37,7 +37,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const emptyDir = require('empty-dir');
|
const rimraf = require('rimraf');
|
||||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||||
import { GBMinInstance, IGBDialog } from 'botlib';
|
import { GBMinInstance, IGBDialog } from 'botlib';
|
||||||
import urlJoin = require('url-join');
|
import urlJoin = require('url-join');
|
||||||
|
@ -83,8 +83,7 @@ export class AdminDialog extends IGBDialog {
|
||||||
await s.downloadFolder(localFolder, siteName, folderName,
|
await s.downloadFolder(localFolder, siteName, folderName,
|
||||||
GBConfigService.get('CLOUD_USERNAME'), GBConfigService.get('CLOUD_PASSWORD'))
|
GBConfigService.get('CLOUD_USERNAME'), GBConfigService.get('CLOUD_PASSWORD'))
|
||||||
await deployer.deployPackage(min, localFolder);
|
await deployer.deployPackage(min, localFolder);
|
||||||
await emptyDir(localFolder);
|
rimraf.sync(localFolder);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
70
packages/core.gbapp/dialogs/SwitchBot.ts
Normal file
70
packages/core.gbapp/dialogs/SwitchBot.ts
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*****************************************************************************\
|
||||||
|
| ( )_ _ |
|
||||||
|
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
||||||
|
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
|
||||||
|
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| (˅) |( (_) ) |
|
||||||
|
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
||||||
|
| | | ( )_) | |
|
||||||
|
| (_) \___/' |
|
||||||
|
| |
|
||||||
|
| 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 General Bots server core.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import { BotAdapter } from 'botbuilder';
|
||||||
|
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||||
|
import { GBMinInstance, IGBDialog } from 'botlib';
|
||||||
|
import { Messages } from '../strings';
|
||||||
|
import { SecService } from '../../security.gblib/services/SecService';
|
||||||
|
/**
|
||||||
|
* Dialog for the bot explains about itself.
|
||||||
|
*/
|
||||||
|
export class SwitchBotDialog extends IGBDialog {
|
||||||
|
/**
|
||||||
|
* Setup dialogs flows and define services call.
|
||||||
|
*
|
||||||
|
* @param bot The bot adapter.
|
||||||
|
* @param min The minimal bot instance data.
|
||||||
|
*/
|
||||||
|
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
||||||
|
min.dialogs.add(new WaterfallDialog('/bot', [
|
||||||
|
|
||||||
|
async step => {
|
||||||
|
const locale = step.context.activity.locale;
|
||||||
|
await step.context.sendActivity(`${min.instance.description}`);
|
||||||
|
return await step.prompt('textPrompt', "Qual seria o código de ativação?");
|
||||||
|
},
|
||||||
|
async step => {
|
||||||
|
let sec = new SecService();
|
||||||
|
let from = step.context.activity.from.id;
|
||||||
|
await sec.updateCurrentBotId(min.instance.instanceId, from, step.result);
|
||||||
|
return await step.next();
|
||||||
|
}
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,6 +41,7 @@ import { Sequelize } from 'sequelize-typescript';
|
||||||
import { WelcomeDialog } from './dialogs/WelcomeDialog';
|
import { WelcomeDialog } from './dialogs/WelcomeDialog';
|
||||||
import { WhoAmIDialog } from './dialogs/WhoAmIDialog';
|
import { WhoAmIDialog } from './dialogs/WhoAmIDialog';
|
||||||
import { GuaribasChannel, GuaribasException, GuaribasInstance, GuaribasPackage } from './models/GBModel';
|
import { GuaribasChannel, GuaribasException, GuaribasInstance, GuaribasPackage } from './models/GBModel';
|
||||||
|
import { SwitchBotDialog } from './dialogs/SwitchBot';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package for core.gbapp.
|
* Package for core.gbapp.
|
||||||
|
@ -68,5 +69,6 @@ export class GBCorePackage implements IGBPackage {
|
||||||
public loadBot(min: GBMinInstance): void {
|
public loadBot(min: GBMinInstance): void {
|
||||||
WelcomeDialog.setup(min.bot, min);
|
WelcomeDialog.setup(min.bot, min);
|
||||||
WhoAmIDialog.setup(min.bot, min);
|
WhoAmIDialog.setup(min.bot, min);
|
||||||
|
SwitchBotDialog.setup(min.bot, min);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,10 @@ export class GBConversationalService implements IGBConversationalService {
|
||||||
|
|
||||||
public async routeNLP(step: GBDialogStep, min: GBMinInstance, text: string): Promise<boolean> {
|
public async routeNLP(step: GBDialogStep, min: GBMinInstance, text: string): Promise<boolean> {
|
||||||
|
|
||||||
|
if (min.instance.nlpAppId === null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const model = new LuisRecognizer({
|
const model = new LuisRecognizer({
|
||||||
applicationId: min.instance.nlpAppId,
|
applicationId: min.instance.nlpAppId,
|
||||||
endpointKey: min.instance.nlpKey,
|
endpointKey: min.instance.nlpKey,
|
||||||
|
|
|
@ -68,6 +68,7 @@ import { Messages } from '../strings';
|
||||||
import { GBAdminPackage } from './../../admin.gbapp/index';
|
import { GBAdminPackage } from './../../admin.gbapp/index';
|
||||||
import { GBConfigService } from './GBConfigService';
|
import { GBConfigService } from './GBConfigService';
|
||||||
import { GBDeployer } from './GBDeployer';
|
import { GBDeployer } from './GBDeployer';
|
||||||
|
import { SecService } from '../../security.gblib/services/SecService';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimal service layer for a bot.
|
* Minimal service layer for a bot.
|
||||||
|
@ -127,11 +128,11 @@ export class GBMinService {
|
||||||
}
|
}
|
||||||
const url = '/webhooks/whatsapp';
|
const url = '/webhooks/whatsapp';
|
||||||
GBServer.globals.server.post(url, async (req, res) => {
|
GBServer.globals.server.post(url, async (req, res) => {
|
||||||
const text = req.body.messages[0].body;
|
const from = req.body.messages[0].chatId.split('@')[0];
|
||||||
const from = req.body.messages[0].author.split('@')[0];
|
|
||||||
const fromName = req.body.messages[0].senderName;
|
|
||||||
|
|
||||||
let botId = 'subway-prd';
|
let sec = new SecService();
|
||||||
|
let user = await sec.getUserFromPhone(from);
|
||||||
|
let botId = user.currentBotId;
|
||||||
const min = GBServer.globals.minInstances.filter(p => p.botId === botId)[0];
|
const min = GBServer.globals.minInstances.filter(p => p.botId === botId)[0];
|
||||||
(min as any).whatsAppDirectLine.received(req, res);
|
(min as any).whatsAppDirectLine.received(req, res);
|
||||||
});
|
});
|
||||||
|
@ -408,6 +409,8 @@ export class GBMinService {
|
||||||
|
|
||||||
const user = await min.userProfile.get(context, {});
|
const user = await min.userProfile.get(context, {});
|
||||||
|
|
||||||
|
// First time processing.
|
||||||
|
|
||||||
if (!user.loaded) {
|
if (!user.loaded) {
|
||||||
await min.conversationalService.sendEvent(step, 'loadInstance', {
|
await min.conversationalService.sendEvent(step, 'loadInstance', {
|
||||||
instanceId: instance.instanceId,
|
instanceId: instance.instanceId,
|
||||||
|
@ -419,6 +422,12 @@ export class GBMinService {
|
||||||
user.subjects = [];
|
user.subjects = [];
|
||||||
user.cb = undefined;
|
user.cb = undefined;
|
||||||
await min.userProfile.set(step.context, user);
|
await min.userProfile.set(step.context, user);
|
||||||
|
|
||||||
|
let sec = new SecService();
|
||||||
|
const member = context.activity.membersAdded[0];
|
||||||
|
|
||||||
|
await sec.ensureUser(instance.instanceId, member.id,
|
||||||
|
min.botId, member.id, "", "web", member.name, member.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
GBLog.info(
|
GBLog.info(
|
||||||
|
|
|
@ -81,6 +81,9 @@ export class GuaribasUser extends Model<GuaribasUser> {
|
||||||
@Column
|
@Column
|
||||||
phone: string
|
phone: string
|
||||||
|
|
||||||
|
@Column
|
||||||
|
currentBotId: string
|
||||||
|
|
||||||
@Column(DataType.TEXT)
|
@Column(DataType.TEXT)
|
||||||
@Column
|
@Column
|
||||||
conversationReference: string
|
conversationReference: string
|
||||||
|
|
|
@ -37,34 +37,36 @@ export class SecService extends GBService {
|
||||||
public async ensureUser(
|
public async ensureUser(
|
||||||
instanceId: number,
|
instanceId: number,
|
||||||
userSystemId: string,
|
userSystemId: string,
|
||||||
|
currentBotId: string,
|
||||||
userName: string,
|
userName: string,
|
||||||
address: string,
|
address: string,
|
||||||
channelName: string,
|
channelName: string,
|
||||||
displayName: string
|
displayName: string,
|
||||||
|
phone: string
|
||||||
): Promise<GuaribasUser> {
|
): Promise<GuaribasUser> {
|
||||||
return new Promise<GuaribasUser>((resolve, reject) => {
|
let user = await GuaribasUser.findOne({
|
||||||
GuaribasUser.findOne({
|
|
||||||
attributes: ['instanceId', 'internalAddress'],
|
where: {
|
||||||
where: {
|
instanceId: instanceId,
|
||||||
instanceId: instanceId,
|
userSystemId: userSystemId
|
||||||
userSystemId: userSystemId
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(user => {
|
|
||||||
if (!user) {
|
|
||||||
user = GuaribasUser.build();
|
|
||||||
}
|
|
||||||
user.userSystemId = userSystemId;
|
|
||||||
user.userName = userName;
|
|
||||||
user.displayName = displayName;
|
|
||||||
user.internalAddress = address;
|
|
||||||
user.email = userName;
|
|
||||||
user.defaultChannel = channelName;
|
|
||||||
user.save();
|
|
||||||
resolve(user);
|
|
||||||
})
|
|
||||||
.error(reject);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
user = GuaribasUser.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
user.instanceId = instanceId;
|
||||||
|
user.userSystemId = userSystemId;
|
||||||
|
user.currentBotId = currentBotId;
|
||||||
|
user.userName = userName;
|
||||||
|
user.displayName = displayName;
|
||||||
|
user.internalAddress = address;
|
||||||
|
user.email = userName;
|
||||||
|
user.phone = phone;
|
||||||
|
user.defaultChannel = channelName;
|
||||||
|
user.save();
|
||||||
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,4 +90,31 @@ export class SecService extends GBService {
|
||||||
await user.save();
|
await user.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async updateCurrentBotId(
|
||||||
|
instanceId: number,
|
||||||
|
userSystemId: string,
|
||||||
|
currentBotId: string
|
||||||
|
): Promise<GuaribasUser> {
|
||||||
|
let user = await GuaribasUser.findOne({
|
||||||
|
where: {
|
||||||
|
instanceId: instanceId,
|
||||||
|
userSystemId: userSystemId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
user.currentBotId = currentBotId;
|
||||||
|
await user.save();
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getUserFromPhone(
|
||||||
|
phone: string
|
||||||
|
): Promise<GuaribasUser> {
|
||||||
|
return await GuaribasUser.findOne({
|
||||||
|
where: {
|
||||||
|
phone: phone
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue