fix (all): path and fs normalization.
|
@ -173,21 +173,7 @@ export class GBAdminService implements IGBAdminService {
|
||||||
const gbaiPath = GBUtil.getGBAIPath(min.instance.botId, packageType, null);
|
const gbaiPath = GBUtil.getGBAIPath(min.instance.botId, packageType, null);
|
||||||
const localFolder = path.join('work', gbaiPath);
|
const localFolder = path.join('work', gbaiPath);
|
||||||
|
|
||||||
// .gbot packages are handled using storage API, so no download
|
await deployer['deployPackage2'](min, user, localFolder, true);
|
||||||
// of local resources is required.
|
|
||||||
const gbai = GBUtil.getGBAIPath(min.instance.botId);
|
|
||||||
|
|
||||||
if (packageType === 'gbkb') {
|
|
||||||
await deployer['cleanupPackage'](min.instance, packageName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
|
||||||
const filePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbaiPath);
|
|
||||||
GBUtil.copyIfNewerRecursive(filePath, localFolder);
|
|
||||||
} else {
|
|
||||||
await deployer['downloadFolder'](min, path.join('work', `${gbai}`), path.basename(localFolder));
|
|
||||||
}
|
|
||||||
await deployer['deployPackage2'](min, user, localFolder);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
public static async rebuildIndexPackageCommand(min: GBMinInstance, deployer: GBDeployer) {
|
public static async rebuildIndexPackageCommand(min: GBMinInstance, deployer: GBDeployer) {
|
||||||
|
|
|
@ -1500,7 +1500,7 @@ export class DialogKeywords {
|
||||||
'cache',
|
'cache',
|
||||||
`${fileOnly.replace(/\s/gi, '')}-${GBAdminService.getNumberIdentifier()}.${ext}`
|
`${fileOnly.replace(/\s/gi, '')}-${GBAdminService.getNumberIdentifier()}.${ext}`
|
||||||
);
|
);
|
||||||
fs.writeFile(localName1, buf, { encoding: null });
|
await fs.writeFile(localName1, buf, { encoding: null });
|
||||||
|
|
||||||
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName1));
|
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName1));
|
||||||
}
|
}
|
||||||
|
@ -1513,7 +1513,7 @@ export class DialogKeywords {
|
||||||
const buf = await fs.readFile(filename);
|
const buf = await fs.readFile(filename);
|
||||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||||
const localName = path.join('work', gbaiName, 'cache', `tmp${GBAdminService.getRndReadableIdentifier()}.${ext}`);
|
const localName = path.join('work', gbaiName, 'cache', `tmp${GBAdminService.getRndReadableIdentifier()}.${ext}`);
|
||||||
fs.writeFile(localName, buf, { encoding: null });
|
await fs.writeFile(localName, buf, { encoding: null });
|
||||||
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1546,7 +1546,7 @@ export class DialogKeywords {
|
||||||
|
|
||||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||||
const localName = path.join('work', gbaiName, 'cache', `qr${GBAdminService.getRndReadableIdentifier()}.png`);
|
const localName = path.join('work', gbaiName, 'cache', `qr${GBAdminService.getRndReadableIdentifier()}.png`);
|
||||||
fs.writeFile(localName, buf, { encoding: null });
|
await fs.writeFile(localName, buf, { encoding: null });
|
||||||
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
|
|
||||||
return { data: data, localName: localName, url: url };
|
return { data: data, localName: localName, url: url };
|
||||||
|
|
|
@ -155,7 +155,7 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
// Write VBS file without pragma keywords.
|
// Write VBS file without pragma keywords.
|
||||||
|
|
||||||
fs.writeFile(urlJoin(folder, vbsFile), text);
|
await fs.writeFile(urlJoin(folder, vbsFile), text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process node_modules install.
|
// Process node_modules install.
|
||||||
|
@ -215,7 +215,7 @@ export class GBVMService extends GBService {
|
||||||
"async-retry": "1.3.3"
|
"async-retry": "1.3.3"
|
||||||
}
|
}
|
||||||
}`;
|
}`;
|
||||||
fs.writeFile(urlJoin(folder, 'package.json'), packageJson);
|
await fs.writeFile(urlJoin(folder, 'package.json'), packageJson);
|
||||||
|
|
||||||
GBLogEx.info(min, `Installing .gbdialog node_modules for ${min.botId}...`);
|
GBLogEx.info(min, `Installing .gbdialog node_modules for ${min.botId}...`);
|
||||||
const npmPath = urlJoin(process.env.PWD, 'node_modules', '.bin', 'npm');
|
const npmPath = urlJoin(process.env.PWD, 'node_modules', '.bin', 'npm');
|
||||||
|
@ -498,10 +498,10 @@ export class GBVMService extends GBService {
|
||||||
// Generates function JSON metadata to be used later.
|
// Generates function JSON metadata to be used later.
|
||||||
|
|
||||||
const jsonFile = `${filename}.json`;
|
const jsonFile = `${filename}.json`;
|
||||||
fs.writeFile(jsonFile, JSON.stringify(metadata));
|
await fs.writeFile(jsonFile, JSON.stringify(metadata));
|
||||||
|
|
||||||
const mapFile = `${filename}.map`;
|
const mapFile = `${filename}.map`;
|
||||||
fs.writeFile(mapFile, JSON.stringify(map));
|
await fs.writeFile(mapFile, JSON.stringify(map));
|
||||||
|
|
||||||
// Execute off-line code tasks
|
// Execute off-line code tasks
|
||||||
|
|
||||||
|
@ -711,7 +711,7 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
code = ji.default(code, ' ');
|
code = ji.default(code, ' ');
|
||||||
|
|
||||||
fs.writeFile(jsfile, code);
|
await fs.writeFile(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}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,7 +723,7 @@ export class GBVMService extends GBService {
|
||||||
// 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.writeFile(tablesFile, JSON.stringify(task.tables));
|
await fs.writeFile(tablesFile, JSON.stringify(task.tables));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -414,7 +414,7 @@ export class SystemKeywords {
|
||||||
const buffer = pngPages[0].content;
|
const buffer = pngPages[0].content;
|
||||||
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
|
|
||||||
fs.writeFile(localName, buffer, { encoding: null });
|
await fs.writeFile(localName, buffer, { encoding: null });
|
||||||
|
|
||||||
return { localName: localName, url: url, data: buffer };
|
return { localName: localName, url: url, data: buffer };
|
||||||
}
|
}
|
||||||
|
@ -707,7 +707,7 @@ export class SystemKeywords {
|
||||||
// Writes it to disk and calculate hash.
|
// Writes it to disk and calculate hash.
|
||||||
|
|
||||||
const data = await response.arrayBuffer();
|
const data = await response.arrayBuffer();
|
||||||
fs.writeFile(localName, Buffer.from(data), { encoding: null });
|
await fs.writeFile(localName, Buffer.from(data), { encoding: null });
|
||||||
const hash = new Uint8Array(md5.array(data));
|
const hash = new Uint8Array(md5.array(data));
|
||||||
|
|
||||||
// Performs uploading passing local hash.
|
// Performs uploading passing local hash.
|
||||||
|
@ -1114,7 +1114,7 @@ export class SystemKeywords {
|
||||||
const localName = path.join('work', gbaiName, 'cache', `csv${GBAdminService.getRndReadableIdentifier()}.csv`);
|
const localName = path.join('work', gbaiName, 'cache', `csv${GBAdminService.getRndReadableIdentifier()}.csv`);
|
||||||
const url = file['@microsoft.graph.downloadUrl'];
|
const url = file['@microsoft.graph.downloadUrl'];
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
fs.writeFile(localName, Buffer.from(await response.arrayBuffer()), { encoding: null });
|
await fs.writeFile(localName, Buffer.from(await response.arrayBuffer()), { encoding: null });
|
||||||
|
|
||||||
var workbook = new Excel.Workbook();
|
var workbook = new Excel.Workbook();
|
||||||
let worksheet = await workbook.csv.readFile(localName);
|
let worksheet = await workbook.csv.readFile(localName);
|
||||||
|
@ -1490,7 +1490,7 @@ export class SystemKeywords {
|
||||||
user.userSystemId,
|
user.userSystemId,
|
||||||
'systemPrompt.txt'
|
'systemPrompt.txt'
|
||||||
);
|
);
|
||||||
fs.writeFile(systemPromptFile, text);
|
await fs.writeFile(systemPromptFile, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1981,7 +1981,7 @@ export class SystemKeywords {
|
||||||
const res = await fetch(url);
|
const res = await fetch(url);
|
||||||
let buf: any = Buffer.from(await res.arrayBuffer());
|
let buf: any = Buffer.from(await res.arrayBuffer());
|
||||||
localName = path.join('work', gbaiName, 'cache', `tmp${GBAdminService.getRndReadableIdentifier()}.docx`);
|
localName = path.join('work', gbaiName, 'cache', `tmp${GBAdminService.getRndReadableIdentifier()}.docx`);
|
||||||
fs.writeFile(localName, buf, { encoding: null });
|
await fs.writeFile(localName, buf, { encoding: null });
|
||||||
|
|
||||||
// Replace image path on all elements of data.
|
// Replace image path on all elements of data.
|
||||||
|
|
||||||
|
@ -2019,7 +2019,7 @@ export class SystemKeywords {
|
||||||
);
|
);
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
const buf = Buffer.from(await response.arrayBuffer());
|
const buf = Buffer.from(await response.arrayBuffer());
|
||||||
fs.writeFile(imageName, buf, { encoding: null });
|
await fs.writeFile(imageName, buf, { encoding: null });
|
||||||
|
|
||||||
const getNormalSize = ({ width, height, orientation }) => {
|
const getNormalSize = ({ width, height, orientation }) => {
|
||||||
return (orientation || 0) >= 5 ? [height, width] : [width, height];
|
return (orientation || 0) >= 5 ? [height, width] : [width, height];
|
||||||
|
@ -2068,7 +2068,7 @@ export class SystemKeywords {
|
||||||
doc.setData(data).render();
|
doc.setData(data).render();
|
||||||
|
|
||||||
buf = doc.getZip().generate({ type: 'nodebuffer', compression: 'DEFLATE' });
|
buf = doc.getZip().generate({ type: 'nodebuffer', compression: 'DEFLATE' });
|
||||||
fs.writeFile(localName, buf, { encoding: null });
|
await fs.writeFile(localName, buf, { encoding: null });
|
||||||
|
|
||||||
return { localName: localName, url: url, data: buf };
|
return { localName: localName, url: url, data: buf };
|
||||||
}
|
}
|
||||||
|
@ -2526,7 +2526,7 @@ export class SystemKeywords {
|
||||||
|
|
||||||
const buf = Buffer.from(data.Payment.QrCodeBase64Image, 'base64');
|
const buf = Buffer.from(data.Payment.QrCodeBase64Image, 'base64');
|
||||||
const localName = path.join('work', gbaiName, 'cache', `qr${GBAdminService.getRndReadableIdentifier()}.png`);
|
const localName = path.join('work', gbaiName, 'cache', `qr${GBAdminService.getRndReadableIdentifier()}.png`);
|
||||||
fs.writeFile(localName, buf, { encoding: null });
|
await fs.writeFile(localName, buf, { encoding: null });
|
||||||
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
|
|
||||||
GBLogEx.info(min, `GBPay: ${data.MerchantOrderId} OK: ${url}.`);
|
GBLogEx.info(min, `GBPay: ${data.MerchantOrderId} OK: ${url}.`);
|
||||||
|
@ -2752,7 +2752,7 @@ export class SystemKeywords {
|
||||||
|
|
||||||
// Criação de um arquivo temporário para enviar
|
// Criação de um arquivo temporário para enviar
|
||||||
const tempFilePath = path.resolve('temp_image.jpg');
|
const tempFilePath = path.resolve('temp_image.jpg');
|
||||||
fs.writeFile(tempFilePath, imageBuffer);
|
await fs.writeFile(tempFilePath, imageBuffer);
|
||||||
|
|
||||||
// Publicação da imagem
|
// Publicação da imagem
|
||||||
const page = new Page(pageId);
|
const page = new Page(pageId);
|
||||||
|
|
|
@ -100,6 +100,7 @@ export class GBConfigService {
|
||||||
case 'CLOUD_USERNAME':
|
case 'CLOUD_USERNAME':
|
||||||
value = undefined;
|
value = undefined;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'CLOUD_PASSWORD':
|
case 'CLOUD_PASSWORD':
|
||||||
value = undefined;
|
value = undefined;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -452,7 +452,7 @@ export class GBConversationalService {
|
||||||
const waveFilename = `work/tmp${name}.pcm`;
|
const waveFilename = `work/tmp${name}.pcm`;
|
||||||
|
|
||||||
let audio = await textToSpeech.repairWavHeaderStream(res.result as any);
|
let audio = await textToSpeech.repairWavHeaderStream(res.result as any);
|
||||||
fs.writeFile(waveFilename, audio);
|
await fs.writeFile(waveFilename, audio);
|
||||||
|
|
||||||
const oggFilenameOnly = `tmp${name}.ogg`;
|
const oggFilenameOnly = `tmp${name}.ogg`;
|
||||||
const oggFilename = `work/${oggFilenameOnly}`;
|
const oggFilename = `work/${oggFilenameOnly}`;
|
||||||
|
@ -482,7 +482,7 @@ export class GBConversationalService {
|
||||||
|
|
||||||
const dest = `work/tmp${name}.wav`;
|
const dest = `work/tmp${name}.wav`;
|
||||||
const src = `work/tmp${name}.ogg`;
|
const src = `work/tmp${name}.ogg`;
|
||||||
fs.writeFile(src, oggFile.read());
|
await fs.writeFile(src, oggFile.read());
|
||||||
|
|
||||||
const makeMp3 = shell([
|
const makeMp3 = shell([
|
||||||
'node_modules/ffmpeg-static/ffmpeg', // TODO: .exe on MSWin.
|
'node_modules/ffmpeg-static/ffmpeg', // TODO: .exe on MSWin.
|
||||||
|
|
|
@ -135,7 +135,7 @@ export class GBCoreService implements IGBCoreService {
|
||||||
} else if (this.dialect === 'sqlite') {
|
} else if (this.dialect === 'sqlite') {
|
||||||
storage = GBConfigService.get('STORAGE_FILE');
|
storage = GBConfigService.get('STORAGE_FILE');
|
||||||
|
|
||||||
if (!await GBUtil.exists(storage)) {
|
if (!(await GBUtil.exists(storage))) {
|
||||||
process.env.STORAGE_SYNC = 'true';
|
process.env.STORAGE_SYNC = 'true';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -313,7 +313,7 @@ STORAGE_SYNC_ALTER=true
|
||||||
ENDPOINT_UPDATE=true
|
ENDPOINT_UPDATE=true
|
||||||
`;
|
`;
|
||||||
|
|
||||||
fs.writeFile('.env', env);
|
await fs.writeFile('.env', env);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -323,7 +323,10 @@ ENDPOINT_UPDATE=true
|
||||||
*/
|
*/
|
||||||
public async ensureProxy(port): Promise<string> {
|
public async ensureProxy(port): Promise<string> {
|
||||||
try {
|
try {
|
||||||
if (await GBUtil.exists('node_modules/ngrok/bin/ngrok.exe') || await GBUtil.exists('node_modules/.bin/ngrok')) {
|
if (
|
||||||
|
(await GBUtil.exists('node_modules/ngrok/bin/ngrok.exe')) ||
|
||||||
|
(await GBUtil.exists('node_modules/.bin/ngrok'))
|
||||||
|
) {
|
||||||
return await ngrok.connect({ port: port });
|
return await ngrok.connect({ port: port });
|
||||||
} else {
|
} else {
|
||||||
GBLog.warn('ngrok executable not found. Check installation or node_modules folder.');
|
GBLog.warn('ngrok executable not found. Check installation or node_modules folder.');
|
||||||
|
@ -825,15 +828,15 @@ ENDPOINT_UPDATE=true
|
||||||
public async ensureFolders(instances, deployer: GBDeployer) {
|
public async ensureFolders(instances, deployer: GBDeployer) {
|
||||||
let libraryPath = GBConfigService.get('STORAGE_LIBRARY');
|
let libraryPath = GBConfigService.get('STORAGE_LIBRARY');
|
||||||
|
|
||||||
if (!await GBUtil.exists(libraryPath)) {
|
if (!(await GBUtil.exists(libraryPath))) {
|
||||||
mkdirp.sync(libraryPath);
|
mkdirp.sync(libraryPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
||||||
|
|
||||||
const files = 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') {
|
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);
|
||||||
|
@ -855,7 +858,7 @@ ENDPOINT_UPDATE=true
|
||||||
instance = await deployer.deployBlankBot(botId, mobile, email);
|
instance = await deployer.deployBlankBot(botId, mobile, email);
|
||||||
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');
|
const base = path.join(process.env.PWD, 'templates', 'default.gbai');
|
||||||
|
|
|
@ -152,9 +152,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
const isDirectory = async source => (await fs.lstat(source)).isDirectory();
|
const isDirectory = async source => (await fs.lstat(source)).isDirectory();
|
||||||
const getDirectories = async source =>
|
const getDirectories = async source =>
|
||||||
(await fs.readdir(source))
|
(await fs.readdir(source)).map(name => path.join(source, name)).filter(isDirectory);
|
||||||
.map(name => path.join(source, name))
|
|
||||||
.filter(isDirectory);
|
|
||||||
const dirs = await getDirectories(directory);
|
const dirs = await getDirectories(directory);
|
||||||
await CollectionUtil.asyncForEach(dirs, async element => {
|
await CollectionUtil.asyncForEach(dirs, async element => {
|
||||||
// For each folder, checks its extensions looking for valid packages.
|
// For each folder, checks its extensions looking for valid packages.
|
||||||
|
@ -472,7 +470,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
GBLogEx.info(min, `Processing ${rows.length} rows from ${filePath}...`);
|
GBLogEx.info(min, `Processing ${rows.length} rows from ${path.basename(filePath)}...`);
|
||||||
rows = null;
|
rows = null;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -497,13 +495,13 @@ export class GBDeployer implements IGBDeployer {
|
||||||
// Creates each subfolder.
|
// Creates each subfolder.
|
||||||
|
|
||||||
let pathBase = localPath;
|
let pathBase = localPath;
|
||||||
if (!await GBUtil.exists(pathBase)) {
|
if (!(await GBUtil.exists(pathBase))) {
|
||||||
fs.mkdir(pathBase);
|
fs.mkdir(pathBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(parts, async item => {
|
await CollectionUtil.asyncForEach(parts, async item => {
|
||||||
pathBase = packagePath.join(pathBase, item);
|
pathBase = packagePath.join(pathBase, item);
|
||||||
if (!await GBUtil.exists(pathBase)) {
|
if (!(await GBUtil.exists(pathBase))) {
|
||||||
fs.mkdir(pathBase);
|
fs.mkdir(pathBase);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -514,7 +512,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
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, `Download URL: ${url}`);
|
GBLogEx.info(min, `Downloading: ${url}`);
|
||||||
|
|
||||||
const res = await client.api(url).get();
|
const res = await client.api(url).get();
|
||||||
const documents = res.value;
|
const documents = res.value;
|
||||||
|
@ -529,7 +527,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
const itemPath = packagePath.join(localPath, remotePath, item.name);
|
const itemPath = packagePath.join(localPath, remotePath, item.name);
|
||||||
|
|
||||||
if (item.folder) {
|
if (item.folder) {
|
||||||
if (!await GBUtil.exists(itemPath)) {
|
if (!(await GBUtil.exists(itemPath))) {
|
||||||
fs.mkdir(itemPath);
|
fs.mkdir(itemPath);
|
||||||
}
|
}
|
||||||
const nextFolder = urlJoin(remotePath, item.name);
|
const nextFolder = urlJoin(remotePath, item.name);
|
||||||
|
@ -549,10 +547,10 @@ export class GBDeployer implements IGBDeployer {
|
||||||
const url = item['@microsoft.graph.downloadUrl'];
|
const url = item['@microsoft.graph.downloadUrl'];
|
||||||
|
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
fs.writeFile(itemPath, Buffer.from(await response.arrayBuffer()), { encoding: null });
|
await fs.writeFile(itemPath, Buffer.from(await response.arrayBuffer()), { encoding: null });
|
||||||
fs.utimes(itemPath, new Date(), new Date(item.lastModifiedDateTime));
|
fs.utimes(itemPath, new Date(), new Date(item.lastModifiedDateTime));
|
||||||
} else {
|
} else {
|
||||||
GBLogEx.info(min, `Local is up to date: ${itemPath}...`);
|
GBLogEx.info(min, `Local is up to date: ${path.basename(itemPath)}...`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -594,11 +592,27 @@ export class GBDeployer implements IGBDeployer {
|
||||||
/**
|
/**
|
||||||
* Deploys a folder into the bot storage.
|
* Deploys a folder into the bot storage.
|
||||||
*/
|
*/
|
||||||
public async deployPackage2(min: GBMinInstance, user, localPath: string) {
|
public async deployPackage2(min: GBMinInstance, user, packageWorkFolder: string, download = false) {
|
||||||
const packageType = path.extname(localPath);
|
const packageName = path.basename(packageWorkFolder);
|
||||||
|
const packageType = path.extname(packageWorkFolder);
|
||||||
let handled = false;
|
let handled = false;
|
||||||
let pck = null;
|
let pck = null;
|
||||||
|
|
||||||
|
const gbai = GBUtil.getGBAIPath(min.instance.botId);
|
||||||
|
|
||||||
|
if (download) {
|
||||||
|
if (packageType === 'gbkb') {
|
||||||
|
await this.cleanupPackage(min.instance, packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GBConfigService.get('STORAGE_NAME')) {
|
||||||
|
const filePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbai);
|
||||||
|
GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder);
|
||||||
|
} else {
|
||||||
|
await this.downloadFolder(min, path.join('work', `${gbai}`), packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Asks for each .gbapp if it will handle the package publishing.
|
// Asks for each .gbapp if it will handle the package publishing.
|
||||||
|
|
||||||
const _this = this;
|
const _this = this;
|
||||||
|
@ -608,7 +622,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(pck = await e.onExchangeData(min, 'handlePackage', {
|
(pck = await e.onExchangeData(min, 'handlePackage', {
|
||||||
name: localPath,
|
name: packageWorkFolder,
|
||||||
createPackage: async packageName => {
|
createPackage: async packageName => {
|
||||||
return await _this.deployPackageToStorage(min.instance.instanceId, packageName);
|
return await _this.deployPackageToStorage(min.instance.instanceId, packageName);
|
||||||
},
|
},
|
||||||
|
@ -634,7 +648,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
case '.gbot':
|
case '.gbot':
|
||||||
// Extracts configuration information from .gbot files.
|
// Extracts configuration information from .gbot files.
|
||||||
|
|
||||||
min.instance.params = await this.loadParamsFromTabular(min, localPath);
|
min.instance.params = await this.loadParamsFromTabular(min, packageWorkFolder);
|
||||||
if (min.instance.params) {
|
if (min.instance.params) {
|
||||||
let connections = [];
|
let connections = [];
|
||||||
|
|
||||||
|
@ -667,12 +681,11 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
const packagePath = GBUtil.getGBAIPath(min.botId, null);
|
const packagePath = GBUtil.getGBAIPath(min.botId, null);
|
||||||
const localFolder = path.join('work', packagePath, 'connections.json');
|
const localFolder = path.join('work', packagePath, 'connections.json');
|
||||||
fs.writeFile(localFolder, JSON.stringify(connections), { encoding: null });
|
await fs.writeFile(localFolder, JSON.stringify(connections), { encoding: null });
|
||||||
|
|
||||||
// Updates instance object.
|
// Updates instance object.
|
||||||
|
|
||||||
await this.core.saveInstance(min.instance);
|
await this.core.saveInstance(min.instance);
|
||||||
GBLogEx.info(min, `Reloading bot ${min.botId}...`);
|
|
||||||
GBServer.globals.minService.unmountBot(min.botId);
|
GBServer.globals.minService.unmountBot(min.botId);
|
||||||
GBServer.globals.minService.mountBot(min.instance);
|
GBServer.globals.minService.mountBot(min.instance);
|
||||||
GBLogEx.info(min, `Bot ${min.botId} reloaded.`);
|
GBLogEx.info(min, `Bot ${min.botId} reloaded.`);
|
||||||
|
@ -683,7 +696,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
// Deploys .gbkb into the storage.
|
// Deploys .gbkb into the storage.
|
||||||
|
|
||||||
const service = new KBService(this.core.sequelize);
|
const service = new KBService(this.core.sequelize);
|
||||||
await service.deployKb(this.core, this, localPath, min);
|
await service.deployKb(this.core, this, packageWorkFolder, min);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '.gbdialog':
|
case '.gbdialog':
|
||||||
|
@ -691,15 +704,14 @@ export class GBDeployer implements IGBDeployer {
|
||||||
// it to the VM.
|
// it to the VM.
|
||||||
|
|
||||||
const vm = new GBVMService();
|
const vm = new GBVMService();
|
||||||
await vm.loadDialogPackage(localPath, min, this.core, this);
|
await vm.loadDialogPackage(packageWorkFolder, min, this.core, this);
|
||||||
GBLogEx.verbose(min, `Dialogs (.gbdialog) for ${min.botId} loaded.`);
|
GBLogEx.verbose(min, `Dialogs (.gbdialog) for ${min.botId} loaded.`);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '.gbtheme':
|
case '.gbtheme':
|
||||||
// Updates server listeners to serve theme files in .gbtheme.
|
// Updates server listeners to serve theme files in .gbtheme.
|
||||||
|
|
||||||
const packageName = path.basename(localPath);
|
GBServer.globals.server.use(`/themes/${packageName}`, express.static(packageWorkFolder));
|
||||||
GBServer.globals.server.use(`/themes/${packageName}`, express.static(localPath));
|
|
||||||
GBLogEx.verbose(min, `Theme (.gbtheme) assets accessible at: /themes/${packageName}.`);
|
GBLogEx.verbose(min, `Theme (.gbtheme) assets accessible at: /themes/${packageName}.`);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -707,13 +719,13 @@ export class GBDeployer implements IGBDeployer {
|
||||||
case '.gbapp':
|
case '.gbapp':
|
||||||
// Dynamically compiles and loads .gbapp packages (Node.js packages).
|
// Dynamically compiles and loads .gbapp packages (Node.js packages).
|
||||||
|
|
||||||
await this.callGBAppCompiler(localPath, this.core);
|
await this.callGBAppCompiler(packageWorkFolder, this.core);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '.gblib':
|
case '.gblib':
|
||||||
// Dynamically compiles and loads .gblib packages (Node.js packages).
|
// Dynamically compiles and loads .gblib packages (Node.js packages).
|
||||||
|
|
||||||
await this.callGBAppCompiler(localPath, this.core);
|
await this.callGBAppCompiler(packageWorkFolder, this.core);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -736,7 +748,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
public async undeployPackageFromPackageName(instance: IGBInstance, packageName: string) {
|
public async undeployPackageFromPackageName(instance: IGBInstance, packageName: string) {
|
||||||
// Gets information about the package.
|
// Gets information about the package.
|
||||||
|
|
||||||
|
|
||||||
const p = await this.getStoragePackageByName(instance.instanceId, packageName);
|
const p = await this.getStoragePackageByName(instance.instanceId, packageName);
|
||||||
|
|
||||||
const packagePath = GBUtil.getGBAIPath(instance.botId, null, packageName);
|
const packagePath = GBUtil.getGBAIPath(instance.botId, null, packageName);
|
||||||
|
@ -881,7 +892,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
if (!(await GBUtil.exists(`${root}/build`)) && process.env.DISABLE_WEB !== 'true') {
|
if (!(await GBUtil.exists(`${root}/build`)) && process.env.DISABLE_WEB !== 'true') {
|
||||||
// Write a .env required to fix some bungs in create-react-app tool.
|
// Write a .env required to fix some bungs in create-react-app tool.
|
||||||
|
|
||||||
fs.writeFile(`${root}/.env`, 'SKIP_PREFLIGHT_CHECK=true');
|
await fs.writeFile(`${root}/.env`, 'SKIP_PREFLIGHT_CHECK=true');
|
||||||
|
|
||||||
// Install modules and compiles the web app.
|
// Install modules and compiles the web app.
|
||||||
|
|
||||||
|
@ -931,7 +942,6 @@ export class GBDeployer implements IGBDeployer {
|
||||||
);
|
);
|
||||||
GBServer.globals.server.use(`/${botId}/cache`, express.static(urlJoin('work', gbaiName, 'cache')));
|
GBServer.globals.server.use(`/${botId}/cache`, express.static(urlJoin('work', gbaiName, 'cache')));
|
||||||
|
|
||||||
|
|
||||||
// FEAT-A7B1F6
|
// FEAT-A7B1F6
|
||||||
|
|
||||||
GBServer.globals.server.use(
|
GBServer.globals.server.use(
|
||||||
|
@ -956,8 +966,8 @@ export class GBDeployer implements IGBDeployer {
|
||||||
GBLogEx.info(0, `Deploying General Bots Application (.gbapp) or Library (.gblib): ${path.basename(gbappPath)}...`);
|
GBLogEx.info(0, `Deploying General Bots Application (.gbapp) or Library (.gblib): ${path.basename(gbappPath)}...`);
|
||||||
let folder = path.join(gbappPath, 'node_modules');
|
let folder = path.join(gbappPath, 'node_modules');
|
||||||
if (process.env.GBAPP_DISABLE_COMPILE !== 'true') {
|
if (process.env.GBAPP_DISABLE_COMPILE !== 'true') {
|
||||||
if (!await GBUtil.exists(folder)) {
|
if (!(await GBUtil.exists(folder))) {
|
||||||
GBLogEx.info(0, `Installing modules for ${gbappPath}...`);
|
GBLogEx.info(0, `Installing modules for ${path.basename(gbappPath)}...`);
|
||||||
child_process.execSync('npm install', { cwd: gbappPath });
|
child_process.execSync('npm install', { cwd: gbappPath });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -967,7 +977,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
// Runs TSC in .gbapp folder.
|
// Runs TSC in .gbapp folder.
|
||||||
|
|
||||||
if (process.env.GBAPP_DISABLE_COMPILE !== 'true') {
|
if (process.env.GBAPP_DISABLE_COMPILE !== 'true') {
|
||||||
GBLogEx.info(0, `Compiling: ${gbappPath}.`);
|
GBLogEx.info(0, `Compiling: ${path.basename(gbappPath)}.`);
|
||||||
child_process.execSync(path.join(process.env.PWD, 'node_modules/.bin/tsc'), { cwd: gbappPath });
|
child_process.execSync(path.join(process.env.PWD, 'node_modules/.bin/tsc'), { cwd: gbappPath });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,10 @@
|
||||||
import { createRpcServer } from '@push-rpc/core';
|
import { createRpcServer } from '@push-rpc/core';
|
||||||
import AuthenticationContext from 'adal-node';
|
import AuthenticationContext from 'adal-node';
|
||||||
import arrayBufferToBuffer from 'arraybuffer-to-buffer';
|
import arrayBufferToBuffer from 'arraybuffer-to-buffer';
|
||||||
|
import { watch } from 'fs';
|
||||||
|
import debounce from 'lodash.debounce';
|
||||||
|
|
||||||
|
import chokidar from 'chokidar';
|
||||||
import {
|
import {
|
||||||
AutoSaveStateMiddleware,
|
AutoSaveStateMiddleware,
|
||||||
BotFrameworkAdapter,
|
BotFrameworkAdapter,
|
||||||
|
@ -45,7 +49,14 @@ import {
|
||||||
UserState
|
UserState
|
||||||
} from 'botbuilder';
|
} from 'botbuilder';
|
||||||
import { FacebookAdapter } from 'botbuilder-adapter-facebook';
|
import { FacebookAdapter } from 'botbuilder-adapter-facebook';
|
||||||
import { AttachmentPrompt, ConfirmPrompt, DialogSet, OAuthPrompt, TextPrompt, WaterfallDialog } from 'botbuilder-dialogs';
|
import {
|
||||||
|
AttachmentPrompt,
|
||||||
|
ConfirmPrompt,
|
||||||
|
DialogSet,
|
||||||
|
OAuthPrompt,
|
||||||
|
TextPrompt,
|
||||||
|
WaterfallDialog
|
||||||
|
} from 'botbuilder-dialogs';
|
||||||
import { MicrosoftAppCredentials } from 'botframework-connector';
|
import { MicrosoftAppCredentials } from 'botframework-connector';
|
||||||
import {
|
import {
|
||||||
GBDialogStep,
|
GBDialogStep,
|
||||||
|
@ -313,39 +324,48 @@ export class GBMinService {
|
||||||
let dir = `work/${gbai}/cache`;
|
let dir = `work/${gbai}/cache`;
|
||||||
const botId = gbai.replace(/\.[^/.]+$/, '');
|
const botId = gbai.replace(/\.[^/.]+$/, '');
|
||||||
|
|
||||||
if (!await GBUtil.exists(dir)) {
|
if (!(await GBUtil.exists(dir))) {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
dir = `work/${gbai}/profile`;
|
dir = `work/${gbai}/profile`;
|
||||||
if (!await GBUtil.exists(dir)) {
|
if (!(await GBUtil.exists(dir))) {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
dir = `work/${gbai}/uploads`;
|
dir = `work/${gbai}/uploads`;
|
||||||
if (!await GBUtil.exists(dir)) {
|
if (!(await GBUtil.exists(dir))) {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = `work/${gbai}/${botId}.gbkb`;
|
dir = `work/${gbai}/${botId}.gbkb`;
|
||||||
if (!await GBUtil.exists(dir)) {
|
if (!(await GBUtil.exists(dir))) {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
|
await this.watchPackages(min, 'gbkb');
|
||||||
|
|
||||||
dir = `work/${gbai}/${botId}.gbkb/docs-vectorized`;
|
dir = `work/${gbai}/${botId}.gbkb/docs-vectorized`;
|
||||||
if (!await GBUtil.exists(dir)) {
|
if (!(await GBUtil.exists(dir))) {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = `work/${gbai}/${botId}.gbdialog`;
|
dir = `work/${gbai}/${botId}.gbdialog`;
|
||||||
if (!await GBUtil.exists(dir)) {
|
if (!(await GBUtil.exists(dir))) {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
|
await this.watchPackages(min, 'gbdialog');
|
||||||
|
|
||||||
dir = `work/${gbai}/${botId}.gbot`;
|
dir = `work/${gbai}/${botId}.gbot`;
|
||||||
if (!await GBUtil.exists(dir)) {
|
if (!(await GBUtil.exists(dir))) {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
|
await this.watchPackages(min, 'gbot');
|
||||||
|
|
||||||
dir = `work/${gbai}/${botId}.gbui`;
|
dir = `work/${gbai}/${botId}.gbui`;
|
||||||
if (!await GBUtil.exists(dir)) {
|
if (!(await GBUtil.exists(dir))) {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = `work/${gbai}/users`;
|
dir = `work/${gbai}/users`;
|
||||||
if (!await GBUtil.exists(dir)) {
|
if (!(await GBUtil.exists(dir))) {
|
||||||
mkdirp.sync(dir);
|
mkdirp.sync(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,10 +407,9 @@ export class GBMinService {
|
||||||
|
|
||||||
const manifest = `${instance.botId}-Teams.zip`;
|
const manifest = `${instance.botId}-Teams.zip`;
|
||||||
const packageTeams = urlJoin(`work`, GBUtil.getGBAIPath(instance.botId), manifest);
|
const packageTeams = urlJoin(`work`, GBUtil.getGBAIPath(instance.botId), manifest);
|
||||||
if (!await GBUtil.exists(packageTeams)) {
|
if (!(await GBUtil.exists(packageTeams))) {
|
||||||
GBLogEx.info(min, 'Generating MS Teams manifest....');
|
|
||||||
const data = await this.deployer.getBotManifest(instance);
|
const data = await this.deployer.getBotManifest(instance);
|
||||||
fs.writeFile(packageTeams, data);
|
await fs.writeFile(packageTeams, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serves individual URL for each bot user interface.
|
// Serves individual URL for each bot user interface.
|
||||||
|
@ -1098,7 +1117,7 @@ export class GBMinService {
|
||||||
const folder = `work/${path}/cache`;
|
const folder = `work/${path}/cache`;
|
||||||
const filename = `${GBAdminService.generateUuid()}.png`;
|
const filename = `${GBAdminService.generateUuid()}.png`;
|
||||||
|
|
||||||
fs.writeFile(urlJoin(folder, filename), data);
|
await fs.writeFile(urlJoin(folder, filename), data);
|
||||||
step.context.activity.text = urlJoin(
|
step.context.activity.text = urlJoin(
|
||||||
GBServer.globals.publicAddress,
|
GBServer.globals.publicAddress,
|
||||||
`${min.instance.botId}`,
|
`${min.instance.botId}`,
|
||||||
|
@ -1286,7 +1305,7 @@ export class GBMinService {
|
||||||
buffer = arrayBufferToBuffer(await res.arrayBuffer());
|
buffer = arrayBufferToBuffer(await res.arrayBuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFile(localFileName, buffer);
|
await fs.writeFile(localFileName, buffer);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fileName: attachment.name,
|
fileName: attachment.name,
|
||||||
|
@ -1723,4 +1742,65 @@ export class GBMinService {
|
||||||
|
|
||||||
createRpcServer(proxies, GBServer.globals.server.apiServer, opts);
|
createRpcServer(proxies, GBServer.globals.server.apiServer, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Map to track recent changes with timestamps
|
||||||
|
private recentChanges: Map<string, number> = new Map();
|
||||||
|
|
||||||
|
private async watchPackages(min: GBMinInstance, packageType) {
|
||||||
|
if (!GBConfigService.get('STORAGE_NAME')) {
|
||||||
|
const packagePath = GBUtil.getGBAIPath(min.botId, packageType);
|
||||||
|
const dirPath = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath);
|
||||||
|
|
||||||
|
const watcher = chokidar.watch(dirPath, {
|
||||||
|
persistent: true,
|
||||||
|
ignoreInitial: true, // Ignore initial add events
|
||||||
|
depth: 99, // Watch subdirectories
|
||||||
|
awaitWriteFinish: {
|
||||||
|
stabilityThreshold: 500, // Wait for 500ms to ensure file is written completely
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const WRITE_INTERVAL = 5000; // 5 seconds interval
|
||||||
|
|
||||||
|
// Function to handle file changes and prevent multiple calls within the 5-second window
|
||||||
|
const handleFileChange = async (filePath) => {
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
// Add or update the file in the recent changes list
|
||||||
|
this.recentChanges.set(filePath, now);
|
||||||
|
|
||||||
|
// Clean up entries older than 5 seconds
|
||||||
|
for (const [key, timestamp] of this.recentChanges.entries()) {
|
||||||
|
if (now - timestamp > WRITE_INTERVAL) {
|
||||||
|
this.recentChanges.delete(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have recent changes, deploy the package only once
|
||||||
|
if (this.recentChanges.size > 0) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
await this.deployer.deployPackage2(min, null, dirPath);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
GBLogEx.error(min, `Error deploying package: ${GBUtil.toYAML(error)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay further processing to prevent multiple deployments within 5 seconds
|
||||||
|
await new Promise(resolve => setTimeout(resolve, WRITE_INTERVAL));
|
||||||
|
|
||||||
|
// After the delay, clear only entries that were processed
|
||||||
|
this.recentChanges.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Watch for file changes
|
||||||
|
watcher.on('change', (filePath) => {
|
||||||
|
handleFileChange(filePath).catch(error => console.error('Error processing file change:', error));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ export class GBSSR {
|
||||||
const file = await fs.readFile(preferences, 'utf8');
|
const file = await fs.readFile(preferences, 'utf8');
|
||||||
const data = JSON.parse(file);
|
const data = JSON.parse(file);
|
||||||
data['profile']['exit_type'] = 'none';
|
data['profile']['exit_type'] = 'none';
|
||||||
fs.writeFile(preferences, JSON.stringify(data));
|
await fs.writeFile(preferences, JSON.stringify(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -441,9 +441,15 @@ export class KBService implements IGBKBService {
|
||||||
min: GBMinInstance,
|
min: GBMinInstance,
|
||||||
packageId: number
|
packageId: number
|
||||||
): Promise<GuaribasQuestion[]> {
|
): Promise<GuaribasQuestion[]> {
|
||||||
GBLogEx.info(min, `Now reading file ${filePath}...`);
|
GBLogEx.info(min, `Now reading file ${path.basename(filePath)}...`);
|
||||||
const workbook = new Excel.Workbook();
|
const workbook = new Excel.Workbook();
|
||||||
const data = await workbook.xlsx.readFile(filePath);
|
|
||||||
|
let data;
|
||||||
|
if (filePath.endsWith('.xlsx')) {
|
||||||
|
data = await workbook.xlsx.readFile(filePath);
|
||||||
|
} else if (filePath.endsWith('.csv')) {
|
||||||
|
data = await workbook.csv.readFile(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
let lastQuestionId: number;
|
let lastQuestionId: number;
|
||||||
let lastAnswer: GuaribasAnswer;
|
let lastAnswer: GuaribasAnswer;
|
||||||
|
@ -451,13 +457,15 @@ export class KBService implements IGBKBService {
|
||||||
// Finds a valid worksheet because Excel returns empty slots
|
// Finds a valid worksheet because Excel returns empty slots
|
||||||
// when loading worksheets collection.
|
// when loading worksheets collection.
|
||||||
|
|
||||||
let worksheet: any;
|
let worksheet = data;
|
||||||
|
if (!worksheet) {
|
||||||
for (let t = 0; t < data.worksheets.length; t++) {
|
for (let t = 0; t < data.worksheets.length; t++) {
|
||||||
worksheet = data.worksheets[t];
|
worksheet = data.worksheets[t];
|
||||||
if (worksheet) {
|
if (worksheet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const rows = worksheet._rows;
|
const rows = worksheet._rows;
|
||||||
const answers = [];
|
const answers = [];
|
||||||
|
@ -778,7 +786,7 @@ export class KBService implements IGBKBService {
|
||||||
path.basename(localName)
|
path.basename(localName)
|
||||||
);
|
);
|
||||||
const buffer = await image.read();
|
const buffer = await image.read();
|
||||||
fs.writeFile(localName, buffer, { encoding: null });
|
await fs.writeFile(localName, buffer, { encoding: null });
|
||||||
return { src: url };
|
return { src: url };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1098,15 +1106,12 @@ export class KBService implements IGBKBService {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
GBLogEx.info(min, `Ignore processing of ${file}. ${GBUtil.toYAML(error)}`);
|
GBLogEx.info(min, `Ignore processing of ${file}. ${GBUtil.toYAML(error)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
files = await walkPromise(urlJoin(localPath, 'docs'));
|
files = await walkPromise(urlJoin(localPath, 'docs'));
|
||||||
|
|
||||||
if (!files[0]) {
|
if (files[0]) {
|
||||||
GBLogEx.info(min, `[GBDeployer] docs folder not created yet in .gbkb neither a website in .gbot.`);
|
|
||||||
} else {
|
|
||||||
await CollectionUtil.asyncForEach(files, async file => {
|
await CollectionUtil.asyncForEach(files, async file => {
|
||||||
let content = null;
|
let content = null;
|
||||||
let filePath = path.join(file.root, file.name);
|
let filePath = path.join(file.root, file.name);
|
||||||
|
@ -1181,7 +1186,7 @@ export class KBService implements IGBKBService {
|
||||||
const files = await walkPromise(localPath);
|
const files = await walkPromise(localPath);
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(files, async file => {
|
await CollectionUtil.asyncForEach(files, async file => {
|
||||||
if (file !== null && file.name.endsWith('.xlsx')) {
|
if (file !== null && (file.name.endsWith('.xlsx') || file.name.endsWith('.csv'))) {
|
||||||
return await this.importKbTabularFile(urlJoin(file.root, file.name), min, packageId);
|
return await this.importKbTabularFile(urlJoin(file.root, file.name), min, packageId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1340,7 +1345,7 @@ export class KBService implements IGBKBService {
|
||||||
public async deployKb(core: IGBCoreService, deployer: GBDeployer, localPath: string, min: GBMinInstance) {
|
public async deployKb(core: IGBCoreService, deployer: GBDeployer, localPath: string, min: GBMinInstance) {
|
||||||
const packageName = path.basename(localPath);
|
const packageName = path.basename(localPath);
|
||||||
const instance = await core.loadInstanceByBotId(min.botId);
|
const instance = await core.loadInstanceByBotId(min.botId);
|
||||||
GBLogEx.info(min, `[GBDeployer] Importing: ${localPath}`);
|
GBLogEx.info(min, `Publishing: ${path.basename(localPath)}`);
|
||||||
|
|
||||||
const p = await deployer.deployPackageToStorage(instance.instanceId, packageName);
|
const p = await deployer.deployPackageToStorage(instance.instanceId, packageName);
|
||||||
await this.importKbPackage(min, localPath, p, instance);
|
await this.importKbPackage(min, localPath, p, instance);
|
||||||
|
@ -1354,14 +1359,18 @@ export class KBService implements IGBKBService {
|
||||||
min['groupCache'] = await KBService.getGroupReplies(instance.instanceId);
|
min['groupCache'] = await KBService.getGroupReplies(instance.instanceId);
|
||||||
await KBService.RefreshNER(min);
|
await KBService.RefreshNER(min);
|
||||||
|
|
||||||
GBLogEx.info(min, `[GBDeployer] Start Bot Server Side Rendering... ${localPath}`);
|
const ssr = min.core.getParam<boolean>(min.instance, 'SSR', false);
|
||||||
|
|
||||||
|
if (ssr) {
|
||||||
|
GBLogEx.info(min, `Start Bot Server Side Rendering... ${localPath}`);
|
||||||
const html = await GBSSR.getHTML(min);
|
const html = await GBSSR.getHTML(min);
|
||||||
let packagePath = GBUtil.getGBAIPath(min.botId, `gbui`);
|
let packagePath = GBUtil.getGBAIPath(min.botId, `gbui`);
|
||||||
packagePath = path.join(process.env.PWD, 'work', packagePath, 'index.html');
|
packagePath = path.join(process.env.PWD, 'work', packagePath, 'index.html');
|
||||||
GBLogEx.info(min, `[GBDeployer] Saving SSR HTML in ${packagePath}.`);
|
GBLogEx.info(min, `Saving SSR HTML in ${packagePath}.`);
|
||||||
fs.writeFile(packagePath, html, 'utf8');
|
await fs.writeFile(packagePath, html, 'utf8');
|
||||||
|
}
|
||||||
|
|
||||||
GBLogEx.info(min, `[GBDeployer] Finished import of ${localPath}`);
|
GBLogEx.info(min, `Done publishing of: ${localPath}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async playAudio(
|
private async playAudio(
|
||||||
|
@ -1434,7 +1443,6 @@ export class KBService implements IGBKBService {
|
||||||
directoryPath: string
|
directoryPath: string
|
||||||
): Promise<string | null> {
|
): Promise<string | null> {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Check if the directory exists, create it if not.
|
// Check if the directory exists, create it if not.
|
||||||
|
|
||||||
const directoryExists = await GBUtil.exists(directoryPath);
|
const directoryExists = await GBUtil.exists(directoryPath);
|
||||||
|
|
|
@ -188,7 +188,7 @@ export class ChatServices {
|
||||||
const gbaiName = GBUtil.getGBAIPath(min.botId, null);
|
const gbaiName = GBUtil.getGBAIPath(min.botId, null);
|
||||||
const localName = path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.png`);
|
const localName = path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.png`);
|
||||||
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
fs.writeFile(localName, buffer, { encoding: null });
|
await fs.writeFile(localName, buffer, { encoding: null });
|
||||||
return { localName: localName, url: url, data: buffer };
|
return { localName: localName, url: url, data: buffer };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ export class ImageServices {
|
||||||
const url = response.data[0].url;
|
const url = response.data[0].url;
|
||||||
const res = await fetch(url);
|
const res = await fetch(url);
|
||||||
let buf: any = Buffer.from(await res.arrayBuffer());
|
let buf: any = Buffer.from(await res.arrayBuffer());
|
||||||
fs.writeFile(localName, buf, { encoding: null });
|
await fs.writeFile(localName, buf, { encoding: null });
|
||||||
|
|
||||||
GBLogEx.info(min, `DALL-E image generated at ${url}.`);
|
GBLogEx.info(min, `DALL-E image generated at ${url}.`);
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ export class WhatsappDirectLine extends GBService {
|
||||||
'cache',
|
'cache',
|
||||||
`qr${GBAdminService.getRndReadableIdentifier()}.png`
|
`qr${GBAdminService.getRndReadableIdentifier()}.png`
|
||||||
);
|
);
|
||||||
fs.writeFile(localName, qrBuf.data);
|
await fs.writeFile(localName, qrBuf.data);
|
||||||
const url = urlJoin(GBServer.globals.publicAddress, this.min.botId, 'cache', path.basename(localName));
|
const url = urlJoin(GBServer.globals.publicAddress, this.min.botId, 'cache', path.basename(localName));
|
||||||
|
|
||||||
if (adminNumber) {
|
if (adminNumber) {
|
||||||
|
@ -331,7 +331,7 @@ export class WhatsappDirectLine extends GBService {
|
||||||
'cache',
|
'cache',
|
||||||
`tmp${GBAdminService.getRndReadableIdentifier()}.docx`
|
`tmp${GBAdminService.getRndReadableIdentifier()}.docx`
|
||||||
);
|
);
|
||||||
fs.writeFile(localName, buf, { encoding: null });
|
await fs.writeFile(localName, buf, { encoding: null });
|
||||||
const url = urlJoin(GBServer.globals.publicAddress, this.min.botId, 'cache', path.basename(localName));
|
const url = urlJoin(GBServer.globals.publicAddress, this.min.botId, 'cache', path.basename(localName));
|
||||||
|
|
||||||
attachments = [];
|
attachments = [];
|
||||||
|
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
@ -39,6 +39,7 @@ NLP Score,
|
||||||
Notes,
|
Notes,
|
||||||
Open AI Key,
|
Open AI Key,
|
||||||
Search Score,
|
Search Score,
|
||||||
|
SSR,
|
||||||
Start Dialog,
|
Start Dialog,
|
||||||
Store Answer Score,
|
Store Answer Score,
|
||||||
Synchronize Database,
|
Synchronize Database,
|
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 958 B After Width: | Height: | Size: 958 B |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 247 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |