2018-04-21 02:59:30 -03:00
|
|
|
/*****************************************************************************\
|
|
|
|
| ( )_ _ |
|
|
|
|
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
2020-07-01 15:00:40 -03:00
|
|
|
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' v `\ /'_`\ |
|
2019-03-09 16:59:31 -03:00
|
|
|
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| (˅) |( (_) ) |
|
2018-04-21 02:59:30 -03:00
|
|
|
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
|
|
|
| | | ( )_) | |
|
|
|
|
| (_) \___/' |
|
|
|
|
| |
|
|
|
|
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
|
|
|
|
| Licensed under the AGPL-3.0. |
|
2018-11-11 19:09:18 -02:00
|
|
|
| |
|
2018-04-21 02:59:30 -03:00
|
|
|
| According to our dual licensing model, this program can be used either |
|
|
|
|
| under the terms of the GNU Affero General Public License, version 3, |
|
|
|
|
| or under a proprietary license. |
|
|
|
|
| |
|
|
|
|
| The texts of the GNU Affero General Public License with an additional |
|
|
|
|
| permission and of our proprietary license can be found at and |
|
|
|
|
| in the LICENSE file you have received along with this program. |
|
|
|
|
| |
|
|
|
|
| This program is distributed in the hope that it will be useful, |
|
2018-09-11 19:40:53 -03:00
|
|
|
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
|
2018-04-21 02:59:30 -03:00
|
|
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
|
| GNU Affero General Public License for more details. |
|
|
|
|
| |
|
|
|
|
| "General Bots" is a registered trademark of Pragmatismo.io. |
|
|
|
|
| The licensing of the program under the AGPLv3 does not imply a |
|
|
|
|
| trademark license. Therefore any rights, title and interest in |
|
|
|
|
| our trademarks remain entirely with us. |
|
|
|
|
| |
|
|
|
|
\*****************************************************************************/
|
|
|
|
|
2018-11-12 12:20:44 -02:00
|
|
|
'use strict';
|
2018-04-21 02:59:30 -03:00
|
|
|
|
2020-05-11 10:41:41 -03:00
|
|
|
import { TurnContext, BotAdapter } from 'botbuilder';
|
|
|
|
import { WaterfallStepContext, WaterfallDialog } from 'botbuilder-dialogs';
|
2019-03-08 19:13:00 -03:00
|
|
|
import { GBLog, GBMinInstance } from 'botlib';
|
2019-03-08 06:37:13 -03:00
|
|
|
import * as request from 'request-promise-native';
|
2019-03-09 16:59:31 -03:00
|
|
|
import urlJoin = require('url-join');
|
2019-02-23 13:17:21 -03:00
|
|
|
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
2019-02-25 08:36:43 -03:00
|
|
|
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
|
2019-03-08 06:37:13 -03:00
|
|
|
import { GBDeployer } from './GBDeployer';
|
2020-12-13 10:02:49 -03:00
|
|
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
2020-08-15 11:39:43 -03:00
|
|
|
import { Messages } from '../strings';
|
2020-05-15 14:07:30 -03:00
|
|
|
import { GBServer } from '../../../src/app';
|
2020-12-01 18:01:53 -03:00
|
|
|
import { SecService } from '../../security.gbapp/services/SecService';
|
2020-05-11 10:41:41 -03:00
|
|
|
const request = require('request-promise-native');
|
2020-12-13 10:02:49 -03:00
|
|
|
const MicrosoftGraph = require('@microsoft/microsoft-graph-client');
|
2019-02-25 08:36:43 -03:00
|
|
|
|
2019-03-09 16:59:31 -03:00
|
|
|
/**
|
|
|
|
* @fileoverview General Bots server core.
|
|
|
|
*/
|
|
|
|
|
2019-02-25 08:36:43 -03:00
|
|
|
/**
|
|
|
|
* BASIC system class for extra manipulation of bot behaviour.
|
|
|
|
*/
|
2019-02-19 15:30:07 -03:00
|
|
|
class SysClass {
|
|
|
|
public min: GBMinInstance;
|
2019-03-08 06:37:13 -03:00
|
|
|
private readonly deployer: GBDeployer;
|
2019-02-19 15:30:07 -03:00
|
|
|
|
2019-03-08 06:37:13 -03:00
|
|
|
constructor(min: GBMinInstance, deployer: GBDeployer) {
|
2019-02-19 15:30:07 -03:00
|
|
|
this.min = min;
|
2019-03-08 06:37:13 -03:00
|
|
|
this.deployer = deployer;
|
2019-02-19 15:30:07 -03:00
|
|
|
}
|
|
|
|
|
2020-05-11 10:41:41 -03:00
|
|
|
public async getFileContents(url) {
|
|
|
|
const options = {
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
encoding: 'binary'
|
|
|
|
};
|
|
|
|
|
|
|
|
const res = await request(options);
|
2020-08-19 13:00:21 -03:00
|
|
|
return Buffer.from(res, 'binary').toString();
|
2020-12-13 10:02:49 -03:00
|
|
|
|
2020-05-11 10:41:41 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
public async getRandomId() {
|
|
|
|
return GBAdminService.getRndReadableIdentifier().substr(5);
|
|
|
|
}
|
|
|
|
|
|
|
|
public async getStock(symbol) {
|
|
|
|
var options = {
|
|
|
|
uri: `http://live-nse.herokuapp.com/?symbol=${symbol}`
|
|
|
|
};
|
|
|
|
|
|
|
|
let data = await request.get(options);
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2020-12-01 18:01:53 -03:00
|
|
|
public async gotoDialog(from: string, dialogName: string) {
|
|
|
|
let sec = new SecService();
|
|
|
|
let user = await sec.getUserFromSystemId(from);
|
|
|
|
if (!user) {
|
|
|
|
user = await sec.ensureUser(this.min.instance.instanceId, from, from, null, 'whatsapp', 'from');
|
|
|
|
}
|
|
|
|
await sec.updateUserHearOnDialog(user.userId, dialogName);
|
|
|
|
}
|
|
|
|
|
2019-02-25 08:36:43 -03:00
|
|
|
public async wait(seconds: number) {
|
2019-03-08 06:37:13 -03:00
|
|
|
// tslint:disable-next-line no-string-based-set-timeout
|
2020-11-08 13:39:18 -03:00
|
|
|
GBLog.info(`BASIC: Talking to a specific user (TALK TO).`);
|
2019-03-08 06:37:13 -03:00
|
|
|
const timeout = async (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
2019-02-25 08:36:43 -03:00
|
|
|
await timeout(seconds * 1000);
|
|
|
|
}
|
|
|
|
|
2020-11-08 13:39:18 -03:00
|
|
|
public async talkTo(mobile: any, message: string) {
|
|
|
|
GBLog.info(`BASIC: Talking '${message}' to a specific user (${mobile}) (TALK TO). `);
|
|
|
|
await this.min.conversationalService.sendMarkdownToMobile(this.min, null, mobile, message);
|
|
|
|
}
|
|
|
|
|
2020-11-26 12:45:10 -03:00
|
|
|
public async sendSmsTo(mobile, message) {
|
|
|
|
await this.min.conversationalService.sendSms(this.min, mobile, message);
|
|
|
|
}
|
|
|
|
|
2020-10-14 13:43:58 -03:00
|
|
|
public async set(file: string, address: string, value: any): Promise<any> {
|
2020-11-08 13:39:18 -03:00
|
|
|
GBLog.info(`BASIC: Defining '${address}' in '${file}' to '${value}' (SET). `);
|
2020-08-15 11:39:43 -03:00
|
|
|
let token = await this.min.adminService.acquireElevatedToken(this.min.instance.instanceId);
|
|
|
|
|
|
|
|
let siteId = process.env.STORAGE_SITE_ID;
|
|
|
|
let libraryId = process.env.STORAGE_LIBRARY;
|
|
|
|
|
|
|
|
let client = MicrosoftGraph.Client.init({
|
|
|
|
authProvider: done => {
|
|
|
|
done(null, token);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
const botId = this.min.instance.botId;
|
|
|
|
const path = `/${botId}.gbai/${botId}.gbdata`;
|
|
|
|
|
|
|
|
let res = await client
|
|
|
|
.api(`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:${path}:/children`)
|
|
|
|
.get();
|
|
|
|
|
|
|
|
let document = res.value.filter(m => {
|
2020-11-09 21:28:14 -03:00
|
|
|
return m.name.toLowerCase() === file.toLowerCase();
|
2020-08-15 11:39:43 -03:00
|
|
|
});
|
|
|
|
|
2020-11-09 21:28:14 -03:00
|
|
|
if (!document || document.length === 0) {
|
2020-12-13 10:02:49 -03:00
|
|
|
throw `File '${file}' specified on save GBasic command SET not found. Check the file extension (.xlsx) and the associated .gbdata/.gbdialog.`;
|
2020-08-15 11:39:43 -03:00
|
|
|
}
|
2020-10-14 13:43:58 -03:00
|
|
|
|
2020-08-15 11:39:43 -03:00
|
|
|
let body = { values: [[]] };
|
|
|
|
body.values[0][0] = value;
|
|
|
|
|
2020-08-15 12:18:03 -03:00
|
|
|
await client
|
2020-08-15 11:39:43 -03:00
|
|
|
.api(
|
|
|
|
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/items/${document[0].id}/workbook/worksheets('Sheet1')/range(address='${address}')`
|
|
|
|
)
|
|
|
|
.patch(body);
|
|
|
|
}
|
|
|
|
|
2020-05-11 10:41:41 -03:00
|
|
|
public async save(file: string, ...args): Promise<any> {
|
2020-11-08 13:39:18 -03:00
|
|
|
GBLog.info(`BASIC: Saving '${file}' (SAVE). Args: ${args.join(',')}.`);
|
2020-08-15 11:39:43 -03:00
|
|
|
let token = await this.min.adminService.acquireElevatedToken(this.min.instance.instanceId);
|
2020-05-11 10:41:41 -03:00
|
|
|
|
2020-06-03 21:31:00 -03:00
|
|
|
let siteId = process.env.STORAGE_SITE_ID;
|
|
|
|
let libraryId = process.env.STORAGE_LIBRARY;
|
2020-05-11 10:41:41 -03:00
|
|
|
|
2020-06-03 21:31:00 -03:00
|
|
|
let client = MicrosoftGraph.Client.init({
|
|
|
|
authProvider: done => {
|
|
|
|
done(null, token);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
const botId = this.min.instance.botId;
|
2020-06-03 21:42:17 -03:00
|
|
|
const path = `/${botId}.gbai/${botId}.gbdata`;
|
2020-05-11 10:41:41 -03:00
|
|
|
|
2020-08-15 11:39:43 -03:00
|
|
|
let res = await client
|
|
|
|
.api(`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:${path}:/children`)
|
2020-06-03 21:31:00 -03:00
|
|
|
.get();
|
2020-05-11 10:41:41 -03:00
|
|
|
|
2020-06-03 21:31:00 -03:00
|
|
|
let document = res.value.filter(m => {
|
2020-11-09 21:28:14 -03:00
|
|
|
return m.name.toLowerCase() === file.toLowerCase();
|
2020-06-03 21:31:00 -03:00
|
|
|
});
|
2020-05-11 10:41:41 -03:00
|
|
|
|
2020-08-15 11:39:43 -03:00
|
|
|
await client
|
|
|
|
.api(
|
2020-12-07 22:25:43 -03:00
|
|
|
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/items/${document[0].id}/workbook/worksheets('Sheet1')/range(address='A2:Z2')/insert`
|
2020-08-15 11:39:43 -03:00
|
|
|
)
|
2020-06-03 21:31:00 -03:00
|
|
|
.post({});
|
2020-05-11 10:41:41 -03:00
|
|
|
|
2020-11-09 21:28:14 -03:00
|
|
|
if (!document || document.length === 0) {
|
2020-06-03 21:31:00 -03:00
|
|
|
throw `File '${file}' specified on save GBasic command SAVE not found. Check the .gbdata or the .gbdialog associated.`;
|
|
|
|
}
|
2020-12-07 22:25:43 -03:00
|
|
|
if (args.length > 128) {
|
|
|
|
throw `File '${file}' has a SAVE call with more than 128 arguments. Check the .gbdialog associated.`;
|
2020-06-03 21:31:00 -03:00
|
|
|
}
|
2020-05-11 10:41:41 -03:00
|
|
|
|
2020-08-15 11:39:43 -03:00
|
|
|
let body = { values: [[]] };
|
2020-05-11 10:41:41 -03:00
|
|
|
|
2020-12-07 22:25:43 -03:00
|
|
|
for (let index = 0; index < 128; index++) {
|
2020-06-03 21:31:00 -03:00
|
|
|
body.values[0][index] = args[index];
|
|
|
|
}
|
2020-05-11 10:41:41 -03:00
|
|
|
|
2020-08-15 11:39:43 -03:00
|
|
|
let res2 = await client
|
|
|
|
.api(
|
2020-12-07 22:25:43 -03:00
|
|
|
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/items/${document[0].id}/workbook/worksheets('Sheet1')/range(address='A2:DX2')`
|
2020-08-15 11:39:43 -03:00
|
|
|
)
|
2020-06-03 21:31:00 -03:00
|
|
|
.patch(body);
|
2020-05-11 10:41:41 -03:00
|
|
|
}
|
|
|
|
|
2020-08-15 11:39:43 -03:00
|
|
|
public async get(file: string, address: string): Promise<any> {
|
|
|
|
let token = await this.min.adminService.acquireElevatedToken(this.min.instance.instanceId);
|
2020-05-14 12:47:46 -03:00
|
|
|
|
|
|
|
let client = MicrosoftGraph.Client.init({
|
|
|
|
authProvider: done => {
|
|
|
|
done(null, token);
|
|
|
|
}
|
|
|
|
});
|
2020-05-23 17:59:01 -03:00
|
|
|
let siteId = process.env.STORAGE_SITE_ID;
|
|
|
|
let libraryId = process.env.STORAGE_LIBRARY;
|
2020-05-14 12:47:46 -03:00
|
|
|
const botId = this.min.instance.botId;
|
2020-05-14 17:16:27 -03:00
|
|
|
const path = `/${botId}.gbai/${botId}.gbdata`;
|
2020-05-14 12:47:46 -03:00
|
|
|
|
2020-08-15 11:39:43 -03:00
|
|
|
let res = await client
|
|
|
|
.api(`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:${path}:/children`)
|
2020-05-15 14:07:30 -03:00
|
|
|
.get();
|
2020-05-14 12:47:46 -03:00
|
|
|
|
2020-08-15 11:39:43 -03:00
|
|
|
// Performs validation.
|
|
|
|
|
|
|
|
let document = res.value.filter(m => {
|
2020-11-09 21:28:14 -03:00
|
|
|
return m.name.toLowerCase() === file.toLowerCase();
|
2020-08-15 11:39:43 -03:00
|
|
|
});
|
|
|
|
|
2020-08-15 12:18:03 -03:00
|
|
|
if (!document || document.length === 0) {
|
2020-08-15 11:39:43 -03:00
|
|
|
throw `File '${file}' specified on save GBasic command GET not found. Check the .gbdata or the .gbdialog associated.`;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates workbook session that will be discarded.
|
|
|
|
|
|
|
|
let results = await client
|
|
|
|
.api(
|
|
|
|
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/items/${document[0].id}/workbook/worksheets('Sheet1')/range(address='${address}')`
|
|
|
|
)
|
|
|
|
.get();
|
|
|
|
|
2020-11-08 13:39:18 -03:00
|
|
|
let val = results.text[0][0];
|
|
|
|
GBLog.info(`BASIC: Getting '${file}' (GET). Value= ${val}.`);
|
|
|
|
return val;
|
2020-08-15 11:39:43 -03:00
|
|
|
}
|
2020-11-08 13:39:18 -03:00
|
|
|
|
2020-12-01 18:01:53 -03:00
|
|
|
|
2020-11-08 13:39:18 -03:00
|
|
|
public async find(file: string, ...args): Promise<any> {
|
|
|
|
let token = await this.min.adminService.acquireElevatedToken(this.min.instance.instanceId);
|
|
|
|
|
|
|
|
let client = MicrosoftGraph.Client.init({
|
|
|
|
authProvider: done => {
|
|
|
|
done(null, token);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
let siteId = process.env.STORAGE_SITE_ID;
|
|
|
|
let libraryId = process.env.STORAGE_LIBRARY;
|
|
|
|
const botId = this.min.instance.botId;
|
|
|
|
const path = `/${botId}.gbai/${botId}.gbdata`;
|
|
|
|
|
|
|
|
let res = await client
|
|
|
|
.api(`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:${path}:/children`)
|
|
|
|
.get();
|
|
|
|
|
|
|
|
// Performs validation.
|
|
|
|
|
|
|
|
let document = res.value.filter(m => {
|
2020-11-09 21:28:14 -03:00
|
|
|
return m.name.toLowerCase() === file.toLowerCase();
|
2020-11-08 13:39:18 -03:00
|
|
|
});
|
|
|
|
|
2020-11-09 21:28:14 -03:00
|
|
|
if (!document || document.length === 0) {
|
2020-11-08 13:39:18 -03:00
|
|
|
throw `File '${file}' specified on save GBasic command FIND not found. Check the .gbdata or the .gbdialog associated.`;
|
|
|
|
}
|
|
|
|
if (args.length > 1) {
|
|
|
|
throw `File '${file}' has a FIND call with more than 1 arguments. Check the .gbdialog associated.`;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates workbook session that will be discarded.
|
|
|
|
|
|
|
|
const filter = args[0].split('=');
|
|
|
|
const columnName = filter[0];
|
|
|
|
const value = filter[1];
|
|
|
|
let results = await client
|
|
|
|
.api(
|
|
|
|
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/items/${document[0].id}/workbook/worksheets('Sheet1')/range(address='A1:Z100')`
|
|
|
|
)
|
|
|
|
.get();
|
|
|
|
|
|
|
|
let columnIndex = 0;
|
|
|
|
const header = results.text[0];
|
|
|
|
for (; columnIndex < header.length; columnIndex++) {
|
2020-11-09 21:28:14 -03:00
|
|
|
if (header[columnIndex].toLowerCase() === columnName.toLowerCase()) {
|
2020-11-08 13:39:18 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-12 15:31:05 -03:00
|
|
|
// As BASIC uses arrays starting with 1 (one) as index,
|
|
|
|
// a ghost element is added at 0 (zero) position.
|
|
|
|
|
2020-11-08 13:39:18 -03:00
|
|
|
let array = [];
|
2020-11-12 15:31:05 -03:00
|
|
|
array.push({ 'this is a base 1': 'array' });
|
2020-11-08 13:39:18 -03:00
|
|
|
let foundIndex = 0;
|
|
|
|
for (; foundIndex < results.text.length; foundIndex++) {
|
2020-11-11 16:03:05 -03:00
|
|
|
// Filter results action.
|
|
|
|
|
2020-11-09 21:28:14 -03:00
|
|
|
if (results.text[foundIndex][columnIndex].toLowerCase() === value.toLowerCase()) {
|
2020-11-08 13:39:18 -03:00
|
|
|
let output = {};
|
|
|
|
const row = results.text[foundIndex];
|
|
|
|
for (let colIndex = 0; colIndex < row.length; colIndex++) {
|
|
|
|
output[header[colIndex]] = row[colIndex];
|
|
|
|
}
|
|
|
|
output['line'] = foundIndex + 1;
|
|
|
|
array.push(output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-12 15:31:05 -03:00
|
|
|
if (array.length === 1) {
|
2020-11-08 13:39:18 -03:00
|
|
|
GBLog.info(`BASIC: FIND the data set is empty.`);
|
|
|
|
return null;
|
2020-11-12 15:31:05 -03:00
|
|
|
} else if (array.length === 2) {
|
2020-11-08 13:39:18 -03:00
|
|
|
GBLog.info(`BASIC: FIND single result: ${array[0]}.`);
|
2020-11-12 15:31:05 -03:00
|
|
|
return array[1];
|
2020-11-08 13:39:18 -03:00
|
|
|
} else {
|
|
|
|
GBLog.info(`BASIC: FIND multiple result count: ${array.length}.`);
|
|
|
|
return array;
|
|
|
|
}
|
2020-12-13 10:02:49 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* folder = CREATE FOLDER "notes\01"
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param name Folder name containing tree separated by slash.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
public async createFolder(name: string) {
|
|
|
|
|
|
|
|
let token = await this.min.adminService.acquireElevatedToken(this.min.instance.instanceId);
|
|
|
|
let siteId = process.env.STORAGE_SITE_ID;
|
|
|
|
let libraryId = process.env.STORAGE_LIBRARY;
|
|
|
|
const botId = this.min.instance.botId;
|
|
|
|
const path = urlJoin(`/${botId}.gbai/${botId}.gbdata`, name);
|
|
|
|
|
|
|
|
return new Promise<any>((resolve, reject) => {
|
|
|
|
let client = MicrosoftGraph.Client.init({
|
|
|
|
authProvider: done => {
|
|
|
|
done(null, token);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
const body = {
|
|
|
|
"name": name,
|
|
|
|
"folder": {},
|
|
|
|
"@microsoft.graph.conflictBehavior": "rename"
|
|
|
|
}
|
|
|
|
client.api(`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:/${path}:/children`)
|
|
|
|
.post(body, (err, res) => {
|
|
|
|
if (err) {
|
|
|
|
reject(err)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
resolve(res);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* folder = CREATE FOLDER "notes\10"
|
|
|
|
* SHARE FOLDER folder, "nome@domain.com", "E-mail message"
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
public async shareFolder(folderReference, email: string, message: string) {
|
|
|
|
let token = await this.min.adminService.acquireElevatedToken(this.min.instance.instanceId);
|
|
|
|
const driveId = folderReference.parentReference.driveId;
|
|
|
|
const itemId = folderReference.id;
|
|
|
|
|
|
|
|
return new Promise<string>((resolve, reject) => {
|
|
|
|
let client = MicrosoftGraph.Client.init({
|
|
|
|
authProvider: done => {
|
|
|
|
done(null, token);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const body =
|
|
|
|
{
|
|
|
|
"recipients": [
|
|
|
|
{
|
|
|
|
"email": email
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"message": message,
|
|
|
|
"requireSignIn": true,
|
|
|
|
"sendInvitation": true,
|
|
|
|
"roles": ["write"]
|
|
|
|
};
|
|
|
|
|
|
|
|
client.api(`https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/invite`)
|
|
|
|
.post(body, (err, res) => {
|
|
|
|
if (err) {
|
|
|
|
reject(err)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
resolve(res);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public async copyFile(src, dst) {
|
|
|
|
|
|
|
|
// let token = await this.min.adminService.acquireElevatedToken(this.min.instance.instanceId);
|
|
|
|
// let siteId = process.env.STORAGE_SITE_ID;
|
|
|
|
// let libraryId = process.env.STORAGE_LIBRARY;
|
|
|
|
// const botId = this.min.instance.botId;
|
|
|
|
// const path = urlJoin(`/${botId}.gbai/${botId}.gbdata`, name);
|
|
|
|
|
|
|
|
// let client = MicrosoftGraph.Client.init({
|
|
|
|
// authProvider: done => {
|
|
|
|
// done(null, token);
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
|
|
|
|
// const body =
|
|
|
|
// {
|
|
|
|
// "parentReference": { driveId: gbaiDest.parentReference.driveId, id: gbaiDest.id },
|
|
|
|
// "name": `${botName}.${kind}`
|
|
|
|
// }
|
|
|
|
|
|
|
|
// const packageName = `${templateName.split('.')[0]}.${kind}`;
|
|
|
|
|
|
|
|
// try {
|
|
|
|
// const src = await client.api(
|
|
|
|
// `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:/${source}`)
|
|
|
|
// .get();
|
|
|
|
|
|
|
|
// return await client.api(
|
|
|
|
// `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/items/${src.id}/copy`)
|
|
|
|
// .post(body);
|
|
|
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
|
|
|
// if (error.code === "itemNotFound") {
|
|
|
|
|
|
|
|
// } else if (error.code === "nameAlreadyExists") {
|
|
|
|
|
|
|
|
// let src = await client.api(
|
|
|
|
// `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:/${templateName}/${packageName}:/children`)
|
|
|
|
// .get();
|
|
|
|
// const dstName = `${botName}.gbai/${botName}.${kind}`;
|
|
|
|
// let dst = await client.api(`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:/${dstName}`)
|
|
|
|
// .get();
|
|
|
|
|
|
|
|
// await CollectionUtil.asyncForEach(src.value, async item => {
|
|
|
|
|
|
|
|
// const body =
|
|
|
|
// {
|
|
|
|
// "parentReference": { driveId: dst.parentReference.driveId, id: dst.id }
|
|
|
|
// }
|
|
|
|
// await client.api(
|
|
|
|
// `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${templateId}/drive/items/${item.id}/copy`)
|
|
|
|
// .post(body);
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
// else {
|
|
|
|
// GBLog.error(error);
|
|
|
|
// throw error;
|
|
|
|
// }
|
|
|
|
// }
|
2020-11-08 13:39:18 -03:00
|
|
|
}
|
|
|
|
|
2019-02-25 08:36:43 -03:00
|
|
|
public generatePassword() {
|
2019-02-23 13:17:21 -03:00
|
|
|
return GBAdminService.getRndPassword();
|
|
|
|
}
|
|
|
|
|
|
|
|
public async createABotFarmUsing(
|
2019-03-08 19:13:00 -03:00
|
|
|
botId: string,
|
|
|
|
username: string,
|
|
|
|
password: string,
|
|
|
|
location: string,
|
|
|
|
nlpAuthoringKey: string,
|
|
|
|
appId: string,
|
|
|
|
appPassword: string,
|
|
|
|
subscriptionId: string
|
2019-02-19 15:30:07 -03:00
|
|
|
) {
|
2019-03-08 06:37:13 -03:00
|
|
|
const service = new AzureDeployerService(this.deployer);
|
2019-02-25 08:36:43 -03:00
|
|
|
await service.deployToCloud(
|
|
|
|
botId,
|
|
|
|
username,
|
|
|
|
password,
|
|
|
|
location,
|
|
|
|
nlpAuthoringKey,
|
|
|
|
appId,
|
|
|
|
appPassword,
|
|
|
|
subscriptionId
|
|
|
|
);
|
2019-02-19 15:30:07 -03:00
|
|
|
}
|
2019-03-08 06:37:13 -03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Generic function to call any REST API.
|
|
|
|
*/
|
|
|
|
public async sendEmail(to, subject, body) {
|
|
|
|
// tslint:disable-next-line:no-console
|
2019-03-08 19:13:00 -03:00
|
|
|
GBLog.info(`[E-mail]: to:${to}, subject: ${subject}, body: ${body}.`);
|
2019-03-08 06:37:13 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generic function to call any REST API.
|
|
|
|
*/
|
2020-08-15 11:39:43 -03:00
|
|
|
public async httpGet(url: string) {
|
|
|
|
const options = {
|
|
|
|
uri: url
|
|
|
|
};
|
|
|
|
|
|
|
|
let result = await request.get(options);
|
|
|
|
GBLog.info(`[GET]: ${url} : ${result}`);
|
|
|
|
return JSON.parse(result);
|
|
|
|
}
|
2019-03-08 06:37:13 -03:00
|
|
|
|
2020-08-15 11:39:43 -03:00
|
|
|
/**
|
|
|
|
* Generic function to call any REST API by POST.
|
|
|
|
*/
|
|
|
|
public async httpPost(url: string, data) {
|
2019-03-08 06:37:13 -03:00
|
|
|
const options = {
|
2020-08-15 11:39:43 -03:00
|
|
|
uri: url,
|
|
|
|
json: true,
|
|
|
|
body: data
|
2019-03-08 06:37:13 -03:00
|
|
|
};
|
|
|
|
|
2020-08-15 11:39:43 -03:00
|
|
|
let result = await request.post(options);
|
|
|
|
GBLog.info(`[POST]: ${url} (${data}): ${result}`);
|
|
|
|
return JSON.parse(result);
|
2019-03-08 06:37:13 -03:00
|
|
|
}
|
|
|
|
|
2020-05-14 12:47:46 -03:00
|
|
|
public async numberOnly(text: string) {
|
2020-08-15 11:39:43 -03:00
|
|
|
return text.replace(/\D/gi, '');
|
2020-05-14 12:47:46 -03:00
|
|
|
}
|
2019-02-19 15:30:07 -03:00
|
|
|
}
|
2019-03-09 16:59:31 -03:00
|
|
|
|
2018-11-26 14:09:09 -02:00
|
|
|
/**
|
2019-03-09 16:59:31 -03:00
|
|
|
* Base services of conversation to be called by BASIC.
|
2018-11-26 14:09:09 -02:00
|
|
|
*/
|
2019-03-09 16:59:31 -03:00
|
|
|
export class DialogClass {
|
2018-11-28 17:08:06 -02:00
|
|
|
public min: GBMinInstance;
|
2018-11-30 11:55:44 -02:00
|
|
|
public context: TurnContext;
|
2018-12-01 14:38:08 -02:00
|
|
|
public step: WaterfallStepContext;
|
2019-02-19 15:30:07 -03:00
|
|
|
public internalSys: SysClass;
|
2018-04-21 02:59:30 -03:00
|
|
|
|
2019-03-08 06:37:13 -03:00
|
|
|
constructor(min: GBMinInstance, deployer: GBDeployer) {
|
2018-11-26 14:09:09 -02:00
|
|
|
this.min = min;
|
2019-03-08 06:37:13 -03:00
|
|
|
this.internalSys = new SysClass(min, deployer);
|
2018-11-27 22:56:11 -02:00
|
|
|
}
|
|
|
|
|
2020-05-11 10:41:41 -03:00
|
|
|
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
2020-08-15 11:39:43 -03:00
|
|
|
min.dialogs.add(
|
|
|
|
new WaterfallDialog('/gbasic-email', [
|
|
|
|
async step => {
|
|
|
|
const locale = step.context.activity.locale;
|
|
|
|
if ((step.options as any).ask) {
|
|
|
|
await min.conversationalService.sendText(min, step, Messages[locale].whats_email);
|
|
|
|
}
|
|
|
|
return await step.prompt('textPrompt', {});
|
|
|
|
},
|
|
|
|
async step => {
|
|
|
|
const locale = step.context.activity.locale;
|
|
|
|
|
|
|
|
const extractEntity = text => {
|
|
|
|
return text.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/gi);
|
|
|
|
};
|
|
|
|
|
|
|
|
const value = extractEntity(step.result);
|
|
|
|
|
|
|
|
if (value === null) {
|
|
|
|
await min.conversationalService.sendText(min, step, Messages[locale].validation_enter_valid_email);
|
|
|
|
return await step.replaceDialog('/gbasic-email', { ask: true });
|
|
|
|
} else {
|
|
|
|
return await step.endDialog(value[0]);
|
|
|
|
}
|
2020-05-11 10:41:41 -03:00
|
|
|
}
|
2020-08-15 11:39:43 -03:00
|
|
|
])
|
|
|
|
);
|
2020-05-11 10:41:41 -03:00
|
|
|
}
|
|
|
|
|
2019-02-25 08:36:43 -03:00
|
|
|
public sys(): SysClass {
|
2019-02-19 15:30:07 -03:00
|
|
|
return this.internalSys;
|
|
|
|
}
|
|
|
|
|
2020-05-11 10:41:41 -03:00
|
|
|
public async getToday(step) {
|
|
|
|
var d = new Date(),
|
|
|
|
month = '' + (d.getMonth() + 1),
|
|
|
|
day = '' + d.getDate(),
|
|
|
|
year = d.getFullYear();
|
|
|
|
|
2020-08-15 11:39:43 -03:00
|
|
|
if (month.length < 2) month = '0' + month;
|
|
|
|
if (day.length < 2) day = '0' + day;
|
2020-05-11 10:41:41 -03:00
|
|
|
|
|
|
|
const locale = step.context.activity.locale;
|
|
|
|
switch (locale) {
|
|
|
|
case 'pt-BR':
|
|
|
|
return [day, month, year].join('/');
|
|
|
|
|
|
|
|
case 'en-US':
|
|
|
|
return [month, day, year].join('/');
|
|
|
|
|
|
|
|
default:
|
|
|
|
return [year, month, day].join('/');
|
|
|
|
}
|
|
|
|
}
|
2020-12-11 07:35:55 -03:00
|
|
|
|
2020-11-30 17:09:47 -03:00
|
|
|
public async isAffirmative(step, text) {
|
2020-12-07 23:24:00 -03:00
|
|
|
return text.toLowerCase().match(Messages['pt-BR'].affirmative_sentences); // TODO: Dynamitize.
|
2020-11-30 17:09:47 -03:00
|
|
|
}
|
2020-12-13 10:02:49 -03:00
|
|
|
|
2020-12-02 17:20:38 -03:00
|
|
|
public async exit(step) {
|
|
|
|
await step.endDialog();
|
|
|
|
}
|
2020-12-01 18:01:53 -03:00
|
|
|
|
2020-11-08 13:39:18 -03:00
|
|
|
public async getNow(step) {
|
2020-11-30 17:09:47 -03:00
|
|
|
const nowUTC = new Date();
|
|
|
|
const now = new Date((typeof nowUTC === "string" ?
|
2020-12-01 18:01:53 -03:00
|
|
|
new Date(nowUTC) :
|
|
|
|
nowUTC).toLocaleString("en-US", { timeZone: process.env.DEFAULT_TIMEZONE }));
|
2020-11-08 13:39:18 -03:00
|
|
|
|
2020-11-30 17:09:47 -03:00
|
|
|
return now.getHours() + ':' + now.getMinutes();
|
2020-11-08 13:39:18 -03:00
|
|
|
}
|
2020-11-12 15:31:05 -03:00
|
|
|
|
2020-11-11 11:10:40 -03:00
|
|
|
public async sendFileTo(step, mobile, filename, caption) {
|
|
|
|
return await this.internalSendFile(null, mobile, filename, caption);
|
|
|
|
}
|
2020-11-08 13:39:18 -03:00
|
|
|
|
2020-05-15 14:07:30 -03:00
|
|
|
public async sendFile(step, filename, caption) {
|
2020-11-11 11:10:40 -03:00
|
|
|
return await this.internalSendFile(step, null, filename, caption);
|
|
|
|
}
|
|
|
|
|
|
|
|
private async internalSendFile(step, mobile, filename, caption) {
|
2020-11-08 13:39:18 -03:00
|
|
|
if (filename.indexOf('.md') > -1) {
|
2020-11-09 18:29:23 -03:00
|
|
|
GBLog.info(`BASIC: Sending the contents of ${filename} markdown to mobile.`);
|
2020-11-08 13:39:18 -03:00
|
|
|
let md = await this.min.kbService.getAnswerTextByMediaName(this.min.instance.instanceId, filename);
|
2020-11-11 11:10:40 -03:00
|
|
|
await this.min.conversationalService.sendMarkdownToMobile(this.min, step, mobile, md);
|
2020-11-08 13:39:18 -03:00
|
|
|
} else {
|
2020-11-09 18:29:23 -03:00
|
|
|
GBLog.info(`BASIC: Sending the file ${filename} to mobile.`);
|
2020-11-08 13:39:18 -03:00
|
|
|
let url = urlJoin(
|
|
|
|
GBServer.globals.publicAddress,
|
|
|
|
'kb',
|
|
|
|
`${this.min.botId}.gbai`,
|
|
|
|
`${this.min.botId}.gbkb`,
|
|
|
|
'assets',
|
|
|
|
filename
|
|
|
|
);
|
|
|
|
|
2020-11-11 11:10:40 -03:00
|
|
|
await this.min.conversationalService.sendFile(this.min, step, mobile, url, caption);
|
2020-11-08 13:39:18 -03:00
|
|
|
}
|
2020-05-15 14:07:30 -03:00
|
|
|
}
|
|
|
|
|
2020-05-11 10:41:41 -03:00
|
|
|
public async getFrom(step) {
|
|
|
|
return step.context.activity.from.id;
|
|
|
|
}
|
|
|
|
|
2020-07-07 10:15:39 -03:00
|
|
|
public async getUserName(step) {
|
|
|
|
return step.context.activity.from.name;
|
|
|
|
}
|
|
|
|
|
|
|
|
public async getUserMobile(step) {
|
2020-08-15 11:39:43 -03:00
|
|
|
if (isNaN(step.context.activity.from.id)) {
|
|
|
|
return 'No mobile available.';
|
|
|
|
} else {
|
|
|
|
return step.context.activity.from.id;
|
2020-07-07 10:15:39 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-11 07:35:55 -03:00
|
|
|
public async showMenu(step) {
|
|
|
|
return await step.beginDialog('/menu');
|
2020-05-11 10:41:41 -03:00
|
|
|
}
|
|
|
|
|
2020-10-14 14:04:02 -03:00
|
|
|
public async transfer(step) {
|
|
|
|
return await step.beginDialog('/t');
|
|
|
|
}
|
|
|
|
|
2020-12-07 22:25:43 -03:00
|
|
|
public async hear(step, promise, previousResolve, kind, ...args) {
|
2019-05-15 22:30:14 -03:00
|
|
|
function random(low, high) {
|
2020-08-15 11:39:43 -03:00
|
|
|
return Math.random() * (high - low) + low;
|
2019-05-15 22:30:14 -03:00
|
|
|
}
|
2019-08-29 19:59:58 -03:00
|
|
|
const idPromise = random(0, 120000000);
|
2019-08-30 14:06:01 -03:00
|
|
|
this.min.cbMap[idPromise] = {};
|
|
|
|
this.min.cbMap[idPromise].promise = promise;
|
2020-05-11 10:41:41 -03:00
|
|
|
|
2020-12-07 22:25:43 -03:00
|
|
|
const opts = { id: idPromise, previousResolve: previousResolve, kind: kind, args };
|
2020-05-11 10:41:41 -03:00
|
|
|
if (previousResolve !== undefined) {
|
|
|
|
previousResolve(opts);
|
2020-08-15 11:39:43 -03:00
|
|
|
} else {
|
2019-08-30 14:06:01 -03:00
|
|
|
await step.beginDialog('/hear', opts);
|
2020-05-11 10:41:41 -03:00
|
|
|
}
|
2018-11-30 11:55:44 -02:00
|
|
|
}
|
2018-11-28 17:08:06 -02:00
|
|
|
|
2019-08-29 19:59:58 -03:00
|
|
|
public async talk(step, text: string) {
|
2020-05-17 21:30:21 +00:00
|
|
|
return await this.min.conversationalService.sendText(this.min, step, text);
|
2018-12-01 14:38:08 -02:00
|
|
|
}
|
2018-11-12 12:20:44 -02:00
|
|
|
}
|