From 650779e363ea1ee336b5894520f706e740294c25 Mon Sep 17 00:00:00 2001 From: Rodrigo Rodriguez Date: Fri, 23 Aug 2019 02:23:00 -0300 Subject: [PATCH] feat(whatsapp.gblib): Switch from Whatsapp channel which bot to talk to with the same number. --- package-lock.json | 135 ++++++++++++------ package.json | 1 + packages/admin.gbapp/dialogs/AdminDialog.ts | 1 - packages/core.gbapp/dialogs/SwitchBot.ts | 6 +- packages/core.gbapp/services/GBDeployer.ts | 16 ++- packages/core.gbapp/services/GBMinService.ts | 17 ++- packages/kb.gbapp/services/KBService.ts | 26 ++-- .../security.gblib/services/SecService.ts | 2 +- 8 files changed, 138 insertions(+), 66 deletions(-) diff --git a/package-lock.json b/package-lock.json index a3dbce11..834c751e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1347,6 +1347,11 @@ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.1.29.tgz", "integrity": "sha1-kyRoBUXAx7HcbCWMtG8yt4R1s6w=" }, + "@types/cookiejar": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.1.tgz", + "integrity": "sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw==" + }, "@types/core-js": { "version": "0.9.46", "resolved": "https://registry.npmjs.org/@types/core-js/-/core-js-0.9.46.tgz", @@ -1397,6 +1402,11 @@ "@types/node": "*" } }, + "@types/geojson": { + "version": "7946.0.7", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz", + "integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==" + }, "@types/glob": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", @@ -1529,6 +1539,15 @@ "@types/node": "*" } }, + "@types/superagent": { + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-3.8.7.tgz", + "integrity": "sha512-9KhCkyXv268A2nZ1Wvu7rQWM+BmdYUVkycFeNnYrUL5Zwu7o8wPQ3wBfW59dDP+wuoxw0ww8YKgTNv8j/cgscA==", + "requires": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, "@types/tough-cookie": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.5.tgz", @@ -2117,6 +2136,78 @@ "resolved": "https://registry.npmjs.org/azure-search/-/azure-search-0.0.21.tgz", "integrity": "sha512-aYsBQp0Per+WqrkPAG19SYBufl5q9F6J0tRO+hh3EI0CUmum+G/yMCUKIp/tK43iXAVSvYL6lfXPUDtBnyfDxg==" }, + "azure-search-client": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/azure-search-client/-/azure-search-client-3.1.5.tgz", + "integrity": "sha512-4IDNlk9uPtDb4PLQfmESTLAwcb3O+0opO+V/qiWOdjDSOHiSaUPsFqaJ4zM/Fg4XEi+MPYRNZwlkPO6vvI3y2A==", + "requires": { + "@types/superagent": "^3.8.5", + "azure-search-types": "^1.0.10", + "superagent": "^3.8.3" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "requires": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" + } + } + } + }, + "azure-search-types": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/azure-search-types/-/azure-search-types-1.0.10.tgz", + "integrity": "sha512-RoidHgt0sIcRFXh9tlCGxEKY4oBEExw1ckhJRzgJwQCCFeGIctZJAiIXAMaNz6Jd+gYBomiRkLRPBTVk0eu+Fw==", + "requires": { + "@types/geojson": "^7946.0.4" + } + }, "azure-storage": { "version": "2.10.2", "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.2.tgz", @@ -3167,30 +3258,6 @@ "resolved": "https://registry.npmjs.org/botframework-schema/-/botframework-schema-4.4.0.tgz", "integrity": "sha512-3BWQEbArzHkw49BCdyNxqmSnLzkrL396Q0c+VcdabT3t75wV+dc4bwzSBuLfG0KW+fBjhSR4BXM8IQfnIZU0Vg==" }, - "botlib": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/botlib/-/botlib-1.2.1.tgz", - "integrity": "sha512-r9mjcag3Ttq3m6p1pewx094Os+dNLDb6rcBiTdGQMFjjeKLzqrLL3NGusYytOGyZek13TKeVciT9aU5ZQGofEQ==", - "requires": { - "async": "2.6.2", - "botbuilder": "4.4.0", - "botbuilder-ai": "4.4.0", - "botbuilder-azure": "4.4.0", - "botbuilder-choices": "4.0.0-preview1.2", - "botbuilder-dialogs": "4.4.0", - "botbuilder-prompts": "4.0.0-preview1.2", - "chrono-node": "1.3.11", - "dotenv-extended": "2.4.0", - "iconv-lite": "0.4.24", - "ms": "2.1.1", - "pragmatismo-io-framework": "1.0.19", - "reflect-metadata": "0.1.13", - "sequelize": "5.8.6", - "sequelize-typescript": "0.6.10", - "wait-until": "0.0.2", - "winston": "3.2.1" - } - }, "bottleneck": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.18.1.tgz", @@ -3596,21 +3663,6 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" }, - "chrono-node": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/chrono-node/-/chrono-node-1.3.11.tgz", - "integrity": "sha512-jDWRnY6nYvzfV3HPYBqo+tot7tcsUs9i3arGbMdI0TouPSXP2C2y/Ctp27rxKTQDi6yuTxAB2cw+Q6igGhOhdQ==", - "requires": { - "moment": "2.21.0" - }, - "dependencies": { - "moment": { - "version": "2.21.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.21.0.tgz", - "integrity": "sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ==" - } - } - }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", @@ -5178,11 +5230,6 @@ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "dev": true }, - "empty-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/empty-dir/-/empty-dir-2.0.0.tgz", - "integrity": "sha512-XAedXlNAQZxMmbllXY9cxuESlNVjZ8xd67bSIUZwbS7VoLyhlNehVN3Iy35yDTGFHKR1opBRgORkp3am0so+WQ==" - }, "enabled": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", diff --git a/package.json b/package.json index 7feb48b4..4c8b2cf5 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "azure-arm-search": "1.3.0-preview", "azure-arm-sql": "5.7.0", "azure-arm-website": "5.7.0", + "azure-search-client": "^3.1.5", "bluebird": "3.5.4", "body-parser": "1.19.0", "botbuilder": "4.4.0", diff --git a/packages/admin.gbapp/dialogs/AdminDialog.ts b/packages/admin.gbapp/dialogs/AdminDialog.ts index de76322f..adca2217 100644 --- a/packages/admin.gbapp/dialogs/AdminDialog.ts +++ b/packages/admin.gbapp/dialogs/AdminDialog.ts @@ -83,7 +83,6 @@ export class AdminDialog extends IGBDialog { await s.downloadFolder(localFolder, siteName, folderName, GBConfigService.get('CLOUD_USERNAME'), GBConfigService.get('CLOUD_PASSWORD')) await deployer.deployPackage(min, localFolder); - rimraf.sync(localFolder); } } diff --git a/packages/core.gbapp/dialogs/SwitchBot.ts b/packages/core.gbapp/dialogs/SwitchBot.ts index 36913038..37e520da 100644 --- a/packages/core.gbapp/dialogs/SwitchBot.ts +++ b/packages/core.gbapp/dialogs/SwitchBot.ts @@ -41,6 +41,7 @@ import { WaterfallDialog } from 'botbuilder-dialogs'; import { GBMinInstance, IGBDialog } from 'botlib'; import { Messages } from '../strings'; import { SecService } from '../../security.gblib/services/SecService'; +import { GBServer } from '../../../src/app'; /** * Dialog for the bot explains about itself. */ @@ -62,7 +63,10 @@ export class SwitchBotDialog extends IGBDialog { async step => { let sec = new SecService(); let from = step.context.activity.from.id; - await sec.updateCurrentBotId(min.instance.instanceId, from, step.result); + const minBoot = GBServer.globals.minInstances[0]; + await sec.updateCurrentBotId(minBoot.instance.instanceId, from, step.result); + await step.context.sendActivity(`Opa, vamos lá!`); + return await step.next(); } ])); diff --git a/packages/core.gbapp/services/GBDeployer.ts b/packages/core.gbapp/services/GBDeployer.ts index c568fac2..c5a48441 100644 --- a/packages/core.gbapp/services/GBDeployer.ts +++ b/packages/core.gbapp/services/GBDeployer.ts @@ -191,8 +191,19 @@ export class GBDeployer { } else { - console.log(GBServer.globals.bootInstance); - instance = Object.assign(instance, GBServer.globals.bootInstance); + let botId = GBConfigService.get('BOT_ID'); + let bootInstance = await this.core.loadInstance(botId); + + instance.searchHost = bootInstance.searchHost; + instance.searchIndex = bootInstance.searchIndex; + instance.searchIndexer = bootInstance.searchIndexer; + instance.searchKey = bootInstance.searchKey; + instance.whatsappServiceKey = bootInstance.whatsappServiceKey; + instance.whatsappBotKey = bootInstance.whatsappBotKey; + instance.whatsappServiceNumber = bootInstance.whatsappServiceNumber; + instance.whatsappServiceUrl = bootInstance.whatsappServiceUrl; + instance.whatsappServiceWebhookUrl = bootInstance.whatsappServiceWebhookUrl; + instance = await service.internalDeployBot( instance, accessToken, @@ -212,6 +223,7 @@ export class GBDeployer { await GBServer.globals.minService.mountBot(instance); } await this.core.saveInstance(instance); + } diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index 3b7f4fec..7c65da81 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -128,10 +128,17 @@ export class GBMinService { } const url = '/webhooks/whatsapp'; GBServer.globals.server.post(url, async (req, res) => { - const from = req.body.messages[0].chatId.split('@')[0]; - + const id = req.body.messages[0].chatId.split('@')[0]; + let sec = new SecService(); - let user = await sec.getUserFromPhone(from); + + const minBoot = GBServer.globals.minInstances[0]; + let user = await sec.getUserFromPhone(id); + if (user === null) { + user = await sec.ensureUser(minBoot.instance.instanceId, id, + minBoot.botId, id, "", "whatsapp", id, id); + } + let botId = user.currentBotId; const min = GBServer.globals.minInstances.filter(p => p.botId === botId)[0]; (min as any).whatsAppDirectLine.received(req, res); @@ -163,7 +170,7 @@ export class GBMinService { GBServer.globals.minInstances.push(min); // Install default VBA module. - //this.deployer.deployPackage(min, 'packages/default.gbdialog'); + // this.deployer.deployPackage(min, 'packages/default.gbdialog'); // Call the loadBot context.activity for all packages. this.invokeLoadBot(GBServer.globals.appPackages, GBServer.globals.sysPackages, min, GBServer.globals.server); @@ -427,7 +434,7 @@ export class GBMinService { const member = context.activity.membersAdded[0]; await sec.ensureUser(instance.instanceId, member.id, - min.botId, member.id, "", "web", member.name, member.id); + min.botId, member.id, "", "web", member.name, member.id); } GBLog.info( diff --git a/packages/kb.gbapp/services/KBService.ts b/packages/kb.gbapp/services/KBService.ts index f24f864d..b419e40f 100644 --- a/packages/kb.gbapp/services/KBService.ts +++ b/packages/kb.gbapp/services/KBService.ts @@ -43,6 +43,7 @@ const asyncPromise = require('async-promises'); const walkPromise = require('walk-promise'); // tslint:disable-next-line:newline-per-chained-call const parse = require('bluebird').promisify(require('csv-parse')); +const { SearchService } = require('azure-search-client'); import { GBDialogStep, GBLog, IGBConversationalService, IGBCoreService, IGBInstance } from 'botlib'; import { AzureSearch } from 'pragmatismo-io-framework'; @@ -169,22 +170,23 @@ export class KBService { query = `${query} ${text}`; } } - // TODO: query = `${query}&$filter=instanceId eq ${instance.instanceId}`; - + // tslint:disable:no-unsafe-any if (instance.searchKey !== null && GBConfigService.get('STORAGE_DIALECT') === 'mssql') { - const service = new AzureSearch( - instance.searchKey, - instance.searchHost, - instance.searchIndex, - instance.searchIndexer - ); - const results = await service.search(query); + const client = new SearchService(instance.searchHost.split('.')[0], instance.searchKey ); + const results = await client.indexes.use(instance.searchIndex) + .buildQuery() + .filter((f) => f.eq('instanceId', instance.instanceId)) + .search(query) + .top(1) + .executeQuery(); - if (results && results.length > 0 && results[0]['@search.score'] >= searchScore) { - const value = await this.getAnswerById(instance.instanceId, results[0].answerId); + const values = results.result.value; + + if (values && values.length > 0 && values[0]['@search.score'] >= searchScore) { + const value = await this.getAnswerById(instance.instanceId, values[0].answerId); if (value !== null) { - return Promise.resolve({ answer: value, questionId: results[0].questionId }); + return Promise.resolve({ answer: value, questionId: values[0].questionId }); } else { return Promise.resolve({ answer: undefined, questionId: 0 }); } diff --git a/packages/security.gblib/services/SecService.ts b/packages/security.gblib/services/SecService.ts index 5813fba3..0eb74aac 100644 --- a/packages/security.gblib/services/SecService.ts +++ b/packages/security.gblib/services/SecService.ts @@ -96,7 +96,7 @@ export class SecService extends GBService { currentBotId: string ): Promise { let user = await GuaribasUser.findOne({ - where: { + where: { instanceId: instanceId, userSystemId: userSystemId }