new(all): Removal of OneDrive dependencies.
This commit is contained in:
parent
e557eaa24f
commit
5fe45a04f7
12 changed files with 214 additions and 164 deletions
|
@ -175,6 +175,7 @@
|
||||||
"mammoth": "1.8.0",
|
"mammoth": "1.8.0",
|
||||||
"mariadb": "3.3.1",
|
"mariadb": "3.3.1",
|
||||||
"mime-types": "2.1.35",
|
"mime-types": "2.1.35",
|
||||||
|
"minio": "^8.0.4",
|
||||||
"moment": "2.30.1",
|
"moment": "2.30.1",
|
||||||
"ms-rest-azure": "3.0.2",
|
"ms-rest-azure": "3.0.2",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
|
|
|
@ -1495,7 +1495,7 @@ export class DialogKeywords {
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
|
|
||||||
const ext = path.extname(filename);
|
const ext = path.extname(filename);
|
||||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||||
|
|
|
@ -150,7 +150,7 @@ 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 && GBConfigService.get('STORAGE_NAME')) {
|
if (writeVBS && GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
let text = await this.getTextFromWord(folder, wordFile);
|
let text = await this.getTextFromWord(folder, wordFile);
|
||||||
|
|
||||||
// Write VBS file without pragma keywords.
|
// Write VBS file without pragma keywords.
|
||||||
|
|
|
@ -2726,7 +2726,7 @@ export class SystemKeywords {
|
||||||
try {
|
try {
|
||||||
let data;
|
let data;
|
||||||
|
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||||
let packagePath = '/' + urlJoin(gbaiName, `${min.botId}.gbdrive`);
|
let packagePath = '/' + urlJoin(gbaiName, `${min.botId}.gbdrive`);
|
||||||
|
|
|
@ -1280,7 +1280,7 @@ export class GBConversationalService {
|
||||||
* Sends a message in a user with an already started conversation (got ConversationReference set)
|
* Sends a message in a user with an already started conversation (got ConversationReference set)
|
||||||
*/
|
*/
|
||||||
public async sendOnConversation(min: GBMinInstance, user: GuaribasUser, message: any) {
|
public async sendOnConversation(min: GBMinInstance, user: GuaribasUser, message: any) {
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
const ref = JSON.parse(user.conversationReference);
|
const ref = JSON.parse(user.conversationReference);
|
||||||
MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl);
|
MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl);
|
||||||
await min.bot['continueConversation'](ref, async t1 => {
|
await min.bot['continueConversation'](ref, async t1 => {
|
||||||
|
|
|
@ -67,6 +67,7 @@ import { GBDeployer } from './GBDeployer.js';
|
||||||
import { SystemKeywords } from '../../basic.gblib/services/SystemKeywords.js';
|
import { SystemKeywords } from '../../basic.gblib/services/SystemKeywords.js';
|
||||||
import csvdb from 'csv-database';
|
import csvdb from 'csv-database';
|
||||||
import { SaaSPackage } from '../../saas.gbapp/index.js';
|
import { SaaSPackage } from '../../saas.gbapp/index.js';
|
||||||
|
import { Client } from 'minio';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GBCoreService contains main logic for handling storage services related
|
* GBCoreService contains main logic for handling storage services related
|
||||||
|
@ -121,27 +122,44 @@ export class GBCoreService implements IGBCoreService {
|
||||||
public async initStorage(): Promise<any> {
|
public async initStorage(): Promise<any> {
|
||||||
this.dialect = GBConfigService.get('STORAGE_DIALECT');
|
this.dialect = GBConfigService.get('STORAGE_DIALECT');
|
||||||
|
|
||||||
|
let port: number | undefined;
|
||||||
let host: string | undefined;
|
let host: string | undefined;
|
||||||
let database: string | undefined;
|
let database: string | undefined;
|
||||||
let username: string | undefined;
|
let username: string | undefined;
|
||||||
let password: string | undefined;
|
let password: string | undefined;
|
||||||
let storage: string | undefined;
|
let storage: string | undefined;
|
||||||
|
|
||||||
if (this.dialect === 'mssql') {
|
// Validar o dialeto
|
||||||
|
if (!['mssql', 'postgres', 'sqlite'].includes(this.dialect)) {
|
||||||
|
throw new Error(`Unknown or unsupported dialect: ${this.dialect}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configurações específicas para cada dialeto
|
||||||
|
if (this.dialect === 'mssql' || this.dialect === 'postgres') {
|
||||||
host = GBConfigService.get('STORAGE_SERVER');
|
host = GBConfigService.get('STORAGE_SERVER');
|
||||||
database = GBConfigService.get('STORAGE_NAME');
|
database = GBConfigService.get('STORAGE_NAME');
|
||||||
username = GBConfigService.get('STORAGE_USERNAME');
|
username = GBConfigService.get('STORAGE_USERNAME');
|
||||||
password = GBConfigService.get('STORAGE_PASSWORD');
|
password = GBConfigService.get('STORAGE_PASSWORD');
|
||||||
|
|
||||||
|
const portStr = GBConfigService.get('STORAGE_PORT');
|
||||||
|
port = portStr ? parseInt(portStr, 10) : undefined;
|
||||||
|
|
||||||
|
if (!host || !database || !username || !password || !port) {
|
||||||
|
throw new Error(`Missing required configuration for ${this.dialect}.`);
|
||||||
|
}
|
||||||
} else if (this.dialect === 'sqlite') {
|
} else if (this.dialect === 'sqlite') {
|
||||||
storage = GBConfigService.get('STORAGE_FILE');
|
storage = GBConfigService.get('STORAGE_FILE');
|
||||||
|
|
||||||
|
if (!storage) {
|
||||||
|
throw new Error('STORAGE_FILE is required for SQLite.');
|
||||||
|
}
|
||||||
|
|
||||||
if (!(await GBUtil.exists(storage))) {
|
if (!(await GBUtil.exists(storage))) {
|
||||||
process.env.STORAGE_SYNC = 'true';
|
process.env.STORAGE_SYNC = 'true';
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
throw new Error(`Unknown dialect: ${this.dialect}.`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configuração de logging
|
||||||
const logging: boolean | Function =
|
const logging: boolean | Function =
|
||||||
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
||||||
? (str: string): void => {
|
? (str: string): void => {
|
||||||
|
@ -149,34 +167,41 @@ export class GBCoreService implements IGBCoreService {
|
||||||
}
|
}
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
|
// Configuração de encrypt (específico para MSSQL)
|
||||||
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
||||||
|
|
||||||
const acquire = parseInt(GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT'));
|
// Configuração do pool
|
||||||
|
const acquireStr = GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT');
|
||||||
|
const acquire = acquireStr ? parseInt(acquireStr, 10) : 10000; // Valor padrão de 10 segundos
|
||||||
|
|
||||||
|
// Configuração do Sequelize
|
||||||
const sequelizeOptions: SequelizeOptions = {
|
const sequelizeOptions: SequelizeOptions = {
|
||||||
define: {
|
define: {
|
||||||
freezeTableName: true,
|
freezeTableName: true,
|
||||||
timestamps: false
|
timestamps: false,
|
||||||
},
|
},
|
||||||
host: host,
|
host: host,
|
||||||
|
port: port,
|
||||||
logging: logging as boolean,
|
logging: logging as boolean,
|
||||||
dialect: this.dialect as Dialect,
|
dialect: this.dialect as Dialect,
|
||||||
storage: storage,
|
storage: storage,
|
||||||
quoteIdentifiers: false, // set case-insensitive
|
quoteIdentifiers: this.dialect === 'postgres',
|
||||||
dialectOptions: {
|
dialectOptions: this.dialect === 'mssql' ? {
|
||||||
options: {
|
options: {
|
||||||
trustServerCertificate: true,
|
trustServerCertificate: true,
|
||||||
encrypt: encrypt
|
encrypt: encrypt,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
} : {},
|
||||||
pool: {
|
pool: {
|
||||||
max: 5,
|
max: 5,
|
||||||
min: 0,
|
min: 0,
|
||||||
idle: 10000,
|
idle: 10000,
|
||||||
evict: 10000,
|
evict: 10000,
|
||||||
acquire: acquire
|
acquire: acquire,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Inicializar o Sequelize
|
||||||
this.sequelize = new Sequelize(database, username, password, sequelizeOptions);
|
this.sequelize = new Sequelize(database, username, password, sequelizeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,7 +700,7 @@ await fs.writeFile('.env', env);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setConfig(min, name: string, value: any): Promise<any> {
|
public async setConfig(min, name: string, value: any): Promise<any> {
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
// 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}'...`);
|
||||||
|
|
||||||
|
@ -836,8 +861,31 @@ await fs.writeFile('.env', env);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ensureFolders(instances, deployer: GBDeployer) {
|
public async ensureFolders(instances, deployer: GBDeployer) {
|
||||||
|
const storageMode = process.env.GB_MODE;
|
||||||
let libraryPath = GBConfigService.get('STORAGE_LIBRARY');
|
let libraryPath = GBConfigService.get('STORAGE_LIBRARY');
|
||||||
|
|
||||||
|
if (storageMode === 'gbcluster') {
|
||||||
|
const minioClient = new Client({
|
||||||
|
endPoint: process.env.DRIVE_SERVER,
|
||||||
|
port: parseInt(process.env.DRIVE_PORT),
|
||||||
|
useSSL: process.env.DRIVE_USE_SSL === 'true',
|
||||||
|
accessKey: process.env.DRIVE_ACCESSKEY,
|
||||||
|
secretKey: process.env.DRIVE_SECRET,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
||||||
|
|
||||||
|
const bucketStream = await minioClient.listBuckets();
|
||||||
|
|
||||||
|
for await (const bucket of bucketStream) {
|
||||||
|
if (bucket.name.endsWith('.gbai') && bucket.name.startsWith(process.env.DRIVE_ORG_PREFIX)) {
|
||||||
|
|
||||||
|
const botId = bucket.name.replace('.gbai', '').replace(process.env.DRIVE_ORG_PREFIX, '');
|
||||||
|
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (!(await GBUtil.exists(libraryPath))) {
|
if (!(await GBUtil.exists(libraryPath))) {
|
||||||
mkdirp.sync(libraryPath);
|
mkdirp.sync(libraryPath);
|
||||||
}
|
}
|
||||||
|
@ -845,20 +893,21 @@ await fs.writeFile('.env', env);
|
||||||
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
||||||
|
|
||||||
const files = await fs.readdir(libraryPath);
|
const files = await fs.readdir(libraryPath);
|
||||||
await CollectionUtil.asyncForEach(files, async file => {
|
await CollectionUtil.asyncForEach(files, async (file) => {
|
||||||
if (file.trim().toLowerCase() !== 'default.gbai' && file.charAt(0) !== '_') {
|
if (file.trim().toLowerCase() !== 'default.gbai' && file.charAt(0) !== '_') {
|
||||||
let botId = file.replace(/\.gbai/, '');
|
let botId = file.replace(/\.gbai/, '');
|
||||||
|
|
||||||
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async syncBotStorage(instances: any, botId: any, deployer: GBDeployer, libraryPath: string) {
|
private async syncBotStorage(instances: any, botId: any, deployer: GBDeployer, libraryPath: string) {
|
||||||
let instance = instances.find(p => p.botId.toLowerCase().trim() === botId.toLowerCase().trim());
|
let instance = instances.find(p => p.botId.toLowerCase().trim() === botId.toLowerCase().trim());
|
||||||
|
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
GBLog.info(`Importing package ${botId}...`);
|
GBLog.info(`Importing package ${botId}.gbai...`);
|
||||||
|
|
||||||
// Creates a bot.
|
// Creates a bot.
|
||||||
|
|
||||||
|
@ -866,45 +915,14 @@ await fs.writeFile('.env', env);
|
||||||
email = null;
|
email = null;
|
||||||
|
|
||||||
instance = await deployer.deployBlankBot(botId, mobile, email);
|
instance = await deployer.deployBlankBot(botId, mobile, email);
|
||||||
|
instances.push(instance);
|
||||||
const gbaiPath = path.join(libraryPath, `${botId}.gbai`);
|
const gbaiPath = path.join(libraryPath, `${botId}.gbai`);
|
||||||
|
|
||||||
if (!(await GBUtil.exists(gbaiPath))) {
|
if (!(await GBUtil.exists(gbaiPath))) {
|
||||||
fs.mkdir(gbaiPath, { recursive: true });
|
fs.mkdir(gbaiPath, { recursive: true });
|
||||||
|
|
||||||
const base = path.join(process.env.PWD, 'templates', 'default.gbai');
|
|
||||||
|
|
||||||
fs.cp(path.join(base, `default.gbkb`), path.join(gbaiPath, `default.gbkb`), {
|
|
||||||
errorOnExist: false,
|
|
||||||
force: true,
|
|
||||||
recursive: true
|
|
||||||
});
|
|
||||||
fs.cp(path.join(base, `default.gbot`), path.join(gbaiPath, `default.gbot`), {
|
|
||||||
errorOnExist: false,
|
|
||||||
force: true,
|
|
||||||
recursive: true
|
|
||||||
});
|
|
||||||
fs.cp(path.join(base, `default.gbtheme`), path.join(gbaiPath, `default.gbtheme`), {
|
|
||||||
errorOnExist: false,
|
|
||||||
force: true,
|
|
||||||
recursive: true
|
|
||||||
});
|
|
||||||
fs.cp(path.join(base, `default.gbdata`), path.join(gbaiPath, `default.gbdata`), {
|
|
||||||
errorOnExist: false,
|
|
||||||
force: true,
|
|
||||||
recursive: true
|
|
||||||
});
|
|
||||||
fs.cp(path.join(base, `default.gbdialog`), path.join(gbaiPath, `default.gbdialog`), {
|
|
||||||
errorOnExist: false,
|
|
||||||
force: true,
|
|
||||||
recursive: true
|
|
||||||
});
|
|
||||||
fs.cp(path.join(base, `default.gbdrive`), path.join(gbaiPath, `default.gbdrive`), {
|
|
||||||
errorOnExist: false,
|
|
||||||
force: true,
|
|
||||||
recursive: true
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async createWebDavServer(minInstances: GBMinInstance[]) {
|
public static async createWebDavServer(minInstances: GBMinInstance[]) {
|
||||||
|
|
|
@ -39,6 +39,8 @@ import express from 'express';
|
||||||
import child_process from 'child_process';
|
import child_process from 'child_process';
|
||||||
import { rimraf } from 'rimraf';
|
import { rimraf } from 'rimraf';
|
||||||
import urlJoin from 'url-join';
|
import urlJoin from 'url-join';
|
||||||
|
import { Client } from 'minio';
|
||||||
|
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBDeployer, IGBInstance, IGBPackage } from 'botlib';
|
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBDeployer, IGBInstance, IGBPackage } from 'botlib';
|
||||||
import { AzureSearch } from 'pragmatismo-io-framework';
|
import { AzureSearch } from 'pragmatismo-io-framework';
|
||||||
|
@ -220,7 +222,7 @@ 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;
|
||||||
|
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
// Gets the access token to perform service operations.
|
// 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'](
|
||||||
|
@ -232,6 +234,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
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.marketplaceId = (application as any).appId;
|
||||||
|
@ -249,7 +252,7 @@ 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')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
await this.deployBotOnAzure(instance, GBServer.globals.publicAddress);
|
await this.deployBotOnAzure(instance, GBServer.globals.publicAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,6 +490,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public async downloadFolder(
|
public async downloadFolder(
|
||||||
min: GBMinInstance,
|
min: GBMinInstance,
|
||||||
localPath: string,
|
localPath: string,
|
||||||
|
@ -494,57 +498,89 @@ export class GBDeployer implements IGBDeployer {
|
||||||
baseUrl: string = null,
|
baseUrl: string = null,
|
||||||
client = null
|
client = null
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
GBLogEx.info(min, `downloadFolder: localPath=${localPath}, remotePath=${remotePath}, baseUrl=${baseUrl}`);
|
const storageMode = process.env.GB_MODE;
|
||||||
|
|
||||||
|
if (storageMode === 'gbcluster') {
|
||||||
|
const minioClient = new Client({
|
||||||
|
endPoint: process.env.DRIVE_SERVER || 'localhost',
|
||||||
|
port: parseInt(process.env.DRIVE_PORT || '9000', 10),
|
||||||
|
useSSL: process.env.DRIVE_USE_SSL === 'true',
|
||||||
|
accessKey: process.env.DRIVE_ACCESSKEY,
|
||||||
|
secretKey: process.env.DRIVE_SECRET,
|
||||||
|
});
|
||||||
|
|
||||||
|
const bucketName = process.env.DRIVE_BUCKETPREFIX + min.botId + '.gbai';
|
||||||
|
|
||||||
|
if (!(await GBUtil.exists(localPath))) {
|
||||||
|
await fs.mkdir(localPath, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const objectsStream = minioClient.listObjects(bucketName, remotePath, true);
|
||||||
|
for await (const obj of objectsStream) {
|
||||||
|
const itemPath = path.join(localPath, obj.name);
|
||||||
|
|
||||||
|
if (obj.name.endsWith('/')) {
|
||||||
|
if (!(await GBUtil.exists(itemPath))) {
|
||||||
|
await fs.mkdir(itemPath, { recursive: true });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let download = true;
|
||||||
|
|
||||||
|
if (await GBUtil.exists(itemPath)) {
|
||||||
|
const stats = await fs.stat(itemPath);
|
||||||
|
if (stats.mtime >= new Date(obj.lastModified)) {
|
||||||
|
download = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (download) {
|
||||||
|
await minioClient.fGetObject(bucketName, obj.name, itemPath);
|
||||||
|
await fs.utimes(itemPath, new Date(), new Date(obj.lastModified));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (!baseUrl) {
|
if (!baseUrl) {
|
||||||
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||||
|
|
||||||
remotePath = remotePath.replace(/\\/gi, '/');
|
remotePath = remotePath.replace(/\\/gi, '/');
|
||||||
const parts = remotePath.split('/');
|
const parts = remotePath.split('/');
|
||||||
|
|
||||||
// Creates each subfolder.
|
|
||||||
|
|
||||||
let pathBase = localPath;
|
let pathBase = localPath;
|
||||||
if (!(await GBUtil.exists(pathBase))) {
|
if (!(await GBUtil.exists(pathBase))) {
|
||||||
fs.mkdir(pathBase);
|
await fs.mkdir(pathBase, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(parts, async item => {
|
await CollectionUtil.asyncForEach(parts, async (item) => {
|
||||||
pathBase = path.join(pathBase, item);
|
pathBase = path.join(pathBase, item);
|
||||||
if (!(await GBUtil.exists(pathBase))) {
|
if (!(await GBUtil.exists(pathBase))) {
|
||||||
fs.mkdir(pathBase);
|
await fs.mkdir(pathBase, { recursive: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Retrieves all files in remote folder.
|
|
||||||
|
|
||||||
let packagePath = GBUtil.getGBAIPath(min.botId);
|
let packagePath = GBUtil.getGBAIPath(min.botId);
|
||||||
packagePath = urlJoin(packagePath, remotePath);
|
packagePath = urlJoin(packagePath, remotePath);
|
||||||
let url = `${baseUrl}/drive/root:/${packagePath}:/children`;
|
let url = `${baseUrl}/drive/root:/${packagePath}:/children`;
|
||||||
|
|
||||||
GBLogEx.info(min, `Downloading: ${url}`);
|
|
||||||
let documents;
|
let documents;
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await client.api(url).get();
|
const res = await client.api(url).get();
|
||||||
documents = res.value;
|
documents = res.value;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
GBLogEx.info(min, `Error downloading: ${error.toString()}`);
|
GBLogEx.info(min, `Error downloading: ${error.toString()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (documents === undefined || documents.length === 0) {
|
if (documents === undefined || documents.length === 0) {
|
||||||
GBLogEx.info(min, `${remotePath} is an empty folder.`);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download files or navigate to directory to recurse.
|
await CollectionUtil.asyncForEach(documents, async (item) => {
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(documents, async item => {
|
|
||||||
const itemPath = path.join(localPath, remotePath, item.name);
|
const itemPath = path.join(localPath, remotePath, item.name);
|
||||||
|
|
||||||
if (item.folder) {
|
if (item.folder) {
|
||||||
if (!(await GBUtil.exists(itemPath))) {
|
if (!(await GBUtil.exists(itemPath))) {
|
||||||
fs.mkdir(itemPath);
|
await fs.mkdir(itemPath, { recursive: true });
|
||||||
}
|
}
|
||||||
const nextFolder = urlJoin(remotePath, item.name);
|
const nextFolder = urlJoin(remotePath, item.name);
|
||||||
await this.downloadFolder(min, localPath, nextFolder);
|
await this.downloadFolder(min, localPath, nextFolder);
|
||||||
|
@ -552,28 +588,28 @@ export class GBDeployer implements IGBDeployer {
|
||||||
let download = true;
|
let download = true;
|
||||||
|
|
||||||
if (await GBUtil.exists(itemPath)) {
|
if (await GBUtil.exists(itemPath)) {
|
||||||
const dt = await fs.stat(itemPath);
|
const stats = await fs.stat(itemPath);
|
||||||
if (new Date(dt.mtime) >= new Date(item.lastModifiedDateTime)) {
|
if (new Date(stats.mtime) >= new Date(item.lastModifiedDateTime)) {
|
||||||
download = false;
|
download = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (download) {
|
if (download) {
|
||||||
GBLogEx.info(min, `Downloading: ${itemPath}...`);
|
|
||||||
const url = item['@microsoft.graph.downloadUrl'];
|
const url = item['@microsoft.graph.downloadUrl'];
|
||||||
|
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
await fs.writeFile(itemPath, Buffer.from(await response.arrayBuffer()), { encoding: null });
|
await fs.writeFile(itemPath, new Uint8Array(await response.arrayBuffer()), { encoding: null });
|
||||||
fs.utimes(itemPath, new Date(), new Date(item.lastModifiedDateTime));
|
await fs.utimes(itemPath, new Date(), new Date(item.lastModifiedDateTime));
|
||||||
} else {
|
|
||||||
GBLogEx.info(min, `Local is up to date: ${path.basename(itemPath)}...`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UndDeploys a bot to the storage.
|
* Undeploys a bot to the storage.
|
||||||
*/
|
*/
|
||||||
public async undeployBot(botId: string, packageName: string): Promise<void> {
|
public async undeployBot(botId: string, packageName: string): Promise<void> {
|
||||||
// Deletes Bot registration on cloud.
|
// Deletes Bot registration on cloud.
|
||||||
|
@ -621,7 +657,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
await this.cleanupPackage(min.instance, packageName);
|
await this.cleanupPackage(min.instance, packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
const filePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbai, packageName);
|
const filePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbai, packageName);
|
||||||
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder);
|
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -730,7 +730,7 @@ export class GBMinService {
|
||||||
color2: this.core.getParam(instance, 'Color2', null)
|
color2: this.core.getParam(instance, 'Color2', null)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
config['domain'] = `http://localhost:${GBConfigService.get('PORT')}/directline/${botId}`;
|
config['domain'] = `http://localhost:${GBConfigService.get('PORT')}/directline/${botId}`;
|
||||||
} else {
|
} else {
|
||||||
const webchatTokenContainer = await this.getWebchatToken(instance);
|
const webchatTokenContainer = await this.getWebchatToken(instance);
|
||||||
|
@ -802,7 +802,7 @@ export class GBMinService {
|
||||||
? instance.marketplacePassword
|
? instance.marketplacePassword
|
||||||
: GBConfigService.get('MARKETPLACE_SECRET')
|
: GBConfigService.get('MARKETPLACE_SECRET')
|
||||||
};
|
};
|
||||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
startRouter(GBServer.globals.server, instance.botId);
|
startRouter(GBServer.globals.server, instance.botId);
|
||||||
config['clientOptions'] = { baseUri: `http://localhost:${GBConfigService.get('PORT')}` };
|
config['clientOptions'] = { baseUri: `http://localhost:${GBConfigService.get('PORT')}` };
|
||||||
}
|
}
|
||||||
|
@ -1047,7 +1047,7 @@ export class GBMinService {
|
||||||
const sec = new SecService();
|
const sec = new SecService();
|
||||||
let member = context.activity.recipient;
|
let member = context.activity.recipient;
|
||||||
|
|
||||||
if (process.env.STORAGE_NAME || !member) {
|
if (process.env.GB_MODE === 'legacy' || !member) {
|
||||||
member = context.activity.from;
|
member = context.activity.from;
|
||||||
}
|
}
|
||||||
let user = await sec.ensureUser(min, member.id, member.name, '', 'web', member.name, null);
|
let user = await sec.ensureUser(min, member.id, member.name, '', 'web', member.name, null);
|
||||||
|
@ -1256,7 +1256,7 @@ export class GBMinService {
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
const context = adapter['createContext'](req);
|
const context = adapter['createContext'](req);
|
||||||
context['_activity'] = context.activity.body;
|
context['_activity'] = context.activity.body;
|
||||||
await handler(context);
|
await handler(context);
|
||||||
|
@ -1800,7 +1800,7 @@ export class GBMinService {
|
||||||
private mutex: Mutex = new Mutex();
|
private mutex: Mutex = new Mutex();
|
||||||
|
|
||||||
public async watchPackages(min: GBMinInstance, packageType: string): Promise<void> {
|
public async watchPackages(min: GBMinInstance, packageType: string): Promise<void> {
|
||||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
const packagePath = GBUtil.getGBAIPath(min.botId, packageType);
|
const packagePath = GBUtil.getGBAIPath(min.botId, packageType);
|
||||||
const libraryPath = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath);
|
const libraryPath = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath);
|
||||||
|
|
||||||
|
|
|
@ -1456,7 +1456,7 @@ export class KBService implements IGBKBService {
|
||||||
await this.importKbPackage(min, localPath, p, instance);
|
await this.importKbPackage(min, localPath, p, instance);
|
||||||
GBDeployer.mountGBKBAssets(packageName, min.botId, localPath);
|
GBDeployer.mountGBKBAssets(packageName, min.botId, localPath);
|
||||||
|
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
const service = await AzureDeployerService.createInstance(deployer);
|
const service = await AzureDeployerService.createInstance(deployer);
|
||||||
const searchIndex = instance.searchIndex ? instance.searchIndex : GBServer.globals.minBoot.instance.searchIndex;
|
const searchIndex = instance.searchIndex ? instance.searchIndex : GBServer.globals.minBoot.instance.searchIndex;
|
||||||
await deployer.rebuildIndex(instance, service.getKBSearchSchema(searchIndex));
|
await deployer.rebuildIndex(instance, service.getKBSearchSchema(searchIndex));
|
||||||
|
|
|
@ -557,7 +557,7 @@ export class WhatsappDirectLine extends GBService {
|
||||||
WhatsappDirectLine.pidByNumber[from] = pid;
|
WhatsappDirectLine.pidByNumber[from] = pid;
|
||||||
GBLogEx.info(this.min, `GBWhatsapp: Starting new conversation on Bot (pid: ${pid}).`);
|
GBLogEx.info(this.min, `GBWhatsapp: Starting new conversation on Bot (pid: ${pid}).`);
|
||||||
let response;
|
let response;
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
response = await client.apis.Conversations.Conversations_StartConversation(
|
response = await client.apis.Conversations.Conversations_StartConversation(
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
25
src/app.ts
25
src/app.ts
|
@ -186,12 +186,8 @@ export class GBServer {
|
||||||
|
|
||||||
// Creates a boot instance or load it from storage.
|
// Creates a boot instance or load it from storage.
|
||||||
|
|
||||||
if (GBConfigService.get('STORAGE_SERVER')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
azureDeployer = await AzureDeployerService.createInstance(deployer);
|
|
||||||
await core.initStorage();
|
await core.initStorage();
|
||||||
} else if (!GBConfigService.get('STORAGE_NAME')) {
|
|
||||||
await core.initStorage();
|
|
||||||
} else {
|
|
||||||
[GBServer.globals.bootInstance, azureDeployer] = await core['createBootInstanceEx'](
|
[GBServer.globals.bootInstance, azureDeployer] = await core['createBootInstanceEx'](
|
||||||
core,
|
core,
|
||||||
null,
|
null,
|
||||||
|
@ -201,6 +197,9 @@ export class GBServer {
|
||||||
);
|
);
|
||||||
await core.saveInstance(GBServer.globals.bootInstance);
|
await core.saveInstance(GBServer.globals.bootInstance);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
await core.initStorage();
|
||||||
|
}
|
||||||
|
|
||||||
// Deploys system and user packages.
|
// Deploys system and user packages.
|
||||||
|
|
||||||
|
@ -225,7 +224,7 @@ export class GBServer {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (instances.length === 0) {
|
if (instances.length === 0) {
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
const instance = await importer.importIfNotExistsBotPackage(
|
const instance = await importer.importIfNotExistsBotPackage(
|
||||||
GBConfigService.get('BOT_ID'),
|
GBConfigService.get('BOT_ID'),
|
||||||
'boot.gbot',
|
'boot.gbot',
|
||||||
|
@ -251,7 +250,8 @@ export class GBServer {
|
||||||
|
|
||||||
// Just sync if not using LOAD_ONLY.
|
// Just sync if not using LOAD_ONLY.
|
||||||
|
|
||||||
if (!GBConfigService.get('STORAGE_NAME') && !process.env.LOAD_ONLY) {
|
if (GBConfigService.get('GB_MODE') !== 'legacy'
|
||||||
|
&& !process.env.LOAD_ONLY) {
|
||||||
await core['ensureFolders'](instances, deployer);
|
await core['ensureFolders'](instances, deployer);
|
||||||
}
|
}
|
||||||
GBServer.globals.bootInstance = instances[0];
|
GBServer.globals.bootInstance = instances[0];
|
||||||
|
@ -308,7 +308,7 @@ export class GBServer {
|
||||||
core.openBrowserInDevelopment();
|
core.openBrowserInDevelopment();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
GBLog.error(`STOP: ${GBUtil.toYAML(error.message)}`);
|
GBLog.error(`STOP: ${GBUtil.toYAML(error)}`);
|
||||||
shutdown();
|
shutdown();
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -378,15 +378,10 @@ export class GBServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
function shutdown() {
|
function shutdown() {
|
||||||
GBServer.globals.server.close(() => {
|
|
||||||
GBLogEx.info(0, 'General Bots server closed.');
|
|
||||||
|
|
||||||
GBServer.globals.apiServer.close(() => {
|
GBLogEx.info(0, 'General Bots server is now shutdown.');
|
||||||
GBLogEx.info(0, 'General Bots API server closed.');
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ export class GBUtil {
|
||||||
*/
|
*/
|
||||||
public static async getDirectLineClient(min: any): Promise<SwaggerClient> {
|
public static async getDirectLineClient(min: any): Promise<SwaggerClient> {
|
||||||
let config;
|
let config;
|
||||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
config = {
|
config = {
|
||||||
spec: JSON.parse(await fs.readFile('directline-v2.json', 'utf8')),
|
spec: JSON.parse(await fs.readFile('directline-v2.json', 'utf8')),
|
||||||
requestInterceptor: req => {
|
requestInterceptor: req => {
|
||||||
|
|
Loading…
Add table
Reference in a new issue