new(basic.gblib): PUT keyword.

This commit is contained in:
Rodrigo Rodriguez 2022-08-05 00:10:23 -03:00
parent 29b1975dab
commit d3769e5bf3
5 changed files with 101 additions and 40 deletions

View file

@ -52,11 +52,10 @@ export class HearDialog {
private static async downloadAttachmentAndWrite(attachment) {
// Retrieve the attachment via the attachment's contentUrl.
const url = attachment.contentUrl;
// Local file path for the bot to save the attachment.
const localFileName = Path.join(__dirname, attachment.name);
const localFolder = Path.join('work', 'dev-rodriguez.gbai', 'uploads');
const localFileName = Path.join(localFolder, attachment.name);
try {
// arraybuffer is necessary for images
@ -135,17 +134,17 @@ export class HearDialog {
if (step.activeDialog.state.options['kind'] === "file") {
// Prepare Promises to download each attachment and then execute each Promise.
const promises = step.context.activity.attachments.map(HearDialog.downloadAttachmentAndWrite);
const promises = step.context.activity.attachments.map(
HearDialog.downloadAttachmentAndWrite);
const successfulSaves = await Promise.all(promises);
async function replyForReceivedAttachments(localAttachmentData) {
if (localAttachmentData) {
// Because the TurnContext was bound to this function, the bot can call
// `TurnContext.sendActivity` via `this.sendActivity`;
await this.sendActivity(`Attachment "${localAttachmentData.fileName}" ` +
`has been received and saved to "${localAttachmentData.localPath}".`);
await this.sendActivity(`Upload OK.`);
} else {
await this.sendActivity('Attachment was not successfully saved to disk.');
await this.sendActivity('Error uploading file. Please, start again.');
}
}
@ -153,6 +152,11 @@ export class HearDialog {
// The current TurnContext is bound so `replyForReceivedAttachments` can also send replies.
const replyPromises = successfulSaves.map(replyForReceivedAttachments.bind(step.context));
await Promise.all(replyPromises);
result = {
data: fs.readFileSync(successfulSaves[0].localPath),
filename: successfulSaves[0].fileName
};
}
else if (step.activeDialog.state.options['kind'] === "boolean") {

View file

@ -407,8 +407,16 @@ export class DialogKeywords {
}
public getCoded(text){
return Buffer.from(text).toString("base64");
public getCoded(value){
// Checks if it is a GB FILE object.
if (value.data && value.filename)
{
value = value.data;
}
return Buffer.from(value).toString("base64");
}
/**

View file

@ -79,7 +79,7 @@ export class GBVMService extends GBService {
const vbsFile = filename.substr(0, filename.indexOf('docx')) + 'vbs';
const fullVbsFile = urlJoin(folder, vbsFile);
const docxStat = fs.statSync(urlJoin(folder, wordFile));
const interval = 30000; // If compiled is older 30 seconds, then recompile.
const interval = 3000; // If compiled is older 30 seconds, then recompile.
let writeVBS = true;
if (fs.existsSync(fullVbsFile)) {
const vbsStat = fs.statSync(fullVbsFile);
@ -324,9 +324,7 @@ export class GBVMService extends GBService {
});
code = code.replace(/(\w+)\s*\=\s*get\s(.*)/gi, ($0, $1, $2, $3) => {
if ($2.indexOf('http') !== -1) {
return `${$1} = sys().getByHttp (${$2}, headers, httpUsername, httpPs)`;
} else {
const count = ($2.match(/\,/g) || []).length;
const values = $2.split(',');
@ -348,11 +346,20 @@ export class GBVMService extends GBService {
else {
return `${$1} = sys().get (${$2})`;
return `${$1} = sys().get (${$2}, headers)`;
}
}
});
code = code.replace(/\= NEW OBJECT/gi, ($0, $1, $2, $3) => {
return ` = {}`;
});
code = code.replace(/\= NEW ARRAY/gi, ($0, $1, $2, $3) => {
return ` = []`;
});
code = code.replace(/(go to)(\s)(.*)/gi, ($0, $1, $2, $3) => {
return `gotoDialog(step, ${$3})\n`;
});
@ -401,6 +408,10 @@ export class GBVMService extends GBService {
return `${$1} = sys().postByHttp (${$2}, ${$3}, headers)`;
});
code = code.replace(/(\w+)\s*\=\s*put\s*(.*),\s*(.*)/gi, ($0, $1, $2, $3) => {
return `${$1} = sys().putByHttp (${$2}, ${$3}, headers)`;
});
code = code.replace(/(\w+)\s*\=\s*download\s*(.*),\s*(.*)/gi, ($0, $1, $2, $3) => {
return `${$1} = sys().download (${$2}, ${$3})`;
});

View file

@ -196,12 +196,12 @@ export class SystemKeywords {
let isObject = false;
if (Array.isArray(data)) {
isObject = Object.keys(data[0]) !== null;
isObject = Object.keys(data[1]) !== null;
}
if (isObject || JSON.parse(data) !== null) {
let keys = Object.keys(data[0]);
let keys = Object.keys(data[1]);
if (headers) {
@ -286,7 +286,7 @@ export class SystemKeywords {
// Guess fields from data variable into Tabulator fields collection.
let fields = [];
let keys = Object.keys(data[1]);
let keys = Object.keys(data[0]);
for (let i = 0; i < keys.length; i++) {
fields.push({ field: keys[i], title: keys[i] });
}
@ -526,6 +526,12 @@ export class SystemKeywords {
const botId = this.min.instance.botId;
const path = `/${botId}.gbai/${botId}.gbdata`;
// Checks if it is a GB FILE object.
if (data.data && data.filename) {
data = data.data;
}
try {
await client
.api(`${baseUrl}/drive/root:/${path}/${file}:/content`)
@ -587,27 +593,34 @@ export class SystemKeywords {
* @example value = GET "file.xlsx", "A2"
*
*/
public async get(file: string, address: string): Promise<any> {
GBLog.info(`BASIC: GET '${address}' in '${file}'.`);
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
const botId = this.min.instance.botId;
const path = `/${botId}.gbai/${botId}.gbdata`;
public async get(file: string, addressOrHeaders: string, httpUsername, httpPs, qs, streaming): Promise<any> {
let document = await this.internalGetDocument(client, baseUrl, path, file);
if (file.startsWith('http')) {
// Creates workbook session that will be discarded.
return await this.getByHttp(file, addressOrHeaders, httpUsername, httpPs, qs, streaming);
}
else {
GBLog.info(`BASIC: GET '${addressOrHeaders}' in '${file}'.`);
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
const botId = this.min.instance.botId;
const path = `/${botId}.gbai/${botId}.gbdata`;
let sheets = await client
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`)
.get();
let document = await this.internalGetDocument(client, baseUrl, path, file);
let results = await client
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${address}')`)
.get();
// Creates workbook session that will be discarded.
let val = results.text[0][0];
GBLog.info(`BASIC: Getting '${file}' (GET). Value= ${val}.`);
return val;
let sheets = await client
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`)
.get();
let results = await client
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${addressOrHeaders}')`)
.get();
let val = results.text[0][0];
GBLog.info(`BASIC: Getting '${file}' (GET). Value= ${val}.`);
return val;
}
}
public isValidDate(dt) {
@ -1356,11 +1369,10 @@ export class SystemKeywords {
*
*/
public async getByHttp(url: string, headers: any, username: string, ps: string, qs: any, streaming = false) {
let options = {
encoding: "binary",
url: url,
headers: headers
};
let options = { url: url };
if (headers) {
options['headers'] = headers;
}
if (username) {
options['auth'] = {
user: username,
@ -1387,6 +1399,28 @@ export class SystemKeywords {
}
}
/**
* Calls any REST API by using POST HTTP method.
*
* @example
*
* user = post "http://server/path", "data"
* talk "The updated user area is" + user.area
*
*/
public async putByHttp(url: string, data, headers) {
const options = {
uri: url,
json: true,
body: data,
headers: headers
};
let result = await request.put(options);
GBLog.info(`[PUT]: ${url} (${data}): ${result}`);
return typeof (result) === 'object' ? result : JSON.parse(result);
}
/**
* Calls any REST API by using POST HTTP method.
*

View file

@ -255,6 +255,10 @@ export class GBMinService {
if (!fs.existsSync(dir)) {
mkdirp.sync(dir);
}
dir = `work/${min.botId}.gbai/uploads`;
if (!fs.existsSync(dir)) {
mkdirp.sync(dir);
}
// Loads Named Entity data for this bot.