diff --git a/packages/admin.gbapp/dialogs/AdminDialog.ts b/packages/admin.gbapp/dialogs/AdminDialog.ts index 5a9b2bcd..2c4c7748 100644 --- a/packages/admin.gbapp/dialogs/AdminDialog.ts +++ b/packages/admin.gbapp/dialogs/AdminDialog.ts @@ -37,74 +37,20 @@ 'use strict'; const crypto = require('crypto'); -const rimraf = require('rimraf'); import { WaterfallDialog } from 'botbuilder-dialogs'; import { GBMinInstance, IGBDialog, GBLog } from 'botlib'; import urlJoin = require('url-join'); -import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService'; import { GBConfigService } from '../../core.gbapp/services/GBConfigService'; import { GBDeployer } from '../../core.gbapp/services/GBDeployer'; import { GBImporter } from '../../core.gbapp/services/GBImporterService'; import { Messages } from '../strings'; -import { GBSharePointService } from '../../sharepoint.gblib/services/SharePointService'; -const Path = require('path'); +import { GBAdminService } from '../services/GBAdminService'; /** * Dialogs for administration tasks. */ export class AdminDialog extends IGBDialog { - public static async undeployPackageCommand(text: any, min: GBMinInstance) { - const packageName = text.split(' ')[1]; - const importer = new GBImporter(min.core); - const deployer = new GBDeployer(min.core, importer); - 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; - } - - public static async deployPackageCommand(min: GBMinInstance, text: string, deployer: GBDeployer) { - const packageName = text.split(' ')[1]; - - if (!AdminDialog.isSharePointPath(packageName)) { - const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH'); - if (additionalPath === undefined) { - throw new Error('ADDITIONAL_DEPLOY_PATH is not set and deployPackage was called.'); - } - await deployer.deployPackage(min, urlJoin(additionalPath, packageName)); - } - else { - let s = new GBSharePointService(); - let siteName = text.split(' ')[1]; - let folderName = text.split(' ')[2]; - - let localFolder = Path.join('work', Path.basename(folderName)); - GBLog.warn(`${GBConfigService.get('CLOUD_USERNAME')} must be authorized on SharePoint related site`); - await s.downloadFolder(localFolder, siteName, folderName, - GBConfigService.get('CLOUD_USERNAME'), GBConfigService.get('CLOUD_PASSWORD')) - await deployer.deployPackage(min, localFolder); - } - } - - public static async rebuildIndexPackageCommand(min: GBMinInstance, deployer: GBDeployer) { - await deployer.rebuildIndex( - min.instance, - new AzureDeployerService(deployer).getKBSearchSchema(min.instance.searchIndex) - ); - } - - public static async syncBotServerCommand(min: GBMinInstance, deployer: GBDeployer) { - const serverName = `${min.instance.botId}-server`; - const service = await AzureDeployerService.createInstance(deployer); - service.syncBotServerRepository(min.instance.botId, serverName); - } - /** * Setup dialogs flows and define services call. * @@ -116,6 +62,7 @@ export class AdminDialog extends IGBDialog { const importer = new GBImporter(min.core); const deployer = new GBDeployer(min.core, importer); + const adminService = new GBAdminService(min.core); AdminDialog.setupSecurityDialogs(min); @@ -156,35 +103,35 @@ export class AdminDialog extends IGBDialog { if (text === 'quit') { return await step.replaceDialog('/'); } else if (cmdName === 'deployPackage') { - await AdminDialog.deployPackageCommand(min, text, deployer); + await GBAdminService.deployPackageCommand(min, text, deployer); return await step.replaceDialog('/admin', { firstRun: false }); } else if (cmdName === 'dp') { let BOT_NAME = text; let address = `https://pragmatismo.sharepoint.com/sites/bots /Shared%20Documents/Rascunho/${BOT_NAME}/${BOT_NAME}.gbai/${BOT_NAME}.gbkb`; - await AdminDialog.deployPackageCommand(min, address, deployer); + await GBAdminService.deployPackageCommand(min, address, deployer); return await step.replaceDialog('/admin', { firstRun: false }); } else if (cmdName === 'redeployPackage') { await step.context.sendActivity('The package is being *unloaded*...'); - await AdminDialog.undeployPackageCommand(text, min); + await GBAdminService.undeployPackageCommand(text, min); await step.context.sendActivity('Now, *deploying* package...'); - await AdminDialog.deployPackageCommand(min, text, deployer); + await GBAdminService.deployPackageCommand(min, text, deployer); await step.context.sendActivity('Package deployed. Just need to rebuild the index... Doing it right now.'); - await AdminDialog.rebuildIndexPackageCommand(min, deployer); + await GBAdminService.rebuildIndexPackageCommand(min, deployer); await step.context.sendActivity('Finished importing of that .gbkb package. Thanks.'); return await step.replaceDialog('/admin', { firstRun: false }); } else if (cmdName === 'undeployPackage') { await step.context.sendActivity('The package is being *undeployed*...'); - await AdminDialog.undeployPackageCommand(text, min); + await GBAdminService.undeployPackageCommand(text, min); await step.context.sendActivity('Package *undeployed*.'); return await step.replaceDialog('/admin', { firstRun: false }); } else if (cmdName === 'rebuildIndex') { - await AdminDialog.rebuildIndexPackageCommand(min, deployer); + await GBAdminService.rebuildIndexPackageCommand(min, deployer); return await step.replaceDialog('/admin', { firstRun: false }); } else if (cmdName === 'syncBotServer') { - await AdminDialog.syncBotServerCommand(min, deployer); + await GBAdminService.syncBotServerCommand(min, deployer); return await step.replaceDialog('/admin', { firstRun: false }); } else if (cmdName === 'setupSecurity') { @@ -253,7 +200,7 @@ export class AdminDialog extends IGBDialog { const locale = step.context.activity.locale; const buf = Buffer.alloc(16); const state = `${min.instance.instanceId}${crypto.randomFillSync(buf).toString('hex')}`; - + min.adminService.setValue(min.instance.instanceId, 'AntiCSRFAttackState', state); const url = `https://login.microsoftonline.com/${ diff --git a/packages/admin.gbapp/services/GBAdminService.ts b/packages/admin.gbapp/services/GBAdminService.ts index e31b7f8b..996c68af 100644 --- a/packages/admin.gbapp/services/GBAdminService.ts +++ b/packages/admin.gbapp/services/GBAdminService.ts @@ -37,12 +37,16 @@ 'use strict'; import { AuthenticationContext, TokenResponse } from 'adal-node'; -import { IGBAdminService, IGBCoreService, IGBInstance } from 'botlib'; +import { IGBAdminService, IGBCoreService, IGBInstance, GBMinInstance, GBLog, IGBDeployer } from 'botlib'; import urlJoin = require('url-join'); import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService'; import { GuaribasInstance } from '../../core.gbapp/models/GBModel'; import { GBConfigService } from '../../core.gbapp/services/GBConfigService'; import { GuaribasAdmin } from '../models/AdminModel'; +import { GBSharePointService } from '../../sharepoint.gblib/services/SharePointService'; +import { GBImporter } from '../../core.gbapp/services/GBImporterService'; +import { GBDeployer } from '../../core.gbapp/services/GBDeployer'; +const Path = require('path'); const msRestAzure = require('ms-rest-azure'); const PasswordGenerator = require('strict-password-generator').default; @@ -61,6 +65,19 @@ export class GBAdminService implements IGBAdminService { this.core = core; } + public async publish(min: GBMinInstance, packageName: string, republish: boolean) { + if (republish) { + GBLog.info('The package is being *unloaded*...'); + let packageNameOnly = Path.basename(packageName); + await GBAdminService.undeployPackageCommand(`undeployPackage ${packageNameOnly}`, min); + } + GBLog.info('Now, *deploying* package...'); + await GBAdminService.deployPackageCommand(min, `deployPackage ${packageName}`, min.deployService); + GBLog.info('Package deployed. Just need to rebuild the index... Doing it right now.'); + await GBAdminService.rebuildIndexPackageCommand(min, min.deployService); + GBLog.info('Finished importing of that .gbkb package.'); + } + public static generateUuid(): string { return msRestAzure.generateUuid(); } @@ -190,4 +207,58 @@ export class GBAdminService implements IGBAdminService { } }); } + + public static async undeployPackageCommand(text: any, min: GBMinInstance) { + const packageName = text.split(' ')[1]; + const importer = new GBImporter(min.core); + const deployer = new GBDeployer(min.core, importer); + 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; + } + + public static async deployPackageCommand(min: GBMinInstance, text: string, deployer: IGBDeployer) { + const packageName = text.split(' ')[1]; + + if (!this.isSharePointPath(packageName)) { + const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH'); + if (additionalPath === undefined) { + throw new Error('ADDITIONAL_DEPLOY_PATH is not set and deployPackage was called.'); + } + await deployer.deployPackage(min, urlJoin(additionalPath, packageName)); + } + else { + let s = new GBSharePointService(); + let siteName = text.split(' ')[1]; + let folderName = text.split(' ')[2]; + + let localFolder = Path.join('work', Path.basename(folderName)); + GBLog.warn(`${GBConfigService.get('CLOUD_USERNAME')} must be authorized on SharePoint related site`); + await s.downloadFolder(localFolder, siteName, folderName, + GBConfigService.get('CLOUD_USERNAME'), GBConfigService.get('CLOUD_PASSWORD')) + await deployer.deployPackage(min, localFolder); + } + } + + public static async rebuildIndexPackageCommand(min: GBMinInstance, deployer: IGBDeployer) { + await deployer.rebuildIndex( + min.instance, + new AzureDeployerService(deployer).getKBSearchSchema(min.instance.searchIndex) + ); + } + + public static async syncBotServerCommand(min: GBMinInstance, deployer: GBDeployer) { + const serverName = `${min.instance.botId}-server`; + const service = await AzureDeployerService.createInstance(deployer); + service.syncBotServerRepository(min.instance.botId, serverName); + } + + + } diff --git a/packages/azuredeployer.gbapp/services/AzureDeployerService.ts b/packages/azuredeployer.gbapp/services/AzureDeployerService.ts index ec60364e..adeb82b2 100644 --- a/packages/azuredeployer.gbapp/services/AzureDeployerService.ts +++ b/packages/azuredeployer.gbapp/services/AzureDeployerService.ts @@ -44,7 +44,7 @@ import { SqlManagementClient } from 'azure-arm-sql'; import { WebSiteManagementClient } from 'azure-arm-website'; //tslint:disable-next-line:no-submodule-imports import { AppServicePlan, Site, SiteConfigResource, SiteLogsConfig, SiteSourceControl } from 'azure-arm-website/lib/models'; -import { GBLog, IGBInstallationDeployer, IGBInstance } from 'botlib'; +import { GBLog, IGBInstallationDeployer, IGBInstance, IGBDeployer } from 'botlib'; import { GBAdminService } from '../../../packages/admin.gbapp/services/GBAdminService'; import { GBCorePackage } from '../../../packages/core.gbapp'; import { GBConfigService } from '../../../packages/core.gbapp/services/GBConfigService'; @@ -81,9 +81,9 @@ export class AzureDeployerService implements IGBInstallationDeployer { public location: string; public subscriptionId: string; public farmName: any; - public deployer: GBDeployer; + public deployer: IGBDeployer; - constructor(deployer: GBDeployer) { + constructor(deployer: IGBDeployer) { this.deployer = deployer; } diff --git a/packages/core.gbapp/services/GBConversationalService.ts b/packages/core.gbapp/services/GBConversationalService.ts index ee18937b..9455b9e5 100644 --- a/packages/core.gbapp/services/GBConversationalService.ts +++ b/packages/core.gbapp/services/GBConversationalService.ts @@ -86,7 +86,7 @@ export class GBConversationalService implements IGBConversationalService { mobile = step.context.activity.from.id; } const filename = url.substring(url.lastIndexOf('/') + 1); - await min.whatsAppDirectLine.sendFileToDevice(mobile, url, filename); + await min.whatsAppDirectLine.sendFileToDevice(mobile, url, filename, caption); } @@ -145,12 +145,17 @@ export class GBConversationalService implements IGBConversationalService { InImageBegin, InImageCaption, InImageAddressBegin, - InImageAddressBody + InImageAddressBody, + InEmbedBegin, + InEmbedEnd, + InEmbedAddressBegin, + InEmbedAddressEnd }; let state = State.InText; let currentImage = ''; let currentText = ''; let currentCaption = ''; + let currentEmbedUrl = ''; //![General Bots](/instance/images/gb.png) for (var i = 0; i < text.length; i++) { @@ -161,10 +166,46 @@ export class GBConversationalService implements IGBConversationalService { if (c === '!') { state = State.InImageBegin; } + else if (c === '[') { + state = State.InEmbedBegin; + } else { currentText = currentText.concat(c); } break; + case State.InEmbedBegin: + if (c === '=') { + if (currentText !== '') { + if (mobile === null) { + await step.context.sendActivity(currentText); + } + else { + this.sendToMobile(min, mobile, currentText); + } + await sleep(3000); + } + currentText = ''; + state = State.InEmbedAddressBegin; + } + + break; + case State.InEmbedAddressBegin: + if (c === ']') { + state = State.InEmbedEnd; + let url = urlJoin(GBServer.globals.publicAddress, currentEmbedUrl); + await this.sendFile(min, step, mobile, url, null); + await sleep(5000); + currentEmbedUrl = ''; + } + else{ + currentEmbedUrl = currentEmbedUrl.concat(c); + } + break; + case State.InEmbedEnd: + if (c === ']') { + state = State.InText; + } + break; case State.InImageBegin: if (c === '[') { if (currentText !== '') { diff --git a/packages/core.gbapp/services/GBDeployer.ts b/packages/core.gbapp/services/GBDeployer.ts index 946bcb4a..1de2e800 100644 --- a/packages/core.gbapp/services/GBDeployer.ts +++ b/packages/core.gbapp/services/GBDeployer.ts @@ -45,7 +45,7 @@ const child_process = require('child_process'); const graph = require('@microsoft/microsoft-graph-client'); const rimraf = require('rimraf'); -import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBInstance, IGBPackage } from 'botlib'; +import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBInstance, IGBPackage, IGBDeployer } from 'botlib'; import { AzureSearch } from 'pragmatismo-io-framework'; import { GBServer } from '../../../src/app'; import { GuaribasPackage, GuaribasInstance } from '../models/GBModel'; @@ -57,12 +57,13 @@ import { GBImporter } from './GBImporterService'; import { GBVMService } from './GBVMService'; import { CollectionUtil } from 'pragmatismo-io-framework'; + /** * * Deployer service for bots, themes, ai and more. */ -export class GBDeployer { +export class GBDeployer implements IGBDeployer{ public static deployFolder = 'packages'; public static workFolder = 'work'; public core: IGBCoreService; @@ -294,6 +295,8 @@ export class GBDeployer { done(undefined, accessToken); } }); + + // TODO: Today a download only approach is used. } public async deployPackage(min: GBMinInstance, localPath: string) { @@ -487,6 +490,7 @@ export class GBDeployer { private mountGBKBAssets(packageName: any, filename: string) { GBServer.globals.server.use(`/kb/${packageName}/subjects`, express.static(urlJoin(filename, 'subjects'))); + GBServer.globals.server.use(`/kb/${packageName}/assets`, express.static(urlJoin(filename, 'assets'))); GBServer.globals.server.use(`/kb/${packageName}/images`, express.static(urlJoin(filename, 'images'))); GBServer.globals.server.use(`/kb/${packageName}/audios`, express.static(urlJoin(filename, 'audios'))); GBLog.info(`KB (.gbkb) assets accessible at: /kb/${packageName}.`); diff --git a/packages/whatsapp.gblib/services/WhatsappDirectLine.ts b/packages/whatsapp.gblib/services/WhatsappDirectLine.ts index ced4e656..5673f440 100644 --- a/packages/whatsapp.gblib/services/WhatsappDirectLine.ts +++ b/packages/whatsapp.gblib/services/WhatsappDirectLine.ts @@ -96,8 +96,7 @@ export class WhatsappDirectLine extends GBService { }; try { - const result = request.post(options); - GBLog.info(result); + request.post(options); } catch (error) { GBLog.error(`Error initializing 3rd party Whatsapp provider(1) ${error.message}`); }