Merge pull request #295 from GeneralBots/vm3-alpha-debugger
Vm3 alpha debugger
This commit is contained in:
commit
2e9c9f8695
91 changed files with 83185 additions and 29818 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -22,3 +22,4 @@
|
||||||
GB.log
|
GB.log
|
||||||
gb.log
|
gb.log
|
||||||
GB.log.json
|
GB.log.json
|
||||||
|
yarn-error.log
|
||||||
|
|
|
||||||
2
.vscode/launch.json.template
vendored
2
.vscode/launch.json.template
vendored
|
|
@ -6,7 +6,7 @@
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"sourceMaps": true,
|
"sourceMaps": true,
|
||||||
"name": "Debug Program",
|
"name": "Debug Program",
|
||||||
"program": "${workspaceRoot}/boot.js",
|
"program": "${workspaceRoot}/boot.mjs",
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"env": {
|
"env": {
|
||||||
"NODE_ENV": "development"
|
"NODE_ENV": "development"
|
||||||
|
|
|
||||||
|
|
@ -136,3 +136,8 @@ CREATE TABLE [dbo].[GuaribasSchedule]
|
||||||
[updatedAt] [datetimeoffset](7) NULL
|
[updatedAt] [datetimeoffset](7) NULL
|
||||||
|
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
|
||||||
|
# 3.0.0
|
||||||
|
|
||||||
|
ALTER TABLE dbo.GuaribasInstance ADD botKey nvarchar(64) NULL;
|
||||||
|
|
|
||||||
77
WARNINGS.md
Normal file
77
WARNINGS.md
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
# default.gbui
|
||||||
|
|
||||||
|
https://github.com/microsoft/BotFramework-WebChat/pull/4524
|
||||||
|
warning botframework-directlinejs > core-js@3.15.2: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
|
||||||
|
warning botframework-webchat > botframework-webchat-component > @emotion/css > @emotion/babel-plugin > @babel/plugin-syntax-jsx@7.18.6" has unmet peer dependency "@babel/core@^7.0.0-0".
|
||||||
|
warning botframework-webchat > botframework-webchat-component > @emotion/css > @emotion/babel-plugin@11.10.5" has unmet peer dependency "@babel/core@^7.0.0".
|
||||||
|
warning botframework-webchat > botframework-webchat-component > react-film > core-js@3.12.1: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
|
||||||
|
warning botframework-webchat > botframework-webchat-component > react-scroll-to-bottom > core-js@3.18.3: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
|
||||||
|
warning botframework-webchat > botframework-webchat-core > redux-devtools-extension@2.13.9: Package moved to @redux-devtools/extension.
|
||||||
|
warning botframework-webchat > microsoft-cognitiveservices-speech-sdk > asn1.js-rfc2560@5.0.1" has unmet peer dependency "asn1.js@^5.0.0".
|
||||||
|
warning botframework-webchat > web-speech-cognitive-services@7.1.2" has incorrect peer dependency "microsoft-cognitiveservices-speech-sdk@~1.17.0".
|
||||||
|
|
||||||
|
https://github.com/microsoft/powerbi-client-react
|
||||||
|
warning react-powerbi@0.9.1" has incorrect peer dependency "react@^16.8.0".
|
||||||
|
|
||||||
|
warning react-scripts > @svgr/webpack > @svgr/plugin-svgo > svgo > stable@0.1.8: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility
|
||||||
|
warning react-scripts > @svgr/webpack > @svgr/plugin-svgo > svgo@1.3.2: This SVGO version is no longer supported. Upgrade to v2.x.x.
|
||||||
|
warning react-scripts > css-minimizer-webpack-plugin > cssnano > cssnano-preset-default > postcss-svgo > svgo > stable@0.1.8: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility
|
||||||
|
warning react-scripts > eslint-config-react-app > @typescript-eslint/eslint-plugin > tsutils@3.21.0" has unmet peer dependency "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta".
|
||||||
|
warning react-scripts > eslint-config-react-app > eslint-plugin-flowtype@8.0.3" has unmet peer dependency "@babel/plugin-syntax-flow@^7.14.5".
|
||||||
|
warning react-scripts > eslint-config-react-app > eslint-plugin-flowtype@8.0.3" has unmet peer dependency "@babel/plugin-transform-react-jsx@^7.14.9".
|
||||||
|
warning react-scripts > jest > @jest/core > jest-config > jest-environment-jsdom > jsdom > w3c-hr-time@1.0.2: Use your platform's native performance.now() and performance.timeOrigin.
|
||||||
|
warning react-scripts > react-dev-utils > fork-ts-checker-webpack-plugin@6.5.2" has unmet peer dependency "typescript@>= 2.7".
|
||||||
|
|
||||||
|
# BotServer
|
||||||
|
|
||||||
|
nodejs/node-gyp#2756
|
||||||
|
warning npm > node-gyp > make-fetch-happen > cacache > @npmcli/move-file@2.0.1: This functionality has been moved to @npmcli/fs
|
||||||
|
|
||||||
|
vasyas/typescript-rest-rpc#20
|
||||||
|
warning typescript-rest-rpc > ts-morph > globby > fast-glob > micromatch > snapdragon > source-map-resolve@0.5.3: See https://github.com/lydell/source-map-resolve#deprecated
|
||||||
|
|
||||||
|
#279
|
||||||
|
warning tslint@6.1.3: TSLint has been deprecated in favor of ESLint. Please see palantir/tslint#4534 for more information.
|
||||||
|
|
||||||
|
AlaSQL/alasql#1541
|
||||||
|
warning alasql > request@2.88.2: request has been deprecated, see request/request#3142
|
||||||
|
|
||||||
|
#281
|
||||||
|
warning c3-chart-maker > data-forge > promised-mongo > mongodb-core > bson@0.4.23: Fixed a critical issue with BSON serialization documented in CVE-2019-2391, see https://bit.ly/2KcpXdo for more details
|
||||||
|
|
||||||
|
#280
|
||||||
|
warning swagger-client > url > querystring@0.2.0: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
|
||||||
|
|
||||||
|
bahmutov/ggit#157
|
||||||
|
warning ban-sensitive-files > ggit > debug@3.2.6: Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (debug-js/debug#797)
|
||||||
|
|
||||||
|
#283
|
||||||
|
warning nexmo > uuid@2.0.3: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
|
||||||
|
|
||||||
|
https://github.com/microsoft/botbuilder-js/issues/4370
|
||||||
|
warning botbuilder-ai > @azure/cognitiveservices-luis-runtime > @azure/ms-rest-js > uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
|
||||||
|
|
||||||
|
https://github.com/Azure/azure-sdk-for-node/issues/5221
|
||||||
|
warning ms-rest-azure > request@2.88.2: request has been deprecated, see request/request#3142
|
||||||
|
|
||||||
|
https://github.com/MontassarLaribi/ssr-for-bots/issues/1
|
||||||
|
warning ssr-for-bots > tslint@6.1.3: TSLint has been deprecated in favor of ESLint. Please see palantir/tslint#4534 for more information.
|
||||||
|
|
||||||
|
https://github.com/vasyas/typescript-rest-rpc/issues/20
|
||||||
|
warning typescript-rest-rpc > ts-morph > globby > fast-glob > micromatch > snapdragon > source-map-resolve > urix@0.1.0: Please see https://github.com/lydell/urix#deprecated
|
||||||
|
|
||||||
|
https://github.com/ash-developer/winston-logs-display/issues/8
|
||||||
|
warning winston-logs-display > jade > transformers@2.1.0: Deprecated, use jstransformer
|
||||||
|
|
||||||
|
https://github.com/softwarescales/git-issues/issues/29
|
||||||
|
warning git-issues > request@2.88.2: request has been deprecated, see request/request#3142
|
||||||
|
|
||||||
|
https://github.com/GeneralBots/BotServer/issues/284
|
||||||
|
warning license-checker > read-installed > readdir-scoped-modules@1.1.0: This functionality has been moved to @npmcli/fs
|
||||||
|
|
||||||
|
https://github.com/semantic-release/semantic-release/issues/1260
|
||||||
|
warning semantic-release > @semantic-release/npm > npm > readdir-scoped-modules@1.1.0: This functionality has been moved to @npmcli/fs
|
||||||
|
|
||||||
|
https://github.com/GeneralBots/BotServer/issues/277
|
||||||
|
warning travis-deploy-once@3.3.0: We recommend to use Travis Build Stages instead
|
||||||
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
const Fs = require('fs');
|
import Fs from 'fs';
|
||||||
const Path = require('path');
|
import Path from 'path';
|
||||||
const { exec } = require('child_process');
|
import { exec } from 'child_process';
|
||||||
var pjson = require('./package.json');
|
import pjson from './package.json' assert { type: "json" };
|
||||||
|
import * as GBServer from "./dist/src/app.js";
|
||||||
|
|
||||||
// Displays version of Node JS being used at runtime and others attributes.
|
// Displays version of Node JS being used at runtime and others attributes.
|
||||||
|
|
||||||
|
|
@ -19,15 +20,14 @@ console.log(`[GB Runtime] debugPort = ${process.debugPort}`);
|
||||||
var now = () => {
|
var now = () => {
|
||||||
return (new Date()).toISOString().replace(/T/, ' ').replace(/\..+/, '') + ' UTC';
|
return (new Date()).toISOString().replace(/T/, ' ').replace(/\..+/, '') + ' UTC';
|
||||||
}
|
}
|
||||||
|
var __dirname = process.env.PWD;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
var run = () => {
|
var run = () => {
|
||||||
|
|
||||||
console.log(`[GB Runtime] Initializing General Bots (BotServer)...`);
|
console.log(`[GB Runtime] Initializing General Bots (BotServer)...`);
|
||||||
const GBServer = require("./dist/src/app").GBServer
|
console.log(`[GB Runtime] ${now()} - Running on '${import.meta.url}'`);
|
||||||
console.log(`[GB Runtime] ${now()} - Running '${GBServer.name}' on '${__dirname}' directory`);
|
GBServer.GBServer.run();
|
||||||
process.env.PWD = __dirname;
|
|
||||||
GBServer.run();
|
|
||||||
}
|
}
|
||||||
var processDist = () => {
|
var processDist = () => {
|
||||||
if (!Fs.existsSync('dist')) {
|
if (!Fs.existsSync('dist')) {
|
||||||
2
gbot.cmd
2
gbot.cmd
|
|
@ -12,4 +12,4 @@ ECHO Compiling...
|
||||||
CALL node_modules\.bin\tsc
|
CALL node_modules\.bin\tsc
|
||||||
|
|
||||||
:ALLSET
|
:ALLSET
|
||||||
node boot.js
|
node boot.cjs
|
||||||
|
|
|
||||||
53651
package-lock.json
generated
53651
package-lock.json
generated
File diff suppressed because it is too large
Load diff
199
package.json
199
package.json
|
|
@ -1,8 +1,9 @@
|
||||||
{
|
{
|
||||||
"name": "botserver",
|
"name": "botserver",
|
||||||
"version": "2.0.179",
|
"version": "3.0.0",
|
||||||
|
"type": "module",
|
||||||
"description": "General Bot Community Edition open-core server.",
|
"description": "General Bot Community Edition open-core server.",
|
||||||
"main": "./boot.js",
|
"main": "./boot.mjs",
|
||||||
"bugs": "https://github.com/pragmatismo-io/BotServer/issues",
|
"bugs": "https://github.com/pragmatismo-io/BotServer/issues",
|
||||||
"homepage": "https://github.com/pragmatismo-io/BotServer/#readme",
|
"homepage": "https://github.com/pragmatismo-io/BotServer/#readme",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
|
|
@ -13,13 +14,13 @@
|
||||||
"Dário Vieira <dario.junior3@gmail.com>"
|
"Dário Vieira <dario.junior3@gmail.com>"
|
||||||
],
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "=14.19.3"
|
"node": "=19.1.0"
|
||||||
},
|
},
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"preferGlobal": true,
|
"preferGlobal": true,
|
||||||
"private": false,
|
"private": false,
|
||||||
"bin": {
|
"bin": {
|
||||||
"gbot": "./boot.js"
|
"gbot": "./boot.cjs"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -33,7 +34,7 @@
|
||||||
"build-gbui": "cd packages/default.gbui && echo SKIP_PREFLIGHT_CHECK=true >.env && npm install && npm run build",
|
"build-gbui": "cd packages/default.gbui && echo SKIP_PREFLIGHT_CHECK=true >.env && npm install && npm run build",
|
||||||
"build-docs": "typedoc --options typedoc.json src/",
|
"build-docs": "typedoc --options typedoc.json src/",
|
||||||
"test": "node test.js",
|
"test": "node test.js",
|
||||||
"start": "node ./boot.js",
|
"start": "node ./boot.cjs",
|
||||||
"reverse-proxy": "node_modules/.bin/ngrok http 4242",
|
"reverse-proxy": "node_modules/.bin/ngrok http 4242",
|
||||||
"watch:build": "tsc --watch",
|
"watch:build": "tsc --watch",
|
||||||
"posttypedoc": "shx cp .nojekyll docs/reference/.nojekyll",
|
"posttypedoc": "shx cp .nojekyll docs/reference/.nojekyll",
|
||||||
|
|
@ -49,131 +50,129 @@
|
||||||
"commit": "git-cz"
|
"commit": "git-cz"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/cognitiveservices-computervision": "8.1.0",
|
"@azure/cognitiveservices-computervision": "8.2.0",
|
||||||
"@azure/ms-rest-js": "2.5.1",
|
"@azure/keyvault-keys": "4.6.0",
|
||||||
"@google-cloud/pubsub": "2.13.0",
|
"@azure/ms-rest-js": "2.6.2",
|
||||||
"@google-cloud/translate": "6.2.6",
|
"@azure/msal-node": "1.14.3",
|
||||||
"@hubspot/api-client": "5.0.0",
|
"@azure/search-documents": "^11.3.1",
|
||||||
"@microsoft/microsoft-graph-client": "2.2.1",
|
"@google-cloud/pubsub": "3.2.1",
|
||||||
"@semantic-release/changelog": "5.0.1",
|
"@google-cloud/translate": "7.0.4",
|
||||||
"@semantic-release/exec": "5.0.0",
|
"@hubspot/api-client": "7.1.2",
|
||||||
"@semantic-release/git": "9.0.0",
|
"@microsoft/microsoft-graph-client": "3.0.4",
|
||||||
"@sendgrid/mail": "7.4.4",
|
"@nosferatu500/textract": "3.1.2",
|
||||||
"@types/node": "8.0.0",
|
"@semantic-release/changelog": "6.0.1",
|
||||||
"@types/validator": "13.1.4",
|
"@semantic-release/exec": "6.0.3",
|
||||||
"adal-node": "0.2.2",
|
"@semantic-release/git": "10.0.1",
|
||||||
"adm-zip": "0.5.6",
|
"@sendgrid/mail": "7.7.0",
|
||||||
"alasql": "^1.7.3",
|
"@types/node": "18.11.9",
|
||||||
|
"@types/validator": "13.7.10",
|
||||||
|
"adm-zip": "0.5.9",
|
||||||
|
"alasql": "2.1.6",
|
||||||
"any-shell-escape": "0.1.1",
|
"any-shell-escape": "0.1.1",
|
||||||
"async-promises": "0.2.3",
|
"async-promises": "0.2.3",
|
||||||
"azure-arm-cognitiveservices": "3.0.0",
|
|
||||||
"azure-arm-resource": "7.4.0",
|
|
||||||
"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",
|
|
||||||
"basic-auth": "2.0.1",
|
"basic-auth": "2.0.1",
|
||||||
"billboard.js": "^3.4.1",
|
"billboard.js": "3.6.3",
|
||||||
"bluebird": "3.7.2",
|
"bluebird": "3.7.2",
|
||||||
"body-parser": "1.19.0",
|
"body-parser": "1.20.1",
|
||||||
"botbuilder": "4.11.0",
|
"botbuilder": "4.18.0",
|
||||||
"botbuilder-adapter-facebook": "1.0.11",
|
"botbuilder-adapter-facebook": "1.0.12",
|
||||||
"botbuilder-ai": "4.11.0",
|
"botbuilder-ai": "4.18.0",
|
||||||
"botbuilder-dialogs": "4.11.0",
|
"botbuilder-dialogs": "4.18.0",
|
||||||
"botframework-connector": "4.11.0",
|
"botframework-connector": "4.18.0",
|
||||||
"botlib": "1.10.9",
|
"botlib": "3.0.0",
|
||||||
"c3-chart-maker": "^0.2.8",
|
"c3-chart-maker": "0.2.8",
|
||||||
"cli-progress": "^3.11.2",
|
"chrome-remote-interface": "0.31.3",
|
||||||
|
"cli-progress": "3.11.2",
|
||||||
"cli-spinner": "0.2.10",
|
"cli-spinner": "0.2.10",
|
||||||
"core-js": "3.14.0",
|
"core-js": "3.26.1",
|
||||||
"data-forge": "^1.9.5",
|
"data-forge": "1.9.6",
|
||||||
"date-diff": "0.2.2",
|
"date-diff": "1.0.2",
|
||||||
"docxtemplater": "^3.31.1",
|
"docxtemplater": "3.32.4",
|
||||||
"dotenv-extended": "2.9.0",
|
"dotenv-extended": "2.9.0",
|
||||||
"exceljs": "4.2.1",
|
"exceljs": "4.3.0",
|
||||||
"express": "4.17.1",
|
"express": "4.18.2",
|
||||||
"express-remove-route": "1.0.0",
|
"express-remove-route": "1.0.0",
|
||||||
"ffmpeg-static": "4.3.0",
|
"ffmpeg-static": "5.1.0",
|
||||||
"google-libphonenumber": "3.2.21",
|
"google-libphonenumber": "3.2.31",
|
||||||
"googleapis": "75.0.0",
|
"googleapis": "109.0.1",
|
||||||
"ibm-watson": "6.1.1",
|
"ibm-watson": "7.1.2",
|
||||||
"js-beautify": "1.13.13",
|
"indent.js": "0.3.5",
|
||||||
"keyv": "^4.5.0",
|
"js-beautify": "1.14.7",
|
||||||
"lodash": "^4.17.21",
|
"keyv": "4.5.2",
|
||||||
"luxon": "2.0.2",
|
"koa": "2.13.4",
|
||||||
"mammoth": "^1.4.21",
|
"koa-body": "6.0.1",
|
||||||
"marked": "2.0.7",
|
"koa-router": "12.0.0",
|
||||||
"momentjs": "2.0.0",
|
"lodash": "4.17.21",
|
||||||
"ms-rest-azure": "3.0.0",
|
"luxon": "3.1.0",
|
||||||
|
"mammoth": "1.5.1",
|
||||||
|
"marked": "4.2.2",
|
||||||
|
"moment": "1.3.0",
|
||||||
|
"ms-rest-azure": "3.0.2",
|
||||||
"nexmo": "2.9.1",
|
"nexmo": "2.9.1",
|
||||||
"node-cron": "3.0.0",
|
"node-cron": "3.0.2",
|
||||||
"node-nlp": "^3.10.2",
|
"node-nlp": "^4.24.0",
|
||||||
"node-tesseract-ocr": "^2.2.1",
|
"node-tesseract-ocr": "2.2.1",
|
||||||
"npm": "7.21.0",
|
"npm": "9.1.2",
|
||||||
"opn": "6.0.0",
|
"open": "8.4.0",
|
||||||
"pdf-extraction": "1.0.2",
|
"pdf-extraction": "1.0.2",
|
||||||
"pdfkit": "^0.13.0",
|
"pdfkit": "0.13.0",
|
||||||
"phone": "2.4.21",
|
"phone": "3.1.30",
|
||||||
"pizzip": "^3.0.6",
|
"pizzip": "3.1.3",
|
||||||
"pptxtemplater": "1.0.5",
|
"pptxtemplater": "1.0.5",
|
||||||
"pragmatismo-io-framework": "1.0.20",
|
"pragmatismo-io-framework": "1.0.20",
|
||||||
"prism-media": "1.3.1",
|
"prism-media": "1.3.4",
|
||||||
"public-ip": "4.0.4",
|
"public-ip": "6.0.1",
|
||||||
"puppeteer": "13.7.0",
|
"punycode": "2.1.1",
|
||||||
"puppeteer-extra": "^3.3.4",
|
"puppeteer": "19.2.2",
|
||||||
"puppeteer-extra-plugin-stealth": "2.4.5",
|
"puppeteer-extra": "3.3.4",
|
||||||
"qrcode": "^1.5.0",
|
"puppeteer-extra-plugin-stealth": "2.11.1",
|
||||||
|
"qrcode": "1.5.1",
|
||||||
"qrcode-terminal": "0.12.0",
|
"qrcode-terminal": "0.12.0",
|
||||||
"readline": "1.3.0",
|
"readline": "1.3.0",
|
||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.1.13",
|
||||||
"request-promise": "4.2.5",
|
|
||||||
"request-promise-native": "1.0.8",
|
|
||||||
"rimraf": "3.0.2",
|
"rimraf": "3.0.2",
|
||||||
"safe-buffer": "5.2.1",
|
"safe-buffer": "5.2.1",
|
||||||
"scanf": "1.1.2",
|
"scanf": "1.1.2",
|
||||||
"sequelize": "6.5.0",
|
"sequelize": "6.25.7",
|
||||||
"sequelize-cli": "6.2.0",
|
"sequelize-cli": "6.5.2",
|
||||||
"sequelize-typescript": "2.1.0",
|
"sequelize-typescript": "2.1.5",
|
||||||
"simple-git": "2.39.1",
|
"simple-git": "3.15.0",
|
||||||
"speakingurl": "14.0.1",
|
"speakingurl": "14.0.1",
|
||||||
"sppull": "2.7.0",
|
|
||||||
"ssr-for-bots": "1.0.1-c",
|
"ssr-for-bots": "1.0.1-c",
|
||||||
"strict-password-generator": "1.1.2",
|
"strict-password-generator": "1.1.2",
|
||||||
"swagger-client": "2.1.18",
|
"swagger-client": "^3.18.5",
|
||||||
"tabulator-tables": "^5.2.6",
|
"tabulator-tables": "5.4.2",
|
||||||
"tedious": "14.0.0",
|
"tedious": "15.1.2",
|
||||||
"textract": "2.5.0",
|
"twitter-api-v2": "1.12.9",
|
||||||
"twitter-api-v2": "1.12.7",
|
"typescript": "4.9.3",
|
||||||
"typescript": "3.6.4",
|
"typescript-rest-rpc": "^1.0.7",
|
||||||
"url-join": "4.0.1",
|
"url-join": "5.0.0",
|
||||||
"vbscript-to-typescript": "1.0.8",
|
"vbscript-to-typescript": "1.0.8",
|
||||||
"vhost": "^3.0.2",
|
"vhost": "3.0.2",
|
||||||
"vm2": "^3.9.11",
|
"vm2": "3.9.11",
|
||||||
|
"vm2-process": "2.1.1",
|
||||||
"walk-promise": "0.2.0",
|
"walk-promise": "0.2.0",
|
||||||
"washyourmouthoutwithsoap": "1.0.2",
|
"washyourmouthoutwithsoap": "1.0.2",
|
||||||
"whatsapp-web.js": "github:pedroslopez/whatsapp-web.js#fix-buttons-list",
|
"whatsapp-web.js": "1.18.3",
|
||||||
"winston": "^2.4.2",
|
"winston": "3.8.2",
|
||||||
"winston-logs-display": "^1.0.0",
|
"winston-logs-display": "^1.0.0",
|
||||||
"yarn": "^1.22.19"
|
"yarn": "^1.22.19"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/puppeteer": "5.4.6",
|
"@types/url-join": "4.0.1",
|
||||||
"@types/url-join": "4.0.0",
|
"ban-sensitive-files": "1.9.18",
|
||||||
"@types/winston": "2.4.4",
|
"commitizen": "4.2.5",
|
||||||
"ban-sensitive-files": "1.9.15",
|
|
||||||
"commitizen": "4.2.4",
|
|
||||||
"cz-conventional-changelog": "3.3.0",
|
"cz-conventional-changelog": "3.3.0",
|
||||||
"dependency-check": "4.1.0",
|
"dependency-check": "4.1.0",
|
||||||
"git-issues": "1.3.1",
|
"git-issues": "^1.0.0",
|
||||||
"license-checker": "25.0.1",
|
"license-checker": "25.0.1",
|
||||||
"ngrok": "4.0.1",
|
"ngrok": "4.3.3",
|
||||||
"nsp": "3.2.1",
|
"prettier-standard": "^15.0.1",
|
||||||
"prettier-standard": "16.4.1",
|
"semantic-release": "19.0.5",
|
||||||
"semantic-release": "17.4.3",
|
"simple-commit-message": "^1.1.0",
|
||||||
"simple-commit-message": "4.1.2",
|
"travis-deploy-once": "^3.0.0",
|
||||||
"travis-deploy-once": "5.0.11",
|
"ts-node": "10.9.1",
|
||||||
"ts-node": "10.0.0",
|
"tslint": "6.1.3"
|
||||||
"tslint": "6.1.2"
|
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"env": {
|
"env": {
|
||||||
|
|
|
||||||
|
|
@ -36,25 +36,25 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const crypto = require('crypto');
|
import crypto from 'crypto';
|
||||||
|
import urlJoin from 'url-join';
|
||||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||||
import { GBMinInstance, IGBDialog, GBLog, IGBPackage } from 'botlib';
|
import { GBMinInstance, IGBDialog, GBLog, IGBPackage } from 'botlib';
|
||||||
const urlJoin = require('url-join');
|
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
|
||||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
|
import { GBImporter } from '../../core.gbapp/services/GBImporterService.js';
|
||||||
import { GBImporter } from '../../core.gbapp/services/GBImporterService';
|
import { Messages } from '../strings.js';
|
||||||
import { Messages } from '../strings';
|
import { GBAdminService } from '../services/GBAdminService.js';
|
||||||
import { GBAdminService } from '../services/GBAdminService';
|
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialogs for administration tasks.
|
* Dialogs for administration tasks.
|
||||||
*/
|
*/
|
||||||
export class AdminDialog extends IGBDialog {
|
export class AdminDialog extends IGBDialog {
|
||||||
public static isIntentYes(locale, utterance) {
|
public static isIntentYes (locale, utterance) {
|
||||||
return utterance.toLowerCase().match(Messages[locale].affirmative_sentences);
|
return utterance.toLowerCase().match(Messages[locale].affirmative_sentences);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static isIntentNo(locale, utterance) {
|
public static isIntentNo (locale, utterance) {
|
||||||
return utterance.toLowerCase().match(Messages[locale].negative_sentences);
|
return utterance.toLowerCase().match(Messages[locale].negative_sentences);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,7 +64,7 @@ export class AdminDialog extends IGBDialog {
|
||||||
* @param bot The bot adapter.
|
* @param bot The bot adapter.
|
||||||
* @param min The minimal bot instance data.
|
* @param min The minimal bot instance data.
|
||||||
*/
|
*/
|
||||||
public static setup(min: GBMinInstance) {
|
public static setup (min: GBMinInstance) {
|
||||||
// Setup services.
|
// Setup services.
|
||||||
|
|
||||||
const importer = new GBImporter(min.core);
|
const importer = new GBImporter(min.core);
|
||||||
|
|
@ -77,8 +77,7 @@ export class AdminDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -109,8 +108,7 @@ export class AdminDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -200,8 +198,7 @@ export class AdminDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -237,17 +234,15 @@ export class AdminDialog extends IGBDialog {
|
||||||
min.dialogs.add(
|
min.dialogs.add(
|
||||||
new WaterfallDialog('/publish', [
|
new WaterfallDialog('/publish', [
|
||||||
async step => {
|
async step => {
|
||||||
|
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async step => {
|
async step => {
|
||||||
if (step.activeDialog.state.options.confirm || process.env.ADMIN_OPEN_PUBLISH === "true") {
|
if (step.activeDialog.state.options.confirm || process.env.ADMIN_OPEN_PUBLISH === 'true') {
|
||||||
return await step.next('sim');
|
return await step.next('sim');
|
||||||
} else {
|
} else {
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
|
|
@ -266,7 +261,7 @@ export class AdminDialog extends IGBDialog {
|
||||||
if (step.activeDialog.state.options.firstTime) {
|
if (step.activeDialog.state.options.firstTime) {
|
||||||
canPublish = true;
|
canPublish = true;
|
||||||
} else {
|
} else {
|
||||||
canPublish = AdminDialog.canPublish(min, from) || process.env.ADMIN_OPEN_PUBLISH === "true";
|
canPublish = AdminDialog.canPublish(min, from) || process.env.ADMIN_OPEN_PUBLISH === 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!canPublish) {
|
if (!canPublish) {
|
||||||
|
|
@ -313,11 +308,14 @@ export class AdminDialog extends IGBDialog {
|
||||||
try {
|
try {
|
||||||
let cmd1;
|
let cmd1;
|
||||||
if (packageName.indexOf('.') !== -1) {
|
if (packageName.indexOf('.') !== -1) {
|
||||||
cmd1 = `deployPackage ${process.env.STORAGE_SITE} /${process.env.STORAGE_LIBRARY}/${botId}.gbai/${packageName}`;
|
cmd1 = `deployPackage ${process.env.STORAGE_SITE} /${
|
||||||
|
process.env.STORAGE_LIBRARY
|
||||||
|
}/${botId}.gbai/${packageName}`;
|
||||||
} else {
|
} else {
|
||||||
cmd1 = `deployPackage ${packageName}`;
|
cmd1 = `deployPackage ${packageName}`;
|
||||||
}
|
}
|
||||||
if ((await (deployer as any).getStoragePackageByName(min.instance.instanceId, packageName)) !== null &&
|
if (
|
||||||
|
(await (deployer as any).getStoragePackageByName(min.instance.instanceId, packageName)) !== null &&
|
||||||
!process.env.DONT_DOWNLOAD
|
!process.env.DONT_DOWNLOAD
|
||||||
) {
|
) {
|
||||||
const cmd2 = `undeployPackage ${packageName}`;
|
const cmd2 = `undeployPackage ${packageName}`;
|
||||||
|
|
@ -350,12 +348,11 @@ export class AdminDialog extends IGBDialog {
|
||||||
* the /broadcast command with specific phone numbers.
|
* the /broadcast command with specific phone numbers.
|
||||||
* @param phone Phone number to check (eg.: +5521900002233)
|
* @param phone Phone number to check (eg.: +5521900002233)
|
||||||
*/
|
*/
|
||||||
public static canPublish(min: GBMinInstance, phone: string): Boolean {
|
public static canPublish (min: GBMinInstance, phone: string): Boolean {
|
||||||
if (process.env.SECURITY_CAN_PUBLISH !== undefined) {
|
if (process.env.SECURITY_CAN_PUBLISH !== undefined) {
|
||||||
let list = process.env.SECURITY_CAN_PUBLISH.split(';');
|
let list = process.env.SECURITY_CAN_PUBLISH.split(';');
|
||||||
|
|
||||||
const canPublish =
|
const canPublish = min.core.getParam(min.instance, 'Can Publish', null);
|
||||||
min.core.getParam(min.instance, 'Can Publish', null);
|
|
||||||
if (canPublish) {
|
if (canPublish) {
|
||||||
list = list.concat(canPublish.split(';'));
|
list = list.concat(canPublish.split(';'));
|
||||||
}
|
}
|
||||||
|
|
@ -370,14 +367,13 @@ export class AdminDialog extends IGBDialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static setupSecurityDialogs(min: GBMinInstance) {
|
private static setupSecurityDialogs (min: GBMinInstance) {
|
||||||
min.dialogs.add(
|
min.dialogs.add(
|
||||||
new WaterfallDialog('/setupSecurity', [
|
new WaterfallDialog('/setupSecurity', [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -398,10 +394,8 @@ export class AdminDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
step.activeDialog.state.authenticatorAuthorityHostUrl = step.result;
|
step.activeDialog.state.authenticatorAuthorityHostUrl = step.result;
|
||||||
|
|
||||||
min.instance.authenticatorTenant =
|
min.instance.authenticatorTenant = step.activeDialog.state.authenticatorTenant;
|
||||||
step.activeDialog.state.authenticatorTenant;
|
min.instance.authenticatorAuthorityHostUrl = step.activeDialog.state.authenticatorAuthorityHostUrl;
|
||||||
min.instance.authenticatorAuthorityHostUrl =
|
|
||||||
step.activeDialog.state.authenticatorAuthorityHostUrl;
|
|
||||||
|
|
||||||
await min.adminService.updateSecurityInfo(
|
await min.adminService.updateSecurityInfo(
|
||||||
min.instance.instanceId,
|
min.instance.instanceId,
|
||||||
|
|
@ -415,15 +409,12 @@ export class AdminDialog extends IGBDialog {
|
||||||
|
|
||||||
min.adminService.setValue(min.instance.instanceId, 'AntiCSRFAttackState', state);
|
min.adminService.setValue(min.instance.instanceId, 'AntiCSRFAttackState', state);
|
||||||
|
|
||||||
const redirectUri = urlJoin(
|
const redirectUri = urlJoin(min.instance.botEndpoint, min.instance.botId, '/token');
|
||||||
min.instance.botEndpoint,
|
const url = `https://login.microsoftonline.com/${
|
||||||
min.instance.botId,
|
step.activeDialog.state.authenticatorTenant
|
||||||
'/token'
|
}/oauth2/authorize?client_id=${
|
||||||
);
|
min.instance.marketplaceId
|
||||||
const url = `https://login.microsoftonline.com/${step.activeDialog.state.authenticatorTenant
|
}&response_type=code&redirect_uri=${redirectUri}&scope=https://graph.microsoft.com/.default&state=${state}&response_mode=query`;
|
||||||
}/oauth2/authorize?client_id=${min.instance.marketplaceId
|
|
||||||
}&response_type=code&redirect_uri=${redirectUri
|
|
||||||
}&scope=https://graph.microsoft.com/.default&state=${state}&response_mode=query`;
|
|
||||||
|
|
||||||
await min.conversationalService.sendText(min, step, Messages[locale].consent(url));
|
await min.conversationalService.sendText(min, step, Messages[locale].consent(url));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@
|
||||||
|
|
||||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||||
import { Sequelize } from 'sequelize-typescript';
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
import { AdminDialog } from './dialogs/AdminDialog';
|
import { AdminDialog } from './dialogs/AdminDialog.js';
|
||||||
import { GuaribasAdmin } from './models/AdminModel';
|
import { GuaribasAdmin } from './models/AdminModel.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The package for admin.gbapp.
|
* The package for admin.gbapp.
|
||||||
|
|
@ -47,28 +47,27 @@ import { GuaribasAdmin } from './models/AdminModel';
|
||||||
export class GBAdminPackage implements IGBPackage {
|
export class GBAdminPackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
|
|
||||||
public async getDialogs(min: GBMinInstance) {
|
public async getDialogs (min: GBMinInstance) {
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
core.sequelize.addModels([GuaribasAdmin]);
|
core.sequelize.addModels([GuaribasAdmin]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {
|
||||||
AdminDialog.setup(min);
|
AdminDialog.setup(min);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,36 +36,27 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import {
|
import { Column, CreatedAt, DataType, Model, Table, UpdatedAt } from 'sequelize-typescript';
|
||||||
Column,
|
|
||||||
CreatedAt,
|
|
||||||
DataType,
|
|
||||||
Model,
|
|
||||||
Table,
|
|
||||||
UpdatedAt
|
|
||||||
} from 'sequelize-typescript';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General settings store.
|
* General settings store.
|
||||||
*/
|
*/
|
||||||
@Table
|
@Table
|
||||||
export class GuaribasAdmin extends Model<GuaribasAdmin> {
|
export class GuaribasAdmin extends Model<GuaribasAdmin> {
|
||||||
|
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
declare instanceId: number;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public key: string;
|
declare key: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(4000))
|
@Column(DataType.STRING(4000))
|
||||||
public value: string;
|
declare value: string;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
public createdAt: Date;
|
declare createdAt: Date;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
public updatedAt: Date;
|
declare updatedAt: Date;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,18 +39,18 @@
|
||||||
import { AuthenticationContext, TokenResponse } from 'adal-node';
|
import { AuthenticationContext, TokenResponse } from 'adal-node';
|
||||||
import { GBLog, GBMinInstance, IGBAdminService, IGBCoreService, IGBDeployer, IGBInstance } from 'botlib';
|
import { GBLog, GBMinInstance, IGBAdminService, IGBCoreService, IGBDeployer, IGBInstance } from 'botlib';
|
||||||
import { FindOptions } from 'sequelize/types';
|
import { FindOptions } from 'sequelize/types';
|
||||||
const urlJoin = require('url-join');
|
import urlJoin from 'url-join';
|
||||||
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
|
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService.js';
|
||||||
import { GuaribasInstance } from '../../core.gbapp/models/GBModel';
|
import { GuaribasInstance } from '../../core.gbapp/models/GBModel.js';
|
||||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService';
|
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
||||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
|
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
|
||||||
import { GBImporter } from '../../core.gbapp/services/GBImporterService';
|
import { GBImporter } from '../../core.gbapp/services/GBImporterService.js';
|
||||||
import { GBSharePointService } from '../../sharepoint.gblib/services/SharePointService';
|
import { GBSharePointService } from '../../sharepoint.gblib/services/SharePointService.js';
|
||||||
import { GuaribasAdmin } from '../models/AdminModel';
|
import { GuaribasAdmin } from '../models/AdminModel.js';
|
||||||
const Path = require('path');
|
import msRestAzure from 'ms-rest-azure';
|
||||||
const msRestAzure = require('ms-rest-azure');
|
import Path from 'path';
|
||||||
const PasswordGenerator = require('strict-password-generator').default;
|
import PasswordGenerator from 'strict-password-generator';
|
||||||
const crypto = require("crypto");
|
import crypto from 'crypto';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Services for server administration.
|
* Services for server administration.
|
||||||
|
|
@ -63,33 +63,35 @@ export class GBAdminService implements IGBAdminService {
|
||||||
|
|
||||||
public core: IGBCoreService;
|
public core: IGBCoreService;
|
||||||
|
|
||||||
constructor(core: IGBCoreService) {
|
constructor (core: IGBCoreService) {
|
||||||
this.core = core;
|
this.core = core;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static generateUuid(): string {
|
public static generateUuid (): string {
|
||||||
return msRestAzure.generateUuid();
|
return crypto.randomUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getNodeVersion() {
|
public static getNodeVersion () {
|
||||||
|
return '19.1.0';
|
||||||
const packageJson = urlJoin(process.cwd(), 'package.json');
|
const packageJson = urlJoin(process.cwd(), 'package.json');
|
||||||
// tslint:disable-next-line: non-literal-require
|
// tslint:disable-next-line: non-literal-require
|
||||||
const pjson = require(packageJson);
|
// TODO
|
||||||
|
// const pjson = require(packageJson);
|
||||||
|
|
||||||
return pjson.engines.node.replace('=', '');
|
// return pjson.engines.node.replace('=', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async getADALTokenFromUsername(username: string, password: string) {
|
public static async getADALTokenFromUsername (username: string, password: string) {
|
||||||
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
|
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
|
||||||
|
|
||||||
return credentials.tokenCache._entries[0].accessToken;
|
return (credentials as any).tokenCache._entries[0].accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
public static getMobileCode () {
|
||||||
const passwordGenerator = new PasswordGenerator();
|
const passwordGenerator = new PasswordGenerator();
|
||||||
const options = {
|
const options = {
|
||||||
upperCaseAlpha: false,
|
upperCaseAlpha: false,
|
||||||
|
|
@ -103,7 +105,7 @@ export class GBAdminService implements IGBAdminService {
|
||||||
return passwordGenerator.generatePassword(options);
|
return passwordGenerator.generatePassword(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getRndPassword(): string {
|
public static getRndPassword (): string {
|
||||||
const passwordGenerator = new PasswordGenerator();
|
const passwordGenerator = new PasswordGenerator();
|
||||||
const options = {
|
const options = {
|
||||||
upperCaseAlpha: true,
|
upperCaseAlpha: true,
|
||||||
|
|
@ -119,7 +121,7 @@ export class GBAdminService implements IGBAdminService {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getRndReadableIdentifier() {
|
public static getRndReadableIdentifier () {
|
||||||
const passwordGenerator = new PasswordGenerator();
|
const passwordGenerator = new PasswordGenerator();
|
||||||
const options = {
|
const options = {
|
||||||
upperCaseAlpha: false,
|
upperCaseAlpha: false,
|
||||||
|
|
@ -133,7 +135,7 @@ export class GBAdminService implements IGBAdminService {
|
||||||
return passwordGenerator.generatePassword(options);
|
return passwordGenerator.generatePassword(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getNumberIdentifier() {
|
public static getNumberIdentifier () {
|
||||||
const passwordGenerator = new PasswordGenerator();
|
const passwordGenerator = new PasswordGenerator();
|
||||||
const options = {
|
const options = {
|
||||||
upperCaseAlpha: false,
|
upperCaseAlpha: false,
|
||||||
|
|
@ -150,8 +152,9 @@ export class GBAdminService implements IGBAdminService {
|
||||||
/**
|
/**
|
||||||
* @see https://stackoverflow.com/a/52171480
|
* @see https://stackoverflow.com/a/52171480
|
||||||
*/
|
*/
|
||||||
public static getHash(str, seed = 0) {
|
public static getHash (str, seed = 0) {
|
||||||
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
|
let h1 = 0xdeadbeef ^ seed,
|
||||||
|
h2 = 0x41c6ce57 ^ seed;
|
||||||
for (let i = 0, ch; i < str.length; i++) {
|
for (let i = 0, ch; i < str.length; i++) {
|
||||||
ch = str.charCodeAt(i);
|
ch = str.charCodeAt(i);
|
||||||
h1 = Math.imul(h1 ^ ch, 2654435761);
|
h1 = Math.imul(h1 ^ ch, 2654435761);
|
||||||
|
|
@ -162,7 +165,7 @@ export class GBAdminService implements IGBAdminService {
|
||||||
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
|
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async undeployPackageCommand(text: any, min: GBMinInstance) {
|
public static async undeployPackageCommand (text: any, min: GBMinInstance) {
|
||||||
const packageName = text.split(' ')[1];
|
const packageName = text.split(' ')[1];
|
||||||
const importer = new GBImporter(min.core);
|
const importer = new GBImporter(min.core);
|
||||||
const deployer = new GBDeployer(min.core, importer);
|
const deployer = new GBDeployer(min.core, importer);
|
||||||
|
|
@ -170,10 +173,10 @@ export class GBAdminService implements IGBAdminService {
|
||||||
await deployer.undeployPackageFromLocalPath(min.instance, localFolder);
|
await deployer.undeployPackageFromLocalPath(min.instance, localFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static isSharePointPath(path: string) {
|
public static isSharePointPath (path: string) {
|
||||||
return path.indexOf('sharepoint.com') !== -1;
|
return path.indexOf('sharepoint.com') !== -1;
|
||||||
}
|
}
|
||||||
public static async deployPackageCommand(min: GBMinInstance, text: string, deployer: IGBDeployer) {
|
public static async deployPackageCommand (min: GBMinInstance, text: string, deployer: IGBDeployer) {
|
||||||
const packageName = text.split(' ')[1];
|
const packageName = text.split(' ')[1];
|
||||||
|
|
||||||
if (!this.isSharePointPath(packageName)) {
|
if (!this.isSharePointPath(packageName)) {
|
||||||
|
|
@ -193,26 +196,24 @@ export class GBAdminService implements IGBAdminService {
|
||||||
// .gbot packages are handled using storage API, so no download
|
// .gbot packages are handled using storage API, so no download
|
||||||
// of local resources is required.
|
// of local resources is required.
|
||||||
|
|
||||||
await deployer['downloadFolder'](min,
|
await deployer['downloadFolder'](min, Path.join('work', `${min.instance.botId}.gbai`), Path.basename(folderName));
|
||||||
Path.join('work', `${min.instance.botId}.gbai`),
|
|
||||||
Path.basename(folderName));
|
|
||||||
await deployer.deployPackage(min, localFolder);
|
await deployer.deployPackage(min, localFolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static async rebuildIndexPackageCommand(min: GBMinInstance, deployer: IGBDeployer) {
|
public static async rebuildIndexPackageCommand (min: GBMinInstance, deployer: IGBDeployer) {
|
||||||
await deployer.rebuildIndex(
|
await deployer.rebuildIndex(
|
||||||
min.instance,
|
min.instance,
|
||||||
new AzureDeployerService(deployer).getKBSearchSchema(min.instance.searchIndex)
|
new AzureDeployerService(deployer).getKBSearchSchema(min.instance.searchIndex)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async syncBotServerCommand(min: GBMinInstance, deployer: GBDeployer) {
|
public static async syncBotServerCommand (min: GBMinInstance, deployer: GBDeployer) {
|
||||||
const serverName = `${min.instance.botId}-server`;
|
const serverName = `${min.instance.botId}-server`;
|
||||||
const service = await AzureDeployerService.createInstance(deployer);
|
const service = await AzureDeployerService.createInstance(deployer);
|
||||||
service.syncBotServerRepository(min.instance.botId, serverName);
|
service.syncBotServerRepository(min.instance.botId, serverName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setValue(instanceId: number, key: string, value: string) {
|
public async setValue (instanceId: number, key: string, value: string) {
|
||||||
const options = <FindOptions>{ where: {} };
|
const options = <FindOptions>{ where: {} };
|
||||||
options.where = { key: key };
|
options.where = { key: key };
|
||||||
let admin = await GuaribasAdmin.findOne(options);
|
let admin = await GuaribasAdmin.findOne(options);
|
||||||
|
|
@ -225,7 +226,7 @@ export class GBAdminService implements IGBAdminService {
|
||||||
await admin.save();
|
await admin.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateSecurityInfo(
|
public async updateSecurityInfo (
|
||||||
instanceId: number,
|
instanceId: number,
|
||||||
authenticatorTenant: string,
|
authenticatorTenant: string,
|
||||||
authenticatorAuthorityHostUrl: string
|
authenticatorAuthorityHostUrl: string
|
||||||
|
|
@ -239,7 +240,7 @@ export class GBAdminService implements IGBAdminService {
|
||||||
return item.save();
|
return item.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getValue(instanceId: number, key: string): Promise<string> {
|
public async getValue (instanceId: number, key: string): Promise<string> {
|
||||||
const options = <FindOptions>{ where: {} };
|
const options = <FindOptions>{ where: {} };
|
||||||
options.where = { key: key, instanceId: instanceId };
|
options.where = { key: key, instanceId: instanceId };
|
||||||
const obj = await GuaribasAdmin.findOne(options);
|
const obj = await GuaribasAdmin.findOne(options);
|
||||||
|
|
@ -247,7 +248,7 @@ export class GBAdminService implements IGBAdminService {
|
||||||
return obj.value;
|
return obj.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async acquireElevatedToken(instanceId: number): Promise<string> {
|
public async acquireElevatedToken (instanceId: number): Promise<string> {
|
||||||
// TODO: Use boot bot as base for authentication.
|
// TODO: Use boot bot as base for authentication.
|
||||||
|
|
||||||
const botId = GBConfigService.get('BOT_ID');
|
const botId = GBConfigService.get('BOT_ID');
|
||||||
|
|
@ -296,5 +297,5 @@ export class GBAdminService implements IGBAdminService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async publish(min: GBMinInstance, packageName: string, republish: boolean): Promise<void> { }
|
public async publish (min: GBMinInstance, packageName: string, republish: boolean): Promise<void> {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ export const Messages = {
|
||||||
authenticate: 'Please, authenticate:',
|
authenticate: 'Please, authenticate:',
|
||||||
welcome: 'Welcome to Pragmatismo.io GeneralBots Administration.',
|
welcome: 'Welcome to Pragmatismo.io GeneralBots Administration.',
|
||||||
which_task: 'Which task do you wanna run now?',
|
which_task: 'Which task do you wanna run now?',
|
||||||
working: (command) => `I'm working on ${command}...`,
|
working: command => `I'm working on ${command}...`,
|
||||||
finished_working: 'Done.',
|
finished_working: 'Done.',
|
||||||
unknown_command: text =>
|
unknown_command: text =>
|
||||||
`Well, but ${text} is not a administrative General Bots command, I will try to search for it.`,
|
`Well, but ${text} is not a administrative General Bots command, I will try to search for it.`,
|
||||||
|
|
@ -12,7 +12,7 @@ export const Messages = {
|
||||||
deployPackage: text => `Deploying package ${text}...`,
|
deployPackage: text => `Deploying package ${text}...`,
|
||||||
redeployPackage: text => `Redeploying package ${text}...`,
|
redeployPackage: text => `Redeploying package ${text}...`,
|
||||||
packageUndeployed: text => `√ Package ${text} undeployed...`,
|
packageUndeployed: text => `√ Package ${text} undeployed...`,
|
||||||
consent: (url) => `Please, consent access to this app at: [Microsoft Online](${url}).`,
|
consent: url => `Please, consent access to this app at: [Microsoft Online](${url}).`,
|
||||||
wrong_password: 'Sorry, wrong password. Please, try again.',
|
wrong_password: 'Sorry, wrong password. Please, try again.',
|
||||||
enter_authenticator_tenant: 'Enter the Authenticator Tenant (eg.: domain.onmicrosoft.com):',
|
enter_authenticator_tenant: 'Enter the Authenticator Tenant (eg.: domain.onmicrosoft.com):',
|
||||||
enter_authenticator_authority_host_url: 'Enter the Authority Host URL (eg.: https://login.microsoftonline.com): ',
|
enter_authenticator_authority_host_url: 'Enter the Authority Host URL (eg.: https://login.microsoftonline.com): ',
|
||||||
|
|
@ -28,7 +28,7 @@ export const Messages = {
|
||||||
authenticate: 'Please, authenticate:',
|
authenticate: 'Please, authenticate:',
|
||||||
welcome: 'Welcome to Pragmatismo.io GeneralBots Administration.',
|
welcome: 'Welcome to Pragmatismo.io GeneralBots Administration.',
|
||||||
which_task: 'Which task do you wanna run now?',
|
which_task: 'Which task do you wanna run now?',
|
||||||
working: (command) => `I'm working on ${command}...`,
|
working: command => `I'm working on ${command}...`,
|
||||||
finished_working: 'Done.',
|
finished_working: 'Done.',
|
||||||
unknown_command: text =>
|
unknown_command: text =>
|
||||||
`Well, but ${text} is not a administrative General Bots command, I will try to search for it.`,
|
`Well, but ${text} is not a administrative General Bots command, I will try to search for it.`,
|
||||||
|
|
@ -37,7 +37,7 @@ export const Messages = {
|
||||||
deployPackage: text => `Deploying package ${text}...`,
|
deployPackage: text => `Deploying package ${text}...`,
|
||||||
redeployPackage: text => `Redeploying package ${text}...`,
|
redeployPackage: text => `Redeploying package ${text}...`,
|
||||||
packageUndeployed: text => `Package ${text} undeployed...`,
|
packageUndeployed: text => `Package ${text} undeployed...`,
|
||||||
consent: (url) => `Please, consent access to this app at: [Microsoft Online](${url}).`,
|
consent: url => `Please, consent access to this app at: [Microsoft Online](${url}).`,
|
||||||
wrong_password: 'Sorry, wrong password. Please, try again.',
|
wrong_password: 'Sorry, wrong password. Please, try again.',
|
||||||
enter_authenticator_tenant: 'Enter the Authenticator Tenant (eg.: domain.onmicrosoft.com):',
|
enter_authenticator_tenant: 'Enter the Authenticator Tenant (eg.: domain.onmicrosoft.com):',
|
||||||
enter_authenticator_authority_host_url: 'Enter the Authority Host URL (eg.: https://login.microsoftonline.com): ',
|
enter_authenticator_authority_host_url: 'Enter the Authority Host URL (eg.: https://login.microsoftonline.com): ',
|
||||||
|
|
|
||||||
|
|
@ -38,35 +38,33 @@
|
||||||
|
|
||||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||||
import { Sequelize } from 'sequelize-typescript';
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
import { GuaribasConversation, GuaribasConversationMessage } from './models';
|
import { GuaribasConversation, GuaribasConversationMessage } from './models/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* .gblib Package handler.
|
* .gblib Package handler.
|
||||||
*/
|
*/
|
||||||
export class GBAnalyticsPackage implements IGBPackage {
|
export class GBAnalyticsPackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
public async getDialogs(min: GBMinInstance) {
|
public async getDialogs (min: GBMinInstance) {
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
GBLog.verbose(`loadPackage called.`);
|
GBLog.verbose(`loadPackage called.`);
|
||||||
core.sequelize.addModels([GuaribasConversation, GuaribasConversationMessage]);
|
core.sequelize.addModels([GuaribasConversation, GuaribasConversationMessage]);
|
||||||
|
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`loadBot called.`);
|
GBLog.verbose(`loadBot called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,58 +54,57 @@ import {
|
||||||
UpdatedAt
|
UpdatedAt
|
||||||
} from 'sequelize-typescript';
|
} from 'sequelize-typescript';
|
||||||
|
|
||||||
import { GuaribasChannel, GuaribasInstance } from '../../core.gbapp/models/GBModel';
|
import { GuaribasChannel, GuaribasInstance } from '../../core.gbapp/models/GBModel.js';
|
||||||
import { GuaribasSubject } from '../../kb.gbapp/models';
|
import { GuaribasSubject } from '../../kb.gbapp/models/index.js';
|
||||||
import { GuaribasUser } from '../../security.gbapp/models';
|
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A conversation that groups many messages.
|
* A conversation that groups many messages.
|
||||||
*/
|
*/
|
||||||
@Table
|
@Table
|
||||||
export class GuaribasConversation extends Model<GuaribasConversation> {
|
export class GuaribasConversation extends Model<GuaribasConversation> {
|
||||||
|
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public conversationId: number;
|
conversationId: number;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
instanceId: number;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasSubject)
|
@ForeignKey(() => GuaribasSubject)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public startSubjectId: number;
|
startSubjectId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasSubject)
|
@BelongsTo(() => GuaribasSubject)
|
||||||
public startSubject: GuaribasSubject;
|
startSubject: GuaribasSubject;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasChannel)
|
@ForeignKey(() => GuaribasChannel)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public channelId: string;
|
channelId: string;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
public rateDate: Date;
|
rateDate: Date;
|
||||||
|
|
||||||
@Column(DataType.FLOAT)
|
@Column(DataType.FLOAT)
|
||||||
public rate: number;
|
rate: number;
|
||||||
|
|
||||||
@Column(DataType.STRING(512))
|
@Column(DataType.STRING(512))
|
||||||
public feedback: string;
|
feedback: string;
|
||||||
|
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
public createdAt: Date;
|
createdAt: Date;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public text: string;
|
text: string;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasUser)
|
@ForeignKey(() => GuaribasUser)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public startedByUserId: number;
|
startedByUserId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasUser)
|
@BelongsTo(() => GuaribasUser)
|
||||||
public startedBy: GuaribasUser;
|
startedBy: GuaribasUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -113,45 +112,43 @@ export class GuaribasConversation extends Model<GuaribasConversation> {
|
||||||
*/
|
*/
|
||||||
@Table
|
@Table
|
||||||
export class GuaribasConversationMessage extends Model<GuaribasConversationMessage> {
|
export class GuaribasConversationMessage extends Model<GuaribasConversationMessage> {
|
||||||
|
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public conversationMessageId: number;
|
conversationMessageId: number;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasSubject)
|
@ForeignKey(() => GuaribasSubject)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public subjectId: number;
|
subjectId: number;
|
||||||
|
|
||||||
@Column(DataType.TEXT)
|
@Column(DataType.TEXT)
|
||||||
public content: string;
|
content: string;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
public createdAt: Date;
|
createdAt: Date;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
public updatedAt: Date;
|
updatedAt: Date;
|
||||||
|
|
||||||
|
|
||||||
//tslint:disable-next-line:no-use-before-declare
|
//tslint:disable-next-line:no-use-before-declare
|
||||||
@ForeignKey(() => GuaribasConversation)
|
@ForeignKey(() => GuaribasConversation)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public conversationId: number;
|
conversationId: number;
|
||||||
|
|
||||||
//tslint:disable-next-line:no-use-before-declare
|
//tslint:disable-next-line:no-use-before-declare
|
||||||
@BelongsTo(() => GuaribasConversation)
|
@BelongsTo(() => GuaribasConversation)
|
||||||
public conversation: GuaribasConversation;
|
conversation: GuaribasConversation;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
instanceId: number;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasUser)
|
@ForeignKey(() => GuaribasUser)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public userId: number;
|
userId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasUser)
|
@BelongsTo(() => GuaribasUser)
|
||||||
public user: GuaribasUser;
|
user: GuaribasUser;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,18 +36,15 @@
|
||||||
|
|
||||||
import { AzureText } from 'pragmatismo-io-framework';
|
import { AzureText } from 'pragmatismo-io-framework';
|
||||||
import { FindOptions } from 'sequelize/types';
|
import { FindOptions } from 'sequelize/types';
|
||||||
import { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GuaribasUser } from '../../security.gbapp/models';
|
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||||
import { GuaribasConversation, GuaribasConversationMessage } from '../models';
|
import { GuaribasConversation, GuaribasConversationMessage } from '../models/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base services for Bot Analytics.
|
* Base services for Bot Analytics.
|
||||||
*/
|
*/
|
||||||
export class AnalyticsService {
|
export class AnalyticsService {
|
||||||
|
public async createConversation (user: GuaribasUser): Promise<GuaribasConversation> {
|
||||||
public async createConversation(
|
|
||||||
user: GuaribasUser
|
|
||||||
): Promise<GuaribasConversation> {
|
|
||||||
const conversation = new GuaribasConversation();
|
const conversation = new GuaribasConversation();
|
||||||
conversation.startedBy = user;
|
conversation.startedBy = user;
|
||||||
conversation.startedByUserId = user.userId;
|
conversation.startedByUserId = user.userId;
|
||||||
|
|
@ -56,15 +53,18 @@ export class AnalyticsService {
|
||||||
return await conversation.save();
|
return await conversation.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateConversationSuggestion(instanceId: number,
|
public async updateConversationSuggestion (
|
||||||
conversationId: string, feedback: string, locale: string): Promise<number> {
|
instanceId: number,
|
||||||
|
conversationId: string,
|
||||||
|
feedback: string,
|
||||||
|
locale: string
|
||||||
|
): Promise<number> {
|
||||||
const minBoot = GBServer.globals.minBoot as any;
|
const minBoot = GBServer.globals.minBoot as any;
|
||||||
const rate = await AzureText.getSentiment(
|
const rate = await AzureText.getSentiment(
|
||||||
minBoot.instance.textAnalyticsKey ? minBoot.instance.textAnalyticsKey :
|
minBoot.instance.textAnalyticsKey ? minBoot.instance.textAnalyticsKey : minBoot.instance.textAnalyticsKey,
|
||||||
minBoot.instance.textAnalyticsKey,
|
minBoot.instance.textAnalyticsEndpoint
|
||||||
minBoot.instance.textAnalyticsEndpoint ? minBoot.instance.textAnalyticsEndpoint :
|
? minBoot.instance.textAnalyticsEndpoint
|
||||||
minBoot.instance.textAnalyticsEndpoint,
|
: minBoot.instance.textAnalyticsEndpoint,
|
||||||
locale,
|
locale,
|
||||||
feedback
|
feedback
|
||||||
);
|
);
|
||||||
|
|
@ -79,18 +79,16 @@ export class AnalyticsService {
|
||||||
await item.save();
|
await item.save();
|
||||||
|
|
||||||
return rate;
|
return rate;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createMessage(
|
public async createMessage (
|
||||||
instanceId: number,
|
instanceId: number,
|
||||||
conversation: GuaribasConversation,
|
conversation: GuaribasConversation,
|
||||||
userId: number,
|
userId: number,
|
||||||
content: string
|
content: string
|
||||||
): Promise<GuaribasConversationMessage> {
|
): Promise<GuaribasConversationMessage> {
|
||||||
|
|
||||||
const message = GuaribasConversationMessage.build();
|
const message = GuaribasConversationMessage.build();
|
||||||
message.content = typeof (content) === 'object' ? JSON.stringify(content) : content;
|
message.content = typeof content === 'object' ? JSON.stringify(content) : content;
|
||||||
message.instanceId = instanceId;
|
message.instanceId = instanceId;
|
||||||
message.userId = userId;
|
message.userId = userId;
|
||||||
message.conversationId = conversation.conversationId;
|
message.conversationId = conversation.conversationId;
|
||||||
|
|
|
||||||
|
|
@ -37,19 +37,19 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { GBLog, IGBInstallationDeployer, IGBInstance } from 'botlib';
|
import { GBLog, IGBInstallationDeployer, IGBInstance } from 'botlib';
|
||||||
import * as fs from 'fs';
|
import * as Fs from 'fs';
|
||||||
import { GBAdminService } from '../../../packages/admin.gbapp/services/GBAdminService';
|
import { GBAdminService } from '../../../packages/admin.gbapp/services/GBAdminService.js';
|
||||||
import { GBConfigService } from '../../../packages/core.gbapp/services/GBConfigService';
|
import { GBConfigService } from '../../../packages/core.gbapp/services/GBConfigService.js';
|
||||||
const scanf = require('scanf');
|
import scanf from 'scanf';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles command-line dialog for getting info for Boot Bot.
|
* Handles command-line dialog for getting info for Boot Bot.
|
||||||
*/
|
*/
|
||||||
export class StartDialog {
|
export class StartDialog {
|
||||||
public static async createBaseInstance(installationDeployer: IGBInstallationDeployer) {
|
public static async createBaseInstance (installationDeployer: IGBInstallationDeployer) {
|
||||||
// No .env so asks for cloud credentials to start a new farm.
|
// No .env so asks for cloud credentials to start a new farm.
|
||||||
|
|
||||||
if (!fs.existsSync(`.env`)) {
|
if (!Fs.existsSync(`.env`)) {
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
'A empty enviroment is detected. To start automatic deploy, please enter some information:\n'
|
'A empty enviroment is detected. To start automatic deploy, please enter some information:\n'
|
||||||
);
|
);
|
||||||
|
|
@ -111,7 +111,7 @@ export class StartDialog {
|
||||||
return { instance, credentials, subscriptionId };
|
return { instance, credentials, subscriptionId };
|
||||||
}
|
}
|
||||||
|
|
||||||
private static retrieveUsername() {
|
private static retrieveUsername () {
|
||||||
let value = GBConfigService.get('CLOUD_USERNAME');
|
let value = GBConfigService.get('CLOUD_USERNAME');
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
process.stdout.write(`${GBAdminService.GB_PROMPT}CLOUD_USERNAME:`);
|
process.stdout.write(`${GBAdminService.GB_PROMPT}CLOUD_USERNAME:`);
|
||||||
|
|
@ -121,7 +121,7 @@ export class StartDialog {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static retrievePassword() {
|
private static retrievePassword () {
|
||||||
let password = GBConfigService.get('CLOUD_PASSWORD');
|
let password = GBConfigService.get('CLOUD_PASSWORD');
|
||||||
if (password === undefined) {
|
if (password === undefined) {
|
||||||
process.stdout.write(`${GBAdminService.GB_PROMPT}CLOUD_PASSWORD:`);
|
process.stdout.write(`${GBAdminService.GB_PROMPT}CLOUD_PASSWORD:`);
|
||||||
|
|
@ -131,7 +131,7 @@ export class StartDialog {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static retrieveBotId() {
|
private static retrieveBotId () {
|
||||||
let botId = GBConfigService.get('BOT_ID');
|
let botId = GBConfigService.get('BOT_ID');
|
||||||
if (botId === undefined) {
|
if (botId === undefined) {
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
|
|
@ -146,12 +146,11 @@ cannot start or end with or contain consecutive dashes and having 4 to 42 charac
|
||||||
return botId;
|
return botId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Update Manifest in Azure: "signInAudience": "AzureADandPersonalMicrosoftAccount" and "accessTokenAcceptedVersion": 2.
|
* Update Manifest in Azure: "signInAudience": "AzureADandPersonalMicrosoftAccount" and "accessTokenAcceptedVersion": 2.
|
||||||
*/
|
*/
|
||||||
private static retrieveAppId() {
|
private static retrieveAppId () {
|
||||||
let appId = GBConfigService.get('MARKETPLACE_ID');
|
let appId = GBConfigService.get('MARKETPLACE_ID');
|
||||||
if (appId === undefined) {
|
if (appId === undefined) {
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
|
|
@ -167,7 +166,7 @@ generate manually an App ID and App Secret.\n`
|
||||||
return appId;
|
return appId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static retrieveAppPassword() {
|
private static retrieveAppPassword () {
|
||||||
let appPassword = GBConfigService.get('MARKETPLACE_SECRET');
|
let appPassword = GBConfigService.get('MARKETPLACE_SECRET');
|
||||||
if (appPassword === undefined) {
|
if (appPassword === undefined) {
|
||||||
process.stdout.write('Generated Password (MARKETPLACE_SECRET):');
|
process.stdout.write('Generated Password (MARKETPLACE_SECRET):');
|
||||||
|
|
@ -177,7 +176,7 @@ generate manually an App ID and App Secret.\n`
|
||||||
return appPassword;
|
return appPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static retrieveSubscriptionId(list) {
|
private static retrieveSubscriptionId (list) {
|
||||||
let subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
|
let subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
|
||||||
const map = {};
|
const map = {};
|
||||||
let index = 1;
|
let index = 1;
|
||||||
|
|
@ -195,7 +194,7 @@ generate manually an App ID and App Secret.\n`
|
||||||
return subscriptionId;
|
return subscriptionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static retrieveLocation() {
|
private static retrieveLocation () {
|
||||||
let location = GBConfigService.get('CLOUD_LOCATION');
|
let location = GBConfigService.get('CLOUD_LOCATION');
|
||||||
if (location === undefined) {
|
if (location === undefined) {
|
||||||
process.stdout.write('CLOUD_LOCATION (eg. westus):');
|
process.stdout.write('CLOUD_LOCATION (eg. westus):');
|
||||||
|
|
|
||||||
|
|
@ -44,26 +44,25 @@ import { Sequelize } from 'sequelize-typescript';
|
||||||
*/
|
*/
|
||||||
export class GBAzureDeployerPackage implements IGBPackage {
|
export class GBAzureDeployerPackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
public async getDialogs(min: GBMinInstance) {
|
public async getDialogs (min: GBMinInstance) {
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
GBLog.verbose(`loadPackage called.`);
|
GBLog.verbose(`loadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`loadBot called.`);
|
GBLog.verbose(`loadBot called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,33 +36,27 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { HttpHeaders, HttpMethods, ServiceClient, WebResource } from '@azure/ms-rest-js';
|
import urlJoin from 'url-join';
|
||||||
import { CognitiveServicesManagementClient } from 'azure-arm-cognitiveservices';
|
import { HttpMethods, ServiceClient, WebResource } from '@azure/ms-rest-js';
|
||||||
import { ResourceManagementClient, SubscriptionClient } from 'azure-arm-resource';
|
import { CognitiveServicesManagementClient } from '@azure/arm-cognitiveservices';
|
||||||
import { SearchManagementClient } from 'azure-arm-search';
|
import { ResourceManagementClient } from '@azure/arm-resources';
|
||||||
import { SqlManagementClient } from 'azure-arm-sql';
|
import { SubscriptionClient } from '@azure/arm-subscriptions';
|
||||||
import { WebSiteManagementClient } from 'azure-arm-website';
|
import { SearchManagementClient } from '@azure/arm-search';
|
||||||
//tslint:disable-next-line:no-submodule-imports
|
import { SqlManagementClient } from '@azure/arm-sql';
|
||||||
import { AppServicePlan, Site, SiteConfigResource, SiteLogsConfig, SiteSourceControl } from 'azure-arm-website/lib/models';
|
import { WebSiteManagementClient } from '@azure/arm-appservice';
|
||||||
|
import { AppServicePlan, Site, SiteLogsConfig, SiteSourceControl } from '@azure/arm-appservice';
|
||||||
import { GBLog, IGBInstallationDeployer, IGBInstance, IGBDeployer, IGBCoreService } from 'botlib';
|
import { GBLog, IGBInstallationDeployer, IGBInstance, IGBDeployer, IGBCoreService } from 'botlib';
|
||||||
import { GBAdminService } from '../../../packages/admin.gbapp/services/GBAdminService';
|
import { GBAdminService } from '../../../packages/admin.gbapp/services/GBAdminService.js';
|
||||||
import { GBCorePackage } from '../../../packages/core.gbapp';
|
import { GBCorePackage } from '../../../packages/core.gbapp/index.js';
|
||||||
import { GBConfigService } from '../../../packages/core.gbapp/services/GBConfigService';
|
import { GBConfigService } from '../../../packages/core.gbapp/services/GBConfigService.js';
|
||||||
import { GBDeployer } from '../../../packages/core.gbapp/services/GBDeployer';
|
import { GBDeployer } from '../../../packages/core.gbapp/services/GBDeployer.js';
|
||||||
const MicrosoftGraph = require("@microsoft/microsoft-graph-client");
|
import { Account } from '@azure/arm-cognitiveservices';
|
||||||
|
import MicrosoftGraph from '@microsoft/microsoft-graph-client';
|
||||||
|
import Spinner from 'cli-spinner';
|
||||||
|
import * as publicIp from 'public-ip';
|
||||||
|
|
||||||
const Spinner = require('cli-spinner').Spinner;
|
|
||||||
// tslint:disable-next-line: no-submodule-imports
|
|
||||||
import * as simplegit from 'simple-git/promise';
|
|
||||||
const git = simplegit();
|
|
||||||
|
|
||||||
// tslint:disable-next-line:no-submodule-imports
|
|
||||||
import { CognitiveServicesAccount } from 'azure-arm-cognitiveservices/lib/models';
|
|
||||||
const urlJoin = require('url-join');
|
|
||||||
const iconUrl = 'https://github.com/pragmatismo-io/BotServer/blob/master/docs/images/generalbots-logo-squared.png';
|
|
||||||
const publicIp = require('public-ip');
|
|
||||||
const WebSiteResponseTimeout = 900;
|
const WebSiteResponseTimeout = 900;
|
||||||
|
const iconUrl = 'https://github.com/pragmatismo-io/BotServer/blob/master/docs/images/generalbots-logo-squared.png';
|
||||||
/**
|
/**
|
||||||
* Deployer for Microsoft cloud.
|
* Deployer for Microsoft cloud.
|
||||||
*/
|
*/
|
||||||
|
|
@ -70,13 +64,13 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
public apiVersion = '2017-12-01';
|
public apiVersion = '2017-12-01';
|
||||||
public defaultEndPoint = 'http://localhost:4242';
|
public defaultEndPoint = 'http://localhost:4242';
|
||||||
public instance: IGBInstance;
|
public instance: IGBInstance;
|
||||||
public cloud: ResourceManagementClient.ResourceManagementClient;
|
public cloud: ResourceManagementClient;
|
||||||
public webSiteClient: WebSiteManagementClient;
|
public webSiteClient: WebSiteManagementClient;
|
||||||
public storageClient: SqlManagementClient;
|
public storageClient: SqlManagementClient;
|
||||||
public cognitiveClient: CognitiveServicesManagementClient;
|
public cognitiveClient: CognitiveServicesManagementClient;
|
||||||
public searchClient: SearchManagementClient;
|
public searchClient: SearchManagementClient;
|
||||||
public provider = 'Microsoft.BotService';
|
public provider = 'Microsoft.BotService';
|
||||||
public subscriptionClient: SubscriptionClient.SubscriptionClient;
|
public subscriptionClient: SubscriptionClient;
|
||||||
public accessToken: string;
|
public accessToken: string;
|
||||||
public location: string;
|
public location: string;
|
||||||
public subscriptionId: string;
|
public subscriptionId: string;
|
||||||
|
|
@ -85,17 +79,16 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
public core: IGBCoreService;
|
public core: IGBCoreService;
|
||||||
private freeTier: boolean;
|
private freeTier: boolean;
|
||||||
|
|
||||||
constructor(deployer: IGBDeployer, freeTier: boolean = true) {
|
constructor (deployer: IGBDeployer, freeTier: boolean = true) {
|
||||||
this.deployer = deployer;
|
this.deployer = deployer;
|
||||||
this.freeTier = freeTier;
|
this.freeTier = freeTier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async runSearch(instance: IGBInstance) {
|
public async runSearch (instance: IGBInstance) {
|
||||||
await this.deployer.rebuildIndex(instance, this.getKBSearchSchema(instance.searchIndex));
|
await this.deployer.rebuildIndex(instance, this.getKBSearchSchema(instance.searchIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async createInstance(deployer: GBDeployer): Promise<AzureDeployerService> {
|
public static async createInstance (deployer: GBDeployer): Promise<AzureDeployerService> {
|
||||||
|
|
||||||
const username = GBConfigService.get('CLOUD_USERNAME');
|
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||||
const password = GBConfigService.get('CLOUD_PASSWORD');
|
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||||
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
|
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
|
||||||
|
|
@ -108,7 +101,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static createRequestObject(url: string, accessToken: string, verb: HttpMethods, body: string) {
|
private static createRequestObject (url: string, accessToken: string, verb: HttpMethods, body: string) {
|
||||||
const req = new WebResource();
|
const req = new WebResource();
|
||||||
req.method = verb;
|
req.method = verb;
|
||||||
req.url = url;
|
req.url = url;
|
||||||
|
|
@ -120,13 +113,13 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getSubscriptions(credentials) {
|
public async getSubscriptions (credentials) {
|
||||||
const subscriptionClient = new SubscriptionClient.default(credentials);
|
const subscriptionClient = new SubscriptionClient(credentials);
|
||||||
|
|
||||||
return subscriptionClient.subscriptions.list();
|
return subscriptionClient.subscriptions.list();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getKBSearchSchema(indexName) {
|
public getKBSearchSchema (indexName) {
|
||||||
return {
|
return {
|
||||||
name: indexName,
|
name: indexName,
|
||||||
fields: [
|
fields: [
|
||||||
|
|
@ -237,23 +230,20 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async botExists(botId) {
|
public async botExists (botId) {
|
||||||
|
|
||||||
const baseUrl = `https://management.azure.com/`;
|
const baseUrl = `https://management.azure.com/`;
|
||||||
const username = GBConfigService.get('CLOUD_USERNAME');
|
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||||
const password = GBConfigService.get('CLOUD_PASSWORD');
|
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||||
|
|
||||||
|
|
||||||
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
||||||
const httpClient = new ServiceClient();
|
const httpClient = new ServiceClient();
|
||||||
|
|
||||||
const query = `providers/${this.provider
|
const query = `providers/${this.provider}/checkNameAvailability/Action?api-version=${this.apiVersion}`;
|
||||||
}/checkNameAvailability/Action?api-version=${this.apiVersion}`;
|
|
||||||
|
|
||||||
const url = urlJoin(baseUrl, query);
|
const url = urlJoin(baseUrl, query);
|
||||||
const body = {
|
const body = {
|
||||||
name: botId,
|
name: botId,
|
||||||
type: "botServices"
|
type: 'botServices'
|
||||||
};
|
};
|
||||||
|
|
||||||
const req = AzureDeployerService.createRequestObject(url, accessToken, 'POST', JSON.stringify(body));
|
const req = AzureDeployerService.createRequestObject(url, accessToken, 'POST', JSON.stringify(body));
|
||||||
|
|
@ -262,7 +252,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
return !res.parsedBody.valid;
|
return !res.parsedBody.valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateBotProxy(botId, group, endpoint) {
|
public async updateBotProxy (botId, group, endpoint) {
|
||||||
const baseUrl = `https://management.azure.com/`;
|
const baseUrl = `https://management.azure.com/`;
|
||||||
const username = GBConfigService.get('CLOUD_USERNAME');
|
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||||
const password = GBConfigService.get('CLOUD_PASSWORD');
|
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||||
|
|
@ -277,7 +267,8 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${this.provider
|
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
|
||||||
|
this.provider
|
||||||
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
||||||
const url = urlJoin(baseUrl, query);
|
const url = urlJoin(baseUrl, query);
|
||||||
const req = AzureDeployerService.createRequestObject(url, accessToken, 'PATCH', JSON.stringify(parameters));
|
const req = AzureDeployerService.createRequestObject(url, accessToken, 'PATCH', JSON.stringify(parameters));
|
||||||
|
|
@ -289,8 +280,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
GBLog.info(`Bot proxy updated at: ${endpoint}.`);
|
GBLog.info(`Bot proxy updated at: ${endpoint}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateBot(botId: string, group: string, name: string,
|
public async updateBot (botId: string, group: string, name: string, description: string, endpoint: string) {
|
||||||
description: string, endpoint: string) {
|
|
||||||
const baseUrl = `https://management.azure.com/`;
|
const baseUrl = `https://management.azure.com/`;
|
||||||
const username = GBConfigService.get('CLOUD_USERNAME');
|
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||||
const password = GBConfigService.get('CLOUD_PASSWORD');
|
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||||
|
|
@ -308,7 +298,8 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${this.provider
|
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
|
||||||
|
this.provider
|
||||||
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
||||||
const url = urlJoin(baseUrl, query);
|
const url = urlJoin(baseUrl, query);
|
||||||
const req = AzureDeployerService.createRequestObject(url, accessToken, 'PATCH', JSON.stringify(parameters));
|
const req = AzureDeployerService.createRequestObject(url, accessToken, 'PATCH', JSON.stringify(parameters));
|
||||||
|
|
@ -320,7 +311,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
GBLog.info(`Bot updated at: ${endpoint}.`);
|
GBLog.info(`Bot updated at: ${endpoint}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async deleteBot(botId: string, group) {
|
public async deleteBot (botId: string, group) {
|
||||||
const baseUrl = `https://management.azure.com/`;
|
const baseUrl = `https://management.azure.com/`;
|
||||||
const username = GBConfigService.get('CLOUD_USERNAME');
|
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||||
const password = GBConfigService.get('CLOUD_PASSWORD');
|
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||||
|
|
@ -329,36 +320,36 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
||||||
const httpClient = new ServiceClient();
|
const httpClient = new ServiceClient();
|
||||||
|
|
||||||
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${this.provider
|
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
|
||||||
|
this.provider
|
||||||
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
||||||
const url = urlJoin(baseUrl, query);
|
const url = urlJoin(baseUrl, query);
|
||||||
const req = AzureDeployerService.createRequestObject(url, accessToken, 'DELETE', undefined);
|
const req = AzureDeployerService.createRequestObject(url, accessToken, 'DELETE', undefined);
|
||||||
const res = await httpClient.sendRequest(req);
|
const res = await httpClient.sendRequest(req);
|
||||||
|
|
||||||
if (res.bodyAsText !== "") {
|
if (res.bodyAsText !== '') {
|
||||||
throw res.bodyAsText;
|
throw res.bodyAsText;
|
||||||
}
|
}
|
||||||
GBLog.info(`Bot ${botId} was deleted from the provider.`);
|
GBLog.info(`Bot ${botId} was deleted from the provider.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async openStorageFirewall(groupName, serverName) {
|
public async openStorageFirewall (groupName, serverName) {
|
||||||
const username = GBConfigService.get('CLOUD_USERNAME');
|
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||||
const password = GBConfigService.get('CLOUD_PASSWORD');
|
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||||
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
|
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
|
||||||
|
|
||||||
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
|
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
|
||||||
const storageClient = new SqlManagementClient(credentials, subscriptionId);
|
const storageClient = new SqlManagementClient(credentials as any, subscriptionId);
|
||||||
|
|
||||||
const ip = await publicIp.v4();
|
const ip = await publicIp.publicIpv4();
|
||||||
let params = {
|
let params = {
|
||||||
startIpAddress: ip,
|
startIpAddress: ip,
|
||||||
endIpAddress: ip
|
endIpAddress: ip
|
||||||
};
|
};
|
||||||
await storageClient.firewallRules.createOrUpdate(groupName, serverName, 'gb', params);
|
await storageClient.firewallRules.createOrUpdate(groupName, serverName, 'gb', params);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async deployFarm(
|
public async deployFarm (
|
||||||
proxyAddress: string,
|
proxyAddress: string,
|
||||||
instance: IGBInstance,
|
instance: IGBInstance,
|
||||||
credentials,
|
credentials,
|
||||||
|
|
@ -373,11 +364,9 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
let keys: any;
|
let keys: any;
|
||||||
const name = instance.botId;
|
const name = instance.botId;
|
||||||
|
|
||||||
|
|
||||||
GBLog.info(`Enabling resource providers...`);
|
GBLog.info(`Enabling resource providers...`);
|
||||||
await this.enableResourceProviders('Microsoft.BotService');
|
await this.enableResourceProviders('Microsoft.BotService');
|
||||||
|
|
||||||
|
|
||||||
GBLog.info(`Deploying Deploy Group (It may take a few minutes)...`);
|
GBLog.info(`Deploying Deploy Group (It may take a few minutes)...`);
|
||||||
await this.createDeployGroup(name, instance.cloudLocation);
|
await this.createDeployGroup(name, instance.cloudLocation);
|
||||||
|
|
||||||
|
|
@ -391,8 +380,13 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
const administratorPassword = GBAdminService.getRndPassword();
|
const administratorPassword = GBAdminService.getRndPassword();
|
||||||
const storageServer = `${name.toLowerCase()}-storage-server`;
|
const storageServer = `${name.toLowerCase()}-storage-server`;
|
||||||
const storageName = `${name}-storage`;
|
const storageName = `${name}-storage`;
|
||||||
await this.createStorageServer(name, storageServer, administratorLogin,
|
await this.createStorageServer(
|
||||||
administratorPassword, storageServer, instance.cloudLocation
|
name,
|
||||||
|
storageServer,
|
||||||
|
administratorLogin,
|
||||||
|
administratorPassword,
|
||||||
|
storageServer,
|
||||||
|
instance.cloudLocation
|
||||||
);
|
);
|
||||||
await this.createStorage(name, storageServer, storageName, instance.cloudLocation);
|
await this.createStorage(name, storageServer, storageName, instance.cloudLocation);
|
||||||
instance.storageUsername = administratorLogin;
|
instance.storageUsername = administratorLogin;
|
||||||
|
|
@ -406,28 +400,28 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
await this.createSearch(name, searchName, instance.cloudLocation);
|
await this.createSearch(name, searchName, instance.cloudLocation);
|
||||||
const searchKeys = await this.searchClient.adminKeys.get(name, searchName);
|
const searchKeys = await this.searchClient.adminKeys.get(name, searchName);
|
||||||
instance.searchHost = `${searchName}.search.windows.net`;
|
instance.searchHost = `${searchName}.search.windows.net`;
|
||||||
instance.searchIndex = 'azuresql-index';
|
instance.searchIndex = 'azuresql-index.js';
|
||||||
instance.searchIndexer = 'azuresql-indexer';
|
instance.searchIndexer = 'azuresql-indexer';
|
||||||
instance.searchKey = searchKeys.primaryKey;
|
instance.searchKey = searchKeys.primaryKey;
|
||||||
|
|
||||||
GBLog.info(`Deploying Speech...`);
|
GBLog.info(`Deploying Speech...`);
|
||||||
const speech = await this.createSpeech(name, `${name}speech`, instance.cloudLocation);
|
const speech = await this.createSpeech(name, `${name}speech`, instance.cloudLocation);
|
||||||
keys = await this.cognitiveClient.accounts.listKeys(name, speech.name);
|
keys = await this.cognitiveClient.accounts.listKeys(name, speech.name);
|
||||||
instance.speechEndpoint = speech.endpoint;
|
instance.speechEndpoint = speech.properties.endpoint;
|
||||||
instance.speechKey = keys.key1;
|
instance.speechKey = keys.key1;
|
||||||
|
|
||||||
GBLog.info(`Deploying Text Analytics...`);
|
GBLog.info(`Deploying Text Analytics...`);
|
||||||
const textAnalytics = await this.createTextAnalytics(name, `${name}-textanalytics`, instance.cloudLocation);
|
const textAnalytics = await this.createTextAnalytics(name, `${name}-textanalytics`, instance.cloudLocation);
|
||||||
instance.textAnalyticsEndpoint = textAnalytics.endpoint.replace(`/text/analytics/v2.0`, '');
|
instance.textAnalyticsEndpoint = textAnalytics.properties.endpoint.replace(`/text/analytics/v2.0`, '');
|
||||||
|
|
||||||
GBLog.info(`Deploying SpellChecker...`);
|
GBLog.info(`Deploying SpellChecker...`);
|
||||||
const spellChecker = await this.createSpellChecker(name, `${name}-spellchecker`);
|
const spellChecker = await this.createSpellChecker(name, `${name}-spellchecker`);
|
||||||
instance.spellcheckerEndpoint = spellChecker.endpoint;
|
instance.spellcheckerEndpoint = spellChecker.properties.endpoint;
|
||||||
|
|
||||||
GBLog.info(`Deploying NLP...`);
|
GBLog.info(`Deploying NLP...`);
|
||||||
const nlp = await this.createNLP(name, `${name}-nlp`, instance.cloudLocation);
|
const nlp = await this.createNLP(name, `${name}-nlp`, instance.cloudLocation);
|
||||||
const nlpa = await this.createNLPAuthoring(name, `${name}-nlpa`, instance.cloudLocation);
|
const nlpa = await this.createNLPAuthoring(name, `${name}-nlpa`, instance.cloudLocation);
|
||||||
instance.nlpEndpoint = nlp.endpoint;
|
instance.nlpEndpoint = nlp.properties.endpoint;
|
||||||
|
|
||||||
const sleep = ms => {
|
const sleep = ms => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
|
@ -435,18 +429,25 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
GBLog.info(`Deploying Bot...`);
|
GBLog.info(`Deploying Bot...`);
|
||||||
instance.botEndpoint = this.defaultEndPoint;
|
instance.botEndpoint = this.defaultEndPoint;
|
||||||
|
|
||||||
instance = await this.internalDeployBot(
|
instance = await this.internalDeployBot(
|
||||||
instance, this.accessToken, name, name, name, 'General BootBot',
|
instance,
|
||||||
`${proxyAddress}/api/messages/${name}`, 'global',
|
this.accessToken,
|
||||||
instance.nlpAppId, instance.nlpKey, instance.marketplaceId, instance.marketplacePassword,
|
name,
|
||||||
|
name,
|
||||||
|
name,
|
||||||
|
'General BootBot',
|
||||||
|
`${proxyAddress}/api/messages/${name}`,
|
||||||
|
'global',
|
||||||
|
instance.nlpAppId,
|
||||||
|
instance.nlpKey,
|
||||||
|
instance.marketplaceId,
|
||||||
|
instance.marketplacePassword,
|
||||||
instance.cloudSubscriptionId
|
instance.cloudSubscriptionId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
GBLog.info(`Waiting one minute to finishing NLP service and keys creation...`);
|
GBLog.info(`Waiting one minute to finishing NLP service and keys creation...`);
|
||||||
await sleep(60000);
|
await sleep(60000);
|
||||||
keys = await this.cognitiveClient.accounts.listKeys(name, textAnalytics.name);
|
keys = await this.cognitiveClient.accounts.listKeys(name, textAnalytics.name);
|
||||||
|
|
@ -461,7 +462,6 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
const nlpAppId = await this.createNLPService(name, name, instance.cloudLocation, culture, instance.nlpAuthoringKey);
|
const nlpAppId = await this.createNLPService(name, name, instance.cloudLocation, culture, instance.nlpAuthoringKey);
|
||||||
instance.nlpAppId = nlpAppId;
|
instance.nlpAppId = nlpAppId;
|
||||||
|
|
||||||
|
|
||||||
GBLog.info('Updating server environment variables...');
|
GBLog.info('Updating server environment variables...');
|
||||||
await this.updateWebisteConfig(name, serverName, serverFarm.id, instance);
|
await this.updateWebisteConfig(name, serverName, serverFarm.id, instance);
|
||||||
|
|
||||||
|
|
@ -470,7 +470,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async deployToCloud(
|
public async deployToCloud (
|
||||||
title: string,
|
title: string,
|
||||||
username: string,
|
username: string,
|
||||||
password: string,
|
password: string,
|
||||||
|
|
@ -501,7 +501,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
/**
|
/**
|
||||||
* @see https://github.com/Azure/azure-rest-api-specs/blob/master/specification/botservice/resource-manager/Microsoft.BotService/preview/2017-12-01/botservice.json
|
* @see https://github.com/Azure/azure-rest-api-specs/blob/master/specification/botservice/resource-manager/Microsoft.BotService/preview/2017-12-01/botservice.json
|
||||||
*/
|
*/
|
||||||
public async internalDeployBot(
|
public async internalDeployBot (
|
||||||
instance,
|
instance,
|
||||||
accessToken,
|
accessToken,
|
||||||
botId,
|
botId,
|
||||||
|
|
@ -540,13 +540,14 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
luisKey: nlpKey,
|
luisKey: nlpKey,
|
||||||
msaAppId: appId,
|
msaAppId: appId,
|
||||||
msaAppPassword: appPassword,
|
msaAppPassword: appPassword,
|
||||||
enabledChannels: ['webchat', "skype"],//, "facebook"],
|
enabledChannels: ['webchat', 'skype'], //, "facebook"],
|
||||||
configuredChannels: ['webchat', "skype"]//, "facebook"]
|
configuredChannels: ['webchat', 'skype'] //, "facebook"]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const httpClient = new ServiceClient();
|
const httpClient = new ServiceClient();
|
||||||
let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${this.provider
|
let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
|
||||||
|
this.provider
|
||||||
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
||||||
let url = urlJoin(baseUrl, query);
|
let url = urlJoin(baseUrl, query);
|
||||||
let req = AzureDeployerService.createRequestObject(url, accessToken, 'PUT', JSON.stringify(parameters));
|
let req = AzureDeployerService.createRequestObject(url, accessToken, 'PUT', JSON.stringify(parameters));
|
||||||
|
|
@ -557,10 +558,10 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//tslint:disable-next-line:max-line-length
|
//tslint:disable-next-line:max-line-length
|
||||||
query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/Microsoft.BotService/botServices/${botId}/channels/WebChatChannel/listChannelWithKeys?api-version=${this.apiVersion
|
query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/Microsoft.BotService/botServices/${botId}/channels/WebChatChannel/listChannelWithKeys?api-version=${
|
||||||
|
this.apiVersion
|
||||||
}`;
|
}`;
|
||||||
url = urlJoin(baseUrl, query);
|
url = urlJoin(baseUrl, query);
|
||||||
req = AzureDeployerService.createRequestObject(url, accessToken, 'POST', JSON.stringify(parameters));
|
req = AzureDeployerService.createRequestObject(url, accessToken, 'POST', JSON.stringify(parameters));
|
||||||
|
|
@ -572,16 +573,15 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async syncBotServerRepository(group, name) {
|
public async syncBotServerRepository (group, name) {
|
||||||
await this.webSiteClient.webApps.syncRepository(group, name);
|
await this.webSiteClient.webApps.syncRepository(group, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public initServices(credentials: any, subscriptionId: string) {
|
public initServices (credentials: any, subscriptionId: string) {
|
||||||
this.cloud = new ResourceManagementClient.default(credentials, subscriptionId);
|
this.cloud = new ResourceManagementClient(credentials, subscriptionId);
|
||||||
this.webSiteClient = new WebSiteManagementClient(credentials, subscriptionId);
|
this.webSiteClient = new WebSiteManagementClient(credentials, subscriptionId);
|
||||||
this.storageClient = new SqlManagementClient(credentials, subscriptionId);
|
this.storageClient = new SqlManagementClient(credentials, subscriptionId);
|
||||||
this.cognitiveClient = new CognitiveServicesManagementClient(credentials, subscriptionId);
|
this.cognitiveClient = new CognitiveServicesManagementClient(credentials, subscriptionId);
|
||||||
|
|
@ -589,7 +589,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
this.accessToken = credentials.tokenCache._entries[0].accessToken;
|
this.accessToken = credentials.tokenCache._entries[0].accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createStorageServer(group, name, administratorLogin, administratorPassword, serverName, location) {
|
private async createStorageServer (group, name, administratorLogin, administratorPassword, serverName, location) {
|
||||||
const params = {
|
const params = {
|
||||||
location: location,
|
location: location,
|
||||||
administratorLogin: administratorLogin,
|
administratorLogin: administratorLogin,
|
||||||
|
|
@ -597,7 +597,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
fullyQualifiedDomainName: serverName
|
fullyQualifiedDomainName: serverName
|
||||||
};
|
};
|
||||||
|
|
||||||
const database = await this.storageClient.servers.createOrUpdate(group, name, params);
|
const database = await this.storageClient.servers.beginCreateOrUpdateAndWait(group, name, params);
|
||||||
|
|
||||||
// AllowAllWindowsAzureIps must be created that way, so the Azure Search can
|
// AllowAllWindowsAzureIps must be created that way, so the Azure Search can
|
||||||
// access SQL Database to index its contents.
|
// access SQL Database to index its contents.
|
||||||
|
|
@ -611,7 +611,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
return database;
|
return database;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createApplication(token: string, name: string) {
|
public async createApplication (token: string, name: string) {
|
||||||
return new Promise<string>((resolve, reject) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
let client = MicrosoftGraph.Client.init({
|
let client = MicrosoftGraph.Client.init({
|
||||||
authProvider: done => {
|
authProvider: done => {
|
||||||
|
|
@ -624,16 +624,15 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
|
|
||||||
client.api(`/applications`).post(app, (err, res) => {
|
client.api(`/applications`).post(app, (err, res) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err)
|
reject(err);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
resolve(res);
|
resolve(res);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createApplicationSecret(token: string, appId: string) {
|
public async createApplicationSecret (token: string, appId: string) {
|
||||||
return new Promise<string>((resolve, reject) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
let client = MicrosoftGraph.Client.init({
|
let client = MicrosoftGraph.Client.init({
|
||||||
authProvider: done => {
|
authProvider: done => {
|
||||||
|
|
@ -642,22 +641,21 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
});
|
});
|
||||||
const body = {
|
const body = {
|
||||||
passwordCredential: {
|
passwordCredential: {
|
||||||
displayName: "General Bots Generated"
|
displayName: 'General Bots Generated'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
client.api(`/applications/${appId}/addPassword`).post(body, (err, res) => {
|
client.api(`/applications/${appId}/addPassword`).post(body, (err, res) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err)
|
reject(err);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
resolve(res.secretText);
|
resolve(res.secretText);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async registerProviders(subscriptionId, baseUrl, accessToken) {
|
private async registerProviders (subscriptionId, baseUrl, accessToken) {
|
||||||
const query = `subscriptions/${subscriptionId}/providers/${this.provider}/register?api-version=2018-02-01`;
|
const query = `subscriptions/${subscriptionId}/providers/${this.provider}/register?api-version=2018-02-01`;
|
||||||
const requestUrl = urlJoin(baseUrl, query);
|
const requestUrl = urlJoin(baseUrl, query);
|
||||||
|
|
||||||
|
|
@ -670,7 +668,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
(req.headers as any).Authorization = `Bearer ${accessToken}`;
|
(req.headers as any).Authorization = `Bearer ${accessToken}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createNLPService(
|
private async createNLPService (
|
||||||
name: string,
|
name: string,
|
||||||
description: string,
|
description: string,
|
||||||
location: string,
|
location: string,
|
||||||
|
|
@ -688,13 +686,12 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
|
|
||||||
let app = null;
|
let app = null;
|
||||||
if (apps.bodyAsText && apps.bodyAsText !== '[]') {
|
if (apps.bodyAsText && apps.bodyAsText !== '[]') {
|
||||||
const result = JSON.parse(apps.bodyAsText)
|
const result = JSON.parse(apps.bodyAsText);
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
if (result.error.code !== "401") {
|
if (result.error.code !== '401') {
|
||||||
throw new Error(result.error);
|
throw new Error(result.error);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
app = result.filter(x => x.name === name)[0];
|
app = result.filter(x => x.name === name)[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -709,7 +706,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
return id.replace(/\'/gi, '');
|
return id.replace(/\'/gi, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
private async makeNlpRequest(
|
private async makeNlpRequest (
|
||||||
location: string,
|
location: string,
|
||||||
authoringKey: string,
|
authoringKey: string,
|
||||||
body: string,
|
body: string,
|
||||||
|
|
@ -728,14 +725,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
return await httpClient.sendRequest(req);
|
return await httpClient.sendRequest(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async refreshEntityList(
|
public async refreshEntityList (location: string, nlpAppId: string, clEntityId: string, nlpKey: string, data: any) {
|
||||||
location: string,
|
|
||||||
nlpAppId: string,
|
|
||||||
clEntityId: string,
|
|
||||||
nlpKey: string,
|
|
||||||
data: any,
|
|
||||||
) {
|
|
||||||
|
|
||||||
const req = new WebResource();
|
const req = new WebResource();
|
||||||
req.method = 'PUT';
|
req.method = 'PUT';
|
||||||
req.url = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/apps/${nlpAppId}/versions/0.1/closedlists/${clEntityId}`;
|
req.url = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/apps/${nlpAppId}/versions/0.1/closedlists/${clEntityId}`;
|
||||||
|
|
@ -748,12 +738,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
return await httpClient.sendRequest(req);
|
return await httpClient.sendRequest(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async trainNLP(
|
public async trainNLP (location: string, nlpAppId: string, nlpAuthoringKey: string) {
|
||||||
location: string,
|
|
||||||
nlpAppId: string,
|
|
||||||
nlpAuthoringKey: string,
|
|
||||||
) {
|
|
||||||
|
|
||||||
const req = new WebResource();
|
const req = new WebResource();
|
||||||
req.method = 'POST';
|
req.method = 'POST';
|
||||||
req.url = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/apps/${nlpAppId}/versions/0.1/train`;
|
req.url = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/apps/${nlpAppId}/versions/0.1/train`;
|
||||||
|
|
@ -765,16 +750,12 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
return await httpClient.sendRequest(req);
|
return await httpClient.sendRequest(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async publishNLP(
|
public async publishNLP (location: string, nlpAppId: string, nlpAuthoringKey: string) {
|
||||||
location: string,
|
|
||||||
nlpAppId: string,
|
|
||||||
nlpAuthoringKey: string,
|
|
||||||
) {
|
|
||||||
const body = {
|
const body = {
|
||||||
versionId: "0.1",
|
versionId: '0.1',
|
||||||
isStaging: false,
|
isStaging: false,
|
||||||
directVersionPublish: false
|
directVersionPublish: false
|
||||||
}
|
};
|
||||||
const req = new WebResource();
|
const req = new WebResource();
|
||||||
req.method = 'POST';
|
req.method = 'POST';
|
||||||
req.url = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/apps/${nlpAppId}/publish`;
|
req.url = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/apps/${nlpAppId}/publish`;
|
||||||
|
|
@ -787,29 +768,28 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
return await httpClient.sendRequest(req);
|
return await httpClient.sendRequest(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createSearch(group, name, location) {
|
private async createSearch (group, name, location) {
|
||||||
const params = {
|
const params = {
|
||||||
sku: {
|
sku: {
|
||||||
name:
|
name: this.freeTier ? 'free' : 'standard'
|
||||||
this.freeTier ? 'free' : 'standard'
|
|
||||||
},
|
},
|
||||||
location: location
|
location: location
|
||||||
};
|
};
|
||||||
|
|
||||||
return await this.searchClient.services.createOrUpdate(group, name, params);
|
return await this.searchClient.services.beginCreateOrUpdateAndWait(group, name, params as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createStorage(group, serverName, name, location) {
|
private async createStorage (group, serverName, name, location) {
|
||||||
const params = {
|
const params = {
|
||||||
sku: { name: this.freeTier ? 'Free' : 'Basic' },
|
sku: { name: this.freeTier ? 'Free' : 'Basic' },
|
||||||
createMode: 'Default',
|
createMode: 'Default',
|
||||||
location: location
|
location: location
|
||||||
};
|
};
|
||||||
|
|
||||||
return await this.storageClient.databases.createOrUpdate(group, serverName, name, params);
|
return await this.storageClient.databases.beginCreateOrUpdateAndWait(group, serverName, name, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createCognitiveServices(group, name, location, kind): Promise<CognitiveServicesAccount> {
|
private async createCognitiveServices (group, name, location, kind): Promise<Account> {
|
||||||
const params = {
|
const params = {
|
||||||
sku: {
|
sku: {
|
||||||
name: name
|
name: name
|
||||||
|
|
@ -832,43 +812,43 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
params.sku.name = this.freeTier ? 'F0' : 'S0';
|
params.sku.name = this.freeTier ? 'F0' : 'S0';
|
||||||
}
|
}
|
||||||
|
|
||||||
return await this.cognitiveClient.accounts.create(group, name, params);
|
return await this.cognitiveClient.accounts.beginCreateAndWait(group, name, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createSpeech(group, name, location): Promise<CognitiveServicesAccount> {
|
private async createSpeech (group, name, location): Promise<Account> {
|
||||||
return await this.createCognitiveServices(group, name, location, 'SpeechServices');
|
return await this.createCognitiveServices(group, name, location, 'SpeechServices');
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createNLP(group, name, location): Promise<CognitiveServicesAccount> {
|
private async createNLP (group, name, location): Promise<Account> {
|
||||||
return await this.createCognitiveServices(group, name, location, 'LUIS');
|
return await this.createCognitiveServices(group, name, location, 'LUIS');
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createNLPAuthoring(group, name, location): Promise<CognitiveServicesAccount> {
|
private async createNLPAuthoring (group, name, location): Promise<Account> {
|
||||||
return await this.createCognitiveServices(group, name, location, 'LUIS.Authoring');
|
return await this.createCognitiveServices(group, name, location, 'LUIS.Authoring');
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createSpellChecker(group, name): Promise<CognitiveServicesAccount> {
|
private async createSpellChecker (group, name): Promise<Account> {
|
||||||
return await this.createCognitiveServices(group, name, 'westus', 'CognitiveServices');
|
return await this.createCognitiveServices(group, name, 'westus', 'CognitiveServices');
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createTextAnalytics(group, name, location): Promise<CognitiveServicesAccount> {
|
private async createTextAnalytics (group, name, location): Promise<Account> {
|
||||||
return await this.createCognitiveServices(group, name, location, 'TextAnalytics');
|
return await this.createCognitiveServices(group, name, location, 'TextAnalytics');
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createDeployGroup(name, location) {
|
private async createDeployGroup (name, location) {
|
||||||
const params = { location: location };
|
const params = { location: location };
|
||||||
|
|
||||||
return await this.cloud.resourceGroups.createOrUpdate(name, params);
|
return await this.cloud.resourceGroups.createOrUpdate(name, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async enableResourceProviders(name) {
|
private async enableResourceProviders (name) {
|
||||||
const ret = await this.cloud.providers.get(name);
|
const ret = await this.cloud.providers.get(name);
|
||||||
if (ret.registrationState === "NotRegistered") {
|
if (ret.registrationState === 'NotRegistered') {
|
||||||
await this.cloud.providers.register(name);
|
await this.cloud.providers.register(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createHostingPlan(group, name, location): Promise<AppServicePlan> {
|
private async createHostingPlan (group, name, location): Promise<AppServicePlan> {
|
||||||
const params = {
|
const params = {
|
||||||
serverFarmWithRichSkuName: name,
|
serverFarmWithRichSkuName: name,
|
||||||
location: location,
|
location: location,
|
||||||
|
|
@ -879,14 +859,12 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return await this.webSiteClient.appServicePlans.createOrUpdate(group, name, params);
|
return await this.webSiteClient.appServicePlans.beginCreateOrUpdateAndWait(group, name, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createServer(farmId, group, name, location) {
|
private async createServer (farmId, group, name, location) {
|
||||||
|
|
||||||
let tryed = false;
|
let tryed = false;
|
||||||
const create = async () => {
|
const create = async () => {
|
||||||
|
|
||||||
const parameters: Site = {
|
const parameters: Site = {
|
||||||
location: location,
|
location: location,
|
||||||
serverFarmId: farmId,
|
serverFarmId: farmId,
|
||||||
|
|
@ -897,7 +875,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
requestTracingEnabled: true
|
requestTracingEnabled: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const server = await this.webSiteClient.webApps.createOrUpdate(group, name, parameters);
|
const server = await this.webSiteClient.webApps.beginCreateOrUpdateAndWait(group, name, parameters);
|
||||||
|
|
||||||
const siteLogsConfig: SiteLogsConfig = {
|
const siteLogsConfig: SiteLogsConfig = {
|
||||||
applicationLogs: {
|
applicationLogs: {
|
||||||
|
|
@ -914,7 +892,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
deploymentRollbackEnabled: false
|
deploymentRollbackEnabled: false
|
||||||
};
|
};
|
||||||
|
|
||||||
await this.webSiteClient.webApps.createOrUpdateSourceControl(group, name, souceControlConfig);
|
await this.webSiteClient.webApps.beginCreateOrUpdateSourceControlAndWait(group, name, souceControlConfig);
|
||||||
return server;
|
return server;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -934,8 +912,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async updateWebisteConfig(group, name, serverFarmId, instance: IGBInstance) {
|
private async updateWebisteConfig (group, name, serverFarmId, instance: IGBInstance) {
|
||||||
|
|
||||||
const parameters: Site = {
|
const parameters: Site = {
|
||||||
location: instance.cloudLocation,
|
location: instance.cloudLocation,
|
||||||
serverFarmId: serverFarmId,
|
serverFarmId: serverFarmId,
|
||||||
|
|
@ -958,12 +935,11 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
{ name: 'STORAGE_NAME', value: `${instance.storageName}` },
|
{ name: 'STORAGE_NAME', value: `${instance.storageName}` },
|
||||||
{ name: 'STORAGE_USERNAME', value: `${instance.storageUsername}` },
|
{ name: 'STORAGE_USERNAME', value: `${instance.storageUsername}` },
|
||||||
{ name: 'STORAGE_PASSWORD', value: `${instance.storagePassword}` },
|
{ name: 'STORAGE_PASSWORD', value: `${instance.storagePassword}` },
|
||||||
{ name: 'STORAGE_SYNC', value: `true` }]
|
{ name: 'STORAGE_SYNC', value: `true` }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return await this.webSiteClient.webApps.createOrUpdate(group, name, parameters);
|
return await this.webSiteClient.webApps.beginCreateOrUpdateAndWait(group, name, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,36 +37,61 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||||
import { GuaribasSchedule } from '../core.gbapp/models/GBModel';
|
import { GuaribasSchedule } from '../core.gbapp/models/GBModel.js';
|
||||||
import { Sequelize } from 'sequelize-typescript';
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
|
import { createServerRouter } from 'typescript-rest-rpc/lib/server.js';
|
||||||
|
import { DialogKeywords } from './services/DialogKeywords.js';
|
||||||
|
import * as koaBody from 'koa-body';
|
||||||
|
import { SystemKeywords } from './services/SystemKeywords.js';
|
||||||
|
import { WebAutomationKeywords } from './services/WebAutomationKeywords.js';
|
||||||
|
import { DebuggerService } from './services/DebuggerService.js';
|
||||||
|
import Koa from 'koa';
|
||||||
|
|
||||||
|
const app = new Koa();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package for core.gbapp.
|
* Package for core.gbapp.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export class GBBasicPackage implements IGBPackage {
|
export class GBBasicPackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
public CurrentEngineName = "guaribas-1.0.0";
|
public CurrentEngineName = 'guaribas-1.0.0';
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
|
||||||
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
core.sequelize.addModels([GuaribasSchedule]);
|
core.sequelize.addModels([GuaribasSchedule]);
|
||||||
|
app.use(koaBody.koaBody({ multipart: true }));
|
||||||
|
app.listen(1111);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getDialogs(min: GBMinInstance) {
|
public async getDialogs (min: GBMinInstance) {
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {
|
||||||
|
const dk = new DialogKeywords(min, null, null);
|
||||||
|
const wa = new WebAutomationKeywords(min, null, dk);
|
||||||
|
const sys = new SystemKeywords(min, null, dk, wa);
|
||||||
|
const dbg = new DebuggerService(min, null, dk);
|
||||||
|
dk.wa = wa;
|
||||||
|
wa.sys = sys;
|
||||||
|
const dialogRouter = createServerRouter(`/api/v2/${min.botId}/dialog`, dk);
|
||||||
|
const waRouter = createServerRouter(`/api/v2/${min.botId}/webautomation`, wa);
|
||||||
|
const sysRouter = createServerRouter(`/api/v2/${min.botId}/system`, sys);
|
||||||
|
const dbgRouter = createServerRouter(`/api/v2/${min.botId}/debugger`, dbg);
|
||||||
|
app.use(dialogRouter.routes());
|
||||||
|
app.use(sysRouter.routes());
|
||||||
|
app.use(waRouter.routes());
|
||||||
|
app.use(dbgRouter.routes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,31 +49,29 @@ import {
|
||||||
UpdatedAt
|
UpdatedAt
|
||||||
} from 'sequelize-typescript';
|
} from 'sequelize-typescript';
|
||||||
|
|
||||||
import { GuaribasInstance } from '../../core.gbapp/models/GBModel';
|
import { GuaribasInstance } from '../../core.gbapp/models/GBModel.js';
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
//tslint:disable-next-line:max-classes-per-file
|
//tslint:disable-next-line:max-classes-per-file
|
||||||
export class GuaribasSchedule extends Model<GuaribasSchedule> {
|
export class GuaribasSchedule extends Model<GuaribasSchedule> {
|
||||||
|
@Column(DataType.STRING(255))
|
||||||
|
name: string;
|
||||||
|
|
||||||
@Column (DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public name: string;
|
schedule: string;
|
||||||
|
|
||||||
@Column (DataType.STRING(255))
|
|
||||||
public schedule: string;
|
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
instanceId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
public instance: GuaribasInstance;
|
instance: GuaribasInstance;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
public createdAt: Date;
|
createdAt: Date;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
public updatedAt: Date;
|
updatedAt: Date;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,27 +32,25 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
import { createBrowser } from '../../core.gbapp/services/GBSSR.js';
|
||||||
import { createBrowser } from '../../core.gbapp/services/GBSSR';
|
|
||||||
|
|
||||||
export class ChartServices {
|
export class ChartServices {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate chart image screenshot
|
* Generate chart image screenshot
|
||||||
* @param {object} options billboard.js generation option object
|
* @param {object} options billboard.js generation option object
|
||||||
* @param {string} path screenshot image full path with file name
|
* @param {string} path screenshot image full path with file name
|
||||||
*/
|
*/
|
||||||
public static async screenshot(args, path) {
|
public static async screenshot (args, path) {
|
||||||
const browser = await createBrowser(null);
|
const browser = await createBrowser(null);
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
|
|
||||||
// load billboard.js assets from CDN.
|
// load billboard.js assets from CDN.
|
||||||
await page.addStyleTag({ url: "https://cdn.jsdelivr.net/npm/billboard.js/dist/theme/datalab.min.css" });
|
await page.addStyleTag({ url: 'https://cdn.jsdelivr.net/npm/billboard.js/dist/theme/datalab.min.css' });
|
||||||
await page.addScriptTag({ url: "https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.pkgd.min.js" });
|
await page.addScriptTag({ url: 'https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.pkgd.min.js' });
|
||||||
|
|
||||||
await page.evaluate(`bb.generate(${JSON.stringify(args)});`);
|
await page.evaluate(`bb.generate(${JSON.stringify(args)});`);
|
||||||
|
|
||||||
const content = await page.$(".bb");
|
const content = await page.$('.bb');
|
||||||
|
|
||||||
await content.screenshot({
|
await content.screenshot({
|
||||||
path,
|
path,
|
||||||
|
|
|
||||||
328
packages/basic.gblib/services/DebuggerService.ts
Normal file
328
packages/basic.gblib/services/DebuggerService.ts
Normal file
|
|
@ -0,0 +1,328 @@
|
||||||
|
/*****************************************************************************\
|
||||||
|
| ( )_ _ |
|
||||||
|
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
||||||
|
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' 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. |
|
||||||
|
| |
|
||||||
|
\*****************************************************************************/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import { GBLog, GBMinInstance } from 'botlib';
|
||||||
|
import { GBServer } from '../../../src/app.js';
|
||||||
|
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||||
|
import { DialogKeywords } from './DialogKeywords.js';
|
||||||
|
import Fs from 'fs';
|
||||||
|
import Swagger from 'swagger-client';
|
||||||
|
import { spawn } from 'child_process';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Web Automation services of conversation to be called by BASIC.
|
||||||
|
*/
|
||||||
|
export class DebuggerService {
|
||||||
|
/**
|
||||||
|
* Reference to minimal bot instance.
|
||||||
|
*/
|
||||||
|
public min: GBMinInstance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the base system keywords functions to be called.
|
||||||
|
*/
|
||||||
|
public dk: DialogKeywords;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current user object to get BASIC properties read.
|
||||||
|
*/
|
||||||
|
public user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTML browser for conversation over page interaction.
|
||||||
|
*/
|
||||||
|
browser: any;
|
||||||
|
|
||||||
|
sys: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number used in this execution for HEAR calls (useful for SET SCHEDULE).
|
||||||
|
*/
|
||||||
|
hrOn: string;
|
||||||
|
|
||||||
|
userId: GuaribasUser;
|
||||||
|
debugWeb: boolean;
|
||||||
|
lastDebugWeb: Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SYSTEM account maxLines,when used with impersonated contexts (eg. running in SET SCHEDULE).
|
||||||
|
*/
|
||||||
|
maxLines: number = 2000;
|
||||||
|
|
||||||
|
conversationsMap = {};
|
||||||
|
watermarkMap = {};
|
||||||
|
static systemVariables = [
|
||||||
|
'AggregateError',
|
||||||
|
'Array',
|
||||||
|
'ArrayBuffer',
|
||||||
|
'Atomics',
|
||||||
|
'BigInt',
|
||||||
|
'BigInt64Array',
|
||||||
|
'BigUint64Array',
|
||||||
|
'Boolean',
|
||||||
|
'DataView',
|
||||||
|
'Date',
|
||||||
|
'Error',
|
||||||
|
'EvalError',
|
||||||
|
'FinalizationRegistry',
|
||||||
|
'Float32Array',
|
||||||
|
'Float64Array',
|
||||||
|
'Function',
|
||||||
|
'Headers',
|
||||||
|
'Infinity',
|
||||||
|
'Int16Array',
|
||||||
|
'Int32Array',
|
||||||
|
'Int8Array',
|
||||||
|
'Intl',
|
||||||
|
'JSON',
|
||||||
|
'Map',
|
||||||
|
'Math',
|
||||||
|
'NaN',
|
||||||
|
'Number',
|
||||||
|
'Object',
|
||||||
|
'Promise',
|
||||||
|
'Proxy',
|
||||||
|
'RangeError',
|
||||||
|
'ReferenceError',
|
||||||
|
'Reflect',
|
||||||
|
'RegExp',
|
||||||
|
'Request',
|
||||||
|
'Response',
|
||||||
|
'Set',
|
||||||
|
'SharedArrayBuffer',
|
||||||
|
'String',
|
||||||
|
'Symbol',
|
||||||
|
'SyntaxError',
|
||||||
|
'TypeError',
|
||||||
|
'URIError',
|
||||||
|
'Uint16Array',
|
||||||
|
'Uint32Array',
|
||||||
|
'Uint8Array',
|
||||||
|
'Uint8ClampedArray',
|
||||||
|
'VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL',
|
||||||
|
'WeakMap',
|
||||||
|
'WeakRef',
|
||||||
|
'WeakSet',
|
||||||
|
'WebAssembly',
|
||||||
|
'__defineGetter__',
|
||||||
|
'__defineSetter__',
|
||||||
|
'__lookupGetter__',
|
||||||
|
'__lookupSetter__',
|
||||||
|
'__proto__',
|
||||||
|
'clearImmediate',
|
||||||
|
'clearInterval',
|
||||||
|
'clearTimeout',
|
||||||
|
'console',
|
||||||
|
'constructor',
|
||||||
|
'decodeURI',
|
||||||
|
'decodeURIComponent',
|
||||||
|
'dss',
|
||||||
|
'encodeURI',
|
||||||
|
'encodeURIComponent',
|
||||||
|
'escape',
|
||||||
|
'eval',
|
||||||
|
'fetch',
|
||||||
|
'global',
|
||||||
|
'globalThis',
|
||||||
|
'hasOwnProperty',
|
||||||
|
'isFinite',
|
||||||
|
'isNaN',
|
||||||
|
'isPrototypeOf',
|
||||||
|
'parseFloat',
|
||||||
|
'parseInt',
|
||||||
|
'process',
|
||||||
|
'propertyIsEnumerable',
|
||||||
|
'setImmediate',
|
||||||
|
'setInterval',
|
||||||
|
'setTimeout',
|
||||||
|
'toLocaleString',
|
||||||
|
'toString',
|
||||||
|
'undefined',
|
||||||
|
'unescape',
|
||||||
|
'valueOf'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When creating this keyword facade,a bot instance is
|
||||||
|
* specified among the deployer service.
|
||||||
|
*/
|
||||||
|
constructor (min: GBMinInstance, user, dk) {
|
||||||
|
this.min = min;
|
||||||
|
this.user = user;
|
||||||
|
this.dk = dk;
|
||||||
|
|
||||||
|
this.debugWeb = this.min.core.getParam<boolean>(this.min.instance, 'Debug Web Automation', false);
|
||||||
|
|
||||||
|
const botId = min.botId;
|
||||||
|
|
||||||
|
GBServer.globals.debuggers[botId] = {};
|
||||||
|
GBServer.globals.debuggers[botId].state = 0;
|
||||||
|
GBServer.globals.debuggers[botId].breaks = [];
|
||||||
|
GBServer.globals.debuggers[botId].stateInfo = 'Stopped';
|
||||||
|
GBServer.globals.debuggers[botId].childProcess = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private client;
|
||||||
|
|
||||||
|
public async breakpoint ({ botId, line }) {
|
||||||
|
GBLog.info(`BASIC: Enabled breakpoint for ${botId} on ${line}.`);
|
||||||
|
GBServer.globals.debuggers[botId].breaks.push(Number.parseInt(line));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async resume ({ botId }) {
|
||||||
|
if (GBServer.globals.debuggers[botId].state === 2) {
|
||||||
|
const client = GBServer.globals.debuggers[botId].client;
|
||||||
|
await client.Debugger.resume();
|
||||||
|
GBServer.globals.debuggers[botId].state = 1;
|
||||||
|
GBServer.globals.debuggers[botId].stateInfo = 'Running (Debug)';
|
||||||
|
return { status: 'OK' };
|
||||||
|
} else {
|
||||||
|
const error = 'Invalid call to resume and state not being debug(2).';
|
||||||
|
return { error: error };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async stop ({ botId }) {
|
||||||
|
GBServer.globals.debuggers[botId].state = 0;
|
||||||
|
GBServer.globals.debuggers[botId].stateInfo = 'Stopped';
|
||||||
|
|
||||||
|
const kill = ref => {
|
||||||
|
spawn('sh', ['-c', `pkill -9 -f ${ref}`]);
|
||||||
|
};
|
||||||
|
|
||||||
|
kill(GBServer.globals.debuggers[botId].childProcess);
|
||||||
|
|
||||||
|
return { status: 'OK' };
|
||||||
|
}
|
||||||
|
|
||||||
|
public async step ({ botId }) {
|
||||||
|
if (GBServer.globals.debuggers[botId].state === 2) {
|
||||||
|
GBServer.globals.debuggers[botId].stateInfo = 'Break';
|
||||||
|
const client = GBServer.globals.debuggers[botId].client;
|
||||||
|
await client.Debugger.stepOver();
|
||||||
|
return { status: 'OK' };
|
||||||
|
} else {
|
||||||
|
const error = 'Invalid call to stepOver and state not being debug(2).';
|
||||||
|
return { error: error };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async context ({ botId }) {
|
||||||
|
const conversationId = this.conversationsMap[botId];
|
||||||
|
let messages = [];
|
||||||
|
if (this.client) {
|
||||||
|
const response = await this.client.Conversations.Conversations_GetActivities({
|
||||||
|
conversationId: conversationId,
|
||||||
|
watermark: this.watermarkMap[botId]
|
||||||
|
});
|
||||||
|
this.watermarkMap[botId] = response.obj.watermark;
|
||||||
|
let activities = response.obj.activites;
|
||||||
|
|
||||||
|
if (activities && activities.length) {
|
||||||
|
activities = activities.filter(m => m.from.id === botId && m.type === 'message');
|
||||||
|
if (activities.length) {
|
||||||
|
activities.forEach(activity => {
|
||||||
|
messages.push({ text: activity.text });
|
||||||
|
GBLog.info(`Debugger sending text to API: ${activity.text}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let messagesText = messages.join('\n');
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 'OK',
|
||||||
|
state: GBServer.globals.debuggers[botId].state,
|
||||||
|
messages: messagesText,
|
||||||
|
scope: GBServer.globals.debuggers[botId].scope,
|
||||||
|
scopeInfo: GBServer.globals.debuggers[botId].stateInfo
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getRunning ({ botId, botApiKey, scriptName }) {
|
||||||
|
let error;
|
||||||
|
botId = botId[0]; // TODO: Handle call in POST.
|
||||||
|
if (!GBServer.globals.debuggers[botId]) {
|
||||||
|
GBServer.globals.debuggers[botId] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scriptName) {
|
||||||
|
scriptName = 'start';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GBServer.globals.debuggers[botId].state === 1) {
|
||||||
|
error = `Cannot DEBUG an already running process. ${botId}`;
|
||||||
|
return { error: error };
|
||||||
|
} else if (GBServer.globals.debuggers[botId].state === 2) {
|
||||||
|
GBLog.info(`BASIC: Releasing execution ${botId} in DEBUG mode.`);
|
||||||
|
await this.resume({ botId });
|
||||||
|
return { status: 'OK' };
|
||||||
|
} else {
|
||||||
|
GBLog.info(`BASIC: Running ${botId} in DEBUG mode.`);
|
||||||
|
GBServer.globals.debuggers[botId].state = 1;
|
||||||
|
GBServer.globals.debuggers[botId].stateInfo = 'Running (Debug)';
|
||||||
|
|
||||||
|
let min: GBMinInstance = GBServer.globals.minInstances.filter(p => p.instance.botId === botId)[0];
|
||||||
|
|
||||||
|
this.client = await new Swagger({
|
||||||
|
spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')),
|
||||||
|
usePromise: true
|
||||||
|
});
|
||||||
|
this.client.clientAuthorizations.add(
|
||||||
|
'AuthorizationBotConnector',
|
||||||
|
new Swagger.ApiKeyAuthorization('Authorization', `Bearer ${min.instance.webchatKey}`, 'header')
|
||||||
|
);
|
||||||
|
const response = await this.client.Conversations.Conversations_StartConversation();
|
||||||
|
const conversationId = response.obj.conversationId;
|
||||||
|
this.conversationsMap[botId] = conversationId;
|
||||||
|
GBServer.globals.debugConversationId = conversationId;
|
||||||
|
|
||||||
|
this.client.Conversations.Conversations_PostActivity({
|
||||||
|
conversationId: conversationId,
|
||||||
|
activity: {
|
||||||
|
textFormat: 'plain',
|
||||||
|
text: `/calldbg ${scriptName}`,
|
||||||
|
type: 'message',
|
||||||
|
from: {
|
||||||
|
id: 'test',
|
||||||
|
name: 'test'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return { status: 'OK' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -33,13 +33,12 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { GBLog, GBMinInstance, GBService } from 'botlib';
|
import { GBLog, GBMinInstance, GBService } from 'botlib';
|
||||||
import { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { GBVMService } from '../../basic.gblib/services/GBVMService';
|
import { GBVMService } from '../../basic.gblib/services/GBVMService.js';
|
||||||
import { GuaribasSchedule } from '../../core.gbapp/models/GBModel';
|
import { GuaribasSchedule } from '../../core.gbapp/models/GBModel.js';
|
||||||
import { FindOptions } from 'sequelize/types';
|
|
||||||
|
|
||||||
const cron = require('node-cron');
|
import cron from 'node-cron';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fileoverview Schedule Services.
|
* @fileoverview Schedule Services.
|
||||||
|
|
@ -49,14 +48,12 @@ const cron = require('node-cron');
|
||||||
* Basic services for BASIC manipulation.
|
* Basic services for BASIC manipulation.
|
||||||
*/
|
*/
|
||||||
export class ScheduleServices extends GBService {
|
export class ScheduleServices extends GBService {
|
||||||
|
public async deleteScheduleIfAny (min: GBMinInstance, name: string) {
|
||||||
public async deleteScheduleIfAny(min: GBMinInstance, name: string) {
|
const task = min['scheduleMap'] ? min['scheduleMap'][name] : null;
|
||||||
|
|
||||||
const task = min["scheduleMap"] ? min["scheduleMap"][name] : null;
|
|
||||||
|
|
||||||
if (task) {
|
if (task) {
|
||||||
task.destroy();
|
task.destroy();
|
||||||
delete min["scheduleMap"][name];
|
delete min['scheduleMap'][name];
|
||||||
}
|
}
|
||||||
|
|
||||||
const count = await GuaribasSchedule.destroy({
|
const count = await GuaribasSchedule.destroy({
|
||||||
|
|
@ -74,11 +71,7 @@ export class ScheduleServices extends GBService {
|
||||||
/**
|
/**
|
||||||
* Finds and update user agent information to a next available person.
|
* Finds and update user agent information to a next available person.
|
||||||
*/
|
*/
|
||||||
public async createOrUpdateSchedule(
|
public async createOrUpdateSchedule (min: GBMinInstance, schedule: string, name: string): Promise<GuaribasSchedule> {
|
||||||
min: GBMinInstance,
|
|
||||||
schedule: string,
|
|
||||||
name: string
|
|
||||||
): Promise<GuaribasSchedule> {
|
|
||||||
let record = await GuaribasSchedule.findOne({
|
let record = await GuaribasSchedule.findOne({
|
||||||
where: {
|
where: {
|
||||||
instanceId: min.instance.instanceId,
|
instanceId: min.instance.instanceId,
|
||||||
|
|
@ -102,12 +95,10 @@ export class ScheduleServices extends GBService {
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load all cached schedule from BASIC SET SCHEDULE keyword.
|
* Load all cached schedule from BASIC SET SCHEDULE keyword.
|
||||||
*/
|
*/
|
||||||
public async scheduleAll() {
|
public async scheduleAll () {
|
||||||
|
|
||||||
let schedules;
|
let schedules;
|
||||||
try {
|
try {
|
||||||
schedules = await GuaribasSchedule.findAll();
|
schedules = await GuaribasSchedule.findAll();
|
||||||
|
|
@ -116,7 +107,7 @@ export class ScheduleServices extends GBService {
|
||||||
p => p.instance.instanceId === item.instanceId
|
p => p.instance.instanceId === item.instanceId
|
||||||
)[0];
|
)[0];
|
||||||
|
|
||||||
if (min){
|
if (min) {
|
||||||
this.ScheduleItem(item, min);
|
this.ScheduleItem(item, min);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -126,7 +117,7 @@ export class ScheduleServices extends GBService {
|
||||||
return schedules;
|
return schedules;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleItem(item: GuaribasSchedule, min: GBMinInstance) {
|
private ScheduleItem (item: GuaribasSchedule, min: GBMinInstance) {
|
||||||
GBLog.info(`Scheduling ${item.name} on ${min.botId}...`);
|
GBLog.info(`Scheduling ${item.name} on ${min.botId}...`);
|
||||||
try {
|
try {
|
||||||
const options = {
|
const options = {
|
||||||
|
|
@ -134,13 +125,13 @@ export class ScheduleServices extends GBService {
|
||||||
timezone: 'America/Sao_Paulo'
|
timezone: 'America/Sao_Paulo'
|
||||||
};
|
};
|
||||||
|
|
||||||
const task = min["scheduleMap"][item.name];
|
const task = min['scheduleMap'][item.name];
|
||||||
if (task) {
|
if (task) {
|
||||||
task.stop();
|
task.stop();
|
||||||
min["scheduleMap"][item.name] = null;
|
min['scheduleMap'][item.name] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
min["scheduleMap"][item.name] = cron.schedule(
|
min['scheduleMap'][item.name] = cron.schedule(
|
||||||
item.schedule,
|
item.schedule,
|
||||||
function () {
|
function () {
|
||||||
const finalData = async () => {
|
const finalData = async () => {
|
||||||
|
|
@ -148,14 +139,15 @@ export class ScheduleServices extends GBService {
|
||||||
let min: GBMinInstance = GBServer.globals.minInstances.filter(
|
let min: GBMinInstance = GBServer.globals.minInstances.filter(
|
||||||
p => p.instance.instanceId === item.instanceId
|
p => p.instance.instanceId === item.instanceId
|
||||||
)[0];
|
)[0];
|
||||||
await GBVMService.callVM(script, min, null, null);
|
await GBVMService.callVM(script, min, null, null, false);
|
||||||
};
|
};
|
||||||
(async () => {
|
(async () => {
|
||||||
await finalData();
|
await finalData();
|
||||||
})();
|
})();
|
||||||
}, options
|
},
|
||||||
|
options
|
||||||
);
|
);
|
||||||
GBLog.info(`Running .gbdialog word ${item.name} on:${item.schedule}...`);
|
GBLog.info(`Running .gbdialog word ${item.name} on:${item.schedule}...`);
|
||||||
} catch (error) { }
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -43,15 +43,15 @@ import * as ts from 'typescript';
|
||||||
* Wrapper for a TypeScript compiler.
|
* Wrapper for a TypeScript compiler.
|
||||||
*/
|
*/
|
||||||
export class TSCompiler {
|
export class TSCompiler {
|
||||||
|
private static shouldIgnoreError (diagnostic) {
|
||||||
private static shouldIgnoreError(diagnostic) {
|
|
||||||
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||||
|
|
||||||
if (message.indexOf('Cannot find name') >= 0
|
if (
|
||||||
|| message.indexOf('Cannot find module') >= 0
|
message.indexOf('Cannot find name') >= 0 ||
|
||||||
|| message.indexOf('implicitly has an') >= 0
|
message.indexOf('Cannot find module') >= 0 ||
|
||||||
|| message.indexOf('Cannot invoke an') >= 0
|
message.indexOf('implicitly has an') >= 0 ||
|
||||||
|| message.indexOf('Cannot use imports, exports, or module') >= 0
|
message.indexOf('Cannot invoke an') >= 0 ||
|
||||||
|
message.indexOf('Cannot use imports, exports, or module') >= 0
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -59,14 +59,14 @@ export class TSCompiler {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public compile(
|
public compile (
|
||||||
fileNames: string[],
|
fileNames: string[],
|
||||||
options: ts.CompilerOptions = {
|
options: ts.CompilerOptions = {
|
||||||
noStrictGenericChecks: true,
|
noStrictGenericChecks: true,
|
||||||
noImplicitUseStrict: true,
|
noImplicitUseStrict: true,
|
||||||
noEmitOnError: false,
|
noEmitOnError: false,
|
||||||
noImplicitAny: true,
|
noImplicitAny: true,
|
||||||
target: ts.ScriptTarget.ES5,
|
target: ts.ScriptTarget.ESNext,
|
||||||
module: ts.ModuleKind.None,
|
module: ts.ModuleKind.None,
|
||||||
moduleResolution: ts.ModuleResolutionKind.Classic,
|
moduleResolution: ts.ModuleResolutionKind.Classic,
|
||||||
noEmitHelpers: true,
|
noEmitHelpers: true,
|
||||||
|
|
@ -99,5 +99,4 @@ export class TSCompiler {
|
||||||
|
|
||||||
return emitResult;
|
return emitResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
386
packages/basic.gblib/services/WebAutomationKeywords.ts
Normal file
386
packages/basic.gblib/services/WebAutomationKeywords.ts
Normal file
|
|
@ -0,0 +1,386 @@
|
||||||
|
/*****************************************************************************\
|
||||||
|
| ( )_ _ |
|
||||||
|
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
||||||
|
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' 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. |
|
||||||
|
| |
|
||||||
|
\*****************************************************************************/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import { GBLog, GBMinInstance } from 'botlib';
|
||||||
|
import { GBServer } from '../../../src/app.js';
|
||||||
|
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
||||||
|
import { createBrowser } from '../../core.gbapp/services/GBSSR.js';
|
||||||
|
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||||
|
import { DialogKeywords } from './DialogKeywords.js';
|
||||||
|
|
||||||
|
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
|
||||||
|
import urlJoin from 'url-join';
|
||||||
|
import Fs from 'fs';
|
||||||
|
import Path from 'path';
|
||||||
|
import url from 'url';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Web Automation services of conversation to be called by BASIC.
|
||||||
|
*/
|
||||||
|
export class WebAutomationKeywords {
|
||||||
|
/**
|
||||||
|
* Reference to minimal bot instance.
|
||||||
|
*/
|
||||||
|
public min: GBMinInstance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the base system keywords functions to be called.
|
||||||
|
*/
|
||||||
|
public dk: DialogKeywords;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current user object to get BASIC properties read.
|
||||||
|
*/
|
||||||
|
public user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTML browser for conversation over page interaction.
|
||||||
|
*/
|
||||||
|
browser: any;
|
||||||
|
|
||||||
|
sys: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number used in this execution for HEAR calls (useful for SET SCHEDULE).
|
||||||
|
*/
|
||||||
|
hrOn: string;
|
||||||
|
|
||||||
|
userId: GuaribasUser;
|
||||||
|
debugWeb: boolean;
|
||||||
|
lastDebugWeb: Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SYSTEM account maxLines,when used with impersonated contexts (eg. running in SET SCHEDULE).
|
||||||
|
*/
|
||||||
|
maxLines: number = 2000;
|
||||||
|
|
||||||
|
pageMap = {};
|
||||||
|
|
||||||
|
cyrb53 = (str, seed = 0) => {
|
||||||
|
let h1 = 0xdeadbeef ^ seed,
|
||||||
|
h2 = 0x41c6ce57 ^ seed;
|
||||||
|
for (let i = 0, ch; i < str.length; i++) {
|
||||||
|
ch = str.charCodeAt(i);
|
||||||
|
h1 = Math.imul(h1 ^ ch, 2654435761);
|
||||||
|
h2 = Math.imul(h2 ^ ch, 1597334677);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
||||||
|
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
|
||||||
|
|
||||||
|
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When creating this keyword facade,a bot instance is
|
||||||
|
* specified among the deployer service.
|
||||||
|
*/
|
||||||
|
constructor (min: GBMinInstance, user, dk) {
|
||||||
|
this.min = min;
|
||||||
|
this.user = user;
|
||||||
|
this.dk = dk;
|
||||||
|
|
||||||
|
this.debugWeb = this.min.core.getParam<boolean>(this.min.instance, 'Debug Web Automation', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the page object.
|
||||||
|
*
|
||||||
|
* @example x = GET PAGE
|
||||||
|
*/
|
||||||
|
public async getPage ({ url, username, password }) {
|
||||||
|
GBLog.info(`BASIC: Web Automation GET PAGE ${url}.`);
|
||||||
|
if (!this.browser) {
|
||||||
|
this.browser = await createBrowser(null);
|
||||||
|
}
|
||||||
|
const page = (await this.browser.pages())[0];
|
||||||
|
if (username || password) {
|
||||||
|
await page.authenticate({ username: username, password: password });
|
||||||
|
}
|
||||||
|
await page.goto(url);
|
||||||
|
|
||||||
|
const handle = this.cyrb53(this.min.botId + url);
|
||||||
|
|
||||||
|
this.pageMap[handle] = page;
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPageByHandle (hash) {
|
||||||
|
return this.pageMap[hash];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find element on page DOM.
|
||||||
|
*
|
||||||
|
* @example GET page,"selector"
|
||||||
|
*/
|
||||||
|
public async getBySelector ({ handle, selector }) {
|
||||||
|
const page = this.getPageByHandle(handle);
|
||||||
|
GBLog.info(`BASIC: Web Automation GET element: ${selector}.`);
|
||||||
|
await page.waitForSelector(selector);
|
||||||
|
let elements = await page.$$(selector);
|
||||||
|
if (elements && elements.length > 1) {
|
||||||
|
return elements;
|
||||||
|
} else {
|
||||||
|
const el = elements[0];
|
||||||
|
el['originalSelector'] = selector;
|
||||||
|
el['href'] = await page.evaluate(e => e.getAttribute('href'), el);
|
||||||
|
el['value'] = await page.evaluate(e => e.getAttribute('value'), el);
|
||||||
|
el['name'] = await page.evaluate(e => e.getAttribute('name'), el);
|
||||||
|
el['class'] = await page.evaluate(e => e.getAttribute('class'), el);
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find element on page DOM.
|
||||||
|
*
|
||||||
|
* @example GET page,"frameSelector,"elementSelector"
|
||||||
|
*/
|
||||||
|
public async getByFrame ({ handle, frame, selector }) {
|
||||||
|
const page = this.getPageByHandle(handle);
|
||||||
|
GBLog.info(`BASIC: Web Automation GET element by frame: ${selector}.`);
|
||||||
|
await page.waitForSelector(frame);
|
||||||
|
let frameHandle = await page.$(frame);
|
||||||
|
const f = await frameHandle.contentFrame();
|
||||||
|
await f.waitForSelector(selector);
|
||||||
|
const element = await f.$(selector);
|
||||||
|
element['originalSelector'] = selector;
|
||||||
|
element['href'] = await f.evaluate(e => e.getAttribute('href'), element);
|
||||||
|
element['value'] = await f.evaluate(e => e.getAttribute('value'), element);
|
||||||
|
element['name'] = await f.evaluate(e => e.getAttribute('name'), element);
|
||||||
|
element['class'] = await f.evaluate(e => e.getAttribute('class'), element);
|
||||||
|
element['frame'] = f;
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simulates a mouse hover an web page element.
|
||||||
|
*/
|
||||||
|
public async hover ({ handle, selector }) {
|
||||||
|
const page = this.getPageByHandle(handle);
|
||||||
|
GBLog.info(`BASIC: Web Automation HOVER element: ${selector}.`);
|
||||||
|
await this.getBySelector({ handle, selector: selector });
|
||||||
|
await page.hover(selector);
|
||||||
|
await this.debugStepWeb(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clicks on an element in a web page.
|
||||||
|
*
|
||||||
|
* @example CLICK page,"#idElement"
|
||||||
|
*/
|
||||||
|
public async click ({ handle, frameOrSelector, selector }) {
|
||||||
|
const page = this.getPageByHandle(handle);
|
||||||
|
GBLog.info(`BASIC: Web Automation CLICK element: ${frameOrSelector}.`);
|
||||||
|
if (selector) {
|
||||||
|
await page.waitForSelector(frameOrSelector);
|
||||||
|
let frameHandle = await page.$(frameOrSelector);
|
||||||
|
const f = await frameHandle.contentFrame();
|
||||||
|
await f.waitForSelector(selector);
|
||||||
|
await f.click(selector);
|
||||||
|
} else {
|
||||||
|
await page.waitForSelector(frameOrSelector);
|
||||||
|
await page.click(frameOrSelector);
|
||||||
|
}
|
||||||
|
await this.debugStepWeb(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async debugStepWeb (page) {
|
||||||
|
let refresh = true;
|
||||||
|
if (this.lastDebugWeb) {
|
||||||
|
refresh = new Date().getTime() - this.lastDebugWeb.getTime() > 5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.debugWeb && refresh) {
|
||||||
|
const mobile = this.min.core.getParam(this.min.instance, 'Bot Admin Number', null);
|
||||||
|
const filename = page;
|
||||||
|
if (mobile) {
|
||||||
|
await this.dk.sendFileTo({ mobile, filename, caption: 'General Bots Debugger' });
|
||||||
|
}
|
||||||
|
this.lastDebugWeb = new Date();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Press ENTER in a web page,useful for logins.
|
||||||
|
*
|
||||||
|
* @example PRESS ENTER ON page
|
||||||
|
*/
|
||||||
|
public async pressKey ({ handle, char, frame }) {
|
||||||
|
const page = this.getPageByHandle(handle);
|
||||||
|
GBLog.info(`BASIC: Web Automation PRESS ${char} ON element: ${frame}.`);
|
||||||
|
if (char.toLowerCase() === 'enter') {
|
||||||
|
char = '\n';
|
||||||
|
}
|
||||||
|
if (frame) {
|
||||||
|
await page.waitForSelector(frame);
|
||||||
|
let frameHandle = await page.$(frame);
|
||||||
|
const f = await frameHandle.contentFrame();
|
||||||
|
await f.keyboard.press(char);
|
||||||
|
} else {
|
||||||
|
await page.keyboard.press(char);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async linkByText ({ handle, text, index }) {
|
||||||
|
const page = this.getPageByHandle(handle);
|
||||||
|
GBLog.info(`BASIC: Web Automation CLICK LINK TEXT: ${text} ${index}.`);
|
||||||
|
if (!index) {
|
||||||
|
index = 1;
|
||||||
|
}
|
||||||
|
const els = await page.$x(`//a[contains(.,'${text}')]`);
|
||||||
|
await els[index - 1].click();
|
||||||
|
await this.debugStepWeb(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the screenshot of page or element
|
||||||
|
*
|
||||||
|
* @example file = SCREENSHOT page
|
||||||
|
*/
|
||||||
|
public async screenshot ({ handle, selector }) {
|
||||||
|
const page = this.getPageByHandle(handle);
|
||||||
|
GBLog.info(`BASIC: Web Automation SCREENSHOT ${selector}.`);
|
||||||
|
|
||||||
|
const gbaiName = `${this.min.botId}.gbai`;
|
||||||
|
const localName = Path.join('work', gbaiName, 'cache', `screen-${GBAdminService.getRndReadableIdentifier()}.jpg`);
|
||||||
|
|
||||||
|
await page.screenshot({ path: localName });
|
||||||
|
|
||||||
|
const url = urlJoin(GBServer.globals.publicAddress, this.min.botId, 'cache', Path.basename(localName));
|
||||||
|
GBLog.info(`BASIC: WebAutomation: Screenshot captured at ${url}.`);
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types the text into the text field.
|
||||||
|
*
|
||||||
|
* @example SET page,"selector","text"
|
||||||
|
*/
|
||||||
|
public async setElementText ({ handle, selector, text }) {
|
||||||
|
const page = this.getPageByHandle(handle);
|
||||||
|
GBLog.info(`BASIC: Web Automation TYPE on ${selector}: ${text}.`);
|
||||||
|
const e = await this.getBySelector({ handle, selector });
|
||||||
|
await e.click({ clickCount: 3 });
|
||||||
|
await page.keyboard.press('Backspace');
|
||||||
|
await e.type(text, { delay: 200 });
|
||||||
|
await this.debugStepWeb(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the download to the .gbdrive Download folder.
|
||||||
|
*
|
||||||
|
* @example file = DOWNLOAD element, folder
|
||||||
|
*/
|
||||||
|
public async download ({ handle, selector, folder }) {
|
||||||
|
const page = this.getPageByHandle(handle);
|
||||||
|
const container = page; // TODO: element['_frame'] ? element['_frame'] : element['_page'];
|
||||||
|
const element = await this.getBySelector({ handle, selector });
|
||||||
|
await page.setRequestInterception(true);
|
||||||
|
await container.click(element.originalSelector);
|
||||||
|
|
||||||
|
const xRequest = await new Promise(resolve => {
|
||||||
|
page.on('request', interceptedRequest => {
|
||||||
|
interceptedRequest.abort(); //stop intercepting requests
|
||||||
|
resolve(interceptedRequest);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
encoding: null,
|
||||||
|
method: xRequest['._method'],
|
||||||
|
uri: xRequest['_url'],
|
||||||
|
body: xRequest['_postData'],
|
||||||
|
headers: xRequest['_headers']
|
||||||
|
};
|
||||||
|
|
||||||
|
const cookies = await page.cookies();
|
||||||
|
options.headers.Cookie = cookies.map(ck => ck.name + '=' + ck.value).join(';');
|
||||||
|
GBLog.info(`BASIC: DOWNLOADING '${options.uri}...'`);
|
||||||
|
|
||||||
|
let local;
|
||||||
|
let filename;
|
||||||
|
if (options.uri.indexOf('file://') != -1) {
|
||||||
|
local = url.fileURLToPath(options.uri);
|
||||||
|
filename = Path.basename(local);
|
||||||
|
} else {
|
||||||
|
const getBasenameFormUrl = urlStr => {
|
||||||
|
const url = new URL(urlStr);
|
||||||
|
return Path.basename(url.pathname);
|
||||||
|
};
|
||||||
|
filename = getBasenameFormUrl(options.uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result: Buffer;
|
||||||
|
if (local) {
|
||||||
|
result = Fs.readFileSync(local);
|
||||||
|
} else {
|
||||||
|
const res = await fetch(options.uri, options);
|
||||||
|
result = Buffer.from(await res.arrayBuffer());
|
||||||
|
}
|
||||||
|
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(this.min);
|
||||||
|
const botId = this.min.instance.botId;
|
||||||
|
|
||||||
|
// Normalizes all slashes.
|
||||||
|
|
||||||
|
folder = folder.replace(/\\/gi, '/');
|
||||||
|
|
||||||
|
// Determines full path at source and destination.
|
||||||
|
|
||||||
|
const root = urlJoin(`/${botId}.gbai/${botId}.gbdrive`);
|
||||||
|
const dstPath = urlJoin(root, folder, filename);
|
||||||
|
|
||||||
|
// Checks if the destination contains subfolders that
|
||||||
|
// need to be created.
|
||||||
|
|
||||||
|
folder = await this.sys.createFolder(folder);
|
||||||
|
|
||||||
|
// Performs the conversion operation getting a reference
|
||||||
|
// to the source and calling /content on drive API.
|
||||||
|
let file;
|
||||||
|
try {
|
||||||
|
file = await client.api(`${baseUrl}/drive/root:/${dstPath}:/content`).put(result);
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code === 'nameAlreadyExists') {
|
||||||
|
GBLog.info(`BASIC: DOWNLOAD destination file already exists: ${dstPath}.`);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,31 +1,32 @@
|
||||||
// Source: https://github.com/uweg/vbscript-to-typescript
|
// Source: https://github.com/uweg/vbscript-to-typescript
|
||||||
"use strict";
|
'use strict';
|
||||||
exports.__esModule = true;
|
|
||||||
var fs_1 = require("fs");
|
import fs_1 from 'fs';
|
||||||
var path = require("path");
|
import path from 'path';
|
||||||
function convertFile(file) {
|
|
||||||
|
export function convertFile (file) {
|
||||||
var extension = path.extname(file);
|
var extension = path.extname(file);
|
||||||
var withoutExtension = file.substr(0, file.length - extension.length);
|
var withoutExtension = file.substr(0, file.length - extension.length);
|
||||||
var targetFile = withoutExtension + ".ts";
|
var targetFile = withoutExtension + '.ts';
|
||||||
var baseName = path.basename(file, extension);
|
var baseName = path.basename(file, extension);
|
||||||
var content = fs_1.readFileSync(file, 'utf8');
|
var content = fs_1.readFileSync(file, 'utf8');
|
||||||
var result = convert(content, baseName);
|
var result = convert(content, baseName);
|
||||||
console.log("Writing to \"" + targetFile + "\"...");
|
console.log('Writing to "' + targetFile + '"...');
|
||||||
fs_1.writeFileSync(targetFile, result);
|
fs_1.writeFileSync(targetFile, result);
|
||||||
}
|
}
|
||||||
exports.convertFile = convertFile;
|
|
||||||
function convert(input, name) {
|
export function convert (input, name) {
|
||||||
var result = convertImports(input, name);
|
var result = convertImports(input, name);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convert = convert;
|
|
||||||
function convertImports(input, name) {
|
function convertImports (input, name) {
|
||||||
var items = [];
|
var items = [];
|
||||||
var result = input.replace(/<!-- #include file="(.*?\/)?(.*?).asp" -->/gi, function (input, group1, group2) {
|
var result = input.replace(/<!-- #include file="(.*?\/)?(.*?).asp" -->/gi, function (input, group1, group2) {
|
||||||
var path = group1 || './';
|
var path = group1 || './';
|
||||||
var file = "" + path + group2;
|
var file = '' + path + group2;
|
||||||
items.push({ name: group2, path: file });
|
items.push({ name: group2, path: file });
|
||||||
return "<%\n" + group2 + "();\n%>";
|
return '<%\n' + group2 + '();\n%>';
|
||||||
});
|
});
|
||||||
result = convertCode(result);
|
result = convertCode(result);
|
||||||
result = convertExpressions(result);
|
result = convertExpressions(result);
|
||||||
|
|
@ -33,12 +34,12 @@ function convertImports(input, name) {
|
||||||
|
|
||||||
for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
|
for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
|
||||||
var item = items_1[_i];
|
var item = items_1[_i];
|
||||||
result = "import {" + item.name + "} from \"" + item.path + "\"\n" + result;
|
result = 'import {' + item.name + '} from "' + item.path + '"\n' + result;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertImports = convertImports;
|
|
||||||
function convertCode(input) {
|
function convertCode (input) {
|
||||||
var result = input.replace(/<%([^=][\s\S]*?)%>/gi, function (input, group1) {
|
var result = input.replace(/<%([^=][\s\S]*?)%>/gi, function (input, group1) {
|
||||||
var code = group1;
|
var code = group1;
|
||||||
code = convertComments(code);
|
code = convertComments(code);
|
||||||
|
|
@ -49,109 +50,107 @@ function convertCode(input) {
|
||||||
code = convertLoops(code);
|
code = convertLoops(code);
|
||||||
code = convertPRec(code);
|
code = convertPRec(code);
|
||||||
code = convertPLan(code);
|
code = convertPLan(code);
|
||||||
return "<%" + code + "%>";
|
return '<%' + code + '%>';
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertCode = convertCode;
|
|
||||||
function convertExpressions(input) {
|
function convertExpressions (input) {
|
||||||
var result = input.replace(/<%=([\s\S]*?)%>/gi, function (input, group1) {
|
var result = input.replace(/<%=([\s\S]*?)%>/gi, function (input, group1) {
|
||||||
var content = convertPRec(group1);
|
var content = convertPRec(group1);
|
||||||
content = convertPLan(content);
|
content = convertPLan(content);
|
||||||
return "${" + content + "}";
|
return '${' + content + '}';
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertExpressions = convertExpressions;
|
|
||||||
function convertStrings(input) {
|
function convertStrings (input) {
|
||||||
var result = input.replace(/%>([\s\S]+?)<%/gi, "\nResponse.Write(`$1`);\n");
|
var result = input.replace(/%>([\s\S]+?)<%/gi, '\nResponse.Write(`$1`);\n');
|
||||||
// Entire document is a string
|
// Entire document is a string
|
||||||
if (result.indexOf("<%") === -1) {
|
if (result.indexOf('<%') === -1) {
|
||||||
result = "Response.Write(`" + result + "`);";
|
result = 'Response.Write(`' + result + '`);';
|
||||||
}
|
}
|
||||||
// Start of the document is a string
|
// Start of the document is a string
|
||||||
var firstIndex = result.indexOf("<%");
|
var firstIndex = result.indexOf('<%');
|
||||||
if (firstIndex > 0) {
|
if (firstIndex > 0) {
|
||||||
result = "Response.Write(`" + result.substr(0, firstIndex) + "`);\n" + result.substring(firstIndex + 2);
|
result = 'Response.Write(`' + result.substr(0, firstIndex) + '`);\n' + result.substring(firstIndex + 2);
|
||||||
}
|
}
|
||||||
result = result.replace(/%>$/, "");
|
result = result.replace(/%>$/, '');
|
||||||
// End of the document is a string
|
// End of the document is a string
|
||||||
var lastIndex = result.lastIndexOf("%>");
|
var lastIndex = result.lastIndexOf('%>');
|
||||||
if (lastIndex > -1 && lastIndex < result.length - 2) {
|
if (lastIndex > -1 && lastIndex < result.length - 2) {
|
||||||
result = result.substr(0, lastIndex) + "\nResponse.Write(`" + result.substr(lastIndex + 3) + "`);";
|
result = result.substr(0, lastIndex) + '\nResponse.Write(`' + result.substr(lastIndex + 3) + '`);';
|
||||||
}
|
}
|
||||||
result = result.replace(/^<%/, "");
|
result = result.replace(/^<%/, '');
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertStrings = convertStrings;
|
|
||||||
function convertComments(input) {
|
function convertComments (input) {
|
||||||
var result = '';
|
var result = '';
|
||||||
var splitted = input.split(/(".*")/gim);
|
var splitted = input.split(/(".*")/gim);
|
||||||
for (var _i = 0, splitted_1 = splitted; _i < splitted_1.length; _i++) {
|
for (var _i = 0, splitted_1 = splitted; _i < splitted_1.length; _i++) {
|
||||||
var part = splitted_1[_i];
|
var part = splitted_1[_i];
|
||||||
if (part.indexOf("\"") === 0) {
|
if (part.indexOf('"') === 0) {
|
||||||
result += part;
|
result += part;
|
||||||
}
|
} else {
|
||||||
else {
|
result += part.replace(/'/gi, '//');
|
||||||
result += part.replace(/'/gi, "//");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertComments = convertComments;
|
|
||||||
function convertIfStatements(input) {
|
function convertIfStatements (input) {
|
||||||
var result = input.replace(/if +(.*?) +then/gi, function (input, group1) {
|
var result = input.replace(/if +(.*?) +then/gi, function (input, group1) {
|
||||||
var condition = convertConditions(group1);
|
var condition = convertConditions(group1);
|
||||||
return "\nif (" + condition + ") {\n";
|
return '\nif (' + condition + ') {\n';
|
||||||
});
|
});
|
||||||
result = result.replace(/end if/gi, "\n}\n");
|
result = result.replace(/end if/gi, '\n}\n');
|
||||||
result = result.replace(/else(?!{)/gi, "\n}\nelse {\n");
|
result = result.replace(/else(?!{)/gi, '\n}\nelse {\n');
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertIfStatements = convertIfStatements;
|
|
||||||
function convertSwitchStatements(input) {
|
function convertSwitchStatements (input) {
|
||||||
var result = input.replace(/select case +(.*)/gi, "\nswitch ($1) {\n");
|
var result = input.replace(/select case +(.*)/gi, '\nswitch ($1) {\n');
|
||||||
result = result.replace(/end select/gi, "\n}\n");
|
result = result.replace(/end select/gi, '\n}\n');
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertSwitchStatements = convertSwitchStatements;
|
|
||||||
function convertFunctions(input) {
|
function convertFunctions (input) {
|
||||||
var result = input.replace(/function +(.*)\((.*)\)/gi, "\n$1 = ($2) => {\n");
|
var result = input.replace(/function +(.*)\((.*)\)/gi, '\n$1 = ($2) => {\n');
|
||||||
result = result.replace(/end function/gi, "\n}\n");
|
result = result.replace(/end function/gi, '\n}\n');
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertFunctions = convertFunctions;
|
|
||||||
function convertForStatements(input) {
|
function convertForStatements (input) {
|
||||||
var result = input.replace(/for +(.*to.*)/gi, "\nfor ($1) {\n");
|
var result = input.replace(/for +(.*to.*)/gi, '\nfor ($1) {\n');
|
||||||
result = result.replace(/^ *next *$/gim, "}\n");
|
result = result.replace(/^ *next *$/gim, '}\n');
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertForStatements = convertForStatements;
|
|
||||||
function convertConditions(input) {
|
function convertConditions (input) {
|
||||||
var result = input.replace(/ +and +/gi, " && ");
|
var result = input.replace(/ +and +/gi, ' && ');
|
||||||
result = result.replace(/ +or +/gi, " || ");
|
result = result.replace(/ +or +/gi, ' || ');
|
||||||
result = result.replace(/ +<> +/gi, " !== ");
|
result = result.replace(/ +<> +/gi, ' !== ');
|
||||||
result = result.replace(/ += +/gi, " === ");
|
result = result.replace(/ += +/gi, ' === ');
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertConditions = convertConditions;
|
|
||||||
function convertLoops(input) {
|
function convertLoops (input) {
|
||||||
var result = input.replace(/do while +(.*)/gi, function (input, group1) {
|
var result = input.replace(/do while +(.*)/gi, function (input, group1) {
|
||||||
var condition = convertConditions(group1);
|
var condition = convertConditions(group1);
|
||||||
return "\nwhile (" + condition + ") {\n";
|
return '\nwhile (' + condition + ') {\n';
|
||||||
});
|
});
|
||||||
|
|
||||||
result = result.replace(/^ *loop *$/gim, "}\n");
|
result = result.replace(/^ *loop *$/gim, '}\n');
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertLoops = convertLoops;
|
|
||||||
function convertPRec(input) {
|
function convertPRec (input) {
|
||||||
var result = input.replace(/(p_rec\("\S+?"\))/gi, "$1.Value");
|
var result = input.replace(/(p_rec\("\S+?"\))/gi, '$1.Value');
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertPRec = convertPRec;
|
|
||||||
function convertPLan(input) {
|
function convertPLan (input) {
|
||||||
var result = input.replace(/(l_\S+?)\(p_lan\)/gi, "$1[p_lan]");
|
var result = input.replace(/(l_\S+?)\(p_lan\)/gi, '$1[p_lan]');
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
exports.convertPLan = convertPLan;
|
|
||||||
|
|
|
||||||
213
packages/basic.gblib/services/vm2-process/index.ts
Normal file
213
packages/basic.gblib/services/vm2-process/index.ts
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
import crypto2 from 'crypto';
|
||||||
|
import { spawn } from 'child_process';
|
||||||
|
import CDP from 'chrome-remote-interface';
|
||||||
|
import {} from 'child_process';
|
||||||
|
import net from 'net';
|
||||||
|
import { GBLog } from 'botlib';
|
||||||
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
|
import { GBServer } from '../../../../src/app.js';
|
||||||
|
import { DebuggerService } from '../DebuggerService.js';
|
||||||
|
import finalStream from 'final-stream';
|
||||||
|
|
||||||
|
const waitUntil = condition => {
|
||||||
|
if (condition()) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
if (!condition()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearInterval(interval);
|
||||||
|
resolve(0);
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createVm2Pool = ({ min, max, ...limits }) => {
|
||||||
|
limits = Object.assign(
|
||||||
|
{
|
||||||
|
cpu: 100,
|
||||||
|
memory: 2000,
|
||||||
|
time: 4000
|
||||||
|
},
|
||||||
|
limits
|
||||||
|
);
|
||||||
|
|
||||||
|
let limitError = null;
|
||||||
|
|
||||||
|
const ref = crypto2.randomBytes(20).toString('hex');
|
||||||
|
|
||||||
|
const kill = x => {
|
||||||
|
spawn('sh', ['-c', `pkill -9 -f ${ref}`]);
|
||||||
|
};
|
||||||
|
|
||||||
|
let stderrCache = '';
|
||||||
|
|
||||||
|
const run = async (code, scope) => {
|
||||||
|
const childProcess = spawn(
|
||||||
|
'cpulimit',
|
||||||
|
[
|
||||||
|
'-ql',
|
||||||
|
limits.cpu,
|
||||||
|
'--',
|
||||||
|
'node',
|
||||||
|
`${limits.debug ? '--inspect=' + limits.debuggerPort : ''}`,
|
||||||
|
`--experimental-fetch`,
|
||||||
|
`--max-old-space-size=${limits.memory}`,
|
||||||
|
limits.script,
|
||||||
|
ref
|
||||||
|
],
|
||||||
|
{ cwd: limits.cwd, shell: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
childProcess.stdout.on('data', data => {
|
||||||
|
childProcess['socket'] = childProcess['socket'] || data.toString().trim();
|
||||||
|
});
|
||||||
|
|
||||||
|
childProcess.stderr.on('data', data => {
|
||||||
|
stderrCache = stderrCache + data.toString();
|
||||||
|
if (stderrCache.includes('failed: address already in use')) {
|
||||||
|
limitError = stderrCache;
|
||||||
|
kill(process);
|
||||||
|
GBServer.globals.debuggers[limits.botId].state = 0;
|
||||||
|
GBServer.globals.debuggers[limits.botId].stateInfo = stderrCache;
|
||||||
|
} else if (
|
||||||
|
stderrCache.includes('FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory')
|
||||||
|
) {
|
||||||
|
limitError = 'code execution exceeed allowed memory';
|
||||||
|
kill(process);
|
||||||
|
GBServer.globals.debuggers[limits.botId].state = 0;
|
||||||
|
GBServer.globals.debuggers[limits.botId].stateInfo = 'Fail';
|
||||||
|
} else if (stderrCache.includes('Debugger attached.')) {
|
||||||
|
GBLog.info(`BASIC: General Bots Debugger attached to Node .gbdialog process for ${limits.botId}.`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let socket = null;
|
||||||
|
await waitUntil(() => childProcess['socket']);
|
||||||
|
|
||||||
|
GBServer.globals.debuggers[limits.botId].childProcess = ref;
|
||||||
|
|
||||||
|
// Only attach if called by debugger/run.
|
||||||
|
|
||||||
|
if (GBServer.globals.debuggers[limits.botId]) {
|
||||||
|
const debug = async () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
CDP(async client => {
|
||||||
|
const { Debugger, Runtime } = client;
|
||||||
|
try {
|
||||||
|
GBServer.globals.debuggers[limits.botId].client = client;
|
||||||
|
|
||||||
|
await client.Debugger.paused(async ({ callFrames, reason, hitBreakpoints }) => {
|
||||||
|
const frame = callFrames[0];
|
||||||
|
|
||||||
|
// Build variable list ignoring system variables of script.
|
||||||
|
|
||||||
|
const scopeObjectId = frame.scopeChain[2].object.objectId;
|
||||||
|
const variables = await Runtime.getProperties({ objectId: scopeObjectId });
|
||||||
|
let variablesText = '';
|
||||||
|
if (variables && variables.result) {
|
||||||
|
await CollectionUtil.asyncForEach(variables.result, async v => {
|
||||||
|
if (!DebuggerService.systemVariables.filter(x => x === v.name)[0]) {
|
||||||
|
if (v.value.value) {
|
||||||
|
variablesText = `${variablesText} \n ${v.name}: ${v.value.value}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
GBServer.globals.debuggers[limits.botId].scope = variablesText;
|
||||||
|
GBLog.info(`BASIC: Breakpoint variables: ${variablesText}`); // (zero-based)
|
||||||
|
|
||||||
|
// Processes breakpoint hits.
|
||||||
|
|
||||||
|
if (hitBreakpoints.length >= 1) {
|
||||||
|
GBLog.info(`BASIC: Break at line ${frame.location.lineNumber + 1}`); // (zero-based)
|
||||||
|
|
||||||
|
GBServer.globals.debuggers[limits.botId].state = 2;
|
||||||
|
GBServer.globals.debuggers[limits.botId].stateInfo = 'Break';
|
||||||
|
} else {
|
||||||
|
GBLog.verbose(`BASIC: Configuring breakpoints if any for ${limits.botId}...`);
|
||||||
|
// Waits for debugger and setup breakpoints.
|
||||||
|
|
||||||
|
await CollectionUtil.asyncForEach(GBServer.globals.debuggers[limits.botId].breaks, async brk => {
|
||||||
|
try {
|
||||||
|
const { breakpointId } = await client.Debugger.setBreakpoint({
|
||||||
|
location: {
|
||||||
|
scriptId: frame.location.scriptId,
|
||||||
|
lineNumber: brk
|
||||||
|
}
|
||||||
|
});
|
||||||
|
GBLog.info(`BASIC break defined ${breakpointId} for ${limits.botId}`);
|
||||||
|
} catch (error) {
|
||||||
|
GBLog.info(`BASIC error defining defining ${brk} for ${limits.botId}. ${error}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await client.Debugger.resume();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await client.Runtime.runIfWaitingForDebugger();
|
||||||
|
await client.Debugger.enable();
|
||||||
|
await client.Runtime.enable();
|
||||||
|
|
||||||
|
resolve(1);
|
||||||
|
} catch (err) {
|
||||||
|
GBLog.error(err);
|
||||||
|
kill(childProcess);
|
||||||
|
GBServer.globals.debuggers[limits.botId].state = 0;
|
||||||
|
GBServer.globals.debuggers[limits.botId].stateInfo = 'Stopped';
|
||||||
|
}
|
||||||
|
}).on('error', err => {
|
||||||
|
console.error(err);
|
||||||
|
kill(childProcess);
|
||||||
|
GBServer.globals.debuggers[limits.botId].state = 0;
|
||||||
|
GBServer.globals.debuggers[limits.botId].stateInfo = 'Stopped';
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
await debug();
|
||||||
|
}
|
||||||
|
socket = net.createConnection(childProcess['socket']);
|
||||||
|
socket.write(JSON.stringify({ code, scope }) + '\n');
|
||||||
|
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
limitError = 'code execution took too long and was killed';
|
||||||
|
|
||||||
|
kill(childProcess);
|
||||||
|
GBServer.globals.debuggers[limits.botId].state = 0;
|
||||||
|
GBServer.globals.debuggers[limits.botId].stateInfo = limitError;
|
||||||
|
}, limits.time);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let data = await finalStream(socket);
|
||||||
|
|
||||||
|
data = JSON.parse(data);
|
||||||
|
|
||||||
|
if (!data.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (data.error) {
|
||||||
|
throw new Error(data.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.result;
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(limitError || error);
|
||||||
|
} finally {
|
||||||
|
kill(childProcess);
|
||||||
|
|
||||||
|
GBServer.globals.debuggers[limits.botId].state = 0;
|
||||||
|
GBServer.globals.debuggers[limits.botId].stateInfo = 'Stopped';
|
||||||
|
clearTimeout(timer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
run
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { VMScript, NodeVM } from 'vm2';
|
||||||
|
import crypto1 from 'crypto';
|
||||||
|
import net1 from 'net';
|
||||||
|
|
||||||
|
const evaluate = async (script, scope) => {
|
||||||
|
const vm = new NodeVM({
|
||||||
|
allowAsync: true,
|
||||||
|
sandbox: {},
|
||||||
|
console: 'inherit',
|
||||||
|
wrapper: 'none',
|
||||||
|
require: {
|
||||||
|
builtin: ['stream', 'http', 'https', 'url', 'buffer', 'zlib', 'isomorphic-fetch', 'punycode', 'encoding'],
|
||||||
|
root: ['./'],
|
||||||
|
external: true,
|
||||||
|
context: 'sandbox'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const s = new VMScript(script, scope);
|
||||||
|
return await vm.run(script, scope);
|
||||||
|
};
|
||||||
|
|
||||||
|
const socketName = crypto1.randomBytes(20).toString('hex');
|
||||||
|
|
||||||
|
const server = net1.createServer(socket => {
|
||||||
|
const buffer = [];
|
||||||
|
|
||||||
|
const sync = async () => {
|
||||||
|
const request = buffer.join('').toString();
|
||||||
|
if (request.includes('\n')) {
|
||||||
|
try {
|
||||||
|
const { code, scope } = JSON.parse(request);
|
||||||
|
const result = await evaluate(code, {
|
||||||
|
...scope,
|
||||||
|
module: null
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(JSON.stringify({ result }));
|
||||||
|
socket.write(JSON.stringify({ result }) + '\n');
|
||||||
|
socket.end();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`BASIC: RUNTIME: ${error.message}, ${error.stack}`);
|
||||||
|
socket.write(JSON.stringify({ error: error.message }) + '\n');
|
||||||
|
socket.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.on('data', data => {
|
||||||
|
buffer.push(data);
|
||||||
|
sync();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on('listening', () => {
|
||||||
|
console.log(`/tmp/vm2-${socketName}.sock`);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(`/tmp/vm2-${socketName}.sock`);
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
export const Messages = {
|
export const Messages = {
|
||||||
'en-US': {
|
'en-US': {
|
||||||
affirmative_sentences: /^(\bsim\b|\bs\b|\bpositivo\b|\bafirmativo\b|\bclaro\b|\bevidente\b|\bsem dúvida\b|\bconfirmo\b|\bconfirmar\b|\bconfirmado\b|\buhum\b|\bsi\b|\by\b|\byes\b|\bsure\b)/i,
|
affirmative_sentences: /^(\bsim\b|\bs\b|\bpositivo\b|\bafirmativo\b|\bclaro\b|\bevidente\b|\bsem dúvida\b|\bconfirmo\b|\bconfirmar\b|\bconfirmado\b|\buhum\b|\bsi\b|\by\b|\byes\b|\bsure\b)/i,
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||||
import { Sequelize } from 'sequelize-typescript';
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
import { ConsoleDirectLine } from './services/ConsoleDirectLine';
|
import { ConsoleDirectLine } from './services/ConsoleDirectLine.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package for console.glib.
|
* Package for console.glib.
|
||||||
|
|
@ -46,25 +46,25 @@ import { ConsoleDirectLine } from './services/ConsoleDirectLine';
|
||||||
export class GBConsolePackage implements IGBPackage {
|
export class GBConsolePackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
public channel: ConsoleDirectLine;
|
public channel: ConsoleDirectLine;
|
||||||
public async getDialogs(min: GBMinInstance) {
|
public async getDialogs (min: GBMinInstance) {
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
GBLog.verbose(`loadPackage called.`);
|
GBLog.verbose(`loadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {
|
||||||
this.channel = new ConsoleDirectLine(min.instance.webchatKey);
|
this.channel = new ConsoleDirectLine(min.instance.webchatKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
const Swagger = require('swagger-client');
|
import Swagger from 'swagger-client';
|
||||||
const rp = require('request-promise');
|
import rp from 'request-promise';
|
||||||
import { GBLog, GBService } from 'botlib';
|
import { GBLog, GBService } from 'botlib';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -11,7 +11,7 @@ export class ConsoleDirectLine extends GBService {
|
||||||
public directLineClientName: string = 'DirectLineClient';
|
public directLineClientName: string = 'DirectLineClient';
|
||||||
public directLineSpecUrl: string = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json';
|
public directLineSpecUrl: string = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json';
|
||||||
|
|
||||||
constructor(directLineSecret: string) {
|
constructor (directLineSecret: string) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.directLineSecret = directLineSecret;
|
this.directLineSecret = directLineSecret;
|
||||||
|
|
@ -57,7 +57,7 @@ export class ConsoleDirectLine extends GBService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public sendMessagesFromConsole(client, conversationId) {
|
public sendMessagesFromConsole (client, conversationId) {
|
||||||
const _this_ = this;
|
const _this_ = this;
|
||||||
process.stdin.resume();
|
process.stdin.resume();
|
||||||
const stdin = process.stdin;
|
const stdin = process.stdin;
|
||||||
|
|
@ -92,7 +92,7 @@ export class ConsoleDirectLine extends GBService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public pollMessages(client, conversationId) {
|
public pollMessages (client, conversationId) {
|
||||||
const _this_ = this;
|
const _this_ = this;
|
||||||
GBLog.info(`Starting polling message for conversationId: ${conversationId}`);
|
GBLog.info(`Starting polling message for conversationId: ${conversationId}`);
|
||||||
let watermark;
|
let watermark;
|
||||||
|
|
@ -112,7 +112,7 @@ export class ConsoleDirectLine extends GBService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// tslint:disable:no-unsafe-any
|
// tslint:disable:no-unsafe-any
|
||||||
public printMessages(activities, directLineClientName) {
|
public printMessages (activities, directLineClientName) {
|
||||||
if (activities && activities.length) {
|
if (activities && activities.length) {
|
||||||
// ignore own messages
|
// ignore own messages
|
||||||
activities = activities.filter(m => {
|
activities = activities.filter(m => {
|
||||||
|
|
@ -133,7 +133,7 @@ export class ConsoleDirectLine extends GBService {
|
||||||
// tslint:enable:no-unsafe-any
|
// tslint:enable:no-unsafe-any
|
||||||
|
|
||||||
// tslint:disable:no-unsafe-any
|
// tslint:disable:no-unsafe-any
|
||||||
public printMessage(activity) {
|
public printMessage (activity) {
|
||||||
if (activity.text) {
|
if (activity.text) {
|
||||||
GBLog.info(activity.text);
|
GBLog.info(activity.text);
|
||||||
}
|
}
|
||||||
|
|
@ -160,7 +160,7 @@ export class ConsoleDirectLine extends GBService {
|
||||||
// tslint:enable:no-unsafe-any
|
// tslint:enable:no-unsafe-any
|
||||||
|
|
||||||
// tslint:disable:no-unsafe-any
|
// tslint:disable:no-unsafe-any
|
||||||
public renderHeroCard(attachment) {
|
public renderHeroCard (attachment) {
|
||||||
const width = 70;
|
const width = 70;
|
||||||
const contentLine = content => {
|
const contentLine = content => {
|
||||||
return `${' '.repeat((width - content.length) / 2)}content${' '.repeat((width - content.length) / 2)}`;
|
return `${' '.repeat((width - content.length) / 2)}content${' '.repeat((width - content.length) / 2)}`;
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,10 @@
|
||||||
import { BotAdapter } from 'botbuilder';
|
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.js';
|
||||||
import { SecService } from '../../security.gbapp/services/SecService';
|
import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||||
import { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBConversationalService } from '../services/GBConversationalService';
|
import { GBConversationalService } from '../services/GBConversationalService.js';
|
||||||
/**
|
/**
|
||||||
* Dialog for the bot explains about itself.
|
* Dialog for the bot explains about itself.
|
||||||
*/
|
*/
|
||||||
|
|
@ -53,14 +53,13 @@ export class BroadcastDialog extends IGBDialog {
|
||||||
* @param bot The bot adapter.
|
* @param bot The bot adapter.
|
||||||
* @param min The minimal bot instance data.
|
* @param min The minimal bot instance data.
|
||||||
*/
|
*/
|
||||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||||
min.dialogs.add(
|
min.dialogs.add(
|
||||||
new WaterfallDialog('/gb-broadcast', [
|
new WaterfallDialog('/gb-broadcast', [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,10 @@
|
||||||
import { BotAdapter } from 'botbuilder';
|
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.js';
|
||||||
import { SecService } from '../../security.gbapp/services/SecService';
|
import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||||
import { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBConversationalService } from '../services/GBConversationalService';
|
import { GBConversationalService } from '../services/GBConversationalService.js';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
/**
|
/**
|
||||||
* Dialog for the bot explains about itself.
|
* Dialog for the bot explains about itself.
|
||||||
|
|
@ -54,13 +54,13 @@ export class LanguageDialog extends IGBDialog {
|
||||||
* @param bot The bot adapter.
|
* @param bot The bot adapter.
|
||||||
* @param min The minimal bot instance data.
|
* @param min The minimal bot instance data.
|
||||||
*/
|
*/
|
||||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||||
min.dialogs.add(new WaterfallDialog('/language', [
|
min.dialogs.add(
|
||||||
|
new WaterfallDialog('/language', [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -68,11 +68,9 @@ export class LanguageDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
|
|
||||||
return await min.conversationalService.prompt(min, step,
|
return await min.conversationalService.prompt(min, step, Messages[locale].which_language);
|
||||||
Messages[locale].which_language);
|
|
||||||
},
|
},
|
||||||
async step => {
|
async step => {
|
||||||
|
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
const user = await min.userProfile.get(step.context, {});
|
const user = await min.userProfile.get(step.context, {});
|
||||||
|
|
||||||
|
|
@ -96,8 +94,10 @@ export class LanguageDialog extends IGBDialog {
|
||||||
const text = step.context.activity['originalText'];
|
const text = step.context.activity['originalText'];
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(list, async item => {
|
await CollectionUtil.asyncForEach(list, async item => {
|
||||||
if (GBConversationalService.kmpSearch(text.toLowerCase(), item.name.toLowerCase()) != -1 ||
|
if (
|
||||||
GBConversationalService.kmpSearch(text.toLowerCase(), item.code.toLowerCase()) != -1) {
|
GBConversationalService.kmpSearch(text.toLowerCase(), item.name.toLowerCase()) != -1 ||
|
||||||
|
GBConversationalService.kmpSearch(text.toLowerCase(), item.code.toLowerCase()) != -1
|
||||||
|
) {
|
||||||
translatorLocale = item.code;
|
translatorLocale = item.code;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -106,11 +106,11 @@ export class LanguageDialog extends IGBDialog {
|
||||||
user.systemUser = await sec.updateUserLocale(user.systemUser.userId, translatorLocale);
|
user.systemUser = await sec.updateUserLocale(user.systemUser.userId, translatorLocale);
|
||||||
|
|
||||||
await min.userProfile.set(step.context, user);
|
await min.userProfile.set(step.context, user);
|
||||||
await min.conversationalService.sendText(min, step,
|
await min.conversationalService.sendText(min, step, Messages[locale].language_chosen);
|
||||||
Messages[locale].language_chosen);
|
|
||||||
|
|
||||||
await step.replaceDialog('/ask', { firstTime: true });
|
await step.replaceDialog('/ask', { firstTime: true });
|
||||||
}
|
}
|
||||||
]));
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,10 @@
|
||||||
import { BotAdapter } from 'botbuilder';
|
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 { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { SecService } from '../../security.gbapp/services/SecService';
|
import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||||
import { GBConversationalService } from '../services/GBConversationalService';
|
import { GBConversationalService } from '../services/GBConversationalService.js';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings.js';
|
||||||
/**
|
/**
|
||||||
* Dialog for the bot explains about itself.
|
* Dialog for the bot explains about itself.
|
||||||
*/
|
*/
|
||||||
|
|
@ -53,13 +53,13 @@ export class SwitchBotDialog extends IGBDialog {
|
||||||
* @param bot The bot adapter.
|
* @param bot The bot adapter.
|
||||||
* @param min The minimal bot instance data.
|
* @param min The minimal bot instance data.
|
||||||
*/
|
*/
|
||||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||||
min.dialogs.add(new WaterfallDialog('/bot', [
|
min.dialogs.add(
|
||||||
|
new WaterfallDialog('/bot', [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -67,7 +67,7 @@ export class SwitchBotDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
|
|
||||||
return await min.conversationalService.prompt (min, step, 'Qual seria o código de ativação?');
|
return await min.conversationalService.prompt(min, step, 'Qual seria o código de ativação?');
|
||||||
},
|
},
|
||||||
async step => {
|
async step => {
|
||||||
const sec = new SecService();
|
const sec = new SecService();
|
||||||
|
|
@ -79,6 +79,7 @@ export class SwitchBotDialog extends IGBDialog {
|
||||||
|
|
||||||
return await step.next();
|
return await step.next();
|
||||||
}
|
}
|
||||||
]));
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,9 @@
|
||||||
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 } from 'botlib';
|
||||||
import { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBConversationalService } from '../services/GBConversationalService';
|
import { GBConversationalService } from '../services/GBConversationalService.js';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog for Welcoming people.
|
* Dialog for Welcoming people.
|
||||||
|
|
@ -53,30 +53,33 @@ export class WelcomeDialog extends IGBDialog {
|
||||||
* @param bot The bot adapter.
|
* @param bot The bot adapter.
|
||||||
* @param min The minimal bot instance data.
|
* @param min The minimal bot instance data.
|
||||||
*/
|
*/
|
||||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||||
|
min.dialogs.add(
|
||||||
min.dialogs.add(new WaterfallDialog('/', [
|
new WaterfallDialog('/', [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async step => {
|
async step => {
|
||||||
|
if (
|
||||||
if (GBServer.globals.entryPointDialog !== null &&
|
GBServer.globals.entryPointDialog !== null &&
|
||||||
min.instance.botId === process.env.BOT_ID &&
|
min.instance.botId === process.env.BOT_ID &&
|
||||||
step.context.activity.channelId === 'webchat') {
|
step.context.activity.channelId === 'webchat'
|
||||||
|
) {
|
||||||
return step.replaceDialog(GBServer.globals.entryPointDialog);
|
return step.replaceDialog(GBServer.globals.entryPointDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await min.userProfile.get(step.context, {});
|
const user = await min.userProfile.get(step.context, {});
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
|
|
||||||
if (!user.once && step.context.activity.channelId === 'webchat'
|
if (
|
||||||
&& min.core.getParam<boolean>(min.instance, 'HelloGoodX', true) === "true") {
|
!user.once &&
|
||||||
|
step.context.activity.channelId === 'webchat' &&
|
||||||
|
min.core.getParam<boolean>(min.instance, 'HelloGoodX', true) === 'true'
|
||||||
|
) {
|
||||||
user.once = true;
|
user.once = true;
|
||||||
await min.userProfile.set(step.context, user);
|
await min.userProfile.set(step.context, user);
|
||||||
const a = new Date();
|
const a = new Date();
|
||||||
|
|
@ -104,6 +107,7 @@ export class WelcomeDialog extends IGBDialog {
|
||||||
|
|
||||||
return await step.next();
|
return await step.next();
|
||||||
}
|
}
|
||||||
]));
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@
|
||||||
import { BotAdapter } from 'botbuilder';
|
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 { GBConversationalService } from '../services/GBConversationalService';
|
import { GBConversationalService } from '../services/GBConversationalService.js';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings.js';
|
||||||
/**
|
/**
|
||||||
* Dialog for the bot explains about itself.
|
* Dialog for the bot explains about itself.
|
||||||
*/
|
*/
|
||||||
|
|
@ -51,13 +51,13 @@ export class WhoAmIDialog extends IGBDialog {
|
||||||
* @param bot The bot adapter.
|
* @param bot The bot adapter.
|
||||||
* @param min The minimal bot instance data.
|
* @param min The minimal bot instance data.
|
||||||
*/
|
*/
|
||||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||||
min.dialogs.add(new WaterfallDialog('/whoAmI', [
|
min.dialogs.add(
|
||||||
|
new WaterfallDialog('/whoAmI', [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -78,6 +78,7 @@ export class WhoAmIDialog extends IGBDialog {
|
||||||
|
|
||||||
return await step.next();
|
return await step.next();
|
||||||
}
|
}
|
||||||
]));
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,12 @@
|
||||||
|
|
||||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||||
import { Sequelize } from 'sequelize-typescript';
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
import { BroadcastDialog } from './dialogs/BroadcastDialog';
|
import { BroadcastDialog } from './dialogs/BroadcastDialog.js';
|
||||||
import { LanguageDialog } from './dialogs/LanguageDialog';
|
import { LanguageDialog } from './dialogs/LanguageDialog.js';
|
||||||
import { SwitchBotDialog } from './dialogs/SwitchBot';
|
import { SwitchBotDialog } from './dialogs/SwitchBot.js';
|
||||||
import { WelcomeDialog } from './dialogs/WelcomeDialog';
|
import { WelcomeDialog } from './dialogs/WelcomeDialog.js';
|
||||||
import { WhoAmIDialog } from './dialogs/WhoAmIDialog';
|
import { WhoAmIDialog } from './dialogs/WhoAmIDialog.js';
|
||||||
import { GuaribasChannel, GuaribasException, GuaribasInstance, GuaribasPackage } from './models/GBModel';
|
import { GuaribasChannel, GuaribasException, GuaribasInstance, GuaribasPackage } from './models/GBModel.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package for core.gbapp.
|
* Package for core.gbapp.
|
||||||
|
|
@ -52,27 +52,27 @@ export class GBCorePackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
public CurrentEngineName = 'guaribas-1.0.0';
|
public CurrentEngineName = 'guaribas-1.0.0';
|
||||||
|
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
core.sequelize.addModels([GuaribasInstance, GuaribasPackage, GuaribasChannel, GuaribasException]);
|
core.sequelize.addModels([GuaribasInstance, GuaribasPackage, GuaribasChannel, GuaribasException]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getDialogs(min: GBMinInstance) {
|
public async getDialogs (min: GBMinInstance) {
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<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);
|
SwitchBotDialog.setup(min.bot, min);
|
||||||
|
|
|
||||||
|
|
@ -47,4 +47,4 @@ import {
|
||||||
Table,
|
Table,
|
||||||
UpdatedAt
|
UpdatedAt
|
||||||
} from 'sequelize-typescript';
|
} from 'sequelize-typescript';
|
||||||
import { GuaribasInstance } from './GBModel';
|
import { GuaribasInstance } from './GBModel.js';
|
||||||
|
|
|
||||||
|
|
@ -55,218 +55,219 @@ import { IGBInstance } from 'botlib';
|
||||||
* Base instance data for a bot.
|
* Base instance data for a bot.
|
||||||
*/
|
*/
|
||||||
@Table
|
@Table
|
||||||
export class GuaribasInstance extends Model<GuaribasInstance>
|
export class GuaribasInstance extends Model<GuaribasInstance> implements IGBInstance {
|
||||||
implements IGBInstance {
|
|
||||||
|
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
instanceId: number;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public botEndpoint: string;
|
declare botEndpoint: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public whoAmIVideo: string;
|
declare whoAmIVideo: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public botId: string;
|
declare botId: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public title: string;
|
declare title: string;
|
||||||
|
|
||||||
@Column({ type: DataType.STRING(16) })
|
@Column({ type: DataType.STRING(16) })
|
||||||
public activationCode: string;
|
declare activationCode: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public description: string;
|
declare description: string;
|
||||||
|
|
||||||
@Column({ type: DataType.STRING(16) })
|
@Column({ type: DataType.STRING(16) })
|
||||||
public state: string;
|
declare state: string;
|
||||||
|
|
||||||
public version: string;
|
declare version: string;
|
||||||
|
|
||||||
|
@Column(DataType.STRING(64))
|
||||||
|
declare botKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public enabledAdmin: boolean;
|
declare enabledAdmin: boolean;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public engineName: string;
|
declare engineName: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public marketplaceId: string;
|
declare marketplaceId: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public textAnalyticsKey: string;
|
declare textAnalyticsKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public textAnalyticsEndpoint: string;
|
declare textAnalyticsEndpoint: string;
|
||||||
|
|
||||||
@Column({ type: DataType.STRING(64) })
|
@Column({ type: DataType.STRING(64) })
|
||||||
public translatorKey: string;
|
declare translatorKey: string;
|
||||||
|
|
||||||
@Column({ type: DataType.STRING(128) })
|
@Column({ type: DataType.STRING(128) })
|
||||||
public translatorEndpoint: string;
|
declare translatorEndpoint: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public marketplacePassword: string;
|
declare marketplacePassword: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public webchatKey: string;
|
declare webchatKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public authenticatorTenant: string;
|
declare authenticatorTenant: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public authenticatorAuthorityHostUrl: string;
|
declare authenticatorAuthorityHostUrl: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public cloudSubscriptionId: string;
|
declare cloudSubscriptionId: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public cloudUsername: string;
|
declare cloudUsername: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public cloudPassword: string;
|
declare cloudPassword: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public cloudLocation: string;
|
declare cloudLocation: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public googleBotKey: string;
|
declare googleBotKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public googleChatApiKey: string;
|
declare googleChatApiKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public googleChatSubscriptionName: string;
|
declare googleChatSubscriptionName: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public googleClientEmail: string;
|
declare googleClientEmail: string;
|
||||||
|
|
||||||
@Column({ type: DataType.STRING(4000) })
|
@Column({ type: DataType.STRING(4000) })
|
||||||
public googlePrivateKey: string;
|
declare googlePrivateKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public googleProjectId: string;
|
declare googleProjectId: string;
|
||||||
|
|
||||||
@Column({ type: DataType.STRING(255) })
|
@Column({ type: DataType.STRING(255) })
|
||||||
facebookWorkplaceVerifyToken: string;
|
declare facebookWorkplaceVerifyToken: string;
|
||||||
|
|
||||||
@Column({ type: DataType.STRING(255) })
|
@Column({ type: DataType.STRING(255) })
|
||||||
facebookWorkplaceAppSecret: string;
|
declare facebookWorkplaceAppSecret: string;
|
||||||
|
|
||||||
@Column({ type: DataType.STRING(512) })
|
@Column({ type: DataType.STRING(512) })
|
||||||
facebookWorkplaceAccessToken: string;
|
declare facebookWorkplaceAccessToken: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public whatsappBotKey: string;
|
declare whatsappBotKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public whatsappServiceKey: string;
|
declare whatsappServiceKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public whatsappServiceNumber: string;
|
declare whatsappServiceNumber: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public whatsappServiceUrl: string;
|
declare whatsappServiceUrl: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public smsKey: string;
|
declare smsKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public smsSecret: string;
|
declare smsSecret: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public smsServiceNumber: string;
|
declare smsServiceNumber: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public speechKey: string;
|
declare speechKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public speechEndpoint: string;
|
declare speechEndpoint: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public spellcheckerKey: string;
|
declare spellcheckerKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public spellcheckerEndpoint: string;
|
declare spellcheckerEndpoint: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public theme: string;
|
declare theme: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public ui: string;
|
declare ui: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public kb: string;
|
declare kb: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public nlpAppId: string;
|
declare nlpAppId: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public nlpKey: string;
|
declare nlpKey: string;
|
||||||
|
|
||||||
@Column({ type: DataType.STRING(512) })
|
@Column({ type: DataType.STRING(512) })
|
||||||
public nlpEndpoint: string;
|
declare nlpEndpoint: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public nlpAuthoringKey: string;
|
declare nlpAuthoringKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public deploymentPaths: string;
|
declare deploymentPaths: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public searchHost: string;
|
declare searchHost: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public searchKey: string;
|
declare searchKey: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public searchIndex: string;
|
declare searchIndex: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public searchIndexer: string;
|
declare searchIndexer: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public storageUsername: string;
|
declare storageUsername: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public storagePassword: string;
|
declare storagePassword: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public storageName: string;
|
declare storageName: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public storageServer: string;
|
declare storageServer: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public storageDialect: string;
|
declare storageDialect: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public storagePath: string;
|
declare storagePath: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public adminPass: string;
|
declare adminPass: string;
|
||||||
|
|
||||||
@Column(DataType.FLOAT)
|
@Column(DataType.FLOAT)
|
||||||
public nlpVsSearch: number; // TODO: Remove field.
|
declare nlpVsSearch: number; // TODO: Remove field.
|
||||||
|
|
||||||
@Column(DataType.FLOAT)
|
@Column(DataType.FLOAT)
|
||||||
public searchScore: number;
|
declare searchScore: number;
|
||||||
|
|
||||||
@Column(DataType.FLOAT)
|
@Column(DataType.FLOAT)
|
||||||
public nlpScore: number;
|
declare nlpScore: number;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
public createdAt: Date;
|
declare createdAt: Date;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
public updatedAt: Date;
|
declare updatedAt: Date;
|
||||||
|
|
||||||
@Column(DataType.STRING(4000))
|
@Column(DataType.STRING(4000))
|
||||||
public params: string;
|
declare params: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -277,28 +278,28 @@ export class GuaribasPackage extends Model<GuaribasPackage> {
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public packageId: number;
|
declare packageId: number;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public packageName: string;
|
declare packageName: string;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
declare instanceId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
public instance: GuaribasInstance;
|
declare instance: GuaribasInstance;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
public createdAt: Date;
|
declare createdAt: Date;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
public updatedAt: Date;
|
declare updatedAt: Date;
|
||||||
|
|
||||||
@Column({ type: DataType.STRING(512) })
|
@Column({ type: DataType.STRING(512) })
|
||||||
public custom: string;
|
declare custom: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -309,18 +310,18 @@ export class GuaribasChannel extends Model<GuaribasChannel> {
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public channelId: number;
|
declare channelId: number;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public title: string;
|
declare title: string;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
public createdAt: Date;
|
declare createdAt: Date;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
public updatedAt: Date;
|
declare updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -332,72 +333,70 @@ export class GuaribasException extends Model<GuaribasException> {
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public exceptionId: number;
|
declare exceptionId: number;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public message: string;
|
declare message: string;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
declare instanceId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
public instance: GuaribasInstance;
|
declare instance: GuaribasInstance;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
public createdAt: Date;
|
declare createdAt: Date;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
public updatedAt: Date;
|
declare updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
//tslint:disable-next-line:max-classes-per-file
|
//tslint:disable-next-line:max-classes-per-file
|
||||||
export class GuaribasApplications extends Model<GuaribasApplications> {
|
export class GuaribasApplications extends Model<GuaribasApplications> {
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public name: string;
|
declare name: string;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
declare instanceId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
public instance: GuaribasInstance;
|
declare instance: GuaribasInstance;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
public createdAt: Date;
|
declare createdAt: Date;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
public updatedAt: Date;
|
declare updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
//tslint:disable-next-line:max-classes-per-file
|
//tslint:disable-next-line:max-classes-per-file
|
||||||
export class GuaribasSchedule extends Model<GuaribasSchedule> {
|
export class GuaribasSchedule extends Model<GuaribasSchedule> {
|
||||||
|
@Column(DataType.STRING(255))
|
||||||
|
declare name: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public name: string;
|
declare schedule: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
|
||||||
public schedule: string;
|
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
declare instanceId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
public instance: GuaribasInstance;
|
declare instance: GuaribasInstance;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
public createdAt: Date;
|
declare createdAt: Date;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
public updatedAt: Date;
|
declare updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { GBLog } from 'botlib';
|
import { GBLog } from 'botlib';
|
||||||
|
import * as en from 'dotenv-extended';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fileoverview General Bots server core.
|
* @fileoverview General Bots server core.
|
||||||
|
|
@ -42,10 +43,10 @@ import { GBLog } from 'botlib';
|
||||||
* Base configuration for the server like storage.
|
* Base configuration for the server like storage.
|
||||||
*/
|
*/
|
||||||
export class GBConfigService {
|
export class GBConfigService {
|
||||||
public static getBoolean(value: string): boolean {
|
public static getBoolean (value: string): boolean {
|
||||||
return this.get(value) as unknown as boolean;
|
return (this.get(value) as unknown) as boolean;
|
||||||
}
|
}
|
||||||
public static getServerPort(): string {
|
public static getServerPort (): string {
|
||||||
if (process.env.PORT) {
|
if (process.env.PORT) {
|
||||||
return process.env.PORT;
|
return process.env.PORT;
|
||||||
}
|
}
|
||||||
|
|
@ -56,9 +57,9 @@ export class GBConfigService {
|
||||||
return '4242';
|
return '4242';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static init(): any {
|
public static init (): any {
|
||||||
try {
|
try {
|
||||||
require('dotenv-extended').load({
|
en.load({
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
silent: true,
|
silent: true,
|
||||||
path: '.env',
|
path: '.env',
|
||||||
|
|
@ -77,7 +78,7 @@ export class GBConfigService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static get(key: string): string | undefined {
|
public static get (key: string): string | undefined {
|
||||||
let value = GBConfigService.tryGet(key);
|
let value = GBConfigService.tryGet(key);
|
||||||
|
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
|
|
@ -163,13 +164,12 @@ export class GBConfigService {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static tryGet(key: string): any {
|
public static tryGet (key: string): any {
|
||||||
let value = process.env[`container:${key}`];
|
let value = process.env[`container:${key}`];
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
value = process.env[key];
|
value = process.env[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,38 +39,36 @@
|
||||||
import { MessageFactory, RecognizerResult, TurnContext } from 'botbuilder';
|
import { MessageFactory, RecognizerResult, TurnContext } from 'botbuilder';
|
||||||
import { LuisRecognizer } from 'botbuilder-ai';
|
import { LuisRecognizer } from 'botbuilder-ai';
|
||||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService } from 'botlib';
|
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService } from 'botlib';
|
||||||
import { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
||||||
import { SecService } from '../../security.gbapp/services/SecService';
|
import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
|
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService.js';
|
||||||
import { MicrosoftAppCredentials } from 'botframework-connector';
|
import { MicrosoftAppCredentials } from 'botframework-connector';
|
||||||
import { GBConfigService } from './GBConfigService';
|
import { GBConfigService } from './GBConfigService.js';
|
||||||
import { Messages } from '../strings';
|
|
||||||
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
|
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
|
||||||
import { GuaribasUser } from '../../security.gbapp/models';
|
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||||
import { GBMinService } from './GBMinService';
|
import { GBMinService } from './GBMinService.js';
|
||||||
const urlJoin = require('url-join');
|
import urlJoin from 'url-join';
|
||||||
const PasswordGenerator = require('strict-password-generator').default;
|
import Fs from 'fs';
|
||||||
const Nexmo = require('nexmo');
|
import PasswordGenerator from 'strict-password-generator';
|
||||||
const { join } = require('path');
|
import Nexmo from 'nexmo';
|
||||||
const shell = require('any-shell-escape');
|
import { join } from 'path';
|
||||||
const { exec } = require('child_process');
|
import shell from 'any-shell-escape';
|
||||||
const prism = require('prism-media');
|
import { exec } from 'child_process';
|
||||||
const request = require('request-promise-native');
|
import prism from 'prism-media';
|
||||||
const fs = require('fs');
|
import request from 'request-promise-native';
|
||||||
const SpeechToTextV1 = require('ibm-watson/speech-to-text/v1');
|
import SpeechToTextV1 from 'ibm-watson/speech-to-text/v1.js';
|
||||||
const TextToSpeechV1 = require('ibm-watson/text-to-speech/v1');
|
import TextToSpeechV1 from 'ibm-watson/text-to-speech/v1.js';
|
||||||
const { IamAuthenticator } = require('ibm-watson/auth');
|
import { IamAuthenticator } from 'ibm-watson/auth/index.js';
|
||||||
const marked = require('marked');
|
import * as marked from 'marked';
|
||||||
const { Translate } = require('@google-cloud/translate').v2;
|
import Translate from '@google-cloud/translate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides basic services for handling messages and dispatching to back-end
|
* Provides basic services for handling messages and dispatching to back-end
|
||||||
* services like NLP or Search.
|
* services like NLP or Search.
|
||||||
*/
|
*/
|
||||||
export class GBConversationalService {
|
export class GBConversationalService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the core service.
|
* Reference to the core service.
|
||||||
*/
|
*/
|
||||||
|
|
@ -80,109 +78,196 @@ export class GBConversationalService {
|
||||||
*
|
*
|
||||||
* @param coreService
|
* @param coreService
|
||||||
*/
|
*/
|
||||||
constructor(coreService: IGBCoreService) {
|
constructor (coreService: IGBCoreService) {
|
||||||
this.coreService = coreService;
|
this.coreService = coreService;
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultDiacriticsRemovalMap = [
|
static defaultDiacriticsRemovalMap = [
|
||||||
{ 'base': 'A', 'letters': '\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F' },
|
{
|
||||||
{ 'base': 'AA', 'letters': '\uA732' },
|
base: 'A',
|
||||||
{ 'base': 'AE', 'letters': '\u00C6\u01FC\u01E2' },
|
letters:
|
||||||
{ 'base': 'AO', 'letters': '\uA734' },
|
'\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F'
|
||||||
{ 'base': 'AU', 'letters': '\uA736' },
|
},
|
||||||
{ 'base': 'AV', 'letters': '\uA738\uA73A' },
|
{ base: 'AA', letters: '\uA732' },
|
||||||
{ 'base': 'AY', 'letters': '\uA73C' },
|
{ base: 'AE', letters: '\u00C6\u01FC\u01E2' },
|
||||||
{ 'base': 'B', 'letters': '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181' },
|
{ base: 'AO', letters: '\uA734' },
|
||||||
{ 'base': 'C', 'letters': '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E' },
|
{ base: 'AU', letters: '\uA736' },
|
||||||
{ 'base': 'D', 'letters': '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0' },
|
{ base: 'AV', letters: '\uA738\uA73A' },
|
||||||
{ 'base': 'DZ', 'letters': '\u01F1\u01C4' },
|
{ base: 'AY', letters: '\uA73C' },
|
||||||
{ 'base': 'Dz', 'letters': '\u01F2\u01C5' },
|
{ base: 'B', letters: '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181' },
|
||||||
{ 'base': 'E', 'letters': '\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E' },
|
{ base: 'C', letters: '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E' },
|
||||||
{ 'base': 'F', 'letters': '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B' },
|
{
|
||||||
{ 'base': 'G', 'letters': '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E' },
|
base: 'D',
|
||||||
{ 'base': 'H', 'letters': '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D' },
|
letters: '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0'
|
||||||
{ 'base': 'I', 'letters': '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197' },
|
},
|
||||||
{ 'base': 'J', 'letters': '\u004A\u24BF\uFF2A\u0134\u0248' },
|
{ base: 'DZ', letters: '\u01F1\u01C4' },
|
||||||
{ 'base': 'K', 'letters': '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2' },
|
{ base: 'Dz', letters: '\u01F2\u01C5' },
|
||||||
{ 'base': 'L', 'letters': '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780' },
|
{
|
||||||
{ 'base': 'LJ', 'letters': '\u01C7' },
|
base: 'E',
|
||||||
{ 'base': 'Lj', 'letters': '\u01C8' },
|
letters:
|
||||||
{ 'base': 'M', 'letters': '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C' },
|
'\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E'
|
||||||
{ 'base': 'N', 'letters': '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4' },
|
},
|
||||||
{ 'base': 'NJ', 'letters': '\u01CA' },
|
{ base: 'F', letters: '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B' },
|
||||||
{ 'base': 'Nj', 'letters': '\u01CB' },
|
{
|
||||||
{ 'base': 'O', 'letters': '\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C' },
|
base: 'G',
|
||||||
{ 'base': 'OI', 'letters': '\u01A2' },
|
letters: '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E'
|
||||||
{ 'base': 'OO', 'letters': '\uA74E' },
|
},
|
||||||
{ 'base': 'OU', 'letters': '\u0222' },
|
{ base: 'H', letters: '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D' },
|
||||||
{ 'base': 'OE', 'letters': '\u008C\u0152' },
|
{
|
||||||
{ 'base': 'oe', 'letters': '\u009C\u0153' },
|
base: 'I',
|
||||||
{ 'base': 'P', 'letters': '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754' },
|
letters:
|
||||||
{ 'base': 'Q', 'letters': '\u0051\u24C6\uFF31\uA756\uA758\u024A' },
|
'\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197'
|
||||||
{ 'base': 'R', 'letters': '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782' },
|
},
|
||||||
{ 'base': 'S', 'letters': '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784' },
|
{ base: 'J', letters: '\u004A\u24BF\uFF2A\u0134\u0248' },
|
||||||
{ 'base': 'T', 'letters': '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786' },
|
{ base: 'K', letters: '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2' },
|
||||||
{ 'base': 'TZ', 'letters': '\uA728' },
|
{
|
||||||
{ 'base': 'U', 'letters': '\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244' },
|
base: 'L',
|
||||||
{ 'base': 'V', 'letters': '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245' },
|
letters:
|
||||||
{ 'base': 'VY', 'letters': '\uA760' },
|
'\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780'
|
||||||
{ 'base': 'W', 'letters': '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72' },
|
},
|
||||||
{ 'base': 'X', 'letters': '\u0058\u24CD\uFF38\u1E8A\u1E8C' },
|
{ base: 'LJ', letters: '\u01C7' },
|
||||||
{ 'base': 'Y', 'letters': '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE' },
|
{ base: 'Lj', letters: '\u01C8' },
|
||||||
{ 'base': 'Z', 'letters': '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762' },
|
{ base: 'M', letters: '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C' },
|
||||||
{ 'base': 'a', 'letters': '\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250' },
|
{
|
||||||
{ 'base': 'aa', 'letters': '\uA733' },
|
base: 'N',
|
||||||
{ 'base': 'ae', 'letters': '\u00E6\u01FD\u01E3' },
|
letters: '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4'
|
||||||
{ 'base': 'ao', 'letters': '\uA735' },
|
},
|
||||||
{ 'base': 'au', 'letters': '\uA737' },
|
{ base: 'NJ', letters: '\u01CA' },
|
||||||
{ 'base': 'av', 'letters': '\uA739\uA73B' },
|
{ base: 'Nj', letters: '\u01CB' },
|
||||||
{ 'base': 'ay', 'letters': '\uA73D' },
|
{
|
||||||
{ 'base': 'b', 'letters': '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253' },
|
base: 'O',
|
||||||
{ 'base': 'c', 'letters': '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184' },
|
letters:
|
||||||
{ 'base': 'd', 'letters': '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A' },
|
'\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C'
|
||||||
{ 'base': 'dz', 'letters': '\u01F3\u01C6' },
|
},
|
||||||
{ 'base': 'e', 'letters': '\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD' },
|
{ base: 'OI', letters: '\u01A2' },
|
||||||
{ 'base': 'f', 'letters': '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C' },
|
{ base: 'OO', letters: '\uA74E' },
|
||||||
{ 'base': 'g', 'letters': '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F' },
|
{ base: 'OU', letters: '\u0222' },
|
||||||
{ 'base': 'h', 'letters': '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265' },
|
{ base: 'OE', letters: '\u008C\u0152' },
|
||||||
{ 'base': 'hv', 'letters': '\u0195' },
|
{ base: 'oe', letters: '\u009C\u0153' },
|
||||||
{ 'base': 'i', 'letters': '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131' },
|
{ base: 'P', letters: '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754' },
|
||||||
{ 'base': 'j', 'letters': '\u006A\u24D9\uFF4A\u0135\u01F0\u0249' },
|
{ base: 'Q', letters: '\u0051\u24C6\uFF31\uA756\uA758\u024A' },
|
||||||
{ 'base': 'k', 'letters': '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3' },
|
{
|
||||||
{ 'base': 'l', 'letters': '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747' },
|
base: 'R',
|
||||||
{ 'base': 'lj', 'letters': '\u01C9' },
|
letters: '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782'
|
||||||
{ 'base': 'm', 'letters': '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F' },
|
},
|
||||||
{ 'base': 'n', 'letters': '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5' },
|
{
|
||||||
{ 'base': 'nj', 'letters': '\u01CC' },
|
base: 'S',
|
||||||
{ 'base': 'o', 'letters': '\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275' },
|
letters: '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784'
|
||||||
{ 'base': 'oi', 'letters': '\u01A3' },
|
},
|
||||||
{ 'base': 'ou', 'letters': '\u0223' },
|
{
|
||||||
{ 'base': 'oo', 'letters': '\uA74F' },
|
base: 'T',
|
||||||
{ 'base': 'p', 'letters': '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755' },
|
letters: '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786'
|
||||||
{ 'base': 'q', 'letters': '\u0071\u24E0\uFF51\u024B\uA757\uA759' },
|
},
|
||||||
{ 'base': 'r', 'letters': '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783' },
|
{ base: 'TZ', letters: '\uA728' },
|
||||||
{ 'base': 's', 'letters': '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B' },
|
{
|
||||||
{ 'base': 't', 'letters': '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787' },
|
base: 'U',
|
||||||
{ 'base': 'tz', 'letters': '\uA729' },
|
letters:
|
||||||
{ 'base': 'u', 'letters': '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289' },
|
'\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244'
|
||||||
{ 'base': 'v', 'letters': '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C' },
|
},
|
||||||
{ 'base': 'vy', 'letters': '\uA761' },
|
{ base: 'V', letters: '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245' },
|
||||||
{ 'base': 'w', 'letters': '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73' },
|
{ base: 'VY', letters: '\uA760' },
|
||||||
{ 'base': 'x', 'letters': '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
|
{ base: 'W', letters: '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72' },
|
||||||
{ 'base': 'y', 'letters': '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF' },
|
{ base: 'X', letters: '\u0058\u24CD\uFF38\u1E8A\u1E8C' },
|
||||||
{ 'base': 'z', 'letters': '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763' }
|
{
|
||||||
|
base: 'Y',
|
||||||
|
letters: '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE'
|
||||||
|
},
|
||||||
|
{ base: 'Z', letters: '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762' },
|
||||||
|
{
|
||||||
|
base: 'a',
|
||||||
|
letters:
|
||||||
|
'\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250'
|
||||||
|
},
|
||||||
|
{ base: 'aa', letters: '\uA733' },
|
||||||
|
{ base: 'ae', letters: '\u00E6\u01FD\u01E3' },
|
||||||
|
{ base: 'ao', letters: '\uA735' },
|
||||||
|
{ base: 'au', letters: '\uA737' },
|
||||||
|
{ base: 'av', letters: '\uA739\uA73B' },
|
||||||
|
{ base: 'ay', letters: '\uA73D' },
|
||||||
|
{ base: 'b', letters: '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253' },
|
||||||
|
{ base: 'c', letters: '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184' },
|
||||||
|
{ base: 'd', letters: '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A' },
|
||||||
|
{ base: 'dz', letters: '\u01F3\u01C6' },
|
||||||
|
{
|
||||||
|
base: 'e',
|
||||||
|
letters:
|
||||||
|
'\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD'
|
||||||
|
},
|
||||||
|
{ base: 'f', letters: '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C' },
|
||||||
|
{
|
||||||
|
base: 'g',
|
||||||
|
letters: '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
base: 'h',
|
||||||
|
letters: '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265'
|
||||||
|
},
|
||||||
|
{ base: 'hv', letters: '\u0195' },
|
||||||
|
{
|
||||||
|
base: 'i',
|
||||||
|
letters:
|
||||||
|
'\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131'
|
||||||
|
},
|
||||||
|
{ base: 'j', letters: '\u006A\u24D9\uFF4A\u0135\u01F0\u0249' },
|
||||||
|
{ base: 'k', letters: '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3' },
|
||||||
|
{
|
||||||
|
base: 'l',
|
||||||
|
letters:
|
||||||
|
'\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747'
|
||||||
|
},
|
||||||
|
{ base: 'lj', letters: '\u01C9' },
|
||||||
|
{ base: 'm', letters: '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F' },
|
||||||
|
{
|
||||||
|
base: 'n',
|
||||||
|
letters: '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5'
|
||||||
|
},
|
||||||
|
{ base: 'nj', letters: '\u01CC' },
|
||||||
|
{
|
||||||
|
base: 'o',
|
||||||
|
letters:
|
||||||
|
'\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275'
|
||||||
|
},
|
||||||
|
{ base: 'oi', letters: '\u01A3' },
|
||||||
|
{ base: 'ou', letters: '\u0223' },
|
||||||
|
{ base: 'oo', letters: '\uA74F' },
|
||||||
|
{ base: 'p', letters: '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755' },
|
||||||
|
{ base: 'q', letters: '\u0071\u24E0\uFF51\u024B\uA757\uA759' },
|
||||||
|
{
|
||||||
|
base: 'r',
|
||||||
|
letters: '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
base: 's',
|
||||||
|
letters:
|
||||||
|
'\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
base: 't',
|
||||||
|
letters: '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787'
|
||||||
|
},
|
||||||
|
{ base: 'tz', letters: '\uA729' },
|
||||||
|
{
|
||||||
|
base: 'u',
|
||||||
|
letters:
|
||||||
|
'\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289'
|
||||||
|
},
|
||||||
|
{ base: 'v', letters: '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C' },
|
||||||
|
{ base: 'vy', letters: '\uA761' },
|
||||||
|
{ base: 'w', letters: '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73' },
|
||||||
|
{ base: 'x', letters: '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
|
||||||
|
{
|
||||||
|
base: 'y',
|
||||||
|
letters: '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF'
|
||||||
|
},
|
||||||
|
{ base: 'z', letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763' }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
// "what?" version ... http://jsperf.com/diacritics/12
|
// "what?" version ... http://jsperf.com/diacritics/12
|
||||||
public static removeDiacriticsAndPunctuation(str) {
|
public static removeDiacriticsAndPunctuation (str) {
|
||||||
|
|
||||||
str = GBConversationalService.removeDiacritics(str);
|
str = GBConversationalService.removeDiacritics(str);
|
||||||
return str.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
|
return str.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, '');
|
||||||
|
|
||||||
}
|
}
|
||||||
public static removeDiacritics(str) {
|
public static removeDiacritics (str) {
|
||||||
|
|
||||||
var diacriticsMap = {};
|
var diacriticsMap = {};
|
||||||
for (var i = 0; i < GBConversationalService.defaultDiacriticsRemovalMap.length; i++) {
|
for (var i = 0; i < GBConversationalService.defaultDiacriticsRemovalMap.length; i++) {
|
||||||
var letters = GBConversationalService.defaultDiacriticsRemovalMap[i].letters;
|
var letters = GBConversationalService.defaultDiacriticsRemovalMap[i].letters;
|
||||||
|
|
@ -196,9 +281,7 @@ export class GBConversationalService {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getNewMobileCode () {
|
||||||
|
|
||||||
public getNewMobileCode() {
|
|
||||||
const passwordGenerator = new PasswordGenerator();
|
const passwordGenerator = new PasswordGenerator();
|
||||||
const options = {
|
const options = {
|
||||||
upperCaseAlpha: false,
|
upperCaseAlpha: false,
|
||||||
|
|
@ -212,15 +295,15 @@ export class GBConversationalService {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getCurrentLanguage(step: GBDialogStep) {
|
public getCurrentLanguage (step: GBDialogStep) {
|
||||||
return step.context.activity.locale;
|
return step.context.activity.locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public userMobile(step) {
|
public userMobile (step) {
|
||||||
return GBMinService.userMobile(step);
|
return GBMinService.userMobile(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendFile(
|
public async sendFile (
|
||||||
min: GBMinInstance,
|
min: GBMinInstance,
|
||||||
step: GBDialogStep,
|
step: GBDialogStep,
|
||||||
mobile: string,
|
mobile: string,
|
||||||
|
|
@ -228,7 +311,6 @@ export class GBConversationalService {
|
||||||
caption: string
|
caption: string
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
if (step !== null) {
|
if (step !== null) {
|
||||||
|
|
||||||
mobile = this.userMobile(step);
|
mobile = this.userMobile(step);
|
||||||
|
|
||||||
if (mobile) {
|
if (mobile) {
|
||||||
|
|
@ -248,17 +330,17 @@ export class GBConversationalService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendAudio(min: GBMinInstance, step: GBDialogStep, url: string): Promise<any> {
|
public async sendAudio (min: GBMinInstance, step: GBDialogStep, url: string): Promise<any> {
|
||||||
const mobile = step.context.activity['mobile'];
|
const mobile = step.context.activity['mobile'];
|
||||||
GBLog.info(`Sending audio to ${mobile} in URL: ${url}.`);
|
GBLog.info(`Sending audio to ${mobile} in URL: ${url}.`);
|
||||||
await min.whatsAppDirectLine.sendAudioToDevice(mobile, url);
|
await min.whatsAppDirectLine.sendAudioToDevice(mobile, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendEvent(min: GBMinInstance, step: GBDialogStep, name: string, value: Object): Promise<any> {
|
public async sendEvent (min: GBMinInstance, step: GBDialogStep, name: string, value: Object): Promise<any> {
|
||||||
if (!this.userMobile(step) &&
|
if (!this.userMobile(step) && step.context.activity.channelId !== 'msteams') {
|
||||||
step.context.activity.channelId !== 'msteams') {
|
GBLog.info(
|
||||||
GBLog.info(`Sending event ${name}:${typeof value === 'object' ? JSON.stringify(value) :
|
`Sending event ${name}:${typeof value === 'object' ? JSON.stringify(value) : value ? value : ''} to client...`
|
||||||
value ? value : ''} to client...`);
|
);
|
||||||
const msg = MessageFactory.text('');
|
const msg = MessageFactory.text('');
|
||||||
msg.value = value;
|
msg.value = value;
|
||||||
msg.type = 'event';
|
msg.type = 'event';
|
||||||
|
|
@ -269,7 +351,7 @@ export class GBConversationalService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// tslint:disable:no-unsafe-any due to Nexmo.
|
// tslint:disable:no-unsafe-any due to Nexmo.
|
||||||
public async sendSms(min: GBMinInstance, mobile: string, text: string): Promise<any> {
|
public async sendSms (min: GBMinInstance, mobile: string, text: string): Promise<any> {
|
||||||
GBLog.info(`Sending SMS to ${mobile} with text: '${text}'.`);
|
GBLog.info(`Sending SMS to ${mobile} with text: '${text}'.`);
|
||||||
|
|
||||||
if (!min.instance.smsKey && min.instance.smsSecret) {
|
if (!min.instance.smsKey && min.instance.smsSecret) {
|
||||||
|
|
@ -277,16 +359,16 @@ export class GBConversationalService {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: 'http://sms-api.megaconecta.com.br/mt',
|
url: 'http://sms-api.megaconecta.com.br/mt',
|
||||||
headers: {
|
headers: {
|
||||||
"content-type": "application/json",
|
'content-type': 'application/json',
|
||||||
"authorization": `Bearer ${min.instance.smsSecret}`
|
authorization: `Bearer ${min.instance.smsSecret}`
|
||||||
},
|
},
|
||||||
body: [
|
body: [
|
||||||
{
|
{
|
||||||
"numero": `${mobile}`,
|
numero: `${mobile}`,
|
||||||
"servico": "short",
|
servico: 'short',
|
||||||
"mensagem": text,
|
mensagem: text,
|
||||||
"parceiro_id": "",
|
parceiro_id: '',
|
||||||
"codificacao": "0"
|
codificacao: '0'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
json: true
|
json: true
|
||||||
|
|
@ -301,15 +383,15 @@ export class GBConversationalService {
|
||||||
|
|
||||||
return Promise.reject(new Error(msg));
|
return Promise.reject(new Error(msg));
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
return new Promise(
|
||||||
return new Promise((resolve: any, reject: any): any => {
|
(resolve: any, reject: any): any => {
|
||||||
const nexmo = new Nexmo({
|
const nexmo = new Nexmo({
|
||||||
apiKey: min.instance.smsKey,
|
apiKey: min.instance.smsKey,
|
||||||
apiSecret: min.instance.smsSecret
|
apiSecret: min.instance.smsSecret
|
||||||
});
|
});
|
||||||
// tslint:disable-next-line:no-unsafe-any
|
// tslint:disable-next-line:no-unsafe-any
|
||||||
nexmo.message.sendSms(min.instance.smsServiceNumber, mobile, text, (err, data) => {
|
nexmo.message.sendSms(min.instance.smsServiceNumber, mobile, text, {}, (err, data) => {
|
||||||
const message = data.messages ? data.messages[0] : {};
|
const message = data.messages ? data.messages[0] : {};
|
||||||
if (err || message['error-text']) {
|
if (err || message['error-text']) {
|
||||||
GBLog.error(`BASIC: error sending SMS to ${mobile}: ${message['error-text']}`);
|
GBLog.error(`BASIC: error sending SMS to ${mobile}: ${message['error-text']}`);
|
||||||
|
|
@ -318,22 +400,21 @@ export class GBConversationalService {
|
||||||
resolve(data);
|
resolve(data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendToMobile(min: GBMinInstance, mobile: string, message: string, conversationId) {
|
public async sendToMobile (min: GBMinInstance, mobile: string, message: string, conversationId) {
|
||||||
GBLog.info(`Sending message ${message} to ${mobile}...`);
|
GBLog.info(`Sending message ${message} to ${mobile}...`);
|
||||||
await min.whatsAppDirectLine.sendToDevice(mobile, message, conversationId);
|
await min.whatsAppDirectLine.sendToDevice(mobile, message, conversationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async getAudioBufferFromText (text): Promise<string> {
|
||||||
public static async getAudioBufferFromText(text): Promise<string> {
|
|
||||||
return new Promise<string>(async (resolve, reject) => {
|
return new Promise<string>(async (resolve, reject) => {
|
||||||
const name = GBAdminService.getRndReadableIdentifier();
|
const name = GBAdminService.getRndReadableIdentifier();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const textToSpeech = new TextToSpeechV1({
|
const textToSpeech = new TextToSpeechV1({
|
||||||
authenticator: new IamAuthenticator({ apikey: process.env.WATSON_TTS_KEY }),
|
authenticator: new IamAuthenticator({ apikey: process.env.WATSON_TTS_KEY }),
|
||||||
url: process.env.WATSON_TTS_URL
|
url: process.env.WATSON_TTS_URL
|
||||||
|
|
@ -350,32 +431,32 @@ export class GBConversationalService {
|
||||||
let res = await textToSpeech.synthesize(params);
|
let res = await textToSpeech.synthesize(params);
|
||||||
const waveFilename = `work/tmp${name}.pcm`;
|
const waveFilename = `work/tmp${name}.pcm`;
|
||||||
|
|
||||||
let audio = '';
|
let audio = await textToSpeech.repairWavHeaderStream(res.result as any);
|
||||||
audio = await textToSpeech.repairWavHeaderStream(res.result);
|
Fs.writeFileSync(waveFilename, audio);
|
||||||
fs.writeFileSync(waveFilename, audio);
|
|
||||||
|
|
||||||
const oggFilenameOnly = `tmp${name}.ogg`;
|
const oggFilenameOnly = `tmp${name}.ogg`;
|
||||||
const oggFilename = `work/${oggFilenameOnly}`;
|
const oggFilename = `work/${oggFilenameOnly}`;
|
||||||
const output = fs.createWriteStream(oggFilename);
|
const output = Fs.createWriteStream(oggFilename);
|
||||||
const transcoder = new prism.FFmpeg({
|
const transcoder = new prism.FFmpeg({
|
||||||
args: ['-analyzeduration', '0', '-loglevel', '0', '-f', 'opus', '-ar', '16000', '-ac', '1']
|
args: ['-analyzeduration', '0', '-loglevel', '0', '-f', 'opus', '-ar', '16000', '-ac', '1']
|
||||||
});
|
});
|
||||||
fs.createReadStream(waveFilename).pipe(transcoder).pipe(output);
|
Fs.createReadStream(waveFilename)
|
||||||
|
.pipe(transcoder)
|
||||||
|
.pipe(output);
|
||||||
|
|
||||||
let url = urlJoin(GBServer.globals.publicAddress, 'audios', oggFilenameOnly);
|
let url = urlJoin(GBServer.globals.publicAddress, 'audios', oggFilenameOnly);
|
||||||
resolve(url);
|
resolve(url);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async getTextFromAudioBuffer(speechKey, cloudRegion, buffer, locale): Promise<string> {
|
public static async getTextFromAudioBuffer (speechKey, cloudRegion, buffer, locale): Promise<string> {
|
||||||
return new Promise<string>(async (resolve, reject) => {
|
return new Promise<string>(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const oggFile = new Readable();
|
const oggFile = new Readable();
|
||||||
oggFile._read = () => { }; // _read is required but you can noop it
|
oggFile._read = () => {}; // _read is required but you can noop it
|
||||||
oggFile.push(buffer);
|
oggFile.push(buffer);
|
||||||
oggFile.push(null);
|
oggFile.push(null);
|
||||||
|
|
||||||
|
|
@ -383,7 +464,7 @@ export class GBConversationalService {
|
||||||
|
|
||||||
const dest = `work/tmp${name}.wav`;
|
const dest = `work/tmp${name}.wav`;
|
||||||
const src = `work/tmp${name}.ogg`;
|
const src = `work/tmp${name}.ogg`;
|
||||||
fs.writeFileSync(src, oggFile.read());
|
Fs.writeFileSync(src, oggFile.read());
|
||||||
|
|
||||||
const makeMp3 = shell([
|
const makeMp3 = shell([
|
||||||
'node_modules/ffmpeg-static/ffmpeg.exe',
|
'node_modules/ffmpeg-static/ffmpeg.exe',
|
||||||
|
|
@ -406,7 +487,7 @@ export class GBConversationalService {
|
||||||
GBLog.error(error);
|
GBLog.error(error);
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
} else {
|
} else {
|
||||||
let data = fs.readFileSync(dest);
|
let data = Fs.readFileSync(dest);
|
||||||
|
|
||||||
const speechToText = new SpeechToTextV1({
|
const speechToText = new SpeechToTextV1({
|
||||||
authenticator: new IamAuthenticator({ apikey: process.env.WATSON_STT_KEY }),
|
authenticator: new IamAuthenticator({ apikey: process.env.WATSON_STT_KEY }),
|
||||||
|
|
@ -439,13 +520,7 @@ export class GBConversationalService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async playMarkdown(
|
public async playMarkdown (min: GBMinInstance, answer: string, channel: string, step: GBDialogStep, mobile: string) {
|
||||||
min: GBMinInstance,
|
|
||||||
answer: string,
|
|
||||||
channel: string,
|
|
||||||
step: GBDialogStep,
|
|
||||||
mobile: string
|
|
||||||
) {
|
|
||||||
const user = step ? await min.userProfile.get(step.context, {}) : null;
|
const user = step ? await min.userProfile.get(step.context, {}) : null;
|
||||||
let text = answer;
|
let text = answer;
|
||||||
|
|
||||||
|
|
@ -461,15 +536,22 @@ export class GBConversationalService {
|
||||||
GBLog.verbose(`Translated text(playMarkdown): ${text}.`);
|
GBLog.verbose(`Translated text(playMarkdown): ${text}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
var renderer = new marked.Renderer();
|
var renderer = new marked.marked.Renderer();
|
||||||
renderer.oldImage = renderer.image;
|
renderer.oldImage = renderer.image;
|
||||||
renderer.image = function (href, title, text) {
|
renderer.image = function (href, title, text) {
|
||||||
var videos = ['webm', 'mp4', 'mov'];
|
var videos = ['webm', 'mp4', 'mov'];
|
||||||
var filetype = href.split('.').pop();
|
var filetype = href.split('.').pop();
|
||||||
if (videos.indexOf(filetype) > -1) {
|
if (videos.indexOf(filetype) > -1) {
|
||||||
var out = '<video autoplay loop alt="' + text + '">'
|
var out =
|
||||||
+ ' <source src="' + href + '" type="video/' + filetype + '">'
|
'<video autoplay loop alt="' +
|
||||||
+ '</video>'
|
text +
|
||||||
|
'">' +
|
||||||
|
' <source src="' +
|
||||||
|
href +
|
||||||
|
'" type="video/' +
|
||||||
|
filetype +
|
||||||
|
'">' +
|
||||||
|
'</video>';
|
||||||
return out;
|
return out;
|
||||||
} else {
|
} else {
|
||||||
return renderer.oldImage(href, title, text);
|
return renderer.oldImage(href, title, text);
|
||||||
|
|
@ -494,8 +576,7 @@ export class GBConversationalService {
|
||||||
|
|
||||||
text = text.replace('! [', '![').replace('] (', '](');
|
text = text.replace('! [', '![').replace('] (', '](');
|
||||||
text = text.replace(`[[embed url=`, process.env.BOT_URL + '/').replace(']]', ''); // TODO: Improve it.
|
text = text.replace(`[[embed url=`, process.env.BOT_URL + '/').replace(']]', ''); // TODO: Improve it.
|
||||||
text = text.replace(`](kb`, "](" + process.env.BOT_URL + '/kb'); // TODO: Improve it.
|
text = text.replace(`](kb`, '](' + process.env.BOT_URL + '/kb'); // TODO: Improve it.
|
||||||
|
|
||||||
|
|
||||||
if (mobile) {
|
if (mobile) {
|
||||||
await this.sendMarkdownToMobile(min, step, mobile, text);
|
await this.sendMarkdownToMobile(min, step, mobile, text);
|
||||||
|
|
@ -508,12 +589,7 @@ export class GBConversationalService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async sendMarkdownToWeb(
|
private async sendMarkdownToWeb (min, step: GBDialogStep, html: string, answer: string) {
|
||||||
min,
|
|
||||||
step: GBDialogStep,
|
|
||||||
html: string,
|
|
||||||
answer: string
|
|
||||||
) {
|
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
|
|
||||||
html = html.replace(/src\=\"kb\//gi, `src=\"../kb/`);
|
html = html.replace(/src\=\"kb\//gi, `src=\"../kb/`);
|
||||||
|
|
@ -523,15 +599,14 @@ export class GBConversationalService {
|
||||||
content: html,
|
content: html,
|
||||||
answer: answer,
|
answer: answer,
|
||||||
prevId: 0, // TODO: answer.prevId,
|
prevId: 0, // TODO: answer.prevId,
|
||||||
nextId: 0, // TODO: answer.nextId
|
nextId: 0 // TODO: answer.nextId
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// tslint:enable:no-unsafe-any
|
// tslint:enable:no-unsafe-any
|
||||||
|
|
||||||
public async sendMarkdownToMobile(min: GBMinInstance, step: GBDialogStep, mobile: string, text: string) {
|
public async sendMarkdownToMobile (min: GBMinInstance, step: GBDialogStep, mobile: string, text: string) {
|
||||||
let sleep = ms => {
|
let sleep = ms => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
setTimeout(resolve, ms);
|
setTimeout(resolve, ms);
|
||||||
|
|
@ -701,21 +776,20 @@ export class GBConversationalService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: Update botlib.
|
// TODO: Update botlib.
|
||||||
public async routeNLP(step: GBDialogStep, min: GBMinInstance, text: string): Promise<boolean> {
|
public async routeNLP (step: GBDialogStep, min: GBMinInstance, text: string): Promise<boolean> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
public async routeNLP2(step: GBDialogStep, min: GBMinInstance, text: string) {
|
public async routeNLP2 (step: GBDialogStep, min: GBMinInstance, text: string) {
|
||||||
if (min.instance.nlpAppId === null || min.instance.nlpAppId === undefined) {
|
if (min.instance.nlpAppId === null || min.instance.nlpAppId === undefined) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
text = text.toLowerCase();
|
text = text.toLowerCase();
|
||||||
text = text.replace('who´s', 'who is');
|
text = text.replace('who´s', 'who is');
|
||||||
text = text.replace('who\'s', 'who is');
|
text = text.replace("who's", 'who is');
|
||||||
text = text.replace('what´s', 'what is');
|
text = text.replace('what´s', 'what is');
|
||||||
text = text.replace('what\'s', 'what is');
|
text = text.replace("what's", 'what is');
|
||||||
text = text.replace('?', ' ');
|
text = text.replace('?', ' ');
|
||||||
text = text.replace('¿', ' ');
|
text = text.replace('¿', ' ');
|
||||||
text = text.replace('!', ' ');
|
text = text.replace('!', ' ');
|
||||||
|
|
@ -734,10 +808,14 @@ export class GBConversationalService {
|
||||||
try {
|
try {
|
||||||
const saved = step.context.activity.text;
|
const saved = step.context.activity.text;
|
||||||
step.context.activity.text = text;
|
step.context.activity.text = text;
|
||||||
nlp = await model.recognize(step.context, {}, {}, { IncludeAllIntents: false, IncludeInstanceData: false, includeAPIResults: true });
|
nlp = await model.recognize(
|
||||||
|
step.context,
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{ IncludeAllIntents: false, IncludeInstanceData: false, includeAPIResults: true }
|
||||||
|
);
|
||||||
step.context.activity.text = saved;
|
step.context.activity.text = saved;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
// tslint:disable:no-unsafe-any
|
// tslint:disable:no-unsafe-any
|
||||||
if (error.statusCode === 404 || error.statusCode === 400) {
|
if (error.statusCode === 404 || error.statusCode === 400) {
|
||||||
GBLog.warn('NLP application still not publish and there are no other options for answering.');
|
GBLog.warn('NLP application still not publish and there are no other options for answering.');
|
||||||
|
|
@ -755,8 +833,11 @@ export class GBConversationalService {
|
||||||
const minBoot = GBServer.globals.minBoot as any;
|
const minBoot = GBServer.globals.minBoot as any;
|
||||||
let nlpActive = false;
|
let nlpActive = false;
|
||||||
let score = 0;
|
let score = 0;
|
||||||
const instanceScore = min.core.getParam(min.instance, 'NLP Score',
|
const instanceScore = min.core.getParam(
|
||||||
min.instance.nlpScore ? min.instance.nlpScore : minBoot.instance.nlpScore);
|
min.instance,
|
||||||
|
'NLP Score',
|
||||||
|
min.instance.nlpScore ? min.instance.nlpScore : minBoot.instance.nlpScore
|
||||||
|
);
|
||||||
|
|
||||||
Object.keys(nlp.intents).forEach(name => {
|
Object.keys(nlp.intents).forEach(name => {
|
||||||
score = nlp.intents[name].score;
|
score = nlp.intents[name].score;
|
||||||
|
|
@ -775,7 +856,9 @@ export class GBConversationalService {
|
||||||
}
|
}
|
||||||
|
|
||||||
GBLog.info(
|
GBLog.info(
|
||||||
`NLP called: ${intent}, entities: ${nlp.entities.length}, score: ${score} > required (nlpScore): ${instanceScore}`
|
`NLP called: ${intent}, entities: ${
|
||||||
|
nlp.entities.length
|
||||||
|
}, score: ${score} > required (nlpScore): ${instanceScore}`
|
||||||
);
|
);
|
||||||
|
|
||||||
step.activeDialog.state.options.entities = nlp.entities;
|
step.activeDialog.state.options.entities = nlp.entities;
|
||||||
|
|
@ -784,7 +867,7 @@ export class GBConversationalService {
|
||||||
|
|
||||||
if (nlp.entities) {
|
if (nlp.entities) {
|
||||||
await CollectionUtil.asyncForEach(Object.keys(nlp.entities), async key => {
|
await CollectionUtil.asyncForEach(Object.keys(nlp.entities), async key => {
|
||||||
if (key !== "$instance") {
|
if (key !== '$instance') {
|
||||||
let entity = nlp.entities[key];
|
let entity = nlp.entities[key];
|
||||||
if (Array.isArray(entity[0])) {
|
if (Array.isArray(entity[0])) {
|
||||||
nlp.entities[key] = entity.slice(1);
|
nlp.entities[key] = entity.slice(1);
|
||||||
|
|
@ -796,14 +879,12 @@ export class GBConversationalService {
|
||||||
return await step.replaceDialog(`/${intent}`, step.activeDialog.state.options);
|
return await step.replaceDialog(`/${intent}`, step.activeDialog.state.options);
|
||||||
}
|
}
|
||||||
|
|
||||||
GBLog.info(
|
GBLog.info(`NLP NOT called: score: ${score} > required (nlpScore): ${instanceScore}`);
|
||||||
`NLP NOT called: score: ${score} > required (nlpScore): ${instanceScore}`
|
|
||||||
);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getLanguage(min: GBMinInstance, text: string): Promise<string> {
|
public async getLanguage (min: GBMinInstance, text: string): Promise<string> {
|
||||||
const key = min.core.getParam<string>(min.instance, 'textAnalyticsKey', null);
|
const key = min.core.getParam<string>(min.instance, 'textAnalyticsKey', null);
|
||||||
if (!key) {
|
if (!key) {
|
||||||
return process.env.DEFAULT_USER_LANGUAGE;
|
return process.env.DEFAULT_USER_LANGUAGE;
|
||||||
|
|
@ -817,9 +898,8 @@ export class GBConversationalService {
|
||||||
return language === '(Unknown)' ? 'en' : language;
|
return language === '(Unknown)' ? 'en' : language;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async spellCheck(min: GBMinInstance, text: string): Promise<string> {
|
public async spellCheck (min: GBMinInstance, text: string): Promise<string> {
|
||||||
const key =
|
const key = min.core.getParam<string>(min.instance, 'spellcheckerKey', null);
|
||||||
min.core.getParam<string>(min.instance, 'spellcheckerKey', null);
|
|
||||||
|
|
||||||
if (key) {
|
if (key) {
|
||||||
text = text.charAt(0).toUpperCase() + text.slice(1);
|
text = text.charAt(0).toUpperCase() + text.slice(1);
|
||||||
|
|
@ -833,7 +913,7 @@ export class GBConversationalService {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async translate(min: GBMinInstance, text: string, language: string): Promise<string> {
|
public async translate (min: GBMinInstance, text: string, language: string): Promise<string> {
|
||||||
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);
|
||||||
|
|
@ -844,7 +924,11 @@ export class GBConversationalService {
|
||||||
const endPoint = min.core.getParam<string>(min.instance, 'translatorEndpoint', null);
|
const endPoint = min.core.getParam<string>(min.instance, 'translatorEndpoint', null);
|
||||||
const key = min.core.getParam<string>(min.instance, 'translatorKey', null);
|
const key = min.core.getParam<string>(min.instance, 'translatorKey', null);
|
||||||
|
|
||||||
if ((endPoint === null && !min.instance.googleProjectId) || !translatorEnabled() || process.env.TRANSLATOR_DISABLED === 'true') {
|
if (
|
||||||
|
(endPoint === null && !min.instance.googleProjectId) ||
|
||||||
|
!translatorEnabled() ||
|
||||||
|
process.env.TRANSLATOR_DISABLED === 'true'
|
||||||
|
) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -859,13 +943,15 @@ export class GBConversationalService {
|
||||||
if (min.instance.googleProjectId) {
|
if (min.instance.googleProjectId) {
|
||||||
// Instantiates a client
|
// Instantiates a client
|
||||||
|
|
||||||
const translate = new Translate({
|
const translate = new Translate.v2.Translate({
|
||||||
projectId: min.instance.googleProjectId,
|
projectId: min.instance.googleProjectId,
|
||||||
credentials: { client_email: min.instance.googleClientEmail, private_key: min.instance.googlePrivateKey.replace(/\\n/gm, '\n') }
|
credentials: {
|
||||||
|
client_email: min.instance.googleClientEmail,
|
||||||
|
private_key: min.instance.googlePrivateKey.replace(/\\n/gm, '\n')
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const [translation] = await translate.translate(text, language);
|
const [translation] = await translate.translate(text, language);
|
||||||
|
|
||||||
return translation;
|
return translation;
|
||||||
|
|
@ -874,10 +960,7 @@ export class GBConversationalService {
|
||||||
|
|
||||||
return Promise.reject(new Error(msg));
|
return Promise.reject(new Error(msg));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
let options = {
|
let options = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
baseUrl: endPoint,
|
baseUrl: endPoint,
|
||||||
|
|
@ -901,7 +984,6 @@ export class GBConversationalService {
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const results = await request(options);
|
const results = await request(options);
|
||||||
|
|
||||||
return results[0].translations[0].text;
|
return results[0].translations[0].text;
|
||||||
|
|
@ -913,11 +995,11 @@ export class GBConversationalService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async prompt(min: GBMinInstance, step: GBDialogStep, text: string) {
|
public async prompt (min: GBMinInstance, step: GBDialogStep, text: string) {
|
||||||
const user = await min.userProfile.get(step.context, {});
|
const user = await min.userProfile.get(step.context, {});
|
||||||
const systemUser = user.systemUser;
|
const systemUser = user.systemUser;
|
||||||
|
|
||||||
if (text && text !== "") {
|
if (text && text !== '') {
|
||||||
text = await min.conversationalService.translate(
|
text = await min.conversationalService.translate(
|
||||||
min,
|
min,
|
||||||
text,
|
text,
|
||||||
|
|
@ -927,21 +1009,18 @@ export class GBConversationalService {
|
||||||
);
|
);
|
||||||
GBLog.verbose(`Translated text(prompt): ${text}.`);
|
GBLog.verbose(`Translated text(prompt): ${text}.`);
|
||||||
}
|
}
|
||||||
if (step.activeDialog.state.options['kind'] === "file") {
|
if (step.activeDialog.state.options['kind'] === 'file') {
|
||||||
return await step.prompt('attachmentPrompt', {});
|
return await step.prompt('attachmentPrompt', {});
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.prompt('textPrompt', text ? text : {});
|
return await step.prompt('textPrompt', text ? text : {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendText(min: GBMinInstance, step, text) {
|
public async sendText (min: GBMinInstance, step, text) {
|
||||||
await this['sendTextWithOptions'](min, step, text, true, null);
|
await this['sendTextWithOptions'](min, step, text, true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendTextWithOptions(min: GBMinInstance, step, text, translate, keepTextList) {
|
public async sendTextWithOptions (min: GBMinInstance, step, text, translate, keepTextList) {
|
||||||
const member = step.context.activity.from;
|
const member = step.context.activity.from;
|
||||||
const user = await min.userProfile.get(step.context, {});
|
const user = await min.userProfile.get(step.context, {});
|
||||||
const systemUser = user.systemUser;
|
const systemUser = user.systemUser;
|
||||||
|
|
@ -968,9 +1047,7 @@ export class GBConversationalService {
|
||||||
text = await min.conversationalService.translate(
|
text = await min.conversationalService.translate(
|
||||||
min,
|
min,
|
||||||
text,
|
text,
|
||||||
locale
|
locale ? locale : min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
||||||
? locale
|
|
||||||
: min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (keepTextList) {
|
if (keepTextList) {
|
||||||
|
|
@ -991,18 +1068,15 @@ export class GBConversationalService {
|
||||||
analytics.createMessage(min.instance.instanceId, user.conversation, null, text);
|
analytics.createMessage(min.instance.instanceId, user.conversation, null, text);
|
||||||
|
|
||||||
if (!isNaN(member.id) && !member.id.startsWith('1000')) {
|
if (!isNaN(member.id) && !member.id.startsWith('1000')) {
|
||||||
|
const to = step.context.activity.group ? step.context.activity.group : member.id;
|
||||||
const to = step.context.activity.group? step.context.activity.group : member.id;
|
|
||||||
|
|
||||||
await min.whatsAppDirectLine.sendToDevice(to, text, step.context.activity.conversation.id);
|
await min.whatsAppDirectLine.sendToDevice(to, text, step.context.activity.conversation.id);
|
||||||
} else {
|
} else {
|
||||||
await step.context.sendActivity(text);
|
await step.context.sendActivity(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async broadcast(min: GBMinInstance, message: string) {
|
public async broadcast (min: GBMinInstance, message: string) {
|
||||||
GBLog.info(`Sending broadcast notifications...`);
|
GBLog.info(`Sending broadcast notifications...`);
|
||||||
|
|
||||||
let sleep = ms => {
|
let sleep = ms => {
|
||||||
|
|
@ -1026,57 +1100,48 @@ export class GBConversationalService {
|
||||||
*
|
*
|
||||||
* Sends a message in a user with an already started conversation (got ConversationReference set)
|
* Sends a message in a user with an already started conversation (got ConversationReference set)
|
||||||
*/
|
*/
|
||||||
public async sendOnConversation(min: GBMinInstance, user: GuaribasUser, message: string) {
|
public async sendOnConversation (min: GBMinInstance, user: GuaribasUser, message: string) {
|
||||||
|
|
||||||
if (user.conversationReference.startsWith('spaces')) {
|
if (user.conversationReference.startsWith('spaces')) {
|
||||||
await min['googleDirectLine'].sendToDevice(user.userSystemId, null, user.conversationReference, message);
|
await min['googleDirectLine'].sendToDevice(user.userSystemId, null, user.conversationReference, message);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
const ref = JSON.parse(user.conversationReference);
|
const ref = JSON.parse(user.conversationReference);
|
||||||
MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl);
|
MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl);
|
||||||
try {
|
try {
|
||||||
await min.bot['continueConversation'](ref, async (t1) => {
|
await min.bot['continueConversation'](ref, async t1 => {
|
||||||
const ref2 = TurnContext.getConversationReference(t1.activity);
|
const ref2 = TurnContext.getConversationReference(t1.activity);
|
||||||
await min.bot.continueConversation(ref2, async (t2) => {
|
await min.bot.continueConversation(ref2, async t2 => {
|
||||||
await t2.sendActivity(message);
|
await t2.sendActivity(message);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error) ;
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static kmpSearch(pattern, text) {
|
public static kmpSearch (pattern, text) {
|
||||||
pattern = pattern.toLowerCase();
|
pattern = pattern.toLowerCase();
|
||||||
text = text.toLowerCase();
|
text = text.toLowerCase();
|
||||||
if (pattern.length == 0)
|
if (pattern.length == 0) return 0; // Immediate match
|
||||||
return 0; // Immediate match
|
|
||||||
|
|
||||||
// Compute longest suffix-prefix table
|
// Compute longest suffix-prefix table
|
||||||
var lsp = [0]; // Base case
|
var lsp = [0]; // Base case
|
||||||
for (var i = 1; i < pattern.length; i++) {
|
for (var i = 1; i < pattern.length; i++) {
|
||||||
var j = lsp[i - 1]; // Start by assuming we're extending the previous LSP
|
var j = lsp[i - 1]; // Start by assuming we're extending the previous LSP
|
||||||
while (j > 0 && pattern.charAt(i) != pattern.charAt(j))
|
while (j > 0 && pattern.charAt(i) != pattern.charAt(j)) j = lsp[j - 1];
|
||||||
j = lsp[j - 1];
|
if (pattern.charAt(i) == pattern.charAt(j)) j++;
|
||||||
if (pattern.charAt(i) == pattern.charAt(j))
|
|
||||||
j++;
|
|
||||||
lsp.push(j);
|
lsp.push(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk through text string
|
// Walk through text string
|
||||||
var j = 0; // Number of chars matched in pattern
|
var j = 0; // Number of chars matched in pattern
|
||||||
for (var i = 0; i < text.length; i++) {
|
for (var i = 0; i < text.length; i++) {
|
||||||
while (j > 0 && text.charAt(i) != pattern.charAt(j))
|
while (j > 0 && text.charAt(i) != pattern.charAt(j)) j = lsp[j - 1]; // Fall back in the pattern
|
||||||
j = lsp[j - 1]; // Fall back in the pattern
|
|
||||||
if (text.charAt(i) == pattern.charAt(j)) {
|
if (text.charAt(i) == pattern.charAt(j)) {
|
||||||
j++; // Next char matched, increment position
|
j++; // Next char matched, increment position
|
||||||
if (j == pattern.length)
|
if (j == pattern.length) return i - (j - 1);
|
||||||
return i - (j - 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1; // Not found
|
return -1; // Not found
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,30 +37,29 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { GBLog, IGBCoreService, IGBInstallationDeployer, IGBInstance, IGBPackage } from 'botlib';
|
import { GBLog, IGBCoreService, IGBInstallationDeployer, IGBInstance, IGBPackage } from 'botlib';
|
||||||
import * as fs from 'fs';
|
import * as Fs from 'fs';
|
||||||
import { Sequelize, SequelizeOptions } from 'sequelize-typescript';
|
import { Sequelize, SequelizeOptions } from 'sequelize-typescript';
|
||||||
import { Op, Dialect } from 'sequelize';
|
import { Op, Dialect } from 'sequelize';
|
||||||
import { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBAdminPackage } from '../../admin.gbapp/index';
|
import { GBAdminPackage } from '../../admin.gbapp/index.js';
|
||||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
||||||
import { GBAnalyticsPackage } from '../../analytics.gblib';
|
import { GBAnalyticsPackage } from '../../analytics.gblib/index.js';
|
||||||
import { StartDialog } from '../../azuredeployer.gbapp/dialogs/StartDialog';
|
import { StartDialog } from '../../azuredeployer.gbapp/dialogs/StartDialog.js';
|
||||||
import { GBCorePackage } from '../../core.gbapp';
|
import { GBCorePackage } from '../../core.gbapp/index.js';
|
||||||
import { GBCustomerSatisfactionPackage } from '../../customer-satisfaction.gbapp';
|
import { GBCustomerSatisfactionPackage } from '../../customer-satisfaction.gbapp/index.js';
|
||||||
import { GBKBPackage } from '../../kb.gbapp';
|
import { GBKBPackage } from '../../kb.gbapp/index.js';
|
||||||
import { GBSecurityPackage } from '../../security.gbapp';
|
import { GBSecurityPackage } from '../../security.gbapp/index.js';
|
||||||
import { GBWhatsappPackage } from '../../whatsapp.gblib/index';
|
import { GBWhatsappPackage } from '../../whatsapp.gblib/index.js';
|
||||||
import { GuaribasInstance } from '../models/GBModel';
|
import { GuaribasInstance } from '../models/GBModel.js';
|
||||||
import { GBConfigService } from './GBConfigService';
|
import { GBConfigService } from './GBConfigService.js';
|
||||||
import { GBAzureDeployerPackage } from '../../azuredeployer.gbapp';
|
import { GBAzureDeployerPackage } from '../../azuredeployer.gbapp/index.js';
|
||||||
import { GBSharePointPackage } from '../../sharepoint.gblib';
|
import { GBSharePointPackage } from '../../sharepoint.gblib/index.js';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { GBBasicPackage } from '../../basic.gblib';
|
import { GBBasicPackage } from '../../basic.gblib/index.js';
|
||||||
import { GBGoogleChatPackage } from '../../google-chat.gblib';
|
import { GBGoogleChatPackage } from '../../google-chat.gblib/index.js';
|
||||||
import { GBHubSpotPackage } from '../../hubspot.gblib';
|
import { GBHubSpotPackage } from '../../hubspot.gblib/index.js';
|
||||||
|
import open from 'open';
|
||||||
const opn = require('opn');
|
import ngrok from 'ngrok';
|
||||||
const cron = require('node-cron');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GBCoreService contains main logic for handling storage services related
|
* GBCoreService contains main logic for handling storage services related
|
||||||
|
|
@ -103,16 +102,16 @@ export class GBCoreService implements IGBCoreService {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor () {
|
||||||
this.adminService = new GBAdminService(this);
|
this.adminService = new GBAdminService(this);
|
||||||
}
|
}
|
||||||
public async ensureInstances(instances: IGBInstance[], bootInstance: any, core: IGBCoreService) { }
|
public async ensureInstances (instances: IGBInstance[], bootInstance: any, core: IGBCoreService) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets database config and connect to storage. Currently two databases
|
* Gets database config and connect to storage. Currently two databases
|
||||||
* are available: SQL Server and SQLite.
|
* are available: SQL Server and SQLite.
|
||||||
*/
|
*/
|
||||||
public async initStorage(): Promise<any> {
|
public async initStorage (): Promise<any> {
|
||||||
this.dialect = GBConfigService.get('STORAGE_DIALECT');
|
this.dialect = GBConfigService.get('STORAGE_DIALECT');
|
||||||
|
|
||||||
let host: string | undefined;
|
let host: string | undefined;
|
||||||
|
|
@ -178,7 +177,7 @@ export class GBCoreService implements IGBCoreService {
|
||||||
* Checks wheather storage is acessible or not and opens firewall
|
* Checks wheather storage is acessible or not and opens firewall
|
||||||
* in case of any connection block.
|
* in case of any connection block.
|
||||||
*/
|
*/
|
||||||
public async checkStorage(installationDeployer: IGBInstallationDeployer) {
|
public async checkStorage (installationDeployer: IGBInstallationDeployer) {
|
||||||
try {
|
try {
|
||||||
await this.sequelize.authenticate();
|
await this.sequelize.authenticate();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -193,11 +192,10 @@ export class GBCoreService implements IGBCoreService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
|
||||||
* Syncronizes structure between model and tables in storage.
|
* Syncronizes structure between model and tables in storage.
|
||||||
*/
|
*/
|
||||||
public async syncDatabaseStructure() {
|
public async syncDatabaseStructure () {
|
||||||
if (GBConfigService.get('STORAGE_SYNC') === 'true') {
|
if (GBConfigService.get('STORAGE_SYNC') === 'true') {
|
||||||
const alter = GBConfigService.get('STORAGE_SYNC_ALTER') === 'true';
|
const alter = GBConfigService.get('STORAGE_SYNC_ALTER') === 'true';
|
||||||
GBLog.info('Syncing database...');
|
GBLog.info('Syncing database...');
|
||||||
|
|
@ -215,7 +213,7 @@ export class GBCoreService implements IGBCoreService {
|
||||||
/**
|
/**
|
||||||
* Loads all items to start several listeners.
|
* Loads all items to start several listeners.
|
||||||
*/
|
*/
|
||||||
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 = [];
|
||||||
|
|
@ -238,7 +236,7 @@ export class GBCoreService implements IGBCoreService {
|
||||||
/**
|
/**
|
||||||
* Loads just one Bot instance by its internal Id.
|
* Loads just one Bot instance by its internal Id.
|
||||||
*/
|
*/
|
||||||
public async loadInstanceById(instanceId: number): Promise<IGBInstance> {
|
public async loadInstanceById (instanceId: number): Promise<IGBInstance> {
|
||||||
const options = { where: { instanceId: instanceId, state: 'active' } };
|
const options = { where: { instanceId: instanceId, state: 'active' } };
|
||||||
|
|
||||||
return await GuaribasInstance.findOne(options);
|
return await GuaribasInstance.findOne(options);
|
||||||
|
|
@ -246,7 +244,7 @@ export class GBCoreService implements IGBCoreService {
|
||||||
/**
|
/**
|
||||||
* Loads just one Bot instance.
|
* Loads just one Bot instance.
|
||||||
*/
|
*/
|
||||||
public async loadInstanceByActivationCode(code: string): Promise<IGBInstance> {
|
public async loadInstanceByActivationCode (code: string): Promise<IGBInstance> {
|
||||||
let options = { where: { activationCode: code, state: 'active' } };
|
let options = { where: { activationCode: code, state: 'active' } };
|
||||||
|
|
||||||
return await GuaribasInstance.findOne(options);
|
return await GuaribasInstance.findOne(options);
|
||||||
|
|
@ -254,7 +252,7 @@ export class GBCoreService implements IGBCoreService {
|
||||||
/**
|
/**
|
||||||
* Loads just one Bot instance.
|
* Loads just one Bot instance.
|
||||||
*/
|
*/
|
||||||
public async loadInstanceByBotId(botId: string): Promise<IGBInstance> {
|
public async loadInstanceByBotId (botId: string): Promise<IGBInstance> {
|
||||||
const options = { where: {} };
|
const options = { where: {} };
|
||||||
options.where = { botId: botId, state: 'active' };
|
options.where = { botId: botId, state: 'active' };
|
||||||
|
|
||||||
|
|
@ -266,7 +264,7 @@ export class GBCoreService implements IGBCoreService {
|
||||||
* first startup, when user is asked some questions to create the
|
* first startup, when user is asked some questions to create the
|
||||||
* full base environment.
|
* full base environment.
|
||||||
*/
|
*/
|
||||||
public async writeEnv(instance: IGBInstance) {
|
public async writeEnv (instance: IGBInstance) {
|
||||||
const env = `
|
const env = `
|
||||||
ADDITIONAL_DEPLOY_PATH=
|
ADDITIONAL_DEPLOY_PATH=
|
||||||
ADMIN_PASS=${instance.adminPass}
|
ADMIN_PASS=${instance.adminPass}
|
||||||
|
|
@ -288,20 +286,18 @@ STORAGE_SYNC_ALTER=true
|
||||||
ENDPOINT_UPDATE=true
|
ENDPOINT_UPDATE=true
|
||||||
`;
|
`;
|
||||||
|
|
||||||
fs.writeFileSync('.env', env);
|
Fs.writeFileSync('.env', env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Certifies that network servers will reach back the development machine
|
* Certifies that network servers will reach back the development machine
|
||||||
* when calling back from web services. This ensures that reverse proxy is
|
* when calling back from web services. This ensures that reverse proxy is
|
||||||
* established.
|
* established.
|
||||||
*/
|
*/
|
||||||
public async ensureProxy(port): Promise<string> {
|
public async ensureProxy (port): Promise<string> {
|
||||||
try {
|
try {
|
||||||
if (fs.existsSync('node_modules/ngrok/bin/ngrok.exe') || fs.existsSync('node_modules/ngrok/bin/ngrok')) {
|
if (Fs.existsSync('node_modules/ngrok/bin/ngrok.exe') || Fs.existsSync('node_modules/ngrok/bin/ngrok')) {
|
||||||
const ngrok = require('ngrok');
|
return await ngrok.connect({ port: port });
|
||||||
return await ngrok.connect({ port: port }, 10);
|
|
||||||
} else {
|
} else {
|
||||||
GBLog.warn('ngrok executable not found (only tested on Windows). Check installation or node_modules folder.');
|
GBLog.warn('ngrok executable not found (only tested on Windows). Check installation or node_modules folder.');
|
||||||
|
|
||||||
|
|
@ -319,7 +315,7 @@ ENDPOINT_UPDATE=true
|
||||||
* Setup generic web hooks so .gbapps can expose application logic
|
* Setup generic web hooks so .gbapps can expose application logic
|
||||||
* and get called on demand.
|
* and get called on demand.
|
||||||
*/
|
*/
|
||||||
public installWebHook(isGet: boolean, url: string, callback: any) {
|
public installWebHook (isGet: boolean, url: string, callback: any) {
|
||||||
if (isGet) {
|
if (isGet) {
|
||||||
GBServer.globals.server.get(url, (req, res) => {
|
GBServer.globals.server.get(url, (req, res) => {
|
||||||
callback(req, res);
|
callback(req, res);
|
||||||
|
|
@ -335,7 +331,7 @@ ENDPOINT_UPDATE=true
|
||||||
* Defines the entry point dialog to be called whenever a user
|
* Defines the entry point dialog to be called whenever a user
|
||||||
* starts talking to the bot.
|
* starts talking to the bot.
|
||||||
*/
|
*/
|
||||||
public setEntryPointDialog(dialogName: string) {
|
public setEntryPointDialog (dialogName: string) {
|
||||||
GBServer.globals.entryPointDialog = dialogName;
|
GBServer.globals.entryPointDialog = dialogName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -343,14 +339,14 @@ ENDPOINT_UPDATE=true
|
||||||
* Replaces the default web application root path used to start the GB
|
* Replaces the default web application root path used to start the GB
|
||||||
* with a custom home page.
|
* with a custom home page.
|
||||||
*/
|
*/
|
||||||
public setWWWRoot(localPath: string) {
|
public setWWWRoot (localPath: string) {
|
||||||
GBServer.globals.wwwroot = localPath;
|
GBServer.globals.wwwroot = localPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a bot instance from storage.
|
* Removes a bot instance from storage.
|
||||||
*/
|
*/
|
||||||
public async deleteInstance(botId: string) {
|
public async deleteInstance (botId: string) {
|
||||||
const options = { where: {} };
|
const options = { where: {} };
|
||||||
options.where = { botId: botId };
|
options.where = { botId: botId };
|
||||||
await GuaribasInstance.destroy(options);
|
await GuaribasInstance.destroy(options);
|
||||||
|
|
@ -360,7 +356,7 @@ ENDPOINT_UPDATE=true
|
||||||
* Saves a bot instance object to the storage handling
|
* Saves a bot instance object to the storage handling
|
||||||
* multi-column JSON based store 'params' field.
|
* multi-column JSON based store 'params' field.
|
||||||
*/
|
*/
|
||||||
public async saveInstance(fullInstance: any) {
|
public async saveInstance (fullInstance: any) {
|
||||||
const options = { where: {} };
|
const options = { where: {} };
|
||||||
options.where = { botId: fullInstance.botId };
|
options.where = { botId: fullInstance.botId };
|
||||||
let instance = await GuaribasInstance.findOne(options);
|
let instance = await GuaribasInstance.findOne(options);
|
||||||
|
|
@ -381,7 +377,7 @@ ENDPOINT_UPDATE=true
|
||||||
/**
|
/**
|
||||||
* Loads all bot instances from object storage, if it's formatted.
|
* Loads all bot instances from object storage, if it's formatted.
|
||||||
*/
|
*/
|
||||||
public async loadAllInstances(
|
public async loadAllInstances (
|
||||||
core: IGBCoreService,
|
core: IGBCoreService,
|
||||||
installationDeployer: IGBInstallationDeployer,
|
installationDeployer: IGBInstallationDeployer,
|
||||||
proxyAddress: string
|
proxyAddress: string
|
||||||
|
|
@ -435,7 +431,7 @@ ENDPOINT_UPDATE=true
|
||||||
/**
|
/**
|
||||||
* Loads all system packages from 'packages' folder.
|
* Loads all system packages from 'packages' folder.
|
||||||
*/
|
*/
|
||||||
public async loadSysPackages(core: GBCoreService): Promise<IGBPackage[]> {
|
public async loadSysPackages (core: GBCoreService): Promise<IGBPackage[]> {
|
||||||
// NOTE: if there is any code before this line a semicolon
|
// NOTE: if there is any code before this line a semicolon
|
||||||
// will be necessary before this line.
|
// will be necessary before this line.
|
||||||
// Loads all system packages.
|
// Loads all system packages.
|
||||||
|
|
@ -473,7 +469,7 @@ ENDPOINT_UPDATE=true
|
||||||
* Verifies that an complex global password has been specified
|
* Verifies that an complex global password has been specified
|
||||||
* before starting the server.
|
* before starting the server.
|
||||||
*/
|
*/
|
||||||
public ensureAdminIsSecured() {
|
public ensureAdminIsSecured () {
|
||||||
const password = GBConfigService.get('ADMIN_PASS');
|
const password = GBConfigService.get('ADMIN_PASS');
|
||||||
if (!GBAdminService.StrongRegex.test(password)) {
|
if (!GBAdminService.StrongRegex.test(password)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|
@ -488,7 +484,7 @@ ENDPOINT_UPDATE=true
|
||||||
* So a base main bot is always deployed and will act as root bot for
|
* So a base main bot is always deployed and will act as root bot for
|
||||||
* configuration tree with three levels: .env > root bot > all other bots.
|
* configuration tree with three levels: .env > root bot > all other bots.
|
||||||
*/
|
*/
|
||||||
public async createBootInstance(
|
public async createBootInstance (
|
||||||
core: GBCoreService,
|
core: GBCoreService,
|
||||||
installationDeployer: IGBInstallationDeployer,
|
installationDeployer: IGBInstallationDeployer,
|
||||||
proxyAddress: string
|
proxyAddress: string
|
||||||
|
|
@ -523,9 +519,9 @@ ENDPOINT_UPDATE=true
|
||||||
/**
|
/**
|
||||||
* Helper to get the web browser onpened in UI interfaces.
|
* Helper to get the web browser onpened in UI interfaces.
|
||||||
*/
|
*/
|
||||||
public openBrowserInDevelopment() {
|
public openBrowserInDevelopment () {
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
opn('http://localhost:4242');
|
open('http://localhost:4242');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -544,19 +540,24 @@ ENDPOINT_UPDATE=true
|
||||||
* // ' FOREIGN KEY ([groupId1], [groupId2]) REFERENCES [Group] ([groupId1], [groupId1]) ON DELETE NO ACTION,' +
|
* // ' FOREIGN KEY ([groupId1], [groupId2]) REFERENCES [Group] ([groupId1], [groupId1]) ON DELETE NO ACTION,' +
|
||||||
* // ' FOREIGN KEY ([instanceId]) REFERENCES [Instance] ([instanceId]) ON DELETE NO ACTION)'
|
* // ' FOREIGN KEY ([instanceId]) REFERENCES [Instance] ([instanceId]) ON DELETE NO ACTION)'
|
||||||
*/
|
*/
|
||||||
private createTableQueryOverride(tableName, attributes, options): string {
|
private createTableQueryOverride (tableName, attributes, options): string {
|
||||||
let sql: string = this.createTableQuery.apply(this.queryGenerator, [tableName, attributes, options]);
|
let sql: string = this.createTableQuery.apply(this.queryGenerator, [tableName, attributes, options]);
|
||||||
const re1 = /CREATE\s+TABLE\s+\[([^\]]*)\]/;
|
const re1 = /CREATE\s+TABLE\s+\[([^\]]*)\]/;
|
||||||
const matches = re1.exec(sql);
|
const matches = re1.exec(sql);
|
||||||
if (matches !== null) {
|
if (matches !== null) {
|
||||||
const table = matches[1];
|
const table = matches[1];
|
||||||
const re2 = /PRIMARY\s+KEY\s+\(\[[^\]]*\](?:,\s*\[[^\]]*\])*\)/;
|
const re2 = /PRIMARY\s+KEY\s+\(\[[^\]]*\](?:,\s*\[[^\]]*\])*\)/;
|
||||||
sql = sql.replace(re2, (match: string, ...args: any[]): string => {
|
sql = sql.replace(
|
||||||
|
re2,
|
||||||
|
(match: string, ...args: any[]): string => {
|
||||||
return `CONSTRAINT [${table}_pk] ${match}`;
|
return `CONSTRAINT [${table}_pk] ${match}`;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
const re3 = /FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g;
|
const re3 = /FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g;
|
||||||
const re4 = /\[([^\]]*)\]/g;
|
const re4 = /\[([^\]]*)\]/g;
|
||||||
sql = sql.replace(re3, (match: string, ...args: any[]): string => {
|
sql = sql.replace(
|
||||||
|
re3,
|
||||||
|
(match: string, ...args: any[]): string => {
|
||||||
const fkcols = args[0];
|
const fkcols = args[0];
|
||||||
let fkname = table;
|
let fkname = table;
|
||||||
let matches2 = re4.exec(fkcols);
|
let matches2 = re4.exec(fkcols);
|
||||||
|
|
@ -566,7 +567,8 @@ ENDPOINT_UPDATE=true
|
||||||
}
|
}
|
||||||
|
|
||||||
return `CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`;
|
return `CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sql;
|
return sql;
|
||||||
|
|
@ -580,7 +582,7 @@ ENDPOINT_UPDATE=true
|
||||||
* ' CONSTRAINT [invalid2] FOREIGN KEY ([groupId1], [groupId2]) REFERENCES [Group] ([groupId1], [groupId2]) ON DELETE NO ACTION, ' +
|
* ' CONSTRAINT [invalid2] FOREIGN KEY ([groupId1], [groupId2]) REFERENCES [Group] ([groupId1], [groupId2]) ON DELETE NO ACTION, ' +
|
||||||
* ' CONSTRAINT [invalid3] FOREIGN KEY ([instanceId1]) REFERENCES [Instance] ([instanceId1]) ON DELETE NO ACTION'
|
* ' CONSTRAINT [invalid3] FOREIGN KEY ([instanceId1]) REFERENCES [Instance] ([instanceId1]) ON DELETE NO ACTION'
|
||||||
*/
|
*/
|
||||||
private changeColumnQueryOverride(tableName, attributes): string {
|
private changeColumnQueryOverride (tableName, attributes): string {
|
||||||
let sql: string = this.changeColumnQuery.apply(this.queryGenerator, [tableName, attributes]);
|
let sql: string = this.changeColumnQuery.apply(this.queryGenerator, [tableName, attributes]);
|
||||||
const re1 = /ALTER\s+TABLE\s+\[([^\]]*)\]/;
|
const re1 = /ALTER\s+TABLE\s+\[([^\]]*)\]/;
|
||||||
const matches = re1.exec(sql);
|
const matches = re1.exec(sql);
|
||||||
|
|
@ -588,7 +590,9 @@ ENDPOINT_UPDATE=true
|
||||||
const table = matches[1];
|
const table = matches[1];
|
||||||
const re2 = /(ADD\s+)?CONSTRAINT\s+\[([^\]]*)\]\s+FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g;
|
const re2 = /(ADD\s+)?CONSTRAINT\s+\[([^\]]*)\]\s+FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g;
|
||||||
const re3 = /\[([^\]]*)\]/g;
|
const re3 = /\[([^\]]*)\]/g;
|
||||||
sql = sql.replace(re2, (match: string, ...args: any[]): string => {
|
sql = sql.replace(
|
||||||
|
re2,
|
||||||
|
(match: string, ...args: any[]): string => {
|
||||||
const fkcols = args[2];
|
const fkcols = args[2];
|
||||||
let fkname = table;
|
let fkname = table;
|
||||||
let matches2 = re3.exec(fkcols);
|
let matches2 = re3.exec(fkcols);
|
||||||
|
|
@ -598,7 +602,8 @@ ENDPOINT_UPDATE=true
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${args[0] ? args[0] : ''}CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`;
|
return `${args[0] ? args[0] : ''}CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sql;
|
return sql;
|
||||||
|
|
@ -607,7 +612,7 @@ ENDPOINT_UPDATE=true
|
||||||
/**
|
/**
|
||||||
* Opens storage firewall used by the server when starting to get root bot instance.
|
* Opens storage firewall used by the server when starting to get root bot instance.
|
||||||
*/
|
*/
|
||||||
private async openStorageFrontier(installationDeployer: IGBInstallationDeployer) {
|
private async openStorageFrontier (installationDeployer: IGBInstallationDeployer) {
|
||||||
const group = GBConfigService.get('CLOUD_GROUP');
|
const group = GBConfigService.get('CLOUD_GROUP');
|
||||||
const serverName = GBConfigService.get('STORAGE_SERVER').split('.database.windows.net')[0];
|
const serverName = GBConfigService.get('STORAGE_SERVER').split('.database.windows.net')[0];
|
||||||
await installationDeployer.openStorageFirewall(group, serverName);
|
await installationDeployer.openStorageFirewall(group, serverName);
|
||||||
|
|
@ -620,7 +625,7 @@ ENDPOINT_UPDATE=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);
|
||||||
|
|
@ -648,5 +653,4 @@ ENDPOINT_UPDATE=true
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,34 +36,32 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Path = require('path');
|
import Path from 'path';
|
||||||
const urlJoin = require('url-join');
|
import express from 'express';
|
||||||
const Fs = require('fs');
|
import child_process from 'child_process';
|
||||||
const express = require('express');
|
import rimraf from 'rimraf';
|
||||||
const child_process = require('child_process');
|
import request from 'request-promise-native';
|
||||||
const rimraf = require('rimraf');
|
import vhost from 'vhost';
|
||||||
const request = require('request-promise-native');
|
import urlJoin from 'url-join';
|
||||||
const vhost = require('vhost')
|
import Fs from 'fs';
|
||||||
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBDeployer, IGBInstance, IGBPackage } from 'botlib';
|
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBDeployer, IGBInstance, IGBPackage } from 'botlib';
|
||||||
import { AzureSearch } from 'pragmatismo-io-framework';
|
import { AzureSearch } from 'pragmatismo-io-framework';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBVMService } from '../../basic.gblib/services/GBVMService';
|
import { GBVMService } from '../../basic.gblib/services/GBVMService.js';
|
||||||
import { GuaribasPackage } from '../models/GBModel';
|
import { GuaribasPackage } from '../models/GBModel.js';
|
||||||
import { GBAdminService } from './../../admin.gbapp/services/GBAdminService';
|
import { GBAdminService } from './../../admin.gbapp/services/GBAdminService.js';
|
||||||
import { AzureDeployerService } from './../../azuredeployer.gbapp/services/AzureDeployerService';
|
import { AzureDeployerService } from './../../azuredeployer.gbapp/services/AzureDeployerService.js';
|
||||||
import { KBService } from './../../kb.gbapp/services/KBService';
|
import { KBService } from './../../kb.gbapp/services/KBService.js';
|
||||||
import { GBConfigService } from './GBConfigService';
|
import { GBConfigService } from './GBConfigService.js';
|
||||||
import { GBImporter } from './GBImporterService';
|
import { GBImporter } from './GBImporterService.js';
|
||||||
import { TeamsService } from '../../teams.gblib/services/TeamsService';
|
import { TeamsService } from '../../teams.gblib/services/TeamsService.js';
|
||||||
const MicrosoftGraph = require('@microsoft/microsoft-graph-client');
|
import MicrosoftGraph from '@microsoft/microsoft-graph-client';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deployer service for bots, themes, ai and more.
|
* Deployer service for bots, themes, ai and more.
|
||||||
*/
|
*/
|
||||||
export class GBDeployer implements IGBDeployer {
|
export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Where should deployer look into for general packages.
|
* Where should deployer look into for general packages.
|
||||||
*/
|
*/
|
||||||
|
|
@ -87,7 +85,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Deployer needs core and importer to be created.
|
* Deployer needs core and importer to be created.
|
||||||
*/
|
*/
|
||||||
constructor(core: IGBCoreService, importer: GBImporter) {
|
constructor (core: IGBCoreService, importer: GBImporter) {
|
||||||
this.core = core;
|
this.core = core;
|
||||||
this.importer = importer;
|
this.importer = importer;
|
||||||
}
|
}
|
||||||
|
|
@ -96,14 +94,16 @@ export class GBDeployer implements IGBDeployer {
|
||||||
* Builds a connection string text to be used in direct
|
* Builds a connection string text to be used in direct
|
||||||
* use to database like the Indexer (Azure Search).
|
* use to database like the Indexer (Azure Search).
|
||||||
*/
|
*/
|
||||||
public static getConnectionStringFromInstance(instance: IGBInstance) {
|
public static getConnectionStringFromInstance (instance: IGBInstance) {
|
||||||
return `Server=tcp:${instance.storageServer},1433;Database=${instance.storageName};User ID=${instance.storageUsername};Password=${instance.storagePassword};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;`;
|
return `Server=tcp:${instance.storageServer},1433;Database=${instance.storageName};User ID=${
|
||||||
|
instance.storageUsername
|
||||||
|
};Password=${instance.storagePassword};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrives token and initialize drive client API.
|
* Retrives token and initialize drive client API.
|
||||||
*/
|
*/
|
||||||
public static async internalGetDriveClient(min: GBMinInstance) {
|
public static async internalGetDriveClient (min: GBMinInstance) {
|
||||||
let token = await min.adminService.acquireElevatedToken(min.instance.instanceId);
|
let token = await min.adminService.acquireElevatedToken(min.instance.instanceId);
|
||||||
let siteId = process.env.STORAGE_SITE_ID;
|
let siteId = process.env.STORAGE_SITE_ID;
|
||||||
let libraryId = process.env.STORAGE_LIBRARY;
|
let libraryId = process.env.STORAGE_LIBRARY;
|
||||||
|
|
@ -114,14 +114,13 @@ export class GBDeployer implements IGBDeployer {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const baseUrl = `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}`;
|
const baseUrl = `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}`;
|
||||||
return [baseUrl, client];
|
return { baseUrl, client };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs package deployment in all .gbai or default.
|
* Performs package deployment in all .gbai or default.
|
||||||
*/
|
*/
|
||||||
public async deployPackages(core: IGBCoreService, server: any, appPackages: IGBPackage[]) {
|
public async deployPackages (core: IGBCoreService, server: any, appPackages: IGBPackage[]) {
|
||||||
|
|
||||||
// Builds lists of paths to search for packages.
|
// Builds lists of paths to search for packages.
|
||||||
|
|
||||||
let paths = [urlJoin(process.env.PWD, GBDeployer.deployFolder), urlJoin(process.env.PWD, GBDeployer.workFolder)];
|
let paths = [urlJoin(process.env.PWD, GBDeployer.deployFolder), urlJoin(process.env.PWD, GBDeployer.workFolder)];
|
||||||
|
|
@ -133,8 +132,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
const gbappPackages: string[] = [];
|
const gbappPackages: string[] = [];
|
||||||
const generalPackages: string[] = [];
|
const generalPackages: string[] = [];
|
||||||
|
|
||||||
async function scanPackageDirectory(path) {
|
async function scanPackageDirectory (path) {
|
||||||
|
|
||||||
// Gets all directories.
|
// Gets all directories.
|
||||||
|
|
||||||
const isDirectory = source => Fs.lstatSync(source).isDirectory();
|
const isDirectory = source => Fs.lstatSync(source).isDirectory();
|
||||||
|
|
@ -144,7 +142,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
.filter(isDirectory);
|
.filter(isDirectory);
|
||||||
const dirs = getDirectories(path);
|
const dirs = getDirectories(path);
|
||||||
await CollectionUtil.asyncForEach(dirs, async element => {
|
await CollectionUtil.asyncForEach(dirs, async element => {
|
||||||
|
|
||||||
// For each folder, checks its extensions looking for valid packages.
|
// For each folder, checks its extensions looking for valid packages.
|
||||||
|
|
||||||
if (element === '.') {
|
if (element === '.') {
|
||||||
|
|
@ -154,8 +151,9 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
// Skips what does not need to be loaded.
|
// Skips what does not need to be loaded.
|
||||||
|
|
||||||
if (process.env.GBAPP_SKIP && (process.env.GBAPP_SKIP.toLowerCase().indexOf(name) !== -1
|
if (
|
||||||
|| process.env.GBAPP_SKIP === 'true')
|
process.env.GBAPP_SKIP &&
|
||||||
|
(process.env.GBAPP_SKIP.toLowerCase().indexOf(name) !== -1 || process.env.GBAPP_SKIP === 'true')
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -203,8 +201,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Deploys a new blank bot to the database, cognitive services and other services.
|
* Deploys a new blank bot to the database, cognitive services and other services.
|
||||||
*/
|
*/
|
||||||
public async deployBlankBot(botId: string, mobile: string, email: string) {
|
public async deployBlankBot (botId: string, mobile: string, email: string) {
|
||||||
|
|
||||||
// Creates a new row on the GuaribasInstance table.
|
// Creates a new row on the GuaribasInstance table.
|
||||||
|
|
||||||
const instance = await this.importer.createBotInstance(botId);
|
const instance = await this.importer.createBotInstance(botId);
|
||||||
|
|
@ -229,9 +226,9 @@ export class GBDeployer implements IGBDeployer {
|
||||||
instance.state = 'active';
|
instance.state = 'active';
|
||||||
instance.nlpScore = 0.8;
|
instance.nlpScore = 0.8;
|
||||||
instance.searchScore = 0.45;
|
instance.searchScore = 0.45;
|
||||||
instance.whatsappServiceKey = bootInstance.whatsappServiceKey;
|
instance.whatsappServiceKey = null;
|
||||||
instance.whatsappServiceNumber = bootInstance.whatsappServiceNumber;
|
instance.whatsappServiceNumber = null;
|
||||||
instance.whatsappServiceUrl = bootInstance.whatsappServiceUrl;
|
instance.whatsappServiceUrl = null;
|
||||||
instance.params = JSON.stringify({ 'Can Publish': mobile, 'Admin Notify E-mail': email });
|
instance.params = JSON.stringify({ 'Can Publish': mobile, 'Admin Notify E-mail': email });
|
||||||
|
|
||||||
// Saves bot information to the store.
|
// Saves bot information to the store.
|
||||||
|
|
@ -246,7 +243,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Verifies if bot exists on bot catalog.
|
* Verifies if bot exists on bot catalog.
|
||||||
*/
|
*/
|
||||||
public async botExists(botId: string): Promise<boolean> {
|
public async botExists (botId: string): Promise<boolean> {
|
||||||
const service = new AzureDeployerService(this);
|
const service = new AzureDeployerService(this);
|
||||||
|
|
||||||
return await service.botExists(botId);
|
return await service.botExists(botId);
|
||||||
|
|
@ -255,8 +252,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Performs all tasks of deploying a new bot on the cloud.
|
* Performs all tasks of deploying a new bot on the cloud.
|
||||||
*/
|
*/
|
||||||
public async deployBotFull(instance: IGBInstance, publicAddress: string): Promise<IGBInstance> {
|
public async deployBotFull (instance: IGBInstance, publicAddress: string): Promise<IGBInstance> {
|
||||||
|
|
||||||
// Reads base configuration from environent file.
|
// Reads base configuration from environent file.
|
||||||
|
|
||||||
const service = new AzureDeployerService(this);
|
const service = new AzureDeployerService(this);
|
||||||
|
|
@ -326,20 +322,23 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Performs the NLP publishing process on remote service.
|
* Performs the NLP publishing process on remote service.
|
||||||
*/
|
*/
|
||||||
public async publishNLP(instance: IGBInstance): Promise<void> {
|
public async publishNLP (instance: IGBInstance): Promise<void> {
|
||||||
const service = new AzureDeployerService(this);
|
const service = new AzureDeployerService(this);
|
||||||
const res = await service.publishNLP(instance.cloudLocation, instance.nlpAppId,
|
const res = await service.publishNLP(instance.cloudLocation, instance.nlpAppId, instance.nlpAuthoringKey);
|
||||||
instance.nlpAuthoringKey);
|
if (res.status !== 200 && res.status !== 201) {
|
||||||
if (res.status !== 200 && res.status !== 201) { throw res.bodyAsText; }
|
throw res.bodyAsText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trains NLP on the remote service.
|
* Trains NLP on the remote service.
|
||||||
*/
|
*/
|
||||||
public async trainNLP(instance: IGBInstance): Promise<void> {
|
public async trainNLP (instance: IGBInstance): Promise<void> {
|
||||||
const service = new AzureDeployerService(this);
|
const service = new AzureDeployerService(this);
|
||||||
const res = await service.trainNLP(instance.cloudLocation, instance.nlpAppId, instance.nlpAuthoringKey);
|
const res = await service.trainNLP(instance.cloudLocation, instance.nlpAppId, instance.nlpAuthoringKey);
|
||||||
if (res.status !== 200 && res.status !== 202) { throw res.bodyAsText; }
|
if (res.status !== 200 && res.status !== 202) {
|
||||||
|
throw res.bodyAsText;
|
||||||
|
}
|
||||||
const sleep = ms => {
|
const sleep = ms => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
setTimeout(resolve, ms);
|
setTimeout(resolve, ms);
|
||||||
|
|
@ -351,10 +350,16 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Return a zip file for importing bot in apps, currently MS Teams.
|
* Return a zip file for importing bot in apps, currently MS Teams.
|
||||||
*/
|
*/
|
||||||
public async getBotManifest(instance: IGBInstance): Promise<Buffer> {
|
public async getBotManifest (instance: IGBInstance): Promise<Buffer> {
|
||||||
const s = new TeamsService();
|
const s = new TeamsService();
|
||||||
const manifest = await s.getManifest(instance.marketplaceId, instance.title, instance.description,
|
const manifest = await s.getManifest(
|
||||||
GBAdminService.generateUuid(), instance.botId, "General Bots");
|
instance.marketplaceId,
|
||||||
|
instance.title,
|
||||||
|
instance.description,
|
||||||
|
GBAdminService.generateUuid(),
|
||||||
|
instance.botId,
|
||||||
|
'General Bots'
|
||||||
|
);
|
||||||
|
|
||||||
return await s.getAppFile(manifest);
|
return await s.getAppFile(manifest);
|
||||||
}
|
}
|
||||||
|
|
@ -362,7 +367,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Refreshes NLP entities on the remote service.
|
* Refreshes NLP entities on the remote service.
|
||||||
*/
|
*/
|
||||||
public async refreshNLPEntity(instance: IGBInstance, listName, listData): Promise<void> {
|
public async refreshNLPEntity (instance: IGBInstance, listName, listData): Promise<void> {
|
||||||
const service = new AzureDeployerService(this);
|
const service = new AzureDeployerService(this);
|
||||||
const res = await service.refreshEntityList(
|
const res = await service.refreshEntityList(
|
||||||
instance.cloudLocation,
|
instance.cloudLocation,
|
||||||
|
|
@ -371,13 +376,15 @@ export class GBDeployer implements IGBDeployer {
|
||||||
instance.nlpAuthoringKey,
|
instance.nlpAuthoringKey,
|
||||||
listData
|
listData
|
||||||
);
|
);
|
||||||
if (res.status !== 200) { throw res.bodyAsText; }
|
if (res.status !== 200) {
|
||||||
|
throw res.bodyAsText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deploys a bot to the storage from a .gbot folder.
|
* Deploys a bot to the storage from a .gbot folder.
|
||||||
*/
|
*/
|
||||||
public async deployBotFromLocalPath(localPath: string, publicAddress: string): Promise<void> {
|
public async deployBotFromLocalPath (localPath: string, publicAddress: string): Promise<void> {
|
||||||
const packageName = Path.basename(localPath);
|
const packageName = Path.basename(localPath);
|
||||||
const instance = await this.importer.importIfNotExistsBotPackage(undefined, packageName, localPath);
|
const instance = await this.importer.importIfNotExistsBotPackage(undefined, packageName, localPath);
|
||||||
await this.deployBotFull(instance, publicAddress);
|
await this.deployBotFull(instance, publicAddress);
|
||||||
|
|
@ -386,7 +393,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Loads all para from tabular file Config.xlsx.
|
* Loads all para from tabular file Config.xlsx.
|
||||||
*/
|
*/
|
||||||
public async loadParamsFromTabular(min: GBMinInstance): Promise<any> {
|
public async loadParamsFromTabular (min: GBMinInstance): Promise<any> {
|
||||||
const siteId = process.env.STORAGE_SITE_ID;
|
const siteId = process.env.STORAGE_SITE_ID;
|
||||||
const libraryId = process.env.STORAGE_LIBRARY;
|
const libraryId = process.env.STORAGE_LIBRARY;
|
||||||
|
|
||||||
|
|
@ -408,9 +415,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
let url = `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:${path}:/children`;
|
let url = `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:${path}:/children`;
|
||||||
|
|
||||||
GBLog.info(`Loading .gbot from Excel: ${url}`);
|
GBLog.info(`Loading .gbot from Excel: ${url}`);
|
||||||
const res = await client
|
const res = await client.api(url).get();
|
||||||
.api(url)
|
|
||||||
.get();
|
|
||||||
|
|
||||||
// Finds Config.xlsx.
|
// Finds Config.xlsx.
|
||||||
|
|
||||||
|
|
@ -428,10 +433,13 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
const results = await client
|
const results = await client
|
||||||
.api(
|
.api(
|
||||||
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/items/${document[0].id}/workbook/worksheets('General')/range(address='A7:B100')`
|
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/items/${
|
||||||
|
document[0].id
|
||||||
|
}/workbook/worksheets('General')/range(address='A7:B100')`
|
||||||
)
|
)
|
||||||
.get();
|
.get();
|
||||||
let index = 0, obj = {};
|
let index = 0,
|
||||||
|
obj = {};
|
||||||
for (; index < results.text.length; index++) {
|
for (; index < results.text.length; index++) {
|
||||||
if (results.text[index][0] === '') {
|
if (results.text[index][0] === '') {
|
||||||
return obj;
|
return obj;
|
||||||
|
|
@ -445,14 +453,17 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Loads all para from tabular file Config.xlsx.
|
* Loads all para from tabular file Config.xlsx.
|
||||||
*/
|
*/
|
||||||
public async downloadFolder(min: GBMinInstance, localPath: string, remotePath: string,
|
public async downloadFolder (
|
||||||
baseUrl: string = null, client = null): Promise<any> {
|
min: GBMinInstance,
|
||||||
|
localPath: string,
|
||||||
|
remotePath: string,
|
||||||
|
baseUrl: string = null,
|
||||||
|
client = null
|
||||||
|
): Promise<any> {
|
||||||
GBLog.info(`downloadFolder: localPath=${localPath}, remotePath=${remotePath}, baseUrl=${baseUrl}`);
|
GBLog.info(`downloadFolder: localPath=${localPath}, remotePath=${remotePath}, baseUrl=${baseUrl}`);
|
||||||
|
|
||||||
if (!baseUrl) {
|
if (!baseUrl) {
|
||||||
[baseUrl, client] = await GBDeployer.internalGetDriveClient(min);
|
client = await GBDeployer.internalGetDriveClient(min);
|
||||||
|
|
||||||
remotePath = remotePath.replace(/\\/gi, '/');
|
remotePath = remotePath.replace(/\\/gi, '/');
|
||||||
const parts = remotePath.split('/');
|
const parts = remotePath.split('/');
|
||||||
|
|
@ -479,9 +490,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
GBLog.info(`Download URL: ${url}`);
|
GBLog.info(`Download URL: ${url}`);
|
||||||
|
|
||||||
const res = await client
|
const res = await client.client.api(url).get();
|
||||||
.api(url)
|
|
||||||
.get();
|
|
||||||
const documents = res.value;
|
const documents = res.value;
|
||||||
if (documents === undefined || documents.length === 0) {
|
if (documents === undefined || documents.length === 0) {
|
||||||
GBLog.info(`${remotePath} is an empty folder.`);
|
GBLog.info(`${remotePath} is an empty folder.`);
|
||||||
|
|
@ -491,7 +500,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
// Download files or navigate to directory to recurse.
|
// Download files or navigate to directory to recurse.
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(documents, async item => {
|
await CollectionUtil.asyncForEach(documents, async item => {
|
||||||
|
|
||||||
const itemPath = Path.join(localPath, remotePath, item.name);
|
const itemPath = Path.join(localPath, remotePath, item.name);
|
||||||
|
|
||||||
if (item.folder) {
|
if (item.folder) {
|
||||||
|
|
@ -516,10 +524,8 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
const response = await request({ uri: url, encoding: null });
|
const response = await request({ uri: url, encoding: null });
|
||||||
Fs.writeFileSync(itemPath, response, { encoding: null });
|
Fs.writeFileSync(itemPath, response, { encoding: null });
|
||||||
Fs.utimesSync(itemPath,
|
Fs.utimesSync(itemPath, new Date(), new Date(item.lastModifiedDateTime));
|
||||||
new Date(), new Date(item.lastModifiedDateTime));
|
} else {
|
||||||
}
|
|
||||||
else {
|
|
||||||
GBLog.info(`Local is up to date: ${itemPath}...`);
|
GBLog.info(`Local is up to date: ${itemPath}...`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -529,8 +535,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* UndDeploys a bot to the storage.
|
* UndDeploys a bot to the storage.
|
||||||
*/
|
*/
|
||||||
public async undeployBot(botId: string, packageName: string): Promise<void> {
|
public async undeployBot (botId: string, packageName: string): Promise<void> {
|
||||||
|
|
||||||
// Deletes Bot registration on cloud.
|
// Deletes Bot registration on cloud.
|
||||||
|
|
||||||
const service = new AzureDeployerService(this);
|
const service = new AzureDeployerService(this);
|
||||||
|
|
@ -551,7 +556,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Deploys a new package to the database storage (just a group).
|
* Deploys a new package to the database storage (just a group).
|
||||||
*/
|
*/
|
||||||
public async deployPackageToStorage(instanceId: number, packageName: string): Promise<GuaribasPackage> {
|
public async deployPackageToStorage (instanceId: number, packageName: string): Promise<GuaribasPackage> {
|
||||||
return await GuaribasPackage.create(<GuaribasPackage>{
|
return await GuaribasPackage.create(<GuaribasPackage>{
|
||||||
packageName: packageName,
|
packageName: packageName,
|
||||||
instanceId: instanceId
|
instanceId: instanceId
|
||||||
|
|
@ -561,8 +566,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Deploys a folder into the bot storage.
|
* Deploys a folder into the bot storage.
|
||||||
*/
|
*/
|
||||||
public async deployPackage(min: GBMinInstance, localPath: string) {
|
public async deployPackage (min: GBMinInstance, localPath: string) {
|
||||||
|
|
||||||
const packageType = Path.extname(localPath);
|
const packageType = Path.extname(localPath);
|
||||||
let handled = false;
|
let handled = false;
|
||||||
let pck = null;
|
let pck = null;
|
||||||
|
|
@ -572,7 +576,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
const _this = this;
|
const _this = this;
|
||||||
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
|
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// If it will be handled, create a temporary service layer to be
|
// If it will be handled, create a temporary service layer to be
|
||||||
// called by .gbapp and manage the associated package row.
|
// called by .gbapp and manage the associated package row.
|
||||||
|
|
||||||
|
|
@ -605,7 +608,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
switch (packageType) {
|
switch (packageType) {
|
||||||
case '.gbot':
|
case '.gbot':
|
||||||
|
|
||||||
// Extracts configuration information from .gbot files.
|
// Extracts configuration information from .gbot files.
|
||||||
|
|
||||||
if (process.env.ENABLE_PARAMS_ONLINE === 'false') {
|
if (process.env.ENABLE_PARAMS_ONLINE === 'false') {
|
||||||
|
|
@ -624,7 +626,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '.gbkb':
|
case '.gbkb':
|
||||||
|
|
||||||
// Deploys .gbkb into the storage.
|
// Deploys .gbkb into the storage.
|
||||||
|
|
||||||
const service = new KBService(this.core.sequelize);
|
const service = new KBService(this.core.sequelize);
|
||||||
|
|
@ -632,7 +633,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '.gbdialog':
|
case '.gbdialog':
|
||||||
|
|
||||||
// Compiles files from .gbdialog into work folder and deploys
|
// Compiles files from .gbdialog into work folder and deploys
|
||||||
// it to the VM.
|
// it to the VM.
|
||||||
|
|
||||||
|
|
@ -642,7 +642,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '.gbtheme':
|
case '.gbtheme':
|
||||||
|
|
||||||
// Updates server listeners to serve theme files in .gbtheme.
|
// Updates server listeners to serve theme files in .gbtheme.
|
||||||
|
|
||||||
const packageName = Path.basename(localPath);
|
const packageName = Path.basename(localPath);
|
||||||
|
|
@ -652,21 +651,18 @@ export class GBDeployer implements IGBDeployer {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '.gbapp':
|
case '.gbapp':
|
||||||
|
|
||||||
// Dynamically compiles and loads .gbapp packages (Node.js packages).
|
// Dynamically compiles and loads .gbapp packages (Node.js packages).
|
||||||
|
|
||||||
await this.callGBAppCompiler(localPath, this.core);
|
await this.callGBAppCompiler(localPath, this.core);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '.gblib':
|
case '.gblib':
|
||||||
|
|
||||||
// Dynamically compiles and loads .gblib packages (Node.js packages).
|
// Dynamically compiles and loads .gblib packages (Node.js packages).
|
||||||
|
|
||||||
await this.callGBAppCompiler(localPath, this.core);
|
await this.callGBAppCompiler(localPath, this.core);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
const err = GBError.create(`Unhandled package type: ${packageType}.`);
|
const err = GBError.create(`Unhandled package type: ${packageType}.`);
|
||||||
Promise.reject(err);
|
Promise.reject(err);
|
||||||
break;
|
break;
|
||||||
|
|
@ -676,8 +672,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Removes the package from the storage and local work folders.
|
* Removes the package from the storage and local work folders.
|
||||||
*/
|
*/
|
||||||
public async undeployPackageFromLocalPath(instance: IGBInstance, localPath: string) {
|
public async undeployPackageFromLocalPath (instance: IGBInstance, localPath: string) {
|
||||||
|
|
||||||
// Gets information about the package.
|
// Gets information about the package.
|
||||||
|
|
||||||
const packageType = Path.extname(localPath);
|
const packageType = Path.extname(localPath);
|
||||||
|
|
@ -687,7 +682,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
// Removes objects from storage, cloud resources and local files if any.
|
// Removes objects from storage, cloud resources and local files if any.
|
||||||
|
|
||||||
switch (packageType) {
|
switch (packageType) {
|
||||||
|
|
||||||
case '.gbot':
|
case '.gbot':
|
||||||
const packageObject = JSON.parse(Fs.readFileSync(urlJoin(localPath, 'package.json'), 'utf8'));
|
const packageObject = JSON.parse(Fs.readFileSync(urlJoin(localPath, 'package.json'), 'utf8'));
|
||||||
await this.undeployBot(packageObject.botId, packageName);
|
await this.undeployBot(packageObject.botId, packageName);
|
||||||
|
|
@ -726,8 +720,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
* Performs automation of the Indexer (Azure Search) and rebuild
|
* Performs automation of the Indexer (Azure Search) and rebuild
|
||||||
* its index based on .gbkb structure.
|
* its index based on .gbkb structure.
|
||||||
*/
|
*/
|
||||||
public async rebuildIndex(instance: IGBInstance, searchSchema: any) {
|
public async rebuildIndex (instance: IGBInstance, searchSchema: any) {
|
||||||
|
|
||||||
// Prepares search.
|
// Prepares search.
|
||||||
|
|
||||||
const search = new AzureSearch(
|
const search = new AzureSearch(
|
||||||
|
|
@ -744,11 +737,9 @@ export class GBDeployer implements IGBDeployer {
|
||||||
try {
|
try {
|
||||||
await search.deleteDataSource(dsName);
|
await search.deleteDataSource(dsName);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
||||||
// If it is a 404 there is nothing to delete as it is the first creation.
|
// If it is a 404 there is nothing to delete as it is the first creation.
|
||||||
|
|
||||||
if (err.code !== 404) {
|
if (err.code !== 404) {
|
||||||
|
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -758,10 +749,9 @@ export class GBDeployer implements IGBDeployer {
|
||||||
try {
|
try {
|
||||||
await search.deleteIndex();
|
await search.deleteIndex();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
||||||
// If it is a 404 there is nothing to delete as it is the first creation.
|
// If it is a 404 there is nothing to delete as it is the first creation.
|
||||||
|
|
||||||
if (err.code !== 404 && err.code !== "OperationNotAllowed") {
|
if (err.code !== 404 && err.code !== 'OperationNotAllowed') {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -780,7 +770,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Finds a storage package by using package name.
|
* Finds a storage package by using package name.
|
||||||
*/
|
*/
|
||||||
public async getStoragePackageByName(instanceId: number, packageName: string): Promise<GuaribasPackage> {
|
public async getStoragePackageByName (instanceId: number, packageName: string): Promise<GuaribasPackage> {
|
||||||
const where = { packageName: packageName, instanceId: instanceId };
|
const where = { packageName: packageName, instanceId: instanceId };
|
||||||
|
|
||||||
return await GuaribasPackage.findOne({
|
return await GuaribasPackage.findOne({
|
||||||
|
|
@ -792,8 +782,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
* Prepares the React application inside default.gbui folder and
|
* Prepares the React application inside default.gbui folder and
|
||||||
* makes this web application available as default web front-end.
|
* makes this web application available as default web front-end.
|
||||||
*/
|
*/
|
||||||
public setupDefaultGBUI() {
|
public setupDefaultGBUI () {
|
||||||
|
|
||||||
// Setups paths.
|
// Setups paths.
|
||||||
|
|
||||||
const root = 'packages/default.gbui';
|
const root = 'packages/default.gbui';
|
||||||
|
|
@ -802,7 +791,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
// Checks if .gbapp compiliation is enabled.
|
// Checks if .gbapp compiliation is enabled.
|
||||||
|
|
||||||
if (!Fs.existsSync(`${root}/build`) && process.env.DISABLE_WEB !== 'true') {
|
if (!Fs.existsSync(`${root}/build`) && process.env.DISABLE_WEB !== 'true') {
|
||||||
|
|
||||||
// Write a .env required to fix some bungs in create-react-app tool.
|
// Write a .env required to fix some bungs in create-react-app tool.
|
||||||
|
|
||||||
Fs.writeFileSync(`${root}/.env`, 'SKIP_PREFLIGHT_CHECK=true');
|
Fs.writeFileSync(`${root}/.env`, 'SKIP_PREFLIGHT_CHECK=true');
|
||||||
|
|
@ -821,8 +809,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Servers bot storage assets to be used by web, WhatsApp and other channels.
|
* Servers bot storage assets to be used by web, WhatsApp and other channels.
|
||||||
*/
|
*/
|
||||||
public static mountGBKBAssets(packageName: any, botId: string, filename: string) {
|
public static mountGBKBAssets (packageName: any, botId: string, filename: string) {
|
||||||
|
|
||||||
// Servers menu assets.
|
// Servers menu assets.
|
||||||
|
|
||||||
GBServer.globals.server.use(
|
GBServer.globals.server.use(
|
||||||
|
|
@ -833,20 +820,27 @@ export class GBDeployer implements IGBDeployer {
|
||||||
// Servers all other assets in .gbkb folders.
|
// Servers all other assets in .gbkb folders.
|
||||||
|
|
||||||
const gbaiName = `${botId}.gbai`;
|
const gbaiName = `${botId}.gbai`;
|
||||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/assets`,
|
GBServer.globals.server.use(
|
||||||
express.static(urlJoin('work', gbaiName, filename, 'assets')));
|
`/kb/${gbaiName}/${packageName}/assets`,
|
||||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/images`,
|
express.static(urlJoin('work', gbaiName, filename, 'assets'))
|
||||||
express.static(urlJoin('work', gbaiName, filename, 'images')));
|
);
|
||||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/audios`,
|
GBServer.globals.server.use(
|
||||||
express.static(urlJoin('work', gbaiName, filename, 'audios')));
|
`/kb/${gbaiName}/${packageName}/images`,
|
||||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/videos`,
|
express.static(urlJoin('work', gbaiName, filename, 'images'))
|
||||||
express.static(urlJoin('work', gbaiName, filename, 'videos')));
|
);
|
||||||
GBServer.globals.server.use(`/${botId}/cache`,
|
GBServer.globals.server.use(
|
||||||
express.static(urlJoin('work', gbaiName, 'cache')));
|
`/kb/${gbaiName}/${packageName}/audios`,
|
||||||
GBServer.globals.server.use(`/${gbaiName}/${botId}.gbdata/public`,
|
express.static(urlJoin('work', gbaiName, filename, 'audios'))
|
||||||
express.static(urlJoin('work', gbaiName, `${botId}.gbdata`, 'public')));
|
);
|
||||||
|
GBServer.globals.server.use(
|
||||||
|
`/kb/${gbaiName}/${packageName}/videos`,
|
||||||
|
express.static(urlJoin('work', gbaiName, filename, 'videos'))
|
||||||
|
);
|
||||||
|
GBServer.globals.server.use(`/${botId}/cache`, express.static(urlJoin('work', gbaiName, 'cache')));
|
||||||
|
GBServer.globals.server.use(
|
||||||
|
`/${gbaiName}/${botId}.gbdata/public`,
|
||||||
|
express.static(urlJoin('work', gbaiName, `${botId}.gbdata`, 'public'))
|
||||||
|
);
|
||||||
|
|
||||||
GBLog.verbose(`KB (.gbkb) assets accessible at: /kb/${botId}.gbai/${packageName}.`);
|
GBLog.verbose(`KB (.gbkb) assets accessible at: /kb/${botId}.gbai/${packageName}.`);
|
||||||
}
|
}
|
||||||
|
|
@ -854,13 +848,12 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Invokes Type Script compiler for a given .gbapp package (Node.js based).
|
* Invokes Type Script compiler for a given .gbapp package (Node.js based).
|
||||||
*/
|
*/
|
||||||
public async callGBAppCompiler(
|
public async callGBAppCompiler (
|
||||||
gbappPath: string,
|
gbappPath: string,
|
||||||
core: IGBCoreService,
|
core: IGBCoreService,
|
||||||
appPackages: any[] = undefined,
|
appPackages: any[] = undefined,
|
||||||
appPackagesProcessed: number = 0
|
appPackagesProcessed: number = 0
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// Runs `npm install` for the package.
|
// Runs `npm install` for the package.
|
||||||
|
|
||||||
GBLog.info(`Deploying General Bots Application (.gbapp) or Library (.gblib): ${Path.basename(gbappPath)}...`);
|
GBLog.info(`Deploying General Bots Application (.gbapp) or Library (.gblib): ${Path.basename(gbappPath)}...`);
|
||||||
|
|
@ -874,7 +867,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
folder = Path.join(gbappPath, 'dist');
|
folder = Path.join(gbappPath, 'dist');
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Runs TSC in .gbapp folder.
|
// Runs TSC in .gbapp folder.
|
||||||
|
|
||||||
if (process.env.GBAPP_DISABLE_COMPILE !== 'true') {
|
if (process.env.GBAPP_DISABLE_COMPILE !== 'true') {
|
||||||
|
|
@ -896,7 +888,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
}
|
}
|
||||||
GBLog.info(`.gbapp or .gblib deployed: ${gbappPath}.`);
|
GBLog.info(`.gbapp or .gblib deployed: ${gbappPath}.`);
|
||||||
appPackagesProcessed++;
|
appPackagesProcessed++;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
GBLog.error(`Error compiling package, message: ${error.message}\n${error.stack}`);
|
GBLog.error(`Error compiling package, message: ${error.message}\n${error.stack}`);
|
||||||
if (error.stdout) {
|
if (error.stdout) {
|
||||||
|
|
@ -911,7 +902,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Determines if a given package is of system kind.
|
* Determines if a given package is of system kind.
|
||||||
*/
|
*/
|
||||||
private isSystemPackage(name: string): Boolean {
|
private isSystemPackage (name: string): Boolean {
|
||||||
const names = [
|
const names = [
|
||||||
'analytics.gblib',
|
'analytics.gblib',
|
||||||
'console.gblib',
|
'console.gblib',
|
||||||
|
|
@ -935,8 +926,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Performs the process of compiling all .gbapp folders.
|
* Performs the process of compiling all .gbapp folders.
|
||||||
*/
|
*/
|
||||||
private async deployAppPackages(gbappPackages: string[], core: any, appPackages: any[]) {
|
private async deployAppPackages (gbappPackages: string[], core: any, appPackages: any[]) {
|
||||||
|
|
||||||
// Loops through all ready to load .gbapp packages.
|
// Loops through all ready to load .gbapp packages.
|
||||||
|
|
||||||
let appPackagesProcessed = 0;
|
let appPackagesProcessed = 0;
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,11 @@
|
||||||
|
|
||||||
import { GBMinInstance, IGBCoreService, IGBInstance } from 'botlib';
|
import { GBMinInstance, IGBCoreService, IGBInstance } from 'botlib';
|
||||||
import { CreateOptions } from 'sequelize/types';
|
import { CreateOptions } from 'sequelize/types';
|
||||||
const fs = require('fs');
|
import Fs from 'fs';
|
||||||
const urlJoin = require('url-join');
|
import urlJoin from 'url-join';
|
||||||
import { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GuaribasInstance } from '../models/GBModel';
|
import { GuaribasInstance } from '../models/GBModel.js';
|
||||||
import { GBConfigService } from './GBConfigService';
|
import { GBConfigService } from './GBConfigService.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the importing of packages.
|
* Handles the importing of packages.
|
||||||
|
|
@ -50,13 +50,17 @@ import { GBConfigService } from './GBConfigService';
|
||||||
export class GBImporter {
|
export class GBImporter {
|
||||||
public core: IGBCoreService;
|
public core: IGBCoreService;
|
||||||
|
|
||||||
constructor(core: IGBCoreService) {
|
constructor (core: IGBCoreService) {
|
||||||
this.core = core;
|
this.core = core;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async importIfNotExistsBotPackage(botId: string,
|
public async importIfNotExistsBotPackage (
|
||||||
packageName: string, localPath: string, additionalInstance: IGBInstance = null) {
|
botId: string,
|
||||||
const settingsJson = JSON.parse(fs.readFileSync(urlJoin(localPath, 'settings.json'), 'utf8'));
|
packageName: string,
|
||||||
|
localPath: string,
|
||||||
|
additionalInstance: IGBInstance = null
|
||||||
|
) {
|
||||||
|
const settingsJson = JSON.parse(Fs.readFileSync(urlJoin(localPath, 'settings.json'), 'utf8'));
|
||||||
if (botId === undefined) {
|
if (botId === undefined) {
|
||||||
botId = settingsJson.botId;
|
botId = settingsJson.botId;
|
||||||
}
|
}
|
||||||
|
|
@ -94,21 +98,21 @@ export class GBImporter {
|
||||||
return await this.createOrUpdateInstanceInternal(instance, botId, localPath, settingsJson);
|
return await this.createOrUpdateInstanceInternal(instance, botId, localPath, settingsJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createBotInstance(botId: string) {
|
public async createBotInstance (botId: string) {
|
||||||
const fullSettingsJson=<GuaribasInstance> { ...GBServer.globals.bootInstance };
|
const fullSettingsJson = <GuaribasInstance>{ ...GBServer.globals.bootInstance };
|
||||||
fullSettingsJson['botId'] = botId;
|
fullSettingsJson['botId'] = botId;
|
||||||
|
|
||||||
return await GuaribasInstance.create(fullSettingsJson);
|
return await GuaribasInstance.create(fullSettingsJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createOrUpdateInstanceInternal(
|
private async createOrUpdateInstanceInternal (
|
||||||
instance: IGBInstance,
|
instance: IGBInstance,
|
||||||
botId: string,
|
botId: string,
|
||||||
localPath: string,
|
localPath: string,
|
||||||
settingsJson: any
|
settingsJson: any
|
||||||
) {
|
) {
|
||||||
const packageJson = JSON.parse(fs.readFileSync(urlJoin(localPath, 'package.json'), 'utf8'));
|
const packageJson = JSON.parse(Fs.readFileSync(urlJoin(localPath, 'package.json'), 'utf8'));
|
||||||
const servicesJson = JSON.parse(fs.readFileSync(urlJoin(localPath, 'services.json'), 'utf8'));
|
const servicesJson = JSON.parse(Fs.readFileSync(urlJoin(localPath, 'services.json'), 'utf8'));
|
||||||
|
|
||||||
const fullSettingsJson = { ...GBServer.globals.bootInstance, ...packageJson, ...settingsJson, ...servicesJson };
|
const fullSettingsJson = { ...GBServer.globals.bootInstance, ...packageJson, ...settingsJson, ...servicesJson };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,19 +35,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
const cliProgress = require('cli-progress');
|
import cliProgress from 'cli-progress';
|
||||||
const { DialogSet, TextPrompt } = require('botbuilder-dialogs');
|
import { DialogSet, TextPrompt } from 'botbuilder-dialogs';
|
||||||
const express = require('express');
|
import express from 'express';
|
||||||
const Swagger = require('swagger-client');
|
import Swagger from 'swagger-client';
|
||||||
const Fs = require('fs');
|
import request from 'request-promise-native';
|
||||||
const request = require('request-promise-native');
|
import removeRoute from 'express-remove-route';
|
||||||
const removeRoute = require('express-remove-route');
|
import AuthenticationContext from '@azure/msal-node';
|
||||||
const AuthenticationContext = require('adal-node').AuthenticationContext;
|
import wash from 'washyourmouthoutwithsoap';
|
||||||
const wash = require('washyourmouthoutwithsoap');
|
import { FacebookAdapter } from 'botbuilder-adapter-facebook';
|
||||||
const { FacebookAdapter } = require('botbuilder-adapter-facebook');
|
import path from 'path';
|
||||||
const path = require('path');
|
import mkdirp from 'mkdirp';
|
||||||
const { NerManager } = require('node-nlp');
|
import Fs from 'fs';
|
||||||
const mkdirp = require('mkdirp');
|
|
||||||
import {
|
import {
|
||||||
AutoSaveStateMiddleware,
|
AutoSaveStateMiddleware,
|
||||||
BotFrameworkAdapter,
|
BotFrameworkAdapter,
|
||||||
|
|
@ -69,31 +68,31 @@ import {
|
||||||
} from 'botlib';
|
} from 'botlib';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { MicrosoftAppCredentials } from 'botframework-connector';
|
import { MicrosoftAppCredentials } from 'botframework-connector';
|
||||||
import { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
||||||
import { GuaribasConversationMessage } from '../../analytics.gblib/models';
|
import { GuaribasConversationMessage } from '../../analytics.gblib/models/index.js';
|
||||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
|
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService.js';
|
||||||
import { GBVMService } from '../../basic.gblib/services/GBVMService';
|
import { GBVMService } from '../../basic.gblib/services/GBVMService.js';
|
||||||
import { AskDialogArgs } from '../../kb.gbapp/dialogs/AskDialog';
|
import { AskDialogArgs } from '../../kb.gbapp/dialogs/AskDialog.js';
|
||||||
import { KBService } from '../../kb.gbapp/services/KBService';
|
import { KBService } from '../../kb.gbapp/services/KBService.js';
|
||||||
import { SecService } from '../../security.gbapp/services/SecService';
|
import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||||
import { WhatsappDirectLine } from '../../whatsapp.gblib/services/WhatsappDirectLine';
|
import { WhatsappDirectLine } from '../../whatsapp.gblib/services/WhatsappDirectLine.js';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings.js';
|
||||||
import { GBConfigService } from './GBConfigService';
|
import { GBConfigService } from './GBConfigService.js';
|
||||||
import { GBConversationalService } from './GBConversationalService';
|
import { GBConversationalService } from './GBConversationalService.js';
|
||||||
import { GBDeployer } from './GBDeployer';
|
import { GBDeployer } from './GBDeployer.js';
|
||||||
import urlJoin = require('url-join');
|
import urlJoin from 'url-join';
|
||||||
import fs = require('fs');
|
import fs from 'fs';
|
||||||
import { GoogleChatDirectLine } from '../../google-chat.gblib/services/GoogleChatDirectLine';
|
import { GoogleChatDirectLine } from '../../google-chat.gblib/services/GoogleChatDirectLine.js';
|
||||||
import { ScheduleServices } from '../../basic.gblib/services/ScheduleServices';
|
import { ScheduleServices } from '../../basic.gblib/services/ScheduleServices.js';
|
||||||
import { SystemKeywords } from '../../basic.gblib/services/SystemKeywords';
|
import { SystemKeywords } from '../../basic.gblib/services/SystemKeywords.js';
|
||||||
import { ssrForBots } from './GBSSR';
|
import { ssrForBots } from './GBSSR';
|
||||||
|
import * as nlp from 'node-nlp';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimal service layer for a bot and encapsulation of BOT Framework calls.
|
* Minimal service layer for a bot and encapsulation of BOT Framework calls.
|
||||||
*/
|
*/
|
||||||
export class GBMinService {
|
export class GBMinService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default General Bots User Interface package.
|
* Default General Bots User Interface package.
|
||||||
*/
|
*/
|
||||||
|
|
@ -119,13 +118,12 @@ export class GBMinService {
|
||||||
*/
|
*/
|
||||||
public deployer: GBDeployer;
|
public deployer: GBDeployer;
|
||||||
|
|
||||||
|
|
||||||
bar1;
|
bar1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static initialization of minimal instance.
|
* Static initialization of minimal instance.
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor (
|
||||||
core: IGBCoreService,
|
core: IGBCoreService,
|
||||||
conversationalService: IGBConversationalService,
|
conversationalService: IGBConversationalService,
|
||||||
adminService: IGBAdminService,
|
adminService: IGBAdminService,
|
||||||
|
|
@ -140,17 +138,15 @@ export class GBMinService {
|
||||||
/**
|
/**
|
||||||
* Constructs a new minimal instance for each bot.
|
* Constructs a new minimal instance for each bot.
|
||||||
*/
|
*/
|
||||||
public async buildMin(instances: IGBInstance[]) {
|
public async buildMin (instances: IGBInstance[]) {
|
||||||
|
|
||||||
// Servers default UI on root address '/' if web enabled.
|
// Servers default UI on root address '/' if web enabled.
|
||||||
|
|
||||||
if (process.env.DISABLE_WEB !== 'true') {
|
if (process.env.DISABLE_WEB !== 'true') {
|
||||||
|
|
||||||
// SSR processing.
|
// SSR processing.
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
prerender: [],
|
prerender: [],
|
||||||
exclude: ["/api/", "/instances/", "/webhooks/"],
|
exclude: ['/api/', '/instances/', '/webhooks/'],
|
||||||
useCache: true,
|
useCache: true,
|
||||||
cacheRefreshRate: 86400
|
cacheRefreshRate: 86400
|
||||||
};
|
};
|
||||||
|
|
@ -164,29 +160,31 @@ export class GBMinService {
|
||||||
|
|
||||||
GBServer.globals.server.use('/', express.static(url));
|
GBServer.globals.server.use('/', express.static(url));
|
||||||
|
|
||||||
|
|
||||||
// Servers the bot information object via HTTP so clients can get
|
// Servers the bot information object via HTTP so clients can get
|
||||||
// instance information stored on server.
|
// instance information stored on server.
|
||||||
|
|
||||||
|
|
||||||
GBServer.globals.server.get('/instances/:botId', this.handleGetInstanceForClient.bind(this));
|
GBServer.globals.server.get('/instances/:botId', this.handleGetInstanceForClient.bind(this));
|
||||||
}
|
}
|
||||||
// Calls mountBot event to all bots.
|
// Calls mountBot event to all bots.
|
||||||
let i = 1;
|
let i = 1;
|
||||||
|
|
||||||
if (instances.length > 1) {
|
if (instances.length > 1) {
|
||||||
this.bar1 = new cliProgress.SingleBar({
|
this.bar1 = new cliProgress.SingleBar(
|
||||||
format: '[{bar}] ({value}/{total}) Loading {botId} ...', barsize: 40,
|
{
|
||||||
|
format: '[{bar}] ({value}/{total}) Loading {botId} ...',
|
||||||
|
barsize: 40,
|
||||||
forceRedraw: true
|
forceRedraw: true
|
||||||
}, cliProgress.Presets.rect);
|
},
|
||||||
this.bar1.start(instances.length, i, { botId: "Boot" });
|
cliProgress.Presets.rect
|
||||||
|
);
|
||||||
|
this.bar1.start(instances.length, i, { botId: 'Boot' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const throttledPromiseAll = async (promises) => {
|
const throttledPromiseAll = async promises => {
|
||||||
const MAX_IN_PROCESS = 20;
|
const MAX_IN_PROCESS = 20;
|
||||||
const results = new Array(promises.length);
|
const results = new Array(promises.length);
|
||||||
|
|
||||||
async function doBlock(startIndex) {
|
async function doBlock (startIndex) {
|
||||||
// Shallow-copy a block of promises to work on
|
// Shallow-copy a block of promises to work on
|
||||||
const currBlock = promises.slice(startIndex, startIndex + MAX_IN_PROCESS);
|
const currBlock = promises.slice(startIndex, startIndex + MAX_IN_PROCESS);
|
||||||
// Await the completion. If any fail, it will throw and that's good.
|
// Await the completion. If any fail, it will throw and that's good.
|
||||||
|
|
@ -203,39 +201,39 @@ export class GBMinService {
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
await throttledPromiseAll(instances.map((async instance => {
|
await throttledPromiseAll(
|
||||||
|
instances.map(
|
||||||
|
(async instance => {
|
||||||
try {
|
try {
|
||||||
await this['mountBot'](instance);
|
await this['mountBot'](instance);
|
||||||
|
|
||||||
if (this.bar1) {
|
if (this.bar1) {
|
||||||
this.bar1.update(i++, { botId: instance.botId });
|
this.bar1.update(i++, { botId: instance.botId });
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
GBLog.error(`Error mounting bot ${instance.botId}: ${error.message}\n${error.stack}`);
|
GBLog.error(`Error mounting bot ${instance.botId}: ${error.message}\n${error.stack}`);
|
||||||
}
|
}
|
||||||
|
}).bind(this)
|
||||||
}).bind(this)));
|
)
|
||||||
|
);
|
||||||
if (this.bar1) {
|
if (this.bar1) {
|
||||||
this.bar1.stop();
|
this.bar1.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads schedules.
|
// // Loads schedules.
|
||||||
GBLog.info(`Preparing SET SCHEDULE dialog calls...`);
|
// GBLog.info(`Preparing SET SCHEDULE dialog calls...`);
|
||||||
|
|
||||||
const service = new ScheduleServices();
|
// const service = new ScheduleServices();
|
||||||
await service.scheduleAll();
|
// await service.scheduleAll();
|
||||||
|
|
||||||
GBLog.info(`All Bot instances loaded.`);
|
GBLog.info(`All Bot instances loaded.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes bot endpoint from web listeners and remove bot instance
|
* Removes bot endpoint from web listeners and remove bot instance
|
||||||
* from list of global server bot instances.
|
* from list of global server bot instances.
|
||||||
*/
|
*/
|
||||||
public async unmountBot(botId: string) {
|
public async unmountBot (botId: string) {
|
||||||
const url = `/api/messages/${botId}`;
|
const url = `/api/messages/${botId}`;
|
||||||
removeRoute(GBServer.globals.server, url);
|
removeRoute(GBServer.globals.server, url);
|
||||||
|
|
||||||
|
|
@ -243,7 +241,6 @@ export class GBMinService {
|
||||||
removeRoute(GBServer.globals.server, uiUrl);
|
removeRoute(GBServer.globals.server, uiUrl);
|
||||||
|
|
||||||
GBServer.globals.minInstances = GBServer.globals.minInstances.filter(p => p.instance.botId !== botId);
|
GBServer.globals.minInstances = GBServer.globals.minInstances.filter(p => p.instance.botId !== botId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -251,8 +248,7 @@ export class GBMinService {
|
||||||
* serving bot endpoint in several URL like WhatsApp endpoint, .gbkb assets,
|
* serving bot endpoint in several URL like WhatsApp endpoint, .gbkb assets,
|
||||||
* installing all BASIC artifacts from .gbdialog and OAuth2.
|
* installing all BASIC artifacts from .gbdialog and OAuth2.
|
||||||
*/
|
*/
|
||||||
public async mountBot(instance: IGBInstance) {
|
public async mountBot (instance: IGBInstance) {
|
||||||
|
|
||||||
// Build bot adapter.
|
// Build bot adapter.
|
||||||
|
|
||||||
const { min, adapter, conversationState } = await this.buildBotAdapter(
|
const { min, adapter, conversationState } = await this.buildBotAdapter(
|
||||||
|
|
@ -268,33 +264,33 @@ export class GBMinService {
|
||||||
// Install per bot deployed packages.
|
// Install per bot deployed packages.
|
||||||
|
|
||||||
let packagePath = `work/${min.botId}.gbai/${min.botId}.gbdialog`;
|
let packagePath = `work/${min.botId}.gbai/${min.botId}.gbdialog`;
|
||||||
if (fs.existsSync(packagePath)) {
|
if (Fs.existsSync(packagePath)) {
|
||||||
await this.deployer.deployPackage(min, packagePath);
|
await this.deployer.deployPackage(min, packagePath);
|
||||||
}
|
}
|
||||||
packagePath = `work/${min.botId}.gbai/${min.botId}.gbapp`;
|
packagePath = `work/${min.botId}.gbai/${min.botId}.gbapp`;
|
||||||
if (fs.existsSync(packagePath)) {
|
if (Fs.existsSync(packagePath)) {
|
||||||
await this.deployer.deployPackage(min, packagePath);
|
await this.deployer.deployPackage(min, packagePath);
|
||||||
}
|
}
|
||||||
packagePath = `work/${min.botId}.gbai/${min.botId}.gbtheme`;
|
packagePath = `work/${min.botId}.gbai/${min.botId}.gbtheme`;
|
||||||
if (fs.existsSync(packagePath)) {
|
if (Fs.existsSync(packagePath)) {
|
||||||
await this.deployer.deployPackage(min, packagePath);
|
await this.deployer.deployPackage(min, packagePath);
|
||||||
}
|
}
|
||||||
packagePath = `work/${min.botId}.gbai/${min.botId}.gblib`;
|
packagePath = `work/${min.botId}.gbai/${min.botId}.gblib`;
|
||||||
if (fs.existsSync(packagePath)) {
|
if (Fs.existsSync(packagePath)) {
|
||||||
await this.deployer.deployPackage(min, packagePath);
|
await this.deployer.deployPackage(min, packagePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dir = `work/${min.botId}.gbai/cache`;
|
let dir = `work/${min.botId}.gbai/cache`;
|
||||||
|
|
||||||
if (!fs.existsSync(dir)) {
|
if (!Fs.existsSync(dir)) {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
dir = `work/${min.botId}.gbai/profile`;
|
dir = `work/${min.botId}.gbai/profile`;
|
||||||
if (!fs.existsSync(dir)) {
|
if (!Fs.existsSync(dir)) {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
dir = `work/${min.botId}.gbai/uploads`;
|
dir = `work/${min.botId}.gbai/uploads`;
|
||||||
if (!fs.existsSync(dir)) {
|
if (!Fs.existsSync(dir)) {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -329,8 +325,11 @@ export class GBMinService {
|
||||||
|
|
||||||
// Test code.
|
// Test code.
|
||||||
if (process.env.TEST_MESSAGE) {
|
if (process.env.TEST_MESSAGE) {
|
||||||
|
GBLog.info(`Starting auto test with '${process.env.TEST_MESSAGE}'.`);
|
||||||
|
|
||||||
const client = await new Swagger({
|
const client = await new Swagger({
|
||||||
spec: JSON.parse(fs.readFileSync('directline-3.0.json', 'utf8')), usePromise: true
|
spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')),
|
||||||
|
usePromise: true
|
||||||
});
|
});
|
||||||
client.clientAuthorizations.add(
|
client.clientAuthorizations.add(
|
||||||
'AuthorizationBotConnector',
|
'AuthorizationBotConnector',
|
||||||
|
|
@ -348,7 +347,6 @@ export class GBMinService {
|
||||||
};
|
};
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(steps, async step => {
|
await CollectionUtil.asyncForEach(steps, async step => {
|
||||||
|
|
||||||
client.Conversations.Conversations_PostActivity({
|
client.Conversations.Conversations_PostActivity({
|
||||||
conversationId: conversationId,
|
conversationId: conversationId,
|
||||||
activity: {
|
activity: {
|
||||||
|
|
@ -362,9 +360,7 @@ export class GBMinService {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await sleep(15000);
|
await sleep(5000);
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -408,25 +404,23 @@ export class GBMinService {
|
||||||
|
|
||||||
this.createCheckHealthAddress(GBServer.globals.server, min, min.instance);
|
this.createCheckHealthAddress(GBServer.globals.server, min, min.instance);
|
||||||
|
|
||||||
GBDeployer.mountGBKBAssets(`${instance.botId}.gbkb`,
|
GBDeployer.mountGBKBAssets(`${instance.botId}.gbkb`, instance.botId, `${instance.botId}.gbkb`);
|
||||||
instance.botId, `${instance.botId}.gbkb`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static isChatAPI(req, res) {
|
public static isChatAPI (req, res) {
|
||||||
if (!res) {
|
if (!res) {
|
||||||
return "GeneralBots";
|
return 'GeneralBots';
|
||||||
}
|
}
|
||||||
return req.body.phone_id ? "maytapi" : "chatapi";
|
return req.body.phone_id ? 'maytapi' : 'chatapi';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a listener that can be used by external monitors to check
|
* Creates a listener that can be used by external monitors to check
|
||||||
* bot instance health.
|
* bot instance health.
|
||||||
*/
|
*/
|
||||||
private createCheckHealthAddress(server: any, min: GBMinInstance, instance: IGBInstance) {
|
private createCheckHealthAddress (server: any, min: GBMinInstance, instance: IGBInstance) {
|
||||||
server.get(`/${min.instance.botId}/check`, async (req, res) => {
|
server.get(`/${min.instance.botId}/check`, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Performs the checking of WhatsApp API if enabled for this instance.
|
// Performs the checking of WhatsApp API if enabled for this instance.
|
||||||
|
|
||||||
if (min.whatsAppDirectLine != undefined && instance.whatsappServiceKey !== null) {
|
if (min.whatsAppDirectLine != undefined && instance.whatsappServiceKey !== null) {
|
||||||
|
|
@ -442,9 +436,7 @@ export class GBMinService {
|
||||||
// GB is OK, so 200.
|
// GB is OK, so 200.
|
||||||
|
|
||||||
res.status(200).send(`General Bot ${min.botId} is healthly.`);
|
res.status(200).send(`General Bot ${min.botId} is healthly.`);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
// GB is not OK, 500 and detail the information on response content.
|
// GB is not OK, 500 and detail the information on response content.
|
||||||
|
|
||||||
GBLog.error(error);
|
GBLog.error(error);
|
||||||
|
|
@ -457,10 +449,8 @@ export class GBMinService {
|
||||||
* Handle OAuth2 web service calls for token requests
|
* Handle OAuth2 web service calls for token requests
|
||||||
* on https://<gbhost>/<BotId>/token URL.
|
* on https://<gbhost>/<BotId>/token URL.
|
||||||
*/
|
*/
|
||||||
private handleOAuthTokenRequests(server: any, min: GBMinInstance, instance: IGBInstance) {
|
private handleOAuthTokenRequests (server: any, min: GBMinInstance, instance: IGBInstance) {
|
||||||
|
|
||||||
server.get(`/${min.instance.botId}/token`, async (req, res) => {
|
server.get(`/${min.instance.botId}/token`, async (req, res) => {
|
||||||
|
|
||||||
// Checks request state by reading AntiCSRFAttackState from GB Admin infrastructure.
|
// Checks request state by reading AntiCSRFAttackState from GB Admin infrastructure.
|
||||||
|
|
||||||
const state = await min.adminService.getValue(instance.instanceId, 'AntiCSRFAttackState');
|
const state = await min.adminService.getValue(instance.instanceId, 'AntiCSRFAttackState');
|
||||||
|
|
@ -469,7 +459,7 @@ export class GBMinService {
|
||||||
GBLog.error(msg);
|
GBLog.error(msg);
|
||||||
throw new Error(msg);
|
throw new Error(msg);
|
||||||
}
|
}
|
||||||
const authenticationContext = new AuthenticationContext(
|
const authenticationContext = new AuthenticationContext.AuthenticationContext(
|
||||||
urlJoin(min.instance.authenticatorAuthorityHostUrl, min.instance.authenticatorTenant)
|
urlJoin(min.instance.authenticatorAuthorityHostUrl, min.instance.authenticatorTenant)
|
||||||
);
|
);
|
||||||
const resource = 'https://graph.microsoft.com';
|
const resource = 'https://graph.microsoft.com';
|
||||||
|
|
@ -488,12 +478,11 @@ export class GBMinService {
|
||||||
GBLog.error(msg);
|
GBLog.error(msg);
|
||||||
res.send(msg);
|
res.send(msg);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Saves token to the database.
|
// Saves token to the database.
|
||||||
|
|
||||||
await this.adminService.setValue(instance.instanceId, 'accessToken', token.accessToken);
|
await this.adminService.setValue(instance.instanceId, 'accessToken', token['accessToken']);
|
||||||
await this.adminService.setValue(instance.instanceId, 'refreshToken', token.refreshToken);
|
await this.adminService.setValue(instance.instanceId, 'refreshToken', token['refreshToken']);
|
||||||
await this.adminService.setValue(instance.instanceId, 'expiresOn', token.expiresOn.toString());
|
await this.adminService.setValue(instance.instanceId, 'expiresOn', token['expiresOn'].toString());
|
||||||
await this.adminService.setValue(instance.instanceId, 'AntiCSRFAttackState', undefined);
|
await this.adminService.setValue(instance.instanceId, 'AntiCSRFAttackState', undefined);
|
||||||
|
|
||||||
// Inform the home for default .gbui after finishing token retrival.
|
// Inform the home for default .gbui after finishing token retrival.
|
||||||
|
|
@ -509,14 +498,15 @@ export class GBMinService {
|
||||||
* Handle OAuth2 web service calls for authorization requests
|
* Handle OAuth2 web service calls for authorization requests
|
||||||
* on https://<gbhost>/<BotId>/auth URL.
|
* on https://<gbhost>/<BotId>/auth URL.
|
||||||
*/
|
*/
|
||||||
private handleOAuthRequests(server: any, min: GBMinInstance) {
|
private handleOAuthRequests (server: any, min: GBMinInstance) {
|
||||||
server.get(`/${min.instance.botId}/auth`, (req, res) => {
|
server.get(`/${min.instance.botId}/auth`, (req, res) => {
|
||||||
let authorizationUrl = urlJoin(
|
let authorizationUrl = urlJoin(
|
||||||
min.instance.authenticatorAuthorityHostUrl,
|
min.instance.authenticatorAuthorityHostUrl,
|
||||||
min.instance.authenticatorTenant,
|
min.instance.authenticatorTenant,
|
||||||
'/oauth2/authorize'
|
'/oauth2/authorize'
|
||||||
);
|
);
|
||||||
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${min.instance.marketplaceId
|
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${
|
||||||
|
min.instance.marketplaceId
|
||||||
}&redirect_uri=${urlJoin(min.instance.botEndpoint, min.instance.botId, 'token')}`;
|
}&redirect_uri=${urlJoin(min.instance.botEndpoint, min.instance.botId, 'token')}`;
|
||||||
GBLog.info(`HandleOAuthRequests: ${authorizationUrl}.`);
|
GBLog.info(`HandleOAuthRequests: ${authorizationUrl}.`);
|
||||||
res.redirect(authorizationUrl);
|
res.redirect(authorizationUrl);
|
||||||
|
|
@ -526,8 +516,7 @@ export class GBMinService {
|
||||||
/**
|
/**
|
||||||
* Returns the instance object to clients requesting bot info.
|
* Returns the instance object to clients requesting bot info.
|
||||||
*/
|
*/
|
||||||
private async handleGetInstanceForClient(req: any, res: any) {
|
private async handleGetInstanceForClient (req: any, res: any) {
|
||||||
|
|
||||||
// Translates the requested botId.
|
// Translates the requested botId.
|
||||||
|
|
||||||
let botId = req.params.botId;
|
let botId = req.params.botId;
|
||||||
|
|
@ -545,7 +534,6 @@ export class GBMinService {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance !== null) {
|
if (instance !== null) {
|
||||||
|
|
||||||
// Gets the webchat token, speech token and theme.
|
// Gets the webchat token, speech token and theme.
|
||||||
|
|
||||||
const webchatTokenContainer = await this.getWebchatToken(instance);
|
const webchatTokenContainer = await this.getWebchatToken(instance);
|
||||||
|
|
@ -558,7 +546,6 @@ export class GBMinService {
|
||||||
theme = `default.gbtheme`;
|
theme = `default.gbtheme`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
res.send(
|
res.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
instanceId: instance.instanceId,
|
instanceId: instance.instanceId,
|
||||||
|
|
@ -586,7 +573,7 @@ export class GBMinService {
|
||||||
/**
|
/**
|
||||||
* Gets Webchat token from Bot Service.
|
* Gets Webchat token from Bot Service.
|
||||||
*/
|
*/
|
||||||
private async getWebchatToken(instance: any) {
|
private async getWebchatToken (instance: any) {
|
||||||
const options = {
|
const options = {
|
||||||
url: 'https://directline.botframework.com/v3/directline/tokens/generate',
|
url: 'https://directline.botframework.com/v3/directline/tokens/generate',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|
@ -609,7 +596,7 @@ export class GBMinService {
|
||||||
/**
|
/**
|
||||||
* Gets a Speech to Text / Text to Speech token from the provider.
|
* Gets a Speech to Text / Text to Speech token from the provider.
|
||||||
*/
|
*/
|
||||||
private async getSTSToken(instance: any) {
|
private async getSTSToken (instance: any) {
|
||||||
const options = {
|
const options = {
|
||||||
url: instance.speechEndpoint,
|
url: instance.speechEndpoint,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|
@ -630,17 +617,19 @@ export class GBMinService {
|
||||||
/**
|
/**
|
||||||
* Builds the BOT Framework & GB infrastructures.
|
* Builds the BOT Framework & GB infrastructures.
|
||||||
*/
|
*/
|
||||||
private async buildBotAdapter(instance: any, sysPackages: IGBPackage[], appPackages: IGBPackage[]) {
|
private async buildBotAdapter (instance: any, sysPackages: IGBPackage[], appPackages: IGBPackage[]) {
|
||||||
|
|
||||||
// MSFT stuff.
|
// MSFT stuff.
|
||||||
|
|
||||||
const adapter = new BotFrameworkAdapter(
|
const adapter = new BotFrameworkAdapter({
|
||||||
{ appId: instance.marketplaceId, appPassword: instance.marketplacePassword });
|
appId: instance.marketplaceId,
|
||||||
|
appPassword: instance.marketplacePassword
|
||||||
|
});
|
||||||
const storage = new MemoryStorage();
|
const storage = new MemoryStorage();
|
||||||
const conversationState = new ConversationState(storage);
|
const conversationState = new ConversationState(storage);
|
||||||
const userState = new UserState(storage);
|
const userState = new UserState(storage);
|
||||||
adapter.use(new AutoSaveStateMiddleware(conversationState, userState));
|
adapter.use(new AutoSaveStateMiddleware(conversationState, userState));
|
||||||
MicrosoftAppCredentials.trustServiceUrl('https://directline.botframework.com',
|
MicrosoftAppCredentials.trustServiceUrl(
|
||||||
|
'https://directline.botframework.com',
|
||||||
new Date(new Date().setFullYear(new Date().getFullYear() + 10))
|
new Date(new Date().setFullYear(new Date().getFullYear() + 10))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -659,9 +648,9 @@ export class GBMinService {
|
||||||
min.cbMap = {};
|
min.cbMap = {};
|
||||||
min.scriptMap = {};
|
min.scriptMap = {};
|
||||||
min.sandBoxMap = {};
|
min.sandBoxMap = {};
|
||||||
min["scheduleMap"] = {};
|
min['scheduleMap'] = {};
|
||||||
min["conversationWelcomed"] = {};
|
min['conversationWelcomed'] = {};
|
||||||
min["nerEngine"] = new NerManager();;
|
min['nerEngine'] = new nlp.default.NerManager();
|
||||||
min.packages = sysPackages;
|
min.packages = sysPackages;
|
||||||
min.appPackages = appPackages;
|
min.appPackages = appPackages;
|
||||||
|
|
||||||
|
|
@ -687,8 +676,6 @@ export class GBMinService {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (min.instance.googlePrivateKey) {
|
if (min.instance.googlePrivateKey) {
|
||||||
min['googleDirectLine'] = new GoogleChatDirectLine(
|
min['googleDirectLine'] = new GoogleChatDirectLine(
|
||||||
min,
|
min,
|
||||||
|
|
@ -703,11 +690,7 @@ export class GBMinService {
|
||||||
await min['googleDirectLine'].setup(true);
|
await min['googleDirectLine'].setup(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const group = min.core.getParam<string>(
|
const group = min.core.getParam<string>(min.instance, 'WhatsApp Group ID', null);
|
||||||
min.instance,
|
|
||||||
'WhatsApp Group ID',
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
|
|
||||||
WhatsappDirectLine.botGroups[min.botId] = group;
|
WhatsappDirectLine.botGroups[min.botId] = group;
|
||||||
|
|
||||||
|
|
@ -766,8 +749,7 @@ export class GBMinService {
|
||||||
/**
|
/**
|
||||||
* Performs calling of loadBot event in all .gbapps.
|
* Performs calling of loadBot event in all .gbapps.
|
||||||
*/
|
*/
|
||||||
private async invokeLoadBot(appPackages: IGBPackage[], sysPackages: IGBPackage[], min: GBMinInstance) {
|
private async invokeLoadBot (appPackages: IGBPackage[], sysPackages: IGBPackage[], min: GBMinInstance) {
|
||||||
|
|
||||||
// Calls loadBot event in all .gbapp packages.
|
// Calls loadBot event in all .gbapp packages.
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(sysPackages, async p => {
|
await CollectionUtil.asyncForEach(sysPackages, async p => {
|
||||||
|
|
@ -801,17 +783,20 @@ export class GBMinService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Unify in util.
|
// TODO: Unify in util.
|
||||||
public static userMobile(step) {
|
public static userMobile (step) {
|
||||||
let mobile = WhatsappDirectLine.mobiles[step.context.activity.conversation.id]
|
let mobile = WhatsappDirectLine.mobiles[step.context.activity.conversation.id];
|
||||||
return mobile;
|
|
||||||
|
|
||||||
|
if (!mobile && step) {
|
||||||
|
return step.context.activity.from.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return mobile;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BOT Framework web service hook method.
|
* BOT Framework web service hook method.
|
||||||
*/
|
*/
|
||||||
private async receiver(
|
private async receiver (
|
||||||
req: any,
|
req: any,
|
||||||
res: any,
|
res: any,
|
||||||
conversationState: ConversationState,
|
conversationState: ConversationState,
|
||||||
|
|
@ -819,7 +804,6 @@ export class GBMinService {
|
||||||
instance: any,
|
instance: any,
|
||||||
appPackages: any[]
|
appPackages: any[]
|
||||||
) {
|
) {
|
||||||
|
|
||||||
let adapter = min.bot;
|
let adapter = min.bot;
|
||||||
|
|
||||||
if (req.body.object) {
|
if (req.body.object) {
|
||||||
|
|
@ -841,13 +825,10 @@ export class GBMinService {
|
||||||
step.context.activity.locale = 'pt-BR';
|
step.context.activity.locale = 'pt-BR';
|
||||||
let firstTime = false;
|
let firstTime = false;
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const sec = new SecService();
|
const sec = new SecService();
|
||||||
const user = await min.userProfile.get(context, {});
|
const user = await min.userProfile.get(context, {});
|
||||||
const conversationReference = JSON.stringify(
|
const conversationReference = JSON.stringify(TurnContext.getConversationReference(context.activity));
|
||||||
TurnContext.getConversationReference(context.activity)
|
|
||||||
);
|
|
||||||
|
|
||||||
// First time processing.
|
// First time processing.
|
||||||
|
|
||||||
|
|
@ -860,7 +841,7 @@ export class GBMinService {
|
||||||
user.subjects = [];
|
user.subjects = [];
|
||||||
user.cb = undefined;
|
user.cb = undefined;
|
||||||
user.welcomed = false;
|
user.welcomed = false;
|
||||||
user.basicOptions = { maxLines: 100, translatorOn: true, wholeWord: true, theme: "white", maxColumns: 40 };
|
user.basicOptions = { maxLines: 100, translatorOn: true, wholeWord: true, theme: 'white', maxColumns: 40 };
|
||||||
|
|
||||||
firstTime = true;
|
firstTime = true;
|
||||||
|
|
||||||
|
|
@ -868,7 +849,6 @@ export class GBMinService {
|
||||||
// including the bot, that is filtered bellow.
|
// including the bot, that is filtered bellow.
|
||||||
|
|
||||||
if (context.activity.from.id !== min.botId) {
|
if (context.activity.from.id !== min.botId) {
|
||||||
|
|
||||||
// Creates a new row in user table if it does not exists.
|
// Creates a new row in user table if it does not exists.
|
||||||
|
|
||||||
const member = context.activity.from;
|
const member = context.activity.from;
|
||||||
|
|
@ -886,7 +866,6 @@ export class GBMinService {
|
||||||
const analytics = new AnalyticsService();
|
const analytics = new AnalyticsService();
|
||||||
user.systemUser = persistedUser;
|
user.systemUser = persistedUser;
|
||||||
user.conversation = await analytics.createConversation(persistedUser);
|
user.conversation = await analytics.createConversation(persistedUser);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await sec.updateConversationReferenceById(user.systemUser.userId, conversationReference);
|
await sec.updateConversationReferenceById(user.systemUser.userId, conversationReference);
|
||||||
|
|
@ -911,37 +890,52 @@ export class GBMinService {
|
||||||
// Required for MSTEAMS handling of persisted conversations.
|
// Required for MSTEAMS handling of persisted conversations.
|
||||||
|
|
||||||
if (step.context.activity.channelId === 'msteams') {
|
if (step.context.activity.channelId === 'msteams') {
|
||||||
|
|
||||||
if (step.context.activity.attachments && step.context.activity.attachments.length > 1) {
|
if (step.context.activity.attachments && step.context.activity.attachments.length > 1) {
|
||||||
|
|
||||||
const file = context.activity.attachments[0];
|
const file = context.activity.attachments[0];
|
||||||
const credentials = new MicrosoftAppCredentials(min.instance.marketplaceId, min.instance.marketplacePassword);
|
const credentials = new MicrosoftAppCredentials(
|
||||||
|
min.instance.marketplaceId,
|
||||||
|
min.instance.marketplacePassword
|
||||||
|
);
|
||||||
const botToken = await credentials.getToken();
|
const botToken = await credentials.getToken();
|
||||||
const headers = { Authorization: `Bearer ${botToken}` };
|
const headers = { Authorization: `Bearer ${botToken}` };
|
||||||
const t = new SystemKeywords(null, null, null);
|
const t = new SystemKeywords(null, null, null, null);
|
||||||
const data = await t.getByHttp(file.contentUrl, headers, null, null, null, true);
|
const data = await t.getByHttp({
|
||||||
|
url: file.contentUrl,
|
||||||
|
headers,
|
||||||
|
username: null,
|
||||||
|
ps: null,
|
||||||
|
qs: null,
|
||||||
|
streaming: true
|
||||||
|
});
|
||||||
const folder = `work/${min.instance.botId}.gbai/cache`;
|
const folder = `work/${min.instance.botId}.gbai/cache`;
|
||||||
const filename = `${GBAdminService.generateUuid()}.png`;
|
const filename = `${GBAdminService.generateUuid()}.png`;
|
||||||
|
|
||||||
Fs.writeFileSync(path.join(folder, filename), data);
|
Fs.writeFileSync(path.join(folder, filename), data);
|
||||||
step.context.activity.text = urlJoin(GBServer.globals.publicAddress, `${min.instance.botId}`, 'cache', filename);
|
step.context.activity.text = urlJoin(
|
||||||
|
GBServer.globals.publicAddress,
|
||||||
|
`${min.instance.botId}`,
|
||||||
|
'cache',
|
||||||
|
filename
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!user.welcomed) {
|
if (!user.welcomed) {
|
||||||
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
||||||
if (startDialog && !user.welcomed) {
|
if (startDialog && !user.welcomed) {
|
||||||
user.welcomed = true;
|
user.welcomed = true;
|
||||||
GBLog.info(`Auto start (teams) dialog is now being called: ${startDialog} for ${min.instance.botId}...`);
|
GBLog.info(`Auto start (teams) dialog is now being called: ${startDialog} for ${min.instance.botId}...`);
|
||||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, this.deployer);
|
await GBVMService.callVM(startDialog.toLowerCase(), min, step, this.deployer, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Required for F0 handling of persisted conversations.
|
// Required for F0 handling of persisted conversations.
|
||||||
|
|
||||||
GBLog.info(`Input> ${context.activity.text} (type: ${context.activity.type}, name: ${context.activity.name}, channelId: ${context.activity.channelId})`);
|
GBLog.info(
|
||||||
|
`Input> ${context.activity.text} (type: ${context.activity.type}, name: ${
|
||||||
|
context.activity.name
|
||||||
|
}, channelId: ${context.activity.channelId})`
|
||||||
|
);
|
||||||
|
|
||||||
// Answer to specific BOT Framework event conversationUpdate to auto start dialogs.
|
// Answer to specific BOT Framework event conversationUpdate to auto start dialogs.
|
||||||
// Skips if the bot is talking.
|
// Skips if the bot is talking.
|
||||||
|
|
@ -949,9 +943,7 @@ export class GBMinService {
|
||||||
|
|
||||||
if (context.activity.type === 'installationUpdate') {
|
if (context.activity.type === 'installationUpdate') {
|
||||||
GBLog.info(`Bot installed on Teams.`);
|
GBLog.info(`Bot installed on Teams.`);
|
||||||
} else if (context.activity.type === 'conversationUpdate' &&
|
} else if (context.activity.type === 'conversationUpdate' && context.activity.membersAdded.length > 0) {
|
||||||
context.activity.membersAdded.length > 0) {
|
|
||||||
|
|
||||||
// Check if a bot or a human participant is being added to the conversation.
|
// Check if a bot or a human participant is being added to the conversation.
|
||||||
|
|
||||||
const member = context.activity.membersAdded[0];
|
const member = context.activity.membersAdded[0];
|
||||||
|
|
@ -967,45 +959,46 @@ export class GBMinService {
|
||||||
// Auto starts dialogs if any is specified.
|
// Auto starts dialogs if any is specified.
|
||||||
|
|
||||||
if (!startDialog && !user.welcomed) {
|
if (!startDialog && !user.welcomed) {
|
||||||
|
|
||||||
// Otherwise, calls / (root) to default welcome users.
|
// Otherwise, calls / (root) to default welcome users.
|
||||||
|
|
||||||
await step.beginDialog('/');
|
await step.beginDialog('/');
|
||||||
}
|
} else {
|
||||||
else {
|
if (
|
||||||
if (!GBMinService.userMobile(step) &&
|
!GBMinService.userMobile(step) &&
|
||||||
!min["conversationWelcomed"][step.context.activity.conversation.id]) {
|
!min['conversationWelcomed'][step.context.activity.conversation.id]
|
||||||
|
) {
|
||||||
|
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
||||||
|
|
||||||
min["conversationWelcomed"][step.context.activity.conversation.id] = true;
|
GBLog.info(
|
||||||
|
`Auto start (web 1) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
||||||
GBLog.info(`Auto start (web 1) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`);
|
);
|
||||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, this.deployer);
|
await GBVMService.callVM(startDialog.toLowerCase(), min, step, this.deployer, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
GBLog.info(`Person added to conversation: ${member.name}`);
|
GBLog.info(`Person added to conversation: ${member.name}`);
|
||||||
|
|
||||||
if (GBMinService.userMobile(step)) {
|
if (GBMinService.userMobile(step)) {
|
||||||
if (startDialog && !min["conversationWelcomed"][step.context.activity.conversation.id] &&
|
if (
|
||||||
!step.context.activity['group']) {
|
startDialog &&
|
||||||
|
!min['conversationWelcomed'][step.context.activity.conversation.id] &&
|
||||||
|
!step.context.activity['group']
|
||||||
|
) {
|
||||||
user.welcomed = true;
|
user.welcomed = true;
|
||||||
min["conversationWelcomed"][step.context.activity.conversation.id] = true;
|
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
||||||
await min.userProfile.set(step.context, user);
|
await min.userProfile.set(step.context, user);
|
||||||
GBLog.info(`Auto start (whatsapp) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`);
|
GBLog.info(
|
||||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, this.deployer);
|
`Auto start (whatsapp) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
||||||
|
);
|
||||||
|
await GBVMService.callVM(startDialog.toLowerCase(), min, step, this.deployer, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (context.activity.type === 'message') {
|
} else if (context.activity.type === 'message') {
|
||||||
|
|
||||||
// Processes messages activities.
|
// Processes messages activities.
|
||||||
|
|
||||||
await this.processMessageActivity(context, min, step);
|
await this.processMessageActivity(context, min, step);
|
||||||
|
|
||||||
} else if (context.activity.type === 'event') {
|
} else if (context.activity.type === 'event') {
|
||||||
|
|
||||||
// Processes events activities.
|
// Processes events activities.
|
||||||
|
|
||||||
await this.processEventActivity(min, user, context, step);
|
await this.processEventActivity(min, user, context, step);
|
||||||
|
|
@ -1014,9 +1007,7 @@ export class GBMinService {
|
||||||
// Saves conversation state for later use.
|
// Saves conversation state for later use.
|
||||||
|
|
||||||
await conversationState.saveChanges(context, true);
|
await conversationState.saveChanges(context, true);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
const msg = `ERROR: ${error.message} ${error.stack ? error.stack : ''}`;
|
const msg = `ERROR: ${error.message} ${error.stack ? error.stack : ''}`;
|
||||||
GBLog.error(msg);
|
GBLog.error(msg);
|
||||||
|
|
||||||
|
|
@ -1034,8 +1025,7 @@ export class GBMinService {
|
||||||
/**
|
/**
|
||||||
* Called to handle all event sent by .gbui clients.
|
* Called to handle all event sent by .gbui clients.
|
||||||
*/
|
*/
|
||||||
private async processEventActivity(min, user, context, step: GBDialogStep) {
|
private async processEventActivity (min, user, context, step: GBDialogStep) {
|
||||||
|
|
||||||
if (context.activity.name === 'whoAmI') {
|
if (context.activity.name === 'whoAmI') {
|
||||||
await step.beginDialog('/whoAmI');
|
await step.beginDialog('/whoAmI');
|
||||||
} else if (context.activity.name === 'showSubjects') {
|
} else if (context.activity.name === 'showSubjects') {
|
||||||
|
|
@ -1057,10 +1047,10 @@ export class GBMinService {
|
||||||
});
|
});
|
||||||
} else if (context.activity.name === 'startGB') {
|
} else if (context.activity.name === 'startGB') {
|
||||||
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
||||||
if (startDialog && !min["conversationWelcomed"][step.context.activity.conversation.id]) {
|
if (startDialog && !min['conversationWelcomed'][step.context.activity.conversation.id]) {
|
||||||
user.welcomed = true;
|
user.welcomed = true;
|
||||||
GBLog.info(`Auto start (web 2) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`);
|
GBLog.info(`Auto start (web 2) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`);
|
||||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, this.deployer);
|
await GBVMService.callVM(startDialog.toLowerCase(), min, step, this.deployer, false);
|
||||||
}
|
}
|
||||||
} else if (context.activity.name === 'updateToken') {
|
} else if (context.activity.name === 'updateToken') {
|
||||||
const token = context.activity.data;
|
const token = context.activity.data;
|
||||||
|
|
@ -1073,8 +1063,7 @@ export class GBMinService {
|
||||||
/**
|
/**
|
||||||
* Called to handle all text messages sent and received by the bot.
|
* Called to handle all text messages sent and received by the bot.
|
||||||
*/
|
*/
|
||||||
private async processMessageActivity(context, min: GBMinInstance, step: GBDialogStep) {
|
private async processMessageActivity (context, min: GBMinInstance, step: GBDialogStep) {
|
||||||
|
|
||||||
const sec = new SecService();
|
const sec = new SecService();
|
||||||
|
|
||||||
if (!context.activity.text) {
|
if (!context.activity.text) {
|
||||||
|
|
@ -1099,12 +1088,10 @@ export class GBMinService {
|
||||||
const user = await min.userProfile.get(context, {});
|
const user = await min.userProfile.get(context, {});
|
||||||
let message: GuaribasConversationMessage;
|
let message: GuaribasConversationMessage;
|
||||||
if (process.env.PRIVACY_STORE_MESSAGES === 'true') {
|
if (process.env.PRIVACY_STORE_MESSAGES === 'true') {
|
||||||
|
|
||||||
// Adds message to the analytics layer.
|
// Adds message to the analytics layer.
|
||||||
|
|
||||||
const analytics = new AnalyticsService();
|
const analytics = new AnalyticsService();
|
||||||
if (user) {
|
if (user) {
|
||||||
|
|
||||||
if (!user.conversation) {
|
if (!user.conversation) {
|
||||||
user.conversation = await analytics.createConversation(user.systemUser);
|
user.conversation = await analytics.createConversation(user.systemUser);
|
||||||
}
|
}
|
||||||
|
|
@ -1128,51 +1115,47 @@ export class GBMinService {
|
||||||
|
|
||||||
const isVMCall = Object.keys(min.scriptMap).find(key => min.scriptMap[key] === context.activity.text) !== undefined;
|
const isVMCall = Object.keys(min.scriptMap).find(key => min.scriptMap[key] === context.activity.text) !== undefined;
|
||||||
if (isVMCall) {
|
if (isVMCall) {
|
||||||
await GBVMService.callVM(context.activity.text, min, step, this.deployer);
|
await GBVMService.callVM(context.activity.text, min, step, this.deployer, false);
|
||||||
} else if (context.activity.text.charAt(0) === '/') {
|
} else if (context.activity.text.charAt(0) === '/') {
|
||||||
|
|
||||||
const text = context.activity.text;
|
const text = context.activity.text;
|
||||||
const parts = text.split(' ');
|
const parts = text.split(' ');
|
||||||
const cmdOrDialogName = parts[0];
|
const cmdOrDialogName = parts[0];
|
||||||
parts.splice(0, 1);
|
parts.splice(0, 1);
|
||||||
const args = parts.join(' ');
|
const args = parts.join(' ');
|
||||||
if (cmdOrDialogName === '/start') {
|
if (cmdOrDialogName === '/start') {
|
||||||
|
|
||||||
|
|
||||||
// Reset user.
|
// Reset user.
|
||||||
|
|
||||||
const user = await min.userProfile.get(context, {});
|
const user = await min.userProfile.get(context, {});
|
||||||
await min.conversationalService.sendEvent(min, step, 'loadInstance', {});
|
await min.conversationalService.sendEvent(min, step, 'loadInstance', {});
|
||||||
user.loaded = false;
|
user.loaded = false;
|
||||||
await min.userProfile.set(step.context, user);
|
await min.userProfile.set(step.context, user);
|
||||||
|
|
||||||
} else if (cmdOrDialogName === '/call') {
|
} else if (cmdOrDialogName === '/call') {
|
||||||
await GBVMService.callVM(args, min, step, this.deployer);
|
await GBVMService.callVM(args, min, step, this.deployer, false);
|
||||||
} else if (cmdOrDialogName === '/callsch') {
|
} else if (cmdOrDialogName === '/callsch') {
|
||||||
await GBVMService.callVM(args, min, null, null);
|
await GBVMService.callVM(args, min, null, null, false);
|
||||||
|
} else if (cmdOrDialogName === '/calldbg') {
|
||||||
|
await GBVMService.callVM(args, min, step, this.deployer, true);
|
||||||
} else {
|
} else {
|
||||||
await step.beginDialog(cmdOrDialogName, { args: args });
|
await step.beginDialog(cmdOrDialogName, { args: args });
|
||||||
}
|
}
|
||||||
} else if (globalQuit(step.context.activity.locale, context.activity.text)) {
|
} else if (globalQuit(step.context.activity.locale, context.activity.text)) {
|
||||||
await step.cancelAllDialogs();
|
await step.cancelAllDialogs();
|
||||||
await min.conversationalService.sendText(min, step, Messages[step.context.activity.locale].canceled);
|
await min.conversationalService.sendText(min, step, Messages[step.context.activity.locale].canceled);
|
||||||
|
|
||||||
} else if (context.activity.text === 'admin') {
|
} else if (context.activity.text === 'admin') {
|
||||||
await step.beginDialog('/admin');
|
await step.beginDialog('/admin');
|
||||||
|
|
||||||
} else if (context.activity.text.startsWith('{"title"')) {
|
} else if (context.activity.text.startsWith('{"title"')) {
|
||||||
await step.beginDialog('/menu', JSON.parse(context.activity.text));
|
await step.beginDialog('/menu', JSON.parse(context.activity.text));
|
||||||
|
|
||||||
} else if (
|
} else if (
|
||||||
!(await this.deployer.getStoragePackageByName(min.instance.instanceId, `${min.instance.botId}.gbkb`)) &&
|
!(await this.deployer.getStoragePackageByName(min.instance.instanceId, `${min.instance.botId}.gbkb`)) &&
|
||||||
process.env.GBKB_ENABLE_AUTO_PUBLISH === 'true'
|
process.env.GBKB_ENABLE_AUTO_PUBLISH === 'true'
|
||||||
) {
|
) {
|
||||||
await min.conversationalService.sendText(min, step,
|
await min.conversationalService.sendText(
|
||||||
|
min,
|
||||||
|
step,
|
||||||
`Oi, ainda não possuo pacotes de conhecimento publicados. Por favor, aguarde alguns segundos enquanto eu auto-publico alguns pacotes.`
|
`Oi, ainda não possuo pacotes de conhecimento publicados. Por favor, aguarde alguns segundos enquanto eu auto-publico alguns pacotes.`
|
||||||
);
|
);
|
||||||
await step.beginDialog('/publish', { confirm: true, firstTime: true });
|
await step.beginDialog('/publish', { confirm: true, firstTime: true });
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Removes unwanted chars in input text.
|
// Removes unwanted chars in input text.
|
||||||
|
|
||||||
let text = context.activity.text;
|
let text = context.activity.text;
|
||||||
|
|
@ -1195,7 +1178,7 @@ export class GBMinService {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const getNormalizedRegExp = (value) => {
|
const getNormalizedRegExp = value => {
|
||||||
var chars = [
|
var chars = [
|
||||||
{ letter: 'a', reg: '[aáàãäâ]' },
|
{ letter: 'a', reg: '[aáàãäâ]' },
|
||||||
{ letter: 'e', reg: '[eéèëê]' },
|
{ letter: 'e', reg: '[eéèëê]' },
|
||||||
|
|
@ -1207,7 +1190,7 @@ export class GBMinService {
|
||||||
|
|
||||||
for (var i in chars) {
|
for (var i in chars) {
|
||||||
value = value.replace(new RegExp(chars[i].letter, 'gi'), chars[i].reg);
|
value = value.replace(new RegExp(chars[i].letter, 'gi'), chars[i].reg);
|
||||||
};
|
}
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1223,7 +1206,10 @@ export class GBMinService {
|
||||||
const replacementToken = 'X' + GBAdminService.getNumberIdentifier().substr(0, 4);
|
const replacementToken = 'X' + GBAdminService.getNumberIdentifier().substr(0, 4);
|
||||||
replacements[i] = { text: item, replacementToken: replacementToken };
|
replacements[i] = { text: item, replacementToken: replacementToken };
|
||||||
i++;
|
i++;
|
||||||
textProcessed = textProcessed.replace(new RegExp(`\\b${getNormalizedRegExp(it.trim())}\\b`, 'gi'), `${replacementToken}`);
|
textProcessed = textProcessed.replace(
|
||||||
|
new RegExp(`\\b${getNormalizedRegExp(it.trim())}\\b`, 'gi'),
|
||||||
|
`${replacementToken}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1235,10 +1221,15 @@ export class GBMinService {
|
||||||
|
|
||||||
// Detects user typed language and updates their locale profile if applies.
|
// Detects user typed language and updates their locale profile if applies.
|
||||||
|
|
||||||
let locale = min.core.getParam<string>(min.instance, 'Default User Language',
|
let locale = min.core.getParam<string>(
|
||||||
|
min.instance,
|
||||||
|
'Default User Language',
|
||||||
GBConfigService.get('DEFAULT_USER_LANGUAGE')
|
GBConfigService.get('DEFAULT_USER_LANGUAGE')
|
||||||
);
|
);
|
||||||
const detectLanguage = min.core.getParam<boolean>(min.instance, 'Language Detector',
|
const detectLanguage =
|
||||||
|
min.core.getParam<boolean>(
|
||||||
|
min.instance,
|
||||||
|
'Language Detector',
|
||||||
GBConfigService.getBoolean('LANGUAGE_DETECTOR')
|
GBConfigService.getBoolean('LANGUAGE_DETECTOR')
|
||||||
) === 'true';
|
) === 'true';
|
||||||
const systemUser = user.systemUser;
|
const systemUser = user.systemUser;
|
||||||
|
|
@ -1246,7 +1237,6 @@ export class GBMinService {
|
||||||
if (text != '' && detectLanguage && !locale) {
|
if (text != '' && detectLanguage && !locale) {
|
||||||
locale = await min.conversationalService.getLanguage(min, text);
|
locale = await min.conversationalService.getLanguage(min, text);
|
||||||
if (systemUser.locale != locale) {
|
if (systemUser.locale != locale) {
|
||||||
|
|
||||||
user.systemUser = await sec.updateUserLocale(systemUser.userId, locale);
|
user.systemUser = await sec.updateUserLocale(systemUser.userId, locale);
|
||||||
await min.userProfile.set(step.context, user);
|
await min.userProfile.set(step.context, user);
|
||||||
}
|
}
|
||||||
|
|
@ -1295,32 +1285,32 @@ export class GBMinService {
|
||||||
const message = await min.kbService.getAnswerTextByMediaName(min.instance.instanceId, filename);
|
const message = await min.kbService.getAnswerTextByMediaName(min.instance.instanceId, filename);
|
||||||
|
|
||||||
if (message === null) {
|
if (message === null) {
|
||||||
GBLog.error(`File ${filename} not found in any .gbkb published. Check the name or publish again the associated .gbkb.`);
|
GBLog.error(
|
||||||
|
`File ${filename} not found in any .gbkb published. Check the name or publish again the associated .gbkb.`
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
await min.conversationalService.sendMarkdownToMobile(min, null, manualUser.userSystemId, message);
|
await min.conversationalService.sendMarkdownToMobile(min, null, manualUser.userSystemId, message);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
await min.whatsAppDirectLine.sendToDeviceEx(
|
||||||
|
manualUser.userSystemId,
|
||||||
|
`${manualUser.agentSystemId}: ${text}`,
|
||||||
|
locale,
|
||||||
|
step.context.activity.conversation.id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
await min.whatsAppDirectLine.sendToDeviceEx(manualUser.userSystemId, `${manualUser.agentSystemId}: ${text}`, locale,
|
if (min.cbMap[user.systemUser.userId] && min.cbMap[user.systemUser.userId].promise == '!GBHEAR') {
|
||||||
step.context.activity.conversation.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
if (min.cbMap[user.systemUser.userId] &&
|
|
||||||
min.cbMap[user.systemUser.userId].promise == '!GBHEAR') {
|
|
||||||
min.cbMap[user.systemUser.userId].promise = text;
|
min.cbMap[user.systemUser.userId].promise = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a dialog in course, continue to the next step.
|
// If there is a dialog in course, continue to the next step.
|
||||||
|
|
||||||
else if (step.activeDialog !== undefined) {
|
else if (step.activeDialog !== undefined) {
|
||||||
await step.continueDialog();
|
await step.continueDialog();
|
||||||
} else {
|
} else {
|
||||||
|
const startDialog = user.hearOnDialog
|
||||||
const startDialog = user.hearOnDialog ?
|
? user.hearOnDialog
|
||||||
user.hearOnDialog :
|
: min.core.getParam(min.instance, 'Start Dialog', null);
|
||||||
min.core.getParam(min.instance, 'Start Dialog', null);
|
|
||||||
|
|
||||||
if (text !== startDialog) {
|
if (text !== startDialog) {
|
||||||
let nextDialog = null;
|
let nextDialog = null;
|
||||||
|
|
@ -1344,7 +1334,6 @@ export class GBMinService {
|
||||||
user: user ? user.dataValues : null,
|
user: user ? user.dataValues : null,
|
||||||
message: message
|
message: message
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,58 +36,45 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const puppeteer = require('puppeteer-extra')
|
import puppeteer from 'puppeteer-extra';
|
||||||
const Fs = require('fs');
|
import Fs from 'fs';
|
||||||
|
|
||||||
// const StealthPlugin = require('puppeteer-extra-plugin-stealth')
|
// const StealthPlugin from 'puppeteer-extra-plugin-stealth')
|
||||||
// puppeteer.use(StealthPlugin());
|
// puppeteer.use(StealthPlugin());
|
||||||
|
|
||||||
import { NextFunction, Request, Response } from "express";
|
import { NextFunction, Request, Response } from 'express';
|
||||||
import urljoin = require("url-join");
|
import urljoin from 'url-join';
|
||||||
const Path = require('path');
|
|
||||||
|
|
||||||
// https://hackernoon.com/tips-and-tricks-for-web-scraping-with-puppeteer-ed391a63d952
|
// https://hackernoon.com/tips-and-tricks-for-web-scraping-with-puppeteer-ed391a63d952
|
||||||
// Dont download all resources, we just need the HTML
|
// Dont download all resources, we just need the HTML
|
||||||
// Also, this is huge performance/response time boost
|
// Also, this is huge performance/response time boost
|
||||||
const blockedResourceTypes = [
|
const blockedResourceTypes = ['image', 'media', 'font', 'texttrack', 'object', 'beacon', 'csp_report', 'imageset'];
|
||||||
"image",
|
|
||||||
"media",
|
|
||||||
"font",
|
|
||||||
"texttrack",
|
|
||||||
"object",
|
|
||||||
"beacon",
|
|
||||||
"csp_report",
|
|
||||||
"imageset",
|
|
||||||
];
|
|
||||||
// const whitelist = ["document", "script", "xhr", "fetch"];
|
// const whitelist = ["document", "script", "xhr", "fetch"];
|
||||||
const skippedResources = [
|
const skippedResources = [
|
||||||
"quantserve",
|
'quantserve',
|
||||||
"adzerk",
|
'adzerk',
|
||||||
"doubleclick",
|
'doubleclick',
|
||||||
"adition",
|
'adition',
|
||||||
"exelator",
|
'exelator',
|
||||||
"sharethrough",
|
'sharethrough',
|
||||||
"cdn.api.twitter",
|
'cdn.api.twitter',
|
||||||
"google-analytics",
|
'google-analytics',
|
||||||
"googletagmanager",
|
'googletagmanager',
|
||||||
"google",
|
'google',
|
||||||
"fontawesome",
|
'fontawesome',
|
||||||
"facebook",
|
'facebook',
|
||||||
"analytics",
|
'analytics',
|
||||||
"optimizely",
|
'optimizely',
|
||||||
"clicktale",
|
'clicktale',
|
||||||
"mixpanel",
|
'mixpanel',
|
||||||
"zedo",
|
'zedo',
|
||||||
"clicksor",
|
'clicksor',
|
||||||
"tiqcdn",
|
'tiqcdn'
|
||||||
];
|
];
|
||||||
|
|
||||||
const RENDER_CACHE = new Map();
|
const RENDER_CACHE = new Map();
|
||||||
|
|
||||||
|
async function createBrowser (profilePath): Promise<any> {
|
||||||
|
|
||||||
async function createBrowser(profilePath): Promise<any> {
|
|
||||||
|
|
||||||
let args = [
|
let args = [
|
||||||
'--check-for-update-interval=2592000',
|
'--check-for-update-interval=2592000',
|
||||||
'--disable-accelerated-2d-canvas',
|
'--disable-accelerated-2d-canvas',
|
||||||
|
|
@ -101,12 +88,12 @@ async function createBrowser(profilePath): Promise<any> {
|
||||||
if (profilePath) {
|
if (profilePath) {
|
||||||
args.push(`--user-data-dir=${profilePath}`);
|
args.push(`--user-data-dir=${profilePath}`);
|
||||||
|
|
||||||
const preferences = urljoin(profilePath, "Default", "Preferences");
|
const preferences = urljoin(profilePath, 'Default', 'Preferences');
|
||||||
if (Fs.existsSync(preferences)) {
|
if (Fs.existsSync(preferences)) {
|
||||||
const file = Fs.readFileSync(preferences, "utf8")
|
const file = Fs.readFileSync(preferences, 'utf8');
|
||||||
const data = JSON.parse(file)
|
const data = JSON.parse(file);
|
||||||
data["profile"]['exit_type'] = "none";
|
data['profile']['exit_type'] = 'none';
|
||||||
Fs.writeFileSync(preferences, JSON.stringify(data))
|
Fs.writeFileSync(preferences, JSON.stringify(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,14 +101,13 @@ async function createBrowser(profilePath): Promise<any> {
|
||||||
args: args,
|
args: args,
|
||||||
ignoreHTTPSErrors: true,
|
ignoreHTTPSErrors: true,
|
||||||
headless: false,
|
headless: false,
|
||||||
devTools: false,
|
|
||||||
defaultViewport: null,
|
defaultViewport: null,
|
||||||
ignoreDefaultArgs: ["--enable-automation", "--enable-blink-features=IdleDetection"]
|
ignoreDefaultArgs: ['--enable-automation', '--enable-blink-features=IdleDetection']
|
||||||
});
|
});
|
||||||
return browser;
|
return browser;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function recursiveFindInFrames(inputFrame, selector) {
|
async function recursiveFindInFrames (inputFrame, selector) {
|
||||||
const frames = inputFrame.childFrames();
|
const frames = inputFrame.childFrames();
|
||||||
const results = await Promise.all(
|
const results = await Promise.all(
|
||||||
frames.map(async frame => {
|
frames.map(async frame => {
|
||||||
|
|
@ -136,25 +122,19 @@ async function recursiveFindInFrames(inputFrame, selector) {
|
||||||
return results.find(Boolean);
|
return results.find(Boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://developers.google.com/web/tools/puppeteer/articles/ssr#reuseinstance
|
* https://developers.google.com/web/tools/puppeteer/articles/ssr#reuseinstance
|
||||||
* @param {string} url URL to prerender.
|
* @param {string} url URL to prerender.
|
||||||
*/
|
*/
|
||||||
async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
async function ssr (url: string, useCache: boolean, cacheRefreshRate: number) {
|
||||||
if (RENDER_CACHE.has(url) && useCache) {
|
if (RENDER_CACHE.has(url) && useCache) {
|
||||||
const cached = RENDER_CACHE.get(url);
|
const cached = RENDER_CACHE.get(url);
|
||||||
if (
|
if (Date.now() - cached.renderedAt > cacheRefreshRate && !(cacheRefreshRate <= 0)) {
|
||||||
Date.now() - cached.renderedAt > cacheRefreshRate &&
|
|
||||||
!(cacheRefreshRate <= 0)
|
|
||||||
) {
|
|
||||||
RENDER_CACHE.delete(url);
|
RENDER_CACHE.delete(url);
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
html: cached.html,
|
html: cached.html,
|
||||||
status: 200,
|
status: 200
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -164,14 +144,17 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
||||||
try {
|
try {
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
await page.setUserAgent(
|
await page.setUserAgent(
|
||||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
|
||||||
);
|
);
|
||||||
await page.setRequestInterception(true);
|
await page.setRequestInterception(true);
|
||||||
page.on("request", (request) => {
|
page.on('request', request => {
|
||||||
const requestUrl = request.url().split("?")[0].split("#")[0];
|
const requestUrl = request
|
||||||
|
.url()
|
||||||
|
.split('?')[0]
|
||||||
|
.split('#')[0];
|
||||||
if (
|
if (
|
||||||
blockedResourceTypes.indexOf(request.resourceType()) !== -1 ||
|
blockedResourceTypes.indexOf(request.resourceType()) !== -1 ||
|
||||||
skippedResources.some((resource) => requestUrl.indexOf(resource) !== -1)
|
skippedResources.some(resource => requestUrl.indexOf(resource) !== -1)
|
||||||
) {
|
) {
|
||||||
request.abort();
|
request.abort();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -179,10 +162,10 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
page.on("response", async (resp) => {
|
page.on('response', async resp => {
|
||||||
const responseUrl = resp.url();
|
const responseUrl = resp.url();
|
||||||
const sameOrigin = new URL(responseUrl).origin === new URL(url).origin;
|
const sameOrigin = new URL(responseUrl).origin === new URL(url).origin;
|
||||||
const isStylesheet = resp.request().resourceType() === "stylesheet";
|
const isStylesheet = resp.request().resourceType() === 'stylesheet';
|
||||||
if (sameOrigin && isStylesheet) {
|
if (sameOrigin && isStylesheet) {
|
||||||
stylesheetContents[responseUrl] = await resp.text();
|
stylesheetContents[responseUrl] = await resp.text();
|
||||||
}
|
}
|
||||||
|
|
@ -190,7 +173,7 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
||||||
|
|
||||||
const response = await page.goto(url, {
|
const response = await page.goto(url, {
|
||||||
timeout: 120000,
|
timeout: 120000,
|
||||||
waitUntil: "networkidle0",
|
waitUntil: 'networkidle0'
|
||||||
});
|
});
|
||||||
|
|
||||||
const sleep = ms => {
|
const sleep = ms => {
|
||||||
|
|
@ -201,8 +184,8 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
||||||
await sleep(45000);
|
await sleep(45000);
|
||||||
|
|
||||||
// Inject <base> on page to relative resources load properly.
|
// Inject <base> on page to relative resources load properly.
|
||||||
await page.evaluate((url) => {
|
await page.evaluate(url => {
|
||||||
const base = document.createElement("base");
|
const base = document.createElement('base');
|
||||||
base.href = url;
|
base.href = url;
|
||||||
// Add to top of head, before all other resources.
|
// Add to top of head, before all other resources.
|
||||||
document.head.prepend(base);
|
document.head.prepend(base);
|
||||||
|
|
@ -211,7 +194,7 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
||||||
// Remove scripts and html imports. They've already executed.
|
// Remove scripts and html imports. They've already executed.
|
||||||
await page.evaluate(() => {
|
await page.evaluate(() => {
|
||||||
const elements = document.querySelectorAll('script, link[rel="import"]');
|
const elements = document.querySelectorAll('script, link[rel="import"]');
|
||||||
elements.forEach((e) => {
|
elements.forEach(e => {
|
||||||
e.remove();
|
e.remove();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -223,7 +206,7 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
||||||
links.forEach((link: any) => {
|
links.forEach((link: any) => {
|
||||||
const cssText = content[link.href];
|
const cssText = content[link.href];
|
||||||
if (cssText) {
|
if (cssText) {
|
||||||
const style = document.createElement("style");
|
const style = document.createElement('style');
|
||||||
style.textContent = cssText;
|
style.textContent = cssText;
|
||||||
link.replaceWith(style);
|
link.replaceWith(style);
|
||||||
}
|
}
|
||||||
|
|
@ -249,7 +232,7 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearCache() {
|
function clearCache () {
|
||||||
RENDER_CACHE.clear();
|
RENDER_CACHE.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -260,7 +243,7 @@ interface Options {
|
||||||
cacheRefreshRate?: number;
|
cacheRefreshRate?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ssrForBots(
|
function ssrForBots (
|
||||||
options: Options = {
|
options: Options = {
|
||||||
prerender: [], // Array containing the user-agents that will trigger the ssr service
|
prerender: [], // Array containing the user-agents that will trigger the ssr service
|
||||||
exclude: [], // Array containing paths and/or extentions that will be excluded from being prerendered by the ssr service
|
exclude: [], // Array containing paths and/or extentions that will be excluded from being prerendered by the ssr service
|
||||||
|
|
@ -280,52 +263,51 @@ function ssrForBots(
|
||||||
|
|
||||||
// Default user agents
|
// Default user agents
|
||||||
const prerenderArray = [
|
const prerenderArray = [
|
||||||
"bot",
|
'bot',
|
||||||
"googlebot",
|
'googlebot',
|
||||||
"Chrome-Lighthouse",
|
'Chrome-Lighthouse',
|
||||||
"DuckDuckBot",
|
'DuckDuckBot',
|
||||||
"ia_archiver",
|
'ia_archiver',
|
||||||
"bingbot",
|
'bingbot',
|
||||||
"yandex",
|
'yandex',
|
||||||
"baiduspider",
|
'baiduspider',
|
||||||
"Facebot",
|
'Facebot',
|
||||||
"facebookexternalhit",
|
'facebookexternalhit',
|
||||||
"facebookexternalhit/1.1",
|
'facebookexternalhit/1.1',
|
||||||
"twitterbot",
|
'twitterbot',
|
||||||
"rogerbot",
|
'rogerbot',
|
||||||
"linkedinbot",
|
'linkedinbot',
|
||||||
"embedly",
|
'embedly',
|
||||||
"quora link preview",
|
'quora link preview',
|
||||||
"showyoubot",
|
'showyoubot',
|
||||||
"outbrain",
|
'outbrain',
|
||||||
"pinterest",
|
'pinterest',
|
||||||
"slackbot",
|
'slackbot',
|
||||||
"vkShare",
|
'vkShare',
|
||||||
"W3C_Validator",
|
'W3C_Validator'
|
||||||
];
|
];
|
||||||
|
|
||||||
// default exclude array
|
// default exclude array
|
||||||
const excludeArray = [".xml", ".ico", ".txt", ".json"];
|
const excludeArray = ['.xml', '.ico', '.txt', '.json'];
|
||||||
|
|
||||||
function ssrOnDemand(req: Request, res: Response, next: NextFunction) {
|
function ssrOnDemand (req: Request, res: Response, next: NextFunction) {
|
||||||
Promise.resolve(() => {
|
Promise.resolve(() => {
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
const userAgent: string = req.headers["user-agent"] || "";
|
const userAgent: string = req.headers['user-agent'] || '';
|
||||||
|
|
||||||
const prerender = new RegExp(
|
const prerender = new RegExp([...prerenderArray, ...applyOptions.prerender].join('|').slice(0, -1), 'i').test(
|
||||||
[...prerenderArray, ...applyOptions.prerender].join("|").slice(0, -1),
|
userAgent
|
||||||
"i"
|
);
|
||||||
).test(userAgent);
|
|
||||||
|
|
||||||
const exclude = !new RegExp(
|
const exclude = !new RegExp([...excludeArray, ...applyOptions.exclude].join('|').slice(0, -1)).test(
|
||||||
[...excludeArray, ...applyOptions.exclude].join("|").slice(0, -1)
|
req.originalUrl
|
||||||
).test(req.originalUrl);
|
);
|
||||||
|
|
||||||
if (req.originalUrl && prerender && exclude) {
|
if (req.originalUrl && prerender && exclude) {
|
||||||
const { html, status } = await ssr(
|
const { html, status } = await ssr(
|
||||||
req.protocol + "://" + req.get("host") + req.originalUrl,
|
req.protocol + '://' + req.get('host') + req.originalUrl,
|
||||||
applyOptions.useCache,
|
applyOptions.useCache,
|
||||||
applyOptions.cacheRefreshRate
|
applyOptions.cacheRefreshRate
|
||||||
);
|
);
|
||||||
|
|
@ -340,5 +322,4 @@ function ssrForBots(
|
||||||
return ssrOnDemand;
|
return ssrOnDemand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export { createBrowser, ssr, clearCache, ssrForBots };
|
export { createBrowser, ssr, clearCache, ssrForBots };
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
export const Messages = {
|
export const Messages = {
|
||||||
global_quit: /^(\bsair\b|\bsai\b|\bchega\b|\bexit\b|\bquit\b|\bfinish\b|\bend\b|\bausfahrt\b|\bverlassen\b)/i,
|
global_quit: /^(\bsair\b|\bsai\b|\bchega\b|\bexit\b|\bquit\b|\bfinish\b|\bend\b|\bausfahrt\b|\bverlassen\b)/i,
|
||||||
'en-US': {
|
'en-US': {
|
||||||
|
|
@ -6,23 +5,22 @@ export const Messages = {
|
||||||
good_morning: 'good morning',
|
good_morning: 'good morning',
|
||||||
good_evening: 'good evening',
|
good_evening: 'good evening',
|
||||||
good_night: 'good night',
|
good_night: 'good night',
|
||||||
hi: (msg) => `Hello, ${msg}.`,
|
hi: msg => `Hello, ${msg}.`,
|
||||||
very_sorry_about_error: `I'm sorry to inform that there was an error which was recorded to be solved.`,
|
very_sorry_about_error: `I'm sorry to inform that there was an error which was recorded to be solved.`,
|
||||||
canceled: 'Canceled. If I can be useful, let me know how',
|
canceled: 'Canceled. If I can be useful, let me know how',
|
||||||
whats_email: 'What\'s your E-mail address?',
|
whats_email: "What's your E-mail address?",
|
||||||
which_language: 'Please, type the language name you would like to talk through.',
|
which_language: 'Please, type the language name you would like to talk through.',
|
||||||
validation_enter_valid_email: 'Please enter a valid e-mail.',
|
validation_enter_valid_email: 'Please enter a valid e-mail.',
|
||||||
language_chosen: 'Very good, so let\'s go...',
|
language_chosen: "Very good, so let's go...",
|
||||||
affirmative_sentences: /^(\bsim\b|\bs\b|\bpositivo\b|\bafirmativo\b|\bclaro\b|\bevidente\b|\bsem dúvida\b|\bconfirmo\b|\bconfirmar\b|\bconfirmado\b|\buhum\b|\bsi\b|\by\b|\byes\b|\bsure\b)/i,
|
affirmative_sentences: /^(\bsim\b|\bs\b|\bpositivo\b|\bafirmativo\b|\bclaro\b|\bevidente\b|\bsem dúvida\b|\bconfirmo\b|\bconfirmar\b|\bconfirmado\b|\buhum\b|\bsi\b|\by\b|\byes\b|\bsure\b)/i,
|
||||||
will_answer_projector:
|
will_answer_projector: "I'll answer on the projector to a better experience..."
|
||||||
'I\'ll answer on the projector to a better experience...',
|
|
||||||
},
|
},
|
||||||
'pt-BR': {
|
'pt-BR': {
|
||||||
show_video: 'Vou te mostrar um vídeo. Por favor, aguarde...',
|
show_video: 'Vou te mostrar um vídeo. Por favor, aguarde...',
|
||||||
good_morning: 'bom dia',
|
good_morning: 'bom dia',
|
||||||
good_evening: 'boa tarde',
|
good_evening: 'boa tarde',
|
||||||
good_night: 'boa noite',
|
good_night: 'boa noite',
|
||||||
hi: (msg) => `Oi, ${msg}.`,
|
hi: msg => `Oi, ${msg}.`,
|
||||||
very_sorry_about_error: `Lamento, ocorreu um erro que já foi registrado para ser tratado.`,
|
very_sorry_about_error: `Lamento, ocorreu um erro que já foi registrado para ser tratado.`,
|
||||||
canceled: 'Cancelado, avise como posso ser útil novamente.',
|
canceled: 'Cancelado, avise como posso ser útil novamente.',
|
||||||
whats_email: 'Qual seu e-mail?',
|
whats_email: 'Qual seu e-mail?',
|
||||||
|
|
@ -30,8 +28,6 @@ export const Messages = {
|
||||||
validation_enter_valid_email: 'Por favor digite um email válido.',
|
validation_enter_valid_email: 'Por favor digite um email válido.',
|
||||||
language_chosen: 'Muito bem, então vamos lá...',
|
language_chosen: 'Muito bem, então vamos lá...',
|
||||||
affirmative_sentences: /^(\bsim\b|\bs\b|\bpositivo\b|\bafirmativo\b|\bclaro\b|\bevidente\b|\bsem dúvida\b|\bconfirmo\b|\bconfirmar\b|\bconfirmado\b|\buhum\b|\bsi\b|\by\b|\byes\b|\bsure\b)/i,
|
affirmative_sentences: /^(\bsim\b|\bs\b|\bpositivo\b|\bafirmativo\b|\bclaro\b|\bevidente\b|\bsem dúvida\b|\bconfirmo\b|\bconfirmar\b|\bconfirmado\b|\buhum\b|\bsi\b|\by\b|\byes\b|\bsure\b)/i,
|
||||||
will_answer_projector:
|
will_answer_projector: 'Vou te responder na tela para melhor visualização...'
|
||||||
'Vou te responder na tela para melhor visualização...',
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,11 @@
|
||||||
import { BotAdapter } from 'botbuilder';
|
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 { GBMinService } from '../../core.gbapp/services/GBMinService';
|
import { GBMinService } from '../../core.gbapp/services/GBMinService.js';
|
||||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
|
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService.js';
|
||||||
import { SecService } from '../../security.gbapp/services/SecService';
|
import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||||
import { CSService } from '../services/CSService';
|
import { CSService } from '../services/CSService.js';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog for feedback collecting.
|
* Dialog for feedback collecting.
|
||||||
|
|
@ -55,7 +55,7 @@ export class FeedbackDialog extends IGBDialog {
|
||||||
* @param bot The bot adapter.
|
* @param bot The bot adapter.
|
||||||
* @param min The minimal bot instance data.
|
* @param min The minimal bot instance data.
|
||||||
*/
|
*/
|
||||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||||
const service = new CSService();
|
const service = new CSService();
|
||||||
|
|
||||||
min.dialogs.add(
|
min.dialogs.add(
|
||||||
|
|
@ -74,13 +74,11 @@ export class FeedbackDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async step => {
|
async step => {
|
||||||
|
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
const sec = new SecService();
|
const sec = new SecService();
|
||||||
let from = GBMinService.userMobile(step);
|
let from = GBMinService.userMobile(step);
|
||||||
|
|
@ -90,40 +88,39 @@ export class FeedbackDialog extends IGBDialog {
|
||||||
// Transfer to...
|
// Transfer to...
|
||||||
|
|
||||||
if (args && args.to) {
|
if (args && args.to) {
|
||||||
|
|
||||||
// An user from Teams willing to transfer to a WhatsApp user.
|
// An user from Teams willing to transfer to a WhatsApp user.
|
||||||
|
|
||||||
await sec.ensureUser(min.instance.instanceId, args.to,
|
await sec.ensureUser(min.instance.instanceId, args.to, 'Name', '', 'whatsapp', 'Name', null);
|
||||||
'Name', '', 'whatsapp', 'Name', null);
|
|
||||||
|
|
||||||
await sec.assignHumanAgent(min, args.to, profile.systemUser.userSystemId);
|
await sec.assignHumanAgent(min, args.to, profile.systemUser.userSystemId);
|
||||||
await min.conversationalService.sendText(min, step,
|
await min.conversationalService.sendText(
|
||||||
Messages[locale].notify_agent_transfer_done(min.instance.botId));
|
min,
|
||||||
|
step,
|
||||||
}
|
Messages[locale].notify_agent_transfer_done(min.instance.botId)
|
||||||
else {
|
);
|
||||||
|
} else {
|
||||||
|
|
||||||
await min.conversationalService.sendText(min, step, Messages[locale].please_wait_transfering);
|
await min.conversationalService.sendText(min, step, Messages[locale].please_wait_transfering);
|
||||||
const agentSystemId = await sec.assignHumanAgent(min, from);
|
const agentSystemId = await sec.assignHumanAgent(min, from);
|
||||||
profile.systemUser = await sec.getUserFromAgentSystemId(agentSystemId);
|
profile.systemUser = await sec.getUserFromAgentSystemId(agentSystemId);
|
||||||
await min.userProfile.set(step.context, profile);
|
await min.userProfile.set(step.context, profile);
|
||||||
|
|
||||||
if (agentSystemId.charAt(2) === ":" || agentSystemId.indexOf("@") > -1) { // Agent is from Teams or Google Chat.
|
if (agentSystemId.charAt(2) === ':' || agentSystemId.indexOf('@') > -1) {
|
||||||
|
// Agent is from Teams or Google Chat.
|
||||||
|
|
||||||
const agent = await sec.getUserFromSystemId(agentSystemId);
|
const agent = await sec.getUserFromSystemId(agentSystemId);
|
||||||
await min.conversationalService['sendOnConversation'](min, agent,
|
await min.conversationalService['sendOnConversation'](
|
||||||
Messages[locale].notify_agent(step.context.activity.from.name));
|
min,
|
||||||
|
agent,
|
||||||
}
|
Messages[locale].notify_agent(step.context.activity.from.name)
|
||||||
else {
|
);
|
||||||
|
} else {
|
||||||
await min.whatsAppDirectLine.sendToDevice(agentSystemId, Messages[locale].notify_agent(step.context.activity.from.name));
|
await min.whatsAppDirectLine.sendToDevice(
|
||||||
|
agentSystemId,
|
||||||
|
Messages[locale].notify_agent(step.context.activity.from.name)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return await step.next();
|
return await step.next();
|
||||||
|
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
@ -133,13 +130,11 @@ export class FeedbackDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async step => {
|
async step => {
|
||||||
|
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
|
|
||||||
const sec = new SecService();
|
const sec = new SecService();
|
||||||
|
|
@ -149,16 +144,27 @@ export class FeedbackDialog extends IGBDialog {
|
||||||
if (user.systemUser.agentMode === 'self') {
|
if (user.systemUser.agentMode === 'self') {
|
||||||
const manualUser = await sec.getUserFromAgentSystemId(userSystemId);
|
const manualUser = await sec.getUserFromAgentSystemId(userSystemId);
|
||||||
|
|
||||||
await min.whatsAppDirectLine.sendToDeviceEx(manualUser.userSystemId,
|
await min.whatsAppDirectLine.sendToDeviceEx(
|
||||||
Messages[locale].notify_end_transfer(min.instance.botId), locale, step.context.activity.conversation.id);
|
manualUser.userSystemId,
|
||||||
|
Messages[locale].notify_end_transfer(min.instance.botId),
|
||||||
|
locale,
|
||||||
|
step.context.activity.conversation.id
|
||||||
|
);
|
||||||
|
|
||||||
if (userSystemId.charAt(2) === ":" || userSystemId.indexOf('@') > -1) { // Agent is from Teams or Google Chat.
|
if (userSystemId.charAt(2) === ':' || userSystemId.indexOf('@') > -1) {
|
||||||
await min.conversationalService.sendText(min, step, Messages[locale].notify_end_transfer(min.instance.botId));
|
// Agent is from Teams or Google Chat.
|
||||||
}
|
await min.conversationalService.sendText(
|
||||||
else {
|
min,
|
||||||
await min.whatsAppDirectLine.sendToDeviceEx(userSystemId,
|
step,
|
||||||
Messages[locale].notify_end_transfer(min.instance.botId), locale
|
Messages[locale].notify_end_transfer(min.instance.botId)
|
||||||
, step.context.activity.conversation.id);
|
);
|
||||||
|
} else {
|
||||||
|
await min.whatsAppDirectLine.sendToDeviceEx(
|
||||||
|
userSystemId,
|
||||||
|
Messages[locale].notify_end_transfer(min.instance.botId),
|
||||||
|
locale,
|
||||||
|
step.context.activity.conversation.id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await sec.updateHumanAgent(userSystemId, min.instance.instanceId, null);
|
await sec.updateHumanAgent(userSystemId, min.instance.instanceId, null);
|
||||||
|
|
@ -166,22 +172,30 @@ export class FeedbackDialog extends IGBDialog {
|
||||||
|
|
||||||
user.systemUser = await sec.getUserFromSystemId(userSystemId);
|
user.systemUser = await sec.getUserFromSystemId(userSystemId);
|
||||||
await min.userProfile.set(step.context, user);
|
await min.userProfile.set(step.context, user);
|
||||||
|
} else if (user.systemUser.agentMode === 'human') {
|
||||||
}
|
|
||||||
|
|
||||||
else if (user.systemUser.agentMode === 'human') {
|
|
||||||
const agent = await sec.getUserFromSystemId(user.systemUser.agentSystemId);
|
const agent = await sec.getUserFromSystemId(user.systemUser.agentSystemId);
|
||||||
|
|
||||||
await min.whatsAppDirectLine.sendToDeviceEx(user.systemUser.userSystemId,
|
await min.whatsAppDirectLine.sendToDeviceEx(
|
||||||
Messages[locale].notify_end_transfer(min.instance.botId), locale, step.context.activity.conversation.id);
|
user.systemUser.userSystemId,
|
||||||
|
Messages[locale].notify_end_transfer(min.instance.botId),
|
||||||
|
locale,
|
||||||
|
step.context.activity.conversation.id
|
||||||
|
);
|
||||||
|
|
||||||
|
if (user.systemUser.agentSystemId.charAt(2) === ':' || userSystemId.indexOf('@') > -1) {
|
||||||
if (user.systemUser.agentSystemId.charAt(2) === ":" || userSystemId.indexOf('@') > -1) { // Agent is from Teams or Google Chat.
|
// Agent is from Teams or Google Chat.
|
||||||
await min.conversationalService.sendText(min, step, Messages[locale].notify_end_transfer(min.instance.botId));
|
await min.conversationalService.sendText(
|
||||||
}
|
min,
|
||||||
else {
|
step,
|
||||||
await min.whatsAppDirectLine.sendToDeviceEx(user.systemUser.agentSystemId,
|
Messages[locale].notify_end_transfer(min.instance.botId)
|
||||||
Messages[locale].notify_end_transfer(min.instance.botId), locale, step.context.activity.conversation.id);
|
);
|
||||||
|
} else {
|
||||||
|
await min.whatsAppDirectLine.sendToDeviceEx(
|
||||||
|
user.systemUser.agentSystemId,
|
||||||
|
Messages[locale].notify_end_transfer(min.instance.botId),
|
||||||
|
locale,
|
||||||
|
step.context.activity.conversation.id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await sec.updateHumanAgent(user.systemUser.userSystemId, min.instance.instanceId, null);
|
await sec.updateHumanAgent(user.systemUser.userSystemId, min.instance.instanceId, null);
|
||||||
|
|
@ -189,15 +203,17 @@ export class FeedbackDialog extends IGBDialog {
|
||||||
|
|
||||||
user.systemUser = await sec.getUserFromSystemId(userSystemId);
|
user.systemUser = await sec.getUserFromSystemId(userSystemId);
|
||||||
await min.userProfile.set(step.context, user);
|
await min.userProfile.set(step.context, user);
|
||||||
|
} else {
|
||||||
}
|
if (user.systemUser.userSystemId.charAt(2) === ':' || userSystemId.indexOf('@') > -1) {
|
||||||
else {
|
// Agent is from Teams or Google Chat.
|
||||||
if (user.systemUser.userSystemId.charAt(2) === ":" || userSystemId.indexOf('@') > -1) { // Agent is from Teams or Google Chat.
|
|
||||||
await min.conversationalService.sendText(min, step, 'Nenhum atendimento em andamento.');
|
await min.conversationalService.sendText(min, step, 'Nenhum atendimento em andamento.');
|
||||||
}
|
} else {
|
||||||
else {
|
await min.whatsAppDirectLine.sendToDeviceEx(
|
||||||
await min.whatsAppDirectLine.sendToDeviceEx(user.systemUser.userSystemId,
|
user.systemUser.userSystemId,
|
||||||
'Nenhum atendimento em andamento.', locale, step.context.activity.conversation.id);
|
'Nenhum atendimento em andamento.',
|
||||||
|
locale,
|
||||||
|
step.context.activity.conversation.id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -211,8 +227,7 @@ export class FeedbackDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -238,8 +253,7 @@ export class FeedbackDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -259,14 +273,20 @@ export class FeedbackDialog extends IGBDialog {
|
||||||
|
|
||||||
const analytics = new AnalyticsService();
|
const analytics = new AnalyticsService();
|
||||||
const rate = await analytics.updateConversationSuggestion(
|
const rate = await analytics.updateConversationSuggestion(
|
||||||
min.instance.instanceId, user.conversation.conversationId, step.result, user.systemUser.locale);
|
min.instance.instanceId,
|
||||||
|
user.conversation.conversationId,
|
||||||
|
step.result,
|
||||||
|
user.systemUser.locale
|
||||||
|
);
|
||||||
|
|
||||||
if (rate > 0.5) {
|
if (rate > 0.5) {
|
||||||
await min.conversationalService.sendText(min, step, Messages[fixedLocale].glad_you_liked);
|
await min.conversationalService.sendText(min, step, Messages[fixedLocale].glad_you_liked);
|
||||||
} else {
|
} else {
|
||||||
|
const message = min.core.getParam<string>(
|
||||||
const message = min.core.getParam<string>(min.instance, 'Feedback Improve Message',
|
min.instance,
|
||||||
Messages[fixedLocale].we_will_improve); // TODO: Improve to be multi-language.
|
'Feedback Improve Message',
|
||||||
|
Messages[fixedLocale].we_will_improve
|
||||||
|
); // TODO: Improve to be multi-language.
|
||||||
|
|
||||||
await min.conversationalService.sendText(min, step, message);
|
await min.conversationalService.sendText(min, step, message);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,10 @@ import { GBMinInstance, IGBDialog } from 'botlib';
|
||||||
|
|
||||||
import { BotAdapter } from 'botbuilder';
|
import { BotAdapter } from 'botbuilder';
|
||||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
|
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService.js';
|
||||||
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
|
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService.js';
|
||||||
import { CSService } from '../services/CSService';
|
import { CSService } from '../services/CSService.js';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog for collecting quality of answer.
|
* Dialog for collecting quality of answer.
|
||||||
|
|
@ -55,19 +55,21 @@ export class QualityDialog extends IGBDialog {
|
||||||
* @param bot The bot adapter.
|
* @param bot The bot adapter.
|
||||||
* @param min The minimal bot instance data.
|
* @param min The minimal bot instance data.
|
||||||
*/
|
*/
|
||||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||||
const service = new CSService();
|
const service = new CSService();
|
||||||
|
|
||||||
min.dialogs.add(new WaterfallDialog('/check', [
|
min.dialogs.add(
|
||||||
|
new WaterfallDialog('/check', [
|
||||||
async step => {
|
async step => {
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
await min.conversationalService.sendText(min, step, Messages[locale].check_whatsapp_ok);
|
await min.conversationalService.sendText(min, step, Messages[locale].check_whatsapp_ok);
|
||||||
return await step.replaceDialog('/ask', { isReturning: true });
|
return await step.replaceDialog('/ask', { isReturning: true });
|
||||||
}
|
}
|
||||||
]
|
])
|
||||||
));
|
);
|
||||||
|
|
||||||
min.dialogs.add(new WaterfallDialog('/quality', [
|
min.dialogs.add(
|
||||||
|
new WaterfallDialog('/quality', [
|
||||||
async step => {
|
async step => {
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
const user = await min.userProfile.get(step.context, {});
|
const user = await min.userProfile.get(step.context, {});
|
||||||
|
|
@ -83,7 +85,7 @@ export class QualityDialog extends IGBDialog {
|
||||||
await min.conversationalService.sendEvent(min, step, 'play', {
|
await min.conversationalService.sendEvent(min, step, 'play', {
|
||||||
playerType: 'markdown',
|
playerType: 'markdown',
|
||||||
data: {
|
data: {
|
||||||
content: Messages[locale].great_thanks,
|
content: Messages[locale].great_thanks
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let sleep = ms => {
|
let sleep = ms => {
|
||||||
|
|
@ -92,23 +94,24 @@ export class QualityDialog extends IGBDialog {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
await service.insertQuestionAlternate(
|
await service.insertQuestionAlternate(min.instance.instanceId, user.lastQuestion, user.lastQuestionId);
|
||||||
min.instance.instanceId,
|
|
||||||
user.lastQuestion,
|
|
||||||
user.lastQuestionId
|
|
||||||
);
|
|
||||||
|
|
||||||
// Updates values to perform Bot Analytics.
|
// Updates values to perform Bot Analytics.
|
||||||
|
|
||||||
const analytics = new AnalyticsService();
|
const analytics = new AnalyticsService();
|
||||||
analytics.updateConversationSuggestion(
|
analytics.updateConversationSuggestion(
|
||||||
min.instance.instanceId, user.conversation, step.result, user.systemUser.locale);
|
min.instance.instanceId,
|
||||||
|
user.conversation,
|
||||||
|
step.result,
|
||||||
|
user.systemUser.locale
|
||||||
|
);
|
||||||
|
|
||||||
// Goes to the ask loop.
|
// Goes to the ask loop.
|
||||||
|
|
||||||
return await step.replaceDialog('/ask', { emptyPrompt: true });
|
return await step.replaceDialog('/ask', { emptyPrompt: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]));
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,10 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||||
const urlJoin = require('url-join');
|
import urlJoin from 'url-join';
|
||||||
import { FeedbackDialog } from './dialogs/FeedbackDialog';
|
import { FeedbackDialog } from './dialogs/FeedbackDialog.js';
|
||||||
import { QualityDialog } from './dialogs/QualityDialog';
|
import { QualityDialog } from './dialogs/QualityDialog.js';
|
||||||
import { GuaribasQuestionAlternate } from './models/index';
|
import { GuaribasQuestionAlternate } from './models/index.js';
|
||||||
|
|
||||||
import { Sequelize } from 'sequelize-typescript';
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
|
|
||||||
|
|
@ -49,26 +49,26 @@ import { Sequelize } from 'sequelize-typescript';
|
||||||
*/
|
*/
|
||||||
export class GBCustomerSatisfactionPackage implements IGBPackage {
|
export class GBCustomerSatisfactionPackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
public async getDialogs(min: GBMinInstance) {
|
public async getDialogs (min: GBMinInstance) {
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
core.sequelize.addModels([GuaribasQuestionAlternate]);
|
core.sequelize.addModels([GuaribasQuestionAlternate]);
|
||||||
}
|
}
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {
|
||||||
FeedbackDialog.setup(min.bot, min);
|
FeedbackDialog.setup(min.bot, min);
|
||||||
QualityDialog.setup(min.bot, min);
|
QualityDialog.setup(min.bot, min);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,40 +36,30 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import {
|
import { AutoIncrement, BelongsTo, Column, DataType, ForeignKey, Model, PrimaryKey, Table } from 'sequelize-typescript';
|
||||||
AutoIncrement,
|
|
||||||
BelongsTo,
|
|
||||||
Column,
|
|
||||||
DataType,
|
|
||||||
ForeignKey,
|
|
||||||
Model,
|
|
||||||
PrimaryKey,
|
|
||||||
Table
|
|
||||||
} from 'sequelize-typescript';
|
|
||||||
|
|
||||||
import { GuaribasInstance } from '../../core.gbapp/models/GBModel';
|
import { GuaribasInstance } from '../../core.gbapp/models/GBModel.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of saved alternate questions.
|
* List of saved alternate questions.
|
||||||
*/
|
*/
|
||||||
@Table
|
@Table
|
||||||
export class GuaribasQuestionAlternate extends Model<GuaribasQuestionAlternate> {
|
export class GuaribasQuestionAlternate extends Model<GuaribasQuestionAlternate> {
|
||||||
|
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public quickAnswerId: number;
|
quickAnswerId: number;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public questionTyped: string;
|
questionTyped: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public questionText: string;
|
questionText: string;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
instanceId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
public instance: GuaribasInstance;
|
instance: GuaribasInstance;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,19 +31,15 @@
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
||||||
import { FindOptions, NonNullFindOptions } from 'sequelize/types';
|
import { FindOptions, NonNullFindOptions } from 'sequelize/types';
|
||||||
import { GuaribasQuestion } from '../../../packages/kb.gbapp/models';
|
import { GuaribasQuestion } from '../../../packages/kb.gbapp/models/index.js';
|
||||||
import { GuaribasConversation } from '../../analytics.gblib/models';
|
import { GuaribasConversation } from '../../analytics.gblib/models/index.js';
|
||||||
import { GuaribasQuestionAlternate } from '../models';
|
import { GuaribasQuestionAlternate } from '../models/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customer Satisfaction Service Layer.
|
* Customer Satisfaction Service Layer.
|
||||||
*/
|
*/
|
||||||
export class CSService {
|
export class CSService {
|
||||||
|
public async getQuestionFromAlternateText (instanceId: number, text: string): Promise<GuaribasQuestion> {
|
||||||
public async getQuestionFromAlternateText(
|
|
||||||
instanceId: number,
|
|
||||||
text: string): Promise<GuaribasQuestion> {
|
|
||||||
|
|
||||||
const questionAlternate = await GuaribasQuestionAlternate.findOne({
|
const questionAlternate = await GuaribasQuestionAlternate.findOne({
|
||||||
where: {
|
where: {
|
||||||
instanceId: instanceId,
|
instanceId: instanceId,
|
||||||
|
|
@ -54,7 +50,6 @@ export class CSService {
|
||||||
let question: GuaribasQuestion = null;
|
let question: GuaribasQuestion = null;
|
||||||
|
|
||||||
if (questionAlternate !== null) {
|
if (questionAlternate !== null) {
|
||||||
|
|
||||||
question = await GuaribasQuestion.findOne({
|
question = await GuaribasQuestion.findOne({
|
||||||
where: {
|
where: {
|
||||||
instanceId: instanceId,
|
instanceId: instanceId,
|
||||||
|
|
@ -66,17 +61,18 @@ export class CSService {
|
||||||
return question;
|
return question;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async insertQuestionAlternate(
|
public async insertQuestionAlternate (
|
||||||
instanceId: number,
|
instanceId: number,
|
||||||
questionTyped: string,
|
questionTyped: string,
|
||||||
questionText: string): Promise<GuaribasQuestionAlternate> {
|
questionText: string
|
||||||
|
): Promise<GuaribasQuestionAlternate> {
|
||||||
return await GuaribasQuestionAlternate.create(<GuaribasQuestionAlternate>{
|
return await GuaribasQuestionAlternate.create(<GuaribasQuestionAlternate>{
|
||||||
questionTyped: questionTyped,
|
questionTyped: questionTyped,
|
||||||
questionText: questionText
|
questionText: questionText
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateConversationRate(
|
public async updateConversationRate (
|
||||||
conversation: GuaribasConversation,
|
conversation: GuaribasConversation,
|
||||||
rate: number
|
rate: number
|
||||||
): Promise<GuaribasConversation> {
|
): Promise<GuaribasConversation> {
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
export const Messages = {
|
export const Messages = {
|
||||||
'en-US': {
|
'en-US': {
|
||||||
|
|
||||||
about_suggestions: 'Suggestions are welcomed and improve my quality...',
|
about_suggestions: 'Suggestions are welcomed and improve my quality...',
|
||||||
what_about_service: 'What about my service?',
|
what_about_service: 'What about my service?',
|
||||||
glad_you_liked: 'I\'m glad you liked. I\'m here for you.',
|
glad_you_liked: "I'm glad you liked. I'm here for you.",
|
||||||
we_will_improve: 'Let\'s take note of that, thanks for sharing.',
|
we_will_improve: "Let's take note of that, thanks for sharing.",
|
||||||
what_about_me: 'What about the service, please rate between 1 and 5.',
|
what_about_me: 'What about the service, please rate between 1 and 5.',
|
||||||
thanks: 'Thanks!',
|
thanks: 'Thanks!',
|
||||||
im_sorry_lets_try: 'I\'m sorry. Let\'s try again...',
|
im_sorry_lets_try: "I'm sorry. Let's try again...",
|
||||||
great_thanks: 'Great, thanks for sharing your thoughts.',
|
great_thanks: 'Great, thanks for sharing your thoughts.',
|
||||||
please_no_bad_words: 'Please, no bad words.',
|
please_no_bad_words: 'Please, no bad words.',
|
||||||
please_wait_transfering: 'Please, wait while I find an agent to answer you.',
|
please_wait_transfering: 'Please, wait while I find an agent to answer you.',
|
||||||
notify_agent: (name) => `New call available for *${name}*, you can answer right here when you are finished, type /qt.`,
|
notify_agent: name =>
|
||||||
notify_end_transfer: (botName) => `All messages will be now routed to user ${botName}.`,
|
`New call available for *${name}*, you can answer right here when you are finished, type /qt.`,
|
||||||
notify_agent_transfer_done: (person) => `Now talking directly to ${person}.`,
|
notify_end_transfer: botName => `All messages will be now routed to user ${botName}.`,
|
||||||
check_whatsapp_ok: 'If you are seeing this message, WhatsApp API is OK.',
|
notify_agent_transfer_done: person => `Now talking directly to ${person}.`,
|
||||||
|
check_whatsapp_ok: 'If you are seeing this message, WhatsApp API is OK.'
|
||||||
},
|
},
|
||||||
'pt-BR': {
|
'pt-BR': {
|
||||||
about_suggestions: 'Sugestões melhoram muito minha qualidade...',
|
about_suggestions: 'Sugestões melhoram muito minha qualidade...',
|
||||||
|
|
@ -27,9 +27,10 @@ export const Messages = {
|
||||||
great_thanks: 'Ótimo, obrigado por contribuir com sua resposta.',
|
great_thanks: 'Ótimo, obrigado por contribuir com sua resposta.',
|
||||||
please_no_bad_words: 'Por favor, sem palavrões!',
|
please_no_bad_words: 'Por favor, sem palavrões!',
|
||||||
please_wait_transfering: 'Por favor, aguarde enquanto eu localizo alguém para te atender.',
|
please_wait_transfering: 'Por favor, aguarde enquanto eu localizo alguém para te atender.',
|
||||||
notify_agent: (name) => `Existe um novo atendimento para *${name}*, por favor, responda aqui mesmo para a pessoa. Para finalizar, digite /qt.`,
|
notify_agent: name =>
|
||||||
notify_end_transfer: (botName) => `Falando novamente com o bot ${botName}.`,
|
`Existe um novo atendimento para *${name}*, por favor, responda aqui mesmo para a pessoa. Para finalizar, digite /qt.`,
|
||||||
notify_agent_transfer_done: (person) => `Todas as mensagens agora sendo transmitidas para ${person}.`,
|
notify_end_transfer: botName => `Falando novamente com o bot ${botName}.`,
|
||||||
check_whatsapp_ok: 'Se você está recebendo esta mensagem, significa que a API do WhatsApp está OK.',
|
notify_agent_transfer_done: person => `Todas as mensagens agora sendo transmitidas para ${person}.`,
|
||||||
|
check_whatsapp_ok: 'Se você está recebendo esta mensagem, significa que a API do WhatsApp está OK.'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
38875
packages/default.gbui/package-lock.json
generated
38875
packages/default.gbui/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -7,27 +7,26 @@
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"homepage": ".",
|
"homepage": ".",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@midudev/react-static-content": "^1.0.4",
|
"@midudev/react-static-content": "1.0.4",
|
||||||
"ajv": "^8.6.0",
|
"ajv": "8.11.2",
|
||||||
"botframework-directlinejs": "0.14.1",
|
"botframework-directlinejs": "0.15.1",
|
||||||
"botframework-webchat": "^4.13.0",
|
"botframework-webchat": "4.15.5",
|
||||||
"deep-extend": "0.6.0",
|
"deep-extend": "0.6.0",
|
||||||
"eslint": "7.11.0",
|
"eslint": "8.28.0",
|
||||||
"fetch": "1.1.0",
|
"fetch": "1.1.0",
|
||||||
"msal": "^1.4.11",
|
"msal": "1.4.17",
|
||||||
"powerbi-client": "2.18.0",
|
"powerbi-client": "2.22.0",
|
||||||
"react": "^17.0.2",
|
"react": "18.2.0",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "18.2.0",
|
||||||
"react-helmet": "6.1.0",
|
"react-helmet": "6.1.0",
|
||||||
"react-modern-audio-player": "^1.2.2",
|
"react-player": "2.11.0",
|
||||||
"react-player": "^2.9.0",
|
|
||||||
"react-powerbi": "0.9.1",
|
"react-powerbi": "0.9.1",
|
||||||
"react-scripts": "^4.0.3",
|
"react-scripts": "5.0.1",
|
||||||
"react-super-seo": "^1.0.6",
|
"react-super-seo": "1.0.7",
|
||||||
"react-transition-group": "^4.4.2",
|
"react-transition-group": "4.4.5",
|
||||||
"rxjs": "^7.1.0",
|
"rxjs": "7.5.7",
|
||||||
"url-join": "4.0.1",
|
"url-join": "5.0.0",
|
||||||
"webpack": "4.44.2"
|
"webpack": "5.75.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
|
|
|
||||||
11005
packages/default.gbui/yarn.lock
Normal file
11005
packages/default.gbui/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||||
import { Sequelize } from 'sequelize-typescript';
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
import { GoogleChatDirectLine } from './services/GoogleChatDirectLine';
|
import { GoogleChatDirectLine } from './services/GoogleChatDirectLine.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package for GoogleChat.gblib
|
* Package for GoogleChat.gblib
|
||||||
|
|
@ -46,27 +46,24 @@ import { GoogleChatDirectLine } from './services/GoogleChatDirectLine';
|
||||||
export class GBGoogleChatPackage implements IGBPackage {
|
export class GBGoogleChatPackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
|
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {}
|
||||||
|
|
||||||
}
|
public async getDialogs (min: GBMinInstance) {
|
||||||
|
|
||||||
public async getDialogs(min: GBMinInstance) {
|
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
GBLog.verbose(`loadPackage called.`);
|
GBLog.verbose(`loadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,20 +30,19 @@
|
||||||
| |
|
| |
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
||||||
const Swagger = require('swagger-client');
|
import Swagger from 'swagger-client';
|
||||||
const fs = require('fs');
|
import { google } from 'googleapis';
|
||||||
const { google } = require('googleapis')
|
import { promisify } from 'util';
|
||||||
const { promisify } = require('util');
|
import { PubSub } from '@google-cloud/pubsub';
|
||||||
const { PubSub } = require('@google-cloud/pubsub');
|
import Fs from 'fs';
|
||||||
import { GBLog, GBMinInstance, GBService } from 'botlib';
|
import { GBLog, GBMinInstance, GBService } from 'botlib';
|
||||||
import { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { SecService } from '../../security.gbapp/services/SecService';
|
import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support for Google Chat.
|
* Support for Google Chat.
|
||||||
*/
|
*/
|
||||||
export class GoogleChatDirectLine extends GBService {
|
export class GoogleChatDirectLine extends GBService {
|
||||||
|
|
||||||
public static conversationIds = {};
|
public static conversationIds = {};
|
||||||
public pollInterval = 5000;
|
public pollInterval = 5000;
|
||||||
public directLineClientName = 'DirectLineClient';
|
public directLineClientName = 'DirectLineClient';
|
||||||
|
|
@ -59,7 +58,7 @@ export class GoogleChatDirectLine extends GBService {
|
||||||
GoogleClientPrivateKey: any;
|
GoogleClientPrivateKey: any;
|
||||||
GoogleProjectId: any;
|
GoogleProjectId: any;
|
||||||
|
|
||||||
constructor(
|
constructor (
|
||||||
min: GBMinInstance,
|
min: GBMinInstance,
|
||||||
botId,
|
botId,
|
||||||
directLineSecret,
|
directLineSecret,
|
||||||
|
|
@ -84,20 +83,17 @@ export class GoogleChatDirectLine extends GBService {
|
||||||
projectId: this.GoogleProjectId,
|
projectId: this.GoogleProjectId,
|
||||||
credentials: { client_email: GoogleClientEmail, private_key: GoogleClientPrivateKey }
|
credentials: { client_email: GoogleClientEmail, private_key: GoogleClientPrivateKey }
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async asyncForEach(array, callback) {
|
public static async asyncForEach (array, callback) {
|
||||||
for (let index = 0; index < array.length; index++) {
|
for (let index = 0; index < array.length; index++) {
|
||||||
await callback(array[index], index, array);
|
await callback(array[index], index, array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setup(setUrl) {
|
public async setup (setUrl) {
|
||||||
|
this.directLineClient = new Swagger({
|
||||||
this.directLineClient =
|
spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')),
|
||||||
new Swagger({
|
|
||||||
spec: JSON.parse(fs.readFileSync('directline-3.0.json', 'utf8')),
|
|
||||||
usePromise: true
|
usePromise: true
|
||||||
});
|
});
|
||||||
const client = await this.directLineClient;
|
const client = await this.directLineClient;
|
||||||
|
|
@ -109,29 +105,24 @@ export class GoogleChatDirectLine extends GBService {
|
||||||
|
|
||||||
if (setUrl) {
|
if (setUrl) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const subscription = this.pubSubClient.subscription(this.GoogleChatSubscriptionName);
|
const subscription = this.pubSubClient.subscription(this.GoogleChatSubscriptionName);
|
||||||
subscription.on('message', this.receiver.bind(this));
|
subscription.on('message', this.receiver.bind(this));
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
GBLog.error(`Error initializing 3rd party GoogleChat provider(1) ${error.message}`);
|
GBLog.error(`Error initializing 3rd party GoogleChat provider(1) ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async resetConversationId(key) {
|
public async resetConversationId (key) {
|
||||||
GoogleChatDirectLine.conversationIds[key] = undefined;
|
GoogleChatDirectLine.conversationIds[key] = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async check() {
|
public async check () {
|
||||||
|
|
||||||
GBLog.info(`GBGoogleChat: Checking server...`);
|
GBLog.info(`GBGoogleChat: Checking server...`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Check service.Users.Messages.List("me").
|
// TODO: Check service.Users.Messages.List("me").
|
||||||
public async receiver(message) {
|
public async receiver (message) {
|
||||||
|
|
||||||
const event = JSON.parse(Buffer.from(message.data, 'binary').toString());
|
const event = JSON.parse(Buffer.from(message.data, 'binary').toString());
|
||||||
|
|
||||||
let from = '';
|
let from = '';
|
||||||
|
|
@ -140,7 +131,6 @@ export class GoogleChatDirectLine extends GBService {
|
||||||
const threadName = event.message.thread.name;
|
const threadName = event.message.thread.name;
|
||||||
|
|
||||||
if (event['type'] === 'ADDED_TO_SPACE' && event['space']['singleUserBotDm']) {
|
if (event['type'] === 'ADDED_TO_SPACE' && event['space']['singleUserBotDm']) {
|
||||||
|
|
||||||
} else if (event['type'] === 'MESSAGE') {
|
} else if (event['type'] === 'MESSAGE') {
|
||||||
text = event.message.text;
|
text = event.message.text;
|
||||||
fromName = event.message.sender.displayName;
|
fromName = event.message.sender.displayName;
|
||||||
|
|
@ -150,8 +140,7 @@ export class GoogleChatDirectLine extends GBService {
|
||||||
message.ack();
|
message.ack();
|
||||||
|
|
||||||
const sec = new SecService();
|
const sec = new SecService();
|
||||||
const user = await sec.ensureUser(this.min.instance.instanceId, from,
|
const user = await sec.ensureUser(this.min.instance.instanceId, from, from, '', 'googlechat', fromName, from);
|
||||||
from, '', 'googlechat', fromName, from);
|
|
||||||
|
|
||||||
await sec.updateConversationReferenceById(user.userId, threadName);
|
await sec.updateConversationReferenceById(user.userId, threadName);
|
||||||
|
|
||||||
|
|
@ -170,12 +159,11 @@ export class GoogleChatDirectLine extends GBService {
|
||||||
this.pollMessages(client, generatedConversationId, threadName, from, fromName);
|
this.pollMessages(client, generatedConversationId, threadName, from, fromName);
|
||||||
this.inputMessage(client, generatedConversationId, threadName, text, from, fromName);
|
this.inputMessage(client, generatedConversationId, threadName, text, from, fromName);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
this.inputMessage(client, conversationId, threadName, text, from, fromName);
|
this.inputMessage(client, conversationId, threadName, text, from, fromName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public inputMessage(client, conversationId, threadName, text, from, fromName) {
|
public inputMessage (client, conversationId, threadName, text, from, fromName) {
|
||||||
return client.Conversations.Conversations_PostActivity({
|
return client.Conversations.Conversations_PostActivity({
|
||||||
conversationId: conversationId,
|
conversationId: conversationId,
|
||||||
activity: {
|
activity: {
|
||||||
|
|
@ -192,7 +180,7 @@ export class GoogleChatDirectLine extends GBService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public pollMessages(client, conversationId, threadName, from, fromName) {
|
public pollMessages (client, conversationId, threadName, from, fromName) {
|
||||||
GBLog.info(`GBGoogleChat: Starting message polling(${from}, ${conversationId}).`);
|
GBLog.info(`GBGoogleChat: Starting message polling(${from}, ${conversationId}).`);
|
||||||
|
|
||||||
let watermark: any;
|
let watermark: any;
|
||||||
|
|
@ -212,7 +200,7 @@ export class GoogleChatDirectLine extends GBService {
|
||||||
setInterval(worker, this.pollInterval);
|
setInterval(worker, this.pollInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async printMessages(activities, conversationId, threadName, from, fromName) {
|
public async printMessages (activities, conversationId, threadName, from, fromName) {
|
||||||
if (activities && activities.length) {
|
if (activities && activities.length) {
|
||||||
// Ignore own messages.
|
// Ignore own messages.
|
||||||
|
|
||||||
|
|
@ -228,7 +216,7 @@ export class GoogleChatDirectLine extends GBService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async printMessage(activity, conversationId, threadName, from, fromName) {
|
public async printMessage (activity, conversationId, threadName, from, fromName) {
|
||||||
let output = '';
|
let output = '';
|
||||||
|
|
||||||
if (activity.text) {
|
if (activity.text) {
|
||||||
|
|
@ -252,27 +240,18 @@ export class GoogleChatDirectLine extends GBService {
|
||||||
await this.sendToDevice(from, conversationId, threadName, output);
|
await this.sendToDevice(from, conversationId, threadName, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendToDevice(from: string, conversationId: string, threadName, msg: string) {
|
public async sendToDevice (from: string, conversationId: string, threadName, msg: string) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
let threadParts = threadName.split('/');
|
let threadParts = threadName.split('/');
|
||||||
let spaces = threadParts[1];
|
let spaces = threadParts[1];
|
||||||
let threadKey = threadParts[3];
|
let threadKey = threadParts[3];
|
||||||
const scopes = ['https://www.googleapis.com/auth/chat.bot'];
|
const scopes = ['https://www.googleapis.com/auth/chat.bot'];
|
||||||
|
|
||||||
const jwtClient = new google.auth.JWT(
|
const jwtClient = new google.auth.JWT(this.GoogleClientEmail, null, this.GoogleClientPrivateKey, scopes, null);
|
||||||
this.GoogleClientEmail,
|
|
||||||
null,
|
|
||||||
this.GoogleClientPrivateKey,
|
|
||||||
scopes,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
await jwtClient.authorize();
|
await jwtClient.authorize();
|
||||||
const chat = google.chat({version: 'v1', auth: jwtClient});
|
const chat = google.chat({ version: 'v1', auth: jwtClient });
|
||||||
chat.spaces.messages.createAsync = promisify(chat.spaces.messages.create);
|
|
||||||
|
|
||||||
const res = await chat.spaces.messages.createAsync({
|
const res = await chat.spaces.messages.create({
|
||||||
parent: `spaces/${spaces}`,
|
parent: `spaces/${spaces}`,
|
||||||
threadKey: threadKey,
|
threadKey: threadKey,
|
||||||
requestBody: {
|
requestBody: {
|
||||||
|
|
@ -286,15 +265,10 @@ export class GoogleChatDirectLine extends GBService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async sendToDeviceEx (to, conversationId, threadName, text, locale) {
|
||||||
public async sendToDeviceEx(to, conversationId, threadName, text, locale) {
|
|
||||||
const minBoot = GBServer.globals.minBoot as any;
|
const minBoot = GBServer.globals.minBoot as any;
|
||||||
|
|
||||||
text = await minBoot.conversationalService.translate(
|
text = await minBoot.conversationalService.translate(minBoot, text, locale);
|
||||||
minBoot,
|
|
||||||
text,
|
|
||||||
locale
|
|
||||||
);
|
|
||||||
await this.sendToDevice(to, conversationId, threadName, text);
|
await this.sendToDevice(to, conversationId, threadName, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
export const Messages = {
|
export const Messages = {
|
||||||
'en-US': {
|
'en-US': {
|
||||||
notify_end_transfer: (botName) => `Now talking to ${botName} again.`
|
notify_end_transfer: botName => `Now talking to ${botName} again.`
|
||||||
},
|
},
|
||||||
'pt-BR': {
|
'pt-BR': {
|
||||||
notify_end_transfer: (botName) => `Falando com o bot ${botName} novamente.`
|
notify_end_transfer: botName => `Falando com o bot ${botName} novamente.`
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -45,27 +45,24 @@ import { Sequelize } from 'sequelize-typescript';
|
||||||
export class GBHubSpotPackage implements IGBPackage {
|
export class GBHubSpotPackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
|
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {}
|
||||||
|
|
||||||
}
|
public async getDialogs (min: GBMinInstance) {
|
||||||
|
|
||||||
public async getDialogs(min: GBMinInstance) {
|
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
GBLog.verbose(`loadPackage called.`);
|
GBLog.verbose(`loadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,171 +30,12 @@
|
||||||
| |
|
| |
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
||||||
const Swagger = require('swagger-client');
|
|
||||||
const fs = require('fs');
|
|
||||||
const { promisify } = require('util');
|
|
||||||
import { GBLog, GBMinInstance, GBService } from 'botlib';
|
import { GBLog, GBMinInstance, GBService } from 'botlib';
|
||||||
import { GBServer } from '../../../src/app';
|
import { promisify } from 'util';
|
||||||
import { SecService } from '../../security.gbapp/services/SecService';
|
import Swagger from 'swagger-client';
|
||||||
const hubspot = require('@hubspot/api-client');
|
import * as hubspot from '@hubspot/api-client';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support for Hub Spot XRM.
|
* Support for Hub Spot XRM.
|
||||||
*/
|
*/
|
||||||
export class HubSpotServices extends GBService {
|
export class HubSpotServices extends GBService {}
|
||||||
|
|
||||||
public static conversationIds = {};
|
|
||||||
public pollInterval = 5000;
|
|
||||||
|
|
||||||
public botId: string;
|
|
||||||
public min: GBMinInstance;
|
|
||||||
private key: any;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
min: GBMinInstance,
|
|
||||||
botId,
|
|
||||||
key
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.min = min;
|
|
||||||
this.botId = botId;
|
|
||||||
this.key = key;
|
|
||||||
|
|
||||||
}
|
|
||||||
public static async asyncForEach(array, callback) {
|
|
||||||
for (let index = 0; index < array.length; index++) {
|
|
||||||
await callback(array[index], index, array);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async addDealNote(name, note)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public async createDeal(dealName, contact, company, amount) {
|
|
||||||
const dealObj = {
|
|
||||||
properties: {
|
|
||||||
dealname: dealName,
|
|
||||||
dealstage: 'appointmentscheduled',
|
|
||||||
pipeline: 'default',
|
|
||||||
amount: amount
|
|
||||||
},
|
|
||||||
}
|
|
||||||
const contactObj = {
|
|
||||||
properties: {
|
|
||||||
firstname: contact
|
|
||||||
},
|
|
||||||
}
|
|
||||||
const companyObj = {
|
|
||||||
properties: {
|
|
||||||
name: company,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const hubspotClient = new hubspot.Client({ apiKey: this.key });
|
|
||||||
const createDealResponse = await hubspotClient.crm.deals.basicApi.create(dealObj);
|
|
||||||
const createContactResponse = await hubspotClient.crm.contacts.basicApi.create(contactObj);
|
|
||||||
const createCompanyResponse = await hubspotClient.crm.companies.basicApi.create(companyObj);
|
|
||||||
|
|
||||||
await hubspotClient.crm.deals.associationsApi.create(
|
|
||||||
createDealResponse.body.id,
|
|
||||||
'contacts',
|
|
||||||
createContactResponse.body.id,
|
|
||||||
'deal_to_contact'
|
|
||||||
)
|
|
||||||
|
|
||||||
await hubspotClient.crm.deals.associationsApi.create(
|
|
||||||
createDealResponse.body.id,
|
|
||||||
'companies',
|
|
||||||
createCompanyResponse.body.id,
|
|
||||||
'deal_to_company'
|
|
||||||
)
|
|
||||||
|
|
||||||
return createDealResponse.body;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async createContact(firstName, lastName, domain, companyName) {
|
|
||||||
const contactObj = {
|
|
||||||
properties: {
|
|
||||||
firstname: firstName,
|
|
||||||
lastname: lastName,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
const companyObj = {
|
|
||||||
properties: {
|
|
||||||
domain: domain,
|
|
||||||
name: companyName,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const hubspotClient = new hubspot.Client({ apiKey: this.key })
|
|
||||||
const createContactResponse = await hubspotClient.crm.contacts.basicApi.create(contactObj)
|
|
||||||
const createCompanyResponse = await hubspotClient.crm.companies.basicApi.create(companyObj)
|
|
||||||
|
|
||||||
return await hubspotClient.crm.companies.associationsApi.create(
|
|
||||||
createCompanyResponse.body.id,
|
|
||||||
'contacts',
|
|
||||||
createContactResponse.body.id,
|
|
||||||
'company_to_contact'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async searchContact(query) {
|
|
||||||
const client = new hubspot.Client({ apiKey: this.key });
|
|
||||||
const sort = JSON.stringify({ propertyName: 'createdate', direction: 'DESCENDING' })
|
|
||||||
|
|
||||||
const properties = ['createdate', 'firstname', 'lastname', 'phone', 'email']
|
|
||||||
const limit = 100
|
|
||||||
const after = 0
|
|
||||||
|
|
||||||
const publicObjectSearchRequest = {
|
|
||||||
sorts: [sort],
|
|
||||||
query,
|
|
||||||
properties,
|
|
||||||
limit,
|
|
||||||
after,
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await client.crm.contacts.searchApi.doSearch(publicObjectSearchRequest)
|
|
||||||
return result.body.results;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async getActiveTasks(): Promise<[]> {
|
|
||||||
|
|
||||||
const client = new hubspot.Client({ apiKey: this.key });
|
|
||||||
let properties = ['hs_task_subject', 'hubspot_owner_id', 'hs_task_status', 'hs_task_priority'];
|
|
||||||
const pageSize = 100;
|
|
||||||
let list;
|
|
||||||
list = [];
|
|
||||||
|
|
||||||
let r = await client.crm.objects.basicApi.getPage("TASK", pageSize, 0, properties);
|
|
||||||
list = list.concat(r.body.results);
|
|
||||||
|
|
||||||
while (r.body.results && r.body.results.length === pageSize) {
|
|
||||||
r = await client.crm.objects.basicApi.getPage("TASK", pageSize, r.body.paging.next.after, properties);
|
|
||||||
list = list.concat(r.body.results);
|
|
||||||
}
|
|
||||||
|
|
||||||
let final;
|
|
||||||
final = [];
|
|
||||||
list.forEach(e => {
|
|
||||||
if (e.properties.hs_task_status === "NOT_STARTED") {
|
|
||||||
e['status'] = e.properties.hs_task_status;
|
|
||||||
e['title'] = e.properties.hs_task_subject;
|
|
||||||
e['ownerId'] = e.properties.hubspot_owner_id;
|
|
||||||
e['priority'] = e.properties.hs_task_priority;
|
|
||||||
|
|
||||||
final.push(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return final;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
export const Messages = {
|
export const Messages = {
|
||||||
'en-US': {
|
'en-US': {},
|
||||||
|
'pt-BR': {}
|
||||||
},
|
|
||||||
'pt-BR': {
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -36,19 +36,19 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { GBServer } from '../../../src/app';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { BotAdapter } from 'botbuilder';
|
import { BotAdapter } from 'botbuilder';
|
||||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||||
import { GBLog, GBMinInstance, IGBDialog, IGBPackage } from 'botlib';
|
import { GBLog, GBMinInstance, IGBDialog, IGBPackage } from 'botlib';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings.js';
|
||||||
import { KBService } from './../services/KBService';
|
import { KBService } from './../services/KBService.js';
|
||||||
import { GuaribasAnswer } from '../models';
|
import { GuaribasAnswer } from '../models/index.js';
|
||||||
import { SecService } from '../../security.gbapp/services/SecService';
|
import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||||
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
|
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
|
||||||
import { GBVMService } from '../../basic.gblib/services/GBVMService';
|
import { GBVMService } from '../../basic.gblib/services/GBVMService.js';
|
||||||
import { GBImporter } from '../../core.gbapp/services/GBImporterService';
|
import { GBImporter } from '../../core.gbapp/services/GBImporterService.js';
|
||||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
|
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
|
||||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService';
|
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog arguments.
|
* Dialog arguments.
|
||||||
|
|
@ -69,7 +69,7 @@ export class AskDialog extends IGBDialog {
|
||||||
* @param bot The bot adapter.
|
* @param bot The bot adapter.
|
||||||
* @param min The minimal bot instance data.
|
* @param min The minimal bot instance data.
|
||||||
*/
|
*/
|
||||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||||
const service = new KBService(min.core.sequelize);
|
const service = new KBService(min.core.sequelize);
|
||||||
const importer = new GBImporter(min.core);
|
const importer = new GBImporter(min.core);
|
||||||
this.deployer = new GBDeployer(min.core, importer);
|
this.deployer = new GBDeployer(min.core, importer);
|
||||||
|
|
@ -79,13 +79,12 @@ export class AskDialog extends IGBDialog {
|
||||||
min.dialogs.add(new WaterfallDialog('/ask', AskDialog.getAskDialog(min)));
|
min.dialogs.add(new WaterfallDialog('/ask', AskDialog.getAskDialog(min)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getAskDialog(min: GBMinInstance) {
|
private static getAskDialog (min: GBMinInstance) {
|
||||||
return [
|
return [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -101,9 +100,9 @@ export class AskDialog extends IGBDialog {
|
||||||
if (step.options && step.options.firstTime) {
|
if (step.options && step.options.firstTime) {
|
||||||
text = Messages[locale].ask_first_time;
|
text = Messages[locale].ask_first_time;
|
||||||
} else if (step.options && step.options.isReturning) {
|
} else if (step.options && step.options.isReturning) {
|
||||||
text = ""; // REMOVED: Messages[locale].anything_else;
|
text = ''; // REMOVED: Messages[locale].anything_else;
|
||||||
} else if (step.options && step.options.emptyPrompt) {
|
} else if (step.options && step.options.emptyPrompt) {
|
||||||
text = "";
|
text = '';
|
||||||
} else if (user.subjects.length > 0) {
|
} else if (user.subjects.length > 0) {
|
||||||
text = Messages[locale].which_question;
|
text = Messages[locale].which_question;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -111,7 +110,6 @@ export class AskDialog extends IGBDialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
return await min.conversationalService.prompt(min, step, text);
|
return await min.conversationalService.prompt(min, step, text);
|
||||||
|
|
||||||
},
|
},
|
||||||
async step => {
|
async step => {
|
||||||
if (step.result) {
|
if (step.result) {
|
||||||
|
|
@ -120,7 +118,15 @@ export class AskDialog extends IGBDialog {
|
||||||
|
|
||||||
let sec = new SecService();
|
let sec = new SecService();
|
||||||
const member = step.context.activity.from;
|
const member = step.context.activity.from;
|
||||||
const user = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name, null);
|
const user = await sec.ensureUser(
|
||||||
|
min.instance.instanceId,
|
||||||
|
member.id,
|
||||||
|
member.name,
|
||||||
|
'',
|
||||||
|
'web',
|
||||||
|
member.name,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
let handled = false;
|
let handled = false;
|
||||||
let nextDialog = null;
|
let nextDialog = null;
|
||||||
|
|
@ -132,9 +138,7 @@ export class AskDialog extends IGBDialog {
|
||||||
user: user ? user['dataValues'] : null
|
user: user ? user['dataValues'] : null
|
||||||
};
|
};
|
||||||
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
|
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
|
||||||
if (
|
if ((nextDialog = await e.onExchangeData(min, 'handleAnswer', data))) {
|
||||||
nextDialog = await e.onExchangeData(min, 'handleAnswer', data)
|
|
||||||
) {
|
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -153,13 +157,12 @@ export class AskDialog extends IGBDialog {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getAnswerDialog(min: GBMinInstance, service: KBService) {
|
private static getAnswerDialog (min: GBMinInstance, service: KBService) {
|
||||||
return [
|
return [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -176,10 +179,9 @@ export class AskDialog extends IGBDialog {
|
||||||
// when people type just the @botName in MSTEAMS for example.
|
// when people type just the @botName in MSTEAMS for example.
|
||||||
|
|
||||||
if (!text) {
|
if (!text) {
|
||||||
const startDialog =
|
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
||||||
min.core.getParam(min.instance, 'Start Dialog', null);
|
|
||||||
if (startDialog) {
|
if (startDialog) {
|
||||||
await GBVMService.callVM(startDialog.toLowerCase().trim(), min, step, this.deployer);
|
await GBVMService.callVM(startDialog.toLowerCase().trim(), min, step, this.deployer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return step.endDialog();
|
return step.endDialog();
|
||||||
|
|
@ -201,8 +203,11 @@ export class AskDialog extends IGBDialog {
|
||||||
|
|
||||||
// Searches KB for the first time.
|
// Searches KB for the first time.
|
||||||
|
|
||||||
const searchScore = min.core.getParam(min.instance, 'Search Score',
|
const searchScore = min.core.getParam(
|
||||||
min.instance.searchScore ? min.instance.searchScore : minBoot.instance.searchScore);
|
min.instance,
|
||||||
|
'Search Score',
|
||||||
|
min.instance.searchScore ? min.instance.searchScore : minBoot.instance.searchScore
|
||||||
|
);
|
||||||
|
|
||||||
user.lastQuestion = text;
|
user.lastQuestion = text;
|
||||||
await min.userProfile.set(step.context, user);
|
await min.userProfile.set(step.context, user);
|
||||||
|
|
@ -256,7 +261,7 @@ export class AskDialog extends IGBDialog {
|
||||||
|
|
||||||
// Tries to answer by NLP.
|
// Tries to answer by NLP.
|
||||||
|
|
||||||
let nextDialog = await min.conversationalService["routeNLP2"](step, min, text);
|
let nextDialog = await min.conversationalService['routeNLP2'](step, min, text);
|
||||||
if (nextDialog) {
|
if (nextDialog) {
|
||||||
return nextDialog;
|
return nextDialog;
|
||||||
}
|
}
|
||||||
|
|
@ -270,58 +275,54 @@ export class AskDialog extends IGBDialog {
|
||||||
const docs = await min.kbService['getDocs'](min.instance.instanceId);
|
const docs = await min.kbService['getDocs'](min.instance.instanceId);
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(docs, async (doc: GuaribasAnswer) => {
|
await CollectionUtil.asyncForEach(docs, async (doc: GuaribasAnswer) => {
|
||||||
|
|
||||||
if (!answered) {
|
if (!answered) {
|
||||||
|
|
||||||
const answerText = await min.kbService['readComprehension'](min.instance.instanceId, doc.content, text);
|
const answerText = await min.kbService['readComprehension'](min.instance.instanceId, doc.content, text);
|
||||||
answered = true;
|
answered = true;
|
||||||
text = await min.conversationalService.translate(min, text, user.systemUser.locale
|
text = await min.conversationalService.translate(
|
||||||
|
min,
|
||||||
|
text,
|
||||||
|
user.systemUser.locale
|
||||||
? user.systemUser.locale
|
? user.systemUser.locale
|
||||||
: min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE')));
|
: min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
||||||
|
);
|
||||||
await min.conversationalService.sendText(min, step, answerText);
|
await min.conversationalService.sendText(min, step, answerText);
|
||||||
await min.conversationalService.sendEvent(min, step, 'stop', undefined);
|
await min.conversationalService.sendEvent(min, step, 'stop', undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
return await step.replaceDialog('/ask', { isReturning: true });
|
return await step.replaceDialog('/ask', { isReturning: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not found.
|
// Not found.
|
||||||
|
|
||||||
const message = min.core.getParam<string>(min.instance, 'Not Found Message',
|
const message = min.core.getParam<string>(min.instance, 'Not Found Message', Messages[locale].did_not_find);
|
||||||
Messages[locale].did_not_find);
|
|
||||||
|
|
||||||
await min.conversationalService.sendText(min, step, message);
|
await min.conversationalService.sendText(min, step, message);
|
||||||
return await step.replaceDialog('/ask', { isReturning: true });
|
return await step.replaceDialog('/ask', { isReturning: true });
|
||||||
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async handleAnswer(service: KBService, min: GBMinInstance, step: any, answer: GuaribasAnswer) {
|
private static async handleAnswer (service: KBService, min: GBMinInstance, step: any, answer: GuaribasAnswer) {
|
||||||
const text = answer.content;
|
const text = answer.content;
|
||||||
if (text.endsWith('.docx')) {
|
if (text.endsWith('.docx')) {
|
||||||
|
|
||||||
|
|
||||||
const mainName = GBVMService.getMethodNameFromVBSFilename(text);
|
const mainName = GBVMService.getMethodNameFromVBSFilename(text);
|
||||||
return await GBVMService.callVM(mainName, min, step, this.deployer);
|
return await GBVMService.callVM(mainName, min, step, this.deployer, false);
|
||||||
} else {
|
} else {
|
||||||
await service.sendAnswer(min, AskDialog.getChannel(step), step, answer);
|
await service.sendAnswer(min, AskDialog.getChannel(step), step, answer);
|
||||||
return await step.replaceDialog('/ask', { isReturning: true });
|
return await step.replaceDialog('/ask', { isReturning: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getChannel(step): string {
|
private static getChannel (step): string {
|
||||||
return !isNaN(step.context.activity['mobile']) ? 'whatsapp' : step.context.activity.channelId;
|
return !isNaN(step.context.activity['mobile']) ? 'whatsapp' : step.context.activity.channelId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getAnswerEventDialog(service: KBService, min: GBMinInstance) {
|
private static getAnswerEventDialog (service: KBService, min: GBMinInstance) {
|
||||||
return [
|
return [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -330,7 +331,7 @@ export class AskDialog extends IGBDialog {
|
||||||
const data = step.options as AskDialogArgs;
|
const data = step.options as AskDialogArgs;
|
||||||
if (data !== undefined && data.questionId !== undefined) {
|
if (data !== undefined && data.questionId !== undefined) {
|
||||||
const question = await service.getQuestionById(min.instance.instanceId, data.questionId);
|
const question = await service.getQuestionById(min.instance.instanceId, data.questionId);
|
||||||
const answer = await service.getAnswerById(min.instance.instanceId, question.answerId );
|
const answer = await service.getAnswerById(min.instance.instanceId, question.answerId);
|
||||||
// Sends the answer to all outputs, including projector.
|
// Sends the answer to all outputs, including projector.
|
||||||
await service.sendAnswer(min, AskDialog.getChannel(step), step, answer);
|
await service.sendAnswer(min, AskDialog.getChannel(step), step, answer);
|
||||||
await step.replaceDialog('/ask', { isReturning: true });
|
await step.replaceDialog('/ask', { isReturning: true });
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,9 @@
|
||||||
import { BotAdapter } from 'botbuilder';
|
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 { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
|
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService.js';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings.js';
|
||||||
import { KBService } from './../services/KBService';
|
import { KBService } from './../services/KBService.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle display of FAQ allowing direct access to KB.
|
* Handle display of FAQ allowing direct access to KB.
|
||||||
|
|
@ -53,16 +53,15 @@ export class FaqDialog extends IGBDialog {
|
||||||
* @param bot The bot adapter.
|
* @param bot The bot adapter.
|
||||||
* @param min The minimal bot instance data.
|
* @param min The minimal bot instance data.
|
||||||
*/
|
*/
|
||||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||||
|
|
||||||
const service = new KBService(min.core.sequelize);
|
const service = new KBService(min.core.sequelize);
|
||||||
|
|
||||||
min.dialogs.add(new WaterfallDialog('/faq', [
|
min.dialogs.add(
|
||||||
|
new WaterfallDialog('/faq', [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -81,6 +80,7 @@ export class FaqDialog extends IGBDialog {
|
||||||
return await step.next();
|
return await step.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]));
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,15 +36,15 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const urlJoin = require('url-join');
|
import urlJoin from 'url-join';
|
||||||
|
|
||||||
import { BotAdapter, CardFactory, MessageFactory } from 'botbuilder';
|
import { BotAdapter, CardFactory, MessageFactory } from 'botbuilder';
|
||||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||||
import { GBMinInstance, IGBDialog } from 'botlib';
|
import { GBMinInstance, IGBDialog } from 'botlib';
|
||||||
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
|
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService.js';
|
||||||
import { GuaribasSubject } from '../models';
|
import { GuaribasSubject } from '../models/index.js';
|
||||||
import { KBService } from '../services/KBService';
|
import { KBService } from '../services/KBService.js';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog arguments.
|
* Dialog arguments.
|
||||||
|
|
@ -64,19 +64,18 @@ export class MenuDialog extends IGBDialog {
|
||||||
* @param bot The bot adapter.
|
* @param bot The bot adapter.
|
||||||
* @param min The minimal bot instance data.
|
* @param min The minimal bot instance data.
|
||||||
*/
|
*/
|
||||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||||
const service = new KBService(min.core.sequelize);
|
const service = new KBService(min.core.sequelize);
|
||||||
|
|
||||||
min.dialogs.add(new WaterfallDialog('/menu', MenuDialog.getMenuDialog(min, service)));
|
min.dialogs.add(new WaterfallDialog('/menu', MenuDialog.getMenuDialog(min, service)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getMenuDialog(min: GBMinInstance, service: KBService) {
|
private static getMenuDialog (min: GBMinInstance, service: KBService) {
|
||||||
return [
|
return [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -103,8 +102,7 @@ export class MenuDialog extends IGBDialog {
|
||||||
|
|
||||||
// Whenever a subject is selected, shows a faq about it.
|
// Whenever a subject is selected, shows a faq about it.
|
||||||
if (user.subjects.length > 0) {
|
if (user.subjects.length > 0) {
|
||||||
const list = await service.getFaqBySubjectArray(min.instance.instanceId,
|
const list = await service.getFaqBySubjectArray(min.instance.instanceId, 'menu', user.subjects);
|
||||||
'menu', user.subjects);
|
|
||||||
await min.conversationalService.sendEvent(min, step, 'play', {
|
await min.conversationalService.sendEvent(min, step, 'play', {
|
||||||
playerType: 'bullet',
|
playerType: 'bullet',
|
||||||
data: list.slice(0, 10)
|
data: list.slice(0, 10)
|
||||||
|
|
@ -142,9 +140,10 @@ export class MenuDialog extends IGBDialog {
|
||||||
attachments.push(card);
|
attachments.push(card);
|
||||||
});
|
});
|
||||||
if (attachments.length === 0) {
|
if (attachments.length === 0) {
|
||||||
|
|
||||||
if (user.subjects && user.subjects.length > 0) {
|
if (user.subjects && user.subjects.length > 0) {
|
||||||
await min.conversationalService.sendText(min, step,
|
await min.conversationalService.sendText(
|
||||||
|
min,
|
||||||
|
step,
|
||||||
Messages[locale].lets_search(KBService.getFormattedSubjectItems(user.subjects))
|
Messages[locale].lets_search(KBService.getFormattedSubjectItems(user.subjects))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,36 +38,36 @@
|
||||||
|
|
||||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||||
import { Sequelize } from 'sequelize-typescript';
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
import { AskDialog } from './dialogs/AskDialog';
|
import { AskDialog } from './dialogs/AskDialog.js';
|
||||||
import { FaqDialog } from './dialogs/FaqDialog';
|
import { FaqDialog } from './dialogs/FaqDialog.js';
|
||||||
import { MenuDialog } from './dialogs/MenuDialog';
|
import { MenuDialog } from './dialogs/MenuDialog.js';
|
||||||
import { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from './models/index';
|
import { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from './models/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package for kb.gbapp.
|
* Package for kb.gbapp.
|
||||||
*/
|
*/
|
||||||
export class GBKBPackage implements IGBPackage {
|
export class GBKBPackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
public async getDialogs(min: GBMinInstance) {
|
public async getDialogs (min: GBMinInstance) {
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
core.sequelize.addModels([GuaribasAnswer, GuaribasQuestion, GuaribasSubject]);
|
core.sequelize.addModels([GuaribasAnswer, GuaribasQuestion, GuaribasSubject]);
|
||||||
}
|
}
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {
|
||||||
AskDialog.setup(min.bot, min);
|
AskDialog.setup(min.bot, min);
|
||||||
FaqDialog.setup(min.bot, min);
|
FaqDialog.setup(min.bot, min);
|
||||||
MenuDialog.setup(min.bot, min);
|
MenuDialog.setup(min.bot, min);
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,8 @@ import {
|
||||||
UpdatedAt
|
UpdatedAt
|
||||||
} from 'sequelize-typescript';
|
} from 'sequelize-typescript';
|
||||||
|
|
||||||
import {
|
import { GuaribasInstance, GuaribasPackage } from '../../core.gbapp/models/GBModel.js';
|
||||||
GuaribasInstance,
|
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||||
GuaribasPackage
|
|
||||||
} from '../../core.gbapp/models/GBModel';
|
|
||||||
import { GuaribasUser } from '../../security.gbapp/models';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subjects to group the pair of questions and answers.
|
* Subjects to group the pair of questions and answers.
|
||||||
|
|
@ -68,53 +65,53 @@ export class GuaribasSubject extends Model<GuaribasSubject> {
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public subjectId: number;
|
subjectId: number;
|
||||||
|
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public internalId: string;
|
internalId: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public title: string;
|
title: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(512))
|
@Column(DataType.STRING(512))
|
||||||
public description: string;
|
description: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public from: string;
|
from: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public to: string;
|
to: string;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasSubject)
|
@ForeignKey(() => GuaribasSubject)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public parentSubjectId: number;
|
parentSubjectId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasSubject, 'parentSubjectId')
|
@BelongsTo(() => GuaribasSubject, 'parentSubjectId')
|
||||||
public parentSubject: GuaribasSubject;
|
parentSubject: GuaribasSubject;
|
||||||
|
|
||||||
@HasMany(() => GuaribasSubject, { foreignKey: 'parentSubjectId' })
|
@HasMany(() => GuaribasSubject, { foreignKey: 'parentSubjectId' })
|
||||||
public childrenSubjects: GuaribasSubject[];
|
childrenSubjects: GuaribasSubject[];
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
instanceId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
public instance: GuaribasInstance;
|
instance: GuaribasInstance;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasUser)
|
@ForeignKey(() => GuaribasUser)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public responsibleUserId: number;
|
responsibleUserId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasUser)
|
@BelongsTo(() => GuaribasUser)
|
||||||
public responsibleUser: GuaribasUser;
|
responsibleUser: GuaribasUser;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasPackage)
|
@ForeignKey(() => GuaribasPackage)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public packageId: number;
|
packageId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasPackage)
|
@BelongsTo(() => GuaribasPackage)
|
||||||
public package: GuaribasPackage;
|
package: GuaribasPackage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -125,62 +122,61 @@ export class GuaribasQuestion extends Model<GuaribasQuestion> {
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public questionId: number;
|
questionId: number;
|
||||||
|
|
||||||
@Column(DataType.STRING(64))
|
@Column(DataType.STRING(64))
|
||||||
public subject1: string;
|
subject1: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(64))
|
@Column(DataType.STRING(64))
|
||||||
public subject2: string;
|
subject2: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(64))
|
@Column(DataType.STRING(64))
|
||||||
public subject3: string;
|
subject3: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(64))
|
@Column(DataType.STRING(64))
|
||||||
public subject4: string;
|
subject4: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(1024))
|
@Column(DataType.STRING(1024))
|
||||||
public keywords: string;
|
keywords: string;
|
||||||
|
|
||||||
@Column(DataType.BOOLEAN)
|
@Column(DataType.BOOLEAN)
|
||||||
public skipIndex: boolean;
|
skipIndex: boolean;
|
||||||
|
|
||||||
@Column(DataType.STRING(512))
|
@Column(DataType.STRING(512))
|
||||||
public from: string;
|
from: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(512))
|
@Column(DataType.STRING(512))
|
||||||
public to: string;
|
to: string;
|
||||||
|
|
||||||
@Column(DataType.TEXT)
|
@Column(DataType.TEXT)
|
||||||
public content: string;
|
content: string;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
public createdAt: Date;
|
createdAt: Date;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
public updatedAt: Date;
|
updatedAt: Date;
|
||||||
|
|
||||||
|
|
||||||
//tslint:disable-next-line:no-use-before-declare
|
//tslint:disable-next-line:no-use-before-declare
|
||||||
@ForeignKey(() => GuaribasAnswer)
|
@ForeignKey(() => GuaribasAnswer)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public answerId: number;
|
answerId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
public instance: GuaribasInstance;
|
instance: GuaribasInstance;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
instanceId: number;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasPackage)
|
@ForeignKey(() => GuaribasPackage)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public packageId: number;
|
packageId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasPackage)
|
@BelongsTo(() => GuaribasPackage)
|
||||||
public package: GuaribasPackage;
|
package: GuaribasPackage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -191,53 +187,52 @@ export class GuaribasAnswer extends Model<GuaribasAnswer> {
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public answerId: number;
|
declare answerId: number;
|
||||||
|
|
||||||
@Length({ min: 0, max: 512 })
|
@Length({ min: 0, max: 512 })
|
||||||
@Column(DataType.STRING(512))
|
@Column(DataType.STRING(512))
|
||||||
public media: string;
|
declare media: string;
|
||||||
|
|
||||||
@Length({ min: 0, max: 12 })
|
@Length({ min: 0, max: 12 })
|
||||||
@Column(DataType.STRING(12))
|
@Column(DataType.STRING(12))
|
||||||
public format: string;
|
declare format: string;
|
||||||
|
|
||||||
@Column(DataType.TEXT)
|
@Column(DataType.TEXT)
|
||||||
public content: string;
|
declare content: string;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
public createdAt: Date;
|
declare createdAt: Date;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
public updatedAt: Date;
|
declare updatedAt: Date;
|
||||||
|
|
||||||
|
|
||||||
@HasMany(() => GuaribasQuestion)
|
@HasMany(() => GuaribasQuestion)
|
||||||
public questions: GuaribasQuestion[];
|
declare questions: GuaribasQuestion[];
|
||||||
|
|
||||||
@HasOne(() => GuaribasQuestion)
|
@HasOne(() => GuaribasQuestion)
|
||||||
public prev: GuaribasQuestion;
|
declare prev: GuaribasQuestion;
|
||||||
|
|
||||||
@HasOne(() => GuaribasQuestion)
|
@HasOne(() => GuaribasQuestion)
|
||||||
public next: GuaribasQuestion;
|
declare next: GuaribasQuestion;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasQuestion)
|
@ForeignKey(() => GuaribasQuestion)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public nextId: number;
|
declare nextId: number;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasQuestion)
|
@ForeignKey(() => GuaribasQuestion)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public prevId: number;
|
declare prevId: number;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
declare instanceId: number;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasPackage)
|
@ForeignKey(() => GuaribasPackage)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public packageId: number;
|
declare packageId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasPackage)
|
@BelongsTo(() => GuaribasPackage)
|
||||||
public package: GuaribasPackage;
|
declare package: GuaribasPackage;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,17 +34,16 @@
|
||||||
* @fileoverview Knowledge base services and logic.
|
* @fileoverview Knowledge base services and logic.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const Path = require('path');
|
import Path from 'path';
|
||||||
const Fs = require('fs');
|
import Fs from 'fs';
|
||||||
const urlJoin = require('url-join');
|
import urlJoin from 'url-join';
|
||||||
const path = require('path');
|
import path from 'path';
|
||||||
const asyncPromise = require('async-promises');
|
import asyncPromise from 'async-promises';
|
||||||
const walkPromise = require('walk-promise');
|
import walkPromise from 'walk-promise';
|
||||||
// tslint:disable-next-line:newline-per-chained-call
|
import { SearchClient } from '@azure/search-documents';
|
||||||
const { SearchService } = require('azure-search-client');
|
import Excel from 'exceljs';
|
||||||
const Excel = require('exceljs');
|
import getSlug from 'speakingurl';
|
||||||
const getSlug = require('speakingurl');
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBServer } from '../../../src/app';
|
|
||||||
import {
|
import {
|
||||||
GBDialogStep,
|
GBDialogStep,
|
||||||
GBLog,
|
GBLog,
|
||||||
|
|
@ -57,15 +56,15 @@ import {
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { Op } from 'sequelize';
|
import { Op } from 'sequelize';
|
||||||
import { Sequelize } from 'sequelize-typescript';
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
|
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService.js';
|
||||||
import { GuaribasPackage } from '../../core.gbapp/models/GBModel';
|
import { GuaribasPackage } from '../../core.gbapp/models/GBModel.js';
|
||||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
|
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
|
||||||
import { CSService } from '../../customer-satisfaction.gbapp/services/CSService';
|
import { CSService } from '../../customer-satisfaction.gbapp/services/CSService.js';
|
||||||
import { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from '../models';
|
import { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from '../models/index.js';
|
||||||
import { GBConfigService } from './../../core.gbapp/services/GBConfigService';
|
import { GBConfigService } from './../../core.gbapp/services/GBConfigService.js';
|
||||||
const request = require('request-promise-native');
|
import request from 'request-promise-native';
|
||||||
const textract = require('textract');
|
import textract from 'textract';
|
||||||
const pdf = require("pdf-extraction");
|
import pdf from 'pdf-extraction';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Result for quey on KB data.
|
* Result for quey on KB data.
|
||||||
|
|
@ -81,11 +80,11 @@ export class KBServiceSearchResults {
|
||||||
export class KBService implements IGBKBService {
|
export class KBService implements IGBKBService {
|
||||||
public sequelize: Sequelize;
|
public sequelize: Sequelize;
|
||||||
|
|
||||||
constructor(sequelize: Sequelize) {
|
constructor (sequelize: Sequelize) {
|
||||||
this.sequelize = sequelize;
|
this.sequelize = sequelize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getFormattedSubjectItems(subjects: GuaribasSubject[]) {
|
public static getFormattedSubjectItems (subjects: GuaribasSubject[]) {
|
||||||
if (subjects === null) {
|
if (subjects === null) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +96,7 @@ export class KBService implements IGBKBService {
|
||||||
return out.join(', ');
|
return out.join(', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getSubjectItemsSeparatedBySpaces(subjects: GuaribasSubject[]) {
|
public static getSubjectItemsSeparatedBySpaces (subjects: GuaribasSubject[]) {
|
||||||
const out = [];
|
const out = [];
|
||||||
if (subjects === undefined) {
|
if (subjects === undefined) {
|
||||||
return '';
|
return '';
|
||||||
|
|
@ -109,7 +108,7 @@ export class KBService implements IGBKBService {
|
||||||
return out.join(' ');
|
return out.join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getAnswerTextByMediaName(instanceId: number, answerMediaName: string): Promise<string> {
|
public async getAnswerTextByMediaName (instanceId: number, answerMediaName: string): Promise<string> {
|
||||||
const answer = await GuaribasAnswer.findOne({
|
const answer = await GuaribasAnswer.findOne({
|
||||||
where: {
|
where: {
|
||||||
instanceId: instanceId,
|
instanceId: instanceId,
|
||||||
|
|
@ -120,7 +119,7 @@ export class KBService implements IGBKBService {
|
||||||
return answer != undefined ? answer.content : null;
|
return answer != undefined ? answer.content : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getQuestionById(instanceId: number, questionId: number): Promise<GuaribasQuestion> {
|
public async getQuestionById (instanceId: number, questionId: number): Promise<GuaribasQuestion> {
|
||||||
return GuaribasQuestion.findOne({
|
return GuaribasQuestion.findOne({
|
||||||
where: {
|
where: {
|
||||||
instanceId: instanceId,
|
instanceId: instanceId,
|
||||||
|
|
@ -129,7 +128,7 @@ export class KBService implements IGBKBService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getAnswerById(instanceId: number, answerId: number): Promise<GuaribasAnswer> {
|
public async getAnswerById (instanceId: number, answerId: number): Promise<GuaribasAnswer> {
|
||||||
return GuaribasAnswer.findOne({
|
return GuaribasAnswer.findOne({
|
||||||
where: {
|
where: {
|
||||||
instanceId: instanceId,
|
instanceId: instanceId,
|
||||||
|
|
@ -141,8 +140,7 @@ export class KBService implements IGBKBService {
|
||||||
/**
|
/**
|
||||||
* Returns a question object given a SEO friendly URL.
|
* Returns a question object given a SEO friendly URL.
|
||||||
*/
|
*/
|
||||||
public async getQuestionIdFromURL(core: IGBCoreService, url: string) {
|
public async getQuestionIdFromURL (core: IGBCoreService, url: string) {
|
||||||
|
|
||||||
// Extracts questionId from URL.
|
// Extracts questionId from URL.
|
||||||
|
|
||||||
const id = url.substr(url.lastIndexOf('-') + 1);
|
const id = url.substr(url.lastIndexOf('-') + 1);
|
||||||
|
|
@ -166,7 +164,7 @@ export class KBService implements IGBKBService {
|
||||||
|
|
||||||
return question;
|
return question;
|
||||||
}
|
}
|
||||||
public static async getQuestionsNER(instanceId: number) {
|
public static async getQuestionsNER (instanceId: number) {
|
||||||
const where = {
|
const where = {
|
||||||
instanceId: instanceId,
|
instanceId: instanceId,
|
||||||
content: { [Op.like]: `%(%` }
|
content: { [Op.like]: `%(%` }
|
||||||
|
|
@ -177,11 +175,9 @@ export class KBService implements IGBKBService {
|
||||||
});
|
});
|
||||||
|
|
||||||
return questions;
|
return questions;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getQuestionsSEO(instanceId: number) {
|
public async getQuestionsSEO (instanceId: number) {
|
||||||
|
|
||||||
const questions = await GuaribasQuestion.findAll({
|
const questions = await GuaribasQuestion.findAll({
|
||||||
where: {
|
where: {
|
||||||
instanceId: instanceId
|
instanceId: instanceId
|
||||||
|
|
@ -199,18 +195,16 @@ export class KBService implements IGBKBService {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getDocs(instanceId: number) {
|
public async getDocs (instanceId: number) {
|
||||||
|
|
||||||
return await GuaribasAnswer.findAll({
|
return await GuaribasAnswer.findAll({
|
||||||
where: {
|
where: {
|
||||||
instanceId: instanceId,
|
instanceId: instanceId,
|
||||||
format: '.docx'
|
format: '.docx'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getAnswerByText(instanceId: number, text: string, from: string = null): Promise<any> {
|
public async getAnswerByText (instanceId: number, text: string, from: string = null): Promise<any> {
|
||||||
text = text.trim();
|
text = text.trim();
|
||||||
|
|
||||||
const service = new CSService();
|
const service = new CSService();
|
||||||
|
|
@ -233,7 +227,7 @@ export class KBService implements IGBKBService {
|
||||||
let where = {
|
let where = {
|
||||||
instanceId: instanceId,
|
instanceId: instanceId,
|
||||||
content: { [Op.eq]: `${text}` }
|
content: { [Op.eq]: `${text}` }
|
||||||
}
|
};
|
||||||
question = await GuaribasQuestion.findOne({
|
question = await GuaribasQuestion.findOne({
|
||||||
where: where
|
where: where
|
||||||
});
|
});
|
||||||
|
|
@ -253,21 +247,16 @@ export class KBService implements IGBKBService {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async addAnswer (obj: GuaribasAnswer): Promise<GuaribasAnswer> {
|
||||||
|
|
||||||
|
|
||||||
public async addAnswer(obj: GuaribasAnswer): Promise<GuaribasAnswer> {
|
|
||||||
return await GuaribasAnswer.create(obj);
|
return await GuaribasAnswer.create(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ask(
|
public async ask (
|
||||||
instance: IGBInstance,
|
instance: IGBInstance,
|
||||||
query: string,
|
query: string,
|
||||||
searchScore: number,
|
searchScore: number,
|
||||||
subjects: GuaribasSubject[]
|
subjects: GuaribasSubject[]
|
||||||
): Promise<KBServiceSearchResults> {
|
): Promise<KBServiceSearchResults> {
|
||||||
|
|
||||||
|
|
||||||
// Builds search query.
|
// Builds search query.
|
||||||
|
|
||||||
query = query.toLowerCase();
|
query = query.toLowerCase();
|
||||||
|
|
@ -293,43 +282,51 @@ export class KBService implements IGBKBService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// No direct match found, so Search is used.
|
// No direct match found, so Search is used.
|
||||||
|
|
||||||
if (instance.searchKey !== null && GBConfigService.get('STORAGE_DIALECT') === 'mssql') {
|
if (instance.searchKey !== null && GBConfigService.get('STORAGE_DIALECT') === 'mssql') {
|
||||||
const client = new SearchService(instance.searchHost.split('.')[0], instance.searchKey);
|
interface SearchResults {
|
||||||
|
instanceId: number;
|
||||||
|
questionId: number;
|
||||||
|
answerId: number;
|
||||||
|
content: string;
|
||||||
|
subject1: string;
|
||||||
|
subject2: string;
|
||||||
|
subject: string;
|
||||||
|
subject4: string;
|
||||||
|
}
|
||||||
|
|
||||||
const results = await client.indexes.use('azuresql-index').search({
|
const client = new SearchClient<SearchResults>(instance.searchHost.split('.')[0], 'azuresql-index', {
|
||||||
count: true,
|
key: instance.searchKey
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
const results = await client.search(query, {
|
||||||
filter: `instanceId eq ${instance.instanceId} and skipIndex eq false`,
|
filter: `instanceId eq ${instance.instanceId} and skipIndex eq false`,
|
||||||
search: query,
|
searchFields: ['content', 'subject1', 'subject2', 'subject', 'subject4'],
|
||||||
searchFields: 'content, subject1, subject2, subject3, subject4',
|
select: ['instanceId', 'questionId', 'answerId'],
|
||||||
select: 'instanceId, questionId, answerId',
|
|
||||||
skip: 0,
|
skip: 0,
|
||||||
top: 1,
|
top: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const values = results.results; // TODO: See.
|
||||||
const values = results.result.value;
|
|
||||||
|
|
||||||
let returnedScore = 0;
|
let returnedScore = 0;
|
||||||
|
|
||||||
// Searches via Search (Azure Search).
|
// Searches via Search (Azure Search).
|
||||||
|
|
||||||
if (values && values.length > 0) {
|
let found = false;
|
||||||
returnedScore = values[0]['@search.score'];
|
for await (const result of values) {
|
||||||
|
found = true;
|
||||||
|
returnedScore = result['@search.score'];
|
||||||
if (returnedScore >= searchScore) {
|
if (returnedScore >= searchScore) {
|
||||||
const value = await this.getAnswerById(instance.instanceId, values[0].answerId);
|
const value = await this.getAnswerById(instance.instanceId, result.document.answerId);
|
||||||
if (value !== null) {
|
if (value !== null) {
|
||||||
GBLog.info(
|
GBLog.info(`SEARCH WILL BE USED with score: ${returnedScore} > required (searchScore): ${searchScore}`);
|
||||||
`SEARCH WILL BE USED with score: ${returnedScore} > required (searchScore): ${searchScore}`
|
|
||||||
);
|
|
||||||
|
|
||||||
|
return { answer: value, questionId: result.document.questionId };
|
||||||
return { answer: value, questionId: values[0].questionId };
|
|
||||||
} else {
|
} else {
|
||||||
GBLog.info(
|
GBLog.info(
|
||||||
`SEARCH WILL NOT be used as answerId ${values[0].answerId} was not found in database,
|
`SEARCH WILL NOT be used as answerId ${result.document.answerId} was not found in database,
|
||||||
returnedScore: ${returnedScore} < required (searchScore): ${searchScore}`
|
returnedScore: ${returnedScore} < required (searchScore): ${searchScore}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -343,17 +340,17 @@ export class KBService implements IGBKBService {
|
||||||
|
|
||||||
return { answer: undefined, questionId: 0 };
|
return { answer: undefined, questionId: 0 };
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
GBLog.info(
|
|
||||||
`SEARCH called but NO answer could be found (zero results).`
|
if (!found) {
|
||||||
);
|
GBLog.info(`SEARCH called but NO answer could be found (zero results).`);
|
||||||
|
}
|
||||||
|
|
||||||
return { answer: undefined, questionId: 0 };
|
return { answer: undefined, questionId: 0 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public async getSubjectItems(instanceId: number, parentId: number): Promise<GuaribasSubject[]> {
|
public async getSubjectItems (instanceId: number, parentId: number): Promise<GuaribasSubject[]> {
|
||||||
const where = { parentSubjectId: parentId, instanceId: instanceId };
|
const where = { parentSubjectId: parentId, instanceId: instanceId };
|
||||||
|
|
||||||
return GuaribasSubject.findAll({
|
return GuaribasSubject.findAll({
|
||||||
|
|
@ -361,7 +358,7 @@ export class KBService implements IGBKBService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getFaqBySubjectArray(instanceId: number, from: string, subjects: any): Promise<GuaribasQuestion[]> {
|
public async getFaqBySubjectArray (instanceId: number, from: string, subjects: any): Promise<GuaribasQuestion[]> {
|
||||||
if (subjects) {
|
if (subjects) {
|
||||||
const where = {
|
const where = {
|
||||||
from: from,
|
from: from,
|
||||||
|
|
@ -403,13 +400,13 @@ export class KBService implements IGBKBService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async getGroupReplies(instanceId: number): Promise<GuaribasQuestion[]> {
|
public static async getGroupReplies (instanceId: number): Promise<GuaribasQuestion[]> {
|
||||||
return await GuaribasQuestion.findAll({
|
return await GuaribasQuestion.findAll({
|
||||||
where: { from: 'group', instanceId: instanceId }
|
where: { from: 'group', instanceId: instanceId }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async importKbTabularFile(
|
public async importKbTabularFile (
|
||||||
filePath: string,
|
filePath: string,
|
||||||
instanceId: number,
|
instanceId: number,
|
||||||
packageId: number
|
packageId: number
|
||||||
|
|
@ -425,8 +422,8 @@ export class KBService implements IGBKBService {
|
||||||
// when loading worksheets collection.
|
// when loading worksheets collection.
|
||||||
|
|
||||||
let worksheet: any;
|
let worksheet: any;
|
||||||
for (let t = 0; t < data._worksheets.length; t++) {
|
for (let t = 0; t < data.worksheets.length; t++) {
|
||||||
worksheet = data._worksheets[t];
|
worksheet = data.worksheets[t];
|
||||||
if (worksheet) {
|
if (worksheet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -456,8 +453,13 @@ export class KBService implements IGBKBService {
|
||||||
const question = line._cells[3].text.trim();
|
const question = line._cells[3].text.trim();
|
||||||
let answer = line._cells[4].text.trim();
|
let answer = line._cells[4].text.trim();
|
||||||
|
|
||||||
if (!(subjectsText === 'subjects' && from === 'from') && answer !== null && question !== null &&
|
if (
|
||||||
answer !== '' && question !== '') {
|
!(subjectsText === 'subjects' && from === 'from') &&
|
||||||
|
answer !== null &&
|
||||||
|
question !== null &&
|
||||||
|
answer !== '' &&
|
||||||
|
question !== ''
|
||||||
|
) {
|
||||||
let format = '.txt';
|
let format = '.txt';
|
||||||
|
|
||||||
// Extracts answer from external media if any.
|
// Extracts answer from external media if any.
|
||||||
|
|
@ -469,16 +471,13 @@ export class KBService implements IGBKBService {
|
||||||
answer =
|
answer =
|
||||||
'Existe um problema na base de conhecimento. Fui treinado para entender sua pergunta, avise a quem me criou que a resposta não foi informada para esta pergunta.';
|
'Existe um problema na base de conhecimento. Fui treinado para entender sua pergunta, avise a quem me criou que a resposta não foi informada para esta pergunta.';
|
||||||
} else if (answer.indexOf('.md') > -1 || answer.indexOf('.docx') > -1) {
|
} else if (answer.indexOf('.md') > -1 || answer.indexOf('.docx') > -1) {
|
||||||
|
|
||||||
const mediaFilename = urlJoin(path.dirname(filePath), '..', 'articles', answer);
|
const mediaFilename = urlJoin(path.dirname(filePath), '..', 'articles', answer);
|
||||||
if (Fs.existsSync(mediaFilename)) {
|
if (Fs.existsSync(mediaFilename)) {
|
||||||
|
|
||||||
// Tries to load .docx file from Articles folder.
|
// Tries to load .docx file from Articles folder.
|
||||||
|
|
||||||
if (answer.indexOf('.docx') > -1) {
|
if (answer.indexOf('.docx') > -1) {
|
||||||
answer = await this.getTextFromFile(filePath);
|
answer = await this.getTextFromFile(filePath);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Loads normally markdown file.
|
// Loads normally markdown file.
|
||||||
|
|
||||||
answer = Fs.readFileSync(mediaFilename, 'utf8');
|
answer = Fs.readFileSync(mediaFilename, 'utf8');
|
||||||
|
|
@ -543,7 +542,7 @@ export class KBService implements IGBKBService {
|
||||||
subject4: subject4,
|
subject4: subject4,
|
||||||
content: question.replace(/["]+/g, ''),
|
content: question.replace(/["]+/g, ''),
|
||||||
instanceId: instanceId,
|
instanceId: instanceId,
|
||||||
skipIndex: (question.charAt(0) === "\""),
|
skipIndex: question.charAt(0) === '"',
|
||||||
packageId: packageId
|
packageId: packageId
|
||||||
};
|
};
|
||||||
questions.push(question1);
|
questions.push(question1);
|
||||||
|
|
@ -573,7 +572,7 @@ export class KBService implements IGBKBService {
|
||||||
return await GuaribasQuestion.bulkCreate(questions);
|
return await GuaribasQuestion.bulkCreate(questions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendAnswer(min: GBMinInstance, channel: string, step: GBDialogStep, answer: GuaribasAnswer) {
|
public async sendAnswer (min: GBMinInstance, channel: string, step: GBDialogStep, answer: GuaribasAnswer) {
|
||||||
if (answer.content.endsWith('.mp4')) {
|
if (answer.content.endsWith('.mp4')) {
|
||||||
await this.playVideo(min, min.conversationalService, step, answer, channel);
|
await this.playVideo(min, min.conversationalService, step, answer, channel);
|
||||||
} else if (
|
} else if (
|
||||||
|
|
@ -583,16 +582,19 @@ export class KBService implements IGBKBService {
|
||||||
answer.content.endsWith('.docx') ||
|
answer.content.endsWith('.docx') ||
|
||||||
answer.content.endsWith('.xls') ||
|
answer.content.endsWith('.xls') ||
|
||||||
answer.content.endsWith('.xlsx')
|
answer.content.endsWith('.xlsx')
|
||||||
|
|
||||||
) {
|
) {
|
||||||
const doc = urlJoin(GBServer.globals.publicAddress, 'kb', `${min.instance.botId}.gbai`,
|
const doc = urlJoin(
|
||||||
`${min.instance.botId}.gbkb`, 'assets', answer.content)
|
GBServer.globals.publicAddress,
|
||||||
|
'kb',
|
||||||
|
`${min.instance.botId}.gbai`,
|
||||||
|
`${min.instance.botId}.gbkb`,
|
||||||
|
'assets',
|
||||||
|
answer.content
|
||||||
|
);
|
||||||
const url = `http://view.officeapps.live.com/op/view.aspx?src=${doc}`;
|
const url = `http://view.officeapps.live.com/op/view.aspx?src=${doc}`;
|
||||||
await this.playUrl(min, min.conversationalService, step, url, channel);
|
await this.playUrl(min, min.conversationalService, step, url, channel);
|
||||||
} else if (answer.content.endsWith('.pdf')) {
|
} else if (answer.content.endsWith('.pdf')) {
|
||||||
|
const url = urlJoin('kb', `${min.instance.botId}.gbai`, `${min.instance.botId}.gbkb`, 'assets', answer.content);
|
||||||
const url = urlJoin('kb', `${min.instance.botId}.gbai`,
|
|
||||||
`${min.instance.botId}.gbkb`, 'assets', answer.content);
|
|
||||||
await this.playUrl(min, min.conversationalService, step, url, channel);
|
await this.playUrl(min, min.conversationalService, step, url, channel);
|
||||||
} else if (answer.format === '.md') {
|
} else if (answer.format === '.md') {
|
||||||
await min.conversationalService['playMarkdown'](min, answer.content, channel, step, min.conversationalService);
|
await min.conversationalService['playMarkdown'](min, answer.content, channel, step, min.conversationalService);
|
||||||
|
|
@ -604,7 +606,7 @@ export class KBService implements IGBKBService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async importKbPackage(
|
public async importKbPackage (
|
||||||
min: GBMinInstance,
|
min: GBMinInstance,
|
||||||
localPath: string,
|
localPath: string,
|
||||||
packageStorage: GuaribasPackage,
|
packageStorage: GuaribasPackage,
|
||||||
|
|
@ -634,7 +636,7 @@ export class KBService implements IGBKBService {
|
||||||
/**
|
/**
|
||||||
* Import all .md files in articles folder that has not been referenced by tabular files.
|
* Import all .md files in articles folder that has not been referenced by tabular files.
|
||||||
*/
|
*/
|
||||||
public async importRemainingArticles(localPath: string, instance: IGBInstance, packageId: number): Promise<any> {
|
public async importRemainingArticles (localPath: string, instance: IGBInstance, packageId: number): Promise<any> {
|
||||||
const files = await walkPromise(urlJoin(localPath, 'articles'));
|
const files = await walkPromise(urlJoin(localPath, 'articles'));
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(files, async file => {
|
await CollectionUtil.asyncForEach(files, async file => {
|
||||||
|
|
@ -661,12 +663,18 @@ export class KBService implements IGBKBService {
|
||||||
/**
|
/**
|
||||||
* Import all .docx files in reading comprehension folder.
|
* Import all .docx files in reading comprehension folder.
|
||||||
*/
|
*/
|
||||||
public async importDocs(min: GBMinInstance, localPath: string, instance: IGBInstance, packageId: number): Promise<any> {
|
public async importDocs (
|
||||||
|
min: GBMinInstance,
|
||||||
|
localPath: string,
|
||||||
|
instance: IGBInstance,
|
||||||
|
packageId: number
|
||||||
|
): Promise<any> {
|
||||||
const files = await walkPromise(urlJoin(localPath, 'docs'));
|
const files = await walkPromise(urlJoin(localPath, 'docs'));
|
||||||
if (!files[0]) {
|
if (!files[0]) {
|
||||||
GBLog.info(`[GBDeployer] docs folder not created yet in .gbkb. To use Reading Comprehension, create this folder at root and put a document to get read by the.`);
|
GBLog.info(
|
||||||
}
|
`[GBDeployer] docs folder not created yet in .gbkb. To use Reading Comprehension, create this folder at root and put a document to get read by the.`
|
||||||
else {
|
);
|
||||||
|
} else {
|
||||||
await CollectionUtil.asyncForEach(files, async file => {
|
await CollectionUtil.asyncForEach(files, async file => {
|
||||||
let content = null;
|
let content = null;
|
||||||
let filePath = Path.join(file.root, file.name);
|
let filePath = Path.join(file.root, file.name);
|
||||||
|
|
@ -689,12 +697,11 @@ export class KBService implements IGBKBService {
|
||||||
packageId: packageId
|
packageId: packageId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async importKbTabularDirectory(localPath: string, instance: IGBInstance, packageId: number): Promise<any> {
|
public async importKbTabularDirectory (localPath: string, instance: IGBInstance, packageId: number): Promise<any> {
|
||||||
const files = await walkPromise(localPath);
|
const files = await walkPromise(localPath);
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(files, async file => {
|
await CollectionUtil.asyncForEach(files, async file => {
|
||||||
|
|
@ -704,7 +711,7 @@ export class KBService implements IGBKBService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async importSubjectFile(packageId: number, filename: string, instance: IGBInstance): Promise<any> {
|
public async importSubjectFile (packageId: number, filename: string, instance: IGBInstance): Promise<any> {
|
||||||
const subjectsLoaded = JSON.parse(Fs.readFileSync(filename, 'utf8'));
|
const subjectsLoaded = JSON.parse(Fs.readFileSync(filename, 'utf8'));
|
||||||
|
|
||||||
const doIt = async (subjects: GuaribasSubject[], parentSubjectId: number) => {
|
const doIt = async (subjects: GuaribasSubject[], parentSubjectId: number) => {
|
||||||
|
|
@ -731,7 +738,7 @@ export class KBService implements IGBKBService {
|
||||||
return doIt(subjectsLoaded.children, undefined);
|
return doIt(subjectsLoaded.children, undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async undeployKbFromStorage(instance: IGBInstance, deployer: GBDeployer, packageId: number) {
|
public async undeployKbFromStorage (instance: IGBInstance, deployer: GBDeployer, packageId: number) {
|
||||||
await GuaribasQuestion.destroy({
|
await GuaribasQuestion.destroy({
|
||||||
where: { instanceId: instance.instanceId, packageId: packageId }
|
where: { instanceId: instance.instanceId, packageId: packageId }
|
||||||
});
|
});
|
||||||
|
|
@ -744,7 +751,7 @@ export class KBService implements IGBKBService {
|
||||||
await this.undeployPackageFromStorage(instance, packageId);
|
await this.undeployPackageFromStorage(instance, packageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async RefreshNER(min: GBMinInstance) {
|
public static async RefreshNER (min: GBMinInstance) {
|
||||||
const questions = await KBService.getQuestionsNER(min.instance.instanceId);
|
const questions = await KBService.getQuestionsNER(min.instance.instanceId);
|
||||||
const contentLocale = min.core.getParam<string>(
|
const contentLocale = min.core.getParam<string>(
|
||||||
min.instance,
|
min.instance,
|
||||||
|
|
@ -761,12 +768,9 @@ export class KBService implements IGBKBService {
|
||||||
if (categoryReg && nameReg) {
|
if (categoryReg && nameReg) {
|
||||||
let category = categoryReg[1];
|
let category = categoryReg[1];
|
||||||
let name = nameReg[1];
|
let name = nameReg[1];
|
||||||
min["nerEngine"].addNamedEntityText(category, name,
|
min['nerEngine'].addNamedEntityText(category, name, [contentLocale], [name]);
|
||||||
[contentLocale], [name]);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -774,7 +778,7 @@ export class KBService implements IGBKBService {
|
||||||
*
|
*
|
||||||
* @param localPath Path to the .gbkb folder.
|
* @param localPath Path to the .gbkb folder.
|
||||||
*/
|
*/
|
||||||
public async deployKb(core: IGBCoreService, deployer: GBDeployer, localPath: string, min: GBMinInstance) {
|
public async deployKb (core: IGBCoreService, deployer: GBDeployer, localPath: string, min: GBMinInstance) {
|
||||||
const packageName = Path.basename(localPath);
|
const packageName = Path.basename(localPath);
|
||||||
GBLog.info(`[GBDeployer] Opening package: ${localPath}`);
|
GBLog.info(`[GBDeployer] Opening package: ${localPath}`);
|
||||||
|
|
||||||
|
|
@ -792,7 +796,7 @@ export class KBService implements IGBKBService {
|
||||||
GBLog.info(`[GBDeployer] Finished import of ${localPath}`);
|
GBLog.info(`[GBDeployer] Finished import of ${localPath}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async playAudio(
|
private async playAudio (
|
||||||
min: GBMinInstance,
|
min: GBMinInstance,
|
||||||
answer: GuaribasAnswer,
|
answer: GuaribasAnswer,
|
||||||
channel: string,
|
channel: string,
|
||||||
|
|
@ -802,7 +806,7 @@ export class KBService implements IGBKBService {
|
||||||
conversationalService.sendAudio(min, step, answer.content);
|
conversationalService.sendAudio(min, step, answer.content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async playUrl(
|
private async playUrl (
|
||||||
min,
|
min,
|
||||||
conversationalService: IGBConversationalService,
|
conversationalService: IGBConversationalService,
|
||||||
step: GBDialogStep,
|
step: GBDialogStep,
|
||||||
|
|
@ -819,7 +823,7 @@ export class KBService implements IGBKBService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async playVideo(
|
private async playVideo (
|
||||||
min,
|
min,
|
||||||
conversationalService: IGBConversationalService,
|
conversationalService: IGBConversationalService,
|
||||||
step: GBDialogStep,
|
step: GBDialogStep,
|
||||||
|
|
@ -836,13 +840,13 @@ export class KBService implements IGBKBService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async undeployPackageFromStorage(instance: any, packageId: number) {
|
private async undeployPackageFromStorage (instance: any, packageId: number) {
|
||||||
await GuaribasPackage.destroy({
|
await GuaribasPackage.destroy({
|
||||||
where: { instanceId: instance.instanceId, packageId: packageId }
|
where: { instanceId: instance.instanceId, packageId: packageId }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async readComprehension(instanceId: number, doc: string, question: string) {
|
public async readComprehension (instanceId: number, doc: string, question: string) {
|
||||||
const options = {
|
const options = {
|
||||||
timeout: 60000 * 5,
|
timeout: 60000 * 5,
|
||||||
uri: `http://${process.env.GBMODELS_SERVER}/reading-comprehension`,
|
uri: `http://${process.env.GBMODELS_SERVER}/reading-comprehension`,
|
||||||
|
|
@ -854,7 +858,7 @@ export class KBService implements IGBKBService {
|
||||||
return await request.post(options);
|
return await request.post(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getTextFromFile(filename: string) {
|
private async getTextFromFile (filename: string) {
|
||||||
return new Promise<string>(async (resolve, reject) => {
|
return new Promise<string>(async (resolve, reject) => {
|
||||||
textract.fromFileWithPath(filename, { preserveLineBreaks: true }, (error, text) => {
|
textract.fromFileWithPath(filename, { preserveLineBreaks: true }, (error, text) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|
@ -866,5 +870,3 @@ export class KBService implements IGBKBService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,27 @@
|
||||||
export const Messages = {
|
export const Messages = {
|
||||||
'en-US': {
|
'en-US': {
|
||||||
did_not_find: 'I\'m sorry I didn\'t find anything.',
|
did_not_find: "I'm sorry I didn't find anything.",
|
||||||
going_answer: 'Great choice, now looking for your answer...',
|
going_answer: 'Great choice, now looking for your answer...',
|
||||||
wider_answer: subjectText =>
|
wider_answer: subjectText => `Answering to you in a broader way... Not just about ${subjectText}.`,
|
||||||
`Answering to you in a broader way... Not just about ${subjectText}.`,
|
which_question: "What's your question?",
|
||||||
which_question: 'What\'s your question?',
|
|
||||||
anything_else: 'Can I help you with anything else?',
|
anything_else: 'Can I help you with anything else?',
|
||||||
here_is_subjects: 'Here are some subjects to choose from...',
|
here_is_subjects: 'Here are some subjects to choose from...',
|
||||||
menu_select: 'Select',
|
menu_select: 'Select',
|
||||||
lets_search: query =>
|
lets_search: query => `Lets search for ${query}... What do you want to know?`,
|
||||||
`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.",
|
||||||
see_faq: 'Please take a look at the FAQ I\'ve prepared for you. You can click on them to get the answer.',
|
|
||||||
|
|
||||||
ask_first_time: 'What are you looking for?'
|
ask_first_time: 'What are you looking for?'
|
||||||
},
|
},
|
||||||
'pt-BR': {
|
'pt-BR': {
|
||||||
did_not_find: 'Desculpe-me, não encontrei nada a respeito.',
|
did_not_find: 'Desculpe-me, não encontrei nada a respeito.',
|
||||||
going_answer: 'Ótima escolha, procurando resposta para sua questão...',
|
going_answer: 'Ótima escolha, procurando resposta para sua questão...',
|
||||||
wider_answer: subjectText =>
|
wider_answer: subjectText => `Vou te responder de modo mais abrangente... Não apenas sobre ${subjectText}`,
|
||||||
`Vou te responder de modo mais abrangente... Não apenas sobre ${subjectText}`,
|
|
||||||
which_question: 'Qual a pergunta?',
|
which_question: 'Qual a pergunta?',
|
||||||
anything_else: 'Posso ajudar em algo mais?',
|
anything_else: 'Posso ajudar em algo mais?',
|
||||||
here_is_subjects: 'Aqui estão algumas categorias de assuntos...',
|
here_is_subjects: 'Aqui estão algumas categorias de assuntos...',
|
||||||
menu_select: 'Selecionar',
|
menu_select: 'Selecionar',
|
||||||
lets_search: query =>
|
lets_search: query => `Let's search about ${query}... What do you want to know?`,
|
||||||
`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.',
|
||||||
see_faq:
|
|
||||||
'Veja algumas perguntas mais frequentes logo na tela. Clique numa delas para eu responder.',
|
|
||||||
|
|
||||||
ask_first_time: 'Como eu posso ajudar?'
|
ask_first_time: 'Como eu posso ajudar?'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,13 +38,13 @@
|
||||||
|
|
||||||
import { TokenResponse } from 'botbuilder';
|
import { TokenResponse } from 'botbuilder';
|
||||||
import { GBLog, GBMinInstance, IGBDialog } from 'botlib';
|
import { GBLog, GBMinInstance, IGBDialog } from 'botlib';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialogs for handling Menu control.
|
* Dialogs for handling Menu control.
|
||||||
*/
|
*/
|
||||||
export class OAuthDialog extends IGBDialog {
|
export class OAuthDialog extends IGBDialog {
|
||||||
public static getOAuthDialog(min: GBMinInstance) {
|
public static getOAuthDialog (min: GBMinInstance) {
|
||||||
return {
|
return {
|
||||||
id: '/auth',
|
id: '/auth',
|
||||||
waterfall: [
|
waterfall: [
|
||||||
|
|
|
||||||
|
|
@ -36,31 +36,23 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const urlJoin = require('url-join');
|
|
||||||
|
|
||||||
import { BotAdapter, CardFactory, MessageFactory } from 'botbuilder';
|
|
||||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
|
||||||
import { GBLog, GBMinInstance, IGBDialog } from 'botlib';
|
import { GBLog, GBMinInstance, IGBDialog } from 'botlib';
|
||||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
||||||
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
|
import { Messages } from '../strings.js';
|
||||||
import { Messages } from '../strings';
|
import * as phone from 'google-libphonenumber';
|
||||||
const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance();
|
|
||||||
const phone = require('phone');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialogs for handling Menu control.
|
* Dialogs for handling Menu control.
|
||||||
*/
|
*/
|
||||||
export class ProfileDialog extends IGBDialog {
|
export class ProfileDialog extends IGBDialog {
|
||||||
|
public static getNameDialog (min: GBMinInstance) {
|
||||||
public static getNameDialog(min: GBMinInstance) {
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: '/profile_name', waterfall: [
|
id: '/profile_name',
|
||||||
|
waterfall: [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -72,7 +64,7 @@ export class ProfileDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
|
|
||||||
const fullName = (text) => {
|
const fullName = text => {
|
||||||
return text.match(/^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$/gi);
|
return text.match(/^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$/gi);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -85,21 +77,20 @@ export class ProfileDialog extends IGBDialog {
|
||||||
step.activeDialog.state.options.name = value[0];
|
step.activeDialog.state.options.name = value[0];
|
||||||
|
|
||||||
return await step.replaceDialog('/profile_mobile', step.activeDialog.state.options);
|
return await step.replaceDialog('/profile_mobile', step.activeDialog.state.options);
|
||||||
|
|
||||||
}
|
}
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getMobileDialog(min: GBMinInstance) {
|
public static getMobileDialog (min: GBMinInstance) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: '/profile_mobile', waterfall: [
|
id: '/profile_mobile',
|
||||||
|
waterfall: [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -112,14 +103,15 @@ export class ProfileDialog extends IGBDialog {
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
let phoneNumber;
|
let phoneNumber;
|
||||||
try {
|
try {
|
||||||
phoneNumber = phone(step.result, 'BRA')[0]; // TODO: Use accordingly to the person.
|
let p = phone.PhoneNumberUtil.getInstance();
|
||||||
phoneNumber = phoneUtil.parse(phoneNumber);
|
phoneNumber = p(step.result, 'BRA')[0]; // TODO: Use accordingly to the person.
|
||||||
|
phoneNumber = phone.phoneUtil.parse(phoneNumber);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await step.context.sendActivity(Messages[locale].validation_enter_valid_mobile);
|
await step.context.sendActivity(Messages[locale].validation_enter_valid_mobile);
|
||||||
|
|
||||||
return await step.replaceDialog('/profile_mobile', step.activeDialog.state.options);
|
return await step.replaceDialog('/profile_mobile', step.activeDialog.state.options);
|
||||||
}
|
}
|
||||||
if (!phoneUtil.isPossibleNumber(phoneNumber)) {
|
if (!phone.phoneUtil.isPossibleNumber(phoneNumber)) {
|
||||||
await step.context.sendActivity(Messages[locale].validation_enter_valid_mobile);
|
await step.context.sendActivity(Messages[locale].validation_enter_valid_mobile);
|
||||||
|
|
||||||
return await step.replaceDialog('/profile_mobile', step.activeDialog.state.options);
|
return await step.replaceDialog('/profile_mobile', step.activeDialog.state.options);
|
||||||
|
|
@ -129,19 +121,19 @@ export class ProfileDialog extends IGBDialog {
|
||||||
|
|
||||||
return await step.replaceDialog('/profile_mobile_confirm', step.activeDialog.state.options);
|
return await step.replaceDialog('/profile_mobile_confirm', step.activeDialog.state.options);
|
||||||
}
|
}
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getMobileConfirmDialog(min: GBMinInstance) {
|
public static getMobileConfirmDialog (min: GBMinInstance) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: '/profile_mobile_confirm', waterfall: [
|
id: '/profile_mobile_confirm',
|
||||||
|
waterfall: [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -150,8 +142,10 @@ export class ProfileDialog extends IGBDialog {
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
const from = step.activeDialog.state.options.mobile;
|
const from = step.activeDialog.state.options.mobile;
|
||||||
if (min.whatsAppDirectLine) {
|
if (min.whatsAppDirectLine) {
|
||||||
|
await min.whatsAppDirectLine.sendToDevice(
|
||||||
await min.whatsAppDirectLine.sendToDevice(from, `${step.activeDialog.state.options.mobileCode} is your General Bots creation code.`);
|
from,
|
||||||
|
`${step.activeDialog.state.options.mobileCode} is your General Bots creation code.`
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
GBLog.info(`WhatsApp not configured. Here is the code: ${step.activeDialog.state.options.mobileCode}.`);
|
GBLog.info(`WhatsApp not configured. Here is the code: ${step.activeDialog.state.options.mobileCode}.`);
|
||||||
}
|
}
|
||||||
|
|
@ -168,18 +162,19 @@ export class ProfileDialog extends IGBDialog {
|
||||||
} else {
|
} else {
|
||||||
await step.replaceDialog('/profile_email', step.activeDialog.state.options);
|
await step.replaceDialog('/profile_email', step.activeDialog.state.options);
|
||||||
}
|
}
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getEmailDialog(min: GBMinInstance) {
|
public static getEmailDialog (min: GBMinInstance) {
|
||||||
return {
|
return {
|
||||||
id: '/profile_email', waterfall: [
|
id: '/profile_email',
|
||||||
|
waterfall: [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||||
return await step.beginDialog('/auth');
|
return await step.beginDialog('/auth');
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return await step.next(step.options);
|
return await step.next(step.options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -190,7 +185,7 @@ export class ProfileDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
|
|
||||||
const extractEntity = (text) => {
|
const extractEntity = text => {
|
||||||
return text.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/gi);
|
return text.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/gi);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -203,7 +198,8 @@ export class ProfileDialog extends IGBDialog {
|
||||||
step.activeDialog.state.options.email = value[0];
|
step.activeDialog.state.options.email = value[0];
|
||||||
await step.replaceDialog(`/${step.activeDialog.state.options.nextDialog}`, step.activeDialog.state.options);
|
await step.replaceDialog(`/${step.activeDialog.state.options.nextDialog}`, step.activeDialog.state.options);
|
||||||
}
|
}
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,21 +36,18 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const urlJoin = require('url-join');
|
|
||||||
|
|
||||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||||
import { Sequelize } from 'sequelize-typescript';
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
import { OAuthDialog } from './dialogs/OAuthDialog';
|
import { OAuthDialog } from './dialogs/OAuthDialog.js';
|
||||||
import { ProfileDialog } from './dialogs/ProfileDialog';
|
import { ProfileDialog } from './dialogs/ProfileDialog.js';
|
||||||
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from './models';
|
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from './models/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package for the security module.
|
* Package for the security module.
|
||||||
*/
|
*/
|
||||||
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) {
|
||||||
|
|
||||||
const out = [
|
const out = [
|
||||||
ProfileDialog.getNameDialog(min),
|
ProfileDialog.getNameDialog(min),
|
||||||
ProfileDialog.getEmailDialog(min),
|
ProfileDialog.getEmailDialog(min),
|
||||||
|
|
@ -62,25 +59,24 @@ export class GBSecurityPackage implements IGBPackage {
|
||||||
out.push(OAuthDialog.getOAuthDialog(min));
|
out.push(OAuthDialog.getOAuthDialog(min));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`loadBot called.`);
|
GBLog.verbose(`loadBot called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
core.sequelize.addModels([GuaribasGroup, GuaribasUser, GuaribasUserGroup]);
|
core.sequelize.addModels([GuaribasGroup, GuaribasUser, GuaribasUserGroup]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ import {
|
||||||
Table
|
Table
|
||||||
} from 'sequelize-typescript';
|
} from 'sequelize-typescript';
|
||||||
|
|
||||||
import { GuaribasInstance } from '../../core.gbapp/models/GBModel';
|
import { GuaribasInstance } from '../../core.gbapp/models/GBModel.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A user and its metadata.
|
* A user and its metadata.
|
||||||
|
|
@ -58,46 +58,46 @@ export class GuaribasUser extends Model<GuaribasUser> {
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public userId: number;
|
userId: number;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public displayName: string;
|
displayName: string;
|
||||||
|
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public userSystemId: string;
|
userSystemId: string;
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public userName: string;
|
userName: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public defaultChannel: string;
|
defaultChannel: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(255))
|
@Column(DataType.STRING(255))
|
||||||
public email: string;
|
email: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(5))
|
@Column(DataType.STRING(5))
|
||||||
public locale: string;
|
locale: string;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
instanceId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
public instance: GuaribasInstance;
|
instance: GuaribasInstance;
|
||||||
|
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public agentSystemId: string;
|
agentSystemId: string;
|
||||||
|
|
||||||
@Column(DataType.DATE)
|
@Column(DataType.DATE)
|
||||||
public agentContacted: Date;
|
agentContacted: Date;
|
||||||
|
|
||||||
@Column(DataType.STRING(16))
|
@Column(DataType.STRING(16))
|
||||||
public agentMode: string;
|
agentMode: string;
|
||||||
|
|
||||||
@Column(DataType.TEXT)
|
@Column(DataType.TEXT)
|
||||||
public conversationReference: string;
|
conversationReference: string;
|
||||||
|
|
||||||
@Column(DataType.STRING(64))
|
@Column(DataType.STRING(64))
|
||||||
public hearOnDialog: string;
|
hearOnDialog: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -108,18 +108,18 @@ export class GuaribasGroup extends Model<GuaribasGroup> {
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public groupId: number;
|
groupId: number;
|
||||||
|
|
||||||
@Length({ min: 0, max: 512 })
|
@Length({ min: 0, max: 512 })
|
||||||
@Column(DataType.STRING(512))
|
@Column(DataType.STRING(512))
|
||||||
public displayName: string;
|
displayName: string;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
instanceId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
public instance: GuaribasInstance;
|
instance: GuaribasInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -129,22 +129,22 @@ export class GuaribasGroup extends Model<GuaribasGroup> {
|
||||||
export class GuaribasUserGroup extends Model<GuaribasUserGroup> {
|
export class GuaribasUserGroup extends Model<GuaribasUserGroup> {
|
||||||
@ForeignKey(() => GuaribasUser)
|
@ForeignKey(() => GuaribasUser)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public userId: number;
|
userId: number;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasGroup)
|
@ForeignKey(() => GuaribasGroup)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public groupId: number;
|
groupId: number;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column(DataType.INTEGER)
|
@Column(DataType.INTEGER)
|
||||||
public instanceId: number;
|
instanceId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
public instance: GuaribasInstance;
|
instance: GuaribasInstance;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasGroup)
|
@BelongsTo(() => GuaribasGroup)
|
||||||
public group: GuaribasGroup;
|
group: GuaribasGroup;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasUser)
|
@BelongsTo(() => GuaribasUser)
|
||||||
public user: GuaribasUser;
|
user: GuaribasUser;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,17 @@
|
||||||
const Fs = require('fs');
|
import Fs from 'fs';
|
||||||
const urlJoin = require('url-join');
|
import urlJoin from 'url-join';
|
||||||
|
|
||||||
import { ConversationReference } from 'botbuilder';
|
import { ConversationReference } from 'botbuilder';
|
||||||
import { GBLog, GBMinInstance, GBService, IGBInstance } from 'botlib';
|
import { GBLog, GBMinInstance, GBService, IGBInstance } from 'botlib';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from '../models';
|
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from '../models/index.js';
|
||||||
import { FindOptions } from 'sequelize';
|
import { FindOptions } from 'sequelize';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Security service layer.
|
* Security service layer.
|
||||||
*/
|
*/
|
||||||
export class SecService extends GBService {
|
export class SecService extends GBService {
|
||||||
|
public async ensureUser (
|
||||||
public async ensureUser(
|
|
||||||
instanceId: number,
|
instanceId: number,
|
||||||
userSystemId: string,
|
userSystemId: string,
|
||||||
userName: string,
|
userName: string,
|
||||||
|
|
@ -44,7 +43,7 @@ export class SecService extends GBService {
|
||||||
/**
|
/**
|
||||||
* Retrives a conversation reference from contact phone.
|
* Retrives a conversation reference from contact phone.
|
||||||
*/
|
*/
|
||||||
public async getConversationReference(phone: string): Promise<ConversationReference> {
|
public async getConversationReference (phone: string): Promise<ConversationReference> {
|
||||||
const options = <FindOptions>{ rejectOnEmpty: true, where: { phone: phone } };
|
const options = <FindOptions>{ rejectOnEmpty: true, where: { phone: phone } };
|
||||||
const user = await GuaribasUser.findOne(options);
|
const user = await GuaribasUser.findOne(options);
|
||||||
|
|
||||||
|
|
@ -54,7 +53,7 @@ export class SecService extends GBService {
|
||||||
/**
|
/**
|
||||||
* Updates a conversation reference from contact phone.
|
* Updates a conversation reference from contact phone.
|
||||||
*/
|
*/
|
||||||
public async updateConversationReference(phone: string, conversationReference: string) {
|
public async updateConversationReference (phone: string, conversationReference: string) {
|
||||||
const options = <FindOptions>{ where: { phone: phone } };
|
const options = <FindOptions>{ where: { phone: phone } };
|
||||||
const user = await GuaribasUser.findOne(options);
|
const user = await GuaribasUser.findOne(options);
|
||||||
|
|
||||||
|
|
@ -62,7 +61,7 @@ export class SecService extends GBService {
|
||||||
await user.save();
|
await user.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateConversationReferenceById(userId: number, conversationReference: string) {
|
public async updateConversationReferenceById (userId: number, conversationReference: string) {
|
||||||
const options = <FindOptions>{ where: { userId: userId } };
|
const options = <FindOptions>{ where: { userId: userId } };
|
||||||
const user = await GuaribasUser.findOne(options);
|
const user = await GuaribasUser.findOne(options);
|
||||||
|
|
||||||
|
|
@ -70,7 +69,7 @@ export class SecService extends GBService {
|
||||||
await user.save();
|
await user.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateUserLocale(userId: number, locale: any): Promise<GuaribasUser> {
|
public async updateUserLocale (userId: number, locale: any): Promise<GuaribasUser> {
|
||||||
const user = await GuaribasUser.findOne({
|
const user = await GuaribasUser.findOne({
|
||||||
where: {
|
where: {
|
||||||
userId: userId
|
userId: userId
|
||||||
|
|
@ -81,7 +80,7 @@ export class SecService extends GBService {
|
||||||
return await user.save();
|
return await user.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateUserHearOnDialog(userId: number, dialogName: string): Promise<GuaribasUser> {
|
public async updateUserHearOnDialog (userId: number, dialogName: string): Promise<GuaribasUser> {
|
||||||
const user = await GuaribasUser.findOne({
|
const user = await GuaribasUser.findOne({
|
||||||
where: {
|
where: {
|
||||||
userId: userId
|
userId: userId
|
||||||
|
|
@ -92,7 +91,7 @@ export class SecService extends GBService {
|
||||||
return await user.save();
|
return await user.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateUserInstance(userSystemId: string, instanceId: number): Promise<GuaribasUser> {
|
public async updateUserInstance (userSystemId: string, instanceId: number): Promise<GuaribasUser> {
|
||||||
const user = await GuaribasUser.findOne({
|
const user = await GuaribasUser.findOne({
|
||||||
where: {
|
where: {
|
||||||
userSystemId: userSystemId
|
userSystemId: userSystemId
|
||||||
|
|
@ -106,7 +105,7 @@ export class SecService extends GBService {
|
||||||
/**
|
/**
|
||||||
* Finds and update user agent information to a next available person.
|
* Finds and update user agent information to a next available person.
|
||||||
*/
|
*/
|
||||||
public async updateHumanAgent(
|
public async updateHumanAgent (
|
||||||
userSystemId: string,
|
userSystemId: string,
|
||||||
instanceId: number,
|
instanceId: number,
|
||||||
agentSystemId: string
|
agentSystemId: string
|
||||||
|
|
@ -153,7 +152,7 @@ export class SecService extends GBService {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async isAgentSystemId(systemId: string): Promise<Boolean> {
|
public async isAgentSystemId (systemId: string): Promise<Boolean> {
|
||||||
const user = await GuaribasUser.findOne({
|
const user = await GuaribasUser.findOne({
|
||||||
where: {
|
where: {
|
||||||
userSystemId: systemId
|
userSystemId: systemId
|
||||||
|
|
@ -167,24 +166,24 @@ export class SecService extends GBService {
|
||||||
return user.agentMode === 'self';
|
return user.agentMode === 'self';
|
||||||
}
|
}
|
||||||
|
|
||||||
public async assignHumanAgent(min: GBMinInstance, userSystemId: string, agentSystemId: string = null): Promise<string> {
|
public async assignHumanAgent (
|
||||||
|
min: GBMinInstance,
|
||||||
|
userSystemId: string,
|
||||||
|
agentSystemId: string = null
|
||||||
|
): Promise<string> {
|
||||||
if (!agentSystemId) {
|
if (!agentSystemId) {
|
||||||
let list = min.core.getParam<string>(
|
let list = min.core.getParam<string>(min.instance, 'Transfer To', process.env.TRANSFER_TO);
|
||||||
min.instance,
|
|
||||||
'Transfer To',
|
|
||||||
process.env.TRANSFER_TO
|
|
||||||
);
|
|
||||||
|
|
||||||
if (list) {
|
if (list) {
|
||||||
list = list.split(';')
|
list = list.split(';');
|
||||||
}
|
}
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(list, async item => {
|
await CollectionUtil.asyncForEach(list, async item => {
|
||||||
if (
|
if (
|
||||||
item !== undefined &&
|
item !== undefined &&
|
||||||
agentSystemId === undefined &&
|
agentSystemId === undefined &&
|
||||||
item !== userSystemId && !await this.isAgentSystemId(item)
|
item !== userSystemId &&
|
||||||
|
!(await this.isAgentSystemId(item))
|
||||||
) {
|
) {
|
||||||
// TODO: Optimize loop.
|
// TODO: Optimize loop.
|
||||||
agentSystemId = item;
|
agentSystemId = item;
|
||||||
|
|
@ -198,7 +197,7 @@ export class SecService extends GBService {
|
||||||
return agentSystemId;
|
return agentSystemId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getUserFromSystemId(systemId: string): Promise<GuaribasUser> {
|
public async getUserFromSystemId (systemId: string): Promise<GuaribasUser> {
|
||||||
return await GuaribasUser.findOne({
|
return await GuaribasUser.findOne({
|
||||||
where: {
|
where: {
|
||||||
userSystemId: systemId
|
userSystemId: systemId
|
||||||
|
|
@ -206,7 +205,7 @@ export class SecService extends GBService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getUserFromAgentSystemId(systemId: string): Promise<GuaribasUser> {
|
public async getUserFromAgentSystemId (systemId: string): Promise<GuaribasUser> {
|
||||||
return await GuaribasUser.findOne({
|
return await GuaribasUser.findOne({
|
||||||
where: {
|
where: {
|
||||||
agentSystemId: systemId
|
agentSystemId: systemId
|
||||||
|
|
@ -214,7 +213,7 @@ export class SecService extends GBService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getAllUsers(instanceId: number): Promise<GuaribasUser[]> {
|
public async getAllUsers (instanceId: number): Promise<GuaribasUser[]> {
|
||||||
return await GuaribasUser.findAll({
|
return await GuaribasUser.findAll({
|
||||||
where: {
|
where: {
|
||||||
instanceId: instanceId
|
instanceId: instanceId
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
export const Messages = {
|
export const Messages = {
|
||||||
'en-US': {
|
'en-US': {
|
||||||
whats_name: 'What\'s your name?',
|
whats_name: "What's your name?",
|
||||||
whats_mobile: 'What\'s your mobile number including country code (e.g. +1 222 9998888)?',
|
whats_mobile: "What's your mobile number including country code (e.g. +1 222 9998888)?",
|
||||||
confirm_mobile: 'Please type the code just sent to your mobile.',
|
confirm_mobile: 'Please type the code just sent to your mobile.',
|
||||||
whats_email: 'What\'s your E-mail address?',
|
whats_email: "What's your E-mail address?",
|
||||||
validation_enter_name: 'Please enter your full name.',
|
validation_enter_name: 'Please enter your full name.',
|
||||||
validation_enter_valid_mobile: 'Please enter a valid mobile number.',
|
validation_enter_valid_mobile: 'Please enter a valid mobile number.',
|
||||||
validation_enter_valid_email: 'Please enter a valid e-mail.'
|
validation_enter_valid_email: 'Please enter a valid e-mail.'
|
||||||
|
|
@ -13,7 +13,8 @@ export const Messages = {
|
||||||
whats_email: 'Qual o seu e-mail?',
|
whats_email: 'Qual o seu e-mail?',
|
||||||
whats_mobile: 'Qual o seu celular?',
|
whats_mobile: 'Qual o seu celular?',
|
||||||
confirm_mobile: 'Por favor, digite o código enviado para seu celular.',
|
confirm_mobile: 'Por favor, digite o código enviado para seu celular.',
|
||||||
confirm_mobile_again: 'Esse não me parece ser um código numérico válido. Por favor, digite novamente o código enviado para seu celular.',
|
confirm_mobile_again:
|
||||||
|
'Esse não me parece ser um código numérico válido. Por favor, digite novamente o código enviado para seu celular.',
|
||||||
validation_enter_valid_email: 'Por favor, digite um e-mail válido no formato nome@domínio.com.br.',
|
validation_enter_valid_email: 'Por favor, digite um e-mail válido no formato nome@domínio.com.br.',
|
||||||
validation_enter_name: 'Por favor, digite seu nome completo',
|
validation_enter_name: 'Por favor, digite seu nome completo',
|
||||||
validation_enter_valid_mobile: 'Por favor, insira um número de celular válido (ex.: +55 21 98888-7766).'
|
validation_enter_valid_mobile: 'Por favor, insira um número de celular válido (ex.: +55 21 98888-7766).'
|
||||||
|
|
|
||||||
|
|
@ -44,26 +44,25 @@ import { Sequelize } from 'sequelize-typescript';
|
||||||
*/
|
*/
|
||||||
export class GBSharePointPackage implements IGBPackage {
|
export class GBSharePointPackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
public async getDialogs(min: GBMinInstance) {
|
public async getDialogs (min: GBMinInstance) {
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
GBLog.verbose(`loadPackage called.`);
|
GBLog.verbose(`loadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`loadBot called.`);
|
GBLog.verbose(`loadBot called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,29 +36,7 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { sppull } = require('sppull');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service facade for SharePoint Online.
|
* Service facade for SharePoint Online.
|
||||||
*/
|
*/
|
||||||
export class GBSharePointService {
|
export class GBSharePointService {}
|
||||||
|
|
||||||
public async downloadFolder(localPath: string, siteUrl: string, folderUrl: string, username: string, password: string) {
|
|
||||||
|
|
||||||
const context = {
|
|
||||||
siteUrl: siteUrl,
|
|
||||||
creds: {
|
|
||||||
username: username,
|
|
||||||
password: password
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
spRootFolder: folderUrl,
|
|
||||||
dlRootFolder: localPath
|
|
||||||
};
|
|
||||||
|
|
||||||
return await sppull(context, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
export const Messages = {
|
export const Messages = {
|
||||||
'en-US': {
|
'en-US': {},
|
||||||
|
'pt-BR': {}
|
||||||
},
|
|
||||||
'pt-BR': {
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -45,27 +45,24 @@ import { Sequelize } from 'sequelize-typescript';
|
||||||
export class GBTeamsPackage implements IGBPackage {
|
export class GBTeamsPackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
|
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {}
|
||||||
|
|
||||||
}
|
public async getDialogs (min: GBMinInstance) {
|
||||||
|
|
||||||
public async getDialogs(min: GBMinInstance) {
|
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
GBLog.verbose(`loadPackage called.`);
|
GBLog.verbose(`loadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,28 +30,24 @@
|
||||||
| |
|
| |
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
||||||
const urlJoin = require('url-join');
|
|
||||||
import { GBService } from 'botlib';
|
import { GBService } from 'botlib';
|
||||||
const fs = require('fs');
|
import Fs from 'fs';
|
||||||
var AdmZip = require("adm-zip");
|
import AdmZip from 'adm-zip';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support for Whatsapp.
|
* Support for Whatsapp.
|
||||||
*/
|
*/
|
||||||
export class TeamsService extends GBService {
|
export class TeamsService extends GBService {
|
||||||
|
public async getAppFile (manifest) {
|
||||||
public async getAppFile(manifest)
|
|
||||||
{
|
|
||||||
var zip = new AdmZip();
|
var zip = new AdmZip();
|
||||||
zip.addFile("manifest.json", Buffer.from(manifest, "utf8"), "Built with General Bots™.");
|
zip.addFile('manifest.json', Buffer.from(manifest, 'utf8'), 'Built with General Bots™.');
|
||||||
zip.addLocalFile("teams-color.png", null, "color.png");
|
zip.addLocalFile('teams-color.png', null, 'color.png');
|
||||||
zip.addLocalFile("teams-outline.png", null, "outline.png");
|
zip.addLocalFile('teams-outline.png', null, 'outline.png');
|
||||||
return zip.toBuffer();
|
return zip.toBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getManifest(marketplaceId, botName, botDescription, id, packageName, yourName) {
|
public async getManifest (marketplaceId, botName, botDescription, id, packageName, yourName) {
|
||||||
let content = fs.readFileSync('teams-manifest.json', 'utf8');
|
let content = Fs.readFileSync('teams-manifest.json', 'utf8');
|
||||||
|
|
||||||
content = content.replace(/\@\@marketplaceId/gi, marketplaceId);
|
content = content.replace(/\@\@marketplaceId/gi, marketplaceId);
|
||||||
content = content.replace(/\@\@botName/gi, botName);
|
content = content.replace(/\@\@botName/gi, botName);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
export const Messages = {
|
export const Messages = {
|
||||||
'en-US': {
|
'en-US': {},
|
||||||
|
'pt-BR': {}
|
||||||
},
|
|
||||||
'pt-BR': {
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||||
import { Sequelize } from 'sequelize-typescript';
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
import { WhatsappDirectLine } from './services/WhatsappDirectLine';
|
import { WhatsappDirectLine } from './services/WhatsappDirectLine.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package for whatsapp.gblib
|
* Package for whatsapp.gblib
|
||||||
|
|
@ -46,27 +46,24 @@ import { WhatsappDirectLine } from './services/WhatsappDirectLine';
|
||||||
export class GBWhatsappPackage implements IGBPackage {
|
export class GBWhatsappPackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
|
|
||||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
public async loadBot (min: GBMinInstance): Promise<void> {}
|
||||||
|
|
||||||
}
|
public async getDialogs (min: GBMinInstance) {
|
||||||
|
|
||||||
public async getDialogs(min: GBMinInstance) {
|
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
}
|
}
|
||||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||||
GBLog.verbose(`loadPackage called.`);
|
GBLog.verbose(`loadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||||
GBLog.verbose(`unloadPackage called.`);
|
GBLog.verbose(`unloadPackage called.`);
|
||||||
}
|
}
|
||||||
public async unloadBot(min: GBMinInstance): Promise<void> {
|
public async unloadBot (min: GBMinInstance): Promise<void> {
|
||||||
GBLog.verbose(`unloadBot called.`);
|
GBLog.verbose(`unloadBot called.`);
|
||||||
}
|
}
|
||||||
public async onNewSession(min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
public async onNewSession (min: GBMinInstance, step: GBDialogStep): Promise<void> {
|
||||||
GBLog.verbose(`onNewSession called.`);
|
GBLog.verbose(`onNewSession called.`);
|
||||||
}
|
}
|
||||||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||||
GBLog.verbose(`onExchangeData called.`);
|
GBLog.verbose(`onExchangeData called.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,8 +1,8 @@
|
||||||
export const Messages = {
|
export const Messages = {
|
||||||
'en-US': {
|
'en-US': {
|
||||||
notify_end_transfer: (botName) => `Now talking to ${botName} again.`
|
notify_end_transfer: botName => `Now talking to ${botName} again.`
|
||||||
},
|
},
|
||||||
'pt-BR': {
|
'pt-BR': {
|
||||||
notify_end_transfer: (botName) => `Falando com o bot ${botName} novamente.`
|
notify_end_transfer: botName => `Falando com o bot ${botName} novamente.`
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
91
src/app.ts
91
src/app.ts
|
|
@ -36,24 +36,24 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const express = require('express');
|
import express from 'express';
|
||||||
const bodyParser = require('body-parser');
|
import bodyParser from 'body-parser';
|
||||||
const https = require('https');
|
import https from 'https';
|
||||||
const mkdirp = require('mkdirp');
|
import mkdirp from 'mkdirp';
|
||||||
const Path = require('path');
|
import Path from 'path';
|
||||||
|
import * as Fs from 'fs';
|
||||||
import * as fs from 'fs';
|
|
||||||
import { GBLog, GBMinInstance, IGBCoreService, IGBInstance, IGBPackage } from 'botlib';
|
import { GBLog, GBMinInstance, IGBCoreService, IGBInstance, IGBPackage } from 'botlib';
|
||||||
import { GBAdminService } from '../packages/admin.gbapp/services/GBAdminService';
|
import { GBAdminService } from '../packages/admin.gbapp/services/GBAdminService.js';
|
||||||
import { AzureDeployerService } from '../packages/azuredeployer.gbapp/services/AzureDeployerService';
|
import { AzureDeployerService } from '../packages/azuredeployer.gbapp/services/AzureDeployerService.js';
|
||||||
import { GBConfigService } from '../packages/core.gbapp/services/GBConfigService';
|
import { GBConfigService } from '../packages/core.gbapp/services/GBConfigService.js';
|
||||||
import { GBConversationalService } from '../packages/core.gbapp/services/GBConversationalService';
|
import { GBConversationalService } from '../packages/core.gbapp/services/GBConversationalService.js';
|
||||||
import { GBCoreService } from '../packages/core.gbapp/services/GBCoreService';
|
import { GBCoreService } from '../packages/core.gbapp/services/GBCoreService.js';
|
||||||
import { GBDeployer } from '../packages/core.gbapp/services/GBDeployer';
|
import { GBDeployer } from '../packages/core.gbapp/services/GBDeployer.js';
|
||||||
import { GBImporter } from '../packages/core.gbapp/services/GBImporterService';
|
import { GBImporter } from '../packages/core.gbapp/services/GBImporterService.js';
|
||||||
import { GBMinService } from '../packages/core.gbapp/services/GBMinService';
|
import { GBMinService } from '../packages/core.gbapp/services/GBMinService.js';
|
||||||
var auth = require('basic-auth');
|
import auth from 'basic-auth';
|
||||||
|
import child_process from 'child_process';
|
||||||
|
import * as winston from 'winston-logs-display';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global shared server data;
|
* Global shared server data;
|
||||||
|
|
@ -70,6 +70,7 @@ export class RootData {
|
||||||
public wwwroot: string; // .gbui or a static webapp.
|
public wwwroot: string; // .gbui or a static webapp.
|
||||||
public entryPointDialog: string; // To replace default welcome dialog.
|
public entryPointDialog: string; // To replace default welcome dialog.
|
||||||
public debugConversationId: any; // Used to self-message during debug.
|
public debugConversationId: any; // Used to self-message during debug.
|
||||||
|
public debuggers: any[]; // Client of attached Debugger instances by botId.
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* General Bots open-core entry point.
|
* General Bots open-core entry point.
|
||||||
|
|
@ -81,37 +82,44 @@ export class GBServer {
|
||||||
* Program entry-point.
|
* Program entry-point.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static run() {
|
public static run () {
|
||||||
|
|
||||||
|
|
||||||
GBLog.info(`The Bot Server is in STARTING mode...`);
|
GBLog.info(`The Bot Server is in STARTING mode...`);
|
||||||
GBServer.globals = new RootData();
|
GBServer.globals = new RootData();
|
||||||
GBConfigService.init();
|
GBConfigService.init();
|
||||||
const port = GBConfigService.getServerPort();
|
const port = GBConfigService.getServerPort();
|
||||||
|
|
||||||
|
if (process.env.TEST_SHELL) {
|
||||||
|
GBLog.info(`Running TEST_SHELL: ${process.env.TEST_SHELL}...`);
|
||||||
|
try {
|
||||||
|
child_process.execSync(process.env.TEST_SHELL);
|
||||||
|
} catch (error) {
|
||||||
|
GBLog.error(`Running TEST_SHELL ERROR: ${error}...`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const server = express();
|
const server = express();
|
||||||
|
|
||||||
GBServer.globals.server = server;
|
GBServer.globals.server = server;
|
||||||
GBServer.globals.appPackages = [];
|
GBServer.globals.appPackages = [];
|
||||||
GBServer.globals.sysPackages = [];
|
GBServer.globals.sysPackages = [];
|
||||||
GBServer.globals.minInstances = [];
|
GBServer.globals.minInstances = [];
|
||||||
GBServer.globals.wwwroot = null;
|
GBServer.globals.wwwroot = null;
|
||||||
GBServer.globals.entryPointDialog = null;
|
GBServer.globals.entryPointDialog = null;
|
||||||
|
GBServer.globals.debuggers = [];
|
||||||
|
|
||||||
server.use(bodyParser.json());
|
server.use(bodyParser.json());
|
||||||
server.use(bodyParser.urlencoded({ extended: true }));
|
server.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
|
||||||
|
|
||||||
// Creates working directory.
|
// Creates working directory.
|
||||||
|
|
||||||
const workDir = Path.join(process.env.PWD, 'work');
|
const workDir = Path.join(process.env.PWD, 'work');
|
||||||
if (!fs.existsSync(workDir)) {
|
if (!Fs.existsSync(workDir)) {
|
||||||
mkdirp.sync(workDir);
|
mkdirp.sync(workDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mainCallback = () => {
|
const mainCallback = () => {
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
GBLog.info(`Now accepting connections on ${port}...`);
|
GBLog.info(`Now accepting connections on ${port}...`);
|
||||||
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
|
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
|
||||||
|
|
||||||
|
|
@ -146,9 +154,11 @@ export class GBServer {
|
||||||
await core.initStorage();
|
await core.initStorage();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
GBLog.verbose(`Error initializing storage: ${error}`);
|
GBLog.verbose(`Error initializing storage: ${error}`);
|
||||||
GBServer.globals.bootInstance =
|
GBServer.globals.bootInstance = await core.createBootInstance(
|
||||||
await core.createBootInstance(core, azureDeployer, GBServer.globals.publicAddress);
|
core,
|
||||||
|
azureDeployer,
|
||||||
|
GBServer.globals.publicAddress
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
core.ensureAdminIsSecured();
|
core.ensureAdminIsSecured();
|
||||||
|
|
@ -176,7 +186,6 @@ export class GBServer {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (instances.length === 0) {
|
if (instances.length === 0) {
|
||||||
|
|
||||||
const instance = await importer.importIfNotExistsBotPackage(
|
const instance = await importer.importIfNotExistsBotPackage(
|
||||||
GBConfigService.get('BOT_ID'),
|
GBConfigService.get('BOT_ID'),
|
||||||
'boot.gbot',
|
'boot.gbot',
|
||||||
|
|
@ -201,30 +210,30 @@ export class GBServer {
|
||||||
await minService.buildMin(instances);
|
await minService.buildMin(instances);
|
||||||
|
|
||||||
if (process.env.ENABLE_WEBLOG) {
|
if (process.env.ENABLE_WEBLOG) {
|
||||||
var admins = {
|
const admins = {
|
||||||
'admin': { password: process.env.ADMIN_PASS },
|
admin: { password: process.env.ADMIN_PASS }
|
||||||
};
|
};
|
||||||
|
|
||||||
// ... some not authenticated middlewares
|
// ... some not authenticated middlewares
|
||||||
|
|
||||||
server.use((req, res, next) => {
|
server.use(async (req, res, next) => {
|
||||||
if (req.originalUrl.startsWith('/logs')) {
|
if (req.originalUrl.startsWith('/logs')) {
|
||||||
var user = auth(req);
|
const user = auth(req);
|
||||||
if (!user || !admins[user.name] || admins[user.name].password !== user.pass) {
|
if (!user || !admins[user.name] || admins[user.name].password !== user.pass) {
|
||||||
res.set('WWW-Authenticate', 'Basic realm="example"');
|
res.set('WWW-Authenticate', 'Basic realm="example"');
|
||||||
return res.status(401).send();
|
return res.status(401).send();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
return next();
|
return next();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// If global log enabled, reorders transports adding web logging.
|
// If global log enabled, reorders transports adding web logging.
|
||||||
|
|
||||||
const loggers = GBLog.getLogger();
|
const loggers = GBLog.getLogger();
|
||||||
require('winston-logs-display')(server, loggers[1]);
|
winston.default(server, loggers[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GBLog.info(`The Bot Server is in RUNNING mode...`);
|
GBLog.info(`The Bot Server is in RUNNING mode...`);
|
||||||
|
|
||||||
// Opens Navigator.
|
// Opens Navigator.
|
||||||
|
|
@ -237,22 +246,20 @@ export class GBServer {
|
||||||
})();
|
})();
|
||||||
};
|
};
|
||||||
if (process.env.CERTIFICATE_PFX) {
|
if (process.env.CERTIFICATE_PFX) {
|
||||||
let options = {
|
const options = {
|
||||||
passphrase: process.env.CERTIFICATE_PASSPHRASE,
|
passphrase: process.env.CERTIFICATE_PASSPHRASE,
|
||||||
pfx: fs.readFileSync(process.env.CERTIFICATE_PFX)
|
pfx: Fs.readFileSync(process.env.CERTIFICATE_PFX)
|
||||||
};
|
};
|
||||||
const httpsServer = https.createServer(options, server).listen(port, mainCallback);
|
const httpsServer = https.createServer(options, server).listen(port, mainCallback);
|
||||||
|
|
||||||
if (process.env.CERTIFICATE2_PFX) {
|
if (process.env.CERTIFICATE2_PFX) {
|
||||||
let options = {
|
const options = {
|
||||||
passphrase: process.env.CERTIFICATE2_PASSPHRASE,
|
passphrase: process.env.CERTIFICATE2_PASSPHRASE,
|
||||||
pfx: fs.readFileSync(process.env.CERTIFICATE2_PFX)
|
pfx: Fs.readFileSync(process.env.CERTIFICATE2_PFX)
|
||||||
};
|
};
|
||||||
httpsServer.addContext(process.env.CERTIFICATE2_DOMAIN, options);
|
httpsServer.addContext(process.env.CERTIFICATE2_DOMAIN, options);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
server.listen(port, mainCallback);
|
server.listen(port, mainCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,12 @@
|
||||||
"declaration": false,
|
"declaration": false,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"mapRoot": "./dist/",
|
"mapRoot": "./dist/",
|
||||||
"module": "commonjs",
|
"moduleResolution": "Node",
|
||||||
"moduleResolution": "node",
|
"module": "ESNext",
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue