Merge branch 'main' of https://github.com/GeneralBots/BotServer
1
.gitignore
vendored
|
@ -29,3 +29,4 @@ package-lock.json
|
||||||
yarn-lock.json
|
yarn-lock.json
|
||||||
logo.svg
|
logo.svg
|
||||||
screenshot.png
|
screenshot.png
|
||||||
|
data.db
|
||||||
|
|
47
.test-init.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import { expect, test } from 'vitest';
|
||||||
|
import { GBServer } from './src/app';
|
||||||
|
import { RootData } from './src/RootData';
|
||||||
|
import { GBMinInstance } from 'botlib';
|
||||||
|
import { Mutex } from 'async-mutex';
|
||||||
|
|
||||||
|
export default function init() {
|
||||||
|
|
||||||
|
const min = {
|
||||||
|
packages: null,
|
||||||
|
appPackages: null,
|
||||||
|
botId: 'gbtest',
|
||||||
|
instance: {botId: 'gbtest'},
|
||||||
|
core: {},
|
||||||
|
conversationalService: {},
|
||||||
|
kbService: {},
|
||||||
|
adminService: {},
|
||||||
|
deployService: {},
|
||||||
|
textServices: {},
|
||||||
|
bot: {},
|
||||||
|
dialogs: {},
|
||||||
|
userState: {},
|
||||||
|
userProfile: {},
|
||||||
|
whatsAppDirectLine: {},
|
||||||
|
cbMap: {},
|
||||||
|
scriptMap: {},
|
||||||
|
sandBoxMap: {},
|
||||||
|
gbappServices: {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GBServer.globals = new RootData();
|
||||||
|
GBServer.globals.server = null;
|
||||||
|
GBServer.globals.httpsServer = null;
|
||||||
|
GBServer.globals.webSessions = {};
|
||||||
|
GBServer.globals.processes = [0, { pid: 1, proc: {step: {}}}];
|
||||||
|
GBServer.globals.files = {};
|
||||||
|
GBServer.globals.appPackages = [];
|
||||||
|
GBServer.globals.sysPackages = [];
|
||||||
|
GBServer.globals.minInstances = [min];
|
||||||
|
GBServer.globals.minBoot = min;
|
||||||
|
GBServer.globals.wwwroot = null;
|
||||||
|
GBServer.globals.entryPointDialog = null;
|
||||||
|
GBServer.globals.debuggers = [];
|
||||||
|
GBServer.globals.indexSemaphore = new Mutex();
|
||||||
|
GBServer.globals.users = {1: {userId: 1}};
|
||||||
|
}
|
2
boot.mjs
|
@ -8,7 +8,7 @@ import pjson from './package.json' assert { type: 'json' };
|
||||||
|
|
||||||
// Displays version of Node JS being used at runtime and others attributes.
|
// Displays version of Node JS being used at runtime and others attributes.
|
||||||
|
|
||||||
process.stdout.write(`General Bots. BotServer@${pjson.version}, botlib@${pjson.dependencies.botlib}, botbuilder@${pjson.dependencies.botbuilder}, node@${process.version.replace('v', '')}, ${process.platform} ${process.arch} `);
|
process.stdout.write(`General Bots. BotServer@${pjson.version}, botlib@${pjson.dependencies.botlib}, node@${process.version.replace('v', '')}, ${process.platform} ${process.arch} `);
|
||||||
console.log(`\nLoading virtual machine source code files...`);
|
console.log(`\nLoading virtual machine source code files...`);
|
||||||
|
|
||||||
var __dirname = process.env.PWD || process.cwd();
|
var __dirname = process.env.PWD || process.cwd();
|
||||||
|
|
10
package.json
|
@ -76,7 +76,7 @@
|
||||||
"@azure/keyvault-keys": "4.8.0",
|
"@azure/keyvault-keys": "4.8.0",
|
||||||
"@azure/ms-rest-js": "2.7.0",
|
"@azure/ms-rest-js": "2.7.0",
|
||||||
"@azure/msal-node": "2.8.1",
|
"@azure/msal-node": "2.8.1",
|
||||||
"@azure/openai": "^2.0.0-beta.1",
|
"@azure/openai": "2.0.0-beta.1",
|
||||||
"@azure/search-documents": "12.0.0",
|
"@azure/search-documents": "12.0.0",
|
||||||
"@azure/storage-blob": "12.18.0",
|
"@azure/storage-blob": "12.18.0",
|
||||||
"@google-cloud/pubsub": "4.4.0",
|
"@google-cloud/pubsub": "4.4.0",
|
||||||
|
@ -137,11 +137,12 @@
|
||||||
"google-libphonenumber": "3.2.34",
|
"google-libphonenumber": "3.2.34",
|
||||||
"googleapis": "126.0.1",
|
"googleapis": "126.0.1",
|
||||||
"hnswlib-node": "3.0.0",
|
"hnswlib-node": "3.0.0",
|
||||||
"html-to-md": "^0.8.5",
|
"html-to-md": "0.8.5",
|
||||||
"http-proxy": "1.18.1",
|
"http-proxy": "1.18.1",
|
||||||
"ibm-watson": "9.1.0",
|
"ibm-watson": "9.1.0",
|
||||||
"instagram-private-api": "^1.46.1",
|
"instagram-private-api": "1.46.1",
|
||||||
"iso-639-1": "3.1.2",
|
"iso-639-1": "3.1.2",
|
||||||
|
"isomorphic-fetch": "3.0.0",
|
||||||
"join-images-updated": "1.1.11",
|
"join-images-updated": "1.1.11",
|
||||||
"js-md5": "0.8.3",
|
"js-md5": "0.8.3",
|
||||||
"json-schema-to-zod": "2.1.0",
|
"json-schema-to-zod": "2.1.0",
|
||||||
|
@ -210,7 +211,7 @@
|
||||||
"textract": "2.5.0",
|
"textract": "2.5.0",
|
||||||
"twilio": "5.1.0",
|
"twilio": "5.1.0",
|
||||||
"twitter-api-v2": "1.17.0",
|
"twitter-api-v2": "1.17.0",
|
||||||
"typeorm": "^0.3.20",
|
"typeorm": "0.3.20",
|
||||||
"typescript": "5.4.5",
|
"typescript": "5.4.5",
|
||||||
"url-join": "5.0.0",
|
"url-join": "5.0.0",
|
||||||
"vhost": "3.0.2",
|
"vhost": "3.0.2",
|
||||||
|
@ -218,6 +219,7 @@
|
||||||
"vm2-process": "2.1.5",
|
"vm2-process": "2.1.5",
|
||||||
"walk-promise": "0.2.0",
|
"walk-promise": "0.2.0",
|
||||||
"washyourmouthoutwithsoap": "1.0.2",
|
"washyourmouthoutwithsoap": "1.0.2",
|
||||||
|
"webdav-server": "2.6.2",
|
||||||
"whatsapp-cloud-api": "0.3.1",
|
"whatsapp-cloud-api": "0.3.1",
|
||||||
"whatsapp-web.js": "https://github.com/Julzk/whatsapp-web.js/tarball/jkr_hotfix_7",
|
"whatsapp-web.js": "https://github.com/Julzk/whatsapp-web.js/tarball/jkr_hotfix_7",
|
||||||
"winston": "3.13.0",
|
"winston": "3.13.0",
|
||||||
|
|
|
@ -313,7 +313,7 @@ export class AdminDialog extends IGBDialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
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} /${GBConfigService.get('STORAGE_LIBRARY')}/${botId}.gbai/${packageName}`;
|
||||||
} else {
|
} else {
|
||||||
cmd1 = `deployPackage ${packageName}`;
|
cmd1 = `deployPackage ${packageName}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************\
|
/*****************************************************************************\
|
||||||
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
||||||
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
|
@ -7,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -23,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -49,13 +47,14 @@ import { GBSharePointService } from '../../sharepoint.gblib/services/SharePointS
|
||||||
import { GuaribasAdmin } from '../models/AdminModel.js';
|
import { GuaribasAdmin } from '../models/AdminModel.js';
|
||||||
import msRestAzure from 'ms-rest-azure';
|
import msRestAzure from 'ms-rest-azure';
|
||||||
import Path from 'path';
|
import Path from 'path';
|
||||||
import { caseSensitive_Numbs_SpecialCharacters_PW, lowercase_PW } from 'super-strong-password-generator'
|
import { caseSensitive_Numbs_SpecialCharacters_PW, lowercase_PW } from 'super-strong-password-generator';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import Fs from 'fs';
|
import Fs from 'fs';
|
||||||
import { GBServer } from '../../../src/app.js';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||||
import { DialogKeywords } from '../../basic.gblib/services/DialogKeywords.js';
|
import { DialogKeywords } from '../../basic.gblib/services/DialogKeywords.js';
|
||||||
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
||||||
|
import { GBUtil } from '../../../src/util.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Services for server administration.
|
* Services for server administration.
|
||||||
|
@ -89,45 +88,40 @@ export class GBAdminService implements IGBAdminService {
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
||||||
|
|
||||||
return this.getNumberIdentifier(6);
|
return this.getNumberIdentifier(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getRndPassword(): string {
|
public static getRndPassword(): string {
|
||||||
|
|
||||||
let password = caseSensitive_Numbs_SpecialCharacters_PW(15);
|
let password = caseSensitive_Numbs_SpecialCharacters_PW(15);
|
||||||
password = password.replace(/[\@\[\=\:\;\?\"\'\#]/gi, '*');
|
password = password.replace(/[\@\[\=\:\;\?\"\'\#]/gi, '*');
|
||||||
|
|
||||||
const removeRepeatedChars = (s, r) => {
|
const removeRepeatedChars = (s, r) => {
|
||||||
let res = '', last = null, counter = 0;
|
let res = '',
|
||||||
|
last = null,
|
||||||
|
counter = 0;
|
||||||
s.split('').forEach(char => {
|
s.split('').forEach(char => {
|
||||||
if (char == last)
|
if (char == last) counter++;
|
||||||
counter++;
|
else {
|
||||||
else {
|
counter = 0;
|
||||||
counter = 0;
|
last = char;
|
||||||
last = char;
|
}
|
||||||
}
|
if (counter < r) res += char;
|
||||||
if (counter < r)
|
|
||||||
res += char;
|
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
}
|
};
|
||||||
|
|
||||||
return removeRepeatedChars(password, 1);
|
return removeRepeatedChars(password, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getRndReadableIdentifier(): string {
|
public static getRndReadableIdentifier(): string {
|
||||||
|
|
||||||
return lowercase_PW(14);
|
return lowercase_PW(14);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getNumberIdentifier(digits: number = 14): string {
|
public static getNumberIdentifier(digits: number = 14): string {
|
||||||
|
|
||||||
if (digits <= 0) {
|
if (digits <= 0) {
|
||||||
throw new Error('Number of digits should be greater than 0.');
|
throw new Error('Number of digits should be greater than 0.');
|
||||||
}
|
}
|
||||||
|
@ -155,7 +149,6 @@ export class GBAdminService implements IGBAdminService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async undeployPackageCommand(text: string, min: GBMinInstance) {
|
public static async undeployPackageCommand(text: string, 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);
|
||||||
|
@ -167,7 +160,12 @@ export class GBAdminService implements IGBAdminService {
|
||||||
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, user: GuaribasUser, text: string, deployer: IGBDeployer) {
|
public static async deployPackageCommand(
|
||||||
|
min: GBMinInstance,
|
||||||
|
user: GuaribasUser,
|
||||||
|
text: string,
|
||||||
|
deployer: IGBDeployer
|
||||||
|
) {
|
||||||
const packageName = text.split(' ')[1];
|
const packageName = text.split(' ')[1];
|
||||||
|
|
||||||
if (!this.isSharePointPath(packageName)) {
|
if (!this.isSharePointPath(packageName)) {
|
||||||
|
@ -190,19 +188,21 @@ export class GBAdminService implements IGBAdminService {
|
||||||
await deployer['cleanupPackage'](min.instance, packageName);
|
await deployer['cleanupPackage'](min.instance, packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
await deployer['downloadFolder'](min,
|
if (!GBConfigService.get('STORAGE_NAME')) {
|
||||||
Path.join('work', `${gbai}`),
|
const path = Path.join(GBConfigService.get('STORAGE_LIBRARY'), gbaiPath);
|
||||||
Path.basename(localFolder));
|
GBUtil.copyIfNewerRecursive(path, localFolder);
|
||||||
|
} else {
|
||||||
|
await deployer['downloadFolder'](min, Path.join('work', `${gbai}`), Path.basename(localFolder));
|
||||||
|
}
|
||||||
await deployer['deployPackage2'](min, user, localFolder);
|
await deployer['deployPackage2'](min, user, localFolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static async rebuildIndexPackageCommand(min: GBMinInstance, deployer: GBDeployer) {
|
public static async rebuildIndexPackageCommand(min: GBMinInstance, deployer: GBDeployer) {
|
||||||
const service = await AzureDeployerService.createInstance(deployer);
|
const service = await AzureDeployerService.createInstance(deployer);
|
||||||
const searchIndex = min.instance.searchIndex ? min.instance.searchIndex : GBServer.globals.minBoot.instance.searchIndex;
|
const searchIndex = min.instance.searchIndex
|
||||||
await deployer.rebuildIndex(
|
? min.instance.searchIndex
|
||||||
min.instance,
|
: GBServer.globals.minBoot.instance.searchIndex;
|
||||||
service.getKBSearchSchema(searchIndex)
|
await deployer.rebuildIndex(min.instance, service.getKBSearchSchema(searchIndex));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async syncBotServerCommand(min: GBMinInstance, deployer: GBDeployer) {
|
public static async syncBotServerCommand(min: GBMinInstance, deployer: GBDeployer) {
|
||||||
|
@ -245,15 +245,15 @@ export class GBAdminService implements IGBAdminService {
|
||||||
return obj.value;
|
return obj.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async acquireElevatedToken(instanceId: number, root: boolean = false,
|
public async acquireElevatedToken(
|
||||||
|
instanceId: number,
|
||||||
|
root: boolean = false,
|
||||||
tokenName: string = '',
|
tokenName: string = '',
|
||||||
clientId: string = null,
|
clientId: string = null,
|
||||||
clientSecret: string = null,
|
clientSecret: string = null,
|
||||||
host: string = null,
|
host: string = null,
|
||||||
tenant: string = null
|
tenant: string = null
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
|
|
||||||
|
|
||||||
if (root) {
|
if (root) {
|
||||||
const minBoot = GBServer.globals.minBoot;
|
const minBoot = GBServer.globals.minBoot;
|
||||||
instanceId = minBoot.instance.instanceId;
|
instanceId = minBoot.instance.instanceId;
|
||||||
|
@ -267,7 +267,6 @@ export class GBAdminService implements IGBAdminService {
|
||||||
throw new Error(`/setupSecurity is required before running /publish.`);
|
throw new Error(`/setupSecurity is required before running /publish.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
@ -276,14 +275,10 @@ export class GBAdminService implements IGBAdminService {
|
||||||
const accessToken = await this.getValue(instanceId, `${tokenName}accessToken`);
|
const accessToken = await this.getValue(instanceId, `${tokenName}accessToken`);
|
||||||
resolve(accessToken);
|
resolve(accessToken);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (tokenName && !root) {
|
if (tokenName && !root) {
|
||||||
|
|
||||||
const refreshToken = await this.getValue(instanceId, `${tokenName}refreshToken`);
|
const refreshToken = await this.getValue(instanceId, `${tokenName}refreshToken`);
|
||||||
|
|
||||||
let url = urlJoin(
|
let url = urlJoin(host, tenant, 'oauth/token');
|
||||||
host,
|
|
||||||
tenant, 'oauth/token');
|
|
||||||
let buff = new Buffer(`${clientId}:${clientSecret}`);
|
let buff = new Buffer(`${clientId}:${clientSecret}`);
|
||||||
const base64 = buff.toString('base64');
|
const base64 = buff.toString('base64');
|
||||||
|
|
||||||
|
@ -295,8 +290,8 @@ export class GBAdminService implements IGBAdminService {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
},
|
},
|
||||||
body: new URLSearchParams({
|
body: new URLSearchParams({
|
||||||
'grant_type': 'refresh_token',
|
grant_type: 'refresh_token',
|
||||||
'refresh_token': refreshToken
|
refresh_token: refreshToken
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
const result = await fetch(url, options);
|
const result = await fetch(url, options);
|
||||||
|
@ -313,15 +308,15 @@ export class GBAdminService implements IGBAdminService {
|
||||||
|
|
||||||
await this.setValue(instanceId, `${tokenName}accessToken`, token['access_token']);
|
await this.setValue(instanceId, `${tokenName}accessToken`, token['access_token']);
|
||||||
await this.setValue(instanceId, `${tokenName}refreshToken`, token['refresh_token']);
|
await this.setValue(instanceId, `${tokenName}refreshToken`, token['refresh_token']);
|
||||||
await this.setValue(instanceId, `${tokenName}expiresOn`,
|
await this.setValue(
|
||||||
new Date(Date.now() + (token['expires_in'] * 1000)).toString());
|
instanceId,
|
||||||
|
`${tokenName}expiresOn`,
|
||||||
|
new Date(Date.now() + token['expires_in'] * 1000).toString()
|
||||||
|
);
|
||||||
await this.setValue(instanceId, `${tokenName}AntiCSRFAttackState`, null);
|
await this.setValue(instanceId, `${tokenName}AntiCSRFAttackState`, null);
|
||||||
|
|
||||||
resolve(token['access_token']);
|
resolve(token['access_token']);
|
||||||
|
} else {
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
const oauth2 = tokenName ? 'oauth' : 'oauth2';
|
const oauth2 = tokenName ? 'oauth' : 'oauth2';
|
||||||
const authorizationUrl = urlJoin(
|
const authorizationUrl = urlJoin(
|
||||||
tokenName ? host : instance.authenticatorAuthorityHostUrl,
|
tokenName ? host : instance.authenticatorAuthorityHostUrl,
|
||||||
|
@ -359,5 +354,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> {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -1,31 +1,29 @@
|
||||||
/*****************************************************************************\
|
/*****************************************************************************\
|
||||||
| ( )_ _ |
|
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
||||||
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' v `\ /'_`\ |
|
| ██ ███ ████ █ ██ █ ████ █████ ██████ ██ ████ █ █ █ ██ |
|
||||||
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__,\| (˅) |( (_) ) |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| | | ( )_) | |
|
|
||||||
| (_) \___/' |
|
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model,this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
| under the terms of the GNU Affero General Public License,version 3, |
|
| under the terms of the GNU Affero General Public License, version 3, |
|
||||||
| or under a proprietary license. |
|
| or under a proprietary license. |
|
||||||
| |
|
| |
|
||||||
| The texts of the GNU Affero General Public License with an additional |
|
| The texts of the GNU Affero General Public License with an additional |
|
||||||
| permission and of our proprietary license can be found at and |
|
| permission and of our proprietary license can be found at and |
|
||||||
| in the LICENSE file you have received along with this program. |
|
| in the LICENSE file you have received along with this program. |
|
||||||
| |
|
| |
|
||||||
| This program is distributed in the hope that it will be useful, |
|
| This program is distributed in the hope that it will be useful, |
|
||||||
| but WITHOUT ANY WARRANTY,without even the implied warranty of |
|
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights,title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
| |
|
| |
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
@ -39,6 +37,7 @@ import SwaggerClient from 'swagger-client';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import { CodeServices } from '../../gpt.gblib/services/CodeServices.js';
|
import { CodeServices } from '../../gpt.gblib/services/CodeServices.js';
|
||||||
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
||||||
|
import { GBUtil } from '../../../src/util.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Web Automation services of conversation to be called by BASIC.
|
* Web Automation services of conversation to be called by BASIC.
|
||||||
|
@ -156,12 +155,8 @@ export class DebuggerService {
|
||||||
|
|
||||||
let min: GBMinInstance = GBServer.globals.minInstances.filter(p => p.instance.botId === botId)[0];
|
let min: GBMinInstance = GBServer.globals.minInstances.filter(p => p.instance.botId === botId)[0];
|
||||||
|
|
||||||
const client = await new SwaggerClient({
|
const client = await GBUtil.getDirectLineClient(min);
|
||||||
spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')),
|
|
||||||
requestInterceptor: req => {
|
|
||||||
req.headers['Authorization'] = `Bearer ${min.instance.webchatKey}`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
GBServer.globals.debuggers[botId].client = client;
|
GBServer.globals.debuggers[botId].client = client;
|
||||||
const response = await client.apis.Conversations.Conversations_StartConversation();
|
const response = await client.apis.Conversations.Conversations_StartConversation();
|
||||||
const conversationId = response.obj.conversationId;
|
const conversationId = response.obj.conversationId;
|
||||||
|
|
|
@ -1,31 +1,29 @@
|
||||||
/*****************************************************************************\
|
/*****************************************************************************\
|
||||||
| ( )_ _ |
|
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
||||||
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' v `\ /'_`\ |
|
| ██ ███ ████ █ ██ █ ████ █████ ██████ ██ ████ █ █ █ ██ |
|
||||||
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__,\| (˅) |( (_) ) |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| | | ( )_) | |
|
|
||||||
| (_) \___/' |
|
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model,this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
| under the terms of the GNU Affero General Public License,version 3, |
|
| under the terms of the GNU Affero General Public License, version 3, |
|
||||||
| or under a proprietary license. |
|
| or under a proprietary license. |
|
||||||
| |
|
| |
|
||||||
| The texts of the GNU Affero General Public License with an additional |
|
| The texts of the GNU Affero General Public License with an additional |
|
||||||
| permission and of our proprietary license can be found at and |
|
| permission and of our proprietary license can be found at and |
|
||||||
| in the LICENSE file you have received along with this program. |
|
| in the LICENSE file you have received along with this program. |
|
||||||
| |
|
| |
|
||||||
| This program is distributed in the hope that it will be useful, |
|
| This program is distributed in the hope that it will be useful, |
|
||||||
| but WITHOUT ANY WARRANTY,without even the implied warranty of |
|
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights,title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
| |
|
| |
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
@ -429,7 +427,7 @@ export class DialogKeywords {
|
||||||
* @example TALK TOLIST (array,member)
|
* @example TALK TOLIST (array,member)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public async getToLst(pid, array, member) {
|
public async getToLst({pid, array, member}) {
|
||||||
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
||||||
|
|
||||||
if (!array) {
|
if (!array) {
|
||||||
|
@ -1350,12 +1348,7 @@ export class DialogKeywords {
|
||||||
|
|
||||||
const conversation = min['apiConversations'][pid];
|
const conversation = min['apiConversations'][pid];
|
||||||
|
|
||||||
const client = await new SwaggerClient({
|
const client = await GBUtil.getDirectLineClient(min);
|
||||||
spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')),
|
|
||||||
requestInterceptor: req => {
|
|
||||||
req.headers['Authorization'] = `Bearer ${min.instance.webchatKey}`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
conversation.client = client;
|
conversation.client = client;
|
||||||
const response = await client.apis.Conversations.Conversations_StartConversation();
|
const response = await client.apis.Conversations.Conversations_StartConversation();
|
||||||
conversation.conversationId = response.obj.conversationId;
|
conversation.conversationId = response.obj.conversationId;
|
||||||
|
@ -1368,7 +1361,7 @@ export class DialogKeywords {
|
||||||
const step = proc.step;
|
const step = proc.step;
|
||||||
const min = GBServer.globals.minInstances.filter(p => p.instance.instanceId == proc.instanceId)[0];
|
const min = GBServer.globals.minInstances.filter(p => p.instance.instanceId == proc.instanceId)[0];
|
||||||
const sec = new SecService();
|
const sec = new SecService();
|
||||||
const user = await sec.getUserFromId(min.instance.instanceId, proc.userId);
|
const user = GBServer.globals.users [proc.userId];
|
||||||
const params = user ? JSON.parse(user.params) : {};
|
const params = user ? JSON.parse(user.params) : {};
|
||||||
return {
|
return {
|
||||||
min,
|
min,
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
import { GBVMService } from './GBVMService';
|
|
||||||
import { expect, test } from 'vitest'
|
|
||||||
|
|
||||||
test('Default', () => {
|
|
||||||
|
|
||||||
|
|
||||||
const args = GBVMService.getSetScheduleKeywordArgs(`
|
|
||||||
|
|
||||||
SET SCHEDULE "0 0 */1 * * *"
|
|
||||||
SET SCHEDULE "0 0 */3 * * *"
|
|
||||||
SET SCHEDULE "0 0 */2 * * *"
|
|
||||||
SET SCHEDULE "0 0 */2 * * *"
|
|
||||||
SET SCHEDULE "0 0 */3 * * *"
|
|
||||||
|
|
||||||
`);
|
|
||||||
|
|
||||||
expect(args.length).toBe(5);
|
|
||||||
|
|
||||||
});
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
import { GBMinInstance, GBService, IGBCoreService, GBLog } from 'botlib';
|
import { GBMinInstance, GBService, IGBCoreService, GBLog } from 'botlib';
|
||||||
import * as Fs from 'fs';
|
import * as Fs from 'fs';
|
||||||
import * as ji from 'just-indent'
|
import * as ji from 'just-indent';
|
||||||
import { GBServer } from '../../../src/app.js';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
|
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
|
@ -52,8 +52,8 @@ import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
||||||
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||||
import { SystemKeywords } from './SystemKeywords.js';
|
import { SystemKeywords } from './SystemKeywords.js';
|
||||||
import { Sequelize, QueryTypes } from '@sequelize/core';
|
import { Sequelize, QueryTypes } from '@sequelize/core';
|
||||||
import { z } from "zod";
|
import { z } from 'zod';
|
||||||
import { zodToJsonSchema } from "zod-to-json-schema";
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fileoverview Decision was to priorize security(isolation) and debugging,
|
* @fileoverview Decision was to priorize security(isolation) and debugging,
|
||||||
|
@ -68,7 +68,8 @@ export class GBVMService extends GBService {
|
||||||
public static API_PORT = 1111;
|
public static API_PORT = 1111;
|
||||||
|
|
||||||
public async loadDialogPackage(folder: string, min: GBMinInstance, core: IGBCoreService, deployer: GBDeployer) {
|
public async loadDialogPackage(folder: string, min: GBMinInstance, core: IGBCoreService, deployer: GBDeployer) {
|
||||||
const files = await walkPromise(folder);
|
const ignore = Path.join('work', DialogKeywords.getGBAIPath(min.botId, 'gbdialog'), 'node_modules');
|
||||||
|
const files = await walkPromise(folder, { ignore: [ignore] });
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(files, async file => {
|
await CollectionUtil.asyncForEach(files, async file => {
|
||||||
if (!file) {
|
if (!file) {
|
||||||
|
@ -77,9 +78,7 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
let filename: string = file.name;
|
let filename: string = file.name;
|
||||||
|
|
||||||
if (filename.endsWith('.docx')) {
|
filename = await this.loadDialog(filename, folder, min);
|
||||||
filename = await this.loadDialog(filename, folder, min);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,14 +90,11 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
//check every key for being same
|
//check every key for being same
|
||||||
return Object.keys(obj1).every(function (key) {
|
return Object.keys(obj1).every(function (key) {
|
||||||
|
|
||||||
//if object
|
//if object
|
||||||
if ((typeof obj1[key] == "object") && (typeof obj2[key] == "object")) {
|
if (typeof obj1[key] == 'object' && typeof obj2[key] == 'object') {
|
||||||
|
|
||||||
//recursively check
|
//recursively check
|
||||||
return GBVMService.compare(obj1[key], obj2[key]);
|
return GBVMService.compare(obj1[key], obj2[key]);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//do the normal compare
|
//do the normal compare
|
||||||
return obj1[key] === obj2[key];
|
return obj1[key] === obj2[key];
|
||||||
}
|
}
|
||||||
|
@ -106,14 +102,27 @@ export class GBVMService extends GBService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadDialog(filename: string, folder: string, min: GBMinInstance) {
|
public async loadDialog(filename: string, folder: string, min: GBMinInstance) {
|
||||||
|
const isWord = filename.endsWith('.docx');
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
isWord ||
|
||||||
|
filename.endsWith('.vbs') ||
|
||||||
|
filename.endsWith('.vb') ||
|
||||||
|
filename.endsWith('.vba') ||
|
||||||
|
filename.endsWith('.bas') ||
|
||||||
|
filename.endsWith('.basic')
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const wordFile = filename;
|
const wordFile = filename;
|
||||||
const vbsFile = filename.substr(0, filename.indexOf('docx')) + 'vbs';
|
const vbsFile = isWord ? filename.substr(0, filename.indexOf('docx')) + 'vbs' : filename;
|
||||||
const fullVbsFile = urlJoin(folder, vbsFile);
|
const fullVbsFile = urlJoin(folder, vbsFile);
|
||||||
const docxStat = Fs.statSync(urlJoin(folder, wordFile));
|
const docxStat = Fs.statSync(urlJoin(folder, wordFile));
|
||||||
const interval = 3000; // If compiled is older 30 seconds, then recompile.
|
const interval = 3000; // If compiled is older 30 seconds, then recompile.
|
||||||
let writeVBS = true;
|
let writeVBS = true;
|
||||||
|
|
||||||
|
|
||||||
// TODO: #412.
|
// TODO: #412.
|
||||||
// const subscription = {
|
// const subscription = {
|
||||||
// changeType: 'created,updated',
|
// changeType: 'created,updated',
|
||||||
|
@ -129,7 +138,6 @@ export class GBVMService extends GBService {
|
||||||
// await client.api('/subscriptions')
|
// await client.api('/subscriptions')
|
||||||
// .post(subscription);
|
// .post(subscription);
|
||||||
|
|
||||||
|
|
||||||
if (Fs.existsSync(fullVbsFile)) {
|
if (Fs.existsSync(fullVbsFile)) {
|
||||||
const vbsStat = Fs.statSync(fullVbsFile);
|
const vbsStat = Fs.statSync(fullVbsFile);
|
||||||
if (docxStat['mtimeMs'] < vbsStat['mtimeMs'] + interval) {
|
if (docxStat['mtimeMs'] < vbsStat['mtimeMs'] + interval) {
|
||||||
|
@ -140,26 +148,9 @@ export class GBVMService extends GBService {
|
||||||
let mainName = GBVMService.getMethodNameFromVBSFilename(filename);
|
let mainName = GBVMService.getMethodNameFromVBSFilename(filename);
|
||||||
min.scriptMap[filename] = mainName;
|
min.scriptMap[filename] = mainName;
|
||||||
|
|
||||||
if (writeVBS) {
|
if (writeVBS && GBConfigService.get('STORAGE_NAME')) {
|
||||||
let text = await this.getTextFromWord(folder, wordFile);
|
let text = await this.getTextFromWord(folder, wordFile);
|
||||||
|
|
||||||
// Pre process SET SCHEDULE calls.
|
|
||||||
|
|
||||||
const schedules = GBVMService.getSetScheduleKeywordArgs(text);
|
|
||||||
|
|
||||||
const s = new ScheduleServices();
|
|
||||||
await s.deleteScheduleIfAny(min, mainName);
|
|
||||||
|
|
||||||
let i = 1;
|
|
||||||
await CollectionUtil.asyncForEach(schedules, async (syntax) => {
|
|
||||||
|
|
||||||
if (s) {
|
|
||||||
await s.createOrUpdateSchedule(min, syntax, `${mainName};${i++}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
text = text.replace(/^\s*SET SCHEDULE (.*)/gim, '');
|
|
||||||
|
|
||||||
// Write VBS file without pragma keywords.
|
// Write VBS file without pragma keywords.
|
||||||
|
|
||||||
Fs.writeFileSync(urlJoin(folder, vbsFile), text);
|
Fs.writeFileSync(urlJoin(folder, vbsFile), text);
|
||||||
|
@ -167,6 +158,41 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
// Process node_modules install.
|
// Process node_modules install.
|
||||||
|
|
||||||
|
this.processNodeModules(folder, min);
|
||||||
|
|
||||||
|
// Hot swap for .vbs files.
|
||||||
|
|
||||||
|
const fullFilename = urlJoin(folder, filename);
|
||||||
|
if (process.env.DEV_HOTSWAP) {
|
||||||
|
Fs.watchFile(fullFilename, async () => {
|
||||||
|
await this.translateBASIC(mainName, fullFilename, min);
|
||||||
|
const parsedCode: string = Fs.readFileSync(jsfile, 'utf8');
|
||||||
|
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const compiledAt = Fs.statSync(fullFilename);
|
||||||
|
const jsfile = urlJoin(folder, `${filename}.js`);
|
||||||
|
|
||||||
|
if (Fs.existsSync(jsfile)) {
|
||||||
|
const jsStat = Fs.statSync(jsfile);
|
||||||
|
const interval = 1000; // If compiled is older 1 seconds, then recompile.
|
||||||
|
if (compiledAt.isFile() && compiledAt['mtimeMs'] > jsStat['mtimeMs'] + interval) {
|
||||||
|
await this.translateBASIC(mainName, fullFilename, min);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await this.translateBASIC(mainName, fullFilename, min);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Syncronizes Database Objects with the ones returned from "Word".
|
||||||
|
|
||||||
|
this.syncStorageFromTABLE(folder, filename, min, mainName);
|
||||||
|
|
||||||
|
const parsedCode: string = Fs.readFileSync(jsfile, 'utf8');
|
||||||
|
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
private processNodeModules(folder: string, min: GBMinInstance) {
|
||||||
const node_modules = urlJoin(process.env.PWD, folder, 'node_modules');
|
const node_modules = urlJoin(process.env.PWD, folder, 'node_modules');
|
||||||
if (!Fs.existsSync(node_modules)) {
|
if (!Fs.existsSync(node_modules)) {
|
||||||
const packageJson = `
|
const packageJson = `
|
||||||
|
@ -193,33 +219,9 @@ export class GBVMService extends GBService {
|
||||||
const npmPath = urlJoin(process.env.PWD, 'node_modules', '.bin', 'npm');
|
const npmPath = urlJoin(process.env.PWD, 'node_modules', '.bin', 'npm');
|
||||||
child_process.execSync(`${npmPath} install`, { cwd: folder });
|
child_process.execSync(`${npmPath} install`, { cwd: folder });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Hot swap for .vbs files.
|
private syncStorageFromTABLE(folder: string, filename: string, min: GBMinInstance, mainName: string) {
|
||||||
|
|
||||||
const fullFilename = urlJoin(folder, filename);
|
|
||||||
if (process.env.DEV_HOTSWAP) {
|
|
||||||
Fs.watchFile(fullFilename, async () => {
|
|
||||||
await this.translateBASIC(mainName, fullFilename, min);
|
|
||||||
const parsedCode: string = Fs.readFileSync(jsfile, 'utf8');
|
|
||||||
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const compiledAt = Fs.statSync(fullFilename);
|
|
||||||
const jsfile = urlJoin(folder, `${filename}.js`);
|
|
||||||
|
|
||||||
if (Fs.existsSync(jsfile)) {
|
|
||||||
const jsStat = Fs.statSync(jsfile);
|
|
||||||
const interval = 30000; // If compiled is older 30 seconds, then recompile.
|
|
||||||
if (compiledAt.isFile() && compiledAt['mtimeMs'] > jsStat['mtimeMs'] + interval) {
|
|
||||||
await this.translateBASIC(mainName, fullFilename, min);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await this.translateBASIC(mainName, fullFilename, min);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Syncronizes Database Objects with the ones returned from "Word".
|
|
||||||
|
|
||||||
const tablesFile = urlJoin(folder, `${filename}.tables.json`);
|
const tablesFile = urlJoin(folder, `${filename}.tables.json`);
|
||||||
let sync = false;
|
let sync = false;
|
||||||
|
|
||||||
|
@ -229,7 +231,6 @@ export class GBVMService extends GBService {
|
||||||
const tableDef = JSON.parse(Fs.readFileSync(tablesFile, 'utf8')) as any;
|
const tableDef = JSON.parse(Fs.readFileSync(tablesFile, 'utf8')) as any;
|
||||||
|
|
||||||
const getTypeBasedOnCondition = (t, size) => {
|
const getTypeBasedOnCondition = (t, size) => {
|
||||||
|
|
||||||
if (1) {
|
if (1) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case 'string':
|
case 'string':
|
||||||
|
@ -253,7 +254,6 @@ export class GBVMService extends GBService {
|
||||||
default:
|
default:
|
||||||
return { type: 'TABLE', name: t };
|
return { type: 'TABLE', name: t };
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case 'string':
|
case 'string':
|
||||||
|
@ -277,43 +277,34 @@ export class GBVMService extends GBService {
|
||||||
default:
|
default:
|
||||||
return { key: 'TABLE', name: t };
|
return { key: 'TABLE', name: t };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const associations = [];
|
const associations = [];
|
||||||
|
|
||||||
// Loads storage custom connections.
|
// Loads storage custom connections.
|
||||||
|
|
||||||
const path = DialogKeywords.getGBAIPath(min.botId, null);
|
const path = DialogKeywords.getGBAIPath(min.botId, null);
|
||||||
const filePath = Path.join('work', path, 'connections.json');
|
const filePath = Path.join('work', path, 'connections.json');
|
||||||
let connections = null;
|
let connections = null;
|
||||||
if (Fs.existsSync(filePath)) {
|
if (Fs.existsSync(filePath)) {
|
||||||
connections = JSON.parse(Fs.readFileSync(filePath, 'utf8'));
|
connections = JSON.parse(Fs.readFileSync(filePath, 'utf8'));
|
||||||
}
|
}
|
||||||
const shouldSync = min.core.getParam<boolean>(
|
const shouldSync = min.core.getParam<boolean>(min.instance, 'Synchronize Database', false);
|
||||||
min.instance,
|
|
||||||
'Synchronize Database',
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
tableDef.forEach(async t => {
|
tableDef.forEach(async t => {
|
||||||
|
|
||||||
const tableName = t.name.trim();
|
const tableName = t.name.trim();
|
||||||
|
|
||||||
// Determines autorelationship.
|
// Determines autorelationship.
|
||||||
|
|
||||||
Object.keys(t.fields).forEach(key => {
|
Object.keys(t.fields).forEach(key => {
|
||||||
let obj = t.fields[key];
|
let obj = t.fields[key];
|
||||||
obj.type = getTypeBasedOnCondition(obj.type, obj.size);
|
obj.type = getTypeBasedOnCondition(obj.type, obj.size);
|
||||||
if (obj.type.key === "TABLE") {
|
if (obj.type.key === 'TABLE') {
|
||||||
obj.type.key = "BIGINT"
|
obj.type.key = 'BIGINT';
|
||||||
associations.push({ from: tableName, to: obj.type.name });
|
associations.push({ from: tableName, to: obj.type.name });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Cutom connection for TABLE.
|
// Cutom connection for TABLE.
|
||||||
|
|
||||||
const connectionName = t.connection;
|
const connectionName = t.connection;
|
||||||
let con;
|
let con;
|
||||||
|
|
||||||
|
@ -330,8 +321,8 @@ export class GBVMService extends GBService {
|
||||||
const logging: boolean | Function =
|
const logging: boolean | Function =
|
||||||
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
||||||
? (str: string): void => {
|
? (str: string): void => {
|
||||||
GBLogEx.info(min, str);
|
GBLogEx.info(min, str);
|
||||||
}
|
}
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
||||||
|
@ -367,11 +358,12 @@ export class GBVMService extends GBService {
|
||||||
if (!min[connectionName]) {
|
if (!min[connectionName]) {
|
||||||
GBLogEx.info(min, `Loading custom connection ${connectionName}...`);
|
GBLogEx.info(min, `Loading custom connection ${connectionName}...`);
|
||||||
min[connectionName] = new Sequelize(storageName, username, password, sequelizeOptions);
|
min[connectionName] = new Sequelize(storageName, username, password, sequelizeOptions);
|
||||||
min[`llmconnection`] ={
|
min[`llmconnection`] = {
|
||||||
type: dialect,
|
type: dialect,
|
||||||
username,
|
username,
|
||||||
database: storageName, password};
|
database: storageName,
|
||||||
|
password
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,27 +372,22 @@ export class GBVMService extends GBService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Field checking, syncs if there is any difference.
|
// Field checking, syncs if there is any difference.
|
||||||
|
const seq = min[connectionName] ? min[connectionName] : minBoot.core.sequelize;
|
||||||
const seq = min[connectionName] ? min[connectionName]
|
|
||||||
: minBoot.core.sequelize;
|
|
||||||
|
|
||||||
if (seq) {
|
if (seq) {
|
||||||
|
|
||||||
const model = seq.models[tableName];
|
const model = seq.models[tableName];
|
||||||
if (model) {
|
if (model) {
|
||||||
// Except Id, checks if has same number of fields.
|
// Except Id, checks if has same number of fields.
|
||||||
|
|
||||||
let equals = 0;
|
let equals = 0;
|
||||||
Object.keys(t.fields).forEach(key => {
|
Object.keys(t.fields).forEach(key => {
|
||||||
let obj1 = t.fields[key];
|
let obj1 = t.fields[key];
|
||||||
let obj2 = model['fieldRawAttributesMap'][key];
|
let obj2 = model['fieldRawAttributesMap'][key];
|
||||||
|
|
||||||
if (key !== "id") {
|
if (key !== 'id') {
|
||||||
if (obj1 && obj2) {
|
if (obj1 && obj2) {
|
||||||
equals++;
|
equals++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (equals != Object.keys(t.fields).length) {
|
if (equals != Object.keys(t.fields).length) {
|
||||||
|
@ -414,19 +401,21 @@ export class GBVMService extends GBService {
|
||||||
let tables;
|
let tables;
|
||||||
|
|
||||||
if (con.storageDriver === 'mssql') {
|
if (con.storageDriver === 'mssql') {
|
||||||
tables = await seq.query(`SELECT table_name, table_schema
|
tables = await seq.query(
|
||||||
|
`SELECT table_name, table_schema
|
||||||
FROM information_schema.tables
|
FROM information_schema.tables
|
||||||
WHERE table_type = 'BASE TABLE'
|
WHERE table_type = 'BASE TABLE'
|
||||||
ORDER BY table_name ASC`, {
|
ORDER BY table_name ASC`,
|
||||||
type: QueryTypes.RAW
|
{
|
||||||
})[0]
|
type: QueryTypes.RAW
|
||||||
}
|
}
|
||||||
else if (con.storageDriver === 'mariadb') {
|
)[0];
|
||||||
|
} else if (con.storageDriver === 'mariadb') {
|
||||||
tables = await seq.getQueryInterface().showAllTables();
|
tables = await seq.getQueryInterface().showAllTables();
|
||||||
}
|
}
|
||||||
|
|
||||||
let found = false;
|
let found = false;
|
||||||
tables.forEach((storageTable) => {
|
tables.forEach(storageTable => {
|
||||||
if (storageTable['table_name'] === tableName) {
|
if (storageTable['table_name'] === tableName) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
@ -441,15 +430,17 @@ export class GBVMService extends GBService {
|
||||||
try {
|
try {
|
||||||
to.hasMany(from);
|
to.hasMany(from);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`BASIC: Invalid relationship in ${mainName}: from ${e.from} to ${e.to} (${min.botId})... ${error.message}`);
|
throw new Error(
|
||||||
|
`BASIC: Invalid relationship in ${mainName}: from ${e.from} to ${e.to} (${min.botId})... ${error.message}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if (sync && shouldSync) {
|
if (sync && shouldSync) {
|
||||||
|
GBLogEx.info(
|
||||||
GBLogEx.info(min, `BASIC: Syncing changes for TABLE ${connectionName} ${tableName} keyword (${min.botId})...`);
|
min,
|
||||||
|
`BASIC: Syncing changes for TABLE ${connectionName} ${tableName} keyword (${min.botId})...`
|
||||||
|
);
|
||||||
|
|
||||||
await seq.sync({
|
await seq.sync({
|
||||||
alter: true,
|
alter: true,
|
||||||
|
@ -460,18 +451,29 @@ export class GBVMService extends GBService {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsedCode: string = Fs.readFileSync(jsfile, 'utf8');
|
|
||||||
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
|
|
||||||
return filename;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async translateBASIC(mainName, filename: any, min: GBMinInstance) {
|
public async translateBASIC(mainName, filename: any, min: GBMinInstance) {
|
||||||
|
|
||||||
// Converts General Bots BASIC into regular VBS
|
// Converts General Bots BASIC into regular VBS
|
||||||
|
|
||||||
let basicCode: string = Fs.readFileSync(filename, 'utf8');
|
let basicCode: string = Fs.readFileSync(filename, 'utf8');
|
||||||
|
|
||||||
|
// Pre process SET SCHEDULE calls.
|
||||||
|
|
||||||
|
const schedules = GBVMService.getSetScheduleKeywordArgs(basicCode);
|
||||||
|
|
||||||
|
const s = new ScheduleServices();
|
||||||
|
await s.deleteScheduleIfAny(min, mainName);
|
||||||
|
|
||||||
|
let i = 1;
|
||||||
|
await CollectionUtil.asyncForEach(schedules, async syntax => {
|
||||||
|
if (s) {
|
||||||
|
await s.createOrUpdateSchedule(min, syntax, `${mainName};${i++}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
basicCode = basicCode.replace(/^\s*SET SCHEDULE (.*)/gim, '');
|
||||||
|
|
||||||
// Process INCLUDE keyword to include another
|
// Process INCLUDE keyword to include another
|
||||||
// dialog inside the dialog.
|
// dialog inside the dialog.
|
||||||
|
|
||||||
|
@ -712,7 +714,6 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
Fs.writeFileSync(jsfile, code);
|
Fs.writeFileSync(jsfile, code);
|
||||||
GBLogEx.info(min, `[GBVMService] Finished loading of ${filename}, JavaScript from Word: \n ${code}`);
|
GBLogEx.info(min, `[GBVMService] Finished loading of ${filename}, JavaScript from Word: \n ${code}`);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async executeTasks(min, tasks) {
|
private async executeTasks(min, tasks) {
|
||||||
|
@ -720,12 +721,10 @@ export class GBVMService extends GBService {
|
||||||
const task = tasks[i];
|
const task = tasks[i];
|
||||||
|
|
||||||
if (task.kind === 'writeTableDefinition') {
|
if (task.kind === 'writeTableDefinition') {
|
||||||
|
|
||||||
// Creates an empty object that will receive Sequelize fields.
|
// Creates an empty object that will receive Sequelize fields.
|
||||||
|
|
||||||
const tablesFile = `${task.file}.tables.json`;
|
const tablesFile = `${task.file}.tables.json`;
|
||||||
Fs.writeFileSync(tablesFile, JSON.stringify(task.tables));
|
Fs.writeFileSync(tablesFile, JSON.stringify(task.tables));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -744,10 +743,10 @@ export class GBVMService extends GBService {
|
||||||
lines.forEach(line => {
|
lines.forEach(line => {
|
||||||
if (line.trim()) {
|
if (line.trim()) {
|
||||||
console.log(line);
|
console.log(line);
|
||||||
const keyword = /\s*SET SCHEDULE (.*)/gi;
|
const keyword = /^\s*SET SCHEDULE (.*)/gi;
|
||||||
let result: any = keyword.exec(line);
|
let result: any = keyword.exec(line);
|
||||||
if (result) {
|
if (result) {
|
||||||
result = result[1].replace(/\`|\"|\'/, '')
|
result = result[1].replace(/\`|\"|\'/, '');
|
||||||
result = result.trim();
|
result = result.trim();
|
||||||
results.push(result);
|
results.push(result);
|
||||||
}
|
}
|
||||||
|
@ -756,6 +755,7 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getTextFromWord(folder: string, filename: string) {
|
private async getTextFromWord(folder: string, filename: string) {
|
||||||
return new Promise<string>(async (resolve, reject) => {
|
return new Promise<string>(async (resolve, reject) => {
|
||||||
const path = urlJoin(folder, filename);
|
const path = urlJoin(folder, filename);
|
||||||
|
@ -777,7 +777,6 @@ export class GBVMService extends GBService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static normalizeQuotes(text: any) {
|
public static normalizeQuotes(text: any) {
|
||||||
|
|
||||||
text = text.replace(/\"/gm, '`');
|
text = text.replace(/\"/gm, '`');
|
||||||
text = text.replace(/\¨/gm, '`');
|
text = text.replace(/\¨/gm, '`');
|
||||||
text = text.replace(/\“/gm, '`');
|
text = text.replace(/\“/gm, '`');
|
||||||
|
@ -791,27 +790,22 @@ export class GBVMService extends GBService {
|
||||||
public static getMetadata(mainName: string, propertiesText, description) {
|
public static getMetadata(mainName: string, propertiesText, description) {
|
||||||
let properties = {};
|
let properties = {};
|
||||||
if (!propertiesText || !description) {
|
if (!propertiesText || !description) {
|
||||||
|
return {};
|
||||||
return {}
|
|
||||||
}
|
}
|
||||||
const getType = asClause => {
|
const getType = asClause => {
|
||||||
|
|
||||||
asClause = asClause.trim().toUpperCase();
|
asClause = asClause.trim().toUpperCase();
|
||||||
|
|
||||||
if (asClause.indexOf('STRING') !== -1) {
|
if (asClause.indexOf('STRING') !== -1) {
|
||||||
return 'string';
|
return 'string';
|
||||||
}
|
} else if (asClause.indexOf('OBJECT') !== -1) {
|
||||||
else if (asClause.indexOf('OBJECT') !== -1) {
|
|
||||||
return 'object';
|
return 'object';
|
||||||
}
|
} else if (asClause.indexOf('INTEGER') !== -1 || asClause.indexOf('NUMBER') !== -1) {
|
||||||
else if (asClause.indexOf('INTEGER') !== -1 || asClause.indexOf('NUMBER') !== -1) {
|
|
||||||
return 'number';
|
return 'number';
|
||||||
} else {
|
} else {
|
||||||
return 'enum';
|
return 'enum';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
for (let i = 0; i < propertiesText.length; i++) {
|
for (let i = 0; i < propertiesText.length; i++) {
|
||||||
const propertiesExp = propertiesText[i];
|
const propertiesExp = propertiesText[i];
|
||||||
const t = getType(propertiesExp[2]);
|
const t = getType(propertiesExp[2]);
|
||||||
|
@ -834,21 +828,19 @@ export class GBVMService extends GBService {
|
||||||
properties[propertiesExp[1].trim()] = element;
|
properties[propertiesExp[1].trim()] = element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let json = {
|
let json = {
|
||||||
type: "function",
|
type: 'function',
|
||||||
function: {
|
function: {
|
||||||
name: `${mainName}`,
|
name: `${mainName}`,
|
||||||
description: description ? description : '',
|
description: description ? description : '',
|
||||||
parameters: zodToJsonSchema(z.object(properties))
|
parameters: zodToJsonSchema(z.object(properties))
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async parseField(line) {
|
public async parseField(line) {
|
||||||
|
|
||||||
let required = line.indexOf('*') !== -1;
|
let required = line.indexOf('*') !== -1;
|
||||||
let unique = /\bunique\b/gi.test(line);
|
let unique = /\bunique\b/gi.test(line);
|
||||||
let primaryKey = /\bkey\b/gi.test(line);
|
let primaryKey = /\bkey\b/gi.test(line);
|
||||||
|
@ -870,7 +862,8 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
let definition = {
|
let definition = {
|
||||||
allowNull: !required,
|
allowNull: !required,
|
||||||
unique: unique, primaryKey: primaryKey,
|
unique: unique,
|
||||||
|
primaryKey: primaryKey,
|
||||||
autoIncrement: autoIncrement
|
autoIncrement: autoIncrement
|
||||||
};
|
};
|
||||||
definition['type'] = t;
|
definition['type'] = t;
|
||||||
|
@ -889,7 +882,6 @@ export class GBVMService extends GBService {
|
||||||
* @param code General Bots BASIC
|
* @param code General Bots BASIC
|
||||||
*/
|
*/
|
||||||
public async convert(filename: string, mainName: string, code: string) {
|
public async convert(filename: string, mainName: string, code: string) {
|
||||||
|
|
||||||
// Start and End of VB2TS tags of processing.
|
// Start and End of VB2TS tags of processing.
|
||||||
|
|
||||||
code = process.env.ENABLE_AUTH ? `hear GBLogExin as login\n${code}` : code;
|
code = process.env.ENABLE_AUTH ? `hear GBLogExin as login\n${code}` : code;
|
||||||
|
@ -910,7 +902,6 @@ export class GBVMService extends GBService {
|
||||||
const outputLines = [];
|
const outputLines = [];
|
||||||
let emmitIndex = 1;
|
let emmitIndex = 1;
|
||||||
for (let i = 1; i <= lines.length; i++) {
|
for (let i = 1; i <= lines.length; i++) {
|
||||||
|
|
||||||
let line = lines[i - 1];
|
let line = lines[i - 1];
|
||||||
|
|
||||||
// Remove lines before statements.
|
// Remove lines before statements.
|
||||||
|
@ -961,12 +952,12 @@ export class GBVMService extends GBService {
|
||||||
const endTableKeyword = /^\s*END TABLE\s*/gim;
|
const endTableKeyword = /^\s*END TABLE\s*/gim;
|
||||||
let endTableReg = endTableKeyword.exec(line);
|
let endTableReg = endTableKeyword.exec(line);
|
||||||
if (endTableReg && table) {
|
if (endTableReg && table) {
|
||||||
|
|
||||||
tables.push({
|
tables.push({
|
||||||
name: table, fields: fields, connection: connection
|
name: table,
|
||||||
|
fields: fields,
|
||||||
|
connection: connection
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
fields = {};
|
fields = {};
|
||||||
table = null;
|
table = null;
|
||||||
connection = null;
|
connection = null;
|
||||||
|
@ -1006,14 +997,14 @@ export class GBVMService extends GBService {
|
||||||
const talkKeyword = /^\s*BEGIN TALK\s*/gim;
|
const talkKeyword = /^\s*BEGIN TALK\s*/gim;
|
||||||
let talkReg = talkKeyword.exec(line);
|
let talkReg = talkKeyword.exec(line);
|
||||||
if (talkReg && !talk) {
|
if (talkReg && !talk) {
|
||||||
talk = "await dk.talk ({pid: pid, text: `";
|
talk = 'await dk.talk ({pid: pid, text: `';
|
||||||
emmit = false;
|
emmit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const systemPromptKeyword = /^\s*BEGIN SYSTEM PROMPT\s*/gim;
|
const systemPromptKeyword = /^\s*BEGIN SYSTEM PROMPT\s*/gim;
|
||||||
let systemPromptReg = systemPromptKeyword.exec(line);
|
let systemPromptReg = systemPromptKeyword.exec(line);
|
||||||
if (systemPromptReg && !systemPrompt) {
|
if (systemPromptReg && !systemPrompt) {
|
||||||
systemPrompt = "await sys.setSystemPrompt ({pid: pid, text: `";
|
systemPrompt = 'await sys.setSystemPrompt ({pid: pid, text: `';
|
||||||
emmit = false;
|
emmit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,9 +1022,10 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
if (tables) {
|
if (tables) {
|
||||||
tasks.push({
|
tasks.push({
|
||||||
kind: 'writeTableDefinition', file: filename, tables
|
kind: 'writeTableDefinition',
|
||||||
|
file: filename,
|
||||||
|
tables
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code = `${outputLines.join('\n')}\n`;
|
code = `${outputLines.join('\n')}\n`;
|
||||||
|
@ -1046,14 +1038,7 @@ export class GBVMService extends GBService {
|
||||||
/**
|
/**
|
||||||
* Executes the converted JavaScript from BASIC code inside execution context.
|
* Executes the converted JavaScript from BASIC code inside execution context.
|
||||||
*/
|
*/
|
||||||
public static async callVM(
|
public static async callVM(text: string, min: GBMinInstance, step, pid, debug: boolean = false, params = []) {
|
||||||
text: string,
|
|
||||||
min: GBMinInstance,
|
|
||||||
step,
|
|
||||||
pid,
|
|
||||||
debug: boolean = false,
|
|
||||||
params = []
|
|
||||||
) {
|
|
||||||
// Creates a class DialogKeywords which is the *this* pointer
|
// Creates a class DialogKeywords which is the *this* pointer
|
||||||
// in BASIC.
|
// in BASIC.
|
||||||
|
|
||||||
|
@ -1069,8 +1054,7 @@ export class GBVMService extends GBService {
|
||||||
// These variables will be automatically be available as normal BASIC variables.
|
// These variables will be automatically be available as normal BASIC variables.
|
||||||
|
|
||||||
try {
|
try {
|
||||||
variables['aadToken'] = await (min.adminService as any)['acquireElevatedToken']
|
variables['aadToken'] = await (min.adminService as any)['acquireElevatedToken'](min.instance.instanceId, false);
|
||||||
(min.instance.instanceId, false);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
variables['aadToken'] = 'ERROR: Configure /setupSecurity before using aadToken variable.';
|
variables['aadToken'] = 'ERROR: Configure /setupSecurity before using aadToken variable.';
|
||||||
}
|
}
|
||||||
|
@ -1111,12 +1095,10 @@ export class GBVMService extends GBService {
|
||||||
let code = min.sandBoxMap[text];
|
let code = min.sandBoxMap[text];
|
||||||
const channel = step ? step.context.activity.channelId : 'web';
|
const channel = step ? step.context.activity.channelId : 'web';
|
||||||
|
|
||||||
|
|
||||||
const dk = new DialogKeywords();
|
const dk = new DialogKeywords();
|
||||||
const sys = new SystemKeywords();
|
const sys = new SystemKeywords();
|
||||||
await dk.setFilter({ pid: pid, value: null });
|
await dk.setFilter({ pid: pid, value: null });
|
||||||
|
|
||||||
|
|
||||||
// Find all tokens in .gbot Config.
|
// Find all tokens in .gbot Config.
|
||||||
|
|
||||||
const strFind = ' Client ID';
|
const strFind = ' Client ID';
|
||||||
|
@ -1152,7 +1134,7 @@ export class GBVMService extends GBService {
|
||||||
return await new Promise((resolve, reject) => {
|
return await new Promise((resolve, reject) => {
|
||||||
sandbox['resolve'] = resolve;
|
sandbox['resolve'] = resolve;
|
||||||
// TODO: #411 sandbox['reject'] = reject;
|
// TODO: #411 sandbox['reject'] = reject;
|
||||||
sandbox['reject'] = ()=>{};
|
sandbox['reject'] = () => {};
|
||||||
|
|
||||||
const vm1 = new NodeVM({
|
const vm1 = new NodeVM({
|
||||||
allowAsync: true,
|
allowAsync: true,
|
||||||
|
@ -1169,7 +1151,6 @@ export class GBVMService extends GBService {
|
||||||
const s = new VMScript(code, { filename: scriptPath });
|
const s = new VMScript(code, { filename: scriptPath });
|
||||||
result = vm1.run(s);
|
result = vm1.run(s);
|
||||||
});
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
} else {
|
} else {
|
||||||
const runnerPath = urlJoin(
|
const runnerPath = urlJoin(
|
||||||
|
@ -1200,10 +1181,15 @@ export class GBVMService extends GBService {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`BASIC RUNTIME ERR: ${error.message ? error.message : error}\n Stack:${error.stack}`);
|
throw new Error(`BASIC RUNTIME ERR: ${error.message ? error.message : error}\n Stack:${error.stack}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static createProcessInfo(user: GuaribasUser, min: GBMinInstance, channel: any, executable: string, step = null) {
|
public static createProcessInfo(
|
||||||
|
user: GuaribasUser,
|
||||||
|
min: GBMinInstance,
|
||||||
|
channel: any,
|
||||||
|
executable: string,
|
||||||
|
step = null
|
||||||
|
) {
|
||||||
const pid = GBAdminService.getNumberIdentifier();
|
const pid = GBAdminService.getNumberIdentifier();
|
||||||
GBServer.globals.processes[pid] = {
|
GBServer.globals.processes[pid] = {
|
||||||
pid: pid,
|
pid: pid,
|
||||||
|
|
|
@ -1,31 +1,29 @@
|
||||||
/*****************************************************************************\
|
/*****************************************************************************\
|
||||||
| ( )_ _ |
|
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
||||||
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' v `\ /'_`\ |
|
| ██ ███ ████ █ ██ █ ████ █████ ██████ ██ ████ █ █ █ ██ |
|
||||||
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__,\| (˅) |( (_) ) |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| | | ( )_) | |
|
|
||||||
| (_) \___/' |
|
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model,this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
| under the terms of the GNU Affero General Public License,version 3, |
|
| under the terms of the GNU Affero General Public License, version 3, |
|
||||||
| or under a proprietary license. |
|
| or under a proprietary license. |
|
||||||
| |
|
| |
|
||||||
| The texts of the GNU Affero General Public License with an additional |
|
| The texts of the GNU Affero General Public License with an additional |
|
||||||
| permission and of our proprietary license can be found at and |
|
| permission and of our proprietary license can be found at and |
|
||||||
| in the LICENSE file you have received along with this program. |
|
| in the LICENSE file you have received along with this program. |
|
||||||
| |
|
| |
|
||||||
| This program is distributed in the hope that it will be useful, |
|
| This program is distributed in the hope that it will be useful, |
|
||||||
| but WITHOUT ANY WARRANTY,without even the implied warranty of |
|
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights,title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
| |
|
| |
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
@ -35,13 +33,13 @@
|
||||||
import Path from 'path';
|
import Path from 'path';
|
||||||
import { GBLog, GBMinInstance } from 'botlib';
|
import { GBLog, GBMinInstance } from 'botlib';
|
||||||
import { DialogKeywords } from './DialogKeywords.js';
|
import { DialogKeywords } from './DialogKeywords.js';
|
||||||
import sharp from 'sharp';
|
|
||||||
import joinImages from 'join-images-updated';
|
import joinImages from 'join-images-updated';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
||||||
import urlJoin from 'url-join';
|
import urlJoin from 'url-join';
|
||||||
import { GBServer } from '../../../src/app.js';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
||||||
|
import sharp from 'sharp';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image processing services of conversation to be called by BASIC.
|
* Image processing services of conversation to be called by BASIC.
|
||||||
|
|
|
@ -1,35 +1,34 @@
|
||||||
/*****************************************************************************\
|
/*****************************************************************************\
|
||||||
| ( )_ _ |
|
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
||||||
| _ _ _ __ _ _ __ __ __ _ _ | ,_)(_) __ __ _ |
|
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' v `\ /'_`\ |
|
| ██ ███ ████ █ ██ █ ████ █████ ██████ ██ ████ █ █ █ ██ |
|
||||||
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__,\| (˅) |( (_) ) |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(___/(_) (_)`\__/' |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| | | ( )_) | |
|
|
||||||
| (_) \__/' |
|
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model,this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
| under the terms of the GNU Affero General Public License,version 3, |
|
| under the terms of the GNU Affero General Public License, version 3, |
|
||||||
| or under a proprietary license. |
|
| or under a proprietary license. |
|
||||||
| |
|
| |
|
||||||
| The texts of the GNU Affero General Public License with an additional |
|
| The texts of the GNU Affero General Public License with an additional |
|
||||||
| permission and of our proprietary license can be found at and |
|
| permission and of our proprietary license can be found at and |
|
||||||
| in the LICENSE file you have received along with this program. |
|
| in the LICENSE file you have received along with this program. |
|
||||||
| |
|
| |
|
||||||
| This program is distributed in the hope that it will be useful, |
|
| This program is distributed in the hope that it will be useful, |
|
||||||
| but WITHOUT ANY WARRANTY,without even the implied warranty of |
|
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights,title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
| |
|
| |
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -47,33 +47,30 @@ import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
||||||
* 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) {
|
||||||
|
|
||||||
let i = 1;
|
let i = 1;
|
||||||
while (i <= 10) {
|
while (i <= 10) {
|
||||||
const task = min['scheduleMap'] ? min['scheduleMap'][name + i] : null;
|
const task = min['scheduleMap'] ? min['scheduleMap'][name + i] : null;
|
||||||
|
|
||||||
if (task) {
|
if (task) {
|
||||||
task.destroy();
|
task.destroy();
|
||||||
const id = `${name};${i}`;
|
|
||||||
|
|
||||||
delete min['scheduleMap'][id];
|
|
||||||
const count = await GuaribasSchedule.destroy({
|
|
||||||
where: {
|
|
||||||
instanceId: min.instance.instanceId,
|
|
||||||
name: id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (count > 0) {
|
|
||||||
GBLogEx.info(min, `BASIC: Removed ${name} SET SCHEDULE and ${count} rows from storage on: ${min.botId}...`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const id = `${name};${i}`;
|
||||||
|
|
||||||
|
delete min['scheduleMap'][id];
|
||||||
|
const count = await GuaribasSchedule.destroy({
|
||||||
|
where: {
|
||||||
|
instanceId: min.instance.instanceId,
|
||||||
|
name: id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (count > 0) {
|
||||||
|
GBLogEx.info(min, `BASIC: Removed ${name} SET SCHEDULE and ${count} rows from storage on: ${min.botId}...`);
|
||||||
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,12 +110,10 @@ export class ScheduleServices extends GBService {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let lastName = '';
|
let lastName = '';
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(schedules, async (item) => {
|
await CollectionUtil.asyncForEach(schedules, async item => {
|
||||||
|
|
||||||
if (item.name === lastName) {
|
if (item.name === lastName) {
|
||||||
item.name = item.name + ++i;
|
item.name = item.name + ++i;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +164,6 @@ export class ScheduleServices extends GBService {
|
||||||
},
|
},
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
GBLogEx.error(min, `Running .gbdialog word ${item.name} : ${error}...`);
|
GBLogEx.error(min, `Running .gbdialog word ${item.name} : ${error}...`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -92,6 +92,7 @@ export class SystemKeywords {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async append({ pid, args }) {
|
public async append({ pid, args }) {
|
||||||
|
if (!args) return [];
|
||||||
let array = [].concat(...args);
|
let array = [].concat(...args);
|
||||||
return array.filter(function (item, pos) {
|
return array.filter(function (item, pos) {
|
||||||
return item;
|
return item;
|
||||||
|
|
|
@ -1,31 +1,29 @@
|
||||||
/*****************************************************************************\
|
/*****************************************************************************\
|
||||||
| ( )_ _ |
|
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
||||||
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' v `\ /'_`\ |
|
| ██ ███ ████ █ ██ █ ████ █████ ██████ ██ ████ █ █ █ ██ |
|
||||||
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__,\| (˅) |( (_) ) |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| | | ( )_) | |
|
|
||||||
| (_) \___/' |
|
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model,this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
| under the terms of the GNU Affero General Public License,version 3, |
|
| under the terms of the GNU Affero General Public License, version 3, |
|
||||||
| or under a proprietary license. |
|
| or under a proprietary license. |
|
||||||
| |
|
| |
|
||||||
| The texts of the GNU Affero General Public License with an additional |
|
| The texts of the GNU Affero General Public License with an additional |
|
||||||
| permission and of our proprietary license can be found at and |
|
| permission and of our proprietary license can be found at and |
|
||||||
| in the LICENSE file you have received along with this program. |
|
| in the LICENSE file you have received along with this program. |
|
||||||
| |
|
| |
|
||||||
| This program is distributed in the hope that it will be useful, |
|
| This program is distributed in the hope that it will be useful, |
|
||||||
| but WITHOUT ANY WARRANTY,without even the implied warranty of |
|
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights,title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
| |
|
| |
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
16
packages/basic.gblib/tests/DialogKeywords.test.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { expect, test } from 'vitest';
|
||||||
|
import { DialogKeywords } from '../services/DialogKeywords';
|
||||||
|
import init from '../../../.test-init'
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
const dk = new DialogKeywords();
|
||||||
|
const pid = 1;
|
||||||
|
|
||||||
|
test('TOLIST', async () => {
|
||||||
|
|
||||||
|
const obj = [{a:1, b:2}, {a:2, b:4}];
|
||||||
|
|
||||||
|
expect(await dk.getToLst({ pid, array: obj, member:'a' }))
|
||||||
|
.toBe("1,2");
|
||||||
|
});
|
43
packages/basic.gblib/tests/GBVMService.test.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { GBVMService } from '../services/GBVMService';
|
||||||
|
import { expect, test } from 'vitest'
|
||||||
|
|
||||||
|
test('Default', () => {
|
||||||
|
|
||||||
|
|
||||||
|
const args = GBVMService.getSetScheduleKeywordArgs(`
|
||||||
|
|
||||||
|
SET SCHEDULE "0 0 */1 * * *"
|
||||||
|
SET SCHEDULE "0 0 */3 * * *"
|
||||||
|
SET SCHEDULE "0 0 */2 * * *"
|
||||||
|
SET SCHEDULE "0 0 */2 * * *"
|
||||||
|
SET SCHEDULE "0 0 */3 * * *"
|
||||||
|
|
||||||
|
`);
|
||||||
|
|
||||||
|
expect(args.length).toBe(5);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('Compare', () => {
|
||||||
|
|
||||||
|
expect(GBVMService.compare(1,1)).toBeTruthy();
|
||||||
|
expect(GBVMService.compare({a:1},{a:1})).toBeTruthy();
|
||||||
|
expect(GBVMService.compare({a:1},{a:2})).toBeFalsy();
|
||||||
|
expect(GBVMService.compare({a:1, b:2},{a:1, b:2})).toBeTruthy();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Parse Storage Field', async () => {
|
||||||
|
|
||||||
|
const s = new GBVMService();
|
||||||
|
|
||||||
|
expect(await s.parseField('name STRING(30)')).toStrictEqual({name: 'name', definition: {
|
||||||
|
allowNull: true,
|
||||||
|
unique: false, primaryKey: false,
|
||||||
|
size: 30,
|
||||||
|
autoIncrement: false,
|
||||||
|
type:"STRING"
|
||||||
|
}});
|
||||||
|
|
||||||
|
});
|
36
packages/basic.gblib/tests/SystemKeywords.test.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { GBVMService } from '../services/GBVMService';
|
||||||
|
import { expect, test } from 'vitest';
|
||||||
|
import { SystemKeywords } from '../services/SystemKeywords';
|
||||||
|
|
||||||
|
const s = new SystemKeywords();
|
||||||
|
const pid = 1;
|
||||||
|
|
||||||
|
test('APPEND', async () => {
|
||||||
|
expect(await s.append({ pid, args: [1, 1, 1, 1] })).toStrictEqual([1, 1, 1, 1]);
|
||||||
|
expect(await s.append({ pid, args: [1] })).toStrictEqual([1]);
|
||||||
|
expect(await s.append({ pid, args: [] })).toStrictEqual([]);
|
||||||
|
expect(await s.append({ pid, args: null })).toStrictEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('COMPARE', () => {
|
||||||
|
expect(GBVMService.compare(1, 1)).toBeTruthy();
|
||||||
|
expect(GBVMService.compare({ a: 1 }, { a: 1 })).toBeTruthy();
|
||||||
|
expect(GBVMService.compare({ a: 1 }, { a: 2 })).toBeFalsy();
|
||||||
|
expect(GBVMService.compare({ a: 1, b: 2 }, { a: 1, b: 2 })).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Parse Storage Field', async () => {
|
||||||
|
const s = new GBVMService();
|
||||||
|
|
||||||
|
expect(await s.parseField('name STRING(30)')).toStrictEqual({
|
||||||
|
name: 'name',
|
||||||
|
definition: {
|
||||||
|
allowNull: true,
|
||||||
|
unique: false,
|
||||||
|
primaryKey: false,
|
||||||
|
size: 30,
|
||||||
|
autoIncrement: false,
|
||||||
|
type: 'STRING'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -36,11 +36,11 @@
|
||||||
|
|
||||||
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 { GBMinInstance, IGBDialog } from 'botlib';
|
||||||
import { GBServer } from '../../../src/app.js';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBConversationalService } from '../services/GBConversationalService.js';
|
|
||||||
import { Messages } from '../strings.js';
|
import { Messages } from '../strings.js';
|
||||||
import { GBLogEx } from '../services/GBLogEx.js';
|
import { GBLogEx } from '../services/GBLogEx.js';
|
||||||
|
import { GBConfigService } from '../services/GBConfigService.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog for Welcoming people.
|
* Dialog for Welcoming people.
|
||||||
|
@ -65,7 +65,7 @@ export class WelcomeDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
if (
|
if (
|
||||||
GBServer.globals.entryPointDialog !== null &&
|
GBServer.globals.entryPointDialog !== null &&
|
||||||
min.instance.botId === process.env.BOT_ID &&
|
min.instance.botId === GBConfigService.get('BOT_ID') &&
|
||||||
step.context.activity.channelId === 'webchat'
|
step.context.activity.channelId === 'webchat'
|
||||||
) {
|
) {
|
||||||
return step.replaceDialog(GBServer.globals.entryPointDialog);
|
return step.replaceDialog(GBServer.globals.entryPointDialog);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -42,7 +42,7 @@ import * as en from 'dotenv-extended';
|
||||||
*/
|
*/
|
||||||
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) {
|
||||||
|
@ -79,13 +79,19 @@ 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) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
case 'STORAGE_NAME':
|
||||||
|
value = null;
|
||||||
|
break;
|
||||||
case 'CLOUD_USERNAME':
|
case 'CLOUD_USERNAME':
|
||||||
value = undefined;
|
value = undefined;
|
||||||
break;
|
break;
|
||||||
|
case 'STORAGE_LIBRARY':
|
||||||
|
value = `${process.env.HOME}/gbpackages`;
|
||||||
|
break;
|
||||||
case 'BOT_ID':
|
case 'BOT_ID':
|
||||||
value = undefined;
|
value = 'default';
|
||||||
break;
|
break;
|
||||||
case 'CLOUD_PASSWORD':
|
case 'CLOUD_PASSWORD':
|
||||||
value = undefined;
|
value = undefined;
|
||||||
|
@ -103,10 +109,10 @@ export class GBConfigService {
|
||||||
value = undefined;
|
value = undefined;
|
||||||
break;
|
break;
|
||||||
case 'STORAGE_DIALECT':
|
case 'STORAGE_DIALECT':
|
||||||
value = undefined;
|
value = 'sqlite';
|
||||||
break;
|
break;
|
||||||
case 'STORAGE_FILE':
|
case 'STORAGE_FILE':
|
||||||
value = './guaribas.sqlite';
|
value = './data.db';
|
||||||
break;
|
break;
|
||||||
case 'GBKB_AUTO_DEPLOY':
|
case 'GBKB_AUTO_DEPLOY':
|
||||||
value = false;
|
value = false;
|
||||||
|
@ -160,7 +166,7 @@ export class GBConfigService {
|
||||||
value = true;
|
value = true;
|
||||||
break;
|
break;
|
||||||
case 'BOT_URL':
|
case 'BOT_URL':
|
||||||
value = undefined;
|
value = 'http://localhost:4242';
|
||||||
break;
|
break;
|
||||||
case 'STORAGE_SERVER':
|
case 'STORAGE_SERVER':
|
||||||
value = undefined;
|
value = undefined;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -341,6 +341,7 @@ export class GBConversationalService {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (step.context.activity.channelId !== 'msteams' && step.context.activity.channelId !== 'omnichannel') {
|
if (step.context.activity.channelId !== 'msteams' && step.context.activity.channelId !== 'omnichannel') {
|
||||||
GBLogEx.info(
|
GBLogEx.info(
|
||||||
min,
|
min,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -50,6 +50,7 @@ import { GBSecurityPackage } from '../../security.gbapp/index.js';
|
||||||
import { GBWhatsappPackage } from '../../whatsapp.gblib/index.js';
|
import { GBWhatsappPackage } from '../../whatsapp.gblib/index.js';
|
||||||
import { GuaribasApplications, GuaribasInstance, GuaribasLog } from '../models/GBModel.js';
|
import { GuaribasApplications, GuaribasInstance, GuaribasLog } from '../models/GBModel.js';
|
||||||
import { GBConfigService } from './GBConfigService.js';
|
import { GBConfigService } from './GBConfigService.js';
|
||||||
|
import mkdirp from 'mkdirp';
|
||||||
import { GBAzureDeployerPackage } from '../../azuredeployer.gbapp/index.js';
|
import { GBAzureDeployerPackage } from '../../azuredeployer.gbapp/index.js';
|
||||||
import { GBSharePointPackage } from '../../sharepoint.gblib/index.js';
|
import { GBSharePointPackage } from '../../sharepoint.gblib/index.js';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
|
@ -109,7 +110,7 @@ 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
|
||||||
|
@ -131,6 +132,12 @@ export class GBCoreService implements IGBCoreService {
|
||||||
password = GBConfigService.get('STORAGE_PASSWORD');
|
password = GBConfigService.get('STORAGE_PASSWORD');
|
||||||
} else if (this.dialect === 'sqlite') {
|
} else if (this.dialect === 'sqlite') {
|
||||||
storage = GBConfigService.get('STORAGE_FILE');
|
storage = GBConfigService.get('STORAGE_FILE');
|
||||||
|
|
||||||
|
if (!Fs.existsSync(storage)){
|
||||||
|
process.env.STORAGE_SYNC = 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Unknown dialect: ${this.dialect}.`);
|
throw new Error(`Unknown dialect: ${this.dialect}.`);
|
||||||
}
|
}
|
||||||
|
@ -138,8 +145,8 @@ export class GBCoreService implements IGBCoreService {
|
||||||
const logging: boolean | Function =
|
const logging: boolean | Function =
|
||||||
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
||||||
? (str: string): void => {
|
? (str: string): void => {
|
||||||
GBLogEx.info(0, str);
|
GBLogEx.info(0, str);
|
||||||
}
|
}
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
||||||
|
@ -231,12 +238,11 @@ export class GBCoreService implements IGBCoreService {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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) {
|
||||||
const bots = process.env.LOAD_ONLY.split(`;`);
|
const bots = process.env.LOAD_ONLY.split(`;`);
|
||||||
const and = [];
|
const and = [];
|
||||||
await CollectionUtil.asyncForEach(bots, async e => {
|
await CollectionUtil.asyncForEach(bots, async e => {
|
||||||
|
@ -426,12 +432,11 @@ ENDPOINT_UPDATE=true
|
||||||
let instances: IGBInstance[];
|
let instances: IGBInstance[];
|
||||||
try {
|
try {
|
||||||
instances = await core.loadInstances();
|
instances = await core.loadInstances();
|
||||||
const group = GBConfigService.get('CLOUD_GROUP')??GBConfigService.get('BOT_ID');
|
|
||||||
if (process.env.ENDPOINT_UPDATE === 'true') {
|
if (process.env.ENDPOINT_UPDATE === 'true') {
|
||||||
|
const group = GBConfigService.get('CLOUD_GROUP') ?? GBConfigService.get('BOT_ID');
|
||||||
await CollectionUtil.asyncForEach(instances, async instance => {
|
await CollectionUtil.asyncForEach(instances, async instance => {
|
||||||
GBLogEx.info(instance.instanceId, `Updating bot endpoint for ${instance.botId}...`);
|
GBLogEx.info(instance.instanceId, `Updating bot endpoint for ${instance.botId}...`);
|
||||||
try {
|
try {
|
||||||
|
|
||||||
await installationDeployer.updateBotProxy(
|
await installationDeployer.updateBotProxy(
|
||||||
instance.botId,
|
instance.botId,
|
||||||
group,
|
group,
|
||||||
|
@ -459,7 +464,10 @@ ENDPOINT_UPDATE=true
|
||||||
Try setting STORAGE_SYNC to true in .env file. Error: ${error.message}.`
|
Try setting STORAGE_SYNC to true in .env file. Error: ${error.message}.`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
GBLogEx.info(0, `Storage is empty. After collecting storage structure from all .gbapps it will get synced.`);
|
GBLogEx.info(
|
||||||
|
0,
|
||||||
|
`Storage is empty. After collecting storage structure from all .gbapps it will get synced.`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Cannot connect to operating storage: ${error.message}.`);
|
throw new Error(`Cannot connect to operating storage: ${error.message}.`);
|
||||||
|
@ -512,15 +520,8 @@ ENDPOINT_UPDATE=true
|
||||||
* before starting the server.
|
* before starting the server.
|
||||||
*/
|
*/
|
||||||
public ensureAdminIsSecured() {
|
public ensureAdminIsSecured() {
|
||||||
const password = GBConfigService.get('ADMIN_PASS');
|
|
||||||
if (!GBAdminService.StrongRegex.test(password)) {
|
|
||||||
throw new Error(
|
|
||||||
'Please, define a really strong password in ADMIN_PASS environment variable before running the server.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async createBootInstance(
|
public async createBootInstance(
|
||||||
core: GBCoreService,
|
core: GBCoreService,
|
||||||
installationDeployer: IGBInstallationDeployer,
|
installationDeployer: IGBInstallationDeployer,
|
||||||
|
@ -529,9 +530,10 @@ ENDPOINT_UPDATE=true
|
||||||
return await this.createBootInstanceEx(
|
return await this.createBootInstanceEx(
|
||||||
core,
|
core,
|
||||||
installationDeployer,
|
installationDeployer,
|
||||||
proxyAddress, null,
|
proxyAddress,
|
||||||
GBConfigService.get('FREE_TIER'));
|
null,
|
||||||
|
GBConfigService.get('FREE_TIER')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Creates the first bot instance (boot instance) used to "boot" the server.
|
* Creates the first bot instance (boot instance) used to "boot" the server.
|
||||||
|
@ -548,8 +550,10 @@ ENDPOINT_UPDATE=true
|
||||||
) {
|
) {
|
||||||
GBLogEx.info(0, `Deploying cognitive infrastructure (on the cloud / on premises)...`);
|
GBLogEx.info(0, `Deploying cognitive infrastructure (on the cloud / on premises)...`);
|
||||||
try {
|
try {
|
||||||
const { instance, credentials, subscriptionId, installationDeployer }
|
const { instance, credentials, subscriptionId, installationDeployer } = await StartDialog.createBaseInstance(
|
||||||
= await StartDialog.createBaseInstance(deployer, freeTier);
|
deployer,
|
||||||
|
freeTier
|
||||||
|
);
|
||||||
installationDeployer['core'] = this;
|
installationDeployer['core'] = this;
|
||||||
const changedInstance = await installationDeployer['deployFarm2'](
|
const changedInstance = await installationDeployer['deployFarm2'](
|
||||||
proxyAddress,
|
proxyAddress,
|
||||||
|
@ -668,27 +672,26 @@ ENDPOINT_UPDATE=true
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setConfig(min, name: string, value: any): Promise<any> {
|
public async setConfig(min, name: string, value: any): Promise<any> {
|
||||||
|
|
||||||
// Handles calls for BASIC persistence on sheet files.
|
// Handles calls for BASIC persistence on sheet files.
|
||||||
|
|
||||||
GBLog.info( `Defining Config.xlsx variable ${name}= '${value}'...`);
|
GBLog.info(`Defining Config.xlsx variable ${name}= '${value}'...`);
|
||||||
|
|
||||||
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||||
|
|
||||||
const maxLines = 512;
|
const maxLines = 512;
|
||||||
const file = "Config.xlsx";
|
const file = 'Config.xlsx';
|
||||||
const path = DialogKeywords.getGBAIPath(min.botId, `gbot`);;
|
const path = DialogKeywords.getGBAIPath(min.botId, `gbot`);
|
||||||
|
|
||||||
let document = await (new SystemKeywords()).internalGetDocument(client, baseUrl, path, file);
|
let document = await new SystemKeywords().internalGetDocument(client, baseUrl, path, file);
|
||||||
|
|
||||||
// Creates workbook session that will be discarded.
|
// Creates book session that will be discarded.
|
||||||
|
|
||||||
let sheets = await client
|
let sheets = await client.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`).get();
|
||||||
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`)
|
|
||||||
.get();
|
|
||||||
|
|
||||||
let results = await client
|
let results = await client
|
||||||
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:A${maxLines}')`)
|
.api(
|
||||||
|
`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:A${maxLines}')`
|
||||||
|
)
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
const rows = results.text;
|
const rows = results.text;
|
||||||
|
@ -708,12 +711,12 @@ ENDPOINT_UPDATE=true
|
||||||
body.values[0][0] = value;
|
body.values[0][0] = value;
|
||||||
|
|
||||||
await client
|
await client
|
||||||
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${address}')`)
|
.api(
|
||||||
|
`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${address}')`
|
||||||
|
)
|
||||||
.patch(body);
|
.patch(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a dynamic param from instance. Dynamic params are defined in Config.xlsx
|
* Get a dynamic param from instance. Dynamic params are defined in Config.xlsx
|
||||||
* and loaded into the work folder from comida command.
|
* and loaded into the work folder from comida command.
|
||||||
|
@ -729,8 +732,7 @@ ENDPOINT_UPDATE=true
|
||||||
// Gets .gbot Params from specified bot.
|
// Gets .gbot Params from specified bot.
|
||||||
|
|
||||||
if (instance.params) {
|
if (instance.params) {
|
||||||
|
params = typeof instance.params === 'object' ? instance.params : JSON.parse(instance.params);
|
||||||
params = typeof (instance.params) === 'object' ? instance.params : JSON.parse(instance.params);
|
|
||||||
params = GBUtil.caseInsensitive(params);
|
params = GBUtil.caseInsensitive(params);
|
||||||
value = params ? params[name] : defaultValue;
|
value = params ? params[name] : defaultValue;
|
||||||
}
|
}
|
||||||
|
@ -740,7 +742,6 @@ ENDPOINT_UPDATE=true
|
||||||
params = GBUtil.caseInsensitive(instance['dataValues']);
|
params = GBUtil.caseInsensitive(instance['dataValues']);
|
||||||
|
|
||||||
if (params && !value) {
|
if (params && !value) {
|
||||||
|
|
||||||
// Retrieves the value from specified bot instance (no params collection).
|
// Retrieves the value from specified bot instance (no params collection).
|
||||||
|
|
||||||
value = instance['dataValues'][name];
|
value = instance['dataValues'][name];
|
||||||
|
@ -749,27 +750,23 @@ ENDPOINT_UPDATE=true
|
||||||
|
|
||||||
const minBoot = GBServer.globals.minBoot as any;
|
const minBoot = GBServer.globals.minBoot as any;
|
||||||
|
|
||||||
if (
|
if (minBoot.instance && !value && instance.botId != minBoot.instance.botId) {
|
||||||
minBoot.instance &&
|
|
||||||
!value && instance.botId != minBoot.instance.botId) {
|
|
||||||
|
|
||||||
instance = minBoot.instance;
|
instance = minBoot.instance;
|
||||||
|
|
||||||
if(instance.params){
|
if (instance.params) {
|
||||||
params = typeof (instance.params) === 'object' ? instance.params : JSON.parse(instance.params);
|
params = typeof instance.params === 'object' ? instance.params : JSON.parse(instance.params);
|
||||||
params = GBUtil.caseInsensitive(params);
|
params = GBUtil.caseInsensitive(params);
|
||||||
value = params ? params[name] : defaultValue;
|
value = params ? params[name] : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If still did not found in boot bot params, try instance fields.
|
// If still did not found in boot bot params, try instance fields.
|
||||||
|
|
||||||
if (!value){
|
if (!value) {
|
||||||
value = instance['dataValues'][name];
|
value = instance['dataValues'][name];
|
||||||
}
|
}
|
||||||
if (!value){
|
if (!value) {
|
||||||
value = instance[name];
|
value = instance[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -787,7 +784,7 @@ ENDPOINT_UPDATE=true
|
||||||
return new Number(value ? value : defaultValue ? defaultValue : 0).valueOf();
|
return new Number(value ? value : defaultValue ? defaultValue : 0).valueOf();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ret = value ?? defaultValue;
|
const ret = value ?? defaultValue;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -798,7 +795,7 @@ ENDPOINT_UPDATE=true
|
||||||
let params = null;
|
let params = null;
|
||||||
const list = [];
|
const list = [];
|
||||||
if (instance.params) {
|
if (instance.params) {
|
||||||
params = typeof (instance.params) === 'object' ? instance.params : JSON.parse(instance.params);
|
params = typeof instance.params === 'object' ? instance.params : JSON.parse(instance.params);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(params).forEach(e => {
|
Object.keys(params).forEach(e => {
|
||||||
|
@ -810,5 +807,79 @@ ENDPOINT_UPDATE=true
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ensureFolders(instances, deployer: GBDeployer) {
|
||||||
|
let libraryPath = GBConfigService.get('STORAGE_LIBRARY');
|
||||||
|
|
||||||
|
if (!Fs.existsSync(libraryPath)) {
|
||||||
|
mkdirp.sync(libraryPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
||||||
|
|
||||||
|
const files = Fs.readdirSync(libraryPath);
|
||||||
|
await CollectionUtil.asyncForEach(files, async file => {
|
||||||
|
|
||||||
|
if (file.trim().toLowerCase() !== 'default.gbai'){
|
||||||
|
|
||||||
|
let botId = file.replace(/\.gbai/, '');
|
||||||
|
|
||||||
|
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async syncBotStorage(instances: any, botId: any, deployer: GBDeployer, libraryPath: string) {
|
||||||
|
let instance = instances.find(p => p.botId.toLowerCase().trim() === botId.toLowerCase().trim());
|
||||||
|
|
||||||
|
if (!instance) {
|
||||||
|
|
||||||
|
GBLog.info(`Importing package ${botId}...`);
|
||||||
|
|
||||||
|
// Creates a bot.
|
||||||
|
|
||||||
|
let mobile = null,
|
||||||
|
email = null;
|
||||||
|
|
||||||
|
instance = await deployer.deployBlankBot(botId, mobile, email);
|
||||||
|
const gbaiPath = Path.join(libraryPath, `${botId}.gbai`);
|
||||||
|
|
||||||
|
if (!Fs.existsSync(gbaiPath)) {
|
||||||
|
|
||||||
|
Fs.mkdirSync(gbaiPath, { recursive: true });
|
||||||
|
|
||||||
|
const base = Path.join(process.env.PWD, 'templates', 'default.gbai');
|
||||||
|
|
||||||
|
Fs.cpSync(Path.join(base, `default.gbkb`), Path.join(gbaiPath,`default.gbkb`), {
|
||||||
|
errorOnExist: false,
|
||||||
|
force: true,
|
||||||
|
recursive: true
|
||||||
|
});
|
||||||
|
Fs.cpSync(Path.join(base, `default.gbot`), Path.join(gbaiPath, `default.gbot`), {
|
||||||
|
errorOnExist: false,
|
||||||
|
force: true,
|
||||||
|
recursive: true
|
||||||
|
});
|
||||||
|
Fs.cpSync(Path.join(base, `default.gbtheme`), Path.join(gbaiPath, `default.gbtheme`), {
|
||||||
|
errorOnExist: false,
|
||||||
|
force: true,
|
||||||
|
recursive: true
|
||||||
|
});
|
||||||
|
Fs.cpSync(Path.join(base, `default.gbdata`), Path.join(gbaiPath, `default.gbdata`), {
|
||||||
|
errorOnExist: false,
|
||||||
|
force: true,
|
||||||
|
recursive: true
|
||||||
|
});
|
||||||
|
Fs.cpSync(Path.join(base, `default.gbdialog`), Path.join(gbaiPath, `default.gbdialog`), {
|
||||||
|
errorOnExist: false,
|
||||||
|
force: true,
|
||||||
|
recursive: true
|
||||||
|
});
|
||||||
|
Fs.cpSync(Path.join(base, `default.gbdrive`), Path.join(gbaiPath, `default.gbdrive`), {
|
||||||
|
errorOnExist: false,
|
||||||
|
force: true,
|
||||||
|
recursive: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -45,6 +45,8 @@ import { AzureSearch } from 'pragmatismo-io-framework';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { GBServer } from '../../../src/app.js';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBVMService } from '../../basic.gblib/services/GBVMService.js';
|
import { GBVMService } from '../../basic.gblib/services/GBVMService.js';
|
||||||
|
import Excel from 'exceljs';
|
||||||
|
import asyncPromise from 'async-promises';
|
||||||
import { GuaribasPackage } from '../models/GBModel.js';
|
import { GuaribasPackage } from '../models/GBModel.js';
|
||||||
import { GBAdminService } from './../../admin.gbapp/services/GBAdminService.js';
|
import { GBAdminService } from './../../admin.gbapp/services/GBAdminService.js';
|
||||||
import { AzureDeployerService } from './../../azuredeployer.gbapp/services/AzureDeployerService.js';
|
import { AzureDeployerService } from './../../azuredeployer.gbapp/services/AzureDeployerService.js';
|
||||||
|
@ -118,7 +120,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
);
|
);
|
||||||
|
|
||||||
const siteId = process.env.STORAGE_SITE_ID;
|
const siteId = process.env.STORAGE_SITE_ID;
|
||||||
const libraryId = process.env.STORAGE_LIBRARY;
|
const libraryId = GBConfigService.get('STORAGE_LIBRARY');
|
||||||
|
|
||||||
const client = MicrosoftGraph.Client.init({
|
const client = MicrosoftGraph.Client.init({
|
||||||
authProvider: done => {
|
authProvider: done => {
|
||||||
|
@ -220,22 +222,24 @@ export class GBDeployer implements IGBDeployer {
|
||||||
const instance = await this.importer.createBotInstance(botId);
|
const instance = await this.importer.createBotInstance(botId);
|
||||||
const bootInstance = GBServer.globals.bootInstance;
|
const bootInstance = GBServer.globals.bootInstance;
|
||||||
|
|
||||||
// Gets the access token to perform service operations.
|
if (GBConfigService.get('STORAGE_NAME')) {
|
||||||
|
// Gets the access token to perform service operations.
|
||||||
|
|
||||||
const accessToken = await (GBServer.globals.minBoot.adminService as any)['acquireElevatedToken'](
|
const accessToken = await (GBServer.globals.minBoot.adminService as any)['acquireElevatedToken'](
|
||||||
bootInstance.instanceId,
|
bootInstance.instanceId,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
// Creates the MSFT application that will be associated to the bot.
|
// Creates the MSFT application that will be associated to the bot.
|
||||||
|
|
||||||
const service = await AzureDeployerService.createInstance(this);
|
const service = await AzureDeployerService.createInstance(this);
|
||||||
const application = await service.createApplication(accessToken, botId);
|
const application = await service.createApplication(accessToken, botId);
|
||||||
|
// Fills new instance base information and get App secret.
|
||||||
|
|
||||||
// Fills new instance base information and get App secret.
|
instance.marketplaceId = (application as any).appId;
|
||||||
|
instance.marketplacePassword = await service.createApplicationSecret(accessToken, (application as any).id);
|
||||||
|
}
|
||||||
|
|
||||||
instance.marketplaceId = (application as any).appId;
|
|
||||||
instance.marketplacePassword = await service.createApplicationSecret(accessToken, (application as any).id);
|
|
||||||
instance.adminPass = GBAdminService.getRndPassword();
|
instance.adminPass = GBAdminService.getRndPassword();
|
||||||
instance.title = botId;
|
instance.title = botId;
|
||||||
instance.activationCode = instance.botId.substring(0, 15);
|
instance.activationCode = instance.botId.substring(0, 15);
|
||||||
|
@ -247,10 +251,17 @@ export class GBDeployer implements IGBDeployer {
|
||||||
// Saves bot information to the store.
|
// Saves bot information to the store.
|
||||||
|
|
||||||
await this.core.saveInstance(instance);
|
await this.core.saveInstance(instance);
|
||||||
|
if (GBConfigService.get('STORAGE_NAME')) {
|
||||||
|
await this.deployBotOnAzure(instance, GBServer.globals.publicAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Makes available bot to the channels and .gbui interfaces.
|
||||||
|
|
||||||
|
await GBServer.globals.minService.mountBot(instance);
|
||||||
|
|
||||||
// Creates remaining objects on the cloud and updates instance information.
|
// Creates remaining objects on the cloud and updates instance information.
|
||||||
|
|
||||||
return await this.deployBotFull(instance, GBServer.globals.publicAddress);
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -265,7 +276,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 deployBotOnAzure(instance: IGBInstance, publicAddress: string): Promise<IGBInstance> {
|
||||||
// Reads base configuration from environent file.
|
// Reads base configuration from environent file.
|
||||||
|
|
||||||
const service = await AzureDeployerService.createInstance(this);
|
const service = await AzureDeployerService.createInstance(this);
|
||||||
|
@ -286,7 +297,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
`${publicAddress}/api/messages/${instance.botId}`
|
`${publicAddress}/api/messages/${instance.botId}`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Internally create resources on cloud provider.
|
// Internally create resources on cloud provider.
|
||||||
|
|
||||||
instance = await service.internalDeployBot(
|
instance = await service.internalDeployBot(
|
||||||
|
@ -305,10 +315,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
subscriptionId
|
subscriptionId
|
||||||
);
|
);
|
||||||
|
|
||||||
// Makes available bot to the channels and .gbui interfaces.
|
|
||||||
|
|
||||||
await GBServer.globals.minService.mountBot(instance);
|
|
||||||
await GBServer.globals.minService.ensureAPI();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Saves final instance object and returns it.
|
// Saves final instance object and returns it.
|
||||||
|
@ -326,7 +332,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
let embedding;
|
let embedding;
|
||||||
if (!azureOpenAIEmbeddingModel) {
|
if (!azureOpenAIEmbeddingModel) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +349,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
vectorStore = new HNSWLib(embedding, {
|
vectorStore = new HNSWLib(embedding, {
|
||||||
space: 'cosine'
|
space: 'cosine'
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
return vectorStore;
|
return vectorStore;
|
||||||
}
|
}
|
||||||
|
@ -412,70 +416,50 @@ export class GBDeployer implements IGBDeployer {
|
||||||
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.deployBotOnAzure(instance, publicAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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, path): Promise<any> {
|
||||||
const siteId = process.env.STORAGE_SITE_ID;
|
const workbook = new Excel.Workbook();
|
||||||
const libraryId = process.env.STORAGE_LIBRARY;
|
const data = await workbook.xlsx.readFile(Path.join(path, 'Config.xlsx'));
|
||||||
|
|
||||||
GBLogEx.info(min, `Connecting to Config.xslx (siteId: ${siteId}, libraryId: ${libraryId})...`);
|
let worksheet: any;
|
||||||
|
for (let t = 0; t < data.worksheets.length; t++) {
|
||||||
|
worksheet = data.worksheets[t];
|
||||||
|
if (worksheet) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const rows = worksheet._rows;
|
||||||
|
GBLogEx.info(min, `Processing ${rows.length} rows from Config file ${path}...`);
|
||||||
|
let list = [];
|
||||||
|
|
||||||
// Connects to MSFT storage.
|
// Skips the header lines.
|
||||||
|
|
||||||
const token = await (min.adminService as any)['acquireElevatedToken'](min.instance.instanceId, true);
|
for (let index = 0; index < 6; index++) {
|
||||||
|
rows.shift();
|
||||||
|
}
|
||||||
|
|
||||||
const client = MicrosoftGraph.Client.init({
|
|
||||||
authProvider: done => {
|
let obj = {};
|
||||||
done(null, token);
|
await asyncPromise.eachSeries(rows, async line => {
|
||||||
|
|
||||||
|
if (line && line._cells[0] && line._cells[1] && line._cells[0].text) {
|
||||||
|
|
||||||
|
// Extracts values from columns in the current line.
|
||||||
|
|
||||||
|
obj[line._cells[0].text] = line._cells[1].text;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Retrieves all files in .bot folder.
|
GBLogEx.info(min, GBUtil.toYAML(list));
|
||||||
|
|
||||||
const botId = min.instance.botId;
|
|
||||||
const path = DialogKeywords.getGBAIPath(botId, 'gbot');
|
|
||||||
let url = `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:/${path}:/children`;
|
|
||||||
|
|
||||||
GBLogEx.info(min, `Loading .gbot from Excel: ${url}`);
|
|
||||||
const res = await client.api(url).get();
|
|
||||||
|
|
||||||
// Finds Config.xlsx.
|
|
||||||
|
|
||||||
const document = res.value.filter(m => {
|
|
||||||
return m.name === 'Config.xlsx';
|
|
||||||
});
|
|
||||||
if (document === undefined || document.length === 0) {
|
|
||||||
GBLogEx.info(min, `Config.xlsx not found on .bot folder, check the package.`);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reads all rows in Config.xlsx that contains a pair of name/value
|
|
||||||
// and fills an object that is returned to be saved in params instance field.
|
|
||||||
|
|
||||||
const results = await client
|
|
||||||
.api(
|
|
||||||
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/items/${document[0].id}/workbook/worksheets('General')/range(address='A7:B100')`
|
|
||||||
)
|
|
||||||
.get();
|
|
||||||
let index = 0,
|
|
||||||
obj = {};
|
|
||||||
for (; index < results.text.length; index++) {
|
|
||||||
if (results.text[index][0] === '') {
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
obj[results.text[index][0]] = results.text[index][1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all para from tabular file Config.xlsx.
|
|
||||||
*/
|
*/
|
||||||
public async downloadFolder(
|
public async downloadFolder(
|
||||||
min: GBMinInstance,
|
min: GBMinInstance,
|
||||||
|
@ -632,14 +616,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
case '.gbot':
|
case '.gbot':
|
||||||
// Extracts configuration information from .gbot files.
|
// Extracts configuration information from .gbot files.
|
||||||
|
|
||||||
if (process.env.ENABLE_PARAMS_ONLINE === 'false') {
|
min.instance.params = await this.loadParamsFromTabular(min, localPath);
|
||||||
if (Fs.existsSync(localPath)) {
|
|
||||||
GBLogEx.info(min, `Loading .gbot from ${localPath}.`);
|
|
||||||
await this.deployBotFromLocalPath(localPath, GBServer.globals.publicAddress);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
min.instance.params = await this.loadParamsFromTabular(min);
|
|
||||||
}
|
|
||||||
|
|
||||||
let connections = [];
|
let connections = [];
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
/*****************************************************************************\
|
/*****************************************************************************\
|
||||||
| ( )_ _ |
|
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
||||||
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ _ _ _ |
|
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/ \ /`\ /'_`\ |
|
| ██ ███ ████ █ ██ █ ████ █████ ██████ ██ ████ █ █ █ ██ |
|
||||||
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| |*| |( (_) ) |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| | | ( )_) | |
|
|
||||||
| (_) \___/' |
|
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -23,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -44,7 +44,9 @@ import Fs from 'fs';
|
||||||
import arrayBufferToBuffer from 'arraybuffer-to-buffer';
|
import arrayBufferToBuffer from 'arraybuffer-to-buffer';
|
||||||
import { NlpManager } from 'node-nlp';
|
import { NlpManager } from 'node-nlp';
|
||||||
import Koa from 'koa';
|
import Koa from 'koa';
|
||||||
|
import { v2 as webdav } from 'webdav-server';
|
||||||
import { createRpcServer } from '@push-rpc/core';
|
import { createRpcServer } from '@push-rpc/core';
|
||||||
|
import { start as startRouter } from '../../../packages/core.gbapp/services/router/bridge.js';
|
||||||
import wash from 'washyourmouthoutwithsoap';
|
import wash from 'washyourmouthoutwithsoap';
|
||||||
import {
|
import {
|
||||||
AutoSaveStateMiddleware,
|
AutoSaveStateMiddleware,
|
||||||
|
@ -140,10 +142,7 @@ export class GBMinService {
|
||||||
this.deployer = deployer;
|
this.deployer = deployer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async enableAPI(min: GBMinInstance) {}
|
||||||
public async enableAPI(min: GBMinInstance) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new minimal instance for each bot.
|
* Constructs a new minimal instance for each bot.
|
||||||
|
@ -168,25 +167,20 @@ export class GBMinService {
|
||||||
|
|
||||||
let i = 1;
|
let i = 1;
|
||||||
|
|
||||||
if (instances.length > 1) {
|
|
||||||
}
|
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(
|
await CollectionUtil.asyncForEach(
|
||||||
instances,
|
instances,
|
||||||
(async instance => {
|
(async instance => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
GBLog.info(`Mounting ${instance.botId}...`)
|
GBLog.info(`Mounting ${instance.botId}...`);
|
||||||
await this['mountBot'](instance);
|
await this['mountBot'](instance);
|
||||||
} 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)
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Loads API.
|
|
||||||
|
|
||||||
await this.ensureAPI();
|
|
||||||
|
|
||||||
// Loads schedules.
|
// Loads schedules.
|
||||||
|
|
||||||
GBLogEx.info(0, `Loading SET SCHEDULE entries...`);
|
GBLogEx.info(0, `Loading SET SCHEDULE entries...`);
|
||||||
|
@ -196,6 +190,37 @@ export class GBMinService {
|
||||||
GBLogEx.info(0, `All Bot instances loaded.`);
|
GBLogEx.info(0, `All Bot instances loaded.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async startSimpleTest(min) {
|
||||||
|
if (process.env.TEST_MESSAGE && min['isDefault']) {
|
||||||
|
GBLogEx.info(min, `Starting auto test with '${process.env.TEST_MESSAGE}'.`);
|
||||||
|
|
||||||
|
const client = await GBUtil.getDirectLineClient(min);
|
||||||
|
|
||||||
|
const response = await client.apis.Conversations.Conversations_StartConversation();
|
||||||
|
const conversationId = response.obj.conversationId;
|
||||||
|
GBServer.globals.debugConversationId = conversationId;
|
||||||
|
|
||||||
|
const steps = process.env.TEST_MESSAGE.split(';');
|
||||||
|
|
||||||
|
await CollectionUtil.asyncForEach(steps, async (step) => {
|
||||||
|
client.apis.Conversations.Conversations_PostActivity({
|
||||||
|
conversationId: conversationId,
|
||||||
|
activity: {
|
||||||
|
textFormat: 'plain',
|
||||||
|
text: step,
|
||||||
|
type: 'message',
|
||||||
|
from: {
|
||||||
|
id: 'test',
|
||||||
|
name: 'test'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await GBUtil.sleep(3000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
|
@ -234,7 +259,7 @@ export class GBMinService {
|
||||||
/**
|
/**
|
||||||
* Unmounts the bot web site (default.gbui) secure domain, if any.
|
* Unmounts the bot web site (default.gbui) secure domain, if any.
|
||||||
*/
|
*/
|
||||||
public async unloadDomain(instance: IGBInstance) { }
|
public async unloadDomain(instance: IGBInstance) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mount the instance by creating an BOT Framework bot object,
|
* Mount the instance by creating an BOT Framework bot object,
|
||||||
|
@ -243,6 +268,7 @@ export class GBMinService {
|
||||||
*/
|
*/
|
||||||
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(
|
||||||
|
@ -254,10 +280,14 @@ export class GBMinService {
|
||||||
// https://github.com/GeneralBots/BotServer/issues/286
|
// https://github.com/GeneralBots/BotServer/issues/286
|
||||||
// min['groupCache'] = await KBService.getGroupReplies(instance.instanceId);
|
// min['groupCache'] = await KBService.getGroupReplies(instance.instanceId);
|
||||||
|
|
||||||
|
min['isDefault'] = GBServer.globals.minInstances.length === 0;
|
||||||
|
|
||||||
GBServer.globals.minInstances.push(min);
|
GBServer.globals.minInstances.push(min);
|
||||||
const user = null; // No user context.
|
const user = null; // No user context.
|
||||||
|
|
||||||
await this.deployer['deployPackage2'](min, user, 'packages/default.gbtheme');
|
// Serves individual URL for each bot conversational interface.
|
||||||
|
|
||||||
|
await this.deployer['deployPackage2'](min, user, 'templates/default.gbai/default.gbtheme');
|
||||||
|
|
||||||
// Install per bot deployed packages.
|
// Install per bot deployed packages.
|
||||||
|
|
||||||
|
@ -318,21 +348,23 @@ export class GBMinService {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads Named Entity data for this bot.
|
if (!GBConfigService.get('STORAGE_NAME')) {
|
||||||
|
dir = Path.join(GBConfigService.get('STORAGE_LIBRARY'), 'work', gbai);
|
||||||
|
|
||||||
// TODO: await KBService.RefreshNER(min);
|
const server = GBServer.globals.webDavServer;
|
||||||
|
server.setFileSystem(`/${botId}`, new webdav.PhysicalFileSystem(dir), success => {
|
||||||
|
GBLogEx.info(1, `WebDav for ${botId} loaded.`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Calls the loadBot context.activity for all packages.
|
// Calls the loadBot context.activity for all packages.
|
||||||
|
|
||||||
await this.invokeLoadBot(min.appPackages, GBServer.globals.sysPackages, min);
|
await this.invokeLoadBot(min.appPackages, GBServer.globals.sysPackages, min);
|
||||||
|
|
||||||
// Serves individual URL for each bot conversational interface.
|
|
||||||
|
|
||||||
const receiver = async (req, res) => {
|
const receiver = async (req, res) => {
|
||||||
await this.receiver(req, res, conversationState, min, instance, GBServer.globals.appPackages);
|
await this.receiver(req, res, conversationState, min, instance, GBServer.globals.appPackages);
|
||||||
};
|
};
|
||||||
const url = `/api/messages/${instance.botId}`;
|
let url = `/api/messages/${instance.botId}`;
|
||||||
GBServer.globals.server.post(url, receiver);
|
|
||||||
GBServer.globals.server.get(url, (req, res) => {
|
GBServer.globals.server.get(url, (req, res) => {
|
||||||
if (req.query['hub.mode'] === 'subscribe') {
|
if (req.query['hub.mode'] === 'subscribe') {
|
||||||
if (req.query['hub.verify_token'] === process.env.FACEBOOK_VERIFY_TOKEN) {
|
if (req.query['hub.verify_token'] === process.env.FACEBOOK_VERIFY_TOKEN) {
|
||||||
|
@ -347,39 +379,6 @@ export class GBMinService {
|
||||||
});
|
});
|
||||||
GBLog.verbose(`GeneralBots(${instance.engineName}) listening on: ${url}.`);
|
GBLog.verbose(`GeneralBots(${instance.engineName}) listening on: ${url}.`);
|
||||||
|
|
||||||
// Test code.
|
|
||||||
if (process.env.TEST_MESSAGE) {
|
|
||||||
GBLogEx.info(min, `Starting auto test with '${process.env.TEST_MESSAGE}'.`);
|
|
||||||
|
|
||||||
const client = await new SwaggerClient({
|
|
||||||
spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')),
|
|
||||||
requestInterceptor: req => {
|
|
||||||
req.headers['Authorization'] = `Bearer ${min.instance.webchatKey}`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await client.apis.Conversations.Conversations_StartConversation();
|
|
||||||
const conversationId = response.obj.conversationId;
|
|
||||||
GBServer.globals.debugConversationId = conversationId;
|
|
||||||
|
|
||||||
const steps = process.env.TEST_MESSAGE.split(';');
|
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(steps, async step => {
|
|
||||||
client.apis.Conversations.Conversations_PostActivity({
|
|
||||||
conversationId: conversationId,
|
|
||||||
activity: {
|
|
||||||
textFormat: 'plain',
|
|
||||||
text: step,
|
|
||||||
type: 'message',
|
|
||||||
from: {
|
|
||||||
id: 'test',
|
|
||||||
name: 'test'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await GBUtil.sleep(3000);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Generates MS Teams manifest.
|
// Generates MS Teams manifest.
|
||||||
|
|
||||||
|
@ -390,7 +389,6 @@ export class GBMinService {
|
||||||
const data = await this.deployer.getBotManifest(instance);
|
const data = await this.deployer.getBotManifest(instance);
|
||||||
Fs.writeFileSync(packageTeams, data);
|
Fs.writeFileSync(packageTeams, data);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Serves individual URL for each bot user interface.
|
// Serves individual URL for each bot user interface.
|
||||||
|
|
||||||
|
@ -426,37 +424,44 @@ export class GBMinService {
|
||||||
|
|
||||||
// Setups official handler for WhatsApp.
|
// Setups official handler for WhatsApp.
|
||||||
|
|
||||||
GBServer.globals.server.all(`/${min.instance.botId}/whatsapp`, async (req, res) => {
|
GBServer.globals.server
|
||||||
|
.all(`/${min.instance.botId}/whatsapp`, async (req, res) => {
|
||||||
|
if (req.query['hub.mode'] === 'subscribe') {
|
||||||
|
const val = req.query['hub.verify_token'];
|
||||||
|
|
||||||
|
if (val === process.env.META_CHALLENGE) {
|
||||||
|
res.send(req.query['hub.challenge']);
|
||||||
|
res.status(200);
|
||||||
|
GBLogEx.info(min, `Meta callback OK. ${JSON.stringify(req.query)}`);
|
||||||
|
} else {
|
||||||
|
res.status(401);
|
||||||
|
}
|
||||||
|
res.end();
|
||||||
|
|
||||||
if (req.query['hub.mode'] === 'subscribe') {
|
return;
|
||||||
const val = req.query['hub.verify_token'];
|
|
||||||
|
|
||||||
if (val === process.env.META_CHALLENGE) {
|
|
||||||
res.send(req.query['hub.challenge']);
|
|
||||||
res.status(200);
|
|
||||||
GBLogEx.info(min, `Meta callback OK. ${JSON.stringify(req.query)}`);
|
|
||||||
} else {
|
|
||||||
res.status(401);
|
|
||||||
}
|
}
|
||||||
res.end();
|
|
||||||
|
|
||||||
return;
|
let whatsAppDirectLine = min.whatsAppDirectLine;
|
||||||
}
|
|
||||||
|
|
||||||
let whatsAppDirectLine = min.whatsAppDirectLine;
|
// Not meta, multiples bots on root bot.
|
||||||
|
|
||||||
// Not meta, multiples bots on root bot.
|
if (!req.body.object) {
|
||||||
|
const to = req.body.To.replace(/whatsapp\:\+/gi, '');
|
||||||
|
whatsAppDirectLine = WhatsappDirectLine.botsByNumber[to];
|
||||||
|
}
|
||||||
|
|
||||||
if (!req.body.object) {
|
if (whatsAppDirectLine) {
|
||||||
const to = req.body.To.replace(/whatsapp\:\+/gi, '');
|
await whatsAppDirectLine.WhatsAppCallback(req, res, whatsAppDirectLine.botId);
|
||||||
whatsAppDirectLine = WhatsappDirectLine.botsByNumber[to];
|
}
|
||||||
}
|
})
|
||||||
|
.bind(min);
|
||||||
await whatsAppDirectLine.WhatsAppCallback(req, res, whatsAppDirectLine.botId);
|
|
||||||
}).bind(min);
|
|
||||||
|
|
||||||
GBDeployer.mountGBKBAssets(`${botId}.gbkb`, botId, `${botId}.gbkb`);
|
GBDeployer.mountGBKBAssets(`${botId}.gbkb`, botId, `${botId}.gbkb`);
|
||||||
|
|
||||||
|
// Loads API.
|
||||||
|
|
||||||
|
await this.ensureAPI();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getProviderName(req: any, res: any) {
|
public static getProviderName(req: any, res: any) {
|
||||||
|
@ -510,9 +515,7 @@ export class GBMinService {
|
||||||
* 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) => {
|
||||||
|
|
||||||
let tokenName = req.query['value'];
|
let tokenName = req.query['value'];
|
||||||
if (!tokenName) {
|
if (!tokenName) {
|
||||||
tokenName = '';
|
tokenName = '';
|
||||||
|
@ -535,9 +538,7 @@ export class GBMinService {
|
||||||
if (tokenName) {
|
if (tokenName) {
|
||||||
const code = req?.query?.code;
|
const code = req?.query?.code;
|
||||||
|
|
||||||
let url = urlJoin(
|
let url = urlJoin(host, tenant, 'oauth/token');
|
||||||
host,
|
|
||||||
tenant, 'oauth/token');
|
|
||||||
let buff = new Buffer(`${clientId}:${clientSecret}`);
|
let buff = new Buffer(`${clientId}:${clientSecret}`);
|
||||||
const base64 = buff.toString('base64');
|
const base64 = buff.toString('base64');
|
||||||
|
|
||||||
|
@ -549,14 +550,14 @@ export class GBMinService {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
},
|
},
|
||||||
body: new URLSearchParams({
|
body: new URLSearchParams({
|
||||||
'grant_type': 'authorization_code',
|
grant_type: 'authorization_code',
|
||||||
'code': code
|
code: code
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
const result = await fetch(url, options);
|
const result = await fetch(url, options);
|
||||||
|
|
||||||
if (result.status != 200) {
|
if (result.status != 200) {
|
||||||
throw new Error(`handleOAuthTokenRequests error: ${result.status}: ${result.statusText}.`)
|
throw new Error(`handleOAuthTokenRequests error: ${result.status}: ${result.statusText}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const text = await result.text();
|
const text = await result.text();
|
||||||
|
@ -564,24 +565,31 @@ export class GBMinService {
|
||||||
|
|
||||||
// Saves token to the database.
|
// Saves token to the database.
|
||||||
|
|
||||||
await this.adminService.setValue(instance.instanceId,
|
await this.adminService.setValue(
|
||||||
`${tokenName}accessToken`, token['accessToken'] ? token['accessToken'] : token['access_token']);
|
instance.instanceId,
|
||||||
await this.adminService.setValue(instance.instanceId,
|
`${tokenName}accessToken`,
|
||||||
`${tokenName}refreshToken`, token['refreshToken'] ? token['refreshToken'] : token['refresh_token']);
|
token['accessToken'] ? token['accessToken'] : token['access_token']
|
||||||
|
);
|
||||||
|
await this.adminService.setValue(
|
||||||
|
instance.instanceId,
|
||||||
|
`${tokenName}refreshToken`,
|
||||||
|
token['refreshToken'] ? token['refreshToken'] : token['refresh_token']
|
||||||
|
);
|
||||||
|
|
||||||
await this.adminService.setValue(instance.instanceId,
|
await this.adminService.setValue(
|
||||||
`${tokenName}expiresOn`, token['expiresOn'] ?
|
instance.instanceId,
|
||||||
token['expiresOn'].toString() :
|
`${tokenName}expiresOn`,
|
||||||
new Date(Date.now() + (token['expires_in'] * 1000)).toString());
|
token['expiresOn']
|
||||||
|
? token['expiresOn'].toString()
|
||||||
|
: new Date(Date.now() + token['expires_in'] * 1000).toString()
|
||||||
|
);
|
||||||
await this.adminService.setValue(instance.instanceId, `${tokenName}AntiCSRFAttackState`, null);
|
await this.adminService.setValue(instance.instanceId, `${tokenName}AntiCSRFAttackState`, null);
|
||||||
|
} else {
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const authenticationContext = new AuthenticationContext.AuthenticationContext(
|
const authenticationContext = new AuthenticationContext.AuthenticationContext(
|
||||||
urlJoin(
|
urlJoin(
|
||||||
tokenName ? host : min.instance.authenticatorAuthorityHostUrl,
|
tokenName ? host : min.instance.authenticatorAuthorityHostUrl,
|
||||||
tokenName ? tenant : min.instance.authenticatorTenant)
|
tokenName ? tenant : min.instance.authenticatorTenant
|
||||||
|
)
|
||||||
);
|
);
|
||||||
const resource = 'https://graph.microsoft.com';
|
const resource = 'https://graph.microsoft.com';
|
||||||
|
|
||||||
|
@ -595,26 +603,24 @@ export class GBMinService {
|
||||||
tokenName ? clientSecret : instance.marketplacePassword,
|
tokenName ? clientSecret : instance.marketplacePassword,
|
||||||
async (err, token) => {
|
async (err, token) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
||||||
const msg = `handleOAuthTokenRequests: Error acquiring token: ${err}`;
|
const msg = `handleOAuthTokenRequests: Error acquiring token: ${err}`;
|
||||||
|
|
||||||
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, `${tokenName}accessToken`, token['accessToken']);
|
await this.adminService.setValue(instance.instanceId, `${tokenName}accessToken`, token['accessToken']);
|
||||||
await this.adminService.setValue(instance.instanceId, `${tokenName}refreshToken`, token['refreshToken']);
|
await this.adminService.setValue(instance.instanceId, `${tokenName}refreshToken`, token['refreshToken']);
|
||||||
await this.adminService.setValue(instance.instanceId, `${tokenName}expiresOn`, token['expiresOn'].toString());
|
await this.adminService.setValue(
|
||||||
|
instance.instanceId,
|
||||||
|
`${tokenName}expiresOn`,
|
||||||
|
token['expiresOn'].toString()
|
||||||
|
);
|
||||||
await this.adminService.setValue(instance.instanceId, `${tokenName}AntiCSRFAttackState`, null);
|
await this.adminService.setValue(instance.instanceId, `${tokenName}AntiCSRFAttackState`, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// Inform the home for default .gbui after finishing token retrival.
|
// Inform the home for default .gbui after finishing token retrival.
|
||||||
|
|
||||||
|
@ -633,8 +639,9 @@ export class GBMinService {
|
||||||
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=${
|
||||||
}&redirect_uri=${urlJoin(process.env.BOT_URL, min.instance.botId, 'token')}`;
|
min.instance.marketplaceId
|
||||||
|
}&redirect_uri=${urlJoin(process.env.BOT_URL, min.instance.botId, 'token')}`;
|
||||||
GBLogEx.info(min, `HandleOAuthRequests: ${authorizationUrl}.`);
|
GBLogEx.info(min, `HandleOAuthRequests: ${authorizationUrl}.`);
|
||||||
res.redirect(authorizationUrl);
|
res.redirect(authorizationUrl);
|
||||||
});
|
});
|
||||||
|
@ -651,7 +658,6 @@ export class GBMinService {
|
||||||
botId = GBConfigService.get('BOT_ID');
|
botId = GBConfigService.get('BOT_ID');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Loads by the botId itself or by the activationCode field.
|
// Loads by the botId itself or by the activationCode field.
|
||||||
|
|
||||||
let instance = await this.core.loadInstanceByBotId(botId);
|
let instance = await this.core.loadInstanceByBotId(botId);
|
||||||
|
@ -663,7 +669,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 speechToken = instance.speechKey != undefined ? await this.getSTSToken(instance) : null;
|
const speechToken = instance.speechKey != undefined ? await this.getSTSToken(instance) : null;
|
||||||
let theme = instance.theme;
|
let theme = instance.theme;
|
||||||
|
|
||||||
|
@ -673,29 +678,36 @@ export class GBMinService {
|
||||||
theme = `default.gbtheme`;
|
theme = `default.gbtheme`;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.send(
|
let logo = this.core.getParam(instance, 'Logo', null);
|
||||||
JSON.stringify({
|
|
||||||
instanceId: instance.instanceId,
|
|
||||||
botId: botId,
|
|
||||||
theme: theme,
|
|
||||||
webchatToken: webchatTokenContainer.token,
|
|
||||||
speechToken: speechToken,
|
|
||||||
conversationId: webchatTokenContainer.conversationId,
|
|
||||||
authenticatorTenant: instance.authenticatorTenant,
|
|
||||||
authenticatorClientId: instance.marketplaceId,
|
|
||||||
paramLogoImageUrl: this.core.getParam(instance, 'Logo Image Url', null),
|
|
||||||
paramLogoImageAlt: this.core.getParam(instance, 'Logo Image Alt', null),
|
|
||||||
paramLogoImageWidth: this.core.getParam(instance, 'Logo Image Width', null),
|
|
||||||
paramLogoImageHeight: this.core.getParam(instance, 'Logo Image Height', null),
|
|
||||||
paramLogoImageType: this.core.getParam(instance, 'Logo Image Type', null),
|
|
||||||
logo: this.core.getParam(instance, 'Logo', null),
|
|
||||||
color1: this.core.getParam(instance, 'Color1', null),
|
|
||||||
color2: this.core.getParam(instance, 'Color2', null),
|
|
||||||
|
|
||||||
|
logo = logo ? urlJoin(instance.botId, 'cache', logo) : 'images/logo-gb.png';
|
||||||
|
|
||||||
|
let config = {
|
||||||
|
instanceId: instance.instanceId,
|
||||||
|
botId: botId,
|
||||||
|
theme: theme,
|
||||||
|
speechToken: speechToken,
|
||||||
|
authenticatorTenant: instance.authenticatorTenant,
|
||||||
|
authenticatorClientId: instance.marketplaceId,
|
||||||
|
paramLogoImageUrl: this.core.getParam(instance, 'Logo Image Url', null),
|
||||||
|
paramLogoImageAlt: this.core.getParam(instance, 'Logo Image Alt', null),
|
||||||
|
paramLogoImageWidth: this.core.getParam(instance, 'Logo Image Width', null),
|
||||||
|
paramLogoImageHeight: this.core.getParam(instance, 'Logo Image Height', null),
|
||||||
|
paramLogoImageType: this.core.getParam(instance, 'Logo Image Type', null),
|
||||||
|
logo: logo,
|
||||||
|
color1: this.core.getParam(instance, 'Color1', null),
|
||||||
|
color2: this.core.getParam(instance, 'Color2', null)
|
||||||
|
};
|
||||||
|
|
||||||
})
|
if (!GBConfigService.get('STORAGE_NAME')) {
|
||||||
);
|
config['domain'] = `http://localhost:${process.env.PORT}/directline/${botId}`;
|
||||||
|
} else {
|
||||||
|
const webchatTokenContainer = await this.getWebchatToken(instance);
|
||||||
|
(config['conversationId'] = webchatTokenContainer.conversationId),
|
||||||
|
(config['webchatToken'] = webchatTokenContainer.token);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send(JSON.stringify(config));
|
||||||
} else {
|
} else {
|
||||||
const error = `Instance not found while retrieving from .gbui web client: ${botId}.`;
|
const error = `Instance not found while retrieving from .gbui web client: ${botId}.`;
|
||||||
res.sendStatus(error);
|
res.sendStatus(error);
|
||||||
|
@ -753,12 +765,18 @@ export class GBMinService {
|
||||||
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({
|
let config = {
|
||||||
appId: instance.marketplaceId ? instance.marketplaceId : GBConfigService.get('MARKETPLACE_ID'),
|
appId: instance.marketplaceId ? instance.marketplaceId : GBConfigService.get('MARKETPLACE_ID'),
|
||||||
appPassword: instance.marketplacePassword
|
appPassword: instance.marketplacePassword
|
||||||
? instance.marketplacePassword
|
? instance.marketplacePassword
|
||||||
: GBConfigService.get('MARKETPLACE_SECRET')
|
: GBConfigService.get('MARKETPLACE_SECRET')
|
||||||
});
|
};
|
||||||
|
if (!GBConfigService.get('STORAGE_NAME')) {
|
||||||
|
startRouter(GBServer.globals.server, instance.botId);
|
||||||
|
config['clientOptions'] = { baseUri: `http://localhost:${process.env.PORT}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
const adapter = new BotFrameworkAdapter(config);
|
||||||
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);
|
||||||
|
@ -771,6 +789,28 @@ export class GBMinService {
|
||||||
// The minimal bot is built here.
|
// The minimal bot is built here.
|
||||||
|
|
||||||
const min = new GBMinInstance();
|
const min = new GBMinInstance();
|
||||||
|
|
||||||
|
// Setups default BOT Framework dialogs.
|
||||||
|
|
||||||
|
min.userProfile = conversationState.createProperty('userProfile');
|
||||||
|
const dialogState = conversationState.createProperty('dialogState');
|
||||||
|
|
||||||
|
min.dialogs = new DialogSet(dialogState);
|
||||||
|
min.dialogs.add(new TextPrompt('textPrompt'));
|
||||||
|
min.dialogs.add(new AttachmentPrompt('attachmentPrompt'));
|
||||||
|
|
||||||
|
min.dialogs.add(new ConfirmPrompt('confirmPrompt'));
|
||||||
|
if (process.env.ENABLE_AUTH) {
|
||||||
|
min.dialogs.add(
|
||||||
|
new OAuthPrompt('oAuthPrompt', {
|
||||||
|
connectionName: 'OAuth2',
|
||||||
|
text: 'Please sign in to General Bots.',
|
||||||
|
title: 'Sign in',
|
||||||
|
timeout: 300000
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
min.botId = instance.botId;
|
min.botId = instance.botId;
|
||||||
min.bot = adapter;
|
min.bot = adapter;
|
||||||
min.userState = userState;
|
min.userState = userState;
|
||||||
|
@ -793,6 +833,15 @@ export class GBMinService {
|
||||||
min['apiConversations'] = {};
|
min['apiConversations'] = {};
|
||||||
min.packages = sysPackages;
|
min.packages = sysPackages;
|
||||||
|
|
||||||
|
const receiver = async (req, res) => {
|
||||||
|
await this.receiver(req, res, conversationState, min, instance, GBServer.globals.appPackages);
|
||||||
|
};
|
||||||
|
|
||||||
|
let url = `/api/messages/${instance.botId}`;
|
||||||
|
GBServer.globals.server.post(url, receiver);
|
||||||
|
url = `/api/messages`;
|
||||||
|
GBServer.globals.server.post(url, receiver);
|
||||||
|
|
||||||
// NLP Manager.
|
// NLP Manager.
|
||||||
|
|
||||||
const manager = new NlpManager({ languages: ['pt'], forceNER: true });
|
const manager = new NlpManager({ languages: ['pt'], forceNER: true });
|
||||||
|
@ -802,7 +851,6 @@ export class GBMinService {
|
||||||
GBServer.globals.minBoot = min;
|
GBServer.globals.minBoot = min;
|
||||||
GBServer.globals.minBoot.instance.marketplaceId = GBConfigService.get('MARKETPLACE_ID');
|
GBServer.globals.minBoot.instance.marketplaceId = GBConfigService.get('MARKETPLACE_ID');
|
||||||
GBServer.globals.minBoot.instance.marketplacePassword = GBConfigService.get('MARKETPLACE_SECRET');
|
GBServer.globals.minBoot.instance.marketplacePassword = GBConfigService.get('MARKETPLACE_SECRET');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (min.instance.facebookWorkplaceVerifyToken) {
|
if (min.instance.facebookWorkplaceVerifyToken) {
|
||||||
|
@ -860,8 +908,7 @@ export class GBMinService {
|
||||||
|
|
||||||
await min.whatsAppDirectLine.setup(true);
|
await min.whatsAppDirectLine.setup(true);
|
||||||
} else {
|
} else {
|
||||||
if (min !== minBoot && minBoot.instance.whatsappServiceKey
|
if (min !== minBoot && minBoot.instance.whatsappServiceKey && min.instance.webchatKey) {
|
||||||
&& min.instance.webchatKey) {
|
|
||||||
min.whatsAppDirectLine = new WhatsappDirectLine(
|
min.whatsAppDirectLine = new WhatsappDirectLine(
|
||||||
min,
|
min,
|
||||||
min.botId,
|
min.botId,
|
||||||
|
@ -882,26 +929,6 @@ export class GBMinService {
|
||||||
WhatsappDirectLine.botsByNumber[botNumber] = min.whatsAppDirectLine;
|
WhatsappDirectLine.botsByNumber[botNumber] = min.whatsAppDirectLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setups default BOT Framework dialogs.
|
|
||||||
|
|
||||||
min.userProfile = conversationState.createProperty('userProfile');
|
|
||||||
const dialogState = conversationState.createProperty('dialogState');
|
|
||||||
|
|
||||||
min.dialogs = new DialogSet(dialogState);
|
|
||||||
min.dialogs.add(new TextPrompt('textPrompt'));
|
|
||||||
min.dialogs.add(new AttachmentPrompt('attachmentPrompt'));
|
|
||||||
|
|
||||||
min.dialogs.add(new ConfirmPrompt('confirmPrompt'));
|
|
||||||
if (process.env.ENABLE_AUTH) {
|
|
||||||
min.dialogs.add(
|
|
||||||
new OAuthPrompt('oAuthPrompt', {
|
|
||||||
connectionName: 'OAuth2',
|
|
||||||
text: 'Please sign in to General Bots.',
|
|
||||||
title: 'Sign in',
|
|
||||||
timeout: 300000
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return { min, adapter, conversationState };
|
return { min, adapter, conversationState };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1087,7 +1114,10 @@ export class GBMinService {
|
||||||
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
||||||
if (startDialog) {
|
if (startDialog) {
|
||||||
await sec.setParam(userId, 'welcomed', 'true');
|
await sec.setParam(userId, 'welcomed', 'true');
|
||||||
GBLogEx.info(min, `Auto start (teams) dialog is now being called: ${startDialog} for ${min.instance.botId}...`);
|
GBLogEx.info(
|
||||||
|
min,
|
||||||
|
`Auto start (teams) dialog is now being called: ${startDialog} for ${min.instance.botId}...`
|
||||||
|
);
|
||||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1095,7 +1125,8 @@ export class GBMinService {
|
||||||
|
|
||||||
// Required for F0 handling of persisted conversations.
|
// Required for F0 handling of persisted conversations.
|
||||||
|
|
||||||
GBLogEx.info(min,
|
GBLogEx.info(
|
||||||
|
min,
|
||||||
`Input> ${context.activity.text} (type: ${context.activity.type}, name: ${context.activity.name}, channelId: ${context.activity.channelId})`
|
`Input> ${context.activity.text} (type: ${context.activity.type}, name: ${context.activity.name}, channelId: ${context.activity.channelId})`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1104,7 +1135,6 @@ export class GBMinService {
|
||||||
|
|
||||||
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
||||||
|
|
||||||
|
|
||||||
if (context.activity.type === 'installationUpdate') {
|
if (context.activity.type === 'installationUpdate') {
|
||||||
GBLogEx.info(min, `Bot installed on Teams.`);
|
GBLogEx.info(min, `Bot installed on Teams.`);
|
||||||
} else if (context.activity.type === 'conversationUpdate' && context.activity.membersAdded.length > 0) {
|
} else if (context.activity.type === 'conversationUpdate' && context.activity.membersAdded.length > 0) {
|
||||||
|
@ -1133,7 +1163,8 @@ export class GBMinService {
|
||||||
) {
|
) {
|
||||||
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
||||||
|
|
||||||
GBLogEx.info(min,
|
GBLogEx.info(
|
||||||
|
min,
|
||||||
`Auto start (web 1) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
`Auto start (web 1) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
||||||
);
|
);
|
||||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
||||||
|
@ -1147,7 +1178,6 @@ export class GBMinService {
|
||||||
} else if (context.activity.type === 'message') {
|
} else if (context.activity.type === 'message') {
|
||||||
// Processes messages activities.
|
// Processes messages activities.
|
||||||
|
|
||||||
|
|
||||||
await this.processMessageActivity(context, min, step, pid);
|
await this.processMessageActivity(context, min, step, pid);
|
||||||
} else if (context.activity.type === 'event') {
|
} else if (context.activity.type === 'event') {
|
||||||
// Processes events activities.
|
// Processes events activities.
|
||||||
|
@ -1155,8 +1185,9 @@ export class GBMinService {
|
||||||
await this.processEventActivity(min, user, context, step);
|
await this.processEventActivity(min, user, context, step);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const msg = `ERROR: ${error.message} ${error.stack} ${error.error ? error.error.body : ''} ${error.error ? (error.error.stack ? error.error.stack : '') : ''
|
const msg = `ERROR: ${error.message} ${error.stack} ${error.error ? error.error.body : ''} ${
|
||||||
}`;
|
error.error ? (error.error.stack ? error.error.stack : '') : ''
|
||||||
|
}`;
|
||||||
GBLog.error(msg);
|
GBLog.error(msg);
|
||||||
|
|
||||||
await min.conversationalService.sendText(
|
await min.conversationalService.sendText(
|
||||||
|
@ -1170,7 +1201,17 @@ export class GBMinService {
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await adapter['processActivity'](req, res, handler);
|
if (!GBConfigService.get('STORAGE_NAME')) {
|
||||||
|
const context = adapter['createContext'](req);
|
||||||
|
context['_activity'] = context.activity.body;
|
||||||
|
await handler(context);
|
||||||
|
// Return status
|
||||||
|
res.status(200);
|
||||||
|
|
||||||
|
res.end();
|
||||||
|
} else {
|
||||||
|
await adapter['processActivity'](req, res, handler);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code === 401) {
|
if (error.code === 401) {
|
||||||
GBLog.error('Calling processActivity due to Signing Key could not be retrieved error.');
|
GBLog.error('Calling processActivity due to Signing Key could not be retrieved error.');
|
||||||
|
@ -1209,7 +1250,10 @@ export class GBMinService {
|
||||||
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;
|
||||||
GBLogEx.info(min, `Auto start (web 2) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`);
|
GBLogEx.info(
|
||||||
|
min,
|
||||||
|
`Auto start (web 2) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
||||||
|
);
|
||||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
||||||
}
|
}
|
||||||
} else if (context.activity.name === 'updateToken') {
|
} else if (context.activity.name === 'updateToken') {
|
||||||
|
@ -1263,7 +1307,6 @@ export class GBMinService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleUploads(min, step, user, params, autoSave) {
|
private async handleUploads(min, step, user, params, autoSave) {
|
||||||
|
|
||||||
// Prepare Promises to download each attachment and then execute each Promise.
|
// Prepare Promises to download each attachment and then execute each Promise.
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -1294,7 +1337,6 @@ export class GBMinService {
|
||||||
GBServer.globals.files[handle] = gbfile;
|
GBServer.globals.files[handle] = gbfile;
|
||||||
|
|
||||||
if (!min.cbMap[user.userId] && autoSave) {
|
if (!min.cbMap[user.userId] && autoSave) {
|
||||||
|
|
||||||
const result = await t['internalAutoSave']({ min: min, handle: handle });
|
const result = await t['internalAutoSave']({ min: min, handle: handle });
|
||||||
await min.conversationalService.sendText(
|
await min.conversationalService.sendText(
|
||||||
min,
|
min,
|
||||||
|
@ -1303,12 +1345,9 @@ export class GBMinService {
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return gbfile;
|
return gbfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
await this.sendActivity('Error uploading file. Please,start again.');
|
await this.sendActivity('Error uploading file. Please,start again.');
|
||||||
}
|
}
|
||||||
|
@ -1367,7 +1406,8 @@ export class GBMinService {
|
||||||
context.activity.text = context.activity.text.trim();
|
context.activity.text = context.activity.text.trim();
|
||||||
|
|
||||||
const member = context.activity.from;
|
const member = context.activity.from;
|
||||||
let memberId, email;
|
let memberId = null,
|
||||||
|
email = null;
|
||||||
|
|
||||||
// Processes e-mail from id in case of Teams messages.
|
// Processes e-mail from id in case of Teams messages.
|
||||||
|
|
||||||
|
@ -1399,10 +1439,8 @@ export class GBMinService {
|
||||||
const userId = user.userId;
|
const userId = user.userId;
|
||||||
const params = user.params ? JSON.parse(user.params) : {};
|
const params = user.params ? JSON.parse(user.params) : {};
|
||||||
|
|
||||||
|
|
||||||
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();
|
||||||
|
@ -1420,7 +1458,6 @@ export class GBMinService {
|
||||||
userId,
|
userId,
|
||||||
context.activity.text
|
context.activity.text
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1439,7 +1476,8 @@ export class GBMinService {
|
||||||
) {
|
) {
|
||||||
await sec.setParam(userId, 'welcomed', 'true');
|
await sec.setParam(userId, 'welcomed', 'true');
|
||||||
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
||||||
GBLogEx.info(min,
|
GBLogEx.info(
|
||||||
|
min,
|
||||||
`Auto start (4) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
`Auto start (4) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
||||||
);
|
);
|
||||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
||||||
|
@ -1500,21 +1538,18 @@ export class GBMinService {
|
||||||
} else {
|
} else {
|
||||||
// Removes unwanted chars in input text.
|
// Removes unwanted chars in input text.
|
||||||
|
|
||||||
|
|
||||||
step.context.activity['originalText'] = context.activity.text;
|
step.context.activity['originalText'] = context.activity.text;
|
||||||
const text = await GBConversationalService.handleText(min, user, step, context.activity.text);
|
const text = await GBConversationalService.handleText(min, user, step, context.activity.text);
|
||||||
step.context.activity['originalText']
|
step.context.activity['originalText'];
|
||||||
step.context.activity['text'] = text;
|
step.context.activity['text'] = text;
|
||||||
|
|
||||||
|
if (notes && text && text !== '') {
|
||||||
if (notes && text && text !== "") {
|
|
||||||
const sys = new SystemKeywords();
|
const sys = new SystemKeywords();
|
||||||
await sys.note({ pid, text });
|
await sys.note({ pid, text });
|
||||||
await step.context.sendActivity('OK.');
|
await step.context.sendActivity('OK.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Checks for bad words on input text.
|
// Checks for bad words on input text.
|
||||||
|
|
||||||
const hasBadWord = wash.check(step.context.activity.locale, text);
|
const hasBadWord = wash.check(step.context.activity.locale, text);
|
||||||
|
@ -1549,7 +1584,7 @@ export class GBMinService {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (min.cbMap[userId] && min.cbMap[userId].promise === '!GBHEAR') {
|
if (min.cbMap[userId] && min.cbMap[userId].promise === '!GBHEAR') {
|
||||||
min.cbMap[userId].promise = step.context.activity['originalText'];;
|
min.cbMap[userId].promise = step.context.activity['originalText'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a dialog in course, continue to the next step.
|
// If there is a dialog in course, continue to the next step.
|
||||||
|
@ -1557,8 +1592,9 @@ export class GBMinService {
|
||||||
try {
|
try {
|
||||||
await step.continueDialog();
|
await step.continueDialog();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const msg = `ERROR: ${error.message} ${error.stack} ${error.error ? error.error.body : ''} ${error.error ? (error.error.stack ? error.error.stack : '') : ''
|
const msg = `ERROR: ${error.message} ${error.stack} ${error.error ? error.error.body : ''} ${
|
||||||
}`;
|
error.error ? (error.error.stack ? error.error.stack : '') : ''
|
||||||
|
}`;
|
||||||
GBLog.error(msg);
|
GBLog.error(msg);
|
||||||
await min.conversationalService.sendText(
|
await min.conversationalService.sendText(
|
||||||
min,
|
min,
|
||||||
|
@ -1601,7 +1637,6 @@ export class GBMinService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ensureAPI() {
|
public async ensureAPI() {
|
||||||
|
|
||||||
const mins = GBServer.globals.minInstances;
|
const mins = GBServer.globals.minInstances;
|
||||||
|
|
||||||
function getRemoteId(ctx: Koa.Context) {
|
function getRemoteId(ctx: Koa.Context) {
|
||||||
|
@ -1611,14 +1646,11 @@ export class GBMinService {
|
||||||
const close = async () => {
|
const close = async () => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
if (GBServer.globals.server.apiServer) {
|
if (GBServer.globals.server.apiServer) {
|
||||||
GBServer.globals.server.apiServer.close(
|
GBServer.globals.server.apiServer.close(cb => {
|
||||||
cb => {
|
resolve(true);
|
||||||
resolve(true);
|
GBLogEx.info(0, 'Reloading General Bots API...');
|
||||||
GBLogEx.info(0, 'Reloading General Bots API...');
|
});
|
||||||
}
|
} else {
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
resolve(true);
|
resolve(true);
|
||||||
GBLogEx.info(0, 'Loading General Bots API...');
|
GBLogEx.info(0, 'Loading General Bots API...');
|
||||||
}
|
}
|
||||||
|
@ -1629,11 +1661,9 @@ export class GBMinService {
|
||||||
|
|
||||||
let proxies = {};
|
let proxies = {};
|
||||||
await CollectionUtil.asyncForEach(mins, async min => {
|
await CollectionUtil.asyncForEach(mins, async min => {
|
||||||
|
|
||||||
let dialogs = {};
|
let dialogs = {};
|
||||||
await CollectionUtil.asyncForEach(Object.values(min.scriptMap), async script => {
|
await CollectionUtil.asyncForEach(Object.values(min.scriptMap), async script => {
|
||||||
|
dialogs[script] = async data => {
|
||||||
dialogs[script] = async (data) => {
|
|
||||||
let sec = new SecService();
|
let sec = new SecService();
|
||||||
const user = await sec.ensureUser(
|
const user = await sec.ensureUser(
|
||||||
min,
|
min,
|
||||||
|
@ -1649,13 +1679,7 @@ export class GBMinService {
|
||||||
if (script === 'start') {
|
if (script === 'start') {
|
||||||
pid = GBVMService.createProcessInfo(user, min, 'api', null);
|
pid = GBVMService.createProcessInfo(user, min, 'api', null);
|
||||||
|
|
||||||
|
const client = await GBUtil.getDirectLineClient(min);
|
||||||
const client = await new SwaggerClient({
|
|
||||||
spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')),
|
|
||||||
requestInterceptor: req => {
|
|
||||||
req.headers['Authorization'] = `Bearer ${min.instance.webchatKey}`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const response = await client.apis.Conversations.Conversations_StartConversation();
|
const response = await client.apis.Conversations.Conversations_StartConversation();
|
||||||
|
|
||||||
min['apiConversations'][pid] = { conversation: response.obj, client: client };
|
min['apiConversations'][pid] = { conversation: response.obj, client: client };
|
||||||
|
@ -1668,7 +1692,7 @@ export class GBMinService {
|
||||||
ret = pid;
|
ret = pid;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const proxy = {
|
const proxy = {
|
||||||
|
@ -1686,10 +1710,10 @@ export class GBMinService {
|
||||||
pingSendTimeout: null,
|
pingSendTimeout: null,
|
||||||
keepAliveTimeout: null,
|
keepAliveTimeout: null,
|
||||||
listeners: {
|
listeners: {
|
||||||
unsubscribed(subscriptions: number): void { },
|
unsubscribed(subscriptions: number): void {},
|
||||||
subscribed(subscriptions: number): void { },
|
subscribed(subscriptions: number): void {},
|
||||||
disconnected(remoteId: string, connections: number): void { },
|
disconnected(remoteId: string, connections: number): void {},
|
||||||
connected(remoteId: string, connections: number): void { },
|
connected(remoteId: string, connections: number): void {},
|
||||||
messageIn(...params): void {
|
messageIn(...params): void {
|
||||||
params.shift();
|
params.shift();
|
||||||
},
|
},
|
||||||
|
@ -1699,16 +1723,8 @@ export class GBMinService {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
GBServer.globals.server.apiServer = createKoaHttpServer(
|
GBServer.globals.server.apiServer = createKoaHttpServer(GBVMService.API_PORT, getRemoteId, { prefix: `api/v3` });
|
||||||
GBVMService.API_PORT,
|
|
||||||
getRemoteId, { prefix: `api/v3` });
|
|
||||||
|
|
||||||
createRpcServer(
|
|
||||||
proxies,
|
|
||||||
GBServer.globals.server.apiServer,
|
|
||||||
opts
|
|
||||||
);
|
|
||||||
|
|
||||||
|
createRpcServer(proxies, GBServer.globals.server.apiServer, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
360
packages/core.gbapp/services/router/bridge.ts
Normal file
|
@ -0,0 +1,360 @@
|
||||||
|
import bodyParser from 'body-parser';
|
||||||
|
import express from 'express';
|
||||||
|
import fetch from 'isomorphic-fetch';
|
||||||
|
import moment from 'moment';
|
||||||
|
import * as uuidv4 from 'uuid';
|
||||||
|
|
||||||
|
import { IActivity, IBotData, IConversation, IConversationUpdateActivity, IMessageActivity } from './types';
|
||||||
|
import { GBConfigService } from '../GBConfigService.js';
|
||||||
|
|
||||||
|
const expiresIn = 1800;
|
||||||
|
const conversationsCleanupInterval = 10000;
|
||||||
|
const conversations: { [key: string]: IConversation } = {};
|
||||||
|
const botDataStore: { [key: string]: IBotData } = {};
|
||||||
|
|
||||||
|
export const getRouter = (
|
||||||
|
serviceUrl: string,
|
||||||
|
botUrl: string,
|
||||||
|
conversationInitRequired = true,
|
||||||
|
botId
|
||||||
|
): express.Router => {
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.use(bodyParser.json()); // for parsing application/json
|
||||||
|
router.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
|
||||||
|
router.use((req, res, next) => {
|
||||||
|
res.header('Access-Control-Allow-Origin', '*');
|
||||||
|
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, PATCH, OPTIONS');
|
||||||
|
res.header(
|
||||||
|
'Access-Control-Allow-Headers',
|
||||||
|
'Origin, X-Requested-With, Content-Type, Accept, Authorization, x-ms-bot-agent'
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
// CLIENT ENDPOINT
|
||||||
|
router.options(`/directline/${botId}/`, (req, res) => {
|
||||||
|
res.status(200).end();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Creates a conversation
|
||||||
|
const reqs = (req, res) => {
|
||||||
|
const conversationId: string = uuidv4.v4().toString();
|
||||||
|
conversations[conversationId] = {
|
||||||
|
conversationId,
|
||||||
|
history: []
|
||||||
|
};
|
||||||
|
console.log('Created conversation with conversationId: ' + conversationId);
|
||||||
|
|
||||||
|
const activity = createConversationUpdateActivity(serviceUrl, conversationId);
|
||||||
|
fetch(botUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(activity),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
}).then(response => {
|
||||||
|
res.status(response.status).send({
|
||||||
|
conversationId,
|
||||||
|
expiresIn
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
router.post('/v3/directline/conversations', reqs);
|
||||||
|
router.post(`/directline/${botId}/conversations`, reqs);
|
||||||
|
router.post(`/directline/conversations`, reqs);
|
||||||
|
|
||||||
|
// Reconnect API
|
||||||
|
router.get('/v3/directline/conversations/:conversationId', (req, res) => {
|
||||||
|
const conversation = getConversation(req.params.conversationId, conversationInitRequired);
|
||||||
|
if (conversation) {
|
||||||
|
res.status(200).send(conversation);
|
||||||
|
} else {
|
||||||
|
// Conversation was never initialized
|
||||||
|
res.status(400).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn('/v3/directline/conversations/:conversationId not implemented');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Gets activities from store (local history array for now)
|
||||||
|
router.get(`/directline/${botId}/conversations/:conversationId/activities`, (req, res) => {
|
||||||
|
const watermark = req.query.watermark && req.query.watermark !== 'null' ? Number(req.query.watermark) : 0;
|
||||||
|
|
||||||
|
const conversation = getConversation(req.params.conversationId, conversationInitRequired);
|
||||||
|
|
||||||
|
if (conversation) {
|
||||||
|
// If the bot has pushed anything into the history array
|
||||||
|
if (conversation.history.length > watermark) {
|
||||||
|
const activities = conversation.history.slice(watermark);
|
||||||
|
res.status(200).json({
|
||||||
|
activities,
|
||||||
|
watermark: watermark + activities.length
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.status(200).send({
|
||||||
|
activities: [],
|
||||||
|
watermark
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Conversation was never initialized
|
||||||
|
res.status(400).send();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sends message to bot. Assumes message activities
|
||||||
|
router.post(`/directline/${botId}/conversations/:conversationId/activities`, (req, res) => {
|
||||||
|
const incomingActivity = req.body;
|
||||||
|
// Make copy of activity. Add required fields
|
||||||
|
const activity = createMessageActivity(incomingActivity, serviceUrl, req.params.conversationId);
|
||||||
|
|
||||||
|
const conversation = getConversation(req.params.conversationId, conversationInitRequired);
|
||||||
|
|
||||||
|
if (conversation) {
|
||||||
|
conversation.history.push(activity);
|
||||||
|
fetch(botUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(activity),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
}).then(response => {
|
||||||
|
res.status(response.status).json({ id: activity.id });
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Conversation was never initialized
|
||||||
|
res.status(400).send();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/v3/directline/conversations/:conversationId/upload', (req, res) => {
|
||||||
|
console.warn('/v3/directline/conversations/:conversationId/upload not implemented');
|
||||||
|
});
|
||||||
|
router.get('/v3/directline/conversations/:conversationId/stream', (req, res) => {
|
||||||
|
console.warn('/v3/directline/conversations/:conversationId/stream not implemented');
|
||||||
|
});
|
||||||
|
|
||||||
|
// BOT CONVERSATION ENDPOINT
|
||||||
|
|
||||||
|
router.post('/v3/conversations', (req, res) => {
|
||||||
|
console.warn('/v3/conversations not implemented');
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/v3/conversations/:conversationId/activities', (req, res) => {
|
||||||
|
let activity: IActivity;
|
||||||
|
|
||||||
|
activity = req.body;
|
||||||
|
activity.id = uuidv4.v4();
|
||||||
|
activity.from = { id: 'id', name: 'Bot' };
|
||||||
|
|
||||||
|
const conversation = getConversation(req.params.conversationId, conversationInitRequired);
|
||||||
|
if (conversation) {
|
||||||
|
conversation.history.push(activity);
|
||||||
|
res.status(200).send();
|
||||||
|
} else {
|
||||||
|
// Conversation was never initialized
|
||||||
|
res.status(400).send();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/v3/conversations/:conversationId/activities/:activityId', (req, res) => {
|
||||||
|
let activity: IActivity;
|
||||||
|
|
||||||
|
activity = req.body;
|
||||||
|
activity.id = uuidv4.v4();
|
||||||
|
activity.from = { id: 'id', name: 'Bot' };
|
||||||
|
|
||||||
|
const conversation = getConversation(req.params.conversationId, conversationInitRequired);
|
||||||
|
if (conversation) {
|
||||||
|
conversation.history.push(activity);
|
||||||
|
res.status(200).send();
|
||||||
|
} else {
|
||||||
|
// Conversation was never initialized
|
||||||
|
res.status(400).send();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/v3/conversations/:conversationId/members', (req, res) => {
|
||||||
|
console.warn('/v3/conversations/:conversationId/members not implemented');
|
||||||
|
});
|
||||||
|
router.get('/v3/conversations/:conversationId/activities/:activityId/members', (req, res) => {
|
||||||
|
console.warn('/v3/conversations/:conversationId/activities/:activityId/members');
|
||||||
|
});
|
||||||
|
|
||||||
|
// BOTSTATE ENDPOINT
|
||||||
|
|
||||||
|
router.get('/v3/botstate/:channelId/users/:userId', (req, res) => {
|
||||||
|
console.log('Called GET user data');
|
||||||
|
getBotData(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/v3/botstate/:channelId/conversations/:conversationId', (req, res) => {
|
||||||
|
console.log('Called GET conversation data');
|
||||||
|
getBotData(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/v3/botstate/:channelId/conversations/:conversationId/users/:userId', (req, res) => {
|
||||||
|
console.log('Called GET private conversation data');
|
||||||
|
getBotData(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/v3/botstate/:channelId/users/:userId', (req, res) => {
|
||||||
|
console.log('Called POST setUserData');
|
||||||
|
setUserData(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/v3/botstate/:channelId/conversations/:conversationId', (req, res) => {
|
||||||
|
console.log('Called POST setConversationData');
|
||||||
|
setConversationData(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/v3/botstate/:channelId/conversations/:conversationId/users/:userId', (req, res) => {
|
||||||
|
setPrivateConversationData(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.delete('/v3/botstate/:channelId/users/:userId', (req, res) => {
|
||||||
|
console.log('Called DELETE deleteStateForUser');
|
||||||
|
deleteStateForUser(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
return router;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param app The express app where your offline-directline endpoint will live
|
||||||
|
* @param port The port where your offline-directline will be hosted
|
||||||
|
* @param botUrl The url of the bot (e.g. http://127.0.0.1:3978/api/messages)
|
||||||
|
* @param conversationInitRequired Requires that a conversation is initialized before it is accessed, returning a 400
|
||||||
|
* when not the case. If set to false, a new conversation reference is created on the fly. This is true by default.
|
||||||
|
*/
|
||||||
|
export const initializeRoutes = (
|
||||||
|
app: express.Express,
|
||||||
|
port: number,
|
||||||
|
botUrl: string,
|
||||||
|
conversationInitRequired = true,
|
||||||
|
botId
|
||||||
|
) => {
|
||||||
|
conversationsCleanup();
|
||||||
|
|
||||||
|
const directLineEndpoint = `http://127.0.0.1:${port}`;
|
||||||
|
const router = getRouter(directLineEndpoint, botUrl, conversationInitRequired, botId);
|
||||||
|
|
||||||
|
app.use(router);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getConversation = (conversationId: string, conversationInitRequired: boolean) => {
|
||||||
|
// Create conversation on the fly when needed and init not required
|
||||||
|
if (!conversations[conversationId] && !conversationInitRequired) {
|
||||||
|
conversations[conversationId] = {
|
||||||
|
conversationId,
|
||||||
|
history: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return conversations[conversationId];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getBotDataKey = (channelId: string, conversationId: string, userId: string) => {
|
||||||
|
return `$${channelId || '*'}!${conversationId || '*'}!${userId || '*'}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const setBotData = (channelId: string, conversationId: string, userId: string, incomingData: IBotData): IBotData => {
|
||||||
|
const key = getBotDataKey(channelId, conversationId, userId);
|
||||||
|
const newData: IBotData = {
|
||||||
|
eTag: new Date().getTime().toString(),
|
||||||
|
data: incomingData.data
|
||||||
|
};
|
||||||
|
|
||||||
|
if (incomingData) {
|
||||||
|
botDataStore[key] = newData;
|
||||||
|
} else {
|
||||||
|
delete botDataStore[key];
|
||||||
|
newData.eTag = '*';
|
||||||
|
}
|
||||||
|
|
||||||
|
return newData;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getBotData = (req: express.Request, res: express.Response) => {
|
||||||
|
const key = getBotDataKey(req.params.channelId, req.params.conversationId, req.params.userId);
|
||||||
|
console.log('Data key: ' + key);
|
||||||
|
|
||||||
|
res.status(200).send(botDataStore[key] || { data: null, eTag: '*' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const setUserData = (req: express.Request, res: express.Response) => {
|
||||||
|
res.status(200).send(setBotData(req.params.channelId, req.params.conversationId, req.params.userId, req.body));
|
||||||
|
};
|
||||||
|
|
||||||
|
const setConversationData = (req: express.Request, res: express.Response) => {
|
||||||
|
res.status(200).send(setBotData(req.params.channelId, req.params.conversationId, req.params.userId, req.body));
|
||||||
|
};
|
||||||
|
|
||||||
|
const setPrivateConversationData = (req: express.Request, res: express.Response) => {
|
||||||
|
res.status(200).send(setBotData(req.params.channelId, req.params.conversationId, req.params.userId, req.body));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const start = (server, botId) => {
|
||||||
|
const port = GBConfigService.getServerPort();
|
||||||
|
initializeRoutes(server, Number(port), `http://127.0.0.1:${port}/api/messages/${botId}`, null, botId);
|
||||||
|
|
||||||
|
if (botId === 'default') {
|
||||||
|
initializeRoutes(server, Number(port), `http://127.0.0.1:${port}/api/messages`, null, botId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteStateForUser = (req: express.Request, res: express.Response) => {
|
||||||
|
Object.keys(botDataStore).forEach(key => {
|
||||||
|
if (key.endsWith(`!{req.query.userId}`)) {
|
||||||
|
delete botDataStore[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
res.status(200).send();
|
||||||
|
};
|
||||||
|
|
||||||
|
// CLIENT ENDPOINT HELPERS
|
||||||
|
const createMessageActivity = (
|
||||||
|
incomingActivity: IMessageActivity,
|
||||||
|
serviceUrl: string,
|
||||||
|
conversationId: string
|
||||||
|
): IMessageActivity => {
|
||||||
|
return {
|
||||||
|
...incomingActivity,
|
||||||
|
channelId: 'emulator',
|
||||||
|
serviceUrl,
|
||||||
|
conversation: { id: conversationId },
|
||||||
|
id: uuidv4.v4()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const createConversationUpdateActivity = (serviceUrl: string, conversationId: string): IConversationUpdateActivity => {
|
||||||
|
const activity: IConversationUpdateActivity = {
|
||||||
|
type: 'conversationUpdate',
|
||||||
|
channelId: 'emulator',
|
||||||
|
serviceUrl,
|
||||||
|
conversation: { id: conversationId },
|
||||||
|
id: uuidv4.v4(),
|
||||||
|
membersAdded: [],
|
||||||
|
membersRemoved: [],
|
||||||
|
from: { id: 'offline-directline', name: 'Offline Directline Server' }
|
||||||
|
};
|
||||||
|
return activity;
|
||||||
|
};
|
||||||
|
|
||||||
|
const conversationsCleanup = () => {
|
||||||
|
setInterval(() => {
|
||||||
|
const expiresTime = moment().subtract(expiresIn, 'seconds');
|
||||||
|
Object.keys(conversations).forEach(conversationId => {
|
||||||
|
if (conversations[conversationId].history.length > 0) {
|
||||||
|
const lastTime = moment(
|
||||||
|
conversations[conversationId].history[conversations[conversationId].history.length - 1].localTimestamp
|
||||||
|
);
|
||||||
|
if (lastTime < expiresTime) {
|
||||||
|
delete conversations[conversationId];
|
||||||
|
console.log('deleted cId: ' + conversationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, conversationsCleanupInterval);
|
||||||
|
};
|
66
packages/core.gbapp/services/router/types.ts
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
export interface IUser {
|
||||||
|
id: string,
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IChannelAccount {
|
||||||
|
id?: string,
|
||||||
|
name?: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IConversationAccount extends IChannelAccount {
|
||||||
|
isGroup?: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAttachment {
|
||||||
|
contentType?: string,
|
||||||
|
contentUrl?: string,
|
||||||
|
content?: any,
|
||||||
|
name?: string,
|
||||||
|
thumbnailUrl?: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IEntity {
|
||||||
|
type?: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IActivity {
|
||||||
|
type?: string,
|
||||||
|
id?: string,
|
||||||
|
serviceUrl?: string,
|
||||||
|
timestamp?: string,
|
||||||
|
localTimestamp?: string,
|
||||||
|
channelId?: string,
|
||||||
|
from?: IChannelAccount,
|
||||||
|
conversation?: IConversationAccount,
|
||||||
|
recipient?: IChannelAccount,
|
||||||
|
replyToId?: string,
|
||||||
|
channelData?: any,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IMessageActivity extends IActivity {
|
||||||
|
locale?: string,
|
||||||
|
text?: string,
|
||||||
|
summary?: string,
|
||||||
|
textFormat?: string,
|
||||||
|
attachmentLayout?: string,
|
||||||
|
attachments?: IAttachment[],
|
||||||
|
entities?: IEntity[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IBotData {
|
||||||
|
eTag: string;
|
||||||
|
data: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IConversation {
|
||||||
|
conversationId: string,
|
||||||
|
history?: IActivity[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IConversationUpdateActivity extends IActivity {
|
||||||
|
membersAdded?: IChannelAccount[],
|
||||||
|
membersRemoved?: IChannelAccount[],
|
||||||
|
topicName?: string,
|
||||||
|
historyDisclosed?: boolean,
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
' General Bots Copyright (c) pragmatismo.cloud. All rights reserved. Licensed under the AGPL-3.0.
|
|
||||||
' Rules from http://jsfiddle.net/roderick/dym05hsy
|
|
||||||
|
|
||||||
talk "How many installments do you want to pay your Credit?"
|
|
||||||
hear installments
|
|
||||||
|
|
||||||
if installments > 60 then
|
|
||||||
talk "The maximum number of payments is 60"
|
|
||||||
else
|
|
||||||
talk "What is the amount requested?"
|
|
||||||
hear amount
|
|
||||||
|
|
||||||
if amount >100000 then
|
|
||||||
talk "We are sorry, we can only accept proposals bellow 100k"
|
|
||||||
else
|
|
||||||
|
|
||||||
talk "What is the best due date?"
|
|
||||||
hear dueDate
|
|
||||||
|
|
||||||
interestRate = 0
|
|
||||||
adjustment = 0
|
|
||||||
|
|
||||||
if installments < 12 then
|
|
||||||
interestRate = 1.60
|
|
||||||
adjustment = 0.09748
|
|
||||||
end if
|
|
||||||
|
|
||||||
if installments > 12 and installments < 18 then
|
|
||||||
interestRate = 1.66
|
|
||||||
adjustment = 0.06869
|
|
||||||
end if
|
|
||||||
|
|
||||||
if installments > 18 and installments < 36 then
|
|
||||||
interestRate = 1.64
|
|
||||||
adjustment = 0.05397
|
|
||||||
end if
|
|
||||||
|
|
||||||
if installments > 36 and installments < 48 then
|
|
||||||
interestRate = 1.62
|
|
||||||
adjustment = 0.03931
|
|
||||||
end if
|
|
||||||
|
|
||||||
if installments > 48 and installments < 60 then
|
|
||||||
interestRate = 1.70
|
|
||||||
adjustment = 0.03270
|
|
||||||
end if
|
|
||||||
|
|
||||||
if installments = 60 then
|
|
||||||
interestRate = 1.79
|
|
||||||
adjustment = 0.02916
|
|
||||||
end if
|
|
||||||
|
|
||||||
if installments > 60 then
|
|
||||||
talk "The maximum number of payments is 60"
|
|
||||||
end if
|
|
||||||
|
|
||||||
nInstallments = parseInt(installments)
|
|
||||||
vamount = parseFloat(amount)
|
|
||||||
initialPayment = vamount * 0.3 ' 30% of the value
|
|
||||||
tac = 800
|
|
||||||
adjustment = 1.3
|
|
||||||
|
|
||||||
totalValue = amount - initialPayment + tac
|
|
||||||
paymentValue = totalValue * adjustment
|
|
||||||
finalValue = paymentValue * nInstallments + initialPayment
|
|
||||||
|
|
||||||
talk "Congratulations! Your credit analysis is **done**:"
|
|
||||||
talk "First payment: **" + initialPayment + "**"
|
|
||||||
talk "Payment value: **" + paymentValue + "**"
|
|
||||||
talk "Interest Rate: **" + interestRate + "%**"
|
|
||||||
talk "Total Value: **" + totalValue + "**"
|
|
||||||
talk "Final Value: **" + finalValue + "**"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end if
|
|
||||||
end if
|
|
|
@ -1,50 +0,0 @@
|
||||||
' General Bots Copyright (c) pragmatismo.cloud. All rights reserved. Licensed under the AGPL-3.0.
|
|
||||||
|
|
||||||
talk "Quer pagar quanto?"
|
|
||||||
hear amount
|
|
||||||
|
|
||||||
talk "Para onde?"
|
|
||||||
hear address
|
|
||||||
|
|
||||||
if amount < 5 then
|
|
||||||
talk "O mínimo que vendo este produto é 5."
|
|
||||||
else
|
|
||||||
|
|
||||||
if address is in "Rio" then
|
|
||||||
get payment amount
|
|
||||||
delivery to address
|
|
||||||
else
|
|
||||||
talk "Vou ver se tenho um parceiro para entregar aí e te falo. Eu só entrego no Rio."
|
|
||||||
end if
|
|
||||||
end if
|
|
||||||
|
|
||||||
talk "Valeu!"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Falar "Qual seu nome?"
|
|
||||||
Ouvir nome
|
|
||||||
|
|
||||||
Falar "Informe seu CEP, por favor:"
|
|
||||||
Ouvir CEP
|
|
||||||
|
|
||||||
Address = CEP
|
|
||||||
|
|
||||||
Confira seu endereço:
|
|
||||||
|
|
||||||
Address.Street
|
|
||||||
Address.Number
|
|
||||||
|
|
||||||
|
|
||||||
Falar "Manda sua localização para eu pedir a alguém para sair agora com o seu pedido"
|
|
||||||
Hear Location
|
|
||||||
|
|
||||||
SAve "Pedidos.xlsx", Nome, From, Location.Street, Location.Number
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Falar "Manda sua localização que eu encontro o posto mais próximo"
|
|
||||||
Hear Location
|
|
||||||
|
|
||||||
Find "Postos.xlsx", "Endereço=" + Location
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
if consulta = "cpf" then
|
|
||||||
talk "Qual seu CPF?"
|
|
||||||
hear cpf
|
|
||||||
talk "Aguarde alguns instantes que eu localizo seu cadastro..."
|
|
||||||
row = find "Cadastro.xlsx", "CPF=" + cpf
|
|
||||||
if row != null then
|
|
||||||
talk "Oi, " + row.Nome + "Tudo bem? "
|
|
||||||
talk "Seu código de cliente é " + row.Cod
|
|
||||||
talk "Vamos te enviar o pedido para seu endereço em: " + row.Endereço
|
|
||||||
send file "boleta.pdf", "Pague já e evite multas!"
|
|
||||||
else
|
|
||||||
talk "Tente novamente."
|
|
||||||
end if
|
|
||||||
else
|
|
||||||
talk "Qual seria seu código?"
|
|
||||||
hear cod
|
|
||||||
talk "Aguarde alguns instantes que eu localizo seu cadastro..."
|
|
||||||
row = find "Cadastro.xlsx", "Cod=" + cod
|
|
||||||
if row != null then
|
|
||||||
talk "Oi, " + row.Nome + "Tudo bem? "
|
|
||||||
talk "Seu CPF é " + row.CPF
|
|
||||||
talk "Vamos te enviar o pedido para seu endereço em: " + row.Endereço
|
|
||||||
send file "boleta.pdf", "Pague já e evite multas!"
|
|
||||||
else
|
|
||||||
talk "Tente novamente."
|
|
||||||
end if
|
|
||||||
end if
|
|
|
@ -1,5 +0,0 @@
|
||||||
talk “Olá! Seja bem vinda(o)!”
|
|
||||||
|
|
||||||
X = find “campanhas.xlsx”, “nome=1239” OR TALK “Desculpe-me, não localizei seu nome.”
|
|
||||||
|
|
||||||
talk “opa, vamos lá!” + x.nome
|
|
|
@ -1,12 +0,0 @@
|
||||||
' General Bots Copyright (c) pragmatismo.cloud. All rights reserved. Licensed under the AGPL-3.0.
|
|
||||||
|
|
||||||
talk "Quer pagar quanto?"
|
|
||||||
hear amount
|
|
||||||
|
|
||||||
if amount < 5 then
|
|
||||||
talk "O mínimo que vendo este produto é 5."
|
|
||||||
else
|
|
||||||
get payment amount
|
|
||||||
end if
|
|
||||||
|
|
||||||
talk "Valeu!"
|
|
|
@ -1,9 +0,0 @@
|
||||||
value = get "list.xslx", "A1:A1"
|
|
||||||
|
|
||||||
set "list.xslx", "A1:A1", "value"
|
|
||||||
|
|
||||||
myVar = find "chamadosbug748.xlsx", "CHAMADO=" + "5521979047667-44129-10"
|
|
||||||
status="alterado"
|
|
||||||
set "chamadosbug748.xlsx", "E" + myVar.line + ":E" + myVar.line, status
|
|
||||||
res = get "chamadosbug748.xlsx", "E" + myVar.line + ":E" + myVar.line
|
|
||||||
talk "Obrigado e até a próxima e veja bem, o resultado é esse: " + res
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
user = get "http://server/path"
|
|
||||||
|
|
||||||
user = post "http://server/path", "data"
|
|
||||||
|
|
||||||
Talk “ The user area is” + user.area, user.validuser, user.user
|
|
|
@ -1,26 +0,0 @@
|
||||||
talk "Qual seu pedido?"
|
|
||||||
hear pedido
|
|
||||||
talk "Qual seu e-mail?"
|
|
||||||
hear email
|
|
||||||
talk "Obrigado, seu pedido será processado e retornamos."
|
|
||||||
ask payment
|
|
||||||
|
|
||||||
|
|
||||||
talk "Qual seu pedido?"
|
|
||||||
hear pedido
|
|
||||||
talk "Obrigado. Agora informe seu nome:"
|
|
||||||
Hear nome
|
|
||||||
Talk "Obrigado" + nome + "! Agora falta saber onde vamos entregar. Qual seu endereço?"
|
|
||||||
Hear endereço
|
|
||||||
Save "BistroBot.gbdata\pedidos.xlsx", nome, pedido, endereço, phone
|
|
||||||
Talk "Aguarde, enquanto eu calculo o valor total do seu pedido. Volto em alguns minutos, aguarde!"
|
|
||||||
Total = Ask "+5521999995555", "Qual o valor para o pedido da(o)" + nome +"?"
|
|
||||||
ask payment Total
|
|
||||||
|
|
||||||
Talk "Qual seunome? "
|
|
||||||
Hear nome
|
|
||||||
Talk "Qual o valor pedido?"
|
|
||||||
Hear pedido
|
|
||||||
Save "Contoso.gbdata\ Aprovações.xlsx", nome, pedido, phone
|
|
||||||
Ask "+5521999995555", "Aprove por favor o pedido tal "
|
|
||||||
Talk "Sua aprovação foi enviada, aguarde."
|
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
talk "O seu nome, por favor?"
|
|
||||||
hear nome
|
|
||||||
|
|
||||||
talk "Qual seu pedido?"
|
|
||||||
hear details
|
|
||||||
|
|
||||||
talk "Valeu " + nome + "! Agora falta saber onde vamos entregar. \nQual seu endereço?"
|
|
||||||
hear address
|
|
||||||
|
|
||||||
save "Pedidos.xlsx", id, nome, from, address, details, today
|
|
|
@ -1,37 +0,0 @@
|
||||||
' General Bots Copyright (c) pragmatismo.cloud. All rights reserved. Licensed under the AGPL-3.0.
|
|
||||||
|
|
||||||
talk "Please, tell me what is the Bot name?"
|
|
||||||
hear title
|
|
||||||
|
|
||||||
talk "If you tell me your username/password, I can show service subscription list to you."
|
|
||||||
talk "What is your Username (eg.: human@domain.bot)"
|
|
||||||
hear email
|
|
||||||
|
|
||||||
talk "What is your Password"
|
|
||||||
hear password
|
|
||||||
|
|
||||||
talk "Your password? (Will be discarded after sigining process)"
|
|
||||||
talk "Can you describe in a few words what the bot is about?"
|
|
||||||
hear description
|
|
||||||
|
|
||||||
talk "Please, paste the Subscription ID (Azure):"
|
|
||||||
hear subscriptionId
|
|
||||||
|
|
||||||
talk "Please, provide the cloud location just like 'westus'?"
|
|
||||||
hear location
|
|
||||||
|
|
||||||
talk "Please, provide the Authoring Key for NLP service (LUIS)?"
|
|
||||||
hear authoringKey
|
|
||||||
|
|
||||||
talk "Sorry, this part cannot be automated yet due to Microsoft schedule, please go to https://apps.dev.microsoft.com/portal/register-app to generate manually an App ID and App Secret."
|
|
||||||
wait 5
|
|
||||||
|
|
||||||
talk "Please, provide the App ID you just generated:"
|
|
||||||
hear appId
|
|
||||||
|
|
||||||
talk "Please, provide the Generated Password:"
|
|
||||||
hear appPassword
|
|
||||||
|
|
||||||
talk "Now, I am going to create a Bot farm... Wait 5 minutes or more..."
|
|
||||||
|
|
||||||
create a bot farm using title, email, password, location, authoringKey, appId, appPassword, subscriptionId
|
|
|
@ -1,25 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
talk "qual seu nome?"
|
|
||||||
hear nome
|
|
||||||
talk "qual seu e-mail?"
|
|
||||||
hear email
|
|
||||||
|
|
||||||
documento = "meutemplate.docx", nome, email,
|
|
||||||
|
|
||||||
send file documento
|
|
||||||
|
|
||||||
save file documento, "curriculos/nome" + ".docx"
|
|
||||||
|
|
||||||
' $name
|
|
||||||
|
|
||||||
'$trabalho
|
|
||||||
|
|
||||||
'Experiência
|
|
||||||
'$ano1
|
|
||||||
'$oquefoifeitoAno1
|
|
||||||
'$ano2
|
|
||||||
'$oquefoifeitoAno2
|
|
||||||
'$ano3
|
|
||||||
'$oquefoifeitoAno1
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
rem hi
|
|
||||||
|
|
||||||
talk "Qual seu nome?"
|
|
||||||
hear name
|
|
||||||
|
|
||||||
talk "Qual seu CPF?"
|
|
||||||
hear CPF
|
|
||||||
|
|
||||||
talk "Por que você abrirá este chamado?"
|
|
||||||
hear translated motivo
|
|
||||||
|
|
||||||
talk "Seu nome: " + name
|
|
||||||
talk "Você disse em Português " + motivo.
|
|
|
@ -1,3 +0,0 @@
|
||||||
Últimas notícias
|
|
||||||
Contato
|
|
||||||
Ofertas
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"botId":"pragmatismo-ai-prd",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "Bot pragmatismo.",
|
|
||||||
"license": "Private"
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
{
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Bots & AI",
|
|
||||||
"description": "Bots & inteligência artificial.",
|
|
||||||
"id": "bots-ai",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "General Bots",
|
|
||||||
"description": "Plataforma de bots da pragmatismo.cloud.",
|
|
||||||
"id": "general-bots"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Cortana Intelligence Suite",
|
|
||||||
"description": "Suite de Big Data da Microsoft.",
|
|
||||||
"id": "cortana"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Produtividade",
|
|
||||||
"description": "Artigos sobre sistemas Internos.",
|
|
||||||
"id": "produtividade",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "Microsoft Project Online",
|
|
||||||
"description": "Artigos sobre o Microsoft Project Online.",
|
|
||||||
"id": "msproject"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "SharePoint",
|
|
||||||
"description": "SharePoint, sites e serviços.",
|
|
||||||
"id": "sharepoint"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Office 365",
|
|
||||||
"description": "Plataforma colaborativa moderna da Microsoft.",
|
|
||||||
"id": "office365"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Microsoft Dynamics",
|
|
||||||
"description": "Artigos sobre plataforma de CRM da Microsoft.",
|
|
||||||
"id": "msdynamics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Power BI",
|
|
||||||
"description": "Dashboards modernos e intuitivos.",
|
|
||||||
"id": "powerbi"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Sobre",
|
|
||||||
"description": "Artigos sobre o Bot da pragmatismo.cloud",
|
|
||||||
"id": "sobre"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 2 KiB |
|
|
@ -1,171 +0,0 @@
|
||||||
body {
|
|
||||||
background-color: #dadada !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader {
|
|
||||||
opacity: 1 !important;
|
|
||||||
filter: opacity(100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.gb-quality-button-yes {
|
|
||||||
width: 54px;
|
|
||||||
text-decoration: none;
|
|
||||||
text-transform: uppercase;
|
|
||||||
background-color: green;
|
|
||||||
color: white;
|
|
||||||
padding: 2px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: 0.9s;
|
|
||||||
transition-delay: 0.3s;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gb-quality-button-no {
|
|
||||||
width: 54px;
|
|
||||||
text-decoration: none;
|
|
||||||
text-transform: uppercase;
|
|
||||||
background-color: red;
|
|
||||||
color: white;
|
|
||||||
padding: 2px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: 0.9s;
|
|
||||||
transition-delay: 0.3s;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gb-markdown-player-quality {
|
|
||||||
background-color: #f5e4a8;
|
|
||||||
padding: 4px;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 14px;
|
|
||||||
left: -9px;
|
|
||||||
width: 100%;
|
|
||||||
border-radius: 5px;
|
|
||||||
color: #52514e;
|
|
||||||
border: 1px solid #b2a46e;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-player {
|
|
||||||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-player-container {
|
|
||||||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-player-link {
|
|
||||||
cursor: pointer !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gb-bullet-player {
|
|
||||||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif !important;
|
|
||||||
background: white;
|
|
||||||
height: 95%;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gb-bullet-player-item {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gb-image-player-outter-div {}
|
|
||||||
|
|
||||||
.gb-image-player-img {}
|
|
||||||
|
|
||||||
.gb-bullet-player-outter-div {}
|
|
||||||
|
|
||||||
.gb-video-player-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gb-video-react-player {
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.App {
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.App .body {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body {
|
|
||||||
flex-basis: 12em;
|
|
||||||
/* Default value of the element before distribuing the remaing space */
|
|
||||||
flex-grow: 0;
|
|
||||||
/* Defined the ability to groe */
|
|
||||||
flex-shrink: 0;
|
|
||||||
/* Defines the ability to shrink */
|
|
||||||
max-width: 12em;
|
|
||||||
order: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-player-container {
|
|
||||||
overflow: auto;
|
|
||||||
max-height: 90%;
|
|
||||||
font-family: "Open Sans", sans-serif;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-player-scroll {
|
|
||||||
height: 1500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 1000px) {
|
|
||||||
.media-player-scroll h1 {
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
.media-player-scroll p {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
.media-player-scroll li {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 451px) {
|
|
||||||
.media-player {
|
|
||||||
position: relative;
|
|
||||||
zoom: 90%;
|
|
||||||
height: 94% !important;
|
|
||||||
width: 95% !important;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-left: 10px;
|
|
||||||
margin-right: -40px;
|
|
||||||
}
|
|
||||||
.gb-markdown-player-quality {
|
|
||||||
bottom: -1px;
|
|
||||||
left: -3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 451px) {
|
|
||||||
.media-player {
|
|
||||||
position: relative;
|
|
||||||
zoom: 90%;
|
|
||||||
height: 100% !important;
|
|
||||||
width: 95% !important;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-left: 20px;
|
|
||||||
margin-right: -40px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
.webchat > div {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.webchat {
|
|
||||||
background-color: white !important;
|
|
||||||
left: 57%;
|
|
||||||
right: 0%;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
overflow: auto !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 1000px) {
|
|
||||||
.webchat {
|
|
||||||
display: inline-block !important;
|
|
||||||
width: 96% !important;
|
|
||||||
height: 57% !important;
|
|
||||||
font-family: 'Open Sans', sans-serif;
|
|
||||||
font-size: 14px;
|
|
||||||
left: 50%;
|
|
||||||
top: 41%;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
margin-left: -48%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 1000px) {
|
|
||||||
.webchat {
|
|
||||||
display: inline-block !important;
|
|
||||||
width: 50% !important;
|
|
||||||
font-family: 'Open Sans', sans-serif;
|
|
||||||
font-size: 14px;
|
|
||||||
top: 1% !important;
|
|
||||||
|
|
||||||
height: 96%;
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
margin-left: -8%;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
border-bottom: 4px solid #4f4f4f;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
.body .container { padding: 1em;width: 100%;height: 100% }
|
|
||||||
|
|
||||||
.body .ms-Breadcrumb {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body .selection {
|
|
||||||
height: calc(100vh - 16.5em);
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body .selection .selection-item {
|
|
||||||
display: flex;
|
|
||||||
padding: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body .selection .selection-item .name { margin-left: 1em; }
|
|
|
@ -1,8 +0,0 @@
|
||||||
.footer {
|
|
||||||
align-items: center;
|
|
||||||
background-color: #450a64;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-container { color: white; }
|
|
|
@ -1,31 +0,0 @@
|
||||||
@media screen and (max-width: 1000px) {
|
|
||||||
.player {
|
|
||||||
width: 93% !important;
|
|
||||||
height: 26% !important;
|
|
||||||
border: 7px solid #272727;
|
|
||||||
position: absolute;
|
|
||||||
top: 9%;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -48%;
|
|
||||||
background: url(../images/general-bot-background.jpg), WHITE;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: contain;
|
|
||||||
background-position: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 1000px) {
|
|
||||||
.player {
|
|
||||||
display: inline-block;
|
|
||||||
width: 46% !important;
|
|
||||||
height: 81% !important;
|
|
||||||
border: 7px solid #272727;
|
|
||||||
background: url(../images/general-bot-background.jpg), WHITE;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: contain;
|
|
||||||
background-position: center;
|
|
||||||
position: absolute;
|
|
||||||
left: 1%;
|
|
||||||
top: 15%;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
.media {
|
|
||||||
margin-top: 20px;
|
|
||||||
height: 280px !important;
|
|
||||||
width: 200px !important;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
.NavBar {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 0.2em 0.5em;
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
color:black;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
.logo {
|
|
||||||
padding-top: 4em;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
.NavBar .searchbox { width: 20em; }
|
|
||||||
|
|
||||||
.NavBar .searchbox .ms-SearchBox {
|
|
||||||
background-color: white;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
|
@ -1,199 +0,0 @@
|
||||||
.ms-Nav {
|
|
||||||
background: #222;
|
|
||||||
color: white;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-Nav-link {
|
|
||||||
color: white !important;
|
|
||||||
background-color: #222222 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-Nav-link a:active {
|
|
||||||
border-right: 2px solid white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-Nav-compositeLink .ms-Nav-chevronButton.ms-Nav-chevronButton--link {
|
|
||||||
background: #222222 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-Nav-compositeLink.is-selected .ms-Nav-chevronButton,
|
|
||||||
.ms-Nav-compositeLink.is-selected a {
|
|
||||||
padding-left: 70px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
html[dir="ltr"] .ms-Nav-compositeLink.is-selected .ms-Nav-chevronButton:after,
|
|
||||||
html[dir="ltr"] .ms-Nav-compositeLink.is-selected a:after {
|
|
||||||
border-left: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 419px) {
|
|
||||||
.sidebar {
|
|
||||||
display: inline-block !important;
|
|
||||||
background-color: #3f3f3f !important;
|
|
||||||
height: 8%;
|
|
||||||
width: 100% !important;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tittleSideBarMenu {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconMenu {
|
|
||||||
color: #d1d1d1;
|
|
||||||
font-size: 13px;
|
|
||||||
display: inline;
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
.iconMenu:hover {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.IconsMenu {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -23px;
|
|
||||||
height: 22px;
|
|
||||||
width: 300px;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -150px;
|
|
||||||
text-align: center;
|
|
||||||
font-family: "Open Sans", sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconText {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 520px) and (max-width:1000px) {
|
|
||||||
.tittleSideBarMenu {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.sidebar {
|
|
||||||
display: inline-block !important;
|
|
||||||
background-color: #3f3f3f !important;
|
|
||||||
height: 8%;
|
|
||||||
width: 100% !important;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
background-image: url(../images/bot-logo.png);
|
|
||||||
background-position: 2px 2px;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: contain;
|
|
||||||
}
|
|
||||||
.IconsMenu {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -11px;
|
|
||||||
height: 22px;
|
|
||||||
width: 416px;
|
|
||||||
left: 100px !important;
|
|
||||||
margin-left: 0px !important;
|
|
||||||
text-align: center;
|
|
||||||
font-family: "Open Sans", sans-serif;
|
|
||||||
}
|
|
||||||
.iconMenu {
|
|
||||||
color: #d1d1d1;
|
|
||||||
}
|
|
||||||
.iconMenu:hover {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 420px) and (max-width: 1000px) {
|
|
||||||
.sidebar {
|
|
||||||
display: inline-block !important;
|
|
||||||
background-color: #3f3f3f !important;
|
|
||||||
height: 8%;
|
|
||||||
width: 100% !important;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
.tittleSideBarMenu {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconMenu {
|
|
||||||
color: #d1d1d1;
|
|
||||||
font-size: 14px;
|
|
||||||
display: inline;
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
.iconMenu:hover {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.IconsMenu {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -11px;
|
|
||||||
height: 22px;
|
|
||||||
width: 416px;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -208px;
|
|
||||||
text-align: center;
|
|
||||||
font-family: "Open Sans", sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconText {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@media screen and (min-width: 1000px) {
|
|
||||||
.sidebar {
|
|
||||||
display: inline-block !important;
|
|
||||||
background-color: #3f3f3f !important;
|
|
||||||
height: 15%;
|
|
||||||
position: absolute;
|
|
||||||
top: 1%;
|
|
||||||
left: 1%;
|
|
||||||
width: 46% !important;
|
|
||||||
border-right: 14px solid #3f3f3f !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tittleSideBarMenu {
|
|
||||||
color: white;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconMenu {
|
|
||||||
color: #d1d1d1;
|
|
||||||
font-size: 14px;
|
|
||||||
text-align: center;
|
|
||||||
margin-right: 20px;
|
|
||||||
margin-left: 20px;
|
|
||||||
}
|
|
||||||
.iconMenu:hover {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.IconsMenu {
|
|
||||||
width: 520px;
|
|
||||||
display: inline-flex;
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -249px;
|
|
||||||
bottom: 10px;
|
|
||||||
height: 22px;
|
|
||||||
font-family: "Open Sans", sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconText {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.iconText:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
body {
|
|
||||||
font-family: 'Open Sans', sans-serif;
|
|
||||||
font-size: 14px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Main Layout rules */
|
|
||||||
|
|
||||||
.App { min-height: 100vh; }
|
|
||||||
|
|
||||||
.App {
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.App .body {
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body .sidebar { order: -1; }
|
|
||||||
|
|
||||||
.body .content { flex: 1; }
|
|
||||||
|
|
||||||
.body .sidebar {
|
|
||||||
flex: 0 0 12em;
|
|
||||||
max-width: 12em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.App .header { height: 4em; }
|
|
||||||
|
|
||||||
.App .footer { height: 4em; }
|
|
||||||
|
|
||||||
/** Text */
|
|
||||||
|
|
||||||
.text-red { color: red; }
|
|
|
@ -1,50 +0,0 @@
|
||||||
{
|
|
||||||
"accent": "Red",
|
|
||||||
"avatarSize": 40,
|
|
||||||
|
|
||||||
"backgroundColor": "White",
|
|
||||||
|
|
||||||
"bubbleBackground": "White",
|
|
||||||
"bubbleBorder": "solid 1px #E6E6E6",
|
|
||||||
"bubbleBorderRadius": 2,
|
|
||||||
"bubbleFromUserBackground": "White",
|
|
||||||
"bubbleFromUserBorder": "solid 1px #E6E6E6",
|
|
||||||
"bubbleFromUserBorderRadius": 2,
|
|
||||||
"bubbleFromUserTextColor": "Black",
|
|
||||||
"bubbleImageHeight": 240,
|
|
||||||
"bubbleMaxWidth": 480,
|
|
||||||
"bubbleMinHeight": 40,
|
|
||||||
"bubbleMinWidth": 250,
|
|
||||||
"bubbleTextColor": "Black",
|
|
||||||
|
|
||||||
"hideSendBox": false,
|
|
||||||
|
|
||||||
"microphoneButtonColorOnDictate": "#F33",
|
|
||||||
|
|
||||||
"paddingRegular": 10,
|
|
||||||
"paddingWide": 20,
|
|
||||||
|
|
||||||
"sendBoxButtonColor": "#999",
|
|
||||||
"sendBoxButtonColorOnDisabled": "#CCC",
|
|
||||||
"sendBoxButtonColorOnFocus": "#333",
|
|
||||||
"sendBoxButtonColorOnHover": "#333",
|
|
||||||
|
|
||||||
"sendBoxHeight": 40,
|
|
||||||
|
|
||||||
"showSpokenText": false,
|
|
||||||
|
|
||||||
"suggestedActionBackground": "White",
|
|
||||||
"suggestedActionBorder": "solid 2px",
|
|
||||||
"suggestedActionBorderRadius": 0,
|
|
||||||
"suggestedActionDisabledBackground": "White",
|
|
||||||
"suggestedActionDisabledBorder": "solid 2px #E6E6E6",
|
|
||||||
"suggestedActionHeight": 40,
|
|
||||||
"transcriptOverlayButtonBackground": "rgba(0, 0, 0, .6)",
|
|
||||||
"transcriptOverlayButtonBackgroundOnFocus": "rgba(0, 0, 0, .8)",
|
|
||||||
"transcriptOverlayButtonBackgroundOnHover": "rgba(0, 0, 0, .8)",
|
|
||||||
"transcriptOverlayButtonColor": "White",
|
|
||||||
"transcriptOverlayButtonColorOnFocus": "White",
|
|
||||||
"transcriptOverlayButtonColorOnHover": "White",
|
|
||||||
|
|
||||||
"videoHeight": 270
|
|
||||||
}
|
|
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 958 B |