Merge pull request #81 from rodrigorodriguez/master
Several bug fixes and start for handling ms-graph calls and sharepoint basic storage
This commit is contained in:
commit
10a2ef71ea
18 changed files with 2076 additions and 2645 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"git.ignoreLimitWarning": true
|
||||||
|
}
|
|
@ -8,9 +8,10 @@
|
||||||
| Releases | [](https://www.npmjs.com/package/botserver/) [](https://www.npmjs.com/package/botlib/) [](https://github.com/semantic-release/semantic-release)|
|
| Releases | [](https://www.npmjs.com/package/botserver/) [](https://www.npmjs.com/package/botlib/) [](https://github.com/semantic-release/semantic-release)|
|
||||||
| [Docker Image](https://github.com/lpicanco/docker-botserver) |      <br/> *Provided by [@lpicanco](https://github.com/lpicanco/docker-botserver)* |
|
| [Docker Image](https://github.com/lpicanco/docker-botserver) |      <br/> *Provided by [@lpicanco](https://github.com/lpicanco/docker-botserver)* |
|
||||||
|
|
||||||
|
|
||||||
#### Watch a video about easeness authoring of bot packages, development environment and self-deployment
|
#### Watch a video about easeness authoring of bot packages, development environment and self-deployment
|
||||||
|
|
||||||
* Now with General Bots you can press F5 on Visual Studio to get a bot factory on your environment* published on November 10th, 2018.
|
* Now with the General Bots server you can press F5 on Visual Studio to get a bot factory on your environment* published on November 10th, 2018.
|
||||||
|
|
||||||
[](https://www.youtube.com/watch?v=AfKTwljoMOs)
|
[](https://www.youtube.com/watch?v=AfKTwljoMOs)
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ Welcome to General Bot Community Edition
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
General Bot is a package based chat bot server focused in convention over configuration and code-less approaches, which brings software packages and application server concepts to help parallel bot development.
|
General Bot is a strongly typed package based chat bot server focused in convention over configuration and code-less approaches, which brings software packages and application server concepts to help parallel bot development.
|
||||||
|
|
||||||
|
|
||||||
## Sample Package #1: [default.gbdialog (VBA)](https://github.com/pragmatismo-io/BotServer/tree/master/packages/default.gbdialog)
|
## Sample Package #1: [default.gbdialog (VBA)](https://github.com/pragmatismo-io/BotServer/tree/master/packages/default.gbdialog)
|
||||||
|
|
4230
package-lock.json
generated
4230
package-lock.json
generated
File diff suppressed because it is too large
Load diff
78
package.json
78
package.json
|
@ -48,30 +48,30 @@
|
||||||
"commit": "git-cz"
|
"commit": "git-cz"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@microsoft/microsoft-graph-client": "1.3.0",
|
"@microsoft/microsoft-graph-client": "1.4.0",
|
||||||
"@semantic-release/exec": "^3.3.0",
|
"@semantic-release/exec": "^3.3.2",
|
||||||
"adal-node": "0.1.28",
|
"adal-node": "0.1.28",
|
||||||
"async": "2.6.1",
|
"async": "2.6.1",
|
||||||
"async-promises": "0.2.1",
|
"async-promises": "0.2.1",
|
||||||
"azure-arm-cognitiveservices": "2.4.0",
|
"azure-arm-cognitiveservices": "2.4.1",
|
||||||
"azure-arm-resource": "7.2.1",
|
"azure-arm-resource": "7.3.0",
|
||||||
"azure-arm-search": "^1.3.0-preview",
|
"azure-arm-search": "^1.3.0-preview",
|
||||||
"azure-arm-sql": "5.6.0",
|
"azure-arm-sql": "5.6.0",
|
||||||
"azure-arm-website": "5.7.0",
|
"azure-arm-website": "5.7.0",
|
||||||
"bluebird": "^3.5.3",
|
"bluebird": "^3.5.3",
|
||||||
"body-parser": "1.18.3",
|
"body-parser": "1.18.3",
|
||||||
"botbuilder": "^4.1.7",
|
"botbuilder": "^4.1.7",
|
||||||
"botbuilder-ai": "^4.1.7",
|
"botbuilder-ai": "^4.2.0",
|
||||||
"botbuilder-azure": "^4.1.7",
|
"botbuilder-azure": "^4.2.0",
|
||||||
"botbuilder-choices": "^4.0.0-preview1.2",
|
"botbuilder-choices": "^4.0.0-preview1.2",
|
||||||
"botbuilder-dialogs": "^4.1.7",
|
"botbuilder-dialogs": "^4.2.0",
|
||||||
"botbuilder-prompts": "^4.0.0-preview1.2",
|
"botbuilder-prompts": "^4.0.0-preview1.2",
|
||||||
"botlib": "^0.1.8",
|
"botlib": "^0.1.10",
|
||||||
"chai": "4.2.0",
|
"chai": "4.2.0",
|
||||||
"child_process": "^1.0.2",
|
"child_process": "^1.0.2",
|
||||||
"chokidar": "2.0.4",
|
"chokidar": "2.0.4",
|
||||||
"cli-spinner": "^0.2.8",
|
"cli-spinner": "^0.2.8",
|
||||||
"csv-parse": "4.1.0",
|
"csv-parse": "4.3.1",
|
||||||
"dotenv-extended": "2.3.0",
|
"dotenv-extended": "2.3.0",
|
||||||
"express": "4.16.4",
|
"express": "4.16.4",
|
||||||
"express-promise-router": "3.0.3",
|
"express-promise-router": "3.0.3",
|
||||||
|
@ -79,68 +79,68 @@
|
||||||
"fs-walk": "0.0.2",
|
"fs-walk": "0.0.2",
|
||||||
"ip": "^1.1.5",
|
"ip": "^1.1.5",
|
||||||
"localize": "0.4.7",
|
"localize": "0.4.7",
|
||||||
"marked": "0.5.2",
|
"marked": "0.6.0",
|
||||||
"mocha": "5.2.0",
|
"mocha": "5.2.0",
|
||||||
"mocha-typescript": "1.1.17",
|
"mocha-typescript": "1.1.17",
|
||||||
"ms": "2.1.1",
|
"ms": "2.1.1",
|
||||||
"ms-rest-azure": "2.5.9",
|
"ms-rest-azure": "2.6.0",
|
||||||
"nexmo": "2.4.0",
|
"nexmo": "2.4.1",
|
||||||
"ngrok": "^3.1.0",
|
"ngrok": "^3.1.0",
|
||||||
"nyc": "^13.1.0",
|
"nyc": "^13.1.0",
|
||||||
"opn": "^5.4.0",
|
"opn": "^5.4.0",
|
||||||
"pragmatismo-io-framework": "1.0.19",
|
"pragmatismo-io-framework": "1.0.19",
|
||||||
"process-exists": "^3.1.0",
|
"process-exists": "^3.1.0",
|
||||||
"public-ip": "^2.4.0",
|
"public-ip": "^3.0.0",
|
||||||
"reflect-metadata": "0.1.12",
|
"reflect-metadata": "0.1.13",
|
||||||
"request-promise-native": "1.0.5",
|
"request-promise-native": "1.0.5",
|
||||||
"scanf": "^1.0.2",
|
"scanf": "^1.0.2",
|
||||||
"sequelize": "4.41.2",
|
"sequelize": "4.42.0",
|
||||||
"sequelize-typescript": "0.6.6",
|
"sequelize-typescript": "0.6.7",
|
||||||
"shx": "^0.3.2",
|
"shx": "^0.3.2",
|
||||||
"simple-git": "^1.107.0",
|
"simple-git": "^1.107.0",
|
||||||
"sqlite3": "4.0.4",
|
"sqlite3": "4.0.6",
|
||||||
"strict-password-generator": "^1.1.1",
|
"strict-password-generator": "^1.1.2",
|
||||||
"swagger-client": "3.8.22",
|
"swagger-client": "3.8.22",
|
||||||
"tedious": "3.0.1",
|
"tedious": "4.1.3",
|
||||||
"ts-node": "7.0.1",
|
"ts-node": "8.0.2",
|
||||||
"typedoc": "0.13.0",
|
"typedoc": "0.14.2",
|
||||||
"typedoc-plugin-external-module-name": "^1.1.3",
|
"typedoc-plugin-external-module-name": "^2.0.0",
|
||||||
"typedoc-plugin-markdown": "^1.1.19",
|
"typedoc-plugin-markdown": "^1.1.25",
|
||||||
"typescript": "3.2.1",
|
"typescript": "3.3.1",
|
||||||
"url-join": "4.0.0",
|
"url-join": "4.0.0",
|
||||||
"vbscript-to-typescript": "^1.0.8",
|
"vbscript-to-typescript": "^1.0.8",
|
||||||
"wait-until": "0.0.2",
|
"wait-until": "0.0.2",
|
||||||
"walk-promise": "0.2.0",
|
"walk-promise": "0.2.0",
|
||||||
"winston": "3.1.0"
|
"winston": "3.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@semantic-release/changelog": "^3.0.1",
|
"@semantic-release/changelog": "^3.0.2",
|
||||||
"@semantic-release/commit-analyzer": "^6.1.0",
|
"@semantic-release/commit-analyzer": "^6.1.0",
|
||||||
"@semantic-release/git": "^7.0.5",
|
"@semantic-release/git": "^7.0.8",
|
||||||
"@semantic-release/github": "^5.2.5",
|
"@semantic-release/github": "^5.2.10",
|
||||||
"@semantic-release/npm": "^5.1.1",
|
"@semantic-release/npm": "^5.1.4",
|
||||||
"@semantic-release/release-notes-generator": "^7.1.4",
|
"@semantic-release/release-notes-generator": "^7.1.4",
|
||||||
"@types/chai": "4.1.7",
|
"@types/chai": "4.1.7",
|
||||||
"@types/mocha": "5.2.5",
|
"@types/mocha": "5.2.5",
|
||||||
"@types/sequelize": "4.27.32",
|
"@types/sequelize": "4.27.34",
|
||||||
"@types/url-join": "0.8.2",
|
"@types/url-join": "4.0.0",
|
||||||
"@types/winston": "2.4.4",
|
"@types/winston": "2.4.4",
|
||||||
"ban-sensitive-files": "1.9.2",
|
"ban-sensitive-files": "1.9.2",
|
||||||
"commitizen": "^3.0.4",
|
"commitizen": "^3.0.5",
|
||||||
"coveralls": "^3.0.2",
|
"coveralls": "^3.0.2",
|
||||||
"cz-conventional-changelog": "^2.1.0",
|
"cz-conventional-changelog": "^2.1.0",
|
||||||
"dependency-check": "3.2.1",
|
"dependency-check": "3.3.0",
|
||||||
"deps-ok": "1.4.1",
|
"deps-ok": "1.4.1",
|
||||||
"git-issues": "1.3.1",
|
"git-issues": "1.3.1",
|
||||||
"license-checker": "24.0.1",
|
"license-checker": "25.0.1",
|
||||||
"nsp": "3.2.1",
|
"nsp": "3.2.1",
|
||||||
"pre-git": "3.17.1",
|
"pre-git": "3.17.1",
|
||||||
"prettier-standard": "8.0.1",
|
"prettier-standard": "9.1.1",
|
||||||
"semantic-release": "^15.12.4",
|
"semantic-release": "^15.13.3",
|
||||||
"standard": "12.0.1",
|
"standard": "12.0.1",
|
||||||
"travis-deploy-once": "5.0.9",
|
"travis-deploy-once": "5.0.11",
|
||||||
"ts-loader": "^5.3.1",
|
"ts-loader": "^5.3.3",
|
||||||
"tslint": "^5.11.0",
|
"tslint": "^5.12.1",
|
||||||
"tslint-microsoft-contrib": "^6.0.0"
|
"tslint-microsoft-contrib": "^6.0.0"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
const UrlJoin = require('url-join');
|
const UrlJoin = require('url-join');
|
||||||
import { BotAdapter } from 'botbuilder';
|
import { BotAdapter } from 'botbuilder';
|
||||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
import { WaterfallDialog, WaterfallStep, WaterfallStepContext } from 'botbuilder-dialogs';
|
||||||
import { GBMinInstance } from 'botlib';
|
import { GBMinInstance } from 'botlib';
|
||||||
import { IGBDialog } from 'botlib';
|
import { IGBDialog } from 'botlib';
|
||||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService';
|
import { GBConfigService } from '../../core.gbapp/services/GBConfigService';
|
||||||
|
@ -60,28 +60,35 @@ export class AdminDialog extends IGBDialog {
|
||||||
await deployer.undeployPackageFromLocalPath(min.instance, UrlJoin('packages', packageName));
|
await deployer.undeployPackageFromLocalPath(min.instance, UrlJoin('packages', packageName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static isSharePointPath(path: string) {
|
||||||
|
return path.indexOf('sharepoint.com') > 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static async deployPackageCommand(min: GBMinInstance, text: string, deployer: GBDeployer) {
|
public static async deployPackageCommand(min: GBMinInstance, text: string, deployer: GBDeployer) {
|
||||||
const packageName = text.split(' ')[1];
|
const packageName = text.split(' ')[1];
|
||||||
const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH');
|
|
||||||
if (!additionalPath)
|
if (AdminDialog.isSharePointPath(packageName)) {
|
||||||
{
|
await deployer.deployFromSharePoint(min.instance.instanceId, packageName);
|
||||||
throw new Error('ADDITIONAL_DEPLOY_PATH is not set and deployPackage was called.');
|
} else {
|
||||||
|
const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH');
|
||||||
|
if (!additionalPath) {
|
||||||
|
throw new Error('ADDITIONAL_DEPLOY_PATH is not set and deployPackage was called.');
|
||||||
|
}
|
||||||
|
await deployer.deployPackageFromLocalPath(min, UrlJoin(additionalPath, packageName));
|
||||||
}
|
}
|
||||||
await deployer.deployPackageFromLocalPath(min, UrlJoin(additionalPath, packageName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async rebuildIndexPackageCommand(min: GBMinInstance, text: string, deployer: GBDeployer) {
|
public static async rebuildIndexPackageCommand(min: GBMinInstance, text: string, deployer: GBDeployer) {
|
||||||
await deployer.rebuildIndex(min.instance);
|
await deployer.rebuildIndex(min.instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async addConnectionCommand(min: GBMinInstance, text: any) {
|
public static async addConnectionCommand(min: GBMinInstance, text: any) {
|
||||||
const packageName = text.split(' ')[1];
|
const packageName = text.split(' ')[1];
|
||||||
const importer = new GBImporter(min.core);
|
const importer = new GBImporter(min.core);
|
||||||
const admin = new GBAdminService(min.core);
|
const admin = new GBAdminService(min.core);
|
||||||
// TODO: await admin.addConnection
|
// TODO: await admin.addConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup dialogs flows and define services call.
|
* Setup dialogs flows and define services call.
|
||||||
*
|
*
|
||||||
|
@ -94,6 +101,8 @@ export class AdminDialog extends IGBDialog {
|
||||||
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);
|
||||||
|
|
||||||
|
AdminDialog.setupSecurityDialogs(min);
|
||||||
|
|
||||||
min.dialogs.add(
|
min.dialogs.add(
|
||||||
new WaterfallDialog('/admin', [
|
new WaterfallDialog('/admin', [
|
||||||
async step => {
|
async step => {
|
||||||
|
@ -151,7 +160,7 @@ export class AdminDialog extends IGBDialog {
|
||||||
|
|
||||||
return await step.replaceDialog('/admin', { firstRun: false });
|
return await step.replaceDialog('/admin', { firstRun: false });
|
||||||
} else if (cmdName === 'setupSecurity') {
|
} else if (cmdName === 'setupSecurity') {
|
||||||
await AdminDialog.setupSecurity(min, step);
|
return await step.beginDialog('/setupSecurity');
|
||||||
} else {
|
} else {
|
||||||
unknownCommand = true;
|
unknownCommand = true;
|
||||||
}
|
}
|
||||||
|
@ -159,7 +168,7 @@ export class AdminDialog extends IGBDialog {
|
||||||
if (unknownCommand) {
|
if (unknownCommand) {
|
||||||
await step.context.sendActivity(Messages[locale].unknown_command);
|
await step.context.sendActivity(Messages[locale].unknown_command);
|
||||||
} else {
|
} else {
|
||||||
await step.context.sendActivity(Messages[locale].finshed_working(cmdName));
|
await step.context.sendActivity(Messages[locale].finished_working);
|
||||||
}
|
}
|
||||||
await step.endDialog();
|
await step.endDialog();
|
||||||
|
|
||||||
|
@ -169,16 +178,66 @@ export class AdminDialog extends IGBDialog {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async setupSecurity(min: any, step: any) {
|
private static setupSecurityDialogs(min: any) {
|
||||||
const locale = step.activity.locale;
|
min.dialogs.add(
|
||||||
const state = `${min.instance.instanceId}${Math.floor(Math.random() * 1000000000)}`;
|
new WaterfallDialog('/setupSecurity', [
|
||||||
await min.adminService.setValue(min.instance.instanceId, 'AntiCSRFAttackState', state);
|
async step => {
|
||||||
const url = `https://login.microsoftonline.com/${min.instance.authenticatorTenant}/oauth2/authorize?client_id=${
|
const locale = step.context.activity.locale;
|
||||||
min.instance.authenticatorClientId
|
const prompt = Messages[locale].enter_authenticator_tenant;
|
||||||
}&response_type=code&redirect_uri=${min.instance.botEndpoint}/${
|
|
||||||
min.instance.botId
|
|
||||||
}/token&state=${state}&response_mode=query`;
|
|
||||||
|
|
||||||
await step.sendActivity(Messages[locale].consent(url));
|
return await step.prompt('textPrompt', prompt);
|
||||||
|
},
|
||||||
|
async step => {
|
||||||
|
step.activeDialog.state.authenticatorTenant = step.result;
|
||||||
|
const locale = step.context.activity.locale;
|
||||||
|
const prompt = Messages[locale].enter_authenticator_authority_host_url;
|
||||||
|
|
||||||
|
return await step.prompt('textPrompt', prompt);
|
||||||
|
},
|
||||||
|
async step => {
|
||||||
|
step.activeDialog.state.authenticatorAuthorityHostUrl = step.result;
|
||||||
|
const locale = step.context.activity.locale;
|
||||||
|
const prompt = Messages[locale].enter_authenticator_client_id;
|
||||||
|
|
||||||
|
return await step.prompt('textPrompt', prompt);
|
||||||
|
},
|
||||||
|
async step => {
|
||||||
|
step.activeDialog.state.authenticatorClientId = step.result;
|
||||||
|
const locale = step.context.activity.locale;
|
||||||
|
const prompt = Messages[locale].enter_authenticator_client_secret;
|
||||||
|
|
||||||
|
return await step.prompt('textPrompt', prompt);
|
||||||
|
},
|
||||||
|
async step => {
|
||||||
|
step.activeDialog.state.authenticatorClientSecret = step.result;
|
||||||
|
|
||||||
|
await min.adminService.updateSecurityInfo(
|
||||||
|
min.instance.instanceId,
|
||||||
|
step.activeDialog.state.authenticatorTenant,
|
||||||
|
step.activeDialog.state.authenticatorAuthorityHostUrl,
|
||||||
|
step.activeDialog.state.authenticatorClientId,
|
||||||
|
step.activeDialog.state.authenticatorClientSecret
|
||||||
|
);
|
||||||
|
|
||||||
|
const locale = step.context.activity.locale;
|
||||||
|
const state = `${min.instance.instanceId}${Math.floor(Math.random() * 1000000000)}`;
|
||||||
|
|
||||||
|
await min.adminService.setValue(min.instance.instanceId, 'AntiCSRFAttackState', state);
|
||||||
|
|
||||||
|
const url = `https://login.microsoftonline.com/${min.instance.authenticatorTenant}/oauth2/authorize?client_id=${
|
||||||
|
min.instance.authenticatorClientId
|
||||||
|
}&response_type=code&redirect_uri=${UrlJoin(
|
||||||
|
min.instance.botEndpoint,
|
||||||
|
min.instance.botId,
|
||||||
|
'/token'
|
||||||
|
)}&state=${state}&response_mode=query`;
|
||||||
|
|
||||||
|
await step.context.sendActivity(Messages[locale].consent(url));
|
||||||
|
|
||||||
|
return await step.replaceDialog('/ask', {isReturning: true});
|
||||||
|
}
|
||||||
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,8 @@ import {
|
||||||
CreatedAt,
|
CreatedAt,
|
||||||
Model,
|
Model,
|
||||||
Table,
|
Table,
|
||||||
UpdatedAt
|
UpdatedAt,
|
||||||
|
DataType
|
||||||
} from 'sequelize-typescript';
|
} from 'sequelize-typescript';
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
|
@ -53,7 +54,7 @@ export class GuaribasAdmin extends Model<GuaribasAdmin> {
|
||||||
@Column
|
@Column
|
||||||
public key: string;
|
public key: string;
|
||||||
|
|
||||||
@Column
|
@Column(DataType.STRING(1024))
|
||||||
public value: string;
|
public value: string;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
|
|
|
@ -38,19 +38,20 @@
|
||||||
|
|
||||||
import { AuthenticationContext, TokenResponse } from 'adal-node';
|
import { AuthenticationContext, TokenResponse } from 'adal-node';
|
||||||
import { IGBCoreService } from 'botlib';
|
import { IGBCoreService } from 'botlib';
|
||||||
|
import { GuaribasInstance } from '../../core.gbapp/models/GBModel';
|
||||||
import { GuaribasAdmin } from '../models/AdminModel';
|
import { GuaribasAdmin } from '../models/AdminModel';
|
||||||
const UrlJoin = require('url-join');
|
const UrlJoin = require('url-join');
|
||||||
const msRestAzure = require('ms-rest-azure');
|
const msRestAzure = require('ms-rest-azure');
|
||||||
const PasswordGenerator = require('strict-password-generator').default;
|
const PasswordGenerator = require('strict-password-generator').default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Services for server administration.
|
||||||
|
*/
|
||||||
export class GBAdminService {
|
export class GBAdminService {
|
||||||
|
|
||||||
public static GB_PROMPT: string = 'GeneralBots: ';
|
public static GB_PROMPT: string = 'GeneralBots: ';
|
||||||
public static masterBotInstanceId = 0;
|
public static masterBotInstanceId = 0;
|
||||||
|
|
||||||
public static StrongRegex = new RegExp(
|
public static StrongRegex = new RegExp('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*+_-])(?=.{8,})');
|
||||||
'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*+_-])(?=.{8,})'
|
|
||||||
);
|
|
||||||
|
|
||||||
public core: IGBCoreService;
|
public core: IGBCoreService;
|
||||||
|
|
||||||
|
@ -62,26 +63,16 @@ export class GBAdminService {
|
||||||
return msRestAzure.generateUuid();
|
return msRestAzure.generateUuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async getADALTokenFromUsername(
|
public static async getADALTokenFromUsername(username: string, password: string) {
|
||||||
username: string,
|
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
|
||||||
password: string
|
|
||||||
) {
|
|
||||||
const credentials = await GBAdminService.getADALCredentialsFromUsername(
|
|
||||||
username,
|
|
||||||
password
|
|
||||||
);
|
|
||||||
const accessToken = credentials.tokenCache._entries[0].accessToken;
|
const accessToken = credentials.tokenCache._entries[0].accessToken;
|
||||||
|
|
||||||
return accessToken;
|
return accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async getADALCredentialsFromUsername(
|
public static async getADALCredentialsFromUsername(username: string, password: string) {
|
||||||
username: string,
|
const credentials = await msRestAzure.loginWithUsernamePassword(username, password);
|
||||||
password: string
|
|
||||||
) {
|
|
||||||
const credentials = await msRestAzure.loginWithUsernamePassword(
|
|
||||||
username,
|
|
||||||
password
|
|
||||||
);
|
|
||||||
return credentials;
|
return credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,31 +105,47 @@ export class GBAdminService {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setValue(
|
public async setValue(instanceId: number, key: string, value: string): Promise<GuaribasAdmin> {
|
||||||
instanceId: number,
|
|
||||||
key: string,
|
|
||||||
value: string
|
|
||||||
): Promise<GuaribasAdmin> {
|
|
||||||
const options = { where: {} };
|
const options = { where: {} };
|
||||||
options.where = { key: key };
|
options.where = { key: key };
|
||||||
let admin = await GuaribasAdmin.findOne(options);
|
let admin = await GuaribasAdmin.findOne(options);
|
||||||
if (admin == null) {
|
if (admin === null) {
|
||||||
admin = new GuaribasAdmin();
|
admin = new GuaribasAdmin();
|
||||||
admin.key = key;
|
admin.key = key;
|
||||||
}
|
}
|
||||||
admin.value = value;
|
admin.value = value;
|
||||||
admin.instanceId = instanceId;
|
admin.instanceId = instanceId;
|
||||||
|
|
||||||
return admin.save();
|
return admin.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async updateSecurityInfo(
|
||||||
|
instanceId: number,
|
||||||
|
authenticatorTenant: string,
|
||||||
|
authenticatorAuthorityHostUrl: string,
|
||||||
|
authenticatorClientId: string,
|
||||||
|
authenticatorClientSecret: string
|
||||||
|
): Promise<GuaribasInstance> {
|
||||||
|
const options = { where: {} };
|
||||||
|
options.where = { instanceId: instanceId };
|
||||||
|
const item = await GuaribasInstance.findOne(options);
|
||||||
|
item.authenticatorTenant = authenticatorTenant;
|
||||||
|
item.authenticatorAuthorityHostUrl = authenticatorAuthorityHostUrl;
|
||||||
|
item.authenticatorClientId = authenticatorClientId;
|
||||||
|
item.authenticatorClientSecret = authenticatorClientSecret;
|
||||||
|
|
||||||
|
return item.save();
|
||||||
|
}
|
||||||
|
|
||||||
public async getValue(instanceId: number, key: string) {
|
public async getValue(instanceId: number, key: string) {
|
||||||
const options = { where: {} };
|
const options = { 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);
|
||||||
|
|
||||||
return Promise.resolve(obj.value);
|
return Promise.resolve(obj.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async acquireElevatedToken(instanceId): Promise<string> {
|
public async acquireElevatedToken(instanceId: number): Promise<string> {
|
||||||
return new Promise<string>(async (resolve, reject) => {
|
return new Promise<string>(async (resolve, reject) => {
|
||||||
const instance = await this.core.loadInstanceById(instanceId);
|
const instance = await this.core.loadInstanceById(instanceId);
|
||||||
|
|
||||||
|
@ -166,21 +173,9 @@ export class GBAdminService {
|
||||||
reject(err);
|
reject(err);
|
||||||
} else {
|
} else {
|
||||||
const token = res as TokenResponse;
|
const token = res as TokenResponse;
|
||||||
await this.setValue(
|
await this.setValue(instanceId, 'accessToken', token.accessToken);
|
||||||
instanceId,
|
await this.setValue(instanceId, 'refreshToken', token.refreshToken);
|
||||||
'accessToken',
|
await this.setValue(instanceId, 'expiresOn', token.expiresOn.toString());
|
||||||
token.accessToken
|
|
||||||
);
|
|
||||||
await this.setValue(
|
|
||||||
instanceId,
|
|
||||||
'refreshToken',
|
|
||||||
token.refreshToken
|
|
||||||
);
|
|
||||||
await this.setValue(
|
|
||||||
instanceId,
|
|
||||||
'expiresOn',
|
|
||||||
token.expiresOn.toString()
|
|
||||||
);
|
|
||||||
resolve(token.accessToken);
|
resolve(token.accessToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,5 +183,4 @@ export class GBAdminService {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ export const Messages = {
|
||||||
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}...`,
|
||||||
finshed_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.`,
|
||||||
hi: text => `Hello, ${text}.`,
|
hi: text => `Hello, ${text}.`,
|
||||||
|
@ -13,7 +13,11 @@ export const Messages = {
|
||||||
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_authority_host_url: 'Enter the Authority Host URL (eg.: https://login.microsoftonline.com): ',
|
||||||
|
enter_authenticator_client_id: 'Enter the Client Id [Application Id](https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview) GUID:',
|
||||||
|
enter_authenticator_client_secret: 'Enter the Client Secret:'
|
||||||
},
|
},
|
||||||
'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...',
|
||||||
|
|
|
@ -36,11 +36,11 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const UrlJoin = require('url-join');
|
|
||||||
import { GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
import { GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||||
import { Sequelize } from 'sequelize-typescript';
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
|
|
||||||
export class GBWhatsappPackage implements IGBPackage {
|
export class GBAzureDeployerPackage implements IGBPackage {
|
||||||
|
|
||||||
public sysPackages: IGBPackage[] = null;
|
public sysPackages: IGBPackage[] = null;
|
||||||
|
|
||||||
public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {}
|
public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {}
|
||||||
|
|
|
@ -224,7 +224,7 @@ export class AzureDeployerService extends GBService {
|
||||||
logger.info(`Deploying Bot Storage...`);
|
logger.info(`Deploying Bot Storage...`);
|
||||||
const administratorLogin = `sa${GBAdminService.getRndReadableIdentifier()}`;
|
const administratorLogin = `sa${GBAdminService.getRndReadableIdentifier()}`;
|
||||||
const administratorPassword = GBAdminService.getRndPassword();
|
const administratorPassword = GBAdminService.getRndPassword();
|
||||||
const storageServer = `${name}-storage-server`;
|
const storageServer = `${name.toLowerCase()}-storage-server`;
|
||||||
const storageName = `${name}-storage`;
|
const storageName = `${name}-storage`;
|
||||||
await this.createStorageServer(
|
await this.createStorageServer(
|
||||||
name,
|
name,
|
||||||
|
@ -311,6 +311,11 @@ export class AzureDeployerService extends GBService {
|
||||||
instance.nlpAppId = nlpAppId;
|
instance.nlpAppId = nlpAppId;
|
||||||
|
|
||||||
logger.info(`Deploying Bot...`);
|
logger.info(`Deploying Bot...`);
|
||||||
|
|
||||||
|
// TODO: Default endpoint, will be updated when it runs in production.
|
||||||
|
|
||||||
|
instance.botEndpoint = 'http://localhost:4242';
|
||||||
|
|
||||||
instance = await this.deployBootBot(
|
instance = await this.deployBootBot(
|
||||||
instance,
|
instance,
|
||||||
name,
|
name,
|
||||||
|
|
|
@ -177,12 +177,11 @@ export class GBCoreService implements IGBCoreService {
|
||||||
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';
|
||||||
const force = GBConfigService.get('STORAGE_SYNC_FORCE') === 'true';
|
|
||||||
logger.info('Syncing database...');
|
logger.info('Syncing database...');
|
||||||
|
|
||||||
return this.sequelize.sync({
|
return this.sequelize.sync({
|
||||||
alter: alter,
|
alter: alter,
|
||||||
force: force
|
force: false // Keep it false this due to data loss danger.
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const msg = `Database synchronization is disabled.`;
|
const msg = `Database synchronization is disabled.`;
|
||||||
|
|
|
@ -43,19 +43,25 @@ const Fs = require('fs');
|
||||||
const WaitUntil = require('wait-until');
|
const WaitUntil = require('wait-until');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const child_process = require('child_process');
|
const child_process = require('child_process');
|
||||||
|
const graph = require('@microsoft/microsoft-graph-client');
|
||||||
|
|
||||||
import { GBMinInstance, IGBCoreService, IGBInstance } from 'botlib';
|
import { GBMinInstance, IGBCoreService, IGBInstance } from 'botlib';
|
||||||
import { GBError,IGBPackage } from 'botlib';
|
import { GBError, IGBPackage } from 'botlib';
|
||||||
import { AzureSearch } from 'pragmatismo-io-framework';
|
import { AzureSearch } from 'pragmatismo-io-framework';
|
||||||
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
|
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
|
||||||
import { GuaribasInstance, GuaribasPackage } from '../models/GBModel';
|
import { GuaribasInstance, GuaribasPackage } from '../models/GBModel';
|
||||||
|
import { GBAdminService } from './../../admin.gbapp/services/GBAdminService';
|
||||||
import { KBService } from './../../kb.gbapp/services/KBService';
|
import { KBService } from './../../kb.gbapp/services/KBService';
|
||||||
import { GBConfigService } from './GBConfigService';
|
import { GBConfigService } from './GBConfigService';
|
||||||
import { GBCoreService } from './GBCoreService';
|
import { GBCoreService } from './GBCoreService';
|
||||||
import { GBImporter } from './GBImporterService';
|
import { GBImporter } from './GBImporterService';
|
||||||
import { GBVMService } from './GBVMService';
|
import { GBVMService } from './GBVMService';
|
||||||
|
|
||||||
/** Deployer service for bots, themes, ai and more. */
|
/**
|
||||||
|
*
|
||||||
|
* Deployer service for bots, themes, ai and more.
|
||||||
|
*/
|
||||||
|
|
||||||
export class GBDeployer {
|
export class GBDeployer {
|
||||||
public static deployFolder = 'packages';
|
public static deployFolder = 'packages';
|
||||||
public core: IGBCoreService;
|
public core: IGBCoreService;
|
||||||
|
@ -170,6 +176,25 @@ export class GBDeployer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async deployFromSharePoint(instanceId: number, path: string) {
|
||||||
|
const adminService = new GBAdminService(this.core);
|
||||||
|
const accessToken = adminService.acquireElevatedToken(instanceId);
|
||||||
|
|
||||||
|
// Initialize Graph client.
|
||||||
|
|
||||||
|
const client = graph.Client.init({
|
||||||
|
authProvider: done => {
|
||||||
|
done(null, accessToken);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const events = await client
|
||||||
|
.api('/me/events')
|
||||||
|
.select('subject,organizer,start,end')
|
||||||
|
.orderby('createdDateTime DESC')
|
||||||
|
.get();
|
||||||
|
}
|
||||||
|
|
||||||
public deployScriptToStorage(instanceId: number, localPath: string) {}
|
public deployScriptToStorage(instanceId: number, localPath: string) {}
|
||||||
|
|
||||||
public deployTheme(localPath: string) {
|
public deployTheme(localPath: string) {
|
||||||
|
@ -184,6 +209,8 @@ export class GBDeployer {
|
||||||
// })
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async deployPackageFromSharePoint(min: GBMinInstance, path: string) {}
|
||||||
|
|
||||||
public async deployPackageFromLocalPath(min: GBMinInstance, localPath: string) {
|
public async deployPackageFromLocalPath(min: GBMinInstance, localPath: string) {
|
||||||
const packageType = Path.extname(localPath);
|
const packageType = Path.extname(localPath);
|
||||||
|
|
||||||
|
@ -375,18 +402,36 @@ export class GBDeployer {
|
||||||
// Skips .gbapp inside deploy folder.
|
// Skips .gbapp inside deploy folder.
|
||||||
if (!e.startsWith('packages')) {
|
if (!e.startsWith('packages')) {
|
||||||
logger.info(`Deploying app: ${e}...`);
|
logger.info(`Deploying app: ${e}...`);
|
||||||
import(e)
|
|
||||||
.then(m => {
|
let folder = Path.join(e, 'node_modules');
|
||||||
const p = new m.Package();
|
if (!Fs.existsSync(folder)) {
|
||||||
p.loadPackage(core, core.sequelize);
|
logger.info(`Installing modules for ${e}...`);
|
||||||
appPackages.push(p);
|
child_process.execSync('npm install', { cwd: e });
|
||||||
logger.info(`App (.gbapp) deployed: ${e}.`);
|
}
|
||||||
|
|
||||||
|
folder = Path.join(e, 'dist');
|
||||||
|
if (!Fs.existsSync()) {
|
||||||
|
logger.info(`Compiling ${e}...`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
child_process.execSync(Path.join(e, 'node_modules/.bin/tsc'), { cwd: e });
|
||||||
|
import(e)
|
||||||
|
.then(m => {
|
||||||
|
const p = new m.Package();
|
||||||
|
p.loadPackage(core, core.sequelize);
|
||||||
|
appPackages.push(p);
|
||||||
|
logger.info(`App (.gbapp) deployed: ${e}.`);
|
||||||
|
appPackagesProcessed++;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
logger.error(`Error deploying .gbapp package: ${e}\n${err}`);
|
||||||
|
appPackagesProcessed++;
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`Error compiling .gbapp package ${e}:\n${error.stdout.toString()}`);
|
||||||
appPackagesProcessed++;
|
appPackagesProcessed++;
|
||||||
})
|
}
|
||||||
.catch(err => {
|
}
|
||||||
logger.error(`Error deploying App (.gbapp): ${e}: ${err}`);
|
|
||||||
appPackagesProcessed++;
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
appPackagesProcessed++;
|
appPackagesProcessed++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ import { GuaribasInstance } from '../models/GBModel';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings';
|
||||||
import { GBAdminPackage } from './../../admin.gbapp/index';
|
import { GBAdminPackage } from './../../admin.gbapp/index';
|
||||||
import { GBDeployer } from './GBDeployer';
|
import { GBDeployer } from './GBDeployer';
|
||||||
|
import { ConfirmPrompt } from 'botbuilder-dialogs';
|
||||||
|
|
||||||
/** Minimal service layer for a bot. */
|
/** Minimal service layer for a bot. */
|
||||||
|
|
||||||
|
@ -193,7 +194,7 @@ export class GBMinService {
|
||||||
);
|
);
|
||||||
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${
|
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${
|
||||||
min.instance.authenticatorClientId
|
min.instance.authenticatorClientId
|
||||||
}&redirect_uri=${min.instance.botEndpoint}/${min.instance.botId}/token`;
|
}&redirect_uri=${UrlJoin(min.instance.botEndpoint, min.instance.botId, 'token')}`;
|
||||||
|
|
||||||
res.redirect(authorizationUrl);
|
res.redirect(authorizationUrl);
|
||||||
});
|
});
|
||||||
|
@ -321,6 +322,7 @@ export class GBMinService {
|
||||||
|
|
||||||
min.dialogs = new DialogSet(dialogState);
|
min.dialogs = new DialogSet(dialogState);
|
||||||
min.dialogs.add(new TextPrompt('textPrompt'));
|
min.dialogs.add(new TextPrompt('textPrompt'));
|
||||||
|
min.dialogs.add(new ConfirmPrompt('confirmPrompt'));
|
||||||
|
|
||||||
return { min, adapter, conversationState };
|
return { min, adapter, conversationState };
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,12 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||||
import { GBMinInstance, IGBCoreService } from 'botlib';
|
import { GBMinInstance, IGBCoreService } from 'botlib';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { DialogClass } from './GBAPIService';
|
import { DialogClass } from './GBAPIService';
|
||||||
import { GBDeployer } from './GBDeployer';
|
import { GBDeployer } from './GBDeployer';
|
||||||
import { TSCompiler } from './TSCompiler';
|
import { TSCompiler } from './TSCompiler';
|
||||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
const logger = require('../../../src/logger');
|
const logger = require('../../../src/logger');
|
||||||
const vm = require('vm');
|
const vm = require('vm');
|
||||||
|
@ -46,10 +46,14 @@ const vb2ts = require('vbscript-to-typescript/dist/converter');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fileoverview Virtualization services for emulation of BASIC.
|
* @fileoverview Virtualization services for emulation of BASIC.
|
||||||
|
* This alpha version is using a converter to translate BASIC to TS
|
||||||
|
* and string replacements to emulate await code.
|
||||||
|
* http://stevehanov.ca/blog/index.php?id=92 should be used to run it without
|
||||||
|
* translation and enhance classic BASIC experience.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export class GBVMService implements IGBCoreService {
|
export class GBVMService implements IGBCoreService {
|
||||||
private script = new vm.Script();
|
private readonly script = new vm.Script();
|
||||||
|
|
||||||
public async loadJS(
|
public async loadJS(
|
||||||
filename: string,
|
filename: string,
|
||||||
|
@ -82,7 +86,7 @@ export class GBVMService implements IGBCoreService {
|
||||||
|
|
||||||
// Run JS into the GB context.
|
// Run JS into the GB context.
|
||||||
const jsfile = `bot.js`;
|
const jsfile = `bot.js`;
|
||||||
let localPath = UrlJoin(path, jsfile);
|
const localPath = UrlJoin(path, jsfile);
|
||||||
|
|
||||||
if (fs.existsSync(localPath)) {
|
if (fs.existsSync(localPath)) {
|
||||||
let code: string = fs.readFileSync(localPath, 'utf8');
|
let code: string = fs.readFileSync(localPath, 'utf8');
|
||||||
|
@ -91,12 +95,11 @@ export class GBVMService implements IGBCoreService {
|
||||||
// Finds all hear calls.
|
// Finds all hear calls.
|
||||||
|
|
||||||
let parsedCode = code;
|
let parsedCode = code;
|
||||||
let hearExp = /(\w+).*hear.*\(\)/;
|
const hearExp = /(\w+).*hear.*\(\)/;
|
||||||
|
|
||||||
let match1;
|
let match1;
|
||||||
|
|
||||||
while ((match1 = hearExp.exec(code))) {
|
while ((match1 = hearExp.exec(code))) {
|
||||||
|
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
|
|
||||||
// Writes async body.
|
// Writes async body.
|
||||||
|
@ -110,7 +113,7 @@ export class GBVMService implements IGBCoreService {
|
||||||
|
|
||||||
pos = pos + match1.index;
|
pos = pos + match1.index;
|
||||||
let tempCode = code.substring(pos + match1[0].length + 1);
|
let tempCode = code.substring(pos + match1[0].length + 1);
|
||||||
let start = pos;
|
const start = pos;
|
||||||
|
|
||||||
// Balances code blocks and checks for exits.
|
// Balances code blocks and checks for exits.
|
||||||
|
|
||||||
|
@ -143,15 +146,15 @@ export class GBVMService implements IGBCoreService {
|
||||||
code = parsedCode;
|
code = parsedCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedCode = parsedCode.replace(/("[^"]*"|'[^']*')|\btalk\b/g, function($0, $1) {
|
parsedCode = parsedCode.replace(/("[^"]*"|'[^']*')|\btalk\b/g, ($0, $1) => {
|
||||||
return $1 == undefined ? 'this.talk' : $1;
|
return $1 == undefined ? 'this.talk' : $1;
|
||||||
});
|
});
|
||||||
|
|
||||||
parsedCode = parsedCode.replace(/("[^"]*"|'[^']*')|\bhear\b/g, function($0, $1) {
|
parsedCode = parsedCode.replace(/("[^"]*"|'[^']*')|\bhear\b/g, ($0, $1) => {
|
||||||
return $1 == undefined ? 'this.hear' : $1;
|
return $1 == undefined ? 'this.hear' : $1;
|
||||||
});
|
});
|
||||||
|
|
||||||
parsedCode = parsedCode.replace(/("[^"]*"|'[^']*')|\bsendEmail\b/g, function($0, $1) {
|
parsedCode = parsedCode.replace(/("[^"]*"|'[^']*')|\bsendEmail\b/g, ($0, $1) => {
|
||||||
return $1 == undefined ? 'this.sendEmail' : $1;
|
return $1 == undefined ? 'this.sendEmail' : $1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -183,7 +186,7 @@ export class GBVMService implements IGBCoreService {
|
||||||
|
|
||||||
const cbId = step.activeDialog.state.cbId;
|
const cbId = step.activeDialog.state.cbId;
|
||||||
const cb = min.cbMap[cbId];
|
const cb = min.cbMap[cbId];
|
||||||
cb.bind({ step: step, context: step.context }); // TODO: Necessary or min.sandbox
|
cb.bind({ step: step, context: step.context }); // TODO: Necessary or min.sandbox?
|
||||||
|
|
||||||
await step.endDialog();
|
await step.endDialog();
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,18 @@ import * as ts from 'typescript';
|
||||||
const logger = require('../../../src/logger');
|
const logger = require('../../../src/logger');
|
||||||
|
|
||||||
export class TSCompiler {
|
export class TSCompiler {
|
||||||
|
|
||||||
|
|
||||||
|
private static shouldIgnoreError(diagnostic) {
|
||||||
|
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||||
|
|
||||||
|
if (message.indexOf('Cannot find name') >= 0 || message.indexOf('Cannot use imports') >= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public compile(
|
public compile(
|
||||||
fileNames: string[],
|
fileNames: string[],
|
||||||
options: ts.CompilerOptions = {
|
options: ts.CompilerOptions = {
|
||||||
|
@ -61,15 +73,19 @@ export class TSCompiler {
|
||||||
const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
|
const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
|
||||||
|
|
||||||
allDiagnostics.forEach(diagnostic => {
|
allDiagnostics.forEach(diagnostic => {
|
||||||
if (diagnostic.file) {
|
if (!TSCompiler.shouldIgnoreError(diagnostic)) {
|
||||||
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!);
|
|
||||||
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||||
logger.error(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
|
|
||||||
} else {
|
if (diagnostic.file) {
|
||||||
logger.error(`${ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')}`);
|
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
||||||
|
logger.error(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
|
||||||
|
} else {
|
||||||
|
logger.error(`${message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return emitResult;
|
return emitResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,14 +60,8 @@ export class AskDialog extends IGBDialog {
|
||||||
new WaterfallDialog('/answerEvent', [
|
new WaterfallDialog('/answerEvent', [
|
||||||
async step => {
|
async step => {
|
||||||
if (step.options && step.options['questionId']) {
|
if (step.options && step.options['questionId']) {
|
||||||
const question = await service.getQuestionById(
|
const question = await service.getQuestionById(min.instance.instanceId, step.options['questionId']);
|
||||||
min.instance.instanceId,
|
const answer = await service.getAnswerById(min.instance.instanceId, question.answerId);
|
||||||
step.options['questionId']
|
|
||||||
);
|
|
||||||
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.
|
||||||
|
|
||||||
|
@ -106,10 +100,7 @@ export class AskDialog extends IGBDialog {
|
||||||
// Spells check the input text before sending Search or NLP.
|
// Spells check the input text before sending Search or NLP.
|
||||||
|
|
||||||
if (min.instance.spellcheckerKey) {
|
if (min.instance.spellcheckerKey) {
|
||||||
const data = await AzureText.getSpelledText(
|
const data = await AzureText.getSpelledText(min.instance.spellcheckerKey, text);
|
||||||
min.instance.spellcheckerKey,
|
|
||||||
text
|
|
||||||
);
|
|
||||||
|
|
||||||
if (data != text) {
|
if (data != text) {
|
||||||
logger.info(`Spelling corrected: ${data}`);
|
logger.info(`Spelling corrected: ${data}`);
|
||||||
|
@ -121,12 +112,7 @@ export class AskDialog extends IGBDialog {
|
||||||
|
|
||||||
user.lastQuestion = text;
|
user.lastQuestion = text;
|
||||||
await min.userProfile.set(step.context, user);
|
await min.userProfile.set(step.context, user);
|
||||||
const resultsA = await service.ask(
|
const resultsA = await service.ask(min.instance, text, min.instance.searchScore, user.subjects);
|
||||||
min.instance,
|
|
||||||
text,
|
|
||||||
min.instance.searchScore,
|
|
||||||
user.subjects
|
|
||||||
);
|
|
||||||
|
|
||||||
// If there is some result, answer immediately.
|
// If there is some result, answer immediately.
|
||||||
|
|
||||||
|
@ -139,30 +125,19 @@ export class AskDialog extends IGBDialog {
|
||||||
|
|
||||||
// Sends the answer to all outputs, including projector.
|
// Sends the answer to all outputs, including projector.
|
||||||
|
|
||||||
await service.sendAnswer(
|
await service.sendAnswer(min.conversationalService, step, resultsA.answer);
|
||||||
min.conversationalService,
|
|
||||||
step,
|
|
||||||
resultsA.answer
|
|
||||||
);
|
|
||||||
|
|
||||||
// Goes to ask loop, again.
|
// Goes to ask loop, again.
|
||||||
|
|
||||||
return await step.replaceDialog('/ask', { isReturning: true });
|
return await step.replaceDialog('/ask', { isReturning: true });
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Second time running Search, now with no filter.
|
// Second time running Search, now with no filter.
|
||||||
|
|
||||||
const resultsB = await service.ask(
|
const resultsB = await service.ask(min.instance, text, min.instance.searchScore, null);
|
||||||
min.instance,
|
|
||||||
text,
|
|
||||||
min.instance.searchScore,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
// If there is some result, answer immediately.
|
// If there is some result, answer immediately.
|
||||||
|
|
||||||
if (resultsB && resultsB.answer) {
|
if (resultsB && resultsB.answer) {
|
||||||
|
|
||||||
// Saves some context info.
|
// Saves some context info.
|
||||||
|
|
||||||
const user = await min.userProfile.get(step.context, {});
|
const user = await min.userProfile.get(step.context, {});
|
||||||
|
@ -173,24 +148,16 @@ export class AskDialog extends IGBDialog {
|
||||||
// Informs user that a broader search will be used.
|
// Informs user that a broader search will be used.
|
||||||
|
|
||||||
if (user.subjects.length > 0) {
|
if (user.subjects.length > 0) {
|
||||||
const subjectText = `${KBService.getSubjectItemsSeparatedBySpaces(
|
const subjectText = `${KBService.getSubjectItemsSeparatedBySpaces(user.subjects)}`;
|
||||||
user.subjects
|
|
||||||
)}`;
|
|
||||||
await step.context.sendActivity(Messages[locale].wider_answer);
|
await step.context.sendActivity(Messages[locale].wider_answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends the answer to all outputs, including projector.
|
// Sends the answer to all outputs, including projector.
|
||||||
|
|
||||||
await service.sendAnswer(
|
await service.sendAnswer(min.conversationalService, step, resultsB.answer);
|
||||||
min.conversationalService,
|
|
||||||
step,
|
|
||||||
resultsB.answer
|
|
||||||
);
|
|
||||||
return await step.replaceDialog('/ask', { isReturning: true });
|
return await step.replaceDialog('/ask', { isReturning: true });
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (!(await min.conversationalService.routeNLP(step, min, text))) {
|
||||||
!(await min.conversationalService.routeNLP(step, min, text))
|
|
||||||
) {
|
|
||||||
await step.context.sendActivity(Messages[locale].did_not_find);
|
await step.context.sendActivity(Messages[locale].did_not_find);
|
||||||
return await step.replaceDialog('/ask', { isReturning: true });
|
return await step.replaceDialog('/ask', { isReturning: true });
|
||||||
}
|
}
|
||||||
|
@ -229,7 +196,11 @@ export class AskDialog extends IGBDialog {
|
||||||
return await step.next();
|
return await step.next();
|
||||||
},
|
},
|
||||||
async step => {
|
async step => {
|
||||||
return await step.replaceDialog('/answer', { query: step.result });
|
if (step.result) {
|
||||||
|
return await step.replaceDialog('/answer', { query: step.result });
|
||||||
|
} else {
|
||||||
|
return await step.next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
|
@ -64,7 +64,7 @@ export class MenuDialog extends IGBDialog {
|
||||||
let rootSubjectId = null;
|
let rootSubjectId = null;
|
||||||
|
|
||||||
if (step.options && step.options['data']) {
|
if (step.options && step.options['data']) {
|
||||||
const subject = step.result.data;
|
const subject = step.options['data'];
|
||||||
|
|
||||||
// If there is a shortcut specified as subject destination, go there.
|
// If there is a shortcut specified as subject destination, go there.
|
||||||
|
|
||||||
|
@ -149,7 +149,6 @@ export class MenuDialog extends IGBDialog {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await step.replaceDialog('/ask', {});
|
|
||||||
} else {
|
} else {
|
||||||
msg.attachments = attachments;
|
msg.attachments = attachments;
|
||||||
await step.context.sendActivity(msg);
|
await step.context.sendActivity(msg);
|
||||||
|
@ -158,16 +157,6 @@ export class MenuDialog extends IGBDialog {
|
||||||
const user = await min.userProfile.get(step.context, {});
|
const user = await min.userProfile.get(step.context, {});
|
||||||
user.isAsking = true;
|
user.isAsking = true;
|
||||||
return await step.next();
|
return await step.next();
|
||||||
},
|
|
||||||
async step => {
|
|
||||||
const text = step.result;
|
|
||||||
const locale = step.context.activity.locale;
|
|
||||||
if (AzureText.isIntentNo(locale, text)) {
|
|
||||||
await step.replaceDialog('/feedback');
|
|
||||||
} else {
|
|
||||||
await step.replaceDialog('/ask');
|
|
||||||
}
|
|
||||||
return await step.next();
|
|
||||||
}
|
}
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
"export-name":false,
|
"export-name":false,
|
||||||
"no-relative-imports": false,
|
"no-relative-imports": false,
|
||||||
"no-backbone-get-set-outside-model": false,
|
"no-backbone-get-set-outside-model": false,
|
||||||
"max-line-length": [true,{"limit":120,"ignore-pattern":"^\\s+\\*"}]
|
"max-line-length": [true,{"limit":120,"ignore-pattern":"^\\s+\\*"}],
|
||||||
|
"await-promise": [true, "Bluebird"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue