new(core.gbapp): Broadcast for msteams available.
This commit is contained in:
parent
a7712fba28
commit
01e959fa61
8 changed files with 223 additions and 49 deletions
|
@ -223,10 +223,6 @@ export class GBAdminService implements IGBAdminService {
|
|||
await deployer.undeployPackageFromLocalPath(min.instance, urlJoin(GBDeployer.workFolder, packageName));
|
||||
}
|
||||
|
||||
public static async broadcastCommand(text: any, min: GBMinInstance) {
|
||||
const packageName = text.split(' ')[1];
|
||||
}
|
||||
|
||||
public static isSharePointPath(path: string) {
|
||||
return path.indexOf('sharepoint.com') > 0;
|
||||
}
|
||||
|
|
71
packages/core.gbapp/dialogs/BroadcastDialog.ts
Normal file
71
packages/core.gbapp/dialogs/BroadcastDialog.ts
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*****************************************************************************\
|
||||
| ( )_ _ |
|
||||
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
||||
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' 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 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.gbapp/services/SecService';
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { GBConversationalService } from '../services/GBConversationalService';
|
||||
/**
|
||||
* Dialog for the bot explains about itself.
|
||||
*/
|
||||
export class BroadcastDialog 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('/gb-broadcast', [
|
||||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
return await min.conversationalService.prompt(min, step, 'Type the message and the broadcast will start.');
|
||||
},
|
||||
async step => {
|
||||
await min.conversationalService['broadcast'](min, step.result);
|
||||
return await step.next();
|
||||
}
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||
import { Sequelize } from 'sequelize-typescript';
|
||||
import { BroadcastDialog } from './dialogs/BroadcastDialog';
|
||||
import { SwitchBotDialog } from './dialogs/SwitchBot';
|
||||
import { WelcomeDialog } from './dialogs/WelcomeDialog';
|
||||
import { WhoAmIDialog } from './dialogs/WhoAmIDialog';
|
||||
|
@ -76,5 +77,6 @@ export class GBCorePackage implements IGBPackage {
|
|||
WhoAmIDialog.setup(min.bot, min);
|
||||
SwitchBotDialog.setup(min.bot, min);
|
||||
DialogClass.setup(min.bot, min);
|
||||
BroadcastDialog.setup(min.bot, min);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,9 @@ import { Readable } from 'stream';
|
|||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import { WaterfallStep, WaterfallStepContext } from 'botbuilder-dialogs';
|
||||
import { MicrosoftAppCredentials } from 'botframework-connector';
|
||||
const urlJoin = require('url-join');
|
||||
const PasswordGenerator = require('strict-password-generator').default;
|
||||
const Nexmo = require('nexmo');
|
||||
|
@ -625,4 +628,31 @@ export class GBConversationalService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async broadcast(min: GBMinInstance, message: string) {
|
||||
GBLog.info(`Sending broadcast notifications...`);
|
||||
|
||||
let sleep = ms => {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
};
|
||||
|
||||
const service = new SecService();
|
||||
const users = await service.getAllUsers(min.instance.instanceId);
|
||||
await CollectionUtil.asyncForEach(users, async user => {
|
||||
if (user.conversationReference) {
|
||||
const ref = JSON.parse(user.conversationReference);
|
||||
MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl);
|
||||
await min.bot['createConversation'](ref, async t1 => {
|
||||
const ref2 = TurnContext.getConversationReference(t1.activity);
|
||||
await min.bot.continueConversation(ref2, async t2 => {
|
||||
await t2.sendActivity(message);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
GBLog.info(`User: ${user.systemUserId} with no conversation ID while broadcasting.`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,9 +43,16 @@ const request = require('request-promise-native');
|
|||
const removeRoute = require('express-remove-route');
|
||||
const AuthenticationContext = require('adal-node').AuthenticationContext;
|
||||
const wash = require('washyourmouthoutwithsoap');
|
||||
import { AutoSaveStateMiddleware, BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } from 'botbuilder';
|
||||
import {
|
||||
AutoSaveStateMiddleware,
|
||||
BotFrameworkAdapter,
|
||||
ConversationState,
|
||||
MemoryStorage,
|
||||
TurnContext,
|
||||
UserState
|
||||
} from 'botbuilder';
|
||||
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
|
||||
import { ConfirmPrompt, WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import { ConfirmPrompt, OAuthPrompt, WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import {
|
||||
GBDialogStep,
|
||||
GBLog,
|
||||
|
@ -227,7 +234,7 @@ export class GBMinService {
|
|||
GBServer.globals.minInstances.push(min);
|
||||
|
||||
await this.deployer.deployPackage(min, 'packages/default.gbtheme');
|
||||
|
||||
|
||||
// Install per bot deployed packages.
|
||||
|
||||
let packagePath = `work/${min.botId}.gbai/${min.botId}.gbdialog`;
|
||||
|
@ -527,6 +534,14 @@ export class GBMinService {
|
|||
min.dialogs = new DialogSet(dialogState);
|
||||
min.dialogs.add(new TextPrompt('textPrompt'));
|
||||
min.dialogs.add(new ConfirmPrompt('confirmPrompt'));
|
||||
min.dialogs.add(
|
||||
new OAuthPrompt('oAuthPrompt', {
|
||||
connectionName: 'OAuth2',
|
||||
text: 'Please sign in.',
|
||||
title: 'Sign in',
|
||||
timeout: 300000
|
||||
})
|
||||
);
|
||||
|
||||
return { min, adapter, conversationState };
|
||||
}
|
||||
|
@ -582,6 +597,7 @@ export class GBMinService {
|
|||
|
||||
// First time processing.
|
||||
|
||||
const sec = new SecService();
|
||||
if (!user.loaded) {
|
||||
await min.conversationalService.sendEvent(min, step, 'loadInstance', {
|
||||
instanceId: instance.instanceId,
|
||||
|
@ -594,7 +610,6 @@ export class GBMinService {
|
|||
user.cb = undefined;
|
||||
|
||||
if (context.activity.from.id !== min.botId) {
|
||||
let sec = new SecService();
|
||||
const member = context.activity.from;
|
||||
|
||||
const persistedUser = await sec.ensureUser(
|
||||
|
@ -605,7 +620,10 @@ export class GBMinService {
|
|||
'web',
|
||||
member.name
|
||||
);
|
||||
|
||||
if (step.context.activity.channelId === "msteams"){
|
||||
persistedUser.conversationReference = JSON.stringify(TurnContext.getConversationReference(context.activity));
|
||||
await persistedUser.save();
|
||||
}
|
||||
const analytics = new AnalyticsService();
|
||||
|
||||
user.systemUser = persistedUser;
|
||||
|
|
69
packages/security.gbapp/dialogs/OAuthDialog.ts
Normal file
69
packages/security.gbapp/dialogs/OAuthDialog.ts
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*****************************************************************************\
|
||||
| ( )_ _ |
|
||||
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
||||
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' 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 Dialog for handling OAuth scenarios.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { TokenResponse } from 'botbuilder';
|
||||
import { IGBDialog, GBLog, GBMinInstance } from 'botlib';
|
||||
import { Messages } from '../strings';
|
||||
|
||||
/**
|
||||
* Dialogs for handling Menu control.
|
||||
*/
|
||||
export class OAuthDialog extends IGBDialog {
|
||||
public static getOAuthDialog(min: GBMinInstance) {
|
||||
return {
|
||||
id: '/auth',
|
||||
waterfall: [
|
||||
async step => {
|
||||
step.activeDialog.state.options = step.options;
|
||||
return await step.beginDialog('oAuthPrompt');
|
||||
},
|
||||
async step => {
|
||||
const tokenResponse: TokenResponse = step.result;
|
||||
if (tokenResponse) {
|
||||
GBLog.info('Token acquired.');
|
||||
|
||||
return await step.endDialog(tokenResponse);
|
||||
} else {
|
||||
await step.context.sendActivity('Please sign in so I can show you your profile.');
|
||||
return await step.replaceDialog('/auth');
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -42,6 +42,7 @@ import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from '
|
|||
import {ProfileDialog} from './dialogs/ProfileDialog'
|
||||
import { Sequelize } from 'sequelize-typescript';
|
||||
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from './models';
|
||||
import { OAuthDialog } from './dialogs/OAuthDialog';
|
||||
|
||||
/**
|
||||
* Package for the security module.
|
||||
|
@ -54,8 +55,9 @@ export class GBSecurityPackage implements IGBPackage {
|
|||
ProfileDialog.getEmailDialog(min),
|
||||
ProfileDialog.getMobileDialog(min),
|
||||
ProfileDialog.getMobileConfirmDialog(min),
|
||||
OAuthDialog.getOAuthDialog(min),
|
||||
];
|
||||
GBLog.verbose(`getDialogs called.`);
|
||||
|
||||
}
|
||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
||||
GBLog.verbose(`unloadPackage called.`);
|
||||
|
@ -72,8 +74,7 @@ export class GBSecurityPackage implements IGBPackage {
|
|||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
||||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||
core.sequelize.addModels([GuaribasGroup, GuaribasUser, GuaribasUserGroup]);
|
||||
}
|
||||
|
|
|
@ -6,12 +6,10 @@ import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from '../models';
|
|||
import { ConversationReference } from 'botbuilder';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
|
||||
|
||||
/**
|
||||
* Security service layer.
|
||||
*/
|
||||
export class SecService extends GBService {
|
||||
|
||||
public async importSecurityFile(localPath: string, instance: IGBInstance) {
|
||||
const security = JSON.parse(Fs.readFileSync(urlJoin(localPath, 'security.json'), 'utf8'));
|
||||
await CollectionUtil.asyncForEach(security.groups, async group => {
|
||||
|
@ -31,7 +29,6 @@ export class SecService extends GBService {
|
|||
userGroup.groupId = g1.groupId;
|
||||
userGroup.userId = user2.userId;
|
||||
await userGroup.save();
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -45,7 +42,6 @@ export class SecService extends GBService {
|
|||
displayName: string
|
||||
): Promise<GuaribasUser> {
|
||||
let user = await GuaribasUser.findOne({
|
||||
|
||||
where: {
|
||||
userSystemId: userSystemId
|
||||
}
|
||||
|
@ -85,13 +81,7 @@ export class SecService extends GBService {
|
|||
await user.save();
|
||||
}
|
||||
|
||||
public async updateUserInstance(
|
||||
userSystemId: string,
|
||||
instanceId: number
|
||||
): Promise<GuaribasUser> {
|
||||
|
||||
|
||||
|
||||
public async updateUserInstance(userSystemId: string, instanceId: number): Promise<GuaribasUser> {
|
||||
let user = await GuaribasUser.findOne({
|
||||
where: {
|
||||
userSystemId: userSystemId
|
||||
|
@ -114,7 +104,6 @@ export class SecService extends GBService {
|
|||
});
|
||||
|
||||
if (agentSystemId === null) {
|
||||
|
||||
const agent = await GuaribasUser.findOne({
|
||||
where: {
|
||||
userSystemId: user.agentSystemId
|
||||
|
@ -122,16 +111,15 @@ export class SecService extends GBService {
|
|||
});
|
||||
|
||||
if (agent !== null && agent !== undefined) {
|
||||
agent.agentMode = "bot";
|
||||
agent.agentMode = 'bot';
|
||||
agent.agentSystemId = null;
|
||||
await agent.save();
|
||||
}
|
||||
|
||||
user.agentMode = "bot";
|
||||
user.agentMode = 'bot';
|
||||
user.agentSystemId = null;
|
||||
|
||||
} else {
|
||||
user.agentMode = "human";
|
||||
user.agentMode = 'human';
|
||||
user.agentSystemId = agentSystemId;
|
||||
const agent = await GuaribasUser.findOne({
|
||||
where: {
|
||||
|
@ -140,7 +128,7 @@ export class SecService extends GBService {
|
|||
});
|
||||
|
||||
agent.instanceId = user.instanceId;
|
||||
agent.agentMode = "self";
|
||||
agent.agentMode = 'self';
|
||||
agent.agentSystemId = null;
|
||||
await agent.save();
|
||||
}
|
||||
|
@ -160,35 +148,30 @@ export class SecService extends GBService {
|
|||
throw `TRANSFER_TO phones must talk first to the bot before becoming an agent.`;
|
||||
}
|
||||
|
||||
return (user.agentMode === "self");
|
||||
return user.agentMode === 'self';
|
||||
}
|
||||
|
||||
|
||||
public async assignHumanAgent(
|
||||
userSystemId: string,
|
||||
instanceId: number
|
||||
): Promise<string> {
|
||||
|
||||
public async assignHumanAgent(userSystemId: string, instanceId: number): Promise<string> {
|
||||
let agentSystemId;
|
||||
const list = process.env.TRANSFER_TO.split(';');
|
||||
await CollectionUtil.asyncForEach(list, async item => {
|
||||
|
||||
if (!await this.isAgentSystemId(item) && item !== undefined &&
|
||||
agentSystemId === undefined && item !== userSystemId) { // TODO: Optimize loop.
|
||||
if (
|
||||
!(await this.isAgentSystemId(item)) &&
|
||||
item !== undefined &&
|
||||
agentSystemId === undefined &&
|
||||
item !== userSystemId
|
||||
) {
|
||||
// TODO: Optimize loop.
|
||||
agentSystemId = item;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
await this.updateCurrentAgent(userSystemId, instanceId, agentSystemId);
|
||||
|
||||
return agentSystemId;
|
||||
|
||||
}
|
||||
|
||||
public async getUserFromSystemId(
|
||||
systemId: string
|
||||
): Promise<GuaribasUser> {
|
||||
public async getUserFromSystemId(systemId: string): Promise<GuaribasUser> {
|
||||
return await GuaribasUser.findOne({
|
||||
where: {
|
||||
userSystemId: systemId
|
||||
|
@ -196,15 +179,19 @@ export class SecService extends GBService {
|
|||
});
|
||||
}
|
||||
|
||||
public async getUserFromAgentSystemId(
|
||||
systemId: string
|
||||
): Promise<GuaribasUser> {
|
||||
public async getUserFromAgentSystemId(systemId: string): Promise<GuaribasUser> {
|
||||
return await GuaribasUser.findOne({
|
||||
where: {
|
||||
agentSystemId: systemId,
|
||||
|
||||
agentSystemId: systemId
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async getAllUsers(instanceId: number): Promise<GuaribasUser[]> {
|
||||
return await GuaribasUser.findAll({
|
||||
where: {
|
||||
instanceId: instanceId
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue