fix(core.gbapp): Lint of all.
This commit is contained in:
parent
f8d2cd895a
commit
4a2f8b7b43
81 changed files with 11121 additions and 6793 deletions
10719
package-lock.json
generated
10719
package-lock.json
generated
File diff suppressed because it is too large
Load diff
11
package.json
11
package.json
|
@ -86,7 +86,6 @@
|
|||
"core-js": "3.26.1",
|
||||
"data-forge": "1.9.6",
|
||||
"date-diff": "1.0.2",
|
||||
"debugger-api": "0.1.2",
|
||||
"docxtemplater": "3.32.4",
|
||||
"dotenv-extended": "2.9.0",
|
||||
"exceljs": "4.3.0",
|
||||
|
@ -106,7 +105,7 @@
|
|||
"luxon": "3.1.0",
|
||||
"mammoth": "1.5.1",
|
||||
"marked": "4.2.2",
|
||||
"moment": "^1.3.0",
|
||||
"moment": "1.3.0",
|
||||
"ms-rest-azure": "3.0.2",
|
||||
"nexmo": "2.9.1",
|
||||
"node-cron": "3.0.2",
|
||||
|
@ -143,7 +142,7 @@
|
|||
"swagger-client": "^3.18.5",
|
||||
"tabulator-tables": "5.4.2",
|
||||
"tedious": "15.1.2",
|
||||
"textract": "^0.20.0",
|
||||
"@nosferatu500/textract": "3.1.2",
|
||||
"twitter-api-v2": "1.12.9",
|
||||
"typescript": "4.9.3",
|
||||
"typescript-rest-rpc": "^1.0.7",
|
||||
|
@ -156,13 +155,11 @@
|
|||
"washyourmouthoutwithsoap": "1.0.2",
|
||||
"whatsapp-web.js": "1.18.3",
|
||||
"winston": "3.8.2",
|
||||
"winston-logs-display": "1.0.0",
|
||||
"yarn": "1.22.19"
|
||||
"yarn": "^1.22.19"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/puppeteer": "7.0.4",
|
||||
"@types/url-join": "4.0.1",
|
||||
"ban-sensitive-files": "^1.3.0",
|
||||
"ban-sensitive-files": "1.9.18",
|
||||
"commitizen": "4.2.5",
|
||||
"cz-conventional-changelog": "3.3.0",
|
||||
"dependency-check": "4.1.0",
|
||||
|
|
|
@ -77,8 +77,7 @@ export class AdminDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -109,8 +108,7 @@ export class AdminDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -200,8 +198,7 @@ export class AdminDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -237,17 +234,15 @@ export class AdminDialog extends IGBDialog {
|
|||
min.dialogs.add(
|
||||
new WaterfallDialog('/publish', [
|
||||
async step => {
|
||||
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
||||
async step => {
|
||||
if (step.activeDialog.state.options.confirm || process.env.ADMIN_OPEN_PUBLISH === "true") {
|
||||
if (step.activeDialog.state.options.confirm || process.env.ADMIN_OPEN_PUBLISH === 'true') {
|
||||
return await step.next('sim');
|
||||
} else {
|
||||
const locale = step.context.activity.locale;
|
||||
|
@ -266,7 +261,7 @@ export class AdminDialog extends IGBDialog {
|
|||
if (step.activeDialog.state.options.firstTime) {
|
||||
canPublish = true;
|
||||
} else {
|
||||
canPublish = AdminDialog.canPublish(min, from) || process.env.ADMIN_OPEN_PUBLISH === "true";
|
||||
canPublish = AdminDialog.canPublish(min, from) || process.env.ADMIN_OPEN_PUBLISH === 'true';
|
||||
}
|
||||
|
||||
if (!canPublish) {
|
||||
|
@ -313,11 +308,14 @@ export class AdminDialog extends IGBDialog {
|
|||
try {
|
||||
let cmd1;
|
||||
if (packageName.indexOf('.') !== -1) {
|
||||
cmd1 = `deployPackage ${process.env.STORAGE_SITE} /${process.env.STORAGE_LIBRARY}/${botId}.gbai/${packageName}`;
|
||||
cmd1 = `deployPackage ${process.env.STORAGE_SITE} /${
|
||||
process.env.STORAGE_LIBRARY
|
||||
}/${botId}.gbai/${packageName}`;
|
||||
} else {
|
||||
cmd1 = `deployPackage ${packageName}`;
|
||||
}
|
||||
if ((await (deployer as any).getStoragePackageByName(min.instance.instanceId, packageName)) !== null &&
|
||||
if (
|
||||
(await (deployer as any).getStoragePackageByName(min.instance.instanceId, packageName)) !== null &&
|
||||
!process.env.DONT_DOWNLOAD
|
||||
) {
|
||||
const cmd2 = `undeployPackage ${packageName}`;
|
||||
|
@ -354,8 +352,7 @@ export class AdminDialog extends IGBDialog {
|
|||
if (process.env.SECURITY_CAN_PUBLISH !== undefined) {
|
||||
let list = process.env.SECURITY_CAN_PUBLISH.split(';');
|
||||
|
||||
const canPublish =
|
||||
min.core.getParam(min.instance, 'Can Publish', null);
|
||||
const canPublish = min.core.getParam(min.instance, 'Can Publish', null);
|
||||
if (canPublish) {
|
||||
list = list.concat(canPublish.split(';'));
|
||||
}
|
||||
|
@ -376,8 +373,7 @@ export class AdminDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -398,10 +394,8 @@ export class AdminDialog extends IGBDialog {
|
|||
async step => {
|
||||
step.activeDialog.state.authenticatorAuthorityHostUrl = step.result;
|
||||
|
||||
min.instance.authenticatorTenant =
|
||||
step.activeDialog.state.authenticatorTenant;
|
||||
min.instance.authenticatorAuthorityHostUrl =
|
||||
step.activeDialog.state.authenticatorAuthorityHostUrl;
|
||||
min.instance.authenticatorTenant = step.activeDialog.state.authenticatorTenant;
|
||||
min.instance.authenticatorAuthorityHostUrl = step.activeDialog.state.authenticatorAuthorityHostUrl;
|
||||
|
||||
await min.adminService.updateSecurityInfo(
|
||||
min.instance.instanceId,
|
||||
|
@ -415,15 +409,12 @@ export class AdminDialog extends IGBDialog {
|
|||
|
||||
min.adminService.setValue(min.instance.instanceId, 'AntiCSRFAttackState', state);
|
||||
|
||||
const redirectUri = urlJoin(
|
||||
min.instance.botEndpoint,
|
||||
min.instance.botId,
|
||||
'/token'
|
||||
);
|
||||
const url = `https://login.microsoftonline.com/${step.activeDialog.state.authenticatorTenant
|
||||
}/oauth2/authorize?client_id=${min.instance.marketplaceId
|
||||
}&response_type=code&redirect_uri=${redirectUri
|
||||
}&scope=https://graph.microsoft.com/.default&state=${state}&response_mode=query`;
|
||||
const redirectUri = urlJoin(min.instance.botEndpoint, min.instance.botId, '/token');
|
||||
const url = `https://login.microsoftonline.com/${
|
||||
step.activeDialog.state.authenticatorTenant
|
||||
}/oauth2/authorize?client_id=${
|
||||
min.instance.marketplaceId
|
||||
}&response_type=code&redirect_uri=${redirectUri}&scope=https://graph.microsoft.com/.default&state=${state}&response_mode=query`;
|
||||
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].consent(url));
|
||||
|
||||
|
|
|
@ -70,5 +70,4 @@ export class GBAdminPackage implements IGBPackage {
|
|||
public async loadBot (min: GBMinInstance): Promise<void> {
|
||||
AdminDialog.setup(min);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,36 +36,27 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import {
|
||||
Column,
|
||||
CreatedAt,
|
||||
DataType,
|
||||
Model,
|
||||
Table,
|
||||
UpdatedAt
|
||||
} from 'sequelize-typescript';
|
||||
import { Column, CreatedAt, DataType, Model, Table, UpdatedAt } from 'sequelize-typescript';
|
||||
|
||||
/**
|
||||
* General settings store.
|
||||
*/
|
||||
@Table
|
||||
export class GuaribasAdmin extends Model<GuaribasAdmin> {
|
||||
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare key: string;
|
||||
key: string;
|
||||
|
||||
@Column(DataType.STRING(4000))
|
||||
declare value: string;
|
||||
value: string;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@CreatedAt
|
||||
declare createdAt: Date;
|
||||
createdAt: Date;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@UpdatedAt
|
||||
declare updatedAt: Date;
|
||||
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ export class GBAdminService implements IGBAdminService {
|
|||
}
|
||||
|
||||
public static getNodeVersion () {
|
||||
return "19.1.0";
|
||||
return '19.1.0';
|
||||
const packageJson = urlJoin(process.cwd(), 'package.json');
|
||||
// tslint:disable-next-line: non-literal-require
|
||||
// TODO
|
||||
|
@ -88,7 +88,7 @@ export class GBAdminService implements IGBAdminService {
|
|||
}
|
||||
|
||||
public static async getADALCredentialsFromUsername (username: string, password: string) {
|
||||
return await msRestAzure.loginWithUsernamePassword(username, password)
|
||||
return await msRestAzure.loginWithUsernamePassword(username, password);
|
||||
}
|
||||
|
||||
public static getMobileCode () {
|
||||
|
@ -153,7 +153,8 @@ export class GBAdminService implements IGBAdminService {
|
|||
* @see https://stackoverflow.com/a/52171480
|
||||
*/
|
||||
public static getHash (str, seed = 0) {
|
||||
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
|
||||
let h1 = 0xdeadbeef ^ seed,
|
||||
h2 = 0x41c6ce57 ^ seed;
|
||||
for (let i = 0, ch; i < str.length; i++) {
|
||||
ch = str.charCodeAt(i);
|
||||
h1 = Math.imul(h1 ^ ch, 2654435761);
|
||||
|
@ -195,9 +196,7 @@ export class GBAdminService implements IGBAdminService {
|
|||
// .gbot packages are handled using storage API, so no download
|
||||
// of local resources is required.
|
||||
|
||||
await deployer['downloadFolder'](min,
|
||||
Path.join('work', `${min.instance.botId}.gbai`),
|
||||
Path.basename(folderName));
|
||||
await deployer['downloadFolder'](min, Path.join('work', `${min.instance.botId}.gbai`), Path.basename(folderName));
|
||||
await deployer.deployPackage(min, localFolder);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ export const Messages = {
|
|||
authenticate: 'Please, authenticate:',
|
||||
welcome: 'Welcome to Pragmatismo.io GeneralBots Administration.',
|
||||
which_task: 'Which task do you wanna run now?',
|
||||
working: (command) => `I'm working on ${command}...`,
|
||||
working: command => `I'm working on ${command}...`,
|
||||
finished_working: 'Done.',
|
||||
unknown_command: text =>
|
||||
`Well, but ${text} is not a administrative General Bots command, I will try to search for it.`,
|
||||
|
@ -12,7 +12,7 @@ export const Messages = {
|
|||
deployPackage: text => `Deploying package ${text}...`,
|
||||
redeployPackage: text => `Redeploying package ${text}...`,
|
||||
packageUndeployed: text => `√ Package ${text} undeployed...`,
|
||||
consent: (url) => `Please, consent access to this app at: [Microsoft Online](${url}).`,
|
||||
consent: url => `Please, consent access to this app at: [Microsoft Online](${url}).`,
|
||||
wrong_password: 'Sorry, wrong password. Please, try again.',
|
||||
enter_authenticator_tenant: 'Enter the Authenticator Tenant (eg.: domain.onmicrosoft.com):',
|
||||
enter_authenticator_authority_host_url: 'Enter the Authority Host URL (eg.: https://login.microsoftonline.com): ',
|
||||
|
@ -28,7 +28,7 @@ export const Messages = {
|
|||
authenticate: 'Please, authenticate:',
|
||||
welcome: 'Welcome to Pragmatismo.io GeneralBots Administration.',
|
||||
which_task: 'Which task do you wanna run now?',
|
||||
working: (command) => `I'm working on ${command}...`,
|
||||
working: command => `I'm working on ${command}...`,
|
||||
finished_working: 'Done.',
|
||||
unknown_command: text =>
|
||||
`Well, but ${text} is not a administrative General Bots command, I will try to search for it.`,
|
||||
|
@ -37,7 +37,7 @@ export const Messages = {
|
|||
deployPackage: text => `Deploying package ${text}...`,
|
||||
redeployPackage: text => `Redeploying package ${text}...`,
|
||||
packageUndeployed: text => `Package ${text} undeployed...`,
|
||||
consent: (url) => `Please, consent access to this app at: [Microsoft Online](${url}).`,
|
||||
consent: url => `Please, consent access to this app at: [Microsoft Online](${url}).`,
|
||||
wrong_password: 'Sorry, wrong password. Please, try again.',
|
||||
enter_authenticator_tenant: 'Enter the Authenticator Tenant (eg.: domain.onmicrosoft.com):',
|
||||
enter_authenticator_authority_host_url: 'Enter the Authority Host URL (eg.: https://login.microsoftonline.com): ',
|
||||
|
|
|
@ -51,7 +51,6 @@ export class GBAnalyticsPackage implements IGBPackage {
|
|||
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||
GBLog.verbose(`loadPackage called.`);
|
||||
core.sequelize.addModels([GuaribasConversation, GuaribasConversationMessage]);
|
||||
|
||||
}
|
||||
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||
GBLog.verbose(`unloadPackage called.`);
|
||||
|
@ -68,5 +67,4 @@ export class GBAnalyticsPackage implements IGBPackage {
|
|||
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -63,49 +63,48 @@ import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
|||
*/
|
||||
@Table
|
||||
export class GuaribasConversation extends Model<GuaribasConversation> {
|
||||
|
||||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
declare conversationId: number;
|
||||
conversationId: number;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@ForeignKey(() => GuaribasSubject)
|
||||
@Column(DataType.INTEGER)
|
||||
declare startSubjectId: number;
|
||||
startSubjectId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasSubject)
|
||||
declare startSubject: GuaribasSubject;
|
||||
startSubject: GuaribasSubject;
|
||||
|
||||
@ForeignKey(() => GuaribasChannel)
|
||||
@Column(DataType.INTEGER)
|
||||
declare channelId: string;
|
||||
channelId: string;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
declare rateDate: Date;
|
||||
rateDate: Date;
|
||||
|
||||
@Column(DataType.FLOAT)
|
||||
declare rate: number;
|
||||
rate: number;
|
||||
|
||||
@Column(DataType.STRING(512))
|
||||
declare feedback: string;
|
||||
feedback: string;
|
||||
|
||||
@CreatedAt
|
||||
@Column(DataType.DATE)
|
||||
declare createdAt: Date;
|
||||
createdAt: Date;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare text: string;
|
||||
text: string;
|
||||
|
||||
@ForeignKey(() => GuaribasUser)
|
||||
@Column(DataType.INTEGER)
|
||||
declare startedByUserId: number;
|
||||
startedByUserId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasUser)
|
||||
declare startedBy: GuaribasUser;
|
||||
startedBy: GuaribasUser;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,45 +112,43 @@ export class GuaribasConversation extends Model<GuaribasConversation> {
|
|||
*/
|
||||
@Table
|
||||
export class GuaribasConversationMessage extends Model<GuaribasConversationMessage> {
|
||||
|
||||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
declare conversationMessageId: number;
|
||||
conversationMessageId: number;
|
||||
|
||||
@ForeignKey(() => GuaribasSubject)
|
||||
@Column(DataType.INTEGER)
|
||||
declare subjectId: number;
|
||||
subjectId: number;
|
||||
|
||||
@Column(DataType.TEXT)
|
||||
declare content: string;
|
||||
content: string;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@CreatedAt
|
||||
declare createdAt: Date;
|
||||
createdAt: Date;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@UpdatedAt
|
||||
declare updatedAt: Date;
|
||||
|
||||
updatedAt: Date;
|
||||
|
||||
//tslint:disable-next-line:no-use-before-declare
|
||||
@ForeignKey(() => GuaribasConversation)
|
||||
@Column(DataType.INTEGER)
|
||||
declare conversationId: number;
|
||||
conversationId: number;
|
||||
|
||||
//tslint:disable-next-line:no-use-before-declare
|
||||
@BelongsTo(() => GuaribasConversation)
|
||||
declare conversation: GuaribasConversation;
|
||||
conversation: GuaribasConversation;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@ForeignKey(() => GuaribasUser)
|
||||
@Column(DataType.INTEGER)
|
||||
declare userId: number;
|
||||
userId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasUser)
|
||||
declare user: GuaribasUser;
|
||||
user: GuaribasUser;
|
||||
}
|
||||
|
|
|
@ -44,10 +44,7 @@ import { GuaribasConversation, GuaribasConversationMessage } from '../models/ind
|
|||
* Base services for Bot Analytics.
|
||||
*/
|
||||
export class AnalyticsService {
|
||||
|
||||
public async createConversation(
|
||||
user: GuaribasUser
|
||||
): Promise<GuaribasConversation> {
|
||||
public async createConversation (user: GuaribasUser): Promise<GuaribasConversation> {
|
||||
const conversation = new GuaribasConversation();
|
||||
conversation.startedBy = user;
|
||||
conversation.startedByUserId = user.userId;
|
||||
|
@ -56,15 +53,18 @@ export class AnalyticsService {
|
|||
return await conversation.save();
|
||||
}
|
||||
|
||||
public async updateConversationSuggestion(instanceId: number,
|
||||
conversationId: string, feedback: string, locale: string): Promise<number> {
|
||||
|
||||
public async updateConversationSuggestion (
|
||||
instanceId: number,
|
||||
conversationId: string,
|
||||
feedback: string,
|
||||
locale: string
|
||||
): Promise<number> {
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
const rate = await AzureText.getSentiment(
|
||||
minBoot.instance.textAnalyticsKey ? minBoot.instance.textAnalyticsKey :
|
||||
minBoot.instance.textAnalyticsKey,
|
||||
minBoot.instance.textAnalyticsEndpoint ? minBoot.instance.textAnalyticsEndpoint :
|
||||
minBoot.instance.textAnalyticsEndpoint,
|
||||
minBoot.instance.textAnalyticsKey ? minBoot.instance.textAnalyticsKey : minBoot.instance.textAnalyticsKey,
|
||||
minBoot.instance.textAnalyticsEndpoint
|
||||
? minBoot.instance.textAnalyticsEndpoint
|
||||
: minBoot.instance.textAnalyticsEndpoint,
|
||||
locale,
|
||||
feedback
|
||||
);
|
||||
|
@ -79,7 +79,6 @@ export class AnalyticsService {
|
|||
await item.save();
|
||||
|
||||
return rate;
|
||||
|
||||
}
|
||||
|
||||
public async createMessage (
|
||||
|
@ -88,9 +87,8 @@ export class AnalyticsService {
|
|||
userId: number,
|
||||
content: string
|
||||
): Promise<GuaribasConversationMessage> {
|
||||
|
||||
const message = GuaribasConversationMessage.build();
|
||||
message.content = typeof (content) === 'object' ? JSON.stringify(content) : content;
|
||||
message.content = typeof content === 'object' ? JSON.stringify(content) : content;
|
||||
message.instanceId = instanceId;
|
||||
message.userId = userId;
|
||||
message.conversationId = conversation.conversationId;
|
||||
|
|
|
@ -146,7 +146,6 @@ cannot start or end with or contain consecutive dashes and having 4 to 42 charac
|
|||
return botId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Update Manifest in Azure: "signInAudience": "AzureADandPersonalMicrosoftAccount" and "accessTokenAcceptedVersion": 2.
|
||||
|
|
|
@ -65,5 +65,4 @@ export class GBAzureDeployerPackage implements IGBPackage {
|
|||
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,11 +51,10 @@ import { GBCorePackage } from '../../../packages/core.gbapp/index.js';
|
|||
import { GBConfigService } from '../../../packages/core.gbapp/services/GBConfigService.js';
|
||||
import { GBDeployer } from '../../../packages/core.gbapp/services/GBDeployer.js';
|
||||
import { Account } from '@azure/arm-cognitiveservices';
|
||||
import MicrosoftGraph from "@microsoft/microsoft-graph-client";
|
||||
import MicrosoftGraph from '@microsoft/microsoft-graph-client';
|
||||
import Spinner from 'cli-spinner';
|
||||
import * as publicIp from 'public-ip';
|
||||
|
||||
|
||||
const WebSiteResponseTimeout = 900;
|
||||
const iconUrl = 'https://github.com/pragmatismo-io/BotServer/blob/master/docs/images/generalbots-logo-squared.png';
|
||||
/**
|
||||
|
@ -90,7 +89,6 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
}
|
||||
|
||||
public static async createInstance (deployer: GBDeployer): Promise<AzureDeployerService> {
|
||||
|
||||
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
|
||||
|
@ -233,22 +231,19 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
}
|
||||
|
||||
public async botExists (botId) {
|
||||
|
||||
const baseUrl = `https://management.azure.com/`;
|
||||
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||
|
||||
|
||||
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
||||
const httpClient = new ServiceClient();
|
||||
|
||||
const query = `providers/${this.provider
|
||||
}/checkNameAvailability/Action?api-version=${this.apiVersion}`;
|
||||
const query = `providers/${this.provider}/checkNameAvailability/Action?api-version=${this.apiVersion}`;
|
||||
|
||||
const url = urlJoin(baseUrl, query);
|
||||
const body = {
|
||||
name: botId,
|
||||
type: "botServices"
|
||||
type: 'botServices'
|
||||
};
|
||||
|
||||
const req = AzureDeployerService.createRequestObject(url, accessToken, 'POST', JSON.stringify(body));
|
||||
|
@ -272,7 +267,8 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
}
|
||||
};
|
||||
|
||||
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${this.provider
|
||||
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
|
||||
this.provider
|
||||
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
||||
const url = urlJoin(baseUrl, query);
|
||||
const req = AzureDeployerService.createRequestObject(url, accessToken, 'PATCH', JSON.stringify(parameters));
|
||||
|
@ -284,8 +280,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
GBLog.info(`Bot proxy updated at: ${endpoint}.`);
|
||||
}
|
||||
|
||||
public async updateBot(botId: string, group: string, name: string,
|
||||
description: string, endpoint: string) {
|
||||
public async updateBot (botId: string, group: string, name: string, description: string, endpoint: string) {
|
||||
const baseUrl = `https://management.azure.com/`;
|
||||
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||
|
@ -303,7 +298,8 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
}
|
||||
};
|
||||
|
||||
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${this.provider
|
||||
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
|
||||
this.provider
|
||||
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
||||
const url = urlJoin(baseUrl, query);
|
||||
const req = AzureDeployerService.createRequestObject(url, accessToken, 'PATCH', JSON.stringify(parameters));
|
||||
|
@ -324,13 +320,14 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
||||
const httpClient = new ServiceClient();
|
||||
|
||||
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${this.provider
|
||||
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
|
||||
this.provider
|
||||
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
||||
const url = urlJoin(baseUrl, query);
|
||||
const req = AzureDeployerService.createRequestObject(url, accessToken, 'DELETE', undefined);
|
||||
const res = await httpClient.sendRequest(req);
|
||||
|
||||
if (res.bodyAsText !== "") {
|
||||
if (res.bodyAsText !== '') {
|
||||
throw res.bodyAsText;
|
||||
}
|
||||
GBLog.info(`Bot ${botId} was deleted from the provider.`);
|
||||
|
@ -350,7 +347,6 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
endIpAddress: ip
|
||||
};
|
||||
await storageClient.firewallRules.createOrUpdate(groupName, serverName, 'gb', params);
|
||||
|
||||
}
|
||||
|
||||
public async deployFarm (
|
||||
|
@ -368,11 +364,9 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
let keys: any;
|
||||
const name = instance.botId;
|
||||
|
||||
|
||||
GBLog.info(`Enabling resource providers...`);
|
||||
await this.enableResourceProviders('Microsoft.BotService');
|
||||
|
||||
|
||||
GBLog.info(`Deploying Deploy Group (It may take a few minutes)...`);
|
||||
await this.createDeployGroup(name, instance.cloudLocation);
|
||||
|
||||
|
@ -386,8 +380,13 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
const administratorPassword = GBAdminService.getRndPassword();
|
||||
const storageServer = `${name.toLowerCase()}-storage-server`;
|
||||
const storageName = `${name}-storage`;
|
||||
await this.createStorageServer(name, storageServer, administratorLogin,
|
||||
administratorPassword, storageServer, instance.cloudLocation
|
||||
await this.createStorageServer(
|
||||
name,
|
||||
storageServer,
|
||||
administratorLogin,
|
||||
administratorPassword,
|
||||
storageServer,
|
||||
instance.cloudLocation
|
||||
);
|
||||
await this.createStorage(name, storageServer, storageName, instance.cloudLocation);
|
||||
instance.storageUsername = administratorLogin;
|
||||
|
@ -430,18 +429,25 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
GBLog.info(`Deploying Bot...`);
|
||||
instance.botEndpoint = this.defaultEndPoint;
|
||||
|
||||
instance = await this.internalDeployBot(
|
||||
instance, this.accessToken, name, name, name, 'General BootBot',
|
||||
`${proxyAddress}/api/messages/${name}`, 'global',
|
||||
instance.nlpAppId, instance.nlpKey, instance.marketplaceId, instance.marketplacePassword,
|
||||
instance,
|
||||
this.accessToken,
|
||||
name,
|
||||
name,
|
||||
name,
|
||||
'General BootBot',
|
||||
`${proxyAddress}/api/messages/${name}`,
|
||||
'global',
|
||||
instance.nlpAppId,
|
||||
instance.nlpKey,
|
||||
instance.marketplaceId,
|
||||
instance.marketplacePassword,
|
||||
instance.cloudSubscriptionId
|
||||
);
|
||||
|
||||
|
||||
GBLog.info(`Waiting one minute to finishing NLP service and keys creation...`);
|
||||
await sleep(60000);
|
||||
keys = await this.cognitiveClient.accounts.listKeys(name, textAnalytics.name);
|
||||
|
@ -456,7 +462,6 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
const nlpAppId = await this.createNLPService(name, name, instance.cloudLocation, culture, instance.nlpAuthoringKey);
|
||||
instance.nlpAppId = nlpAppId;
|
||||
|
||||
|
||||
GBLog.info('Updating server environment variables...');
|
||||
await this.updateWebisteConfig(name, serverName, serverFarm.id, instance);
|
||||
|
||||
|
@ -535,13 +540,14 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
luisKey: nlpKey,
|
||||
msaAppId: appId,
|
||||
msaAppPassword: appPassword,
|
||||
enabledChannels: ['webchat', "skype"],//, "facebook"],
|
||||
configuredChannels: ['webchat', "skype"]//, "facebook"]
|
||||
enabledChannels: ['webchat', 'skype'], //, "facebook"],
|
||||
configuredChannels: ['webchat', 'skype'] //, "facebook"]
|
||||
}
|
||||
};
|
||||
|
||||
const httpClient = new ServiceClient();
|
||||
let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${this.provider
|
||||
let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
|
||||
this.provider
|
||||
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
||||
let url = urlJoin(baseUrl, query);
|
||||
let req = AzureDeployerService.createRequestObject(url, accessToken, 'PUT', JSON.stringify(parameters));
|
||||
|
@ -552,10 +558,10 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
//tslint:disable-next-line:max-line-length
|
||||
query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/Microsoft.BotService/botServices/${botId}/channels/WebChatChannel/listChannelWithKeys?api-version=${this.apiVersion
|
||||
query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/Microsoft.BotService/botServices/${botId}/channels/WebChatChannel/listChannelWithKeys?api-version=${
|
||||
this.apiVersion
|
||||
}`;
|
||||
url = urlJoin(baseUrl, query);
|
||||
req = AzureDeployerService.createRequestObject(url, accessToken, 'POST', JSON.stringify(parameters));
|
||||
|
@ -567,7 +573,6 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -619,9 +624,8 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
|
||||
client.api(`/applications`).post(app, (err, res) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
}
|
||||
else {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(res);
|
||||
}
|
||||
});
|
||||
|
@ -637,15 +641,14 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
});
|
||||
const body = {
|
||||
passwordCredential: {
|
||||
displayName: "General Bots Generated"
|
||||
displayName: 'General Bots Generated'
|
||||
}
|
||||
};
|
||||
|
||||
client.api(`/applications/${appId}/addPassword`).post(body, (err, res) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
}
|
||||
else {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(res.secretText);
|
||||
}
|
||||
});
|
||||
|
@ -683,13 +686,12 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
|
||||
let app = null;
|
||||
if (apps.bodyAsText && apps.bodyAsText !== '[]') {
|
||||
const result = JSON.parse(apps.bodyAsText)
|
||||
const result = JSON.parse(apps.bodyAsText);
|
||||
if (result.error) {
|
||||
if (result.error.code !== "401") {
|
||||
if (result.error.code !== '401') {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
app = result.filter(x => x.name === name)[0];
|
||||
}
|
||||
}
|
||||
|
@ -723,14 +725,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
return await httpClient.sendRequest(req);
|
||||
}
|
||||
|
||||
public async refreshEntityList(
|
||||
location: string,
|
||||
nlpAppId: string,
|
||||
clEntityId: string,
|
||||
nlpKey: string,
|
||||
data: any,
|
||||
) {
|
||||
|
||||
public async refreshEntityList (location: string, nlpAppId: string, clEntityId: string, nlpKey: string, data: any) {
|
||||
const req = new WebResource();
|
||||
req.method = 'PUT';
|
||||
req.url = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/apps/${nlpAppId}/versions/0.1/closedlists/${clEntityId}`;
|
||||
|
@ -743,12 +738,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
return await httpClient.sendRequest(req);
|
||||
}
|
||||
|
||||
public async trainNLP(
|
||||
location: string,
|
||||
nlpAppId: string,
|
||||
nlpAuthoringKey: string,
|
||||
) {
|
||||
|
||||
public async trainNLP (location: string, nlpAppId: string, nlpAuthoringKey: string) {
|
||||
const req = new WebResource();
|
||||
req.method = 'POST';
|
||||
req.url = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/apps/${nlpAppId}/versions/0.1/train`;
|
||||
|
@ -760,16 +750,12 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
return await httpClient.sendRequest(req);
|
||||
}
|
||||
|
||||
public async publishNLP(
|
||||
location: string,
|
||||
nlpAppId: string,
|
||||
nlpAuthoringKey: string,
|
||||
) {
|
||||
public async publishNLP (location: string, nlpAppId: string, nlpAuthoringKey: string) {
|
||||
const body = {
|
||||
versionId: "0.1",
|
||||
versionId: '0.1',
|
||||
isStaging: false,
|
||||
directVersionPublish: false
|
||||
}
|
||||
};
|
||||
const req = new WebResource();
|
||||
req.method = 'POST';
|
||||
req.url = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/apps/${nlpAppId}/publish`;
|
||||
|
@ -785,8 +771,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
private async createSearch (group, name, location) {
|
||||
const params = {
|
||||
sku: {
|
||||
name:
|
||||
this.freeTier ? 'free' : 'standard'
|
||||
name: this.freeTier ? 'free' : 'standard'
|
||||
},
|
||||
location: location
|
||||
};
|
||||
|
@ -858,7 +843,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
|
||||
private async enableResourceProviders (name) {
|
||||
const ret = await this.cloud.providers.get(name);
|
||||
if (ret.registrationState === "NotRegistered") {
|
||||
if (ret.registrationState === 'NotRegistered') {
|
||||
await this.cloud.providers.register(name);
|
||||
}
|
||||
}
|
||||
|
@ -878,10 +863,8 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
}
|
||||
|
||||
private async createServer (farmId, group, name, location) {
|
||||
|
||||
let tryed = false;
|
||||
const create = async () => {
|
||||
|
||||
const parameters: Site = {
|
||||
location: location,
|
||||
serverFarmId: farmId,
|
||||
|
@ -930,7 +913,6 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
}
|
||||
|
||||
private async updateWebisteConfig (group, name, serverFarmId, instance: IGBInstance) {
|
||||
|
||||
const parameters: Site = {
|
||||
location: instance.cloudLocation,
|
||||
serverFarmId: serverFarmId,
|
||||
|
@ -953,12 +935,11 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
{ name: 'STORAGE_NAME', value: `${instance.storageName}` },
|
||||
{ name: 'STORAGE_USERNAME', value: `${instance.storageUsername}` },
|
||||
{ name: 'STORAGE_PASSWORD', value: `${instance.storagePassword}` },
|
||||
{ name: 'STORAGE_SYNC', value: `true` }]
|
||||
|
||||
{ name: 'STORAGE_SYNC', value: `true` }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
return await this.webSiteClient.webApps.beginCreateOrUpdateAndWait(group, name, parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,15 +39,15 @@
|
|||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||
import { GuaribasSchedule } from '../core.gbapp/models/GBModel.js';
|
||||
import { Sequelize } from 'sequelize-typescript';
|
||||
import { createServerRouter } from "typescript-rest-rpc/lib/server.js"
|
||||
import { createServerRouter } from 'typescript-rest-rpc/lib/server.js';
|
||||
import { DialogKeywords } from './services/DialogKeywords.js';
|
||||
import * as koaBody from "koa-body"
|
||||
import * as koaBody from 'koa-body';
|
||||
import { SystemKeywords } from './services/SystemKeywords.js';
|
||||
import { WebAutomationKeywords } from './services/WebAutomationKeywords.js';
|
||||
import { DebuggerService } from './services/DebuggerService.js';
|
||||
import Koa from 'koa';
|
||||
|
||||
const app = new Koa()
|
||||
const app = new Koa();
|
||||
|
||||
/**
|
||||
* Package for core.gbapp.
|
||||
|
@ -55,8 +55,7 @@ const app = new Koa()
|
|||
|
||||
export class GBBasicPackage implements IGBPackage {
|
||||
public sysPackages: IGBPackage[];
|
||||
public CurrentEngineName = "guaribas-1.0.0";
|
||||
|
||||
public CurrentEngineName = 'guaribas-1.0.0';
|
||||
|
||||
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||
core.sequelize.addModels([GuaribasSchedule]);
|
||||
|
|
|
@ -54,26 +54,24 @@ import { GuaribasInstance } from '../../core.gbapp/models/GBModel.js';
|
|||
@Table
|
||||
//tslint:disable-next-line:max-classes-per-file
|
||||
export class GuaribasSchedule extends Model<GuaribasSchedule> {
|
||||
@Column(DataType.STRING(255))
|
||||
name: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare name: string;
|
||||
|
||||
@Column (DataType.STRING(255))
|
||||
declare schedule: string;
|
||||
schedule: string;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasInstance)
|
||||
declare instance: GuaribasInstance;
|
||||
instance: GuaribasInstance;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@CreatedAt
|
||||
declare createdAt: Date;
|
||||
createdAt: Date;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@UpdatedAt
|
||||
declare updatedAt: Date;
|
||||
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
|
|
@ -32,11 +32,9 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
|
||||
import { createBrowser } from '../../core.gbapp/services/GBSSR.js';
|
||||
|
||||
export class ChartServices {
|
||||
|
||||
/**
|
||||
* Generate chart image screenshot
|
||||
* @param {object} options billboard.js generation option object
|
||||
|
@ -47,12 +45,12 @@ export class ChartServices {
|
|||
const page = await browser.newPage();
|
||||
|
||||
// load billboard.js assets from CDN.
|
||||
await page.addStyleTag({ url: "https://cdn.jsdelivr.net/npm/billboard.js/dist/theme/datalab.min.css" });
|
||||
await page.addScriptTag({ url: "https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.pkgd.min.js" });
|
||||
await page.addStyleTag({ url: 'https://cdn.jsdelivr.net/npm/billboard.js/dist/theme/datalab.min.css' });
|
||||
await page.addScriptTag({ url: 'https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.pkgd.min.js' });
|
||||
|
||||
await page.evaluate(`bb.generate(${JSON.stringify(args)});`);
|
||||
|
||||
const content = await page.$(".bb");
|
||||
const content = await page.$('.bb');
|
||||
|
||||
await content.screenshot({
|
||||
path,
|
||||
|
|
|
@ -75,7 +75,6 @@ export class DebuggerService {
|
|||
debugWeb: boolean;
|
||||
lastDebugWeb: Date;
|
||||
|
||||
|
||||
/**
|
||||
* SYSTEM account maxLines,when used with impersonated contexts (eg. running in SET SCHEDULE).
|
||||
*/
|
||||
|
@ -190,7 +189,7 @@ export class DebuggerService {
|
|||
GBServer.globals.debuggers[botId] = {};
|
||||
GBServer.globals.debuggers[botId].state = 0;
|
||||
GBServer.globals.debuggers[botId].breaks = [];
|
||||
GBServer.globals.debuggers[botId].stateInfo = "Stopped";
|
||||
GBServer.globals.debuggers[botId].stateInfo = 'Stopped';
|
||||
GBServer.globals.debuggers[botId].childProcess = null;
|
||||
}
|
||||
|
||||
|
@ -206,7 +205,7 @@ export class DebuggerService {
|
|||
const client = GBServer.globals.debuggers[botId].client;
|
||||
await client.Debugger.resume();
|
||||
GBServer.globals.debuggers[botId].state = 1;
|
||||
GBServer.globals.debuggers[botId].stateInfo = "Running (Debug)";
|
||||
GBServer.globals.debuggers[botId].stateInfo = 'Running (Debug)';
|
||||
return { status: 'OK' };
|
||||
} else {
|
||||
const error = 'Invalid call to resume and state not being debug(2).';
|
||||
|
@ -216,7 +215,7 @@ export class DebuggerService {
|
|||
|
||||
public async stop ({ botId }) {
|
||||
GBServer.globals.debuggers[botId].state = 0;
|
||||
GBServer.globals.debuggers[botId].stateInfo = "Stopped";
|
||||
GBServer.globals.debuggers[botId].stateInfo = 'Stopped';
|
||||
|
||||
const kill = ref => {
|
||||
spawn('sh', ['-c', `pkill -9 -f ${ref}`]);
|
||||
|
@ -229,7 +228,7 @@ export class DebuggerService {
|
|||
|
||||
public async step ({ botId }) {
|
||||
if (GBServer.globals.debuggers[botId].state === 2) {
|
||||
GBServer.globals.debuggers[botId].stateInfo = "Break";
|
||||
GBServer.globals.debuggers[botId].stateInfo = 'Break';
|
||||
const client = GBServer.globals.debuggers[botId].client;
|
||||
await client.Debugger.stepOver();
|
||||
return { status: 'OK' };
|
||||
|
@ -275,8 +274,7 @@ export class DebuggerService {
|
|||
public async getRunning ({ botId, botApiKey, scriptName }) {
|
||||
let error;
|
||||
botId = botId[0]; // TODO: Handle call in POST.
|
||||
if (!GBServer.globals.debuggers[botId])
|
||||
{
|
||||
if (!GBServer.globals.debuggers[botId]) {
|
||||
GBServer.globals.debuggers[botId] = {};
|
||||
}
|
||||
|
||||
|
@ -294,7 +292,7 @@ export class DebuggerService {
|
|||
} else {
|
||||
GBLog.info(`BASIC: Running ${botId} in DEBUG mode.`);
|
||||
GBServer.globals.debuggers[botId].state = 1;
|
||||
GBServer.globals.debuggers[botId].stateInfo = "Running (Debug)";
|
||||
GBServer.globals.debuggers[botId].stateInfo = 'Running (Debug)';
|
||||
|
||||
let min: GBMinInstance = GBServer.globals.minInstances.filter(p => p.instance.botId === botId)[0];
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ import qrcode from 'qrcode';
|
|||
* Base services of conversation to be called by BASIC.
|
||||
*/
|
||||
export class DialogKeywords {
|
||||
|
||||
/**
|
||||
* Reference to minimal bot instance.
|
||||
*/
|
||||
|
@ -116,12 +115,7 @@ export class DialogKeywords {
|
|||
this.user = user;
|
||||
this.internalSys = new SystemKeywords(min, deployer, this, null);
|
||||
|
||||
this.debugWeb = this.min.core.getParam<boolean>(
|
||||
this.min.instance,
|
||||
'Debug Web Automation',
|
||||
false
|
||||
);
|
||||
|
||||
this.debugWeb = this.min.core.getParam<boolean>(this.min.instance, 'Debug Web Automation', false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -146,11 +140,9 @@ export class DialogKeywords {
|
|||
* @see https://www.npmjs.com/package/plot
|
||||
*/
|
||||
public async chart ({ type, data, legends, transpose }) {
|
||||
|
||||
let table = [[]];
|
||||
|
||||
if (legends) {
|
||||
|
||||
const legends_ = legends.split(';');
|
||||
|
||||
// Columns and data are merged like:
|
||||
|
@ -163,26 +155,22 @@ export class DialogKeywords {
|
|||
table[i] = [legends_[i]];
|
||||
table[i] = table[i].concat(data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
table = SystemKeywords.JSONAsGBTable(data, false);
|
||||
table.shift();
|
||||
}
|
||||
|
||||
if (transpose) {
|
||||
const transpose = (array) => {
|
||||
return array.reduce((prev, next) => next.map((item, i) =>
|
||||
(prev[i] || []).concat(next[i])
|
||||
), []);
|
||||
}
|
||||
const transpose = array => {
|
||||
return array.reduce((prev, next) => next.map((item, i) => (prev[i] || []).concat(next[i])), []);
|
||||
};
|
||||
table = transpose(table);
|
||||
}
|
||||
|
||||
|
||||
let definition = {
|
||||
size: {
|
||||
"height": 420,
|
||||
"width": 680
|
||||
height: 420,
|
||||
width: 680
|
||||
},
|
||||
data: {
|
||||
columns: table,
|
||||
|
@ -201,7 +189,7 @@ export class DialogKeywords {
|
|||
tick: {
|
||||
format: '%Y-%m-%d'
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const gbaiName = `${this.min.botId}.gbai`;
|
||||
|
@ -209,12 +197,7 @@ export class DialogKeywords {
|
|||
|
||||
await ChartServices.screenshot(definition, localName);
|
||||
|
||||
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));
|
||||
|
||||
GBLog.info(`BASIC: Visualization: Chart generated at ${url}.`);
|
||||
|
||||
|
@ -228,12 +211,11 @@ export class DialogKeywords {
|
|||
public async getOCR ({ localFile }) {
|
||||
GBLog.info(`BASIC: OCR processing on ${localFile}.`);
|
||||
|
||||
|
||||
const config = {
|
||||
lang: "eng",
|
||||
lang: 'eng',
|
||||
oem: 1,
|
||||
psm: 3,
|
||||
}
|
||||
psm: 3
|
||||
};
|
||||
|
||||
return await tesseract.recognize(localFile, config);
|
||||
}
|
||||
|
@ -249,8 +231,12 @@ export class DialogKeywords {
|
|||
day = '' + d.getDate(),
|
||||
year = d.getFullYear();
|
||||
|
||||
if (month.length < 2) { month = '0' + month; }
|
||||
if (day.length < 2) { day = '0' + day; }
|
||||
if (month.length < 2) {
|
||||
month = '0' + month;
|
||||
}
|
||||
if (day.length < 2) {
|
||||
day = '0' + day;
|
||||
}
|
||||
|
||||
const contentLocale = this.min.core.getParam<string>(
|
||||
this.min.instance,
|
||||
|
@ -275,34 +261,28 @@ export class DialogKeywords {
|
|||
*
|
||||
* @example EXIT
|
||||
*/
|
||||
public async exit({}) {
|
||||
|
||||
}
|
||||
public async exit ({}) {}
|
||||
|
||||
/**
|
||||
* Get active tasks.
|
||||
*
|
||||
* @example list = ACTIVE TASKS
|
||||
*/
|
||||
public async getActiveTasks({}) {
|
||||
}
|
||||
public async getActiveTasks ({}) {}
|
||||
|
||||
/**
|
||||
* Creates a new deal.
|
||||
*
|
||||
* @example CREATE DEAL dealname,contato,empresa,amount
|
||||
*/
|
||||
public async createDeal({dealName, contact, company, amount}) {
|
||||
}
|
||||
public async createDeal ({ dealName, contact, company, amount }) {}
|
||||
|
||||
/**
|
||||
* Finds contacts in XRM.
|
||||
*
|
||||
* @example list = FIND CONTACT "Sandra"
|
||||
*/
|
||||
public async fndContact({name}) {
|
||||
}
|
||||
|
||||
public async fndContact ({ name }) {}
|
||||
|
||||
public getContentLocaleWithCulture (contentLocale) {
|
||||
switch (contentLocale) {
|
||||
|
@ -315,18 +295,16 @@ export class DialogKeywords {
|
|||
default:
|
||||
return 'en-us';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async getCoded ({ value }) {
|
||||
|
||||
// Checks if it is a GB FILE object.
|
||||
|
||||
if (value.data && value.filename) {
|
||||
value = value.data;
|
||||
}
|
||||
|
||||
return Buffer.from(value).toString("base64");
|
||||
return Buffer.from(value).toString('base64');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -336,7 +314,6 @@ export class DialogKeywords {
|
|||
*
|
||||
*/
|
||||
public getWeekFromDate (date) {
|
||||
|
||||
const contentLocale = this.min.core.getParam<string>(
|
||||
this.min.instance,
|
||||
'Default Content Language',
|
||||
|
@ -376,12 +353,18 @@ export class DialogKeywords {
|
|||
}
|
||||
const diff = new DateDiff(date1, date2);
|
||||
switch (mode) {
|
||||
case 'year': return diff.years();
|
||||
case 'month': return diff.months();
|
||||
case 'week': return diff.weeks();
|
||||
case 'day': return diff.days();
|
||||
case 'hour': return diff.hours();
|
||||
case 'minute': return diff.minutes();
|
||||
case 'year':
|
||||
return diff.years();
|
||||
case 'month':
|
||||
return diff.months();
|
||||
case 'week':
|
||||
return diff.weeks();
|
||||
case 'day':
|
||||
return diff.days();
|
||||
case 'hour':
|
||||
return diff.hours();
|
||||
case 'minute':
|
||||
return diff.minutes();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -398,23 +381,44 @@ export class DialogKeywords {
|
|||
dateCopy = new Date(dateCopy);
|
||||
}
|
||||
var ret = new Date(dateCopy); //don't change original date
|
||||
var checkRollover = function () { if (ret.getDate() != date.getDate()) ret.setDate(0); };
|
||||
var checkRollover = function () {
|
||||
if (ret.getDate() != date.getDate()) ret.setDate(0);
|
||||
};
|
||||
switch (String(mode).toLowerCase()) {
|
||||
case 'year': ret.setFullYear(ret.getFullYear() + units); checkRollover(); break;
|
||||
case 'quarter': ret.setMonth(ret.getMonth() + 3 * units); checkRollover(); break;
|
||||
case 'month': ret.setMonth(ret.getMonth() + units); checkRollover(); break;
|
||||
case 'week': ret.setDate(ret.getDate() + 7 * units); break;
|
||||
case 'day': ret.setDate(ret.getDate() + units); break;
|
||||
case 'hour': ret.setTime(ret.getTime() + units * 3600000); break;
|
||||
case 'minute': ret.setTime(ret.getTime() + units * 60000); break;
|
||||
case 'second': ret.setTime(ret.getTime() + units * 1000); break;
|
||||
default: ret = undefined; break;
|
||||
case 'year':
|
||||
ret.setFullYear(ret.getFullYear() + units);
|
||||
checkRollover();
|
||||
break;
|
||||
case 'quarter':
|
||||
ret.setMonth(ret.getMonth() + 3 * units);
|
||||
checkRollover();
|
||||
break;
|
||||
case 'month':
|
||||
ret.setMonth(ret.getMonth() + units);
|
||||
checkRollover();
|
||||
break;
|
||||
case 'week':
|
||||
ret.setDate(ret.getDate() + 7 * units);
|
||||
break;
|
||||
case 'day':
|
||||
ret.setDate(ret.getDate() + units);
|
||||
break;
|
||||
case 'hour':
|
||||
ret.setTime(ret.getTime() + units * 3600000);
|
||||
break;
|
||||
case 'minute':
|
||||
ret.setTime(ret.getTime() + units * 60000);
|
||||
break;
|
||||
case 'second':
|
||||
ret.setTime(ret.getTime() + units * 1000);
|
||||
break;
|
||||
default:
|
||||
ret = undefined;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns specified list member separated by comma.
|
||||
*
|
||||
|
@ -423,15 +427,19 @@ export class DialogKeywords {
|
|||
*/
|
||||
public getToLst (array, member) {
|
||||
if (!array) {
|
||||
return "<Empty>"
|
||||
return '<Empty>';
|
||||
}
|
||||
if (array[0] && array[0]['gbarray']) {
|
||||
array = array.slice(1);
|
||||
}
|
||||
array = array.filter((v, i, a) => a.findIndex(t => (t[member] === v[member])) === i);
|
||||
array = array.filter(function (item, pos) { return item != undefined; });
|
||||
array = array.map((item) => { return item[member]; })
|
||||
array = array.join(",");
|
||||
array = array.filter((v, i, a) => a.findIndex(t => t[member] === v[member]) === i);
|
||||
array = array.filter(function (item, pos) {
|
||||
return item != undefined;
|
||||
});
|
||||
array = array.map(item => {
|
||||
return item[member];
|
||||
});
|
||||
array = array.join(',');
|
||||
|
||||
return array;
|
||||
}
|
||||
|
@ -445,7 +453,7 @@ export class DialogKeywords {
|
|||
public getHourFromDate (date) {
|
||||
function addZero (i) {
|
||||
if (i < 10) {
|
||||
i = "0" + i;
|
||||
i = '0' + i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
@ -481,17 +489,15 @@ export class DialogKeywords {
|
|||
);
|
||||
|
||||
const nowUTC = new Date();
|
||||
const now = typeof nowUTC === 'string' ?
|
||||
new Date(nowUTC) :
|
||||
nowUTC;
|
||||
const now = typeof nowUTC === 'string' ? new Date(nowUTC) : nowUTC;
|
||||
|
||||
const nowText = now.toLocaleString(this.getContentLocaleWithCulture(contentLocale),
|
||||
{ timeZone: process.env.DEFAULT_TIMEZONE });
|
||||
const nowText = now.toLocaleString(this.getContentLocaleWithCulture(contentLocale), {
|
||||
timeZone: process.env.DEFAULT_TIMEZONE
|
||||
});
|
||||
|
||||
return /\b([0-9]|0[0-9]|1?[0-9]|2[0-3]):[0-5]?[0-9]/.exec(nowText)[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends an e-mail.
|
||||
*
|
||||
|
@ -501,7 +507,6 @@ export class DialogKeywords {
|
|||
*
|
||||
*/
|
||||
public async sendEmail ({ to, subject, body }) {
|
||||
|
||||
// tslint:disable-next-line:no-console
|
||||
|
||||
GBLog.info(`[E-mail]: to:${to},subject: ${subject},body: ${body}.`);
|
||||
|
@ -509,7 +514,7 @@ export class DialogKeywords {
|
|||
|
||||
// Inline word document used as e-mail body.
|
||||
|
||||
if (typeof (body) === "object") {
|
||||
if (typeof body === 'object') {
|
||||
const result = await mammoth.convertToHtml({ buffer: body });
|
||||
body = result.value;
|
||||
}
|
||||
|
@ -525,9 +530,8 @@ export class DialogKeywords {
|
|||
};
|
||||
sgMail.send(msg, false, (err, res) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
}
|
||||
else {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(res);
|
||||
}
|
||||
});
|
||||
|
@ -588,13 +592,11 @@ export class DialogKeywords {
|
|||
public async setMaxLines ({ count }) {
|
||||
if (this.user) {
|
||||
// TODO: PARAM user.basicOptions.maxLines = count;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.maxLines = count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines the maximum lines to scan in spreedsheets.
|
||||
*
|
||||
|
@ -603,10 +605,8 @@ export class DialogKeywords {
|
|||
*/
|
||||
public async setMaxColumns ({ count }) {
|
||||
// TODO: user.basicOptions.maxColumns = count;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines the FIND behaviour to consider whole words while searching.
|
||||
*
|
||||
|
@ -634,11 +634,9 @@ export class DialogKeywords {
|
|||
*
|
||||
*/
|
||||
public async setTranslatorOn ({ on }) {
|
||||
|
||||
// TODO: user.basicOptions.translatorOn = (on.trim() === "on");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the user acquired by WhatsApp API.
|
||||
*/
|
||||
|
@ -665,14 +663,11 @@ export class DialogKeywords {
|
|||
// TODO: return await beginDialog('/menu');
|
||||
}
|
||||
private static async downloadAttachmentAndWrite (attachment) {
|
||||
|
||||
|
||||
const url = attachment.contentUrl;
|
||||
const localFolder = Path.join('work'); // TODO: ,'${botId}','uploads');
|
||||
const localFileName = Path.join(localFolder, attachment.name);
|
||||
|
||||
try {
|
||||
|
||||
let response;
|
||||
if (url.startsWith('data:')) {
|
||||
var regex = /^data:.+\/(.+);base64,(.*)$/;
|
||||
|
@ -680,18 +675,17 @@ export class DialogKeywords {
|
|||
var ext = matches[1];
|
||||
var data = matches[2];
|
||||
response = Buffer.from(data, 'base64');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// arraybuffer is necessary for images
|
||||
const options = {
|
||||
url: url,
|
||||
method: 'GET',
|
||||
encoding: 'binary',
|
||||
encoding: 'binary'
|
||||
};
|
||||
response = await request.get(options);
|
||||
}
|
||||
|
||||
Fs.writeFile(localFileName, response, (fsError) => {
|
||||
Fs.writeFile(localFileName, response, fsError => {
|
||||
if (fsError) {
|
||||
throw fsError;
|
||||
}
|
||||
|
@ -725,7 +719,6 @@ export class DialogKeywords {
|
|||
*
|
||||
*/
|
||||
public async getHear ({ kind, arg }) {
|
||||
|
||||
// Handles first arg as an array of args.
|
||||
|
||||
let args = [];
|
||||
|
@ -733,19 +726,16 @@ export class DialogKeywords {
|
|||
args = arg;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
|
||||
let user;
|
||||
const isIntentYes = (locale, utterance) => {
|
||||
return utterance.toLowerCase().match(Messages[locale].affirmative_sentences);
|
||||
}
|
||||
};
|
||||
|
||||
if (this.hrOn) {
|
||||
const sec = new SecService();
|
||||
user = await sec.getUserFromAgentSystemId(this.hrOn)
|
||||
}
|
||||
else {
|
||||
user = await sec.getUserFromAgentSystemId(this.hrOn);
|
||||
} else {
|
||||
user = this.user.systemUser;
|
||||
}
|
||||
const userId = user.userId;
|
||||
|
@ -755,7 +745,6 @@ export class DialogKeywords {
|
|||
// TODO: https://github.com/GeneralBots/BotServer/issues/266
|
||||
|
||||
if (args && args.length > 1) {
|
||||
|
||||
let choices = [];
|
||||
let i = 0;
|
||||
await CollectionUtil.asyncForEach(args, async arg => {
|
||||
|
@ -768,9 +757,7 @@ export class DialogKeywords {
|
|||
// TODO: await this.talk(button);
|
||||
|
||||
GBLog.info(`BASIC: HEAR with [${args.toString()}] (Asking for input).`);
|
||||
}
|
||||
else {
|
||||
|
||||
} else {
|
||||
GBLog.info('BASIC: HEAR (Asking for input).');
|
||||
}
|
||||
|
||||
|
@ -781,7 +768,7 @@ export class DialogKeywords {
|
|||
setTimeout(resolve, ms);
|
||||
});
|
||||
};
|
||||
this.min.cbMap[userId] = {}
|
||||
this.min.cbMap[userId] = {};
|
||||
this.min.cbMap[userId]['promise'] = '!GBHEAR';
|
||||
|
||||
while (this.min.cbMap[userId].promise === '!GBHEAR') {
|
||||
|
@ -790,14 +777,12 @@ export class DialogKeywords {
|
|||
|
||||
const text = this.min.cbMap[userId].promise;
|
||||
|
||||
if (kind === "file") {
|
||||
if (kind === 'file') {
|
||||
// await prompt('attachmentPrompt',{});
|
||||
|
||||
// // Prepare Promises to download each attachment and then execute each Promise.
|
||||
// const promises = step.context.activity.attachments.map(
|
||||
// DialogKeywords.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
|
||||
|
@ -807,43 +792,34 @@ export class DialogKeywords {
|
|||
// await this.sendActivity('Error uploading file. Please,start again.');
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Prepare Promises to reply to the user with information about saved attachments.
|
||||
// // 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 (kind === "boolean") {
|
||||
} else if (kind === 'boolean') {
|
||||
if (isIntentYes('pt-BR', text)) {
|
||||
result = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else if (kind === "email") {
|
||||
|
||||
const extractEntity = (text) => {
|
||||
} else if (kind === 'email') {
|
||||
const extractEntity = text => {
|
||||
return text.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/gi);
|
||||
}
|
||||
};
|
||||
|
||||
const value = extractEntity(text);
|
||||
|
||||
if (value === null) {
|
||||
await this.talk({text: "Por favor,digite um e-mail válido."});
|
||||
await this.talk({ text: 'Por favor,digite um e-mail válido.' });
|
||||
return await this.getHear({ kind, arg });
|
||||
}
|
||||
|
||||
result = value;
|
||||
|
||||
}
|
||||
else if (kind === "name") {
|
||||
} else if (kind === 'name') {
|
||||
const extractEntity = text => {
|
||||
return text.match(/[_a-zA-Z][_a-zA-Z0-9]{0,16}/gi);
|
||||
};
|
||||
|
@ -851,14 +827,12 @@ export class DialogKeywords {
|
|||
const value = extractEntity(text);
|
||||
|
||||
if (value === null || value.length != 1) {
|
||||
await this.talk({text:"Por favor,digite um nome válido."});
|
||||
await this.talk({ text: 'Por favor,digite um nome válido.' });
|
||||
return await this.getHear({ kind, arg });
|
||||
}
|
||||
|
||||
result = value;
|
||||
|
||||
}
|
||||
else if (kind === "integer") {
|
||||
} else if (kind === 'integer') {
|
||||
const extractEntity = text => {
|
||||
return text.match(/\d+/gi);
|
||||
};
|
||||
|
@ -866,28 +840,27 @@ export class DialogKeywords {
|
|||
const value = extractEntity(text);
|
||||
|
||||
if (value === null || value.length != 1) {
|
||||
await this.talk({text:"Por favor,digite um número válido."});
|
||||
await this.talk({ text: 'Por favor,digite um número válido.' });
|
||||
return await this.getHear({ kind, arg });
|
||||
}
|
||||
|
||||
result = value;
|
||||
}
|
||||
else if (kind === "date") {
|
||||
} else if (kind === 'date') {
|
||||
const extractEntity = text => {
|
||||
return text.match(/(^(((0[1-9]|1[0-9]|2[0-8])[\/](0[1-9]|1[012]))|((29|30|31)[\/](0[13578]|1[02]))|((29|30)[\/](0[4,6,9]|11)))[\/](19|[2-9][0-9])\d\d$)|(^29[\/]02[\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)/gi);
|
||||
return text.match(
|
||||
/(^(((0[1-9]|1[0-9]|2[0-8])[\/](0[1-9]|1[012]))|((29|30|31)[\/](0[13578]|1[02]))|((29|30)[\/](0[4,6,9]|11)))[\/](19|[2-9][0-9])\d\d$)|(^29[\/]02[\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)/gi
|
||||
);
|
||||
};
|
||||
|
||||
const value = extractEntity(text);
|
||||
|
||||
if (value === null || value.length != 1) {
|
||||
await this.talk({text:"Por favor,digite uma data no formato 12/12/2020."});
|
||||
await this.talk({ text: 'Por favor,digite uma data no formato 12/12/2020.' });
|
||||
return await this.getHear({ kind, arg });
|
||||
}
|
||||
|
||||
result = value;
|
||||
}
|
||||
else if (kind === "hour") {
|
||||
|
||||
} else if (kind === 'hour') {
|
||||
const extractEntity = text => {
|
||||
return text.match(/^([0-1]?[0-9]|2[0-4]):([0-5][0-9])(:[0-5][0-9])?$/gi);
|
||||
};
|
||||
|
@ -895,15 +868,13 @@ export class DialogKeywords {
|
|||
const value = extractEntity(text);
|
||||
|
||||
if (value === null || value.length != 1) {
|
||||
await this.talk({text:"Por favor,digite um horário no formato hh:ss."});
|
||||
await this.talk({ text: 'Por favor,digite um horário no formato hh:ss.' });
|
||||
return await this.getHear({ kind, arg });
|
||||
}
|
||||
|
||||
result = value;
|
||||
}
|
||||
else if (kind === "money") {
|
||||
} else if (kind === 'money') {
|
||||
const extractEntity = text => {
|
||||
|
||||
// if (user.locale === 'en') { // TODO: Change to user.
|
||||
// return text.match(/(?:\d{1,3},)*\d{1,3}(?:\.\d+)?/gi);
|
||||
// }
|
||||
|
@ -916,14 +887,12 @@ export class DialogKeywords {
|
|||
const value = extractEntity(text);
|
||||
|
||||
if (value === null || value.length != 1) {
|
||||
await this.talk({text:"Por favor,digite um valor monetário."});
|
||||
await this.talk({ text: 'Por favor,digite um valor monetário.' });
|
||||
return await this.getHear({ kind, arg });
|
||||
}
|
||||
|
||||
result = value;
|
||||
}
|
||||
else if (kind === "mobile") {
|
||||
|
||||
} else if (kind === 'mobile') {
|
||||
let phoneNumber;
|
||||
try {
|
||||
phoneNumber = phone(text, { country: 'BRA' })[0]; // TODO: Use accordingly to the person.
|
||||
|
@ -934,39 +903,32 @@ export class DialogKeywords {
|
|||
return await this.getHear({ kind, arg });
|
||||
}
|
||||
if (!phoneUtil.isPossibleNumber(phoneNumber)) {
|
||||
await this.talk({text:"Por favor,digite um número de telefone válido."});
|
||||
await this.talk({ text: 'Por favor,digite um número de telefone válido.' });
|
||||
return await this.getHear({ kind, arg });
|
||||
}
|
||||
|
||||
result = phoneNumber;
|
||||
|
||||
}
|
||||
else if (kind === "zipcode") {
|
||||
} else if (kind === 'zipcode') {
|
||||
const extractEntity = text => {
|
||||
|
||||
text = text.replace(/\-/gi, '');
|
||||
|
||||
if (user.locale === 'en') { // TODO: Change to user.
|
||||
if (user.locale === 'en') {
|
||||
// TODO: Change to user.
|
||||
return text.match(/\d{8}/gi);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return text.match(/(?:\d{1,3}.)*\d{1,3}(?:\,\d+)?/gi);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const value = extractEntity(text);
|
||||
|
||||
if (value === null || value.length != 1) {
|
||||
await this.talk({text:"Por favor, digite um CEP válido."});
|
||||
await this.talk({ text: 'Por favor, digite um CEP válido.' });
|
||||
return await this.getHear({ kind, arg });
|
||||
}
|
||||
|
||||
result = value[0];
|
||||
|
||||
}
|
||||
else if (kind === "menu") {
|
||||
|
||||
} else if (kind === 'menu') {
|
||||
const list = args;
|
||||
result = null;
|
||||
await CollectionUtil.asyncForEach(list, async item => {
|
||||
|
@ -979,9 +941,7 @@ export class DialogKeywords {
|
|||
await this.talk({ text: `Escolha por favor um dos itens sugeridos.` });
|
||||
return await this.getHear({ kind, arg });
|
||||
}
|
||||
}
|
||||
else if (kind === "language") {
|
||||
|
||||
} else if (kind === 'language') {
|
||||
result = null;
|
||||
|
||||
const list = [
|
||||
|
@ -1000,10 +960,11 @@ export class DialogKeywords {
|
|||
{ name: 'alemão', code: 'de' }
|
||||
];
|
||||
|
||||
|
||||
await CollectionUtil.asyncForEach(list, async item => {
|
||||
if (GBConversationalService.kmpSearch(text.toLowerCase(), item.name.toLowerCase()) != -1 ||
|
||||
GBConversationalService.kmpSearch(text.toLowerCase(), item.code.toLowerCase()) != -1) {
|
||||
if (
|
||||
GBConversationalService.kmpSearch(text.toLowerCase(), item.name.toLowerCase()) != -1 ||
|
||||
GBConversationalService.kmpSearch(text.toLowerCase(), item.code.toLowerCase()) != -1
|
||||
) {
|
||||
result = item.code;
|
||||
}
|
||||
});
|
||||
|
@ -1030,13 +991,19 @@ export class DialogKeywords {
|
|||
let sec = new SecService();
|
||||
let user = await sec.getUserFromSystemId(fromOrDialogName);
|
||||
if (!user) {
|
||||
user = await sec.ensureUser(this.min.instance.instanceId, fromOrDialogName,
|
||||
fromOrDialogName, null, 'whatsapp', 'from', null);
|
||||
user = await sec.ensureUser(
|
||||
this.min.instance.instanceId,
|
||||
fromOrDialogName,
|
||||
fromOrDialogName,
|
||||
null,
|
||||
'whatsapp',
|
||||
'from',
|
||||
null
|
||||
);
|
||||
}
|
||||
await sec.updateUserHearOnDialog(user.userId, dialogName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// TODO: await step.beginDialog(fromOrDialogName);
|
||||
}
|
||||
}
|
||||
|
@ -1051,10 +1018,10 @@ export class DialogKeywords {
|
|||
headers: {},
|
||||
data: {},
|
||||
list: [],
|
||||
httpUsername: "",
|
||||
httpPs: ""
|
||||
}
|
||||
httpUsername: '',
|
||||
httpPs: ''
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Talks to the user by using the specified text.
|
||||
|
@ -1064,8 +1031,7 @@ export class DialogKeywords {
|
|||
if (this.user) {
|
||||
const translate = this.user ? this.user.basicOptions.translatorOn : false;
|
||||
|
||||
await this.min.conversationalService['sendOnConversation'](this.min,
|
||||
this.user.systemUser, text);
|
||||
await this.min.conversationalService['sendOnConversation'](this.min, this.user.systemUser, text);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1074,34 +1040,26 @@ export class DialogKeywords {
|
|||
// TODO:
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Processes the sending of the file.
|
||||
*/
|
||||
private async internalSendFile ({ mobile, filename, caption }) {
|
||||
|
||||
// Handles SEND FILE TO mobile,element in Web Automation.
|
||||
|
||||
const element = filename._page ? filename._page : (filename.screenshot ? filename : null);
|
||||
const element = filename._page ? filename._page : filename.screenshot ? filename : null;
|
||||
|
||||
if (element) {
|
||||
const gbaiName = `${this.min.botId}.gbai`;
|
||||
const localName = Path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.jpg`);
|
||||
await element.screenshot({ path: localName, fullPage: true });
|
||||
|
||||
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));
|
||||
|
||||
GBLog.info(`BASIC: WebAutomation: Sending the file ${url} to mobile ${mobile}.`);
|
||||
await this.min.conversationalService.sendFile(this.min, null, mobile, url, caption);
|
||||
}
|
||||
|
||||
// Handles Markdown.
|
||||
|
||||
else if (filename.indexOf('.md') > -1) {
|
||||
GBLog.info(`BASIC: Sending the contents of ${filename} markdown to mobile ${mobile}.`);
|
||||
const md = await this.min.kbService.getAnswerTextByMediaName(this.min.instance.instanceId, filename);
|
||||
|
@ -1109,13 +1067,11 @@ export class DialogKeywords {
|
|||
GBLog.info(`BASIC: Markdown file ${filename} not found on database for ${this.min.instance.botId}.`);
|
||||
}
|
||||
|
||||
await this.min.conversationalService['playMarkdown'](this.min, md,
|
||||
DialogKeywords.getChannel(), mobile);
|
||||
|
||||
await this.min.conversationalService['playMarkdown'](this.min, md, DialogKeywords.getChannel(), mobile);
|
||||
} else {
|
||||
GBLog.info(`BASIC: Sending the file ${filename} to mobile ${mobile}.`);
|
||||
let url;
|
||||
if (!filename.startsWith("https://")) {
|
||||
if (!filename.startsWith('https://')) {
|
||||
url = urlJoin(
|
||||
GBServer.globals.publicAddress,
|
||||
'kb',
|
||||
|
@ -1124,8 +1080,7 @@ export class DialogKeywords {
|
|||
'assets',
|
||||
filename
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
url = filename;
|
||||
}
|
||||
|
||||
|
@ -1135,8 +1090,8 @@ export class DialogKeywords {
|
|||
|
||||
public async getQRCode ({ text }) {
|
||||
const img = await qrcode.toDataURL(text);
|
||||
const data = img.replace(/^data:image\/\w+;base64,/, "");
|
||||
const buf = Buffer.from(data, "base64");
|
||||
const data = img.replace(/^data:image\/\w+;base64,/, '');
|
||||
const buf = Buffer.from(data, 'base64');
|
||||
return buf;
|
||||
}
|
||||
}
|
|
@ -91,8 +91,7 @@ export class GBVMService extends GBService {
|
|||
const s = new ScheduleServices();
|
||||
if (schedule) {
|
||||
await s.createOrUpdateSchedule(min, schedule, mainName);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
await s.deleteScheduleIfAny(min, mainName);
|
||||
}
|
||||
text = text.replace(/^\s*SET SCHEDULE (.*)/gim, '');
|
||||
|
@ -155,7 +154,6 @@ export class GBVMService extends GBService {
|
|||
}
|
||||
|
||||
public async translateBASIC (filename: any, min: GBMinInstance, deployer: GBDeployer, mainName: string) {
|
||||
|
||||
// Converts General Bots BASIC into regular VBS
|
||||
|
||||
let basicCode: string = Fs.readFileSync(filename, 'utf8');
|
||||
|
@ -165,8 +163,7 @@ export class GBVMService extends GBService {
|
|||
|
||||
if (process.env.GBDIALOG_NOEND === 'true') {
|
||||
basicCode = basicCode.replace(/^\s*END(\W|\n)/gim, '');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let end = /^\s*END(\W|\n)/gi.exec(basicCode);
|
||||
if (end) {
|
||||
basicCode = basicCode.substring(0, end.index);
|
||||
|
@ -183,18 +180,18 @@ export class GBVMService extends GBService {
|
|||
|
||||
let include = null;
|
||||
do {
|
||||
include = /^include\b(.*)$/gmi.exec(basicCode);
|
||||
include = /^include\b(.*)$/gim.exec(basicCode);
|
||||
|
||||
if (include) {
|
||||
let includeName = include[1].trim();
|
||||
includeName = Path.join(Path.dirname(filename), includeName);
|
||||
includeName = includeName.substr(0, includeName.lastIndexOf(".")) + ".vbs";
|
||||
includeName = includeName.substr(0, includeName.lastIndexOf('.')) + '.vbs';
|
||||
|
||||
// To use include, two /publish will be necessary (for now)
|
||||
// because of alphabet order may raise not found errors.
|
||||
|
||||
let includeCode: string = Fs.readFileSync(includeName, 'utf8');
|
||||
basicCode = basicCode.replace(/^include\b.*$/gmi, includeCode);
|
||||
basicCode = basicCode.replace(/^include\b.*$/gim, includeCode);
|
||||
}
|
||||
} while (include);
|
||||
|
||||
|
@ -285,8 +282,7 @@ export class GBVMService extends GBService {
|
|||
}
|
||||
|
||||
public static getSetScheduleKeywordArgs (code: string) {
|
||||
if (!code)
|
||||
return null;
|
||||
if (!code) return null;
|
||||
const keyword = /^\s*SET SCHEDULE (.*)/gim;
|
||||
const result = keyword.exec(code);
|
||||
return result ? result[1] : null;
|
||||
|
@ -310,21 +306,23 @@ export class GBVMService extends GBService {
|
|||
}
|
||||
|
||||
private getParams = (text, names) => {
|
||||
|
||||
let ret = {};
|
||||
const splitParamsButIgnoreCommasInDoublequotes = (str) => {
|
||||
return str.split(',').reduce((accum, curr) => {
|
||||
const splitParamsButIgnoreCommasInDoublequotes = str => {
|
||||
return str.split(',').reduce(
|
||||
(accum, curr) => {
|
||||
if (accum.isConcatting) {
|
||||
accum.soFar[accum.soFar.length - 1] += ',' + curr
|
||||
accum.soFar[accum.soFar.length - 1] += ',' + curr;
|
||||
} else {
|
||||
accum.soFar.push(curr)
|
||||
accum.soFar.push(curr);
|
||||
}
|
||||
if (curr.split('"').length % 2 == 0) {
|
||||
accum.isConcatting = !accum.isConcatting
|
||||
accum.isConcatting = !accum.isConcatting;
|
||||
}
|
||||
return accum;
|
||||
}, { soFar: [], isConcatting: false }).soFar
|
||||
}
|
||||
},
|
||||
{ soFar: [], isConcatting: false }
|
||||
).soFar;
|
||||
};
|
||||
|
||||
const items = splitParamsButIgnoreCommasInDoublequotes(text);
|
||||
|
||||
|
@ -335,12 +333,11 @@ export class GBVMService extends GBService {
|
|||
i++;
|
||||
json = `${json} "${name}": ${value} ${names.length == i ? '' : ','}`;
|
||||
});
|
||||
json = `${json}}`
|
||||
json = `${json}}`;
|
||||
|
||||
return json;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts General Bots BASIC
|
||||
*
|
||||
|
@ -348,7 +345,6 @@ export class GBVMService extends GBService {
|
|||
* @param code General Bots BASIC
|
||||
*/
|
||||
public async convertGBASICToVBS (min: GBMinInstance, code: string) {
|
||||
|
||||
// Start and End of VB2TS tags of processing.
|
||||
|
||||
code = `<%\n
|
||||
|
@ -359,7 +355,7 @@ export class GBVMService extends GBService {
|
|||
|
||||
`;
|
||||
|
||||
var allLines = code.split("\n");
|
||||
var allLines = code.split('\n');
|
||||
const keywords = this.getKeywords();
|
||||
const offset = 34;
|
||||
const jsonMap = {};
|
||||
|
@ -371,7 +367,7 @@ export class GBVMService extends GBService {
|
|||
// Add additional lines returned from replacement.
|
||||
|
||||
let add = allLines[i].split(/\r\n|\r|\n/).length;
|
||||
jsonMap[i] = (offset + i) + (add ? add : 0);
|
||||
jsonMap[i] = offset + i + (add ? add : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,391 +376,616 @@ export class GBVMService extends GBService {
|
|||
}
|
||||
|
||||
private getKeywords () {
|
||||
|
||||
// Keywords from General Bots BASIC.
|
||||
|
||||
let keywords = [];
|
||||
let i = 0;
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*SELECT\s*(.*)/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*SELECT\s*(.*)/gim,
|
||||
($0, $1, $2) => {
|
||||
let tableName = /\sFROM\s(\w+)/.exec($2)[1];
|
||||
let sql = `SELECT ${$2}`.replace(tableName, '?');
|
||||
return `${$1} = await sys.executeSQL({data:${$1}, sql:"${sql}", tableName:"${tableName}"})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*open\s*(.*)/gim, ($0, $1, $2) => {
|
||||
|
||||
if (!$1.startsWith("\"") && !$1.startsWith("\'")) {
|
||||
keywords[i++] = [
|
||||
/^\s*open\s*(.*)/gim,
|
||||
($0, $1, $2) => {
|
||||
if (!$1.startsWith('"') && !$1.startsWith("'")) {
|
||||
$1 = `"${$1}"`;
|
||||
}
|
||||
const params = this.getParams($1, ['url', 'username', 'password']);
|
||||
|
||||
return `page = await wa.getPage(${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(set hear on)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(set hear on)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `hrOn = ${$3}\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as login/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as login/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getHear({kind:"login"})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as email/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as email/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getHear({kind:"email"})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as integer/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as integer/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getHear({kind:"integer"})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as file/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as file/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getHear({kind:"file"})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as boolean/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as boolean/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getHear({kind:"boolean"})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as name/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as name/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getHear({kind:"name"})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as date/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as date/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getHear({kind:"date"})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as hour/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as hour/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getHear({kind:"hour"})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as phone/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as phone/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getHear({kind:"phone"})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as money/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as money/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getHear({kind:"money")}`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as language/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as language/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getHear({kind:"language")}`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as zipcode/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as zipcode/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getHear({kind:"zipcode")}`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\shear (\w+) as (.*)/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\shear (\w+) as (.*)/gim,
|
||||
($0, $1, $2) => {
|
||||
return `${$1} = await dk.getHear({kind:"menu", args: [${$2}])}`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(hear)\s*(\w+)/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(hear)\s*(\w+)/gim,
|
||||
($0, $1, $2) => {
|
||||
return `${$2} = await dk.getHear({})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*find contact\s*(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*find contact\s*(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `${$1} = await dk.fndContact({${$2})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*=\s*find\s*(.*)\s*or talk\s*(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*=\s*find\s*(.*)\s*or talk\s*(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `${$1} = await sys.find({args:[${$2}])\n
|
||||
if (!${$1}) {
|
||||
await dk.talk ({${$3}})\n;
|
||||
return -1;
|
||||
}
|
||||
`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\sCALL\s*(.*)/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\sCALL\s*(.*)/gim,
|
||||
($0, $1) => {
|
||||
return `await ${$1}\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*find\s*(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*find\s*(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `
|
||||
${$1} = await sys.find({args: [${$2}]})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*create deal(\s)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*create deal(\s)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['dealName', 'contact', 'company', 'amount']);
|
||||
|
||||
return `${$1} = await dk.createDeal(${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*active tasks/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*active tasks/gim,
|
||||
($0, $1) => {
|
||||
return `${$1} = await dk.getActiveTasks({})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*append\s*(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*append\s*(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `${$1} = await sys.append({args:[${$2}]})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*sort\s*(\w+)\s*by(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*sort\s*(\w+)\s*by(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `${$1} = await sys.sortBy({array: ${$2}, memberName: "${$3}"})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\ssee\s*text\s*of\s*(\w+)\s*as\s*(\w+)\s*/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\ssee\s*text\s*of\s*(\w+)\s*as\s*(\w+)\s*/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `${$2} = await sys.seeText({url: ${$1})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\ssee\s*caption\s*of\s*(\w+)\s*as(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\ssee\s*caption\s*of\s*(\w+)\s*as(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `${$2} = await sys.seeCaption({url: ${$1})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(wait)\s*(\d+)/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(wait)\s*(\d+)/gim,
|
||||
($0, $1, $2) => {
|
||||
return `await sys.wait({seconds:${$2}})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(get stock for )(.*)/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(get stock for )(.*)/gim,
|
||||
($0, $1, $2) => {
|
||||
return `stock = await sys.getStock({symbol: ${$2})`;
|
||||
}];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*get\s(.*)/gim, ($0, $1, $2, $3) => {
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*get\s(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const count = ($2.match(/\,/g) || []).length;
|
||||
const values = $2.split(',');
|
||||
|
||||
// Handles GET "selector".
|
||||
|
||||
if (count == 1) {
|
||||
|
||||
return `${$1} = await wa.getBySelector({handle:page, selector: ${values[0]}})`;
|
||||
}
|
||||
|
||||
// Handles GET "frameSelector", "selector"
|
||||
|
||||
else if (count == 2) {
|
||||
|
||||
return `${$1} = await wa.getByFrame({handle: page, ${values[0]}, frameOrSelector: ${values[1]}, selector: ${values[2]}})`;
|
||||
return `${$1} = await wa.getByFrame({handle: page, ${values[0]}, frameOrSelector: ${values[1]}, selector: ${
|
||||
values[2]
|
||||
}})`;
|
||||
}
|
||||
|
||||
// Handles the GET http version.
|
||||
|
||||
else {
|
||||
return `${$1} = await sys.get ({file: ${$2}, addressOrHeaders: headers, httpUsername, httpPs})`;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
}];
|
||||
|
||||
keywords[i++] = [/\= NEW OBJECT/gi, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/\= NEW OBJECT/gi,
|
||||
($0, $1, $2, $3) => {
|
||||
return ` = {}`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/\= NEW ARRAY/gi, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/\= NEW ARRAY/gi,
|
||||
($0, $1, $2, $3) => {
|
||||
return ` = []`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
keywords[i++] = [/^\s*(go to)(\s)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(go to)(\s)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['fromOrDialogName', 'dialogName']);
|
||||
return `await dk.gotoDialog(${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(set language)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(set language)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `await dk.setLanguage ({${$3}})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*set header\s*(.*)\sas\s(.*)/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\s*set header\s*(.*)\sas\s(.*)/gim,
|
||||
($0, $1, $2) => {
|
||||
return `headers[${$1}]=${$2})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*set http username\s*\=\s*(.*)/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\s*set http username\s*\=\s*(.*)/gim,
|
||||
($0, $1) => {
|
||||
return `httpUsername = ${$1}`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\sset http password\s*\=\s*(.*)/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\sset http password\s*\=\s*(.*)/gim,
|
||||
($0, $1) => {
|
||||
return `httpPs = ${$1}`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(datediff)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(datediff)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['date1', 'date2', 'mode']);
|
||||
return `await dk.dateDiff (${params}})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(dateadd)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(dateadd)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['date', 'mode', 'units']);
|
||||
return `await dk.dateAdd (${$3})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(set max lines)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(set max lines)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `await dk.setMaxLines ({count: ${$3}})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(set max columns)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(set max columns)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `await dk.setMaxColumns ({count: ${$3}})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(set translator)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(set translator)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `await dk.setTranslatorOn ({on: "${$3.toLowerCase()}"})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(set theme)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(set theme)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `await dk.setTheme ({theme: "${$3.toLowerCase()}"})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(set whole word)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(set whole word)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `await dk.setWholeWord ({on: "${$3.toLowerCase()}"})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*post\s*(.*),\s*(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*post\s*(.*),\s*(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `${$1} = await sys.postByHttp ({url:${$2}, data:${$3}, headers})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*put\s*(.*),\s*(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*put\s*(.*),\s*(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `${$1} = await sys.putByHttp ({url:${$2}, data:${$3}, headers})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*download\s*(.*),\s*(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*download\s*(.*),\s*(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `${$1} = await sys.download ({handle:page, selector: ${$2}, folder:${$3}})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*CREATE FOLDER\s*(.*)/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*CREATE FOLDER\s*(.*)/gim,
|
||||
($0, $1, $2) => {
|
||||
return `${$1} = await sys.createFolder ({name:${$2}})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\sSHARE FOLDER\s*(.*)/gim, ($0, $1) => {
|
||||
keywords[i++] = [
|
||||
/^\sSHARE FOLDER\s*(.*)/gim,
|
||||
($0, $1) => {
|
||||
return `await sys.shareFolder ({name: ${$1}})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(create a bot farm using)(\s)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(create a bot farm using)(\s)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `await sys.createABotFarmUsing ({${$3}})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(transfer to)(\s)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(transfer to)(\s)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `await dk.transferTo ({to:${$3}})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\btransfer\b)(?=(?:[^"]|"[^"]*")*$)/gim, () => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\btransfer\b)(?=(?:[^"]|"[^"]*")*$)/gim,
|
||||
() => {
|
||||
return `await dk.transferTo ({})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(exit)/gim, () => {
|
||||
keywords[i++] = [
|
||||
/^\s*(exit)/gim,
|
||||
() => {
|
||||
return ``;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(show menu)/gim, () => {
|
||||
keywords[i++] = [
|
||||
/^\s*(show menu)/gim,
|
||||
() => {
|
||||
return `await dk.showMenu ({})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(talk to)(\s)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(talk to)(\s)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['mobile', 'message']);
|
||||
return `await sys.talkTo(${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(talk)(\s)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
if ($3.substr(0, 1) !== "\"") {
|
||||
keywords[i++] = [
|
||||
/^\s*(talk)(\s)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
if ($3.substr(0, 1) !== '"') {
|
||||
$3 = `"${$3}"`;
|
||||
}
|
||||
return `await dk.talk ({text: ${$3}})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(send sms to)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(send sms to)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['mobile', 'message']);
|
||||
return `await sys.sendSmsTo(${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(send email)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(send email)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['to', 'subject', 'body']);
|
||||
return `await dk.sendEmail(${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(send mail)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(send mail)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['to', 'subject', 'body']);
|
||||
return `await dk.sendEmail(${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(send file to)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(send file to)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['mobile', 'filename', 'caption']);
|
||||
return `await dk.sendFileTo(${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(hover)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(hover)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['handle', 'selector']);
|
||||
return `await wa.hover (${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(click link text)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(click link text)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams('page,' + $3, ['handle', 'text', 'index']);
|
||||
return `await wa.linkByText (${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(click)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(click)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
// TODO: page is not string.
|
||||
const params = this.getParams('page,' + $3, ['handle', 'frameOrSelector', 'selector']);
|
||||
return `await wa.click (${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(send file)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(send file)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['filename', 'caption']);
|
||||
return `await dk.sendFile(${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(copy)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(copy)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['src', 'dst']);
|
||||
return `await sys.copyFile (${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(convert)(\s*)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(convert)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['src', 'dst']);
|
||||
return `await sys.convert (${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*(.*)\s*as chart/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*(.*)\s*as chart/gim,
|
||||
($0, $1, $2) => {
|
||||
return `await dk.chart ({type:'bar', data: ${2}, legends:null, transpose: false})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(chart)(\s)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(chart)(\s)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['type', 'data', 'legends', 'transpose']);
|
||||
return `await dk.chart (${params})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\sMERGE\s(.*)\sWITH\s(.*)BY\s(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\sMERGE\s(.*)\sWITH\s(.*)BY\s(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `await sys.merge({file: ${$1}, data: ${$2}, key1: ${$3}})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\sPRESS\s(.*)/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\sPRESS\s(.*)/gim,
|
||||
($0, $1, $2) => {
|
||||
return `await wa.pressKey({handle: page, char: ${$1})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\sSCREENSHOT\s(.*)/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\sSCREENSHOT\s(.*)/gim,
|
||||
($0, $1, $2) => {
|
||||
return `await wa.screenshot({handle: page, selector: ${$1}})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\sTWEET\s(.*)/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\sTWEET\s(.*)/gim,
|
||||
($0, $1, $2) => {
|
||||
return `await sys.tweet({text: ${$1})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*(.*)\s*as image/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*(.*)\s*as image/gim,
|
||||
($0, $1, $2) => {
|
||||
return `${$1} = await sys.asImage({data: ${$2}})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*(.*)\s*as pdf/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*(.*)\s*as pdf/gim,
|
||||
($0, $1, $2) => {
|
||||
return `${$1} = await sys.asPdf({data: ${$2})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\s*(\w+)\s*\=\s*FILL\s(.*)\sWITH\s(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\s*(\w+)\s*\=\s*FILL\s(.*)\sWITH\s(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `${$1} = await sys.fill({templateName: ${$2}, data: ${$3}})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\ssave\s(.*)\sas\s(.*)/gim, ($0, $1, $2, $3) => {
|
||||
keywords[i++] = [
|
||||
/^\ssave\s(.*)\sas\s(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `await sys.saveFile({file: ${$2}, data: ${$1})\n`;
|
||||
}];
|
||||
keywords[i++] = [/^\s*(save)(\s)(.*)/gim, ($0, $1, $2, $3) => {
|
||||
}
|
||||
];
|
||||
keywords[i++] = [
|
||||
/^\s*(save)(\s)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
return `await sys.save({args: [${$3}]})\n`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
keywords[i++] = [/^\sset\s(.*)/gim, ($0, $1, $2) => {
|
||||
keywords[i++] = [
|
||||
/^\sset\s(.*)/gim,
|
||||
($0, $1, $2) => {
|
||||
const params = this.getParams($1, ['file', 'address', 'value']);
|
||||
return `await sys.set (${params})`;
|
||||
}];
|
||||
}
|
||||
];
|
||||
return keywords;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes the converted JavaScript from BASIC code inside execution context.
|
||||
*/
|
||||
public static async callVM (text: string, min: GBMinInstance, step, GBDialogdeployer: GBDeployer, debug: boolean) {
|
||||
|
||||
const debuggerPort = 9222;
|
||||
|
||||
// Creates a class DialogKeywords which is the *this* pointer
|
||||
|
@ -783,9 +1004,7 @@ export class GBVMService extends GBService {
|
|||
// Auto-NLP generates BASIC variables related to entities.
|
||||
|
||||
if (step && step.context.activity['originalText']) {
|
||||
const entities = await min["nerEngine"].findEntities(
|
||||
step.context.activity['originalText'],
|
||||
contentLocale);
|
||||
const entities = await min['nerEngine'].findEntities(step.context.activity['originalText'], contentLocale);
|
||||
|
||||
for (let i = 0; i < entities.length; i++) {
|
||||
const v = entities[i];
|
||||
|
@ -802,7 +1021,6 @@ export class GBVMService extends GBService {
|
|||
|
||||
if (GBConfigService.get('VM3') === 'true') {
|
||||
try {
|
||||
|
||||
const vm1 = new NodeVM({
|
||||
allowAsync: true,
|
||||
sandbox: {},
|
||||
|
@ -813,7 +1031,7 @@ export class GBVMService extends GBService {
|
|||
root: ['./'],
|
||||
external: true,
|
||||
context: 'sandbox'
|
||||
},
|
||||
}
|
||||
});
|
||||
const s = new VMScript(code, { filename: scriptPath });
|
||||
let x = vm1.run(s);
|
||||
|
@ -821,9 +1039,16 @@ export class GBVMService extends GBService {
|
|||
} catch (error) {
|
||||
throw new Error(`BASIC RUNTIME ERR: ${error.message ? error.message : error}\n Stack:${error.stack}`);
|
||||
}
|
||||
|
||||
} else {
|
||||
const runnerPath = urlJoin(process.cwd(), 'dist', 'packages', 'basic.gblib', 'services', 'vm2-process', 'vm2ProcessRunner.js');
|
||||
const runnerPath = urlJoin(
|
||||
process.cwd(),
|
||||
'dist',
|
||||
'packages',
|
||||
'basic.gblib',
|
||||
'services',
|
||||
'vm2-process',
|
||||
'vm2ProcessRunner.js'
|
||||
);
|
||||
|
||||
try {
|
||||
const { run } = createVm2Pool({
|
||||
|
|
|
@ -48,14 +48,12 @@ import cron from 'node-cron';
|
|||
* Basic services for BASIC manipulation.
|
||||
*/
|
||||
export class ScheduleServices extends GBService {
|
||||
|
||||
public async deleteScheduleIfAny (min: GBMinInstance, name: string) {
|
||||
|
||||
const task = min["scheduleMap"] ? min["scheduleMap"][name] : null;
|
||||
const task = min['scheduleMap'] ? min['scheduleMap'][name] : null;
|
||||
|
||||
if (task) {
|
||||
task.destroy();
|
||||
delete min["scheduleMap"][name];
|
||||
delete min['scheduleMap'][name];
|
||||
}
|
||||
|
||||
const count = await GuaribasSchedule.destroy({
|
||||
|
@ -73,11 +71,7 @@ export class ScheduleServices extends GBService {
|
|||
/**
|
||||
* Finds and update user agent information to a next available person.
|
||||
*/
|
||||
public async createOrUpdateSchedule(
|
||||
min: GBMinInstance,
|
||||
schedule: string,
|
||||
name: string
|
||||
): Promise<GuaribasSchedule> {
|
||||
public async createOrUpdateSchedule (min: GBMinInstance, schedule: string, name: string): Promise<GuaribasSchedule> {
|
||||
let record = await GuaribasSchedule.findOne({
|
||||
where: {
|
||||
instanceId: min.instance.instanceId,
|
||||
|
@ -101,12 +95,10 @@ export class ScheduleServices extends GBService {
|
|||
return record;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load all cached schedule from BASIC SET SCHEDULE keyword.
|
||||
*/
|
||||
public async scheduleAll () {
|
||||
|
||||
let schedules;
|
||||
try {
|
||||
schedules = await GuaribasSchedule.findAll();
|
||||
|
@ -133,13 +125,13 @@ export class ScheduleServices extends GBService {
|
|||
timezone: 'America/Sao_Paulo'
|
||||
};
|
||||
|
||||
const task = min["scheduleMap"][item.name];
|
||||
const task = min['scheduleMap'][item.name];
|
||||
if (task) {
|
||||
task.stop();
|
||||
min["scheduleMap"][item.name] = null;
|
||||
min['scheduleMap'][item.name] = null;
|
||||
}
|
||||
|
||||
min["scheduleMap"][item.name] = cron.schedule(
|
||||
min['scheduleMap'][item.name] = cron.schedule(
|
||||
item.schedule,
|
||||
function () {
|
||||
const finalData = async () => {
|
||||
|
@ -152,7 +144,8 @@ export class ScheduleServices extends GBService {
|
|||
(async () => {
|
||||
await finalData();
|
||||
})();
|
||||
}, options
|
||||
},
|
||||
options
|
||||
);
|
||||
GBLog.info(`Running .gbdialog word ${item.name} on:${item.schedule}...`);
|
||||
} catch (error) {}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -43,15 +43,15 @@ import * as ts from 'typescript';
|
|||
* Wrapper for a TypeScript compiler.
|
||||
*/
|
||||
export class TSCompiler {
|
||||
|
||||
private static shouldIgnoreError (diagnostic) {
|
||||
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||
|
||||
if (message.indexOf('Cannot find name') >= 0
|
||||
|| message.indexOf('Cannot find module') >= 0
|
||||
|| message.indexOf('implicitly has an') >= 0
|
||||
|| message.indexOf('Cannot invoke an') >= 0
|
||||
|| message.indexOf('Cannot use imports, exports, or module') >= 0
|
||||
if (
|
||||
message.indexOf('Cannot find name') >= 0 ||
|
||||
message.indexOf('Cannot find module') >= 0 ||
|
||||
message.indexOf('implicitly has an') >= 0 ||
|
||||
message.indexOf('Cannot invoke an') >= 0 ||
|
||||
message.indexOf('Cannot use imports, exports, or module') >= 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
@ -99,5 +99,4 @@ export class TSCompiler {
|
|||
|
||||
return emitResult;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -49,7 +49,6 @@ import url from 'url';
|
|||
* Web Automation services of conversation to be called by BASIC.
|
||||
*/
|
||||
export class WebAutomationKeywords {
|
||||
|
||||
/**
|
||||
* Reference to minimal bot instance.
|
||||
*/
|
||||
|
@ -112,11 +111,7 @@ export class WebAutomationKeywords {
|
|||
this.user = user;
|
||||
this.dk = dk;
|
||||
|
||||
this.debugWeb = this.min.core.getParam<boolean>(
|
||||
this.min.instance,
|
||||
'Debug Web Automation',
|
||||
false
|
||||
);
|
||||
this.debugWeb = this.min.core.getParam<boolean>(this.min.instance, 'Debug Web Automation', false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,7 +126,7 @@ export class WebAutomationKeywords {
|
|||
}
|
||||
const page = (await this.browser.pages())[0];
|
||||
if (username || password) {
|
||||
await page.authenticate({ 'username': username, 'password': password });
|
||||
await page.authenticate({ username: username, password: password });
|
||||
}
|
||||
await page.goto(url);
|
||||
|
||||
|
@ -154,12 +149,11 @@ export class WebAutomationKeywords {
|
|||
public async getBySelector ({ handle, selector }) {
|
||||
const page = this.getPageByHandle(handle);
|
||||
GBLog.info(`BASIC: Web Automation GET element: ${selector}.`);
|
||||
await page.waitForSelector(selector)
|
||||
await page.waitForSelector(selector);
|
||||
let elements = await page.$$(selector);
|
||||
if (elements && elements.length > 1) {
|
||||
return elements;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const el = elements[0];
|
||||
el['originalSelector'] = selector;
|
||||
el['href'] = await page.evaluate(e => e.getAttribute('href'), el);
|
||||
|
@ -178,7 +172,7 @@ export class WebAutomationKeywords {
|
|||
public async getByFrame ({ handle, frame, selector }) {
|
||||
const page = this.getPageByHandle(handle);
|
||||
GBLog.info(`BASIC: Web Automation GET element by frame: ${selector}.`);
|
||||
await page.waitForSelector(frame)
|
||||
await page.waitForSelector(frame);
|
||||
let frameHandle = await page.$(frame);
|
||||
const f = await frameHandle.contentFrame();
|
||||
await f.waitForSelector(selector);
|
||||
|
@ -212,13 +206,12 @@ export class WebAutomationKeywords {
|
|||
const page = this.getPageByHandle(handle);
|
||||
GBLog.info(`BASIC: Web Automation CLICK element: ${frameOrSelector}.`);
|
||||
if (selector) {
|
||||
await page.waitForSelector(frameOrSelector)
|
||||
await page.waitForSelector(frameOrSelector);
|
||||
let frameHandle = await page.$(frameOrSelector);
|
||||
const f = await frameHandle.contentFrame();
|
||||
await f.waitForSelector(selector);
|
||||
await f.click(selector);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
await page.waitForSelector(frameOrSelector);
|
||||
await page.click(frameOrSelector);
|
||||
}
|
||||
|
@ -226,17 +219,16 @@ export class WebAutomationKeywords {
|
|||
}
|
||||
|
||||
private async debugStepWeb (page) {
|
||||
|
||||
let refresh = true;
|
||||
if (this.lastDebugWeb) {
|
||||
refresh = (new Date().getTime() - this.lastDebugWeb.getTime()) > 5000;
|
||||
refresh = new Date().getTime() - this.lastDebugWeb.getTime() > 5000;
|
||||
}
|
||||
|
||||
if (this.debugWeb && refresh) {
|
||||
const mobile = this.min.core.getParam(this.min.instance, 'Bot Admin Number', null);
|
||||
const filename = page;
|
||||
if (mobile) {
|
||||
await this.dk.sendFileTo({ mobile, filename, caption: "General Bots Debugger" });
|
||||
await this.dk.sendFileTo({ mobile, filename, caption: 'General Bots Debugger' });
|
||||
}
|
||||
this.lastDebugWeb = new Date();
|
||||
}
|
||||
|
@ -250,16 +242,15 @@ export class WebAutomationKeywords {
|
|||
public async pressKey ({ handle, char, frame }) {
|
||||
const page = this.getPageByHandle(handle);
|
||||
GBLog.info(`BASIC: Web Automation PRESS ${char} ON element: ${frame}.`);
|
||||
if (char.toLowerCase() === "enter") {
|
||||
if (char.toLowerCase() === 'enter') {
|
||||
char = '\n';
|
||||
}
|
||||
if (frame) {
|
||||
await page.waitForSelector(frame)
|
||||
await page.waitForSelector(frame);
|
||||
let frameHandle = await page.$(frame);
|
||||
const f = await frameHandle.contentFrame();
|
||||
await f.keyboard.press(char);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
await page.keyboard.press(char);
|
||||
}
|
||||
}
|
||||
|
@ -268,15 +259,13 @@ export class WebAutomationKeywords {
|
|||
const page = this.getPageByHandle(handle);
|
||||
GBLog.info(`BASIC: Web Automation CLICK LINK TEXT: ${text} ${index}.`);
|
||||
if (!index) {
|
||||
index = 1
|
||||
index = 1;
|
||||
}
|
||||
const els = await page.$x(`//a[contains(.,'${text}')]`);
|
||||
await els[index - 1].click();
|
||||
await this.debugStepWeb(page);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the screenshot of page or element
|
||||
*
|
||||
|
@ -291,18 +280,12 @@ export class WebAutomationKeywords {
|
|||
|
||||
await page.screenshot({ path: localName });
|
||||
|
||||
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));
|
||||
GBLog.info(`BASIC: WebAutomation: Screenshot captured at ${url}.`);
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Types the text into the text field.
|
||||
*
|
||||
|
@ -318,7 +301,6 @@ export class WebAutomationKeywords {
|
|||
await this.debugStepWeb(page);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs the download to the .gbdrive Download folder.
|
||||
*
|
||||
|
@ -344,7 +326,7 @@ export class WebAutomationKeywords {
|
|||
uri: xRequest['_url'],
|
||||
body: xRequest['_postData'],
|
||||
headers: xRequest['_headers']
|
||||
}
|
||||
};
|
||||
|
||||
const cookies = await page.cookies();
|
||||
options.headers.Cookie = cookies.map(ck => ck.name + '=' + ck.value).join(';');
|
||||
|
@ -355,11 +337,10 @@ export class WebAutomationKeywords {
|
|||
if (options.uri.indexOf('file://') != -1) {
|
||||
local = url.fileURLToPath(options.uri);
|
||||
filename = Path.basename(local);
|
||||
}
|
||||
else {
|
||||
const getBasenameFormUrl = (urlStr) => {
|
||||
const url = new URL(urlStr)
|
||||
return Path.basename(url.pathname)
|
||||
} else {
|
||||
const getBasenameFormUrl = urlStr => {
|
||||
const url = new URL(urlStr);
|
||||
return Path.basename(url.pathname);
|
||||
};
|
||||
filename = getBasenameFormUrl(options.uri);
|
||||
}
|
||||
|
@ -391,14 +372,9 @@ export class WebAutomationKeywords {
|
|||
// to the source and calling /content on drive API.
|
||||
let file;
|
||||
try {
|
||||
|
||||
file = await client
|
||||
.api(`${baseUrl}/drive/root:/${dstPath}:/content`)
|
||||
.put(result);
|
||||
|
||||
file = await client.api(`${baseUrl}/drive/root:/${dstPath}:/content`).put(result);
|
||||
} catch (error) {
|
||||
|
||||
if (error.code === "nameAlreadyExists") {
|
||||
if (error.code === 'nameAlreadyExists') {
|
||||
GBLog.info(`BASIC: DOWNLOAD destination file already exists: ${dstPath}.`);
|
||||
}
|
||||
throw error;
|
||||
|
@ -406,6 +382,4 @@ export class WebAutomationKeywords {
|
|||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// Source: https://github.com/uweg/vbscript-to-typescript
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
import fs_1 from 'fs';
|
||||
import path from 'path';
|
||||
|
@ -7,11 +7,11 @@ import path from 'path';
|
|||
export function convertFile (file) {
|
||||
var extension = path.extname(file);
|
||||
var withoutExtension = file.substr(0, file.length - extension.length);
|
||||
var targetFile = withoutExtension + ".ts";
|
||||
var targetFile = withoutExtension + '.ts';
|
||||
var baseName = path.basename(file, extension);
|
||||
var content = fs_1.readFileSync(file, 'utf8');
|
||||
var result = convert(content, baseName);
|
||||
console.log("Writing to \"" + targetFile + "\"...");
|
||||
console.log('Writing to "' + targetFile + '"...');
|
||||
fs_1.writeFileSync(targetFile, result);
|
||||
}
|
||||
|
||||
|
@ -24,9 +24,9 @@ function convertImports(input, name) {
|
|||
var items = [];
|
||||
var result = input.replace(/<!-- #include file="(.*?\/)?(.*?).asp" -->/gi, function (input, group1, group2) {
|
||||
var path = group1 || './';
|
||||
var file = "" + path + group2;
|
||||
var file = '' + path + group2;
|
||||
items.push({ name: group2, path: file });
|
||||
return "<%\n" + group2 + "();\n%>";
|
||||
return '<%\n' + group2 + '();\n%>';
|
||||
});
|
||||
result = convertCode(result);
|
||||
result = convertExpressions(result);
|
||||
|
@ -34,7 +34,7 @@ function convertImports(input, name) {
|
|||
|
||||
for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
|
||||
var item = items_1[_i];
|
||||
result = "import {" + item.name + "} from \"" + item.path + "\"\n" + result;
|
||||
result = 'import {' + item.name + '} from "' + item.path + '"\n' + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ function convertCode(input) {
|
|||
code = convertLoops(code);
|
||||
code = convertPRec(code);
|
||||
code = convertPLan(code);
|
||||
return "<%" + code + "%>";
|
||||
return '<%' + code + '%>';
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
@ -59,29 +59,29 @@ function convertExpressions(input) {
|
|||
var result = input.replace(/<%=([\s\S]*?)%>/gi, function (input, group1) {
|
||||
var content = convertPRec(group1);
|
||||
content = convertPLan(content);
|
||||
return "${" + content + "}";
|
||||
return '${' + content + '}';
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertStrings (input) {
|
||||
var result = input.replace(/%>([\s\S]+?)<%/gi, "\nResponse.Write(`$1`);\n");
|
||||
var result = input.replace(/%>([\s\S]+?)<%/gi, '\nResponse.Write(`$1`);\n');
|
||||
// Entire document is a string
|
||||
if (result.indexOf("<%") === -1) {
|
||||
result = "Response.Write(`" + result + "`);";
|
||||
if (result.indexOf('<%') === -1) {
|
||||
result = 'Response.Write(`' + result + '`);';
|
||||
}
|
||||
// Start of the document is a string
|
||||
var firstIndex = result.indexOf("<%");
|
||||
var firstIndex = result.indexOf('<%');
|
||||
if (firstIndex > 0) {
|
||||
result = "Response.Write(`" + result.substr(0, firstIndex) + "`);\n" + result.substring(firstIndex + 2);
|
||||
result = 'Response.Write(`' + result.substr(0, firstIndex) + '`);\n' + result.substring(firstIndex + 2);
|
||||
}
|
||||
result = result.replace(/%>$/, "");
|
||||
result = result.replace(/%>$/, '');
|
||||
// End of the document is a string
|
||||
var lastIndex = result.lastIndexOf("%>");
|
||||
var lastIndex = result.lastIndexOf('%>');
|
||||
if (lastIndex > -1 && lastIndex < result.length - 2) {
|
||||
result = result.substr(0, lastIndex) + "\nResponse.Write(`" + result.substr(lastIndex + 3) + "`);";
|
||||
result = result.substr(0, lastIndex) + '\nResponse.Write(`' + result.substr(lastIndex + 3) + '`);';
|
||||
}
|
||||
result = result.replace(/^<%/, "");
|
||||
result = result.replace(/^<%/, '');
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -90,11 +90,10 @@ function convertComments(input) {
|
|||
var splitted = input.split(/(".*")/gim);
|
||||
for (var _i = 0, splitted_1 = splitted; _i < splitted_1.length; _i++) {
|
||||
var part = splitted_1[_i];
|
||||
if (part.indexOf("\"") === 0) {
|
||||
if (part.indexOf('"') === 0) {
|
||||
result += part;
|
||||
}
|
||||
else {
|
||||
result += part.replace(/'/gi, "//");
|
||||
} else {
|
||||
result += part.replace(/'/gi, '//');
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -103,56 +102,55 @@ function convertComments(input) {
|
|||
function convertIfStatements (input) {
|
||||
var result = input.replace(/if +(.*?) +then/gi, function (input, group1) {
|
||||
var condition = convertConditions(group1);
|
||||
return "\nif (" + condition + ") {\n";
|
||||
return '\nif (' + condition + ') {\n';
|
||||
});
|
||||
result = result.replace(/end if/gi, "\n}\n");
|
||||
result = result.replace(/else(?!{)/gi, "\n}\nelse {\n");
|
||||
result = result.replace(/end if/gi, '\n}\n');
|
||||
result = result.replace(/else(?!{)/gi, '\n}\nelse {\n');
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertSwitchStatements (input) {
|
||||
var result = input.replace(/select case +(.*)/gi, "\nswitch ($1) {\n");
|
||||
result = result.replace(/end select/gi, "\n}\n");
|
||||
var result = input.replace(/select case +(.*)/gi, '\nswitch ($1) {\n');
|
||||
result = result.replace(/end select/gi, '\n}\n');
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertFunctions (input) {
|
||||
var result = input.replace(/function +(.*)\((.*)\)/gi, "\n$1 = ($2) => {\n");
|
||||
result = result.replace(/end function/gi, "\n}\n");
|
||||
var result = input.replace(/function +(.*)\((.*)\)/gi, '\n$1 = ($2) => {\n');
|
||||
result = result.replace(/end function/gi, '\n}\n');
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertForStatements (input) {
|
||||
var result = input.replace(/for +(.*to.*)/gi, "\nfor ($1) {\n");
|
||||
result = result.replace(/^ *next *$/gim, "}\n");
|
||||
var result = input.replace(/for +(.*to.*)/gi, '\nfor ($1) {\n');
|
||||
result = result.replace(/^ *next *$/gim, '}\n');
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertConditions (input) {
|
||||
var result = input.replace(/ +and +/gi, " && ");
|
||||
result = result.replace(/ +or +/gi, " || ");
|
||||
result = result.replace(/ +<> +/gi, " !== ");
|
||||
result = result.replace(/ += +/gi, " === ");
|
||||
var result = input.replace(/ +and +/gi, ' && ');
|
||||
result = result.replace(/ +or +/gi, ' || ');
|
||||
result = result.replace(/ +<> +/gi, ' !== ');
|
||||
result = result.replace(/ += +/gi, ' === ');
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertLoops (input) {
|
||||
var result = input.replace(/do while +(.*)/gi, function (input, group1) {
|
||||
var condition = convertConditions(group1);
|
||||
return "\nwhile (" + condition + ") {\n";
|
||||
return '\nwhile (' + condition + ') {\n';
|
||||
});
|
||||
|
||||
result = result.replace(/^ *loop *$/gim, "}\n");
|
||||
result = result.replace(/^ *loop *$/gim, '}\n');
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertPRec (input) {
|
||||
var result = input.replace(/(p_rec\("\S+?"\))/gi, "$1.Value");
|
||||
var result = input.replace(/(p_rec\("\S+?"\))/gi, '$1.Value');
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertPLan (input) {
|
||||
var result = input.replace(/(l_\S+?)\(p_lan\)/gi, "$1[p_lan]");
|
||||
var result = input.replace(/(l_\S+?)\(p_lan\)/gi, '$1[p_lan]');
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ export const createVm2Pool = ({ min, max, ...limits }) => {
|
|||
{ cwd: limits.cwd, shell: false }
|
||||
);
|
||||
|
||||
|
||||
childProcess.stdout.on('data', data => {
|
||||
childProcess['socket'] = childProcess['socket'] || data.toString().trim();
|
||||
});
|
||||
|
@ -75,14 +74,14 @@ export const createVm2Pool = ({ min, max, ...limits }) => {
|
|||
kill(process);
|
||||
GBServer.globals.debuggers[limits.botId].state = 0;
|
||||
GBServer.globals.debuggers[limits.botId].stateInfo = stderrCache;
|
||||
}
|
||||
else if (stderrCache.includes('FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory')) {
|
||||
} else if (
|
||||
stderrCache.includes('FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory')
|
||||
) {
|
||||
limitError = 'code execution exceeed allowed memory';
|
||||
kill(process);
|
||||
GBServer.globals.debuggers[limits.botId].state = 0;
|
||||
GBServer.globals.debuggers[limits.botId].stateInfo = 'Fail';
|
||||
}
|
||||
else if (stderrCache.includes('Debugger attached.')) {
|
||||
} else if (stderrCache.includes('Debugger attached.')) {
|
||||
GBLog.info(`BASIC: General Bots Debugger attached to Node .gbdialog process for ${limits.botId}.`);
|
||||
}
|
||||
});
|
||||
|
@ -92,7 +91,6 @@ export const createVm2Pool = ({ min, max, ...limits }) => {
|
|||
|
||||
GBServer.globals.debuggers[limits.botId].childProcess = ref;
|
||||
|
||||
|
||||
// Only attach if called by debugger/run.
|
||||
|
||||
if (GBServer.globals.debuggers[limits.botId]) {
|
||||
|
@ -155,7 +153,6 @@ export const createVm2Pool = ({ min, max, ...limits }) => {
|
|||
await client.Debugger.enable();
|
||||
await client.Runtime.enable();
|
||||
|
||||
|
||||
resolve(1);
|
||||
} catch (err) {
|
||||
GBLog.error(err);
|
||||
|
@ -214,4 +211,3 @@ export const createVm2Pool = ({ min, max, ...limits }) => {
|
|||
run
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ const evaluate = async (script, scope) => {
|
|||
root: ['./'],
|
||||
external: true,
|
||||
context: 'sandbox'
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
const s = new VMScript(script, scope);
|
||||
|
@ -22,7 +22,7 @@ const evaluate = async (script, scope) => {
|
|||
|
||||
const socketName = crypto1.randomBytes(20).toString('hex');
|
||||
|
||||
const server = net1.createServer((socket) => {
|
||||
const server = net1.createServer(socket => {
|
||||
const buffer = [];
|
||||
|
||||
const sync = async () => {
|
||||
|
@ -39,7 +39,7 @@ const server = net1.createServer((socket) => {
|
|||
socket.write(JSON.stringify({ result }) + '\n');
|
||||
socket.end();
|
||||
} catch (error) {
|
||||
console.log(`BASIC: RUNTIME: ${error.message}, ${error.stack}`)
|
||||
console.log(`BASIC: RUNTIME: ${error.message}, ${error.stack}`);
|
||||
socket.write(JSON.stringify({ error: error.message }) + '\n');
|
||||
socket.end();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
export const Messages = {
|
||||
'en-US': {
|
||||
affirmative_sentences: /^(\bsim\b|\bs\b|\bpositivo\b|\bafirmativo\b|\bclaro\b|\bevidente\b|\bsem dúvida\b|\bconfirmo\b|\bconfirmar\b|\bconfirmado\b|\buhum\b|\bsi\b|\by\b|\byes\b|\bsure\b)/i,
|
||||
|
|
|
@ -59,8 +59,7 @@ export class BroadcastDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -55,12 +55,12 @@ export class LanguageDialog extends IGBDialog {
|
|||
* @param min The minimal bot instance data.
|
||||
*/
|
||||
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||
min.dialogs.add(new WaterfallDialog('/language', [
|
||||
min.dialogs.add(
|
||||
new WaterfallDialog('/language', [
|
||||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -68,11 +68,9 @@ export class LanguageDialog extends IGBDialog {
|
|||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
return await min.conversationalService.prompt(min, step,
|
||||
Messages[locale].which_language);
|
||||
return await min.conversationalService.prompt(min, step, Messages[locale].which_language);
|
||||
},
|
||||
async step => {
|
||||
|
||||
const locale = step.context.activity.locale;
|
||||
const user = await min.userProfile.get(step.context, {});
|
||||
|
||||
|
@ -96,8 +94,10 @@ export class LanguageDialog extends IGBDialog {
|
|||
const text = step.context.activity['originalText'];
|
||||
|
||||
await CollectionUtil.asyncForEach(list, async item => {
|
||||
if (GBConversationalService.kmpSearch(text.toLowerCase(), item.name.toLowerCase()) != -1 ||
|
||||
GBConversationalService.kmpSearch(text.toLowerCase(), item.code.toLowerCase()) != -1) {
|
||||
if (
|
||||
GBConversationalService.kmpSearch(text.toLowerCase(), item.name.toLowerCase()) != -1 ||
|
||||
GBConversationalService.kmpSearch(text.toLowerCase(), item.code.toLowerCase()) != -1
|
||||
) {
|
||||
translatorLocale = item.code;
|
||||
}
|
||||
});
|
||||
|
@ -106,11 +106,11 @@ export class LanguageDialog extends IGBDialog {
|
|||
user.systemUser = await sec.updateUserLocale(user.systemUser.userId, translatorLocale);
|
||||
|
||||
await min.userProfile.set(step.context, user);
|
||||
await min.conversationalService.sendText(min, step,
|
||||
Messages[locale].language_chosen);
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].language_chosen);
|
||||
|
||||
await step.replaceDialog('/ask', { firstTime: true });
|
||||
}
|
||||
]));
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,12 +54,12 @@ export class SwitchBotDialog extends IGBDialog {
|
|||
* @param min The minimal bot instance data.
|
||||
*/
|
||||
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||
min.dialogs.add(new WaterfallDialog('/bot', [
|
||||
min.dialogs.add(
|
||||
new WaterfallDialog('/bot', [
|
||||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -79,6 +79,7 @@ export class SwitchBotDialog extends IGBDialog {
|
|||
|
||||
return await step.next();
|
||||
}
|
||||
]));
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,29 +54,32 @@ export class WelcomeDialog extends IGBDialog {
|
|||
* @param min The minimal bot instance data.
|
||||
*/
|
||||
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||
|
||||
min.dialogs.add(new WaterfallDialog('/', [
|
||||
min.dialogs.add(
|
||||
new WaterfallDialog('/', [
|
||||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
async step => {
|
||||
|
||||
if (GBServer.globals.entryPointDialog !== null &&
|
||||
if (
|
||||
GBServer.globals.entryPointDialog !== null &&
|
||||
min.instance.botId === process.env.BOT_ID &&
|
||||
step.context.activity.channelId === 'webchat') {
|
||||
step.context.activity.channelId === 'webchat'
|
||||
) {
|
||||
return step.replaceDialog(GBServer.globals.entryPointDialog);
|
||||
}
|
||||
|
||||
const user = await min.userProfile.get(step.context, {});
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
if (!user.once && step.context.activity.channelId === 'webchat'
|
||||
&& min.core.getParam<boolean>(min.instance, 'HelloGoodX', true) === "true") {
|
||||
if (
|
||||
!user.once &&
|
||||
step.context.activity.channelId === 'webchat' &&
|
||||
min.core.getParam<boolean>(min.instance, 'HelloGoodX', true) === 'true'
|
||||
) {
|
||||
user.once = true;
|
||||
await min.userProfile.set(step.context, user);
|
||||
const a = new Date();
|
||||
|
@ -104,6 +107,7 @@ export class WelcomeDialog extends IGBDialog {
|
|||
|
||||
return await step.next();
|
||||
}
|
||||
]));
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,12 +52,12 @@ export class WhoAmIDialog extends IGBDialog {
|
|||
* @param min The minimal bot instance data.
|
||||
*/
|
||||
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||
min.dialogs.add(new WaterfallDialog('/whoAmI', [
|
||||
min.dialogs.add(
|
||||
new WaterfallDialog('/whoAmI', [
|
||||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -78,6 +78,7 @@ export class WhoAmIDialog extends IGBDialog {
|
|||
|
||||
return await step.next();
|
||||
}
|
||||
]));
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,221 +55,219 @@ import { IGBInstance } from 'botlib';
|
|||
* Base instance data for a bot.
|
||||
*/
|
||||
@Table
|
||||
export class GuaribasInstance extends Model<GuaribasInstance>
|
||||
implements IGBInstance {
|
||||
|
||||
export class GuaribasInstance extends Model<GuaribasInstance> implements IGBInstance {
|
||||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare botEndpoint: string;
|
||||
botEndpoint: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare whoAmIVideo: string;
|
||||
whoAmIVideo: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare botId: string;
|
||||
botId: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare title: string;
|
||||
title: string;
|
||||
|
||||
@Column({ type: DataType.STRING(16) })
|
||||
declare activationCode: string;
|
||||
activationCode: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare description: string;
|
||||
description: string;
|
||||
|
||||
@Column({ type: DataType.STRING(16) })
|
||||
declare state: string;
|
||||
state: string;
|
||||
|
||||
declare version: string;
|
||||
version: string;
|
||||
|
||||
@Column(DataType.STRING(64))
|
||||
declare botKey: string;
|
||||
botKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare enabledAdmin: boolean;
|
||||
enabledAdmin: boolean;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare engineName: string;
|
||||
engineName: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare marketplaceId: string;
|
||||
marketplaceId: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare textAnalyticsKey: string;
|
||||
textAnalyticsKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare textAnalyticsEndpoint: string;
|
||||
textAnalyticsEndpoint: string;
|
||||
|
||||
@Column({ type: DataType.STRING(64) })
|
||||
declare translatorKey: string;
|
||||
translatorKey: string;
|
||||
|
||||
@Column({ type: DataType.STRING(128) })
|
||||
declare translatorEndpoint: string;
|
||||
translatorEndpoint: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare marketplacePassword: string;
|
||||
marketplacePassword: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare webchatKey: string;
|
||||
webchatKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare authenticatorTenant: string;
|
||||
authenticatorTenant: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare authenticatorAuthorityHostUrl: string;
|
||||
authenticatorAuthorityHostUrl: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare cloudSubscriptionId: string;
|
||||
cloudSubscriptionId: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare cloudUsername: string;
|
||||
cloudUsername: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare cloudPassword: string;
|
||||
cloudPassword: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare cloudLocation: string;
|
||||
cloudLocation: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare googleBotKey: string;
|
||||
googleBotKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare googleChatApiKey: string;
|
||||
googleChatApiKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare googleChatSubscriptionName: string;
|
||||
googleChatSubscriptionName: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare googleClientEmail: string;
|
||||
googleClientEmail: string;
|
||||
|
||||
@Column({ type: DataType.STRING(4000) })
|
||||
declare googlePrivateKey: string;
|
||||
googlePrivateKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare googleProjectId: string;
|
||||
googleProjectId: string;
|
||||
|
||||
@Column({ type: DataType.STRING(255) })
|
||||
declare facebookWorkplaceVerifyToken: string;
|
||||
facebookWorkplaceVerifyToken: string;
|
||||
|
||||
@Column({ type: DataType.STRING(255) })
|
||||
declare facebookWorkplaceAppSecret: string;
|
||||
facebookWorkplaceAppSecret: string;
|
||||
|
||||
@Column({ type: DataType.STRING(512) })
|
||||
declare facebookWorkplaceAccessToken: string;
|
||||
facebookWorkplaceAccessToken: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare whatsappBotKey: string;
|
||||
whatsappBotKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare whatsappServiceKey: string;
|
||||
whatsappServiceKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare whatsappServiceNumber: string;
|
||||
whatsappServiceNumber: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare whatsappServiceUrl: string;
|
||||
whatsappServiceUrl: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare smsKey: string;
|
||||
smsKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare smsSecret: string;
|
||||
smsSecret: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare smsServiceNumber: string;
|
||||
smsServiceNumber: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare speechKey: string;
|
||||
speechKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare speechEndpoint: string;
|
||||
speechEndpoint: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare spellcheckerKey: string;
|
||||
spellcheckerKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare spellcheckerEndpoint: string;
|
||||
spellcheckerEndpoint: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare theme: string;
|
||||
theme: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare ui: string;
|
||||
ui: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare kb: string;
|
||||
kb: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare nlpAppId: string;
|
||||
nlpAppId: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare nlpKey: string;
|
||||
nlpKey: string;
|
||||
|
||||
@Column({ type: DataType.STRING(512) })
|
||||
declare nlpEndpoint: string;
|
||||
nlpEndpoint: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare nlpAuthoringKey: string;
|
||||
nlpAuthoringKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare deploymentPaths: string;
|
||||
deploymentPaths: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare searchHost: string;
|
||||
searchHost: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare searchKey: string;
|
||||
searchKey: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare searchIndex: string;
|
||||
searchIndex: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare searchIndexer: string;
|
||||
searchIndexer: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare storageUsername: string;
|
||||
storageUsername: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare storagePassword: string;
|
||||
storagePassword: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare storageName: string;
|
||||
storageName: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare storageServer: string;
|
||||
storageServer: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare storageDialect: string;
|
||||
storageDialect: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare storagePath: string;
|
||||
storagePath: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare adminPass: string;
|
||||
adminPass: string;
|
||||
|
||||
@Column(DataType.FLOAT)
|
||||
declare nlpVsSearch: number; // TODO: Remove field.
|
||||
nlpVsSearch: number; // TODO: Remove field.
|
||||
|
||||
@Column(DataType.FLOAT)
|
||||
declare searchScore: number;
|
||||
searchScore: number;
|
||||
|
||||
@Column(DataType.FLOAT)
|
||||
declare nlpScore: number;
|
||||
nlpScore: number;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@CreatedAt
|
||||
declare createdAt: Date;
|
||||
createdAt: Date;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@UpdatedAt
|
||||
declare updatedAt: Date;
|
||||
updatedAt: Date;
|
||||
|
||||
@Column(DataType.STRING(4000))
|
||||
declare params: string;
|
||||
params: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -280,28 +278,28 @@ export class GuaribasPackage extends Model<GuaribasPackage> {
|
|||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
declare packageId: number;
|
||||
packageId: number;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare packageName: string;
|
||||
packageName: string;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasInstance)
|
||||
declare instance: GuaribasInstance;
|
||||
instance: GuaribasInstance;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@CreatedAt
|
||||
declare createdAt: Date;
|
||||
createdAt: Date;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@UpdatedAt
|
||||
declare updatedAt: Date;
|
||||
updatedAt: Date;
|
||||
|
||||
@Column({ type: DataType.STRING(512) })
|
||||
declare custom: string;
|
||||
custom: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -312,18 +310,18 @@ export class GuaribasChannel extends Model<GuaribasChannel> {
|
|||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
declare channelId: number;
|
||||
channelId: number;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare title: string;
|
||||
title: string;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@CreatedAt
|
||||
declare createdAt: Date;
|
||||
createdAt: Date;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@UpdatedAt
|
||||
declare updatedAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -335,72 +333,70 @@ export class GuaribasException extends Model<GuaribasException> {
|
|||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
declare exceptionId: number;
|
||||
exceptionId: number;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare message: string;
|
||||
message: string;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasInstance)
|
||||
declare instance: GuaribasInstance;
|
||||
instance: GuaribasInstance;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@CreatedAt
|
||||
declare createdAt: Date;
|
||||
createdAt: Date;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@UpdatedAt
|
||||
declare updatedAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@Table
|
||||
//tslint:disable-next-line:max-classes-per-file
|
||||
export class GuaribasApplications extends Model<GuaribasApplications> {
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare name: string;
|
||||
name: string;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasInstance)
|
||||
declare instance: GuaribasInstance;
|
||||
instance: GuaribasInstance;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@CreatedAt
|
||||
declare createdAt: Date;
|
||||
createdAt: Date;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@UpdatedAt
|
||||
declare updatedAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@Table
|
||||
//tslint:disable-next-line:max-classes-per-file
|
||||
export class GuaribasSchedule extends Model<GuaribasSchedule> {
|
||||
@Column(DataType.STRING(255))
|
||||
name: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare name: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare schedule: string;
|
||||
schedule: string;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasInstance)
|
||||
declare instance: GuaribasInstance;
|
||||
instance: GuaribasInstance;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@CreatedAt
|
||||
declare createdAt: Date;
|
||||
createdAt: Date;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@UpdatedAt
|
||||
declare updatedAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ import * as en from 'dotenv-extended';
|
|||
*/
|
||||
export class GBConfigService {
|
||||
public static getBoolean (value: string): boolean {
|
||||
return this.get(value) as unknown as boolean;
|
||||
return (this.get(value) as unknown) as boolean;
|
||||
}
|
||||
public static getServerPort (): string {
|
||||
if (process.env.PORT) {
|
||||
|
@ -170,7 +170,6 @@ export class GBConfigService {
|
|||
value = process.env[key];
|
||||
}
|
||||
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,6 @@ import Translate from '@google-cloud/translate';
|
|||
* services like NLP or Search.
|
||||
*/
|
||||
export class GBConversationalService {
|
||||
|
||||
/**
|
||||
* Reference to the core service.
|
||||
*/
|
||||
|
@ -84,104 +83,191 @@ export class GBConversationalService {
|
|||
}
|
||||
|
||||
static defaultDiacriticsRemovalMap = [
|
||||
{ 'base': 'A', 'letters': '\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F' },
|
||||
{ 'base': 'AA', 'letters': '\uA732' },
|
||||
{ 'base': 'AE', 'letters': '\u00C6\u01FC\u01E2' },
|
||||
{ 'base': 'AO', 'letters': '\uA734' },
|
||||
{ 'base': 'AU', 'letters': '\uA736' },
|
||||
{ 'base': 'AV', 'letters': '\uA738\uA73A' },
|
||||
{ 'base': 'AY', 'letters': '\uA73C' },
|
||||
{ 'base': 'B', 'letters': '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181' },
|
||||
{ 'base': 'C', 'letters': '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E' },
|
||||
{ 'base': 'D', 'letters': '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0' },
|
||||
{ 'base': 'DZ', 'letters': '\u01F1\u01C4' },
|
||||
{ 'base': 'Dz', 'letters': '\u01F2\u01C5' },
|
||||
{ 'base': 'E', 'letters': '\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E' },
|
||||
{ 'base': 'F', 'letters': '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B' },
|
||||
{ 'base': 'G', 'letters': '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E' },
|
||||
{ 'base': 'H', 'letters': '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D' },
|
||||
{ 'base': 'I', 'letters': '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197' },
|
||||
{ 'base': 'J', 'letters': '\u004A\u24BF\uFF2A\u0134\u0248' },
|
||||
{ 'base': 'K', 'letters': '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2' },
|
||||
{ 'base': 'L', 'letters': '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780' },
|
||||
{ 'base': 'LJ', 'letters': '\u01C7' },
|
||||
{ 'base': 'Lj', 'letters': '\u01C8' },
|
||||
{ 'base': 'M', 'letters': '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C' },
|
||||
{ 'base': 'N', 'letters': '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4' },
|
||||
{ 'base': 'NJ', 'letters': '\u01CA' },
|
||||
{ 'base': 'Nj', 'letters': '\u01CB' },
|
||||
{ 'base': 'O', 'letters': '\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C' },
|
||||
{ 'base': 'OI', 'letters': '\u01A2' },
|
||||
{ 'base': 'OO', 'letters': '\uA74E' },
|
||||
{ 'base': 'OU', 'letters': '\u0222' },
|
||||
{ 'base': 'OE', 'letters': '\u008C\u0152' },
|
||||
{ 'base': 'oe', 'letters': '\u009C\u0153' },
|
||||
{ 'base': 'P', 'letters': '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754' },
|
||||
{ 'base': 'Q', 'letters': '\u0051\u24C6\uFF31\uA756\uA758\u024A' },
|
||||
{ 'base': 'R', 'letters': '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782' },
|
||||
{ 'base': 'S', 'letters': '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784' },
|
||||
{ 'base': 'T', 'letters': '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786' },
|
||||
{ 'base': 'TZ', 'letters': '\uA728' },
|
||||
{ 'base': 'U', 'letters': '\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244' },
|
||||
{ 'base': 'V', 'letters': '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245' },
|
||||
{ 'base': 'VY', 'letters': '\uA760' },
|
||||
{ 'base': 'W', 'letters': '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72' },
|
||||
{ 'base': 'X', 'letters': '\u0058\u24CD\uFF38\u1E8A\u1E8C' },
|
||||
{ 'base': 'Y', 'letters': '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE' },
|
||||
{ 'base': 'Z', 'letters': '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762' },
|
||||
{ 'base': 'a', 'letters': '\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250' },
|
||||
{ 'base': 'aa', 'letters': '\uA733' },
|
||||
{ 'base': 'ae', 'letters': '\u00E6\u01FD\u01E3' },
|
||||
{ 'base': 'ao', 'letters': '\uA735' },
|
||||
{ 'base': 'au', 'letters': '\uA737' },
|
||||
{ 'base': 'av', 'letters': '\uA739\uA73B' },
|
||||
{ 'base': 'ay', 'letters': '\uA73D' },
|
||||
{ 'base': 'b', 'letters': '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253' },
|
||||
{ 'base': 'c', 'letters': '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184' },
|
||||
{ 'base': 'd', 'letters': '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A' },
|
||||
{ 'base': 'dz', 'letters': '\u01F3\u01C6' },
|
||||
{ 'base': 'e', 'letters': '\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD' },
|
||||
{ 'base': 'f', 'letters': '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C' },
|
||||
{ 'base': 'g', 'letters': '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F' },
|
||||
{ 'base': 'h', 'letters': '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265' },
|
||||
{ 'base': 'hv', 'letters': '\u0195' },
|
||||
{ 'base': 'i', 'letters': '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131' },
|
||||
{ 'base': 'j', 'letters': '\u006A\u24D9\uFF4A\u0135\u01F0\u0249' },
|
||||
{ 'base': 'k', 'letters': '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3' },
|
||||
{ 'base': 'l', 'letters': '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747' },
|
||||
{ 'base': 'lj', 'letters': '\u01C9' },
|
||||
{ 'base': 'm', 'letters': '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F' },
|
||||
{ 'base': 'n', 'letters': '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5' },
|
||||
{ 'base': 'nj', 'letters': '\u01CC' },
|
||||
{ 'base': 'o', 'letters': '\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275' },
|
||||
{ 'base': 'oi', 'letters': '\u01A3' },
|
||||
{ 'base': 'ou', 'letters': '\u0223' },
|
||||
{ 'base': 'oo', 'letters': '\uA74F' },
|
||||
{ 'base': 'p', 'letters': '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755' },
|
||||
{ 'base': 'q', 'letters': '\u0071\u24E0\uFF51\u024B\uA757\uA759' },
|
||||
{ 'base': 'r', 'letters': '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783' },
|
||||
{ 'base': 's', 'letters': '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B' },
|
||||
{ 'base': 't', 'letters': '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787' },
|
||||
{ 'base': 'tz', 'letters': '\uA729' },
|
||||
{ 'base': 'u', 'letters': '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289' },
|
||||
{ 'base': 'v', 'letters': '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C' },
|
||||
{ 'base': 'vy', 'letters': '\uA761' },
|
||||
{ 'base': 'w', 'letters': '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73' },
|
||||
{ 'base': 'x', 'letters': '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
|
||||
{ 'base': 'y', 'letters': '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF' },
|
||||
{ 'base': 'z', 'letters': '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763' }
|
||||
{
|
||||
base: 'A',
|
||||
letters:
|
||||
'\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F'
|
||||
},
|
||||
{ base: 'AA', letters: '\uA732' },
|
||||
{ base: 'AE', letters: '\u00C6\u01FC\u01E2' },
|
||||
{ base: 'AO', letters: '\uA734' },
|
||||
{ base: 'AU', letters: '\uA736' },
|
||||
{ base: 'AV', letters: '\uA738\uA73A' },
|
||||
{ base: 'AY', letters: '\uA73C' },
|
||||
{ base: 'B', letters: '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181' },
|
||||
{ base: 'C', letters: '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E' },
|
||||
{
|
||||
base: 'D',
|
||||
letters: '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0'
|
||||
},
|
||||
{ base: 'DZ', letters: '\u01F1\u01C4' },
|
||||
{ base: 'Dz', letters: '\u01F2\u01C5' },
|
||||
{
|
||||
base: 'E',
|
||||
letters:
|
||||
'\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E'
|
||||
},
|
||||
{ base: 'F', letters: '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B' },
|
||||
{
|
||||
base: 'G',
|
||||
letters: '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E'
|
||||
},
|
||||
{ base: 'H', letters: '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D' },
|
||||
{
|
||||
base: 'I',
|
||||
letters:
|
||||
'\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197'
|
||||
},
|
||||
{ base: 'J', letters: '\u004A\u24BF\uFF2A\u0134\u0248' },
|
||||
{ base: 'K', letters: '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2' },
|
||||
{
|
||||
base: 'L',
|
||||
letters:
|
||||
'\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780'
|
||||
},
|
||||
{ base: 'LJ', letters: '\u01C7' },
|
||||
{ base: 'Lj', letters: '\u01C8' },
|
||||
{ base: 'M', letters: '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C' },
|
||||
{
|
||||
base: 'N',
|
||||
letters: '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4'
|
||||
},
|
||||
{ base: 'NJ', letters: '\u01CA' },
|
||||
{ base: 'Nj', letters: '\u01CB' },
|
||||
{
|
||||
base: 'O',
|
||||
letters:
|
||||
'\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C'
|
||||
},
|
||||
{ base: 'OI', letters: '\u01A2' },
|
||||
{ base: 'OO', letters: '\uA74E' },
|
||||
{ base: 'OU', letters: '\u0222' },
|
||||
{ base: 'OE', letters: '\u008C\u0152' },
|
||||
{ base: 'oe', letters: '\u009C\u0153' },
|
||||
{ base: 'P', letters: '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754' },
|
||||
{ base: 'Q', letters: '\u0051\u24C6\uFF31\uA756\uA758\u024A' },
|
||||
{
|
||||
base: 'R',
|
||||
letters: '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782'
|
||||
},
|
||||
{
|
||||
base: 'S',
|
||||
letters: '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784'
|
||||
},
|
||||
{
|
||||
base: 'T',
|
||||
letters: '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786'
|
||||
},
|
||||
{ base: 'TZ', letters: '\uA728' },
|
||||
{
|
||||
base: 'U',
|
||||
letters:
|
||||
'\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244'
|
||||
},
|
||||
{ base: 'V', letters: '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245' },
|
||||
{ base: 'VY', letters: '\uA760' },
|
||||
{ base: 'W', letters: '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72' },
|
||||
{ base: 'X', letters: '\u0058\u24CD\uFF38\u1E8A\u1E8C' },
|
||||
{
|
||||
base: 'Y',
|
||||
letters: '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE'
|
||||
},
|
||||
{ base: 'Z', letters: '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762' },
|
||||
{
|
||||
base: 'a',
|
||||
letters:
|
||||
'\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250'
|
||||
},
|
||||
{ base: 'aa', letters: '\uA733' },
|
||||
{ base: 'ae', letters: '\u00E6\u01FD\u01E3' },
|
||||
{ base: 'ao', letters: '\uA735' },
|
||||
{ base: 'au', letters: '\uA737' },
|
||||
{ base: 'av', letters: '\uA739\uA73B' },
|
||||
{ base: 'ay', letters: '\uA73D' },
|
||||
{ base: 'b', letters: '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253' },
|
||||
{ base: 'c', letters: '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184' },
|
||||
{ base: 'd', letters: '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A' },
|
||||
{ base: 'dz', letters: '\u01F3\u01C6' },
|
||||
{
|
||||
base: 'e',
|
||||
letters:
|
||||
'\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD'
|
||||
},
|
||||
{ base: 'f', letters: '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C' },
|
||||
{
|
||||
base: 'g',
|
||||
letters: '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F'
|
||||
},
|
||||
{
|
||||
base: 'h',
|
||||
letters: '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265'
|
||||
},
|
||||
{ base: 'hv', letters: '\u0195' },
|
||||
{
|
||||
base: 'i',
|
||||
letters:
|
||||
'\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131'
|
||||
},
|
||||
{ base: 'j', letters: '\u006A\u24D9\uFF4A\u0135\u01F0\u0249' },
|
||||
{ base: 'k', letters: '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3' },
|
||||
{
|
||||
base: 'l',
|
||||
letters:
|
||||
'\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747'
|
||||
},
|
||||
{ base: 'lj', letters: '\u01C9' },
|
||||
{ base: 'm', letters: '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F' },
|
||||
{
|
||||
base: 'n',
|
||||
letters: '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5'
|
||||
},
|
||||
{ base: 'nj', letters: '\u01CC' },
|
||||
{
|
||||
base: 'o',
|
||||
letters:
|
||||
'\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275'
|
||||
},
|
||||
{ base: 'oi', letters: '\u01A3' },
|
||||
{ base: 'ou', letters: '\u0223' },
|
||||
{ base: 'oo', letters: '\uA74F' },
|
||||
{ base: 'p', letters: '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755' },
|
||||
{ base: 'q', letters: '\u0071\u24E0\uFF51\u024B\uA757\uA759' },
|
||||
{
|
||||
base: 'r',
|
||||
letters: '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783'
|
||||
},
|
||||
{
|
||||
base: 's',
|
||||
letters:
|
||||
'\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B'
|
||||
},
|
||||
{
|
||||
base: 't',
|
||||
letters: '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787'
|
||||
},
|
||||
{ base: 'tz', letters: '\uA729' },
|
||||
{
|
||||
base: 'u',
|
||||
letters:
|
||||
'\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289'
|
||||
},
|
||||
{ base: 'v', letters: '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C' },
|
||||
{ base: 'vy', letters: '\uA761' },
|
||||
{ base: 'w', letters: '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73' },
|
||||
{ base: 'x', letters: '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
|
||||
{
|
||||
base: 'y',
|
||||
letters: '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF'
|
||||
},
|
||||
{ base: 'z', letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763' }
|
||||
];
|
||||
|
||||
|
||||
// "what?" version ... http://jsperf.com/diacritics/12
|
||||
public static removeDiacriticsAndPunctuation (str) {
|
||||
|
||||
str = GBConversationalService.removeDiacritics(str);
|
||||
return str.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
|
||||
|
||||
return str.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, '');
|
||||
}
|
||||
public static removeDiacritics (str) {
|
||||
|
||||
var diacriticsMap = {};
|
||||
for (var i = 0; i < GBConversationalService.defaultDiacriticsRemovalMap.length; i++) {
|
||||
var letters = GBConversationalService.defaultDiacriticsRemovalMap[i].letters;
|
||||
|
@ -195,8 +281,6 @@ export class GBConversationalService {
|
|||
return str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public getNewMobileCode () {
|
||||
const passwordGenerator = new PasswordGenerator();
|
||||
const options = {
|
||||
|
@ -227,7 +311,6 @@ export class GBConversationalService {
|
|||
caption: string
|
||||
): Promise<any> {
|
||||
if (step !== null) {
|
||||
|
||||
mobile = this.userMobile(step);
|
||||
|
||||
if (mobile) {
|
||||
|
@ -254,10 +337,10 @@ export class GBConversationalService {
|
|||
}
|
||||
|
||||
public async sendEvent (min: GBMinInstance, step: GBDialogStep, name: string, value: Object): Promise<any> {
|
||||
if (!this.userMobile(step) &&
|
||||
step.context.activity.channelId !== 'msteams') {
|
||||
GBLog.info(`Sending event ${name}:${typeof value === 'object' ? JSON.stringify(value) :
|
||||
value ? value : ''} to client...`);
|
||||
if (!this.userMobile(step) && step.context.activity.channelId !== 'msteams') {
|
||||
GBLog.info(
|
||||
`Sending event ${name}:${typeof value === 'object' ? JSON.stringify(value) : value ? value : ''} to client...`
|
||||
);
|
||||
const msg = MessageFactory.text('');
|
||||
msg.value = value;
|
||||
msg.type = 'event';
|
||||
|
@ -276,16 +359,16 @@ export class GBConversationalService {
|
|||
method: 'POST',
|
||||
url: 'http://sms-api.megaconecta.com.br/mt',
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
"authorization": `Bearer ${min.instance.smsSecret}`
|
||||
'content-type': 'application/json',
|
||||
authorization: `Bearer ${min.instance.smsSecret}`
|
||||
},
|
||||
body: [
|
||||
{
|
||||
"numero": `${mobile}`,
|
||||
"servico": "short",
|
||||
"mensagem": text,
|
||||
"parceiro_id": "",
|
||||
"codificacao": "0"
|
||||
numero: `${mobile}`,
|
||||
servico: 'short',
|
||||
mensagem: text,
|
||||
parceiro_id: '',
|
||||
codificacao: '0'
|
||||
}
|
||||
],
|
||||
json: true
|
||||
|
@ -300,9 +383,9 @@ export class GBConversationalService {
|
|||
|
||||
return Promise.reject(new Error(msg));
|
||||
}
|
||||
}
|
||||
else {
|
||||
return new Promise((resolve: any, reject: any): any => {
|
||||
} else {
|
||||
return new Promise(
|
||||
(resolve: any, reject: any): any => {
|
||||
const nexmo = new Nexmo({
|
||||
apiKey: min.instance.smsKey,
|
||||
apiSecret: min.instance.smsSecret
|
||||
|
@ -316,9 +399,10 @@ export class GBConversationalService {
|
|||
} else {
|
||||
resolve(data);
|
||||
}
|
||||
}, );
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async sendToMobile (min: GBMinInstance, mobile: string, message: string, conversationId) {
|
||||
|
@ -326,13 +410,11 @@ export class GBConversationalService {
|
|||
await min.whatsAppDirectLine.sendToDevice(mobile, message, conversationId);
|
||||
}
|
||||
|
||||
|
||||
public static async getAudioBufferFromText (text): Promise<string> {
|
||||
return new Promise<string>(async (resolve, reject) => {
|
||||
const name = GBAdminService.getRndReadableIdentifier();
|
||||
|
||||
try {
|
||||
|
||||
const textToSpeech = new TextToSpeechV1({
|
||||
authenticator: new IamAuthenticator({ apikey: process.env.WATSON_TTS_KEY }),
|
||||
url: process.env.WATSON_TTS_URL
|
||||
|
@ -358,11 +440,12 @@ export class GBConversationalService {
|
|||
const transcoder = new prism.FFmpeg({
|
||||
args: ['-analyzeduration', '0', '-loglevel', '0', '-f', 'opus', '-ar', '16000', '-ac', '1']
|
||||
});
|
||||
Fs.createReadStream(waveFilename).pipe(transcoder).pipe(output);
|
||||
Fs.createReadStream(waveFilename)
|
||||
.pipe(transcoder)
|
||||
.pipe(output);
|
||||
|
||||
let url = urlJoin(GBServer.globals.publicAddress, 'audios', oggFilenameOnly);
|
||||
resolve(url);
|
||||
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
|
@ -437,13 +520,7 @@ export class GBConversationalService {
|
|||
});
|
||||
}
|
||||
|
||||
public async playMarkdown(
|
||||
min: GBMinInstance,
|
||||
answer: string,
|
||||
channel: string,
|
||||
step: GBDialogStep,
|
||||
mobile: string
|
||||
) {
|
||||
public async playMarkdown (min: GBMinInstance, answer: string, channel: string, step: GBDialogStep, mobile: string) {
|
||||
const user = step ? await min.userProfile.get(step.context, {}) : null;
|
||||
let text = answer;
|
||||
|
||||
|
@ -465,9 +542,16 @@ export class GBConversationalService {
|
|||
var videos = ['webm', 'mp4', 'mov'];
|
||||
var filetype = href.split('.').pop();
|
||||
if (videos.indexOf(filetype) > -1) {
|
||||
var out = '<video autoplay loop alt="' + text + '">'
|
||||
+ ' <source src="' + href + '" type="video/' + filetype + '">'
|
||||
+ '</video>'
|
||||
var out =
|
||||
'<video autoplay loop alt="' +
|
||||
text +
|
||||
'">' +
|
||||
' <source src="' +
|
||||
href +
|
||||
'" type="video/' +
|
||||
filetype +
|
||||
'">' +
|
||||
'</video>';
|
||||
return out;
|
||||
} else {
|
||||
return renderer.oldImage(href, title, text);
|
||||
|
@ -492,8 +576,7 @@ export class GBConversationalService {
|
|||
|
||||
text = text.replace('! [', '![').replace('] (', '](');
|
||||
text = text.replace(`[[embed url=`, process.env.BOT_URL + '/').replace(']]', ''); // TODO: Improve it.
|
||||
text = text.replace(`](kb`, "](" + process.env.BOT_URL + '/kb'); // TODO: Improve it.
|
||||
|
||||
text = text.replace(`](kb`, '](' + process.env.BOT_URL + '/kb'); // TODO: Improve it.
|
||||
|
||||
if (mobile) {
|
||||
await this.sendMarkdownToMobile(min, step, mobile, text);
|
||||
|
@ -506,12 +589,7 @@ export class GBConversationalService {
|
|||
}
|
||||
}
|
||||
|
||||
private async sendMarkdownToWeb(
|
||||
min,
|
||||
step: GBDialogStep,
|
||||
html: string,
|
||||
answer: string
|
||||
) {
|
||||
private async sendMarkdownToWeb (min, step: GBDialogStep, html: string, answer: string) {
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
html = html.replace(/src\=\"kb\//gi, `src=\"../kb/`);
|
||||
|
@ -521,12 +599,11 @@ export class GBConversationalService {
|
|||
content: html,
|
||||
answer: answer,
|
||||
prevId: 0, // TODO: answer.prevId,
|
||||
nextId: 0, // TODO: answer.nextId
|
||||
nextId: 0 // TODO: answer.nextId
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// tslint:enable:no-unsafe-any
|
||||
|
||||
public async sendMarkdownToMobile (min: GBMinInstance, step: GBDialogStep, mobile: string, text: string) {
|
||||
|
@ -699,7 +776,6 @@ export class GBConversationalService {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: Update botlib.
|
||||
public async routeNLP (step: GBDialogStep, min: GBMinInstance, text: string): Promise<boolean> {
|
||||
return false;
|
||||
|
@ -711,9 +787,9 @@ export class GBConversationalService {
|
|||
|
||||
text = text.toLowerCase();
|
||||
text = text.replace('who´s', 'who is');
|
||||
text = text.replace('who\'s', 'who is');
|
||||
text = text.replace("who's", 'who is');
|
||||
text = text.replace('what´s', 'what is');
|
||||
text = text.replace('what\'s', 'what is');
|
||||
text = text.replace("what's", 'what is');
|
||||
text = text.replace('?', ' ');
|
||||
text = text.replace('¿', ' ');
|
||||
text = text.replace('!', ' ');
|
||||
|
@ -732,10 +808,14 @@ export class GBConversationalService {
|
|||
try {
|
||||
const saved = step.context.activity.text;
|
||||
step.context.activity.text = text;
|
||||
nlp = await model.recognize(step.context, {}, {}, { IncludeAllIntents: false, IncludeInstanceData: false, includeAPIResults: true });
|
||||
nlp = await model.recognize(
|
||||
step.context,
|
||||
{},
|
||||
{},
|
||||
{ IncludeAllIntents: false, IncludeInstanceData: false, includeAPIResults: true }
|
||||
);
|
||||
step.context.activity.text = saved;
|
||||
} catch (error) {
|
||||
|
||||
// tslint:disable:no-unsafe-any
|
||||
if (error.statusCode === 404 || error.statusCode === 400) {
|
||||
GBLog.warn('NLP application still not publish and there are no other options for answering.');
|
||||
|
@ -753,8 +833,11 @@ export class GBConversationalService {
|
|||
const minBoot = GBServer.globals.minBoot as any;
|
||||
let nlpActive = false;
|
||||
let score = 0;
|
||||
const instanceScore = min.core.getParam(min.instance, 'NLP Score',
|
||||
min.instance.nlpScore ? min.instance.nlpScore : minBoot.instance.nlpScore);
|
||||
const instanceScore = min.core.getParam(
|
||||
min.instance,
|
||||
'NLP Score',
|
||||
min.instance.nlpScore ? min.instance.nlpScore : minBoot.instance.nlpScore
|
||||
);
|
||||
|
||||
Object.keys(nlp.intents).forEach(name => {
|
||||
score = nlp.intents[name].score;
|
||||
|
@ -773,7 +856,9 @@ export class GBConversationalService {
|
|||
}
|
||||
|
||||
GBLog.info(
|
||||
`NLP called: ${intent}, entities: ${nlp.entities.length}, score: ${score} > required (nlpScore): ${instanceScore}`
|
||||
`NLP called: ${intent}, entities: ${
|
||||
nlp.entities.length
|
||||
}, score: ${score} > required (nlpScore): ${instanceScore}`
|
||||
);
|
||||
|
||||
step.activeDialog.state.options.entities = nlp.entities;
|
||||
|
@ -782,7 +867,7 @@ export class GBConversationalService {
|
|||
|
||||
if (nlp.entities) {
|
||||
await CollectionUtil.asyncForEach(Object.keys(nlp.entities), async key => {
|
||||
if (key !== "$instance") {
|
||||
if (key !== '$instance') {
|
||||
let entity = nlp.entities[key];
|
||||
if (Array.isArray(entity[0])) {
|
||||
nlp.entities[key] = entity.slice(1);
|
||||
|
@ -794,9 +879,7 @@ export class GBConversationalService {
|
|||
return await step.replaceDialog(`/${intent}`, step.activeDialog.state.options);
|
||||
}
|
||||
|
||||
GBLog.info(
|
||||
`NLP NOT called: score: ${score} > required (nlpScore): ${instanceScore}`
|
||||
);
|
||||
GBLog.info(`NLP NOT called: score: ${score} > required (nlpScore): ${instanceScore}`);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -816,8 +899,7 @@ export class GBConversationalService {
|
|||
}
|
||||
|
||||
public async spellCheck (min: GBMinInstance, text: string): Promise<string> {
|
||||
const key =
|
||||
min.core.getParam<string>(min.instance, 'spellcheckerKey', null);
|
||||
const key = min.core.getParam<string>(min.instance, 'spellcheckerKey', null);
|
||||
|
||||
if (key) {
|
||||
text = text.charAt(0).toUpperCase() + text.slice(1);
|
||||
|
@ -842,7 +924,11 @@ export class GBConversationalService {
|
|||
const endPoint = min.core.getParam<string>(min.instance, 'translatorEndpoint', null);
|
||||
const key = min.core.getParam<string>(min.instance, 'translatorKey', null);
|
||||
|
||||
if ((endPoint === null && !min.instance.googleProjectId) || !translatorEnabled() || process.env.TRANSLATOR_DISABLED === 'true') {
|
||||
if (
|
||||
(endPoint === null && !min.instance.googleProjectId) ||
|
||||
!translatorEnabled() ||
|
||||
process.env.TRANSLATOR_DISABLED === 'true'
|
||||
) {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -859,11 +945,13 @@ export class GBConversationalService {
|
|||
|
||||
const translate = new Translate.v2.Translate({
|
||||
projectId: min.instance.googleProjectId,
|
||||
credentials: { client_email: min.instance.googleClientEmail, private_key: min.instance.googlePrivateKey.replace(/\\n/gm, '\n') }
|
||||
credentials: {
|
||||
client_email: min.instance.googleClientEmail,
|
||||
private_key: min.instance.googlePrivateKey.replace(/\\n/gm, '\n')
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
const [translation] = await translate.translate(text, language);
|
||||
|
||||
return translation;
|
||||
|
@ -872,10 +960,7 @@ export class GBConversationalService {
|
|||
|
||||
return Promise.reject(new Error(msg));
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
} else {
|
||||
let options = {
|
||||
method: 'POST',
|
||||
baseUrl: endPoint,
|
||||
|
@ -899,7 +984,6 @@ export class GBConversationalService {
|
|||
};
|
||||
|
||||
try {
|
||||
|
||||
const results = await request(options);
|
||||
|
||||
return results[0].translations[0].text;
|
||||
|
@ -915,7 +999,7 @@ export class GBConversationalService {
|
|||
const user = await min.userProfile.get(step.context, {});
|
||||
const systemUser = user.systemUser;
|
||||
|
||||
if (text && text !== "") {
|
||||
if (text && text !== '') {
|
||||
text = await min.conversationalService.translate(
|
||||
min,
|
||||
text,
|
||||
|
@ -925,14 +1009,11 @@ export class GBConversationalService {
|
|||
);
|
||||
GBLog.verbose(`Translated text(prompt): ${text}.`);
|
||||
}
|
||||
if (step.activeDialog.state.options['kind'] === "file") {
|
||||
if (step.activeDialog.state.options['kind'] === 'file') {
|
||||
return await step.prompt('attachmentPrompt', {});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.prompt('textPrompt', text ? text : {});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public async sendText (min: GBMinInstance, step, text) {
|
||||
|
@ -966,9 +1047,7 @@ export class GBConversationalService {
|
|||
text = await min.conversationalService.translate(
|
||||
min,
|
||||
text,
|
||||
locale
|
||||
? locale
|
||||
: min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
||||
locale ? locale : min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
||||
);
|
||||
|
||||
if (keepTextList) {
|
||||
|
@ -989,15 +1068,12 @@ export class GBConversationalService {
|
|||
analytics.createMessage(min.instance.instanceId, user.conversation, null, text);
|
||||
|
||||
if (!isNaN(member.id) && !member.id.startsWith('1000')) {
|
||||
|
||||
const to = step.context.activity.group ? step.context.activity.group : member.id;
|
||||
|
||||
await min.whatsAppDirectLine.sendToDevice(to, text, step.context.activity.conversation.id);
|
||||
} else {
|
||||
await step.context.sendActivity(text);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public async broadcast (min: GBMinInstance, message: string) {
|
||||
|
@ -1025,21 +1101,18 @@ export class GBConversationalService {
|
|||
* Sends a message in a user with an already started conversation (got ConversationReference set)
|
||||
*/
|
||||
public async sendOnConversation (min: GBMinInstance, user: GuaribasUser, message: string) {
|
||||
|
||||
if (user.conversationReference.startsWith('spaces')) {
|
||||
await min['googleDirectLine'].sendToDevice(user.userSystemId, null, user.conversationReference, message);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const ref = JSON.parse(user.conversationReference);
|
||||
MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl);
|
||||
try {
|
||||
await min.bot['continueConversation'](ref, async (t1) => {
|
||||
await min.bot['continueConversation'](ref, async t1 => {
|
||||
const ref2 = TurnContext.getConversationReference(t1.activity);
|
||||
await min.bot.continueConversation(ref2, async (t2) => {
|
||||
await min.bot.continueConversation(ref2, async t2 => {
|
||||
await t2.sendActivity(message);
|
||||
});
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
@ -1049,32 +1122,26 @@ export class GBConversationalService {
|
|||
public static kmpSearch (pattern, text) {
|
||||
pattern = pattern.toLowerCase();
|
||||
text = text.toLowerCase();
|
||||
if (pattern.length == 0)
|
||||
return 0; // Immediate match
|
||||
if (pattern.length == 0) return 0; // Immediate match
|
||||
|
||||
// Compute longest suffix-prefix table
|
||||
var lsp = [0]; // Base case
|
||||
for (var i = 1; i < pattern.length; i++) {
|
||||
var j = lsp[i - 1]; // Start by assuming we're extending the previous LSP
|
||||
while (j > 0 && pattern.charAt(i) != pattern.charAt(j))
|
||||
j = lsp[j - 1];
|
||||
if (pattern.charAt(i) == pattern.charAt(j))
|
||||
j++;
|
||||
while (j > 0 && pattern.charAt(i) != pattern.charAt(j)) j = lsp[j - 1];
|
||||
if (pattern.charAt(i) == pattern.charAt(j)) j++;
|
||||
lsp.push(j);
|
||||
}
|
||||
|
||||
// Walk through text string
|
||||
var j = 0; // Number of chars matched in pattern
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
while (j > 0 && text.charAt(i) != pattern.charAt(j))
|
||||
j = lsp[j - 1]; // Fall back in the pattern
|
||||
while (j > 0 && text.charAt(i) != pattern.charAt(j)) j = lsp[j - 1]; // Fall back in the pattern
|
||||
if (text.charAt(i) == pattern.charAt(j)) {
|
||||
j++; // Next char matched, increment position
|
||||
if (j == pattern.length)
|
||||
return i - (j - 1);
|
||||
if (j == pattern.length) return i - (j - 1);
|
||||
}
|
||||
}
|
||||
return -1; // Not found
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -192,7 +192,6 @@ export class GBCoreService implements IGBCoreService {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Syncronizes structure between model and tables in storage.
|
||||
*/
|
||||
|
@ -290,7 +289,6 @@ ENDPOINT_UPDATE=true
|
|||
Fs.writeFileSync('.env', env);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Certifies that network servers will reach back the development machine
|
||||
* when calling back from web services. This ensures that reverse proxy is
|
||||
|
@ -299,7 +297,6 @@ ENDPOINT_UPDATE=true
|
|||
public async ensureProxy (port): Promise<string> {
|
||||
try {
|
||||
if (Fs.existsSync('node_modules/ngrok/bin/ngrok.exe') || Fs.existsSync('node_modules/ngrok/bin/ngrok')) {
|
||||
|
||||
return await ngrok.connect({ port: port });
|
||||
} else {
|
||||
GBLog.warn('ngrok executable not found (only tested on Windows). Check installation or node_modules folder.');
|
||||
|
@ -550,12 +547,17 @@ ENDPOINT_UPDATE=true
|
|||
if (matches !== null) {
|
||||
const table = matches[1];
|
||||
const re2 = /PRIMARY\s+KEY\s+\(\[[^\]]*\](?:,\s*\[[^\]]*\])*\)/;
|
||||
sql = sql.replace(re2, (match: string, ...args: any[]): string => {
|
||||
sql = sql.replace(
|
||||
re2,
|
||||
(match: string, ...args: any[]): string => {
|
||||
return `CONSTRAINT [${table}_pk] ${match}`;
|
||||
});
|
||||
}
|
||||
);
|
||||
const re3 = /FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g;
|
||||
const re4 = /\[([^\]]*)\]/g;
|
||||
sql = sql.replace(re3, (match: string, ...args: any[]): string => {
|
||||
sql = sql.replace(
|
||||
re3,
|
||||
(match: string, ...args: any[]): string => {
|
||||
const fkcols = args[0];
|
||||
let fkname = table;
|
||||
let matches2 = re4.exec(fkcols);
|
||||
|
@ -565,7 +567,8 @@ ENDPOINT_UPDATE=true
|
|||
}
|
||||
|
||||
return `CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`;
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return sql;
|
||||
|
@ -587,7 +590,9 @@ ENDPOINT_UPDATE=true
|
|||
const table = matches[1];
|
||||
const re2 = /(ADD\s+)?CONSTRAINT\s+\[([^\]]*)\]\s+FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g;
|
||||
const re3 = /\[([^\]]*)\]/g;
|
||||
sql = sql.replace(re2, (match: string, ...args: any[]): string => {
|
||||
sql = sql.replace(
|
||||
re2,
|
||||
(match: string, ...args: any[]): string => {
|
||||
const fkcols = args[2];
|
||||
let fkname = table;
|
||||
let matches2 = re3.exec(fkcols);
|
||||
|
@ -597,7 +602,8 @@ ENDPOINT_UPDATE=true
|
|||
}
|
||||
|
||||
return `${args[0] ? args[0] : ''}CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`;
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return sql;
|
||||
|
@ -647,5 +653,4 @@ ENDPOINT_UPDATE=true
|
|||
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ import express from 'express';
|
|||
import child_process from 'child_process';
|
||||
import rimraf from 'rimraf';
|
||||
import request from 'request-promise-native';
|
||||
import vhost from 'vhost'
|
||||
import vhost from 'vhost';
|
||||
import urlJoin from 'url-join';
|
||||
import Fs from 'fs';
|
||||
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBDeployer, IGBInstance, IGBPackage } from 'botlib';
|
||||
|
@ -58,12 +58,10 @@ import { GBImporter } from './GBImporterService.js';
|
|||
import { TeamsService } from '../../teams.gblib/services/TeamsService.js';
|
||||
import MicrosoftGraph from '@microsoft/microsoft-graph-client';
|
||||
|
||||
|
||||
/**
|
||||
* Deployer service for bots, themes, ai and more.
|
||||
*/
|
||||
export class GBDeployer implements IGBDeployer {
|
||||
|
||||
/**
|
||||
* Where should deployer look into for general packages.
|
||||
*/
|
||||
|
@ -97,7 +95,9 @@ export class GBDeployer implements IGBDeployer {
|
|||
* use to database like the Indexer (Azure Search).
|
||||
*/
|
||||
public static getConnectionStringFromInstance (instance: IGBInstance) {
|
||||
return `Server=tcp:${instance.storageServer},1433;Database=${instance.storageName};User ID=${instance.storageUsername};Password=${instance.storagePassword};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;`;
|
||||
return `Server=tcp:${instance.storageServer},1433;Database=${instance.storageName};User ID=${
|
||||
instance.storageUsername
|
||||
};Password=${instance.storagePassword};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,7 +121,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
* Performs package deployment in all .gbai or default.
|
||||
*/
|
||||
public async deployPackages (core: IGBCoreService, server: any, appPackages: IGBPackage[]) {
|
||||
|
||||
// Builds lists of paths to search for packages.
|
||||
|
||||
let paths = [urlJoin(process.env.PWD, GBDeployer.deployFolder), urlJoin(process.env.PWD, GBDeployer.workFolder)];
|
||||
|
@ -134,7 +133,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
const generalPackages: string[] = [];
|
||||
|
||||
async function scanPackageDirectory (path) {
|
||||
|
||||
// Gets all directories.
|
||||
|
||||
const isDirectory = source => Fs.lstatSync(source).isDirectory();
|
||||
|
@ -144,7 +142,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
.filter(isDirectory);
|
||||
const dirs = getDirectories(path);
|
||||
await CollectionUtil.asyncForEach(dirs, async element => {
|
||||
|
||||
// For each folder, checks its extensions looking for valid packages.
|
||||
|
||||
if (element === '.') {
|
||||
|
@ -154,8 +151,9 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
// Skips what does not need to be loaded.
|
||||
|
||||
if (process.env.GBAPP_SKIP && (process.env.GBAPP_SKIP.toLowerCase().indexOf(name) !== -1
|
||||
|| process.env.GBAPP_SKIP === 'true')
|
||||
if (
|
||||
process.env.GBAPP_SKIP &&
|
||||
(process.env.GBAPP_SKIP.toLowerCase().indexOf(name) !== -1 || process.env.GBAPP_SKIP === 'true')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -204,7 +202,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
* Deploys a new blank bot to the database, cognitive services and other services.
|
||||
*/
|
||||
public async deployBlankBot (botId: string, mobile: string, email: string) {
|
||||
|
||||
// Creates a new row on the GuaribasInstance table.
|
||||
|
||||
const instance = await this.importer.createBotInstance(botId);
|
||||
|
@ -256,7 +253,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
* Performs all tasks of deploying a new bot on the cloud.
|
||||
*/
|
||||
public async deployBotFull (instance: IGBInstance, publicAddress: string): Promise<IGBInstance> {
|
||||
|
||||
// Reads base configuration from environent file.
|
||||
|
||||
const service = new AzureDeployerService(this);
|
||||
|
@ -328,9 +324,10 @@ export class GBDeployer implements IGBDeployer {
|
|||
*/
|
||||
public async publishNLP (instance: IGBInstance): Promise<void> {
|
||||
const service = new AzureDeployerService(this);
|
||||
const res = await service.publishNLP(instance.cloudLocation, instance.nlpAppId,
|
||||
instance.nlpAuthoringKey);
|
||||
if (res.status !== 200 && res.status !== 201) { throw res.bodyAsText; }
|
||||
const res = await service.publishNLP(instance.cloudLocation, instance.nlpAppId, instance.nlpAuthoringKey);
|
||||
if (res.status !== 200 && res.status !== 201) {
|
||||
throw res.bodyAsText;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -339,7 +336,9 @@ export class GBDeployer implements IGBDeployer {
|
|||
public async trainNLP (instance: IGBInstance): Promise<void> {
|
||||
const service = new AzureDeployerService(this);
|
||||
const res = await service.trainNLP(instance.cloudLocation, instance.nlpAppId, instance.nlpAuthoringKey);
|
||||
if (res.status !== 200 && res.status !== 202) { throw res.bodyAsText; }
|
||||
if (res.status !== 200 && res.status !== 202) {
|
||||
throw res.bodyAsText;
|
||||
}
|
||||
const sleep = ms => {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, ms);
|
||||
|
@ -353,8 +352,14 @@ export class GBDeployer implements IGBDeployer {
|
|||
*/
|
||||
public async getBotManifest (instance: IGBInstance): Promise<Buffer> {
|
||||
const s = new TeamsService();
|
||||
const manifest = await s.getManifest(instance.marketplaceId, instance.title, instance.description,
|
||||
GBAdminService.generateUuid(), instance.botId, "General Bots");
|
||||
const manifest = await s.getManifest(
|
||||
instance.marketplaceId,
|
||||
instance.title,
|
||||
instance.description,
|
||||
GBAdminService.generateUuid(),
|
||||
instance.botId,
|
||||
'General Bots'
|
||||
);
|
||||
|
||||
return await s.getAppFile(manifest);
|
||||
}
|
||||
|
@ -371,7 +376,9 @@ export class GBDeployer implements IGBDeployer {
|
|||
instance.nlpAuthoringKey,
|
||||
listData
|
||||
);
|
||||
if (res.status !== 200) { throw res.bodyAsText; }
|
||||
if (res.status !== 200) {
|
||||
throw res.bodyAsText;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -408,9 +415,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
let url = `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:${path}:/children`;
|
||||
|
||||
GBLog.info(`Loading .gbot from Excel: ${url}`);
|
||||
const res = await client
|
||||
.api(url)
|
||||
.get();
|
||||
const res = await client.api(url).get();
|
||||
|
||||
// Finds Config.xlsx.
|
||||
|
||||
|
@ -428,10 +433,13 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
const results = await client
|
||||
.api(
|
||||
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/items/${document[0].id}/workbook/worksheets('General')/range(address='A7:B100')`
|
||||
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/items/${
|
||||
document[0].id
|
||||
}/workbook/worksheets('General')/range(address='A7:B100')`
|
||||
)
|
||||
.get();
|
||||
let index = 0, obj = {};
|
||||
let index = 0,
|
||||
obj = {};
|
||||
for (; index < results.text.length; index++) {
|
||||
if (results.text[index][0] === '') {
|
||||
return obj;
|
||||
|
@ -445,10 +453,13 @@ export class GBDeployer implements IGBDeployer {
|
|||
/**
|
||||
* Loads all para from tabular file Config.xlsx.
|
||||
*/
|
||||
public async downloadFolder(min: GBMinInstance, localPath: string, remotePath: string,
|
||||
baseUrl: string = null, client = null): Promise<any> {
|
||||
|
||||
|
||||
public async downloadFolder (
|
||||
min: GBMinInstance,
|
||||
localPath: string,
|
||||
remotePath: string,
|
||||
baseUrl: string = null,
|
||||
client = null
|
||||
): Promise<any> {
|
||||
GBLog.info(`downloadFolder: localPath=${localPath}, remotePath=${remotePath}, baseUrl=${baseUrl}`);
|
||||
|
||||
if (!baseUrl) {
|
||||
|
@ -479,9 +490,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
GBLog.info(`Download URL: ${url}`);
|
||||
|
||||
const res = await client.client
|
||||
.api(url)
|
||||
.get();
|
||||
const res = await client.client.api(url).get();
|
||||
const documents = res.value;
|
||||
if (documents === undefined || documents.length === 0) {
|
||||
GBLog.info(`${remotePath} is an empty folder.`);
|
||||
|
@ -491,7 +500,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
// Download files or navigate to directory to recurse.
|
||||
|
||||
await CollectionUtil.asyncForEach(documents, async item => {
|
||||
|
||||
const itemPath = Path.join(localPath, remotePath, item.name);
|
||||
|
||||
if (item.folder) {
|
||||
|
@ -516,10 +524,8 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
const response = await request({ uri: url, encoding: null });
|
||||
Fs.writeFileSync(itemPath, response, { encoding: null });
|
||||
Fs.utimesSync(itemPath,
|
||||
new Date(), new Date(item.lastModifiedDateTime));
|
||||
}
|
||||
else {
|
||||
Fs.utimesSync(itemPath, new Date(), new Date(item.lastModifiedDateTime));
|
||||
} else {
|
||||
GBLog.info(`Local is up to date: ${itemPath}...`);
|
||||
}
|
||||
}
|
||||
|
@ -530,7 +536,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
* UndDeploys a bot to the storage.
|
||||
*/
|
||||
public async undeployBot (botId: string, packageName: string): Promise<void> {
|
||||
|
||||
// Deletes Bot registration on cloud.
|
||||
|
||||
const service = new AzureDeployerService(this);
|
||||
|
@ -562,7 +567,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
* Deploys a folder into the bot storage.
|
||||
*/
|
||||
public async deployPackage (min: GBMinInstance, localPath: string) {
|
||||
|
||||
const packageType = Path.extname(localPath);
|
||||
let handled = false;
|
||||
let pck = null;
|
||||
|
@ -572,7 +576,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
const _this = this;
|
||||
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
|
||||
try {
|
||||
|
||||
// If it will be handled, create a temporary service layer to be
|
||||
// called by .gbapp and manage the associated package row.
|
||||
|
||||
|
@ -605,7 +608,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
switch (packageType) {
|
||||
case '.gbot':
|
||||
|
||||
// Extracts configuration information from .gbot files.
|
||||
|
||||
if (process.env.ENABLE_PARAMS_ONLINE === 'false') {
|
||||
|
@ -624,7 +626,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
break;
|
||||
|
||||
case '.gbkb':
|
||||
|
||||
// Deploys .gbkb into the storage.
|
||||
|
||||
const service = new KBService(this.core.sequelize);
|
||||
|
@ -632,7 +633,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
break;
|
||||
|
||||
case '.gbdialog':
|
||||
|
||||
// Compiles files from .gbdialog into work folder and deploys
|
||||
// it to the VM.
|
||||
|
||||
|
@ -642,7 +642,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
break;
|
||||
|
||||
case '.gbtheme':
|
||||
|
||||
// Updates server listeners to serve theme files in .gbtheme.
|
||||
|
||||
const packageName = Path.basename(localPath);
|
||||
|
@ -652,21 +651,18 @@ export class GBDeployer implements IGBDeployer {
|
|||
break;
|
||||
|
||||
case '.gbapp':
|
||||
|
||||
// Dynamically compiles and loads .gbapp packages (Node.js packages).
|
||||
|
||||
await this.callGBAppCompiler(localPath, this.core);
|
||||
break;
|
||||
|
||||
case '.gblib':
|
||||
|
||||
// Dynamically compiles and loads .gblib packages (Node.js packages).
|
||||
|
||||
await this.callGBAppCompiler(localPath, this.core);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
const err = GBError.create(`Unhandled package type: ${packageType}.`);
|
||||
Promise.reject(err);
|
||||
break;
|
||||
|
@ -677,7 +673,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
* Removes the package from the storage and local work folders.
|
||||
*/
|
||||
public async undeployPackageFromLocalPath (instance: IGBInstance, localPath: string) {
|
||||
|
||||
// Gets information about the package.
|
||||
|
||||
const packageType = Path.extname(localPath);
|
||||
|
@ -687,7 +682,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
// Removes objects from storage, cloud resources and local files if any.
|
||||
|
||||
switch (packageType) {
|
||||
|
||||
case '.gbot':
|
||||
const packageObject = JSON.parse(Fs.readFileSync(urlJoin(localPath, 'package.json'), 'utf8'));
|
||||
await this.undeployBot(packageObject.botId, packageName);
|
||||
|
@ -727,7 +721,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
* its index based on .gbkb structure.
|
||||
*/
|
||||
public async rebuildIndex (instance: IGBInstance, searchSchema: any) {
|
||||
|
||||
// Prepares search.
|
||||
|
||||
const search = new AzureSearch(
|
||||
|
@ -744,11 +737,9 @@ export class GBDeployer implements IGBDeployer {
|
|||
try {
|
||||
await search.deleteDataSource(dsName);
|
||||
} catch (err) {
|
||||
|
||||
// If it is a 404 there is nothing to delete as it is the first creation.
|
||||
|
||||
if (err.code !== 404) {
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
@ -758,10 +749,9 @@ export class GBDeployer implements IGBDeployer {
|
|||
try {
|
||||
await search.deleteIndex();
|
||||
} catch (err) {
|
||||
|
||||
// If it is a 404 there is nothing to delete as it is the first creation.
|
||||
|
||||
if (err.code !== 404 && err.code !== "OperationNotAllowed") {
|
||||
if (err.code !== 404 && err.code !== 'OperationNotAllowed') {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
@ -793,7 +783,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
* makes this web application available as default web front-end.
|
||||
*/
|
||||
public setupDefaultGBUI () {
|
||||
|
||||
// Setups paths.
|
||||
|
||||
const root = 'packages/default.gbui';
|
||||
|
@ -802,7 +791,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
// Checks if .gbapp compiliation is enabled.
|
||||
|
||||
if (!Fs.existsSync(`${root}/build`) && process.env.DISABLE_WEB !== 'true') {
|
||||
|
||||
// Write a .env required to fix some bungs in create-react-app tool.
|
||||
|
||||
Fs.writeFileSync(`${root}/.env`, 'SKIP_PREFLIGHT_CHECK=true');
|
||||
|
@ -822,7 +810,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
* Servers bot storage assets to be used by web, WhatsApp and other channels.
|
||||
*/
|
||||
public static mountGBKBAssets (packageName: any, botId: string, filename: string) {
|
||||
|
||||
// Servers menu assets.
|
||||
|
||||
GBServer.globals.server.use(
|
||||
|
@ -833,20 +820,27 @@ export class GBDeployer implements IGBDeployer {
|
|||
// Servers all other assets in .gbkb folders.
|
||||
|
||||
const gbaiName = `${botId}.gbai`;
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/assets`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'assets')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/images`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'images')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/audios`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'audios')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/videos`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'videos')));
|
||||
GBServer.globals.server.use(`/${botId}/cache`,
|
||||
express.static(urlJoin('work', gbaiName, 'cache')));
|
||||
GBServer.globals.server.use(`/${gbaiName}/${botId}.gbdata/public`,
|
||||
express.static(urlJoin('work', gbaiName, `${botId}.gbdata`, 'public')));
|
||||
|
||||
|
||||
GBServer.globals.server.use(
|
||||
`/kb/${gbaiName}/${packageName}/assets`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'assets'))
|
||||
);
|
||||
GBServer.globals.server.use(
|
||||
`/kb/${gbaiName}/${packageName}/images`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'images'))
|
||||
);
|
||||
GBServer.globals.server.use(
|
||||
`/kb/${gbaiName}/${packageName}/audios`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'audios'))
|
||||
);
|
||||
GBServer.globals.server.use(
|
||||
`/kb/${gbaiName}/${packageName}/videos`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'videos'))
|
||||
);
|
||||
GBServer.globals.server.use(`/${botId}/cache`, express.static(urlJoin('work', gbaiName, 'cache')));
|
||||
GBServer.globals.server.use(
|
||||
`/${gbaiName}/${botId}.gbdata/public`,
|
||||
express.static(urlJoin('work', gbaiName, `${botId}.gbdata`, 'public'))
|
||||
);
|
||||
|
||||
GBLog.verbose(`KB (.gbkb) assets accessible at: /kb/${botId}.gbai/${packageName}.`);
|
||||
}
|
||||
|
@ -860,7 +854,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
appPackages: any[] = undefined,
|
||||
appPackagesProcessed: number = 0
|
||||
) {
|
||||
|
||||
// Runs `npm install` for the package.
|
||||
|
||||
GBLog.info(`Deploying General Bots Application (.gbapp) or Library (.gblib): ${Path.basename(gbappPath)}...`);
|
||||
|
@ -874,7 +867,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
folder = Path.join(gbappPath, 'dist');
|
||||
try {
|
||||
|
||||
// Runs TSC in .gbapp folder.
|
||||
|
||||
if (process.env.GBAPP_DISABLE_COMPILE !== 'true') {
|
||||
|
@ -896,7 +888,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
}
|
||||
GBLog.info(`.gbapp or .gblib deployed: ${gbappPath}.`);
|
||||
appPackagesProcessed++;
|
||||
|
||||
} catch (error) {
|
||||
GBLog.error(`Error compiling package, message: ${error.message}\n${error.stack}`);
|
||||
if (error.stdout) {
|
||||
|
@ -936,7 +927,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
* Performs the process of compiling all .gbapp folders.
|
||||
*/
|
||||
private async deployAppPackages (gbappPackages: string[], core: any, appPackages: any[]) {
|
||||
|
||||
// Loops through all ready to load .gbapp packages.
|
||||
|
||||
let appPackagesProcessed = 0;
|
||||
|
|
|
@ -54,8 +54,12 @@ export class GBImporter {
|
|||
this.core = core;
|
||||
}
|
||||
|
||||
public async importIfNotExistsBotPackage(botId: string,
|
||||
packageName: string, localPath: string, additionalInstance: IGBInstance = null) {
|
||||
public async importIfNotExistsBotPackage (
|
||||
botId: string,
|
||||
packageName: string,
|
||||
localPath: string,
|
||||
additionalInstance: IGBInstance = null
|
||||
) {
|
||||
const settingsJson = JSON.parse(Fs.readFileSync(urlJoin(localPath, 'settings.json'), 'utf8'));
|
||||
if (botId === undefined) {
|
||||
botId = settingsJson.botId;
|
||||
|
|
|
@ -93,7 +93,6 @@ import * as nlp from 'node-nlp';
|
|||
* Minimal service layer for a bot and encapsulation of BOT Framework calls.
|
||||
*/
|
||||
export class GBMinService {
|
||||
|
||||
/**
|
||||
* Default General Bots User Interface package.
|
||||
*/
|
||||
|
@ -119,7 +118,6 @@ export class GBMinService {
|
|||
*/
|
||||
public deployer: GBDeployer;
|
||||
|
||||
|
||||
bar1;
|
||||
|
||||
/**
|
||||
|
@ -141,16 +139,14 @@ export class GBMinService {
|
|||
* Constructs a new minimal instance for each bot.
|
||||
*/
|
||||
public async buildMin (instances: IGBInstance[]) {
|
||||
|
||||
// Servers default UI on root address '/' if web enabled.
|
||||
|
||||
if (process.env.DISABLE_WEB !== 'true') {
|
||||
|
||||
// SSR processing.
|
||||
|
||||
const defaultOptions = {
|
||||
prerender: [],
|
||||
exclude: ["/api/", "/instances/", "/webhooks/"],
|
||||
exclude: ['/api/', '/instances/', '/webhooks/'],
|
||||
useCache: true,
|
||||
cacheRefreshRate: 86400
|
||||
};
|
||||
|
@ -164,25 +160,27 @@ export class GBMinService {
|
|||
|
||||
GBServer.globals.server.use('/', express.static(url));
|
||||
|
||||
|
||||
// Servers the bot information object via HTTP so clients can get
|
||||
// instance information stored on server.
|
||||
|
||||
|
||||
GBServer.globals.server.get('/instances/:botId', this.handleGetInstanceForClient.bind(this));
|
||||
}
|
||||
// Calls mountBot event to all bots.
|
||||
let i = 1;
|
||||
|
||||
if (instances.length > 1) {
|
||||
this.bar1 = new cliProgress.SingleBar({
|
||||
format: '[{bar}] ({value}/{total}) Loading {botId} ...', barsize: 40,
|
||||
this.bar1 = new cliProgress.SingleBar(
|
||||
{
|
||||
format: '[{bar}] ({value}/{total}) Loading {botId} ...',
|
||||
barsize: 40,
|
||||
forceRedraw: true
|
||||
}, cliProgress.Presets.rect);
|
||||
this.bar1.start(instances.length, i, { botId: "Boot" });
|
||||
},
|
||||
cliProgress.Presets.rect
|
||||
);
|
||||
this.bar1.start(instances.length, i, { botId: 'Boot' });
|
||||
}
|
||||
|
||||
const throttledPromiseAll = async (promises) => {
|
||||
const throttledPromiseAll = async promises => {
|
||||
const MAX_IN_PROCESS = 20;
|
||||
const results = new Array(promises.length);
|
||||
|
||||
|
@ -203,19 +201,21 @@ export class GBMinService {
|
|||
return results;
|
||||
};
|
||||
|
||||
await throttledPromiseAll(instances.map((async instance => {
|
||||
await throttledPromiseAll(
|
||||
instances.map(
|
||||
(async instance => {
|
||||
try {
|
||||
await this['mountBot'](instance);
|
||||
|
||||
if (this.bar1) {
|
||||
this.bar1.update(i++, { botId: instance.botId });
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
GBLog.error(`Error mounting bot ${instance.botId}: ${error.message}\n${error.stack}`);
|
||||
}
|
||||
|
||||
}).bind(this)));
|
||||
}).bind(this)
|
||||
)
|
||||
);
|
||||
if (this.bar1) {
|
||||
this.bar1.stop();
|
||||
}
|
||||
|
@ -229,8 +229,6 @@ export class GBMinService {
|
|||
GBLog.info(`All Bot instances loaded.`);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Removes bot endpoint from web listeners and remove bot instance
|
||||
* from list of global server bot instances.
|
||||
|
@ -243,7 +241,6 @@ export class GBMinService {
|
|||
removeRoute(GBServer.globals.server, uiUrl);
|
||||
|
||||
GBServer.globals.minInstances = GBServer.globals.minInstances.filter(p => p.instance.botId !== botId);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -252,7 +249,6 @@ export class GBMinService {
|
|||
* installing all BASIC artifacts from .gbdialog and OAuth2.
|
||||
*/
|
||||
public async mountBot (instance: IGBInstance) {
|
||||
|
||||
// Build bot adapter.
|
||||
|
||||
const { min, adapter, conversationState } = await this.buildBotAdapter(
|
||||
|
@ -329,11 +325,11 @@ export class GBMinService {
|
|||
|
||||
// Test code.
|
||||
if (process.env.TEST_MESSAGE) {
|
||||
|
||||
GBLog.info(`Starting auto test with '${process.env.TEST_MESSAGE}'.`);
|
||||
|
||||
const client = await new Swagger({
|
||||
spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')), usePromise: true
|
||||
spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')),
|
||||
usePromise: true
|
||||
});
|
||||
client.clientAuthorizations.add(
|
||||
'AuthorizationBotConnector',
|
||||
|
@ -351,7 +347,6 @@ export class GBMinService {
|
|||
};
|
||||
|
||||
await CollectionUtil.asyncForEach(steps, async step => {
|
||||
|
||||
client.Conversations.Conversations_PostActivity({
|
||||
conversationId: conversationId,
|
||||
activity: {
|
||||
|
@ -366,8 +361,6 @@ export class GBMinService {
|
|||
});
|
||||
|
||||
await sleep(5000);
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -411,15 +404,14 @@ export class GBMinService {
|
|||
|
||||
this.createCheckHealthAddress(GBServer.globals.server, min, min.instance);
|
||||
|
||||
GBDeployer.mountGBKBAssets(`${instance.botId}.gbkb`,
|
||||
instance.botId, `${instance.botId}.gbkb`);
|
||||
GBDeployer.mountGBKBAssets(`${instance.botId}.gbkb`, instance.botId, `${instance.botId}.gbkb`);
|
||||
}
|
||||
|
||||
public static isChatAPI (req, res) {
|
||||
if (!res) {
|
||||
return "GeneralBots";
|
||||
return 'GeneralBots';
|
||||
}
|
||||
return req.body.phone_id ? "maytapi" : "chatapi";
|
||||
return req.body.phone_id ? 'maytapi' : 'chatapi';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -429,7 +421,6 @@ export class GBMinService {
|
|||
private createCheckHealthAddress (server: any, min: GBMinInstance, instance: IGBInstance) {
|
||||
server.get(`/${min.instance.botId}/check`, async (req, res) => {
|
||||
try {
|
||||
|
||||
// Performs the checking of WhatsApp API if enabled for this instance.
|
||||
|
||||
if (min.whatsAppDirectLine != undefined && instance.whatsappServiceKey !== null) {
|
||||
|
@ -445,9 +436,7 @@ export class GBMinService {
|
|||
// GB is OK, so 200.
|
||||
|
||||
res.status(200).send(`General Bot ${min.botId} is healthly.`);
|
||||
|
||||
} catch (error) {
|
||||
|
||||
// GB is not OK, 500 and detail the information on response content.
|
||||
|
||||
GBLog.error(error);
|
||||
|
@ -461,9 +450,7 @@ export class GBMinService {
|
|||
* on https://<gbhost>/<BotId>/token URL.
|
||||
*/
|
||||
private handleOAuthTokenRequests (server: any, min: GBMinInstance, instance: IGBInstance) {
|
||||
|
||||
server.get(`/${min.instance.botId}/token`, async (req, res) => {
|
||||
|
||||
// Checks request state by reading AntiCSRFAttackState from GB Admin infrastructure.
|
||||
|
||||
const state = await min.adminService.getValue(instance.instanceId, 'AntiCSRFAttackState');
|
||||
|
@ -491,7 +478,6 @@ export class GBMinService {
|
|||
GBLog.error(msg);
|
||||
res.send(msg);
|
||||
} else {
|
||||
|
||||
// Saves token to the database.
|
||||
|
||||
await this.adminService.setValue(instance.instanceId, 'accessToken', token['accessToken']);
|
||||
|
@ -519,7 +505,8 @@ export class GBMinService {
|
|||
min.instance.authenticatorTenant,
|
||||
'/oauth2/authorize'
|
||||
);
|
||||
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${min.instance.marketplaceId
|
||||
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${
|
||||
min.instance.marketplaceId
|
||||
}&redirect_uri=${urlJoin(min.instance.botEndpoint, min.instance.botId, 'token')}`;
|
||||
GBLog.info(`HandleOAuthRequests: ${authorizationUrl}.`);
|
||||
res.redirect(authorizationUrl);
|
||||
|
@ -530,7 +517,6 @@ export class GBMinService {
|
|||
* Returns the instance object to clients requesting bot info.
|
||||
*/
|
||||
private async handleGetInstanceForClient (req: any, res: any) {
|
||||
|
||||
// Translates the requested botId.
|
||||
|
||||
let botId = req.params.botId;
|
||||
|
@ -548,7 +534,6 @@ export class GBMinService {
|
|||
}
|
||||
|
||||
if (instance !== null) {
|
||||
|
||||
// Gets the webchat token, speech token and theme.
|
||||
|
||||
const webchatTokenContainer = await this.getWebchatToken(instance);
|
||||
|
@ -561,7 +546,6 @@ export class GBMinService {
|
|||
theme = `default.gbtheme`;
|
||||
}
|
||||
|
||||
|
||||
res.send(
|
||||
JSON.stringify({
|
||||
instanceId: instance.instanceId,
|
||||
|
@ -634,16 +618,18 @@ export class GBMinService {
|
|||
* Builds the BOT Framework & GB infrastructures.
|
||||
*/
|
||||
private async buildBotAdapter (instance: any, sysPackages: IGBPackage[], appPackages: IGBPackage[]) {
|
||||
|
||||
// MSFT stuff.
|
||||
|
||||
const adapter = new BotFrameworkAdapter(
|
||||
{ appId: instance.marketplaceId, appPassword: instance.marketplacePassword });
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
appId: instance.marketplaceId,
|
||||
appPassword: instance.marketplacePassword
|
||||
});
|
||||
const storage = new MemoryStorage();
|
||||
const conversationState = new ConversationState(storage);
|
||||
const userState = new UserState(storage);
|
||||
adapter.use(new AutoSaveStateMiddleware(conversationState, userState));
|
||||
MicrosoftAppCredentials.trustServiceUrl('https://directline.botframework.com',
|
||||
MicrosoftAppCredentials.trustServiceUrl(
|
||||
'https://directline.botframework.com',
|
||||
new Date(new Date().setFullYear(new Date().getFullYear() + 10))
|
||||
);
|
||||
|
||||
|
@ -662,9 +648,9 @@ export class GBMinService {
|
|||
min.cbMap = {};
|
||||
min.scriptMap = {};
|
||||
min.sandBoxMap = {};
|
||||
min["scheduleMap"] = {};
|
||||
min["conversationWelcomed"] = {};
|
||||
min["nerEngine"] = new nlp.default.NerManager();
|
||||
min['scheduleMap'] = {};
|
||||
min['conversationWelcomed'] = {};
|
||||
min['nerEngine'] = new nlp.default.NerManager();
|
||||
min.packages = sysPackages;
|
||||
min.appPackages = appPackages;
|
||||
|
||||
|
@ -690,8 +676,6 @@ export class GBMinService {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
if (min.instance.googlePrivateKey) {
|
||||
min['googleDirectLine'] = new GoogleChatDirectLine(
|
||||
min,
|
||||
|
@ -706,11 +690,7 @@ export class GBMinService {
|
|||
await min['googleDirectLine'].setup(true);
|
||||
}
|
||||
|
||||
const group = min.core.getParam<string>(
|
||||
min.instance,
|
||||
'WhatsApp Group ID',
|
||||
null,
|
||||
);
|
||||
const group = min.core.getParam<string>(min.instance, 'WhatsApp Group ID', null);
|
||||
|
||||
WhatsappDirectLine.botGroups[min.botId] = group;
|
||||
|
||||
|
@ -770,7 +750,6 @@ export class GBMinService {
|
|||
* Performs calling of loadBot event in all .gbapps.
|
||||
*/
|
||||
private async invokeLoadBot (appPackages: IGBPackage[], sysPackages: IGBPackage[], min: GBMinInstance) {
|
||||
|
||||
// Calls loadBot event in all .gbapp packages.
|
||||
|
||||
await CollectionUtil.asyncForEach(sysPackages, async p => {
|
||||
|
@ -805,17 +784,15 @@ export class GBMinService {
|
|||
|
||||
// TODO: Unify in util.
|
||||
public static userMobile (step) {
|
||||
let mobile = WhatsappDirectLine.mobiles[step.context.activity.conversation.id]
|
||||
let mobile = WhatsappDirectLine.mobiles[step.context.activity.conversation.id];
|
||||
|
||||
if (!mobile && step) {
|
||||
return step.context.activity.from.id;
|
||||
}
|
||||
|
||||
return mobile;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* BOT Framework web service hook method.
|
||||
*/
|
||||
|
@ -827,7 +804,6 @@ export class GBMinService {
|
|||
instance: any,
|
||||
appPackages: any[]
|
||||
) {
|
||||
|
||||
let adapter = min.bot;
|
||||
|
||||
if (req.body.object) {
|
||||
|
@ -849,13 +825,10 @@ export class GBMinService {
|
|||
step.context.activity.locale = 'pt-BR';
|
||||
let firstTime = false;
|
||||
|
||||
|
||||
try {
|
||||
const sec = new SecService();
|
||||
const user = await min.userProfile.get(context, {});
|
||||
const conversationReference = JSON.stringify(
|
||||
TurnContext.getConversationReference(context.activity)
|
||||
);
|
||||
const conversationReference = JSON.stringify(TurnContext.getConversationReference(context.activity));
|
||||
|
||||
// First time processing.
|
||||
|
||||
|
@ -868,7 +841,7 @@ export class GBMinService {
|
|||
user.subjects = [];
|
||||
user.cb = undefined;
|
||||
user.welcomed = false;
|
||||
user.basicOptions = { maxLines: 100, translatorOn: true, wholeWord: true, theme: "white", maxColumns: 40 };
|
||||
user.basicOptions = { maxLines: 100, translatorOn: true, wholeWord: true, theme: 'white', maxColumns: 40 };
|
||||
|
||||
firstTime = true;
|
||||
|
||||
|
@ -876,7 +849,6 @@ export class GBMinService {
|
|||
// including the bot, that is filtered bellow.
|
||||
|
||||
if (context.activity.from.id !== min.botId) {
|
||||
|
||||
// Creates a new row in user table if it does not exists.
|
||||
|
||||
const member = context.activity.from;
|
||||
|
@ -894,7 +866,6 @@ export class GBMinService {
|
|||
const analytics = new AnalyticsService();
|
||||
user.systemUser = persistedUser;
|
||||
user.conversation = await analytics.createConversation(persistedUser);
|
||||
|
||||
}
|
||||
|
||||
await sec.updateConversationReferenceById(user.systemUser.userId, conversationReference);
|
||||
|
@ -919,27 +890,35 @@ export class GBMinService {
|
|||
// Required for MSTEAMS handling of persisted conversations.
|
||||
|
||||
if (step.context.activity.channelId === 'msteams') {
|
||||
|
||||
if (step.context.activity.attachments && step.context.activity.attachments.length > 1) {
|
||||
|
||||
const file = context.activity.attachments[0];
|
||||
const credentials = new MicrosoftAppCredentials(min.instance.marketplaceId, min.instance.marketplacePassword);
|
||||
const credentials = new MicrosoftAppCredentials(
|
||||
min.instance.marketplaceId,
|
||||
min.instance.marketplacePassword
|
||||
);
|
||||
const botToken = await credentials.getToken();
|
||||
const headers = { Authorization: `Bearer ${botToken}` };
|
||||
const t = new SystemKeywords(null, null, null, null);
|
||||
const data = await t.getByHttp({
|
||||
url: file.contentUrl, headers, username: null,
|
||||
ps: null, qs: null, streaming: true
|
||||
url: file.contentUrl,
|
||||
headers,
|
||||
username: null,
|
||||
ps: null,
|
||||
qs: null,
|
||||
streaming: true
|
||||
});
|
||||
const folder = `work/${min.instance.botId}.gbai/cache`;
|
||||
const filename = `${GBAdminService.generateUuid()}.png`;
|
||||
|
||||
Fs.writeFileSync(path.join(folder, filename), data);
|
||||
step.context.activity.text = urlJoin(GBServer.globals.publicAddress, `${min.instance.botId}`, 'cache', filename);
|
||||
step.context.activity.text = urlJoin(
|
||||
GBServer.globals.publicAddress,
|
||||
`${min.instance.botId}`,
|
||||
'cache',
|
||||
filename
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!user.welcomed) {
|
||||
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
||||
if (startDialog && !user.welcomed) {
|
||||
|
@ -952,7 +931,11 @@ export class GBMinService {
|
|||
|
||||
// Required for F0 handling of persisted conversations.
|
||||
|
||||
GBLog.info(`Input> ${context.activity.text} (type: ${context.activity.type}, name: ${context.activity.name}, channelId: ${context.activity.channelId})`);
|
||||
GBLog.info(
|
||||
`Input> ${context.activity.text} (type: ${context.activity.type}, name: ${
|
||||
context.activity.name
|
||||
}, channelId: ${context.activity.channelId})`
|
||||
);
|
||||
|
||||
// Answer to specific BOT Framework event conversationUpdate to auto start dialogs.
|
||||
// Skips if the bot is talking.
|
||||
|
@ -960,9 +943,7 @@ export class GBMinService {
|
|||
|
||||
if (context.activity.type === 'installationUpdate') {
|
||||
GBLog.info(`Bot installed on Teams.`);
|
||||
} else if (context.activity.type === 'conversationUpdate' &&
|
||||
context.activity.membersAdded.length > 0) {
|
||||
|
||||
} else if (context.activity.type === 'conversationUpdate' && context.activity.membersAdded.length > 0) {
|
||||
// Check if a bot or a human participant is being added to the conversation.
|
||||
|
||||
const member = context.activity.membersAdded[0];
|
||||
|
@ -978,45 +959,46 @@ export class GBMinService {
|
|||
// Auto starts dialogs if any is specified.
|
||||
|
||||
if (!startDialog && !user.welcomed) {
|
||||
|
||||
// Otherwise, calls / (root) to default welcome users.
|
||||
|
||||
await step.beginDialog('/');
|
||||
}
|
||||
else {
|
||||
if (!GBMinService.userMobile(step) &&
|
||||
!min["conversationWelcomed"][step.context.activity.conversation.id]) {
|
||||
} else {
|
||||
if (
|
||||
!GBMinService.userMobile(step) &&
|
||||
!min['conversationWelcomed'][step.context.activity.conversation.id]
|
||||
) {
|
||||
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
||||
|
||||
min["conversationWelcomed"][step.context.activity.conversation.id] = true;
|
||||
|
||||
GBLog.info(`Auto start (web 1) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`);
|
||||
GBLog.info(
|
||||
`Auto start (web 1) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
||||
);
|
||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, this.deployer, false);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
GBLog.info(`Person added to conversation: ${member.name}`);
|
||||
|
||||
if (GBMinService.userMobile(step)) {
|
||||
if (startDialog && !min["conversationWelcomed"][step.context.activity.conversation.id] &&
|
||||
!step.context.activity['group']) {
|
||||
if (
|
||||
startDialog &&
|
||||
!min['conversationWelcomed'][step.context.activity.conversation.id] &&
|
||||
!step.context.activity['group']
|
||||
) {
|
||||
user.welcomed = true;
|
||||
min["conversationWelcomed"][step.context.activity.conversation.id] = true;
|
||||
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
||||
await min.userProfile.set(step.context, user);
|
||||
GBLog.info(`Auto start (whatsapp) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`);
|
||||
GBLog.info(
|
||||
`Auto start (whatsapp) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
||||
);
|
||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, this.deployer, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (context.activity.type === 'message') {
|
||||
|
||||
// Processes messages activities.
|
||||
|
||||
await this.processMessageActivity(context, min, step);
|
||||
|
||||
} else if (context.activity.type === 'event') {
|
||||
|
||||
// Processes events activities.
|
||||
|
||||
await this.processEventActivity(min, user, context, step);
|
||||
|
@ -1025,9 +1007,7 @@ export class GBMinService {
|
|||
// Saves conversation state for later use.
|
||||
|
||||
await conversationState.saveChanges(context, true);
|
||||
|
||||
} catch (error) {
|
||||
|
||||
const msg = `ERROR: ${error.message} ${error.stack ? error.stack : ''}`;
|
||||
GBLog.error(msg);
|
||||
|
||||
|
@ -1046,7 +1026,6 @@ export class GBMinService {
|
|||
* Called to handle all event sent by .gbui clients.
|
||||
*/
|
||||
private async processEventActivity (min, user, context, step: GBDialogStep) {
|
||||
|
||||
if (context.activity.name === 'whoAmI') {
|
||||
await step.beginDialog('/whoAmI');
|
||||
} else if (context.activity.name === 'showSubjects') {
|
||||
|
@ -1068,7 +1047,7 @@ export class GBMinService {
|
|||
});
|
||||
} else if (context.activity.name === 'startGB') {
|
||||
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
||||
if (startDialog && !min["conversationWelcomed"][step.context.activity.conversation.id]) {
|
||||
if (startDialog && !min['conversationWelcomed'][step.context.activity.conversation.id]) {
|
||||
user.welcomed = true;
|
||||
GBLog.info(`Auto start (web 2) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`);
|
||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, this.deployer, false);
|
||||
|
@ -1085,7 +1064,6 @@ export class GBMinService {
|
|||
* Called to handle all text messages sent and received by the bot.
|
||||
*/
|
||||
private async processMessageActivity (context, min: GBMinInstance, step: GBDialogStep) {
|
||||
|
||||
const sec = new SecService();
|
||||
|
||||
if (!context.activity.text) {
|
||||
|
@ -1110,12 +1088,10 @@ export class GBMinService {
|
|||
const user = await min.userProfile.get(context, {});
|
||||
let message: GuaribasConversationMessage;
|
||||
if (process.env.PRIVACY_STORE_MESSAGES === 'true') {
|
||||
|
||||
// Adds message to the analytics layer.
|
||||
|
||||
const analytics = new AnalyticsService();
|
||||
if (user) {
|
||||
|
||||
if (!user.conversation) {
|
||||
user.conversation = await analytics.createConversation(user.systemUser);
|
||||
}
|
||||
|
@ -1141,22 +1117,18 @@ export class GBMinService {
|
|||
if (isVMCall) {
|
||||
await GBVMService.callVM(context.activity.text, min, step, this.deployer, false);
|
||||
} else if (context.activity.text.charAt(0) === '/') {
|
||||
|
||||
const text = context.activity.text;
|
||||
const parts = text.split(' ');
|
||||
const cmdOrDialogName = parts[0];
|
||||
parts.splice(0, 1);
|
||||
const args = parts.join(' ');
|
||||
if (cmdOrDialogName === '/start') {
|
||||
|
||||
|
||||
// Reset user.
|
||||
|
||||
const user = await min.userProfile.get(context, {});
|
||||
await min.conversationalService.sendEvent(min, step, 'loadInstance', {});
|
||||
user.loaded = false;
|
||||
await min.userProfile.set(step.context, user);
|
||||
|
||||
} else if (cmdOrDialogName === '/call') {
|
||||
await GBVMService.callVM(args, min, step, this.deployer, false);
|
||||
} else if (cmdOrDialogName === '/callsch') {
|
||||
|
@ -1169,23 +1141,21 @@ export class GBMinService {
|
|||
} else if (globalQuit(step.context.activity.locale, context.activity.text)) {
|
||||
await step.cancelAllDialogs();
|
||||
await min.conversationalService.sendText(min, step, Messages[step.context.activity.locale].canceled);
|
||||
|
||||
} else if (context.activity.text === 'admin') {
|
||||
await step.beginDialog('/admin');
|
||||
|
||||
} else if (context.activity.text.startsWith('{"title"')) {
|
||||
await step.beginDialog('/menu', JSON.parse(context.activity.text));
|
||||
|
||||
} else if (
|
||||
!(await this.deployer.getStoragePackageByName(min.instance.instanceId, `${min.instance.botId}.gbkb`)) &&
|
||||
process.env.GBKB_ENABLE_AUTO_PUBLISH === 'true'
|
||||
) {
|
||||
await min.conversationalService.sendText(min, step,
|
||||
await min.conversationalService.sendText(
|
||||
min,
|
||||
step,
|
||||
`Oi, ainda não possuo pacotes de conhecimento publicados. Por favor, aguarde alguns segundos enquanto eu auto-publico alguns pacotes.`
|
||||
);
|
||||
await step.beginDialog('/publish', { confirm: true, firstTime: true });
|
||||
} else {
|
||||
|
||||
// Removes unwanted chars in input text.
|
||||
|
||||
let text = context.activity.text;
|
||||
|
@ -1208,7 +1178,7 @@ export class GBMinService {
|
|||
}
|
||||
});
|
||||
|
||||
const getNormalizedRegExp = (value) => {
|
||||
const getNormalizedRegExp = value => {
|
||||
var chars = [
|
||||
{ letter: 'a', reg: '[aáàãäâ]' },
|
||||
{ letter: 'e', reg: '[eéèëê]' },
|
||||
|
@ -1220,7 +1190,7 @@ export class GBMinService {
|
|||
|
||||
for (var i in chars) {
|
||||
value = value.replace(new RegExp(chars[i].letter, 'gi'), chars[i].reg);
|
||||
};
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
|
@ -1236,7 +1206,10 @@ export class GBMinService {
|
|||
const replacementToken = 'X' + GBAdminService.getNumberIdentifier().substr(0, 4);
|
||||
replacements[i] = { text: item, replacementToken: replacementToken };
|
||||
i++;
|
||||
textProcessed = textProcessed.replace(new RegExp(`\\b${getNormalizedRegExp(it.trim())}\\b`, 'gi'), `${replacementToken}`);
|
||||
textProcessed = textProcessed.replace(
|
||||
new RegExp(`\\b${getNormalizedRegExp(it.trim())}\\b`, 'gi'),
|
||||
`${replacementToken}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1248,10 +1221,15 @@ export class GBMinService {
|
|||
|
||||
// Detects user typed language and updates their locale profile if applies.
|
||||
|
||||
let locale = min.core.getParam<string>(min.instance, 'Default User Language',
|
||||
let locale = min.core.getParam<string>(
|
||||
min.instance,
|
||||
'Default User Language',
|
||||
GBConfigService.get('DEFAULT_USER_LANGUAGE')
|
||||
);
|
||||
const detectLanguage = min.core.getParam<boolean>(min.instance, 'Language Detector',
|
||||
const detectLanguage =
|
||||
min.core.getParam<boolean>(
|
||||
min.instance,
|
||||
'Language Detector',
|
||||
GBConfigService.getBoolean('LANGUAGE_DETECTOR')
|
||||
) === 'true';
|
||||
const systemUser = user.systemUser;
|
||||
|
@ -1259,7 +1237,6 @@ export class GBMinService {
|
|||
if (text != '' && detectLanguage && !locale) {
|
||||
locale = await min.conversationalService.getLanguage(min, text);
|
||||
if (systemUser.locale != locale) {
|
||||
|
||||
user.systemUser = await sec.updateUserLocale(systemUser.userId, locale);
|
||||
await min.userProfile.set(step.context, user);
|
||||
}
|
||||
|
@ -1308,32 +1285,32 @@ export class GBMinService {
|
|||
const message = await min.kbService.getAnswerTextByMediaName(min.instance.instanceId, filename);
|
||||
|
||||
if (message === null) {
|
||||
GBLog.error(`File ${filename} not found in any .gbkb published. Check the name or publish again the associated .gbkb.`);
|
||||
GBLog.error(
|
||||
`File ${filename} not found in any .gbkb published. Check the name or publish again the associated .gbkb.`
|
||||
);
|
||||
} else {
|
||||
await min.conversationalService.sendMarkdownToMobile(min, null, manualUser.userSystemId, message);
|
||||
}
|
||||
} else {
|
||||
await min.whatsAppDirectLine.sendToDeviceEx(
|
||||
manualUser.userSystemId,
|
||||
`${manualUser.agentSystemId}: ${text}`,
|
||||
locale,
|
||||
step.context.activity.conversation.id
|
||||
);
|
||||
}
|
||||
else {
|
||||
await min.whatsAppDirectLine.sendToDeviceEx(manualUser.userSystemId, `${manualUser.agentSystemId}: ${text}`, locale,
|
||||
step.context.activity.conversation.id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (min.cbMap[user.systemUser.userId] &&
|
||||
min.cbMap[user.systemUser.userId].promise == '!GBHEAR') {
|
||||
} else {
|
||||
if (min.cbMap[user.systemUser.userId] && min.cbMap[user.systemUser.userId].promise == '!GBHEAR') {
|
||||
min.cbMap[user.systemUser.userId].promise = text;
|
||||
}
|
||||
|
||||
// If there is a dialog in course, continue to the next step.
|
||||
|
||||
else if (step.activeDialog !== undefined) {
|
||||
await step.continueDialog();
|
||||
} else {
|
||||
|
||||
const startDialog = user.hearOnDialog ?
|
||||
user.hearOnDialog :
|
||||
min.core.getParam(min.instance, 'Start Dialog', null);
|
||||
const startDialog = user.hearOnDialog
|
||||
? user.hearOnDialog
|
||||
: min.core.getParam(min.instance, 'Start Dialog', null);
|
||||
|
||||
if (text !== startDialog) {
|
||||
let nextDialog = null;
|
||||
|
@ -1357,7 +1334,6 @@ export class GBMinService {
|
|||
user: user ? user.dataValues : null,
|
||||
message: message
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,52 +42,39 @@ import Fs from 'fs';
|
|||
// const StealthPlugin from 'puppeteer-extra-plugin-stealth')
|
||||
// puppeteer.use(StealthPlugin());
|
||||
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import urljoin from "url-join";
|
||||
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
import urljoin from 'url-join';
|
||||
|
||||
// https://hackernoon.com/tips-and-tricks-for-web-scraping-with-puppeteer-ed391a63d952
|
||||
// Dont download all resources, we just need the HTML
|
||||
// Also, this is huge performance/response time boost
|
||||
const blockedResourceTypes = [
|
||||
"image",
|
||||
"media",
|
||||
"font",
|
||||
"texttrack",
|
||||
"object",
|
||||
"beacon",
|
||||
"csp_report",
|
||||
"imageset",
|
||||
];
|
||||
const blockedResourceTypes = ['image', 'media', 'font', 'texttrack', 'object', 'beacon', 'csp_report', 'imageset'];
|
||||
// const whitelist = ["document", "script", "xhr", "fetch"];
|
||||
const skippedResources = [
|
||||
"quantserve",
|
||||
"adzerk",
|
||||
"doubleclick",
|
||||
"adition",
|
||||
"exelator",
|
||||
"sharethrough",
|
||||
"cdn.api.twitter",
|
||||
"google-analytics",
|
||||
"googletagmanager",
|
||||
"google",
|
||||
"fontawesome",
|
||||
"facebook",
|
||||
"analytics",
|
||||
"optimizely",
|
||||
"clicktale",
|
||||
"mixpanel",
|
||||
"zedo",
|
||||
"clicksor",
|
||||
"tiqcdn",
|
||||
'quantserve',
|
||||
'adzerk',
|
||||
'doubleclick',
|
||||
'adition',
|
||||
'exelator',
|
||||
'sharethrough',
|
||||
'cdn.api.twitter',
|
||||
'google-analytics',
|
||||
'googletagmanager',
|
||||
'google',
|
||||
'fontawesome',
|
||||
'facebook',
|
||||
'analytics',
|
||||
'optimizely',
|
||||
'clicktale',
|
||||
'mixpanel',
|
||||
'zedo',
|
||||
'clicksor',
|
||||
'tiqcdn'
|
||||
];
|
||||
|
||||
const RENDER_CACHE = new Map();
|
||||
|
||||
|
||||
|
||||
async function createBrowser (profilePath): Promise<any> {
|
||||
|
||||
let args = [
|
||||
'--check-for-update-interval=2592000',
|
||||
'--disable-accelerated-2d-canvas',
|
||||
|
@ -101,12 +88,12 @@ async function createBrowser(profilePath): Promise<any> {
|
|||
if (profilePath) {
|
||||
args.push(`--user-data-dir=${profilePath}`);
|
||||
|
||||
const preferences = urljoin(profilePath, "Default", "Preferences");
|
||||
const preferences = urljoin(profilePath, 'Default', 'Preferences');
|
||||
if (Fs.existsSync(preferences)) {
|
||||
const file = Fs.readFileSync(preferences, "utf8")
|
||||
const data = JSON.parse(file)
|
||||
data["profile"]['exit_type'] = "none";
|
||||
Fs.writeFileSync(preferences, JSON.stringify(data))
|
||||
const file = Fs.readFileSync(preferences, 'utf8');
|
||||
const data = JSON.parse(file);
|
||||
data['profile']['exit_type'] = 'none';
|
||||
Fs.writeFileSync(preferences, JSON.stringify(data));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +102,7 @@ async function createBrowser(profilePath): Promise<any> {
|
|||
ignoreHTTPSErrors: true,
|
||||
headless: false,
|
||||
defaultViewport: null,
|
||||
ignoreDefaultArgs: ["--enable-automation", "--enable-blink-features=IdleDetection"]
|
||||
ignoreDefaultArgs: ['--enable-automation', '--enable-blink-features=IdleDetection']
|
||||
});
|
||||
return browser;
|
||||
}
|
||||
|
@ -135,9 +122,6 @@ async function recursiveFindInFrames(inputFrame, selector) {
|
|||
return results.find(Boolean);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* https://developers.google.com/web/tools/puppeteer/articles/ssr#reuseinstance
|
||||
* @param {string} url URL to prerender.
|
||||
|
@ -145,15 +129,12 @@ async function recursiveFindInFrames(inputFrame, selector) {
|
|||
async function ssr (url: string, useCache: boolean, cacheRefreshRate: number) {
|
||||
if (RENDER_CACHE.has(url) && useCache) {
|
||||
const cached = RENDER_CACHE.get(url);
|
||||
if (
|
||||
Date.now() - cached.renderedAt > cacheRefreshRate &&
|
||||
!(cacheRefreshRate <= 0)
|
||||
) {
|
||||
if (Date.now() - cached.renderedAt > cacheRefreshRate && !(cacheRefreshRate <= 0)) {
|
||||
RENDER_CACHE.delete(url);
|
||||
} else {
|
||||
return {
|
||||
html: cached.html,
|
||||
status: 200,
|
||||
status: 200
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -163,14 +144,17 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
|||
try {
|
||||
const page = await browser.newPage();
|
||||
await page.setUserAgent(
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
|
||||
);
|
||||
await page.setRequestInterception(true);
|
||||
page.on("request", (request) => {
|
||||
const requestUrl = request.url().split("?")[0].split("#")[0];
|
||||
page.on('request', request => {
|
||||
const requestUrl = request
|
||||
.url()
|
||||
.split('?')[0]
|
||||
.split('#')[0];
|
||||
if (
|
||||
blockedResourceTypes.indexOf(request.resourceType()) !== -1 ||
|
||||
skippedResources.some((resource) => requestUrl.indexOf(resource) !== -1)
|
||||
skippedResources.some(resource => requestUrl.indexOf(resource) !== -1)
|
||||
) {
|
||||
request.abort();
|
||||
} else {
|
||||
|
@ -178,10 +162,10 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
|||
}
|
||||
});
|
||||
|
||||
page.on("response", async (resp) => {
|
||||
page.on('response', async resp => {
|
||||
const responseUrl = resp.url();
|
||||
const sameOrigin = new URL(responseUrl).origin === new URL(url).origin;
|
||||
const isStylesheet = resp.request().resourceType() === "stylesheet";
|
||||
const isStylesheet = resp.request().resourceType() === 'stylesheet';
|
||||
if (sameOrigin && isStylesheet) {
|
||||
stylesheetContents[responseUrl] = await resp.text();
|
||||
}
|
||||
|
@ -189,7 +173,7 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
|||
|
||||
const response = await page.goto(url, {
|
||||
timeout: 120000,
|
||||
waitUntil: "networkidle0",
|
||||
waitUntil: 'networkidle0'
|
||||
});
|
||||
|
||||
const sleep = ms => {
|
||||
|
@ -200,8 +184,8 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
|||
await sleep(45000);
|
||||
|
||||
// Inject <base> on page to relative resources load properly.
|
||||
await page.evaluate((url) => {
|
||||
const base = document.createElement("base");
|
||||
await page.evaluate(url => {
|
||||
const base = document.createElement('base');
|
||||
base.href = url;
|
||||
// Add to top of head, before all other resources.
|
||||
document.head.prepend(base);
|
||||
|
@ -210,7 +194,7 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
|||
// Remove scripts and html imports. They've already executed.
|
||||
await page.evaluate(() => {
|
||||
const elements = document.querySelectorAll('script, link[rel="import"]');
|
||||
elements.forEach((e) => {
|
||||
elements.forEach(e => {
|
||||
e.remove();
|
||||
});
|
||||
});
|
||||
|
@ -222,7 +206,7 @@ async function ssr(url: string, useCache: boolean, cacheRefreshRate: number) {
|
|||
links.forEach((link: any) => {
|
||||
const cssText = content[link.href];
|
||||
if (cssText) {
|
||||
const style = document.createElement("style");
|
||||
const style = document.createElement('style');
|
||||
style.textContent = cssText;
|
||||
link.replaceWith(style);
|
||||
}
|
||||
|
@ -279,52 +263,51 @@ function ssrForBots(
|
|||
|
||||
// Default user agents
|
||||
const prerenderArray = [
|
||||
"bot",
|
||||
"googlebot",
|
||||
"Chrome-Lighthouse",
|
||||
"DuckDuckBot",
|
||||
"ia_archiver",
|
||||
"bingbot",
|
||||
"yandex",
|
||||
"baiduspider",
|
||||
"Facebot",
|
||||
"facebookexternalhit",
|
||||
"facebookexternalhit/1.1",
|
||||
"twitterbot",
|
||||
"rogerbot",
|
||||
"linkedinbot",
|
||||
"embedly",
|
||||
"quora link preview",
|
||||
"showyoubot",
|
||||
"outbrain",
|
||||
"pinterest",
|
||||
"slackbot",
|
||||
"vkShare",
|
||||
"W3C_Validator",
|
||||
'bot',
|
||||
'googlebot',
|
||||
'Chrome-Lighthouse',
|
||||
'DuckDuckBot',
|
||||
'ia_archiver',
|
||||
'bingbot',
|
||||
'yandex',
|
||||
'baiduspider',
|
||||
'Facebot',
|
||||
'facebookexternalhit',
|
||||
'facebookexternalhit/1.1',
|
||||
'twitterbot',
|
||||
'rogerbot',
|
||||
'linkedinbot',
|
||||
'embedly',
|
||||
'quora link preview',
|
||||
'showyoubot',
|
||||
'outbrain',
|
||||
'pinterest',
|
||||
'slackbot',
|
||||
'vkShare',
|
||||
'W3C_Validator'
|
||||
];
|
||||
|
||||
// default exclude array
|
||||
const excludeArray = [".xml", ".ico", ".txt", ".json"];
|
||||
const excludeArray = ['.xml', '.ico', '.txt', '.json'];
|
||||
|
||||
function ssrOnDemand (req: Request, res: Response, next: NextFunction) {
|
||||
Promise.resolve(() => {
|
||||
return true;
|
||||
})
|
||||
.then(async () => {
|
||||
const userAgent: string = req.headers["user-agent"] || "";
|
||||
const userAgent: string = req.headers['user-agent'] || '';
|
||||
|
||||
const prerender = new RegExp(
|
||||
[...prerenderArray, ...applyOptions.prerender].join("|").slice(0, -1),
|
||||
"i"
|
||||
).test(userAgent);
|
||||
const prerender = new RegExp([...prerenderArray, ...applyOptions.prerender].join('|').slice(0, -1), 'i').test(
|
||||
userAgent
|
||||
);
|
||||
|
||||
const exclude = !new RegExp(
|
||||
[...excludeArray, ...applyOptions.exclude].join("|").slice(0, -1)
|
||||
).test(req.originalUrl);
|
||||
const exclude = !new RegExp([...excludeArray, ...applyOptions.exclude].join('|').slice(0, -1)).test(
|
||||
req.originalUrl
|
||||
);
|
||||
|
||||
if (req.originalUrl && prerender && exclude) {
|
||||
const { html, status } = await ssr(
|
||||
req.protocol + "://" + req.get("host") + req.originalUrl,
|
||||
req.protocol + '://' + req.get('host') + req.originalUrl,
|
||||
applyOptions.useCache,
|
||||
applyOptions.cacheRefreshRate
|
||||
);
|
||||
|
@ -339,5 +322,4 @@ function ssrForBots(
|
|||
return ssrOnDemand;
|
||||
}
|
||||
|
||||
|
||||
export { createBrowser, ssr, clearCache, ssrForBots };
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
export const Messages = {
|
||||
global_quit: /^(\bsair\b|\bsai\b|\bchega\b|\bexit\b|\bquit\b|\bfinish\b|\bend\b|\bausfahrt\b|\bverlassen\b)/i,
|
||||
'en-US': {
|
||||
|
@ -6,23 +5,22 @@ export const Messages = {
|
|||
good_morning: 'good morning',
|
||||
good_evening: 'good evening',
|
||||
good_night: 'good night',
|
||||
hi: (msg) => `Hello, ${msg}.`,
|
||||
hi: msg => `Hello, ${msg}.`,
|
||||
very_sorry_about_error: `I'm sorry to inform that there was an error which was recorded to be solved.`,
|
||||
canceled: 'Canceled. If I can be useful, let me know how',
|
||||
whats_email: 'What\'s your E-mail address?',
|
||||
whats_email: "What's your E-mail address?",
|
||||
which_language: 'Please, type the language name you would like to talk through.',
|
||||
validation_enter_valid_email: 'Please enter a valid e-mail.',
|
||||
language_chosen: 'Very good, so let\'s go...',
|
||||
language_chosen: "Very good, so let's go...",
|
||||
affirmative_sentences: /^(\bsim\b|\bs\b|\bpositivo\b|\bafirmativo\b|\bclaro\b|\bevidente\b|\bsem dúvida\b|\bconfirmo\b|\bconfirmar\b|\bconfirmado\b|\buhum\b|\bsi\b|\by\b|\byes\b|\bsure\b)/i,
|
||||
will_answer_projector:
|
||||
'I\'ll answer on the projector to a better experience...',
|
||||
will_answer_projector: "I'll answer on the projector to a better experience..."
|
||||
},
|
||||
'pt-BR': {
|
||||
show_video: 'Vou te mostrar um vídeo. Por favor, aguarde...',
|
||||
good_morning: 'bom dia',
|
||||
good_evening: 'boa tarde',
|
||||
good_night: 'boa noite',
|
||||
hi: (msg) => `Oi, ${msg}.`,
|
||||
hi: msg => `Oi, ${msg}.`,
|
||||
very_sorry_about_error: `Lamento, ocorreu um erro que já foi registrado para ser tratado.`,
|
||||
canceled: 'Cancelado, avise como posso ser útil novamente.',
|
||||
whats_email: 'Qual seu e-mail?',
|
||||
|
@ -30,8 +28,6 @@ export const Messages = {
|
|||
validation_enter_valid_email: 'Por favor digite um email válido.',
|
||||
language_chosen: 'Muito bem, então vamos lá...',
|
||||
affirmative_sentences: /^(\bsim\b|\bs\b|\bpositivo\b|\bafirmativo\b|\bclaro\b|\bevidente\b|\bsem dúvida\b|\bconfirmo\b|\bconfirmar\b|\bconfirmado\b|\buhum\b|\bsi\b|\by\b|\byes\b|\bsure\b)/i,
|
||||
will_answer_projector:
|
||||
'Vou te responder na tela para melhor visualização...',
|
||||
|
||||
will_answer_projector: 'Vou te responder na tela para melhor visualização...'
|
||||
}
|
||||
};
|
||||
|
|
|
@ -74,13 +74,11 @@ export class FeedbackDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
async step => {
|
||||
|
||||
const locale = step.context.activity.locale;
|
||||
const sec = new SecService();
|
||||
let from = GBMinService.userMobile(step);
|
||||
|
@ -90,40 +88,39 @@ export class FeedbackDialog extends IGBDialog {
|
|||
// Transfer to...
|
||||
|
||||
if (args && args.to) {
|
||||
|
||||
// An user from Teams willing to transfer to a WhatsApp user.
|
||||
|
||||
await sec.ensureUser(min.instance.instanceId, args.to,
|
||||
'Name', '', 'whatsapp', 'Name', null);
|
||||
await sec.ensureUser(min.instance.instanceId, args.to, 'Name', '', 'whatsapp', 'Name', null);
|
||||
|
||||
await sec.assignHumanAgent(min, args.to, profile.systemUser.userSystemId);
|
||||
await min.conversationalService.sendText(min, step,
|
||||
Messages[locale].notify_agent_transfer_done(min.instance.botId));
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
await min.conversationalService.sendText(
|
||||
min,
|
||||
step,
|
||||
Messages[locale].notify_agent_transfer_done(min.instance.botId)
|
||||
);
|
||||
} else {
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].please_wait_transfering);
|
||||
const agentSystemId = await sec.assignHumanAgent(min, from);
|
||||
profile.systemUser = await sec.getUserFromAgentSystemId(agentSystemId);
|
||||
await min.userProfile.set(step.context, profile);
|
||||
|
||||
if (agentSystemId.charAt(2) === ":" || agentSystemId.indexOf("@") > -1) { // Agent is from Teams or Google Chat.
|
||||
if (agentSystemId.charAt(2) === ':' || agentSystemId.indexOf('@') > -1) {
|
||||
// Agent is from Teams or Google Chat.
|
||||
|
||||
const agent = await sec.getUserFromSystemId(agentSystemId);
|
||||
await min.conversationalService['sendOnConversation'](min, agent,
|
||||
Messages[locale].notify_agent(step.context.activity.from.name));
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
await min.whatsAppDirectLine.sendToDevice(agentSystemId, Messages[locale].notify_agent(step.context.activity.from.name));
|
||||
|
||||
await min.conversationalService['sendOnConversation'](
|
||||
min,
|
||||
agent,
|
||||
Messages[locale].notify_agent(step.context.activity.from.name)
|
||||
);
|
||||
} else {
|
||||
await min.whatsAppDirectLine.sendToDevice(
|
||||
agentSystemId,
|
||||
Messages[locale].notify_agent(step.context.activity.from.name)
|
||||
);
|
||||
}
|
||||
}
|
||||
return await step.next();
|
||||
|
||||
}
|
||||
])
|
||||
);
|
||||
|
@ -133,13 +130,11 @@ export class FeedbackDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
async step => {
|
||||
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
const sec = new SecService();
|
||||
|
@ -149,16 +144,27 @@ export class FeedbackDialog extends IGBDialog {
|
|||
if (user.systemUser.agentMode === 'self') {
|
||||
const manualUser = await sec.getUserFromAgentSystemId(userSystemId);
|
||||
|
||||
await min.whatsAppDirectLine.sendToDeviceEx(manualUser.userSystemId,
|
||||
Messages[locale].notify_end_transfer(min.instance.botId), locale, step.context.activity.conversation.id);
|
||||
await min.whatsAppDirectLine.sendToDeviceEx(
|
||||
manualUser.userSystemId,
|
||||
Messages[locale].notify_end_transfer(min.instance.botId),
|
||||
locale,
|
||||
step.context.activity.conversation.id
|
||||
);
|
||||
|
||||
if (userSystemId.charAt(2) === ":" || userSystemId.indexOf('@') > -1) { // Agent is from Teams or Google Chat.
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].notify_end_transfer(min.instance.botId));
|
||||
}
|
||||
else {
|
||||
await min.whatsAppDirectLine.sendToDeviceEx(userSystemId,
|
||||
Messages[locale].notify_end_transfer(min.instance.botId), locale
|
||||
, step.context.activity.conversation.id);
|
||||
if (userSystemId.charAt(2) === ':' || userSystemId.indexOf('@') > -1) {
|
||||
// Agent is from Teams or Google Chat.
|
||||
await min.conversationalService.sendText(
|
||||
min,
|
||||
step,
|
||||
Messages[locale].notify_end_transfer(min.instance.botId)
|
||||
);
|
||||
} else {
|
||||
await min.whatsAppDirectLine.sendToDeviceEx(
|
||||
userSystemId,
|
||||
Messages[locale].notify_end_transfer(min.instance.botId),
|
||||
locale,
|
||||
step.context.activity.conversation.id
|
||||
);
|
||||
}
|
||||
|
||||
await sec.updateHumanAgent(userSystemId, min.instance.instanceId, null);
|
||||
|
@ -166,22 +172,30 @@ export class FeedbackDialog extends IGBDialog {
|
|||
|
||||
user.systemUser = await sec.getUserFromSystemId(userSystemId);
|
||||
await min.userProfile.set(step.context, user);
|
||||
|
||||
}
|
||||
|
||||
else if (user.systemUser.agentMode === 'human') {
|
||||
} else if (user.systemUser.agentMode === 'human') {
|
||||
const agent = await sec.getUserFromSystemId(user.systemUser.agentSystemId);
|
||||
|
||||
await min.whatsAppDirectLine.sendToDeviceEx(user.systemUser.userSystemId,
|
||||
Messages[locale].notify_end_transfer(min.instance.botId), locale, step.context.activity.conversation.id);
|
||||
await min.whatsAppDirectLine.sendToDeviceEx(
|
||||
user.systemUser.userSystemId,
|
||||
Messages[locale].notify_end_transfer(min.instance.botId),
|
||||
locale,
|
||||
step.context.activity.conversation.id
|
||||
);
|
||||
|
||||
|
||||
if (user.systemUser.agentSystemId.charAt(2) === ":" || userSystemId.indexOf('@') > -1) { // Agent is from Teams or Google Chat.
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].notify_end_transfer(min.instance.botId));
|
||||
}
|
||||
else {
|
||||
await min.whatsAppDirectLine.sendToDeviceEx(user.systemUser.agentSystemId,
|
||||
Messages[locale].notify_end_transfer(min.instance.botId), locale, step.context.activity.conversation.id);
|
||||
if (user.systemUser.agentSystemId.charAt(2) === ':' || userSystemId.indexOf('@') > -1) {
|
||||
// Agent is from Teams or Google Chat.
|
||||
await min.conversationalService.sendText(
|
||||
min,
|
||||
step,
|
||||
Messages[locale].notify_end_transfer(min.instance.botId)
|
||||
);
|
||||
} else {
|
||||
await min.whatsAppDirectLine.sendToDeviceEx(
|
||||
user.systemUser.agentSystemId,
|
||||
Messages[locale].notify_end_transfer(min.instance.botId),
|
||||
locale,
|
||||
step.context.activity.conversation.id
|
||||
);
|
||||
}
|
||||
|
||||
await sec.updateHumanAgent(user.systemUser.userSystemId, min.instance.instanceId, null);
|
||||
|
@ -189,15 +203,17 @@ export class FeedbackDialog extends IGBDialog {
|
|||
|
||||
user.systemUser = await sec.getUserFromSystemId(userSystemId);
|
||||
await min.userProfile.set(step.context, user);
|
||||
|
||||
}
|
||||
else {
|
||||
if (user.systemUser.userSystemId.charAt(2) === ":" || userSystemId.indexOf('@') > -1) { // Agent is from Teams or Google Chat.
|
||||
} else {
|
||||
if (user.systemUser.userSystemId.charAt(2) === ':' || userSystemId.indexOf('@') > -1) {
|
||||
// Agent is from Teams or Google Chat.
|
||||
await min.conversationalService.sendText(min, step, 'Nenhum atendimento em andamento.');
|
||||
}
|
||||
else {
|
||||
await min.whatsAppDirectLine.sendToDeviceEx(user.systemUser.userSystemId,
|
||||
'Nenhum atendimento em andamento.', locale, step.context.activity.conversation.id);
|
||||
} else {
|
||||
await min.whatsAppDirectLine.sendToDeviceEx(
|
||||
user.systemUser.userSystemId,
|
||||
'Nenhum atendimento em andamento.',
|
||||
locale,
|
||||
step.context.activity.conversation.id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,8 +227,7 @@ export class FeedbackDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -238,8 +253,7 @@ export class FeedbackDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -259,14 +273,20 @@ export class FeedbackDialog extends IGBDialog {
|
|||
|
||||
const analytics = new AnalyticsService();
|
||||
const rate = await analytics.updateConversationSuggestion(
|
||||
min.instance.instanceId, user.conversation.conversationId, step.result, user.systemUser.locale);
|
||||
min.instance.instanceId,
|
||||
user.conversation.conversationId,
|
||||
step.result,
|
||||
user.systemUser.locale
|
||||
);
|
||||
|
||||
if (rate > 0.5) {
|
||||
await min.conversationalService.sendText(min, step, Messages[fixedLocale].glad_you_liked);
|
||||
} else {
|
||||
|
||||
const message = min.core.getParam<string>(min.instance, 'Feedback Improve Message',
|
||||
Messages[fixedLocale].we_will_improve); // TODO: Improve to be multi-language.
|
||||
const message = min.core.getParam<string>(
|
||||
min.instance,
|
||||
'Feedback Improve Message',
|
||||
Messages[fixedLocale].we_will_improve
|
||||
); // TODO: Improve to be multi-language.
|
||||
|
||||
await min.conversationalService.sendText(min, step, message);
|
||||
}
|
||||
|
|
|
@ -58,16 +58,18 @@ export class QualityDialog extends IGBDialog {
|
|||
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||
const service = new CSService();
|
||||
|
||||
min.dialogs.add(new WaterfallDialog('/check', [
|
||||
min.dialogs.add(
|
||||
new WaterfallDialog('/check', [
|
||||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].check_whatsapp_ok);
|
||||
return await step.replaceDialog('/ask', { isReturning: true });
|
||||
}
|
||||
]
|
||||
));
|
||||
])
|
||||
);
|
||||
|
||||
min.dialogs.add(new WaterfallDialog('/quality', [
|
||||
min.dialogs.add(
|
||||
new WaterfallDialog('/quality', [
|
||||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
const user = await min.userProfile.get(step.context, {});
|
||||
|
@ -83,7 +85,7 @@ export class QualityDialog extends IGBDialog {
|
|||
await min.conversationalService.sendEvent(min, step, 'play', {
|
||||
playerType: 'markdown',
|
||||
data: {
|
||||
content: Messages[locale].great_thanks,
|
||||
content: Messages[locale].great_thanks
|
||||
}
|
||||
});
|
||||
let sleep = ms => {
|
||||
|
@ -92,23 +94,24 @@ export class QualityDialog extends IGBDialog {
|
|||
});
|
||||
};
|
||||
|
||||
await service.insertQuestionAlternate(
|
||||
min.instance.instanceId,
|
||||
user.lastQuestion,
|
||||
user.lastQuestionId
|
||||
);
|
||||
await service.insertQuestionAlternate(min.instance.instanceId, user.lastQuestion, user.lastQuestionId);
|
||||
|
||||
// Updates values to perform Bot Analytics.
|
||||
|
||||
const analytics = new AnalyticsService();
|
||||
analytics.updateConversationSuggestion(
|
||||
min.instance.instanceId, user.conversation, step.result, user.systemUser.locale);
|
||||
min.instance.instanceId,
|
||||
user.conversation,
|
||||
step.result,
|
||||
user.systemUser.locale
|
||||
);
|
||||
|
||||
// Goes to the ask loop.
|
||||
|
||||
return await step.replaceDialog('/ask', { emptyPrompt: true });
|
||||
}
|
||||
}
|
||||
]));
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,16 +36,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import {
|
||||
AutoIncrement,
|
||||
BelongsTo,
|
||||
Column,
|
||||
DataType,
|
||||
ForeignKey,
|
||||
Model,
|
||||
PrimaryKey,
|
||||
Table
|
||||
} from 'sequelize-typescript';
|
||||
import { AutoIncrement, BelongsTo, Column, DataType, ForeignKey, Model, PrimaryKey, Table } from 'sequelize-typescript';
|
||||
|
||||
import { GuaribasInstance } from '../../core.gbapp/models/GBModel.js';
|
||||
|
||||
|
@ -54,22 +45,21 @@ import { GuaribasInstance } from '../../core.gbapp/models/GBModel.js';
|
|||
*/
|
||||
@Table
|
||||
export class GuaribasQuestionAlternate extends Model<GuaribasQuestionAlternate> {
|
||||
|
||||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
declare quickAnswerId: number;
|
||||
quickAnswerId: number;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare questionTyped: string;
|
||||
questionTyped: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare questionText: string;
|
||||
questionText: string;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasInstance)
|
||||
declare instance: GuaribasInstance;
|
||||
instance: GuaribasInstance;
|
||||
}
|
||||
|
|
|
@ -39,11 +39,7 @@ import { GuaribasQuestionAlternate } from '../models/index.js';
|
|||
* Customer Satisfaction Service Layer.
|
||||
*/
|
||||
export class CSService {
|
||||
|
||||
public async getQuestionFromAlternateText(
|
||||
instanceId: number,
|
||||
text: string): Promise<GuaribasQuestion> {
|
||||
|
||||
public async getQuestionFromAlternateText (instanceId: number, text: string): Promise<GuaribasQuestion> {
|
||||
const questionAlternate = await GuaribasQuestionAlternate.findOne({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
|
@ -54,7 +50,6 @@ export class CSService {
|
|||
let question: GuaribasQuestion = null;
|
||||
|
||||
if (questionAlternate !== null) {
|
||||
|
||||
question = await GuaribasQuestion.findOne({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
|
@ -69,7 +64,8 @@ export class CSService {
|
|||
public async insertQuestionAlternate (
|
||||
instanceId: number,
|
||||
questionTyped: string,
|
||||
questionText: string): Promise<GuaribasQuestionAlternate> {
|
||||
questionText: string
|
||||
): Promise<GuaribasQuestionAlternate> {
|
||||
return await GuaribasQuestionAlternate.create(<GuaribasQuestionAlternate>{
|
||||
questionTyped: questionTyped,
|
||||
questionText: questionText
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
export const Messages = {
|
||||
'en-US': {
|
||||
|
||||
about_suggestions: 'Suggestions are welcomed and improve my quality...',
|
||||
what_about_service: 'What about my service?',
|
||||
glad_you_liked: 'I\'m glad you liked. I\'m here for you.',
|
||||
we_will_improve: 'Let\'s take note of that, thanks for sharing.',
|
||||
glad_you_liked: "I'm glad you liked. I'm here for you.",
|
||||
we_will_improve: "Let's take note of that, thanks for sharing.",
|
||||
what_about_me: 'What about the service, please rate between 1 and 5.',
|
||||
thanks: 'Thanks!',
|
||||
im_sorry_lets_try: 'I\'m sorry. Let\'s try again...',
|
||||
im_sorry_lets_try: "I'm sorry. Let's try again...",
|
||||
great_thanks: 'Great, thanks for sharing your thoughts.',
|
||||
please_no_bad_words: 'Please, no bad words.',
|
||||
please_wait_transfering: 'Please, wait while I find an agent to answer you.',
|
||||
notify_agent: (name) => `New call available for *${name}*, you can answer right here when you are finished, type /qt.`,
|
||||
notify_end_transfer: (botName) => `All messages will be now routed to user ${botName}.`,
|
||||
notify_agent_transfer_done: (person) => `Now talking directly to ${person}.`,
|
||||
check_whatsapp_ok: 'If you are seeing this message, WhatsApp API is OK.',
|
||||
notify_agent: name =>
|
||||
`New call available for *${name}*, you can answer right here when you are finished, type /qt.`,
|
||||
notify_end_transfer: botName => `All messages will be now routed to user ${botName}.`,
|
||||
notify_agent_transfer_done: person => `Now talking directly to ${person}.`,
|
||||
check_whatsapp_ok: 'If you are seeing this message, WhatsApp API is OK.'
|
||||
},
|
||||
'pt-BR': {
|
||||
about_suggestions: 'Sugestões melhoram muito minha qualidade...',
|
||||
|
@ -27,9 +27,10 @@ export const Messages = {
|
|||
great_thanks: 'Ótimo, obrigado por contribuir com sua resposta.',
|
||||
please_no_bad_words: 'Por favor, sem palavrões!',
|
||||
please_wait_transfering: 'Por favor, aguarde enquanto eu localizo alguém para te atender.',
|
||||
notify_agent: (name) => `Existe um novo atendimento para *${name}*, por favor, responda aqui mesmo para a pessoa. Para finalizar, digite /qt.`,
|
||||
notify_end_transfer: (botName) => `Falando novamente com o bot ${botName}.`,
|
||||
notify_agent_transfer_done: (person) => `Todas as mensagens agora sendo transmitidas para ${person}.`,
|
||||
check_whatsapp_ok: 'Se você está recebendo esta mensagem, significa que a API do WhatsApp está OK.',
|
||||
notify_agent: name =>
|
||||
`Existe um novo atendimento para *${name}*, por favor, responda aqui mesmo para a pessoa. Para finalizar, digite /qt.`,
|
||||
notify_end_transfer: botName => `Falando novamente com o bot ${botName}.`,
|
||||
notify_agent_transfer_done: person => `Todas as mensagens agora sendo transmitidas para ${person}.`,
|
||||
check_whatsapp_ok: 'Se você está recebendo esta mensagem, significa que a API do WhatsApp está OK.'
|
||||
}
|
||||
};
|
||||
|
|
|
@ -8,26 +8,26 @@
|
|||
"homepage": ".",
|
||||
"dependencies": {
|
||||
"@midudev/react-static-content": "^1.0.4",
|
||||
"ajv": "^8.6.0",
|
||||
"botframework-directlinejs": "0.14.1",
|
||||
"botframework-webchat": "^4.13.0",
|
||||
"ajv": "^8.11.2",
|
||||
"botframework-directlinejs": "0.15.1",
|
||||
"botframework-webchat": "^4.15.5",
|
||||
"deep-extend": "0.6.0",
|
||||
"eslint": "7.11.0",
|
||||
"eslint": "8.28.0",
|
||||
"fetch": "1.1.0",
|
||||
"msal": "^1.4.11",
|
||||
"powerbi-client": "2.18.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"msal": "^1.4.17",
|
||||
"powerbi-client": "2.22.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-helmet": "6.1.0",
|
||||
"react-modern-audio-player": "^1.2.2",
|
||||
"react-player": "^2.9.0",
|
||||
"react-modern-audio-player": "^1.3.0",
|
||||
"react-player": "^2.11.0",
|
||||
"react-powerbi": "0.9.1",
|
||||
"react-scripts": "^4.0.3",
|
||||
"react-super-seo": "^1.0.6",
|
||||
"react-transition-group": "^4.4.2",
|
||||
"rxjs": "^7.1.0",
|
||||
"url-join": "4.0.1",
|
||||
"webpack": "4.44.2"
|
||||
"react-scripts": "^5.0.1",
|
||||
"react-super-seo": "^1.0.7",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"rxjs": "^7.5.7",
|
||||
"url-join": "5.0.0",
|
||||
"webpack": "5.75.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
|
|
@ -46,9 +46,7 @@ import { GoogleChatDirectLine } from './services/GoogleChatDirectLine.js';
|
|||
export class GBGoogleChatPackage implements IGBPackage {
|
||||
public sysPackages: IGBPackage[];
|
||||
|
||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
||||
|
||||
}
|
||||
public async loadBot (min: GBMinInstance): Promise<void> {}
|
||||
|
||||
public async getDialogs (min: GBMinInstance) {
|
||||
GBLog.verbose(`getDialogs called.`);
|
||||
|
@ -68,5 +66,4 @@ export class GBGoogleChatPackage implements IGBPackage {
|
|||
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ import { SecService } from '../../security.gbapp/services/SecService.js';
|
|||
* Support for Google Chat.
|
||||
*/
|
||||
export class GoogleChatDirectLine extends GBService {
|
||||
|
||||
public static conversationIds = {};
|
||||
public pollInterval = 5000;
|
||||
public directLineClientName = 'DirectLineClient';
|
||||
|
@ -84,7 +83,6 @@ export class GoogleChatDirectLine extends GBService {
|
|||
projectId: this.GoogleProjectId,
|
||||
credentials: { client_email: GoogleClientEmail, private_key: GoogleClientPrivateKey }
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public static async asyncForEach (array, callback) {
|
||||
|
@ -94,9 +92,7 @@ export class GoogleChatDirectLine extends GBService {
|
|||
}
|
||||
|
||||
public async setup (setUrl) {
|
||||
|
||||
this.directLineClient =
|
||||
new Swagger({
|
||||
this.directLineClient = new Swagger({
|
||||
spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')),
|
||||
usePromise: true
|
||||
});
|
||||
|
@ -109,15 +105,12 @@ export class GoogleChatDirectLine extends GBService {
|
|||
|
||||
if (setUrl) {
|
||||
try {
|
||||
|
||||
const subscription = this.pubSubClient.subscription(this.GoogleChatSubscriptionName);
|
||||
subscription.on('message', this.receiver.bind(this));
|
||||
|
||||
} catch (error) {
|
||||
GBLog.error(`Error initializing 3rd party GoogleChat provider(1) ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async resetConversationId (key) {
|
||||
|
@ -125,13 +118,11 @@ export class GoogleChatDirectLine extends GBService {
|
|||
}
|
||||
|
||||
public async check () {
|
||||
|
||||
GBLog.info(`GBGoogleChat: Checking server...`);
|
||||
}
|
||||
|
||||
// TODO: Check service.Users.Messages.List("me").
|
||||
public async receiver (message) {
|
||||
|
||||
const event = JSON.parse(Buffer.from(message.data, 'binary').toString());
|
||||
|
||||
let from = '';
|
||||
|
@ -140,7 +131,6 @@ export class GoogleChatDirectLine extends GBService {
|
|||
const threadName = event.message.thread.name;
|
||||
|
||||
if (event['type'] === 'ADDED_TO_SPACE' && event['space']['singleUserBotDm']) {
|
||||
|
||||
} else if (event['type'] === 'MESSAGE') {
|
||||
text = event.message.text;
|
||||
fromName = event.message.sender.displayName;
|
||||
|
@ -150,8 +140,7 @@ export class GoogleChatDirectLine extends GBService {
|
|||
message.ack();
|
||||
|
||||
const sec = new SecService();
|
||||
const user = await sec.ensureUser(this.min.instance.instanceId, from,
|
||||
from, '', 'googlechat', fromName, from);
|
||||
const user = await sec.ensureUser(this.min.instance.instanceId, from, from, '', 'googlechat', fromName, from);
|
||||
|
||||
await sec.updateConversationReferenceById(user.userId, threadName);
|
||||
|
||||
|
@ -170,7 +159,6 @@ export class GoogleChatDirectLine extends GBService {
|
|||
this.pollMessages(client, generatedConversationId, threadName, from, fromName);
|
||||
this.inputMessage(client, generatedConversationId, threadName, text, from, fromName);
|
||||
} else {
|
||||
|
||||
this.inputMessage(client, conversationId, threadName, text, from, fromName);
|
||||
}
|
||||
}
|
||||
|
@ -253,25 +241,16 @@ export class GoogleChatDirectLine extends GBService {
|
|||
}
|
||||
|
||||
public async sendToDevice (from: string, conversationId: string, threadName, msg: string) {
|
||||
|
||||
try {
|
||||
|
||||
let threadParts = threadName.split('/');
|
||||
let spaces = threadParts[1];
|
||||
let threadKey = threadParts[3];
|
||||
const scopes = ['https://www.googleapis.com/auth/chat.bot'];
|
||||
|
||||
const jwtClient = new google.auth.JWT(
|
||||
this.GoogleClientEmail,
|
||||
null,
|
||||
this.GoogleClientPrivateKey,
|
||||
scopes,
|
||||
null
|
||||
);
|
||||
const jwtClient = new google.auth.JWT(this.GoogleClientEmail, null, this.GoogleClientPrivateKey, scopes, null);
|
||||
await jwtClient.authorize();
|
||||
const chat = google.chat({ version: 'v1', auth: jwtClient });
|
||||
|
||||
|
||||
const res = await chat.spaces.messages.create({
|
||||
parent: `spaces/${spaces}`,
|
||||
threadKey: threadKey,
|
||||
|
@ -286,15 +265,10 @@ export class GoogleChatDirectLine extends GBService {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public async sendToDeviceEx (to, conversationId, threadName, text, locale) {
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
|
||||
text = await minBoot.conversationalService.translate(
|
||||
minBoot,
|
||||
text,
|
||||
locale
|
||||
);
|
||||
text = await minBoot.conversationalService.translate(minBoot, text, locale);
|
||||
await this.sendToDevice(to, conversationId, threadName, text);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
export const Messages = {
|
||||
'en-US': {
|
||||
notify_end_transfer: (botName) => `Now talking to ${botName} again.`
|
||||
notify_end_transfer: botName => `Now talking to ${botName} again.`
|
||||
},
|
||||
'pt-BR': {
|
||||
notify_end_transfer: (botName) => `Falando com o bot ${botName} novamente.`
|
||||
notify_end_transfer: botName => `Falando com o bot ${botName} novamente.`
|
||||
}
|
||||
};
|
||||
|
|
|
@ -45,9 +45,7 @@ import { Sequelize } from 'sequelize-typescript';
|
|||
export class GBHubSpotPackage implements IGBPackage {
|
||||
public sysPackages: IGBPackage[];
|
||||
|
||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
||||
|
||||
}
|
||||
public async loadBot (min: GBMinInstance): Promise<void> {}
|
||||
|
||||
public async getDialogs (min: GBMinInstance) {
|
||||
GBLog.verbose(`getDialogs called.`);
|
||||
|
@ -67,5 +65,4 @@ export class GBHubSpotPackage implements IGBPackage {
|
|||
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,17 +30,12 @@
|
|||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
|
||||
import { GBLog, GBMinInstance, GBService } from 'botlib';
|
||||
import { promisify } from 'util';
|
||||
import Swagger from 'swagger-client';
|
||||
import * as hubspot from '@hubspot/api-client';
|
||||
|
||||
|
||||
/**
|
||||
* Support for Hub Spot XRM.
|
||||
*/
|
||||
export class HubSpotServices extends GBService {
|
||||
|
||||
|
||||
}
|
||||
export class HubSpotServices extends GBService {}
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
export const Messages = {
|
||||
'en-US': {
|
||||
|
||||
},
|
||||
'pt-BR': {
|
||||
|
||||
}
|
||||
'en-US': {},
|
||||
'pt-BR': {}
|
||||
};
|
||||
|
|
|
@ -84,8 +84,7 @@ export class AskDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -101,9 +100,9 @@ export class AskDialog extends IGBDialog {
|
|||
if (step.options && step.options.firstTime) {
|
||||
text = Messages[locale].ask_first_time;
|
||||
} else if (step.options && step.options.isReturning) {
|
||||
text = ""; // REMOVED: Messages[locale].anything_else;
|
||||
text = ''; // REMOVED: Messages[locale].anything_else;
|
||||
} else if (step.options && step.options.emptyPrompt) {
|
||||
text = "";
|
||||
text = '';
|
||||
} else if (user.subjects.length > 0) {
|
||||
text = Messages[locale].which_question;
|
||||
} else {
|
||||
|
@ -111,7 +110,6 @@ export class AskDialog extends IGBDialog {
|
|||
}
|
||||
|
||||
return await min.conversationalService.prompt(min, step, text);
|
||||
|
||||
},
|
||||
async step => {
|
||||
if (step.result) {
|
||||
|
@ -120,7 +118,15 @@ export class AskDialog extends IGBDialog {
|
|||
|
||||
let sec = new SecService();
|
||||
const member = step.context.activity.from;
|
||||
const user = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name, null);
|
||||
const user = await sec.ensureUser(
|
||||
min.instance.instanceId,
|
||||
member.id,
|
||||
member.name,
|
||||
'',
|
||||
'web',
|
||||
member.name,
|
||||
null
|
||||
);
|
||||
|
||||
let handled = false;
|
||||
let nextDialog = null;
|
||||
|
@ -132,9 +138,7 @@ export class AskDialog extends IGBDialog {
|
|||
user: user ? user['dataValues'] : null
|
||||
};
|
||||
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
|
||||
if (
|
||||
nextDialog = await e.onExchangeData(min, 'handleAnswer', data)
|
||||
) {
|
||||
if ((nextDialog = await e.onExchangeData(min, 'handleAnswer', data))) {
|
||||
handled = true;
|
||||
}
|
||||
});
|
||||
|
@ -158,8 +162,7 @@ export class AskDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -176,8 +179,7 @@ export class AskDialog extends IGBDialog {
|
|||
// when people type just the @botName in MSTEAMS for example.
|
||||
|
||||
if (!text) {
|
||||
const startDialog =
|
||||
min.core.getParam(min.instance, 'Start Dialog', null);
|
||||
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
||||
if (startDialog) {
|
||||
await GBVMService.callVM(startDialog.toLowerCase().trim(), min, step, this.deployer, false);
|
||||
}
|
||||
|
@ -201,8 +203,11 @@ export class AskDialog extends IGBDialog {
|
|||
|
||||
// Searches KB for the first time.
|
||||
|
||||
const searchScore = min.core.getParam(min.instance, 'Search Score',
|
||||
min.instance.searchScore ? min.instance.searchScore : minBoot.instance.searchScore);
|
||||
const searchScore = min.core.getParam(
|
||||
min.instance,
|
||||
'Search Score',
|
||||
min.instance.searchScore ? min.instance.searchScore : minBoot.instance.searchScore
|
||||
);
|
||||
|
||||
user.lastQuestion = text;
|
||||
await min.userProfile.set(step.context, user);
|
||||
|
@ -256,7 +261,7 @@ export class AskDialog extends IGBDialog {
|
|||
|
||||
// Tries to answer by NLP.
|
||||
|
||||
let nextDialog = await min.conversationalService["routeNLP2"](step, min, text);
|
||||
let nextDialog = await min.conversationalService['routeNLP2'](step, min, text);
|
||||
if (nextDialog) {
|
||||
return nextDialog;
|
||||
}
|
||||
|
@ -270,30 +275,29 @@ export class AskDialog extends IGBDialog {
|
|||
const docs = await min.kbService['getDocs'](min.instance.instanceId);
|
||||
|
||||
await CollectionUtil.asyncForEach(docs, async (doc: GuaribasAnswer) => {
|
||||
|
||||
if (!answered) {
|
||||
|
||||
const answerText = await min.kbService['readComprehension'](min.instance.instanceId, doc.content, text);
|
||||
answered = true;
|
||||
text = await min.conversationalService.translate(min, text, user.systemUser.locale
|
||||
text = await min.conversationalService.translate(
|
||||
min,
|
||||
text,
|
||||
user.systemUser.locale
|
||||
? user.systemUser.locale
|
||||
: min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE')));
|
||||
: min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
||||
);
|
||||
await min.conversationalService.sendText(min, step, answerText);
|
||||
await min.conversationalService.sendEvent(min, step, 'stop', undefined);
|
||||
}
|
||||
|
||||
});
|
||||
return await step.replaceDialog('/ask', { isReturning: true });
|
||||
}
|
||||
|
||||
// Not found.
|
||||
|
||||
const message = min.core.getParam<string>(min.instance, 'Not Found Message',
|
||||
Messages[locale].did_not_find);
|
||||
const message = min.core.getParam<string>(min.instance, 'Not Found Message', Messages[locale].did_not_find);
|
||||
|
||||
await min.conversationalService.sendText(min, step, message);
|
||||
return await step.replaceDialog('/ask', { isReturning: true });
|
||||
|
||||
}
|
||||
];
|
||||
}
|
||||
|
@ -301,8 +305,6 @@ export class AskDialog extends IGBDialog {
|
|||
private static async handleAnswer (service: KBService, min: GBMinInstance, step: any, answer: GuaribasAnswer) {
|
||||
const text = answer.content;
|
||||
if (text.endsWith('.docx')) {
|
||||
|
||||
|
||||
const mainName = GBVMService.getMethodNameFromVBSFilename(text);
|
||||
return await GBVMService.callVM(mainName, min, step, this.deployer, false);
|
||||
} else {
|
||||
|
@ -320,8 +322,7 @@ export class AskDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -54,15 +54,14 @@ export class FaqDialog extends IGBDialog {
|
|||
* @param min The minimal bot instance data.
|
||||
*/
|
||||
public static setup (bot: BotAdapter, min: GBMinInstance) {
|
||||
|
||||
const service = new KBService(min.core.sequelize);
|
||||
|
||||
min.dialogs.add(new WaterfallDialog('/faq', [
|
||||
min.dialogs.add(
|
||||
new WaterfallDialog('/faq', [
|
||||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -81,6 +80,7 @@ export class FaqDialog extends IGBDialog {
|
|||
return await step.next();
|
||||
}
|
||||
}
|
||||
]));
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,8 +75,7 @@ export class MenuDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -103,8 +102,7 @@ export class MenuDialog extends IGBDialog {
|
|||
|
||||
// Whenever a subject is selected, shows a faq about it.
|
||||
if (user.subjects.length > 0) {
|
||||
const list = await service.getFaqBySubjectArray(min.instance.instanceId,
|
||||
'menu', user.subjects);
|
||||
const list = await service.getFaqBySubjectArray(min.instance.instanceId, 'menu', user.subjects);
|
||||
await min.conversationalService.sendEvent(min, step, 'play', {
|
||||
playerType: 'bullet',
|
||||
data: list.slice(0, 10)
|
||||
|
@ -142,9 +140,10 @@ export class MenuDialog extends IGBDialog {
|
|||
attachments.push(card);
|
||||
});
|
||||
if (attachments.length === 0) {
|
||||
|
||||
if (user.subjects && user.subjects.length > 0) {
|
||||
await min.conversationalService.sendText(min, step,
|
||||
await min.conversationalService.sendText(
|
||||
min,
|
||||
step,
|
||||
Messages[locale].lets_search(KBService.getFormattedSubjectItems(user.subjects))
|
||||
);
|
||||
}
|
||||
|
|
|
@ -54,10 +54,7 @@ import {
|
|||
UpdatedAt
|
||||
} from 'sequelize-typescript';
|
||||
|
||||
import {
|
||||
GuaribasInstance,
|
||||
GuaribasPackage
|
||||
} from '../../core.gbapp/models/GBModel.js';
|
||||
import { GuaribasInstance, GuaribasPackage } from '../../core.gbapp/models/GBModel.js';
|
||||
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||
|
||||
/**
|
||||
|
@ -68,53 +65,53 @@ export class GuaribasSubject extends Model<GuaribasSubject> {
|
|||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
declare subjectId: number;
|
||||
subjectId: number;
|
||||
|
||||
@Column(DataType.INTEGER)
|
||||
declare internalId: string;
|
||||
internalId: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare title: string;
|
||||
title: string;
|
||||
|
||||
@Column(DataType.STRING(512))
|
||||
declare description: string;
|
||||
description: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare from: string;
|
||||
from: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare to: string;
|
||||
to: string;
|
||||
|
||||
@ForeignKey(() => GuaribasSubject)
|
||||
@Column(DataType.INTEGER)
|
||||
declare parentSubjectId: number;
|
||||
parentSubjectId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasSubject, 'parentSubjectId')
|
||||
declare parentSubject: GuaribasSubject;
|
||||
parentSubject: GuaribasSubject;
|
||||
|
||||
@HasMany(() => GuaribasSubject, { foreignKey: 'parentSubjectId' })
|
||||
declare childrenSubjects: GuaribasSubject[];
|
||||
childrenSubjects: GuaribasSubject[];
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasInstance)
|
||||
declare instance: GuaribasInstance;
|
||||
instance: GuaribasInstance;
|
||||
|
||||
@ForeignKey(() => GuaribasUser)
|
||||
@Column(DataType.INTEGER)
|
||||
declare responsibleUserId: number;
|
||||
responsibleUserId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasUser)
|
||||
declare responsibleUser: GuaribasUser;
|
||||
responsibleUser: GuaribasUser;
|
||||
|
||||
@ForeignKey(() => GuaribasPackage)
|
||||
@Column(DataType.INTEGER)
|
||||
declare packageId: number;
|
||||
packageId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasPackage)
|
||||
declare package: GuaribasPackage;
|
||||
package: GuaribasPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -125,62 +122,61 @@ export class GuaribasQuestion extends Model<GuaribasQuestion> {
|
|||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
declare questionId: number;
|
||||
questionId: number;
|
||||
|
||||
@Column(DataType.STRING(64))
|
||||
declare subject1: string;
|
||||
subject1: string;
|
||||
|
||||
@Column(DataType.STRING(64))
|
||||
declare subject2: string;
|
||||
subject2: string;
|
||||
|
||||
@Column(DataType.STRING(64))
|
||||
declare subject3: string;
|
||||
subject3: string;
|
||||
|
||||
@Column(DataType.STRING(64))
|
||||
declare subject4: string;
|
||||
subject4: string;
|
||||
|
||||
@Column(DataType.STRING(1024))
|
||||
declare keywords: string;
|
||||
keywords: string;
|
||||
|
||||
@Column(DataType.BOOLEAN)
|
||||
declare skipIndex: boolean;
|
||||
skipIndex: boolean;
|
||||
|
||||
@Column(DataType.STRING(512))
|
||||
declare from: string;
|
||||
from: string;
|
||||
|
||||
@Column(DataType.STRING(512))
|
||||
declare to: string;
|
||||
to: string;
|
||||
|
||||
@Column(DataType.TEXT)
|
||||
declare content: string;
|
||||
content: string;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@CreatedAt
|
||||
declare createdAt: Date;
|
||||
createdAt: Date;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@UpdatedAt
|
||||
declare updatedAt: Date;
|
||||
|
||||
updatedAt: Date;
|
||||
|
||||
//tslint:disable-next-line:no-use-before-declare
|
||||
@ForeignKey(() => GuaribasAnswer)
|
||||
@Column(DataType.INTEGER)
|
||||
declare answerId: number;
|
||||
answerId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasInstance)
|
||||
declare instance: GuaribasInstance;
|
||||
instance: GuaribasInstance;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@ForeignKey(() => GuaribasPackage)
|
||||
@Column(DataType.INTEGER)
|
||||
declare packageId: number;
|
||||
packageId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasPackage)
|
||||
declare package: GuaribasPackage;
|
||||
package: GuaribasPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -191,53 +187,52 @@ export class GuaribasAnswer extends Model<GuaribasAnswer> {
|
|||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
declare answerId: number;
|
||||
answerId: number;
|
||||
|
||||
@Length({ min: 0, max: 512 })
|
||||
@Column(DataType.STRING(512))
|
||||
declare media: string;
|
||||
media: string;
|
||||
|
||||
@Length({ min: 0, max: 12 })
|
||||
@Column(DataType.STRING(12))
|
||||
declare format: string;
|
||||
format: string;
|
||||
|
||||
@Column(DataType.TEXT)
|
||||
declare content: string;
|
||||
content: string;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@CreatedAt
|
||||
declare createdAt: Date;
|
||||
createdAt: Date;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@UpdatedAt
|
||||
declare updatedAt: Date;
|
||||
|
||||
updatedAt: Date;
|
||||
|
||||
@HasMany(() => GuaribasQuestion)
|
||||
declare questions: GuaribasQuestion[];
|
||||
questions: GuaribasQuestion[];
|
||||
|
||||
@HasOne(() => GuaribasQuestion)
|
||||
declare prev: GuaribasQuestion;
|
||||
prev: GuaribasQuestion;
|
||||
|
||||
@HasOne(() => GuaribasQuestion)
|
||||
declare next: GuaribasQuestion;
|
||||
next: GuaribasQuestion;
|
||||
|
||||
@ForeignKey(() => GuaribasQuestion)
|
||||
@Column(DataType.INTEGER)
|
||||
declare nextId: number;
|
||||
nextId: number;
|
||||
|
||||
@ForeignKey(() => GuaribasQuestion)
|
||||
@Column(DataType.INTEGER)
|
||||
declare prevId: number;
|
||||
prevId: number;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@ForeignKey(() => GuaribasPackage)
|
||||
@Column(DataType.INTEGER)
|
||||
declare packageId: number;
|
||||
packageId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasPackage)
|
||||
declare package: GuaribasPackage;
|
||||
package: GuaribasPackage;
|
||||
}
|
||||
|
|
|
@ -1,32 +1,27 @@
|
|||
export const Messages = {
|
||||
'en-US': {
|
||||
did_not_find: 'I\'m sorry I didn\'t find anything.',
|
||||
did_not_find: "I'm sorry I didn't find anything.",
|
||||
going_answer: 'Great choice, now looking for your answer...',
|
||||
wider_answer: subjectText =>
|
||||
`Answering to you in a broader way... Not just about ${subjectText}.`,
|
||||
which_question: 'What\'s your question?',
|
||||
wider_answer: subjectText => `Answering to you in a broader way... Not just about ${subjectText}.`,
|
||||
which_question: "What's your question?",
|
||||
anything_else: 'Can I help you with anything else?',
|
||||
here_is_subjects: 'Here are some subjects to choose from...',
|
||||
menu_select: 'Select',
|
||||
lets_search: query =>
|
||||
`Lets search for ${query}... What do you want to know?`,
|
||||
see_faq: 'Please take a look at the FAQ I\'ve prepared for you. You can click on them to get the answer.',
|
||||
lets_search: query => `Lets search for ${query}... What do you want to know?`,
|
||||
see_faq: "Please take a look at the FAQ I've prepared for you. You can click on them to get the answer.",
|
||||
|
||||
ask_first_time: 'What are you looking for?'
|
||||
},
|
||||
'pt-BR': {
|
||||
did_not_find: 'Desculpe-me, não encontrei nada a respeito.',
|
||||
going_answer: 'Ótima escolha, procurando resposta para sua questão...',
|
||||
wider_answer: subjectText =>
|
||||
`Vou te responder de modo mais abrangente... Não apenas sobre ${subjectText}`,
|
||||
wider_answer: subjectText => `Vou te responder de modo mais abrangente... Não apenas sobre ${subjectText}`,
|
||||
which_question: 'Qual a pergunta?',
|
||||
anything_else: 'Posso ajudar em algo mais?',
|
||||
here_is_subjects: 'Aqui estão algumas categorias de assuntos...',
|
||||
menu_select: 'Selecionar',
|
||||
lets_search: query =>
|
||||
`Let's search about ${query}... What do you want to know?`,
|
||||
see_faq:
|
||||
'Veja algumas perguntas mais frequentes logo na tela. Clique numa delas para eu responder.',
|
||||
lets_search: query => `Let's search about ${query}... What do you want to know?`,
|
||||
see_faq: 'Veja algumas perguntas mais frequentes logo na tela. Clique numa delas para eu responder.',
|
||||
|
||||
ask_first_time: 'Como eu posso ajudar?'
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
|
||||
import { GBLog, GBMinInstance, IGBDialog } from 'botlib';
|
||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
||||
import { Messages } from '../strings.js';
|
||||
|
@ -46,16 +45,14 @@ import * as phone from 'google-libphonenumber';
|
|||
* Dialogs for handling Menu control.
|
||||
*/
|
||||
export class ProfileDialog extends IGBDialog {
|
||||
|
||||
public static getNameDialog (min: GBMinInstance) {
|
||||
|
||||
return {
|
||||
id: '/profile_name', waterfall: [
|
||||
id: '/profile_name',
|
||||
waterfall: [
|
||||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -67,7 +64,7 @@ export class ProfileDialog extends IGBDialog {
|
|||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
const fullName = (text) => {
|
||||
const fullName = text => {
|
||||
return text.match(/^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$/gi);
|
||||
};
|
||||
|
||||
|
@ -80,21 +77,20 @@ export class ProfileDialog extends IGBDialog {
|
|||
step.activeDialog.state.options.name = value[0];
|
||||
|
||||
return await step.replaceDialog('/profile_mobile', step.activeDialog.state.options);
|
||||
|
||||
}
|
||||
}]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
public static getMobileDialog (min: GBMinInstance) {
|
||||
|
||||
return {
|
||||
id: '/profile_mobile', waterfall: [
|
||||
id: '/profile_mobile',
|
||||
waterfall: [
|
||||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -125,19 +121,19 @@ export class ProfileDialog extends IGBDialog {
|
|||
|
||||
return await step.replaceDialog('/profile_mobile_confirm', step.activeDialog.state.options);
|
||||
}
|
||||
}]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
public static getMobileConfirmDialog (min: GBMinInstance) {
|
||||
|
||||
return {
|
||||
id: '/profile_mobile_confirm', waterfall: [
|
||||
id: '/profile_mobile_confirm',
|
||||
waterfall: [
|
||||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -146,8 +142,10 @@ export class ProfileDialog extends IGBDialog {
|
|||
const locale = step.context.activity.locale;
|
||||
const from = step.activeDialog.state.options.mobile;
|
||||
if (min.whatsAppDirectLine) {
|
||||
|
||||
await min.whatsAppDirectLine.sendToDevice(from, `${step.activeDialog.state.options.mobileCode} is your General Bots creation code.`);
|
||||
await min.whatsAppDirectLine.sendToDevice(
|
||||
from,
|
||||
`${step.activeDialog.state.options.mobileCode} is your General Bots creation code.`
|
||||
);
|
||||
} else {
|
||||
GBLog.info(`WhatsApp not configured. Here is the code: ${step.activeDialog.state.options.mobileCode}.`);
|
||||
}
|
||||
|
@ -164,18 +162,19 @@ export class ProfileDialog extends IGBDialog {
|
|||
} else {
|
||||
await step.replaceDialog('/profile_email', step.activeDialog.state.options);
|
||||
}
|
||||
}]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
public static getEmailDialog (min: GBMinInstance) {
|
||||
return {
|
||||
id: '/profile_email', waterfall: [
|
||||
id: '/profile_email',
|
||||
waterfall: [
|
||||
async step => {
|
||||
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
|
||||
return await step.beginDialog('/auth');
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return await step.next(step.options);
|
||||
}
|
||||
},
|
||||
|
@ -186,7 +185,7 @@ export class ProfileDialog extends IGBDialog {
|
|||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
const extractEntity = (text) => {
|
||||
const extractEntity = text => {
|
||||
return text.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/gi);
|
||||
};
|
||||
|
||||
|
@ -199,7 +198,8 @@ export class ProfileDialog extends IGBDialog {
|
|||
step.activeDialog.state.options.email = value[0];
|
||||
await step.replaceDialog(`/${step.activeDialog.state.options.nextDialog}`, step.activeDialog.state.options);
|
||||
}
|
||||
}]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from './models/index.j
|
|||
export class GBSecurityPackage implements IGBPackage {
|
||||
public sysPackages: IGBPackage[];
|
||||
public async getDialogs (min: GBMinInstance) {
|
||||
|
||||
const out = [
|
||||
ProfileDialog.getNameDialog(min),
|
||||
ProfileDialog.getEmailDialog(min),
|
||||
|
@ -60,7 +59,6 @@ export class GBSecurityPackage implements IGBPackage {
|
|||
out.push(OAuthDialog.getOAuthDialog(min));
|
||||
}
|
||||
return out;
|
||||
|
||||
}
|
||||
public async unloadPackage (core: IGBCoreService): Promise<void> {
|
||||
GBLog.verbose(`unloadPackage called.`);
|
||||
|
|
|
@ -58,46 +58,46 @@ export class GuaribasUser extends Model<GuaribasUser> {
|
|||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
declare userId: number;
|
||||
userId: number;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare displayName: string;
|
||||
displayName: string;
|
||||
|
||||
@Column(DataType.INTEGER)
|
||||
declare userSystemId: string;
|
||||
userSystemId: string;
|
||||
@Column(DataType.STRING(255))
|
||||
declare userName: string;
|
||||
userName: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare defaultChannel: string;
|
||||
defaultChannel: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
declare email: string;
|
||||
email: string;
|
||||
|
||||
@Column(DataType.STRING(5))
|
||||
declare locale: string;
|
||||
locale: string;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasInstance)
|
||||
declare instance: GuaribasInstance;
|
||||
instance: GuaribasInstance;
|
||||
|
||||
@Column(DataType.INTEGER)
|
||||
declare agentSystemId: string;
|
||||
agentSystemId: string;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
declare agentContacted: Date;
|
||||
agentContacted: Date;
|
||||
|
||||
@Column(DataType.STRING(16))
|
||||
declare agentMode: string;
|
||||
agentMode: string;
|
||||
|
||||
@Column(DataType.TEXT)
|
||||
declare conversationReference: string;
|
||||
conversationReference: string;
|
||||
|
||||
@Column(DataType.STRING(64))
|
||||
declare hearOnDialog: string;
|
||||
hearOnDialog: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,18 +108,18 @@ export class GuaribasGroup extends Model<GuaribasGroup> {
|
|||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
declare groupId: number;
|
||||
groupId: number;
|
||||
|
||||
@Length({ min: 0, max: 512 })
|
||||
@Column(DataType.STRING(512))
|
||||
declare displayName: string;
|
||||
displayName: string;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasInstance)
|
||||
declare instance: GuaribasInstance;
|
||||
instance: GuaribasInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,22 +129,22 @@ export class GuaribasGroup extends Model<GuaribasGroup> {
|
|||
export class GuaribasUserGroup extends Model<GuaribasUserGroup> {
|
||||
@ForeignKey(() => GuaribasUser)
|
||||
@Column(DataType.INTEGER)
|
||||
declare userId: number;
|
||||
userId: number;
|
||||
|
||||
@ForeignKey(() => GuaribasGroup)
|
||||
@Column(DataType.INTEGER)
|
||||
declare groupId: number;
|
||||
groupId: number;
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
declare instanceId: number;
|
||||
instanceId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasInstance)
|
||||
declare instance: GuaribasInstance;
|
||||
instance: GuaribasInstance;
|
||||
|
||||
@BelongsTo(() => GuaribasGroup)
|
||||
declare group: GuaribasGroup;
|
||||
group: GuaribasGroup;
|
||||
|
||||
@BelongsTo(() => GuaribasUser)
|
||||
declare user: GuaribasUser;
|
||||
user: GuaribasUser;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import { FindOptions } from 'sequelize';
|
|||
* Security service layer.
|
||||
*/
|
||||
export class SecService extends GBService {
|
||||
|
||||
public async ensureUser (
|
||||
instanceId: number,
|
||||
userSystemId: string,
|
||||
|
@ -167,24 +166,24 @@ export class SecService extends GBService {
|
|||
return user.agentMode === 'self';
|
||||
}
|
||||
|
||||
public async assignHumanAgent(min: GBMinInstance, userSystemId: string, agentSystemId: string = null): Promise<string> {
|
||||
|
||||
public async assignHumanAgent (
|
||||
min: GBMinInstance,
|
||||
userSystemId: string,
|
||||
agentSystemId: string = null
|
||||
): Promise<string> {
|
||||
if (!agentSystemId) {
|
||||
let list = min.core.getParam<string>(
|
||||
min.instance,
|
||||
'Transfer To',
|
||||
process.env.TRANSFER_TO
|
||||
);
|
||||
let list = min.core.getParam<string>(min.instance, 'Transfer To', process.env.TRANSFER_TO);
|
||||
|
||||
if (list) {
|
||||
list = list.split(';')
|
||||
list = list.split(';');
|
||||
}
|
||||
|
||||
await CollectionUtil.asyncForEach(list, async item => {
|
||||
if (
|
||||
item !== undefined &&
|
||||
agentSystemId === undefined &&
|
||||
item !== userSystemId && !await this.isAgentSystemId(item)
|
||||
item !== userSystemId &&
|
||||
!(await this.isAgentSystemId(item))
|
||||
) {
|
||||
// TODO: Optimize loop.
|
||||
agentSystemId = item;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
export const Messages = {
|
||||
'en-US': {
|
||||
whats_name: 'What\'s your name?',
|
||||
whats_mobile: 'What\'s your mobile number including country code (e.g. +1 222 9998888)?',
|
||||
whats_name: "What's your name?",
|
||||
whats_mobile: "What's your mobile number including country code (e.g. +1 222 9998888)?",
|
||||
confirm_mobile: 'Please type the code just sent to your mobile.',
|
||||
whats_email: 'What\'s your E-mail address?',
|
||||
whats_email: "What's your E-mail address?",
|
||||
validation_enter_name: 'Please enter your full name.',
|
||||
validation_enter_valid_mobile: 'Please enter a valid mobile number.',
|
||||
validation_enter_valid_email: 'Please enter a valid e-mail.'
|
||||
|
@ -13,7 +13,8 @@ export const Messages = {
|
|||
whats_email: 'Qual o seu e-mail?',
|
||||
whats_mobile: 'Qual o seu celular?',
|
||||
confirm_mobile: 'Por favor, digite o código enviado para seu celular.',
|
||||
confirm_mobile_again: 'Esse não me parece ser um código numérico válido. Por favor, digite novamente o código enviado para seu celular.',
|
||||
confirm_mobile_again:
|
||||
'Esse não me parece ser um código numérico válido. Por favor, digite novamente o código enviado para seu celular.',
|
||||
validation_enter_valid_email: 'Por favor, digite um e-mail válido no formato nome@domínio.com.br.',
|
||||
validation_enter_name: 'Por favor, digite seu nome completo',
|
||||
validation_enter_valid_mobile: 'Por favor, insira um número de celular válido (ex.: +55 21 98888-7766).'
|
||||
|
|
|
@ -65,5 +65,4 @@ export class GBSharePointPackage implements IGBPackage {
|
|||
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,12 +36,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Service facade for SharePoint Online.
|
||||
*/
|
||||
export class GBSharePointService {
|
||||
|
||||
|
||||
}
|
||||
export class GBSharePointService {}
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
export const Messages = {
|
||||
'en-US': {
|
||||
|
||||
},
|
||||
'pt-BR': {
|
||||
|
||||
}
|
||||
'en-US': {},
|
||||
'pt-BR': {}
|
||||
};
|
||||
|
|
|
@ -45,9 +45,7 @@ import { Sequelize } from 'sequelize-typescript';
|
|||
export class GBTeamsPackage implements IGBPackage {
|
||||
public sysPackages: IGBPackage[];
|
||||
|
||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
||||
|
||||
}
|
||||
public async loadBot (min: GBMinInstance): Promise<void> {}
|
||||
|
||||
public async getDialogs (min: GBMinInstance) {
|
||||
GBLog.verbose(`getDialogs called.`);
|
||||
|
@ -67,5 +65,4 @@ export class GBTeamsPackage implements IGBPackage {
|
|||
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,13 +38,11 @@ import AdmZip from 'adm-zip';
|
|||
* Support for Whatsapp.
|
||||
*/
|
||||
export class TeamsService extends GBService {
|
||||
|
||||
public async getAppFile(manifest)
|
||||
{
|
||||
public async getAppFile (manifest) {
|
||||
var zip = new AdmZip();
|
||||
zip.addFile("manifest.json", Buffer.from(manifest, "utf8"), "Built with General Bots™.");
|
||||
zip.addLocalFile("teams-color.png", null, "color.png");
|
||||
zip.addLocalFile("teams-outline.png", null, "outline.png");
|
||||
zip.addFile('manifest.json', Buffer.from(manifest, 'utf8'), 'Built with General Bots™.');
|
||||
zip.addLocalFile('teams-color.png', null, 'color.png');
|
||||
zip.addLocalFile('teams-outline.png', null, 'outline.png');
|
||||
return zip.toBuffer();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
export const Messages = {
|
||||
'en-US': {
|
||||
|
||||
},
|
||||
'pt-BR': {
|
||||
|
||||
}
|
||||
'en-US': {},
|
||||
'pt-BR': {}
|
||||
};
|
||||
|
|
|
@ -46,9 +46,7 @@ import { WhatsappDirectLine } from './services/WhatsappDirectLine.js';
|
|||
export class GBWhatsappPackage implements IGBPackage {
|
||||
public sysPackages: IGBPackage[];
|
||||
|
||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
||||
|
||||
}
|
||||
public async loadBot (min: GBMinInstance): Promise<void> {}
|
||||
|
||||
public async getDialogs (min: GBMinInstance) {
|
||||
GBLog.verbose(`getDialogs called.`);
|
||||
|
@ -68,5 +66,4 @@ export class GBWhatsappPackage implements IGBPackage {
|
|||
public async onExchangeData (min: GBMinInstance, kind: string, data: any) {
|
||||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ import express from 'express';
|
|||
* Support for Whatsapp.
|
||||
*/
|
||||
export class WhatsappDirectLine extends GBService {
|
||||
|
||||
public static conversationIds = {};
|
||||
public static mobiles = {};
|
||||
public static phones = {};
|
||||
|
@ -96,8 +95,12 @@ export class WhatsappDirectLine extends GBService {
|
|||
this.whatsappServiceKey = whatsappServiceKey;
|
||||
this.whatsappServiceNumber = whatsappServiceNumber;
|
||||
this.whatsappServiceUrl = whatsappServiceUrl;
|
||||
this.provider = whatsappServiceKey === "internal" ?
|
||||
'GeneralBots' : whatsappServiceNumber.indexOf(';') > -1 ? 'maytapi' : 'chatapi';
|
||||
this.provider =
|
||||
whatsappServiceKey === 'internal'
|
||||
? 'GeneralBots'
|
||||
: whatsappServiceNumber.indexOf(';') > -1
|
||||
? 'maytapi'
|
||||
: 'chatapi';
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
|
@ -108,10 +111,9 @@ export class WhatsappDirectLine extends GBService {
|
|||
}
|
||||
|
||||
public async setup (setUrl) {
|
||||
|
||||
this.directLineClient =
|
||||
new Swagger({
|
||||
spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')), usePromise: true
|
||||
this.directLineClient = new Swagger({
|
||||
spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')),
|
||||
usePromise: true
|
||||
});
|
||||
const client = await this.directLineClient;
|
||||
|
||||
|
@ -123,25 +125,21 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
switch (this.provider) {
|
||||
case 'GeneralBots':
|
||||
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
|
||||
// TODO: REMOVE THIS.
|
||||
if (minBoot.botId !== this.botId) {
|
||||
|
||||
this.customClient = minBoot.whatsAppDirectLine.customClient;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
} else {
|
||||
// Initialize the browser using a local profile for each bot.
|
||||
|
||||
const gbaiName = `${this.min.botId}.gbai`;
|
||||
const localName = Path.join('work', gbaiName, 'profile');
|
||||
|
||||
const createClient = async (browserWSEndpoint) => {
|
||||
const createClient = async browserWSEndpoint => {
|
||||
let puppeteer: any = {
|
||||
headless: false, args: [
|
||||
headless: false,
|
||||
args: [
|
||||
'--no-sandbox',
|
||||
'--disable-setuid-sandbox',
|
||||
'--disable-dev-shm-usage',
|
||||
|
@ -152,27 +150,31 @@ export class WhatsappDirectLine extends GBService {
|
|||
'--disable-gpu',
|
||||
'--disable-infobars',
|
||||
'--disable-features=site-per-process',
|
||||
`--user-data-dir=${localName}`]
|
||||
`--user-data-dir=${localName}`
|
||||
]
|
||||
};
|
||||
if (browserWSEndpoint) {
|
||||
puppeteer = { browserWSEndpoint: browserWSEndpoint };
|
||||
}
|
||||
|
||||
const client = this.customClient = new wpp.Client({
|
||||
const client = (this.customClient = new wpp.Client({
|
||||
authStrategy: new wpp.LocalAuth({
|
||||
clientId: this.min.botId,
|
||||
dataPath: localName
|
||||
}),
|
||||
puppeteer: puppeteer
|
||||
});
|
||||
}));
|
||||
|
||||
|
||||
client.on('message', (async message => {
|
||||
client.on(
|
||||
'message',
|
||||
(async message => {
|
||||
await this.WhatsAppCallback(message, null);
|
||||
}).bind(this));
|
||||
|
||||
client.on('qr', (async (qr) => {
|
||||
}).bind(this)
|
||||
);
|
||||
|
||||
client.on(
|
||||
'qr',
|
||||
(async qr => {
|
||||
const adminNumber = this.min.core.getParam(this.min.instance, 'Bot Admin Number', null);
|
||||
const adminEmail = this.min.core.getParam(this.min.instance, 'Bot Admin E-mail', null);
|
||||
|
||||
|
@ -197,8 +199,8 @@ export class WhatsappDirectLine extends GBService {
|
|||
// );
|
||||
// GBServer.globals.minBoot.whatsAppDirectLine.sendFileToDevice(adminNumber, url, Path.basename(localName), msg);
|
||||
// s.sendEmail(adminEmail, `Check your WhatsApp for bot ${this.botId}`, msg);
|
||||
|
||||
}).bind(this));
|
||||
}).bind(this)
|
||||
);
|
||||
|
||||
client.on('authenticated', async () => {
|
||||
this.browserWSEndpoint = client.pupBrowser.wsEndpoint();
|
||||
|
@ -206,11 +208,13 @@ export class WhatsappDirectLine extends GBService {
|
|||
});
|
||||
|
||||
client.on('ready', async () => {
|
||||
|
||||
client.pupBrowser.on('disconnected', (async () => {
|
||||
client.pupBrowser.on(
|
||||
'disconnected',
|
||||
(async () => {
|
||||
GBLog.info(`Browser terminated. Restarting ${this.min.botId} WhatsApp native provider.`);
|
||||
await (createClient.bind(this))(null);
|
||||
}).bind(this));
|
||||
await createClient.bind(this)(null);
|
||||
}).bind(this)
|
||||
);
|
||||
|
||||
GBLog.verbose(`GBWhatsApp: Emptying chat list for ${this.botId}...`);
|
||||
|
||||
|
@ -218,7 +222,6 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
const chats = await client.getChats();
|
||||
await CollectionUtil.asyncForEach(chats, async chat => {
|
||||
|
||||
const sleep = ms => {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, ms);
|
||||
|
@ -228,24 +231,21 @@ export class WhatsappDirectLine extends GBService {
|
|||
await sleep(wait);
|
||||
if (chat.isGroup) {
|
||||
await chat.clearMessages();
|
||||
}
|
||||
else if (!chat.pinned) {
|
||||
} else if (!chat.pinned) {
|
||||
await chat.delete();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
client.initialize();
|
||||
};
|
||||
await (createClient.bind(this))(this.browserWSEndpoint);
|
||||
await createClient.bind(this)(this.browserWSEndpoint);
|
||||
|
||||
setUrl = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'chatapi':
|
||||
|
||||
options = {
|
||||
method: 'POST',
|
||||
url: urlJoin(this.whatsappServiceUrl, 'webhook'),
|
||||
|
@ -262,9 +262,8 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
break;
|
||||
case 'maytapi':
|
||||
|
||||
let phoneId = this.whatsappServiceNumber.split(';')[0];
|
||||
let productId = this.whatsappServiceNumber.split(';')[1]
|
||||
let productId = this.whatsappServiceNumber.split(';')[1];
|
||||
let url = `${this.INSTANCE_URL}/${productId}/${phoneId}/config`;
|
||||
WhatsappDirectLine.phones[phoneId] = this.botId;
|
||||
|
||||
|
@ -273,19 +272,18 @@ export class WhatsappDirectLine extends GBService {
|
|||
method: 'POST',
|
||||
body: {
|
||||
webhook: `${GBServer.globals.publicAddress}/webhooks/whatsapp/${this.botId}`,
|
||||
"ack_delivery": false
|
||||
ack_delivery: false
|
||||
},
|
||||
headers: {
|
||||
'x-maytapi-key': this.whatsappServiceKey,
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
json: true,
|
||||
json: true
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
if (setUrl && options && this.whatsappServiceUrl) {
|
||||
|
||||
GBServer.globals.server.use(`/audios`, express.static('work'));
|
||||
|
||||
if (options) {
|
||||
|
@ -321,16 +319,14 @@ export class WhatsappDirectLine extends GBService {
|
|||
}
|
||||
|
||||
public static providerFromRequest (req) {
|
||||
return req.body.messages ? 'chatapi' :
|
||||
req.body.message ? 'maytapi' : 'GeneralBots';
|
||||
return req.body.messages ? 'chatapi' : req.body.message ? 'maytapi' : 'GeneralBots';
|
||||
}
|
||||
|
||||
public async received (req, res) {
|
||||
|
||||
const provider = WhatsappDirectLine.providerFromRequest(req);
|
||||
|
||||
let message, from, fromName, text;
|
||||
let group = "";
|
||||
let group = '';
|
||||
let answerText = null;
|
||||
let attachments = null;
|
||||
|
||||
|
@ -338,15 +334,13 @@ export class WhatsappDirectLine extends GBService {
|
|||
case 'GeneralBots':
|
||||
message = req;
|
||||
text = message.body;
|
||||
from = message.from.endsWith('@g.us') ?
|
||||
message.author.split('@')[0] : message.from.split('@')[0];
|
||||
from = message.from.endsWith('@g.us') ? message.author.split('@')[0] : message.from.split('@')[0];
|
||||
fromName = message._data.notifyName;
|
||||
|
||||
if (message.hasMedia) {
|
||||
const base64Image = await message.downloadMedia();
|
||||
attachments = [];
|
||||
attachments.push(
|
||||
{
|
||||
attachments.push({
|
||||
name: 'uploaded.png',
|
||||
contentType: base64Image.mimetype,
|
||||
contentUrl: `data:${base64Image.mimetype};base64,${base64Image.data}`
|
||||
|
@ -363,8 +357,7 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
if (message.type !== 'chat') {
|
||||
attachments = [];
|
||||
attachments.push(
|
||||
{
|
||||
attachments.push({
|
||||
name: 'uploaded',
|
||||
contentType: 'application/octet-stream',
|
||||
contentUrl: message.body
|
||||
|
@ -399,18 +392,16 @@ export class WhatsappDirectLine extends GBService {
|
|||
let botGroupID = WhatsappDirectLine.botGroups[this.min.botId];
|
||||
let botShortcuts = this.min.core.getParam<string>(this.min.instance, 'WhatsApp Group Shortcuts', null);
|
||||
if (!botShortcuts) {
|
||||
botShortcuts = new Array()
|
||||
}
|
||||
else {
|
||||
botShortcuts = new Array();
|
||||
} else {
|
||||
botShortcuts = botShortcuts.split(' ');
|
||||
}
|
||||
|
||||
if (provider === "chatapi") {
|
||||
if (provider === 'chatapi') {
|
||||
if (message.chatName.charAt(0) !== '+') {
|
||||
group = message.chatName;
|
||||
}
|
||||
}
|
||||
else if (provider === "GeneralBots") {
|
||||
} else if (provider === 'GeneralBots') {
|
||||
if (message.from.endsWith('@g.us')) {
|
||||
group = message.from;
|
||||
}
|
||||
|
@ -422,7 +413,6 @@ export class WhatsappDirectLine extends GBService {
|
|||
// Bot name must be specified on config.
|
||||
|
||||
if (botGroupID === group) {
|
||||
|
||||
// Shortcut has been mentioned?
|
||||
|
||||
let found = false;
|
||||
|
@ -434,21 +424,18 @@ export class WhatsappDirectLine extends GBService {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
// Verify if it is a group cache answer.
|
||||
|
||||
const questions = this.min['groupCache'];
|
||||
if (questions && questions.length > 0) {
|
||||
questions.forEach(q => {
|
||||
if (q.content === e1 && !found) {
|
||||
const answer = this.min.kbService['getAnswerById'](this.min.instance.instanceId,
|
||||
q.answerId);
|
||||
const answer = this.min.kbService['getAnswerById'](this.min.instance.instanceId, q.answerId);
|
||||
answerText = answer.content;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Ignore group messages without the mention to Bot.
|
||||
|
||||
let smsServiceNumber = this.min.core.getParam<string>(this.min.instance, 'whatsappServiceNumber', null);
|
||||
|
@ -458,10 +445,8 @@ export class WhatsappDirectLine extends GBService {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const botId = this.min.instance.botId;
|
||||
|
@ -472,8 +457,7 @@ export class WhatsappDirectLine extends GBService {
|
|||
await state.promise(null, text);
|
||||
|
||||
return; // Exit here.
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// Processes .gbapp message interception.
|
||||
|
||||
|
@ -482,8 +466,7 @@ export class WhatsappDirectLine extends GBService {
|
|||
});
|
||||
|
||||
const sec = new SecService();
|
||||
const user = await sec.ensureUser(this.min.instance.instanceId, from,
|
||||
fromName, '', 'whatsapp', fromName, null);
|
||||
const user = await sec.ensureUser(this.min.instance.instanceId, from, fromName, '', 'whatsapp', fromName, null);
|
||||
const locale = user.locale ? user.locale : 'pt';
|
||||
|
||||
if (answerText) {
|
||||
|
@ -493,7 +476,6 @@ export class WhatsappDirectLine extends GBService {
|
|||
}
|
||||
|
||||
if (message.type === 'ptt') {
|
||||
|
||||
if (process.env.AUDIO_DISABLED !== 'true') {
|
||||
const options = {
|
||||
url: provider ? message.body : message.text,
|
||||
|
@ -506,11 +488,11 @@ export class WhatsappDirectLine extends GBService {
|
|||
text = await GBConversationalService.getTextFromAudioBuffer(
|
||||
this.min.instance.speechKey,
|
||||
this.min.instance.cloudLocation,
|
||||
buf, locale
|
||||
buf,
|
||||
locale
|
||||
);
|
||||
} else {
|
||||
await this.sendToDevice(user.userSystemId,
|
||||
`No momento estou apenas conseguindo ler mensagens de texto.`, null);
|
||||
await this.sendToDevice(user.userSystemId, `No momento estou apenas conseguindo ler mensagens de texto.`, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,14 +503,11 @@ export class WhatsappDirectLine extends GBService {
|
|||
// Check if this message is from a Human Agent itself.
|
||||
|
||||
if (user.agentMode === 'self') {
|
||||
|
||||
// Check if there is someone being handled by this Human Agent.
|
||||
|
||||
const manualUser = await sec.getUserFromAgentSystemId(from);
|
||||
if (manualUser === null) {
|
||||
|
||||
await sec.updateHumanAgent(from, this.min.instance.instanceId, null);
|
||||
|
||||
} else {
|
||||
const agent = await sec.getUserFromSystemId(user.agentSystemId);
|
||||
|
||||
|
@ -538,23 +517,38 @@ export class WhatsappDirectLine extends GBService {
|
|||
const message = await this.min.kbService.getAnswerTextByMediaName(this.min.instance.instanceId, filename);
|
||||
|
||||
if (message === null) {
|
||||
await this.sendToDeviceEx(user.userSystemId, `File ${filename} not found in any .gbkb published. Check the name or publish again the associated .gbkb.`,
|
||||
locale, null);
|
||||
await this.sendToDeviceEx(
|
||||
user.userSystemId,
|
||||
`File ${filename} not found in any .gbkb published. Check the name or publish again the associated .gbkb.`,
|
||||
locale,
|
||||
null
|
||||
);
|
||||
} else {
|
||||
await this.min.conversationalService.sendMarkdownToMobile(this.min, null, user.userSystemId, message);
|
||||
}
|
||||
} else if (text === '/qt') {
|
||||
// TODO: Transfers only in pt-br for now.
|
||||
await this.sendToDeviceEx(manualUser.userSystemId,
|
||||
Messages[this.locale].notify_end_transfer(this.min.instance.botId), locale, null);
|
||||
|
||||
if (user.agentSystemId.charAt(2) === ":") { // Agent is from Teams.
|
||||
await this.min.conversationalService['sendOnConversation'](this.min, agent, Messages[this.locale].notify_end_transfer(this.min.instance.botId));
|
||||
}
|
||||
else {
|
||||
await this.sendToDeviceEx(user.agentSystemId,
|
||||
Messages[this.locale].notify_end_transfer(this.min.instance.botId), locale, null);
|
||||
await this.sendToDeviceEx(
|
||||
manualUser.userSystemId,
|
||||
Messages[this.locale].notify_end_transfer(this.min.instance.botId),
|
||||
locale,
|
||||
null
|
||||
);
|
||||
|
||||
if (user.agentSystemId.charAt(2) === ':') {
|
||||
// Agent is from Teams.
|
||||
await this.min.conversationalService['sendOnConversation'](
|
||||
this.min,
|
||||
agent,
|
||||
Messages[this.locale].notify_end_transfer(this.min.instance.botId)
|
||||
);
|
||||
} else {
|
||||
await this.sendToDeviceEx(
|
||||
user.agentSystemId,
|
||||
Messages[this.locale].notify_end_transfer(this.min.instance.botId),
|
||||
locale,
|
||||
null
|
||||
);
|
||||
}
|
||||
await sec.updateHumanAgent(manualUser.userSystemId, this.min.instance.instanceId, null);
|
||||
await sec.updateHumanAgent(user.agentSystemId, this.min.instance.instanceId, null);
|
||||
|
@ -563,48 +557,50 @@ export class WhatsappDirectLine extends GBService {
|
|||
await this.sendToDeviceEx(manualUser.userSystemId, `AGENTE: *${text}*`, locale, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if (user.agentMode === 'human') {
|
||||
|
||||
const agent = await sec.getUserFromSystemId(user.agentSystemId);
|
||||
if (text === '/t') {
|
||||
await this.sendToDeviceEx(user.userSystemId, `Você já está sendo atendido por ${agent.userSystemId}.`, locale, null);
|
||||
await this.sendToDeviceEx(
|
||||
user.userSystemId,
|
||||
`Você já está sendo atendido por ${agent.userSystemId}.`,
|
||||
locale,
|
||||
null
|
||||
);
|
||||
} else if (text === '/qt' || text === 'Sair' || text === 'Fechar') {
|
||||
// TODO: Transfers only in pt-br for now.
|
||||
await this.endTransfer(from, locale, user, agent, sec);
|
||||
} else {
|
||||
GBLog.info(`USER (${from}) TO AGENT ${agent.userSystemId}: ${text}`);
|
||||
|
||||
if (user.agentSystemId.charAt(2) === ":" || agent.userSystemId.indexOf("@") > -1) { // Agent is from Teams or Google Chat.
|
||||
if (user.agentSystemId.charAt(2) === ':' || agent.userSystemId.indexOf('@') > -1) {
|
||||
// Agent is from Teams or Google Chat.
|
||||
await this.min.conversationalService['sendOnConversation'](this.min, agent, text);
|
||||
} else {
|
||||
await this.sendToDeviceEx(
|
||||
user.agentSystemId,
|
||||
`Bot: ${this.min.instance.botId}\n${from}: ${text}`,
|
||||
locale,
|
||||
null
|
||||
);
|
||||
}
|
||||
else {
|
||||
await this.sendToDeviceEx(user.agentSystemId, `Bot: ${this.min.instance.botId}\n${from}: ${text}`, locale, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if (user.agentMode === 'bot' || user.agentMode === null || user.agentMode === undefined) {
|
||||
|
||||
if (WhatsappDirectLine.conversationIds[botId + from + group] === undefined) {
|
||||
GBLog.info(`GBWhatsapp: Starting new conversation on Bot.`);
|
||||
const response = await client.Conversations.Conversations_StartConversation();
|
||||
const generatedConversationId = response.obj.conversationId;
|
||||
|
||||
WhatsappDirectLine.conversationIds[botId + from + group] = generatedConversationId;
|
||||
if (provider === "GeneralBots") {
|
||||
if (provider === 'GeneralBots') {
|
||||
WhatsappDirectLine.chatIds[generatedConversationId] = message.from;
|
||||
}
|
||||
WhatsappDirectLine.mobiles[generatedConversationId] = from;
|
||||
WhatsappDirectLine.usernames[from] = fromName;
|
||||
WhatsappDirectLine.chatIds[generatedConversationId] = message.chatId;
|
||||
|
||||
|
||||
this.pollMessages(client, generatedConversationId, from, fromName);
|
||||
this.inputMessage(client, generatedConversationId, text, from, fromName, group, attachments);
|
||||
} else {
|
||||
|
||||
this.inputMessage(client, conversationId, text, from, fromName, group, attachments);
|
||||
}
|
||||
} else {
|
||||
|
@ -617,14 +613,22 @@ export class WhatsappDirectLine extends GBService {
|
|||
}
|
||||
|
||||
private async endTransfer (id: any, locale: string, user: GuaribasUser, agent: GuaribasUser, sec: SecService) {
|
||||
await this.sendToDeviceEx(id,
|
||||
Messages[this.locale].notify_end_transfer(this.min.instance.botId), locale, null);
|
||||
await this.sendToDeviceEx(id, Messages[this.locale].notify_end_transfer(this.min.instance.botId), locale, null);
|
||||
|
||||
if (user.agentSystemId.charAt(2) === ":") { // Agent is from Teams.
|
||||
await this.min.conversationalService['sendOnConversation'](this.min, agent, Messages[this.locale].notify_end_transfer(this.min.instance.botId));
|
||||
}
|
||||
else {
|
||||
await this.sendToDeviceEx(user.agentSystemId, Messages[this.locale].notify_end_transfer(this.min.instance.botId), locale, null);
|
||||
if (user.agentSystemId.charAt(2) === ':') {
|
||||
// Agent is from Teams.
|
||||
await this.min.conversationalService['sendOnConversation'](
|
||||
this.min,
|
||||
agent,
|
||||
Messages[this.locale].notify_end_transfer(this.min.instance.botId)
|
||||
);
|
||||
} else {
|
||||
await this.sendToDeviceEx(
|
||||
user.agentSystemId,
|
||||
Messages[this.locale].notify_end_transfer(this.min.instance.botId),
|
||||
locale,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
await sec.updateHumanAgent(id, this.min.instance.instanceId, null);
|
||||
|
@ -663,8 +667,11 @@ export class WhatsappDirectLine extends GBService {
|
|||
watermark = response.obj.watermark;
|
||||
await this.printMessages(response.obj.activities, conversationId, from, fromName);
|
||||
} catch (err) {
|
||||
GBLog.error(`Error calling printMessages on Whatsapp channel ${err.data === undefined ?
|
||||
err : err.data} ${err.errObj ? err.errObj.message : ''}`);
|
||||
GBLog.error(
|
||||
`Error calling printMessages on Whatsapp channel ${err.data === undefined ? err : err.data} ${
|
||||
err.errObj ? err.errObj.message : ''
|
||||
}`
|
||||
);
|
||||
}
|
||||
};
|
||||
setInterval(worker, this.pollInterval);
|
||||
|
@ -719,7 +726,6 @@ export class WhatsappDirectLine extends GBService {
|
|||
}
|
||||
|
||||
public async sendFileToDevice (to, url, filename, caption, chatId) {
|
||||
|
||||
let options;
|
||||
switch (this.provider) {
|
||||
case 'GeneralBots':
|
||||
|
@ -727,8 +733,7 @@ export class WhatsappDirectLine extends GBService {
|
|||
if (to.indexOf('@') == -1) {
|
||||
if (to.length == 18) {
|
||||
to = to + '@g.us';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
to = to + '@c.us';
|
||||
}
|
||||
}
|
||||
|
@ -737,7 +742,6 @@ export class WhatsappDirectLine extends GBService {
|
|||
break;
|
||||
|
||||
case 'chatapi':
|
||||
|
||||
options = {
|
||||
method: 'POST',
|
||||
url: urlJoin(this.whatsappServiceUrl, 'sendFile'),
|
||||
|
@ -758,17 +762,16 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
break;
|
||||
case 'maytapi':
|
||||
|
||||
let contents = 0;
|
||||
let body = {
|
||||
to_number: to,
|
||||
type: "media",
|
||||
type: 'media',
|
||||
message: url,
|
||||
text: caption
|
||||
};
|
||||
|
||||
let phoneId = this.whatsappServiceNumber.split(';')[0];
|
||||
let productId = this.whatsappServiceNumber.split(';')[1]
|
||||
let productId = this.whatsappServiceNumber.split(';')[1];
|
||||
|
||||
options = {
|
||||
url: `${this.INSTANCE_URL}/${productId}/${phoneId}/sendMessage`,
|
||||
|
@ -777,8 +780,8 @@ export class WhatsappDirectLine extends GBService {
|
|||
body,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'x-maytapi-key': this.whatsappServiceKey,
|
||||
},
|
||||
'x-maytapi-key': this.whatsappServiceKey
|
||||
}
|
||||
};
|
||||
|
||||
break;
|
||||
|
@ -795,18 +798,15 @@ export class WhatsappDirectLine extends GBService {
|
|||
}
|
||||
|
||||
public async sendAudioToDevice (to, url, chatId) {
|
||||
|
||||
let options;
|
||||
switch (this.provider) {
|
||||
case 'GeneralBots':
|
||||
|
||||
const attachment = wpp.MessageMedia.fromUrl(url);
|
||||
await this.customClient.sendMessage(to, attachment);
|
||||
|
||||
break;
|
||||
|
||||
case 'chatapi':
|
||||
|
||||
options = {
|
||||
method: 'POST',
|
||||
url: urlJoin(this.whatsappServiceUrl, 'sendPTT'),
|
||||
|
@ -823,7 +823,6 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
break;
|
||||
case 'maytapi':
|
||||
|
||||
options = {}; // TODO: Code Maytapi.
|
||||
|
||||
break;
|
||||
|
@ -840,36 +839,29 @@ export class WhatsappDirectLine extends GBService {
|
|||
}
|
||||
|
||||
public async sendTextAsAudioToDevice (to, msg, chatId) {
|
||||
|
||||
const url = await GBConversationalService.getAudioBufferFromText(
|
||||
msg
|
||||
);
|
||||
const url = await GBConversationalService.getAudioBufferFromText(msg);
|
||||
|
||||
await this.sendFileToDevice(to, url, 'Audio', msg, chatId);
|
||||
}
|
||||
|
||||
public async sendToDevice (to: string, msg: string, conversationId) {
|
||||
|
||||
const cmd = '/audio ';
|
||||
|
||||
let chatId = WhatsappDirectLine.chatIds[conversationId];
|
||||
|
||||
if (typeof (msg) !== 'object' && msg.startsWith(cmd)) {
|
||||
if (typeof msg !== 'object' && msg.startsWith(cmd)) {
|
||||
msg = msg.substr(cmd.length);
|
||||
|
||||
return await this.sendTextAsAudioToDevice(to, msg, chatId);
|
||||
} else {
|
||||
|
||||
let options;
|
||||
|
||||
switch (this.provider) {
|
||||
case 'GeneralBots':
|
||||
|
||||
if (to.indexOf('@') == -1) {
|
||||
if (to.length == 18) {
|
||||
to = to + '@g.us';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
to = to + '@c.us';
|
||||
}
|
||||
}
|
||||
|
@ -878,8 +870,6 @@ export class WhatsappDirectLine extends GBService {
|
|||
break;
|
||||
|
||||
case 'chatapi':
|
||||
|
||||
|
||||
options = {
|
||||
method: 'POST',
|
||||
url: urlJoin(this.whatsappServiceUrl, 'message'),
|
||||
|
@ -896,7 +886,7 @@ export class WhatsappDirectLine extends GBService {
|
|||
break;
|
||||
case 'maytapi':
|
||||
let phoneId = this.whatsappServiceNumber.split(';')[0];
|
||||
let productId = this.whatsappServiceNumber.split(';')[1]
|
||||
let productId = this.whatsappServiceNumber.split(';')[1];
|
||||
let url = `${this.INSTANCE_URL}/${productId}/${phoneId}/sendMessage`;
|
||||
|
||||
options = {
|
||||
|
@ -906,8 +896,8 @@ export class WhatsappDirectLine extends GBService {
|
|||
body: { type: 'text', message: msg, to_number: to },
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'x-maytapi-key': this.whatsappServiceKey,
|
||||
},
|
||||
'x-maytapi-key': this.whatsappServiceKey
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
@ -916,8 +906,7 @@ export class WhatsappDirectLine extends GBService {
|
|||
try {
|
||||
GBLog.info(`Message [${msg}] is being sent to ${to}...`);
|
||||
await request.post(options);
|
||||
}
|
||||
catch (error) {
|
||||
} catch (error) {
|
||||
GBLog.error(`Error sending message to Whatsapp provider ${error.message}`);
|
||||
|
||||
// TODO: Handle Error: socket hang up and retry.
|
||||
|
@ -927,18 +916,12 @@ export class WhatsappDirectLine extends GBService {
|
|||
}
|
||||
|
||||
public async sendToDeviceEx (to, text, locale, conversationId) {
|
||||
text = await this.min.conversationalService.translate(
|
||||
this.min,
|
||||
text,
|
||||
locale
|
||||
);
|
||||
text = await this.min.conversationalService.translate(this.min, text, locale);
|
||||
await this.sendToDevice(to, text, conversationId);
|
||||
|
||||
}
|
||||
|
||||
private async WhatsAppCallback (req, res) {
|
||||
try {
|
||||
|
||||
if (req.body && req.body.webhook) {
|
||||
res.status(200);
|
||||
res.end();
|
||||
|
@ -952,14 +935,11 @@ export class WhatsappDirectLine extends GBService {
|
|||
let botId;
|
||||
let text;
|
||||
|
||||
|
||||
switch (provider) {
|
||||
case "GeneralBots":
|
||||
|
||||
case 'GeneralBots':
|
||||
// Ignore E2E messages used during initialization.
|
||||
|
||||
if (req.type && req.type === 'e2e_notification') {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -967,11 +947,9 @@ export class WhatsappDirectLine extends GBService {
|
|||
senderName = req._data.notifyName;
|
||||
text = req.body;
|
||||
|
||||
|
||||
break;
|
||||
|
||||
case "chatapi":
|
||||
|
||||
case 'chatapi':
|
||||
if (req.body.ack) {
|
||||
res.status(200);
|
||||
res.end();
|
||||
|
@ -991,8 +969,7 @@ export class WhatsappDirectLine extends GBService {
|
|||
botId = GBConfigService.get('BOT_ID');
|
||||
}
|
||||
break;
|
||||
case "maytapi":
|
||||
|
||||
case 'maytapi':
|
||||
if (req.body.type !== 'message') {
|
||||
res.status(200);
|
||||
res.end();
|
||||
|
@ -1017,8 +994,7 @@ export class WhatsappDirectLine extends GBService {
|
|||
let user = await sec.getUserFromSystemId(id);
|
||||
GBLog.info(`A WhatsApp mobile requested instance for: ${botId}.`);
|
||||
|
||||
let urlMin: any = GBServer.globals.minInstances.filter
|
||||
(p => p.instance.botId === botId)[0];
|
||||
let urlMin: any = GBServer.globals.minInstances.filter(p => p.instance.botId === botId)[0];
|
||||
|
||||
const botNumber = urlMin ? urlMin.core.getParam(urlMin.instance, 'Bot Number', null) : null;
|
||||
let activeMin;
|
||||
|
@ -1028,17 +1004,14 @@ export class WhatsappDirectLine extends GBService {
|
|||
text = text.replace(/\@\d+ /gi, '');
|
||||
|
||||
let group;
|
||||
if (provider === "chatapi") {
|
||||
|
||||
if (provider === 'chatapi') {
|
||||
// Ensures that the bot group is the active bot for the user (like switching).
|
||||
|
||||
const message = req.body.messages[0];
|
||||
if (message.chatName.charAt(0) !== '+') {
|
||||
group = message.chatName;
|
||||
}
|
||||
}
|
||||
else if (provider === "GeneralBots") {
|
||||
|
||||
} else if (provider === 'GeneralBots') {
|
||||
// Ensures that the bot group is the active bot for the user (like switching).
|
||||
|
||||
const message = req;
|
||||
|
@ -1053,13 +1026,11 @@ export class WhatsappDirectLine extends GBService {
|
|||
return Object.keys(object).find(key => object[key] === value);
|
||||
}
|
||||
const botId = getKeyByValue(WhatsappDirectLine.botGroups, group);
|
||||
if (botId && user.instanceId !== this.min.instance.instanceId || !user) {
|
||||
if ((botId && user.instanceId !== this.min.instance.instanceId) || !user) {
|
||||
user = await sec.ensureUser(this.min.instance.instanceId, id, senderName, '', 'whatsApp', senderName, null);
|
||||
|
||||
}
|
||||
if (botId) {
|
||||
activeMin = GBServer.globals.minInstances.filter
|
||||
(p => p.instance.botId === botId)[0];
|
||||
activeMin = GBServer.globals.minInstances.filter(p => p.instance.botId === botId)[0];
|
||||
await (activeMin as any).whatsAppDirectLine.received(req, res);
|
||||
return; // EXIT HERE.
|
||||
}
|
||||
|
@ -1068,7 +1039,6 @@ export class WhatsappDirectLine extends GBService {
|
|||
// Detects if the welcome message is enabled.
|
||||
|
||||
if (process.env.WHATSAPP_WELCOME_DISABLED !== 'true') {
|
||||
|
||||
// Tries to find if user wants to switch bots.
|
||||
|
||||
let toSwitchMin = GBServer.globals.minInstances.filter(
|
||||
|
@ -1082,8 +1052,7 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
// If bot has a fixed Find active bot instance.
|
||||
|
||||
activeMin = botNumber ? urlMin :
|
||||
toSwitchMin ? toSwitchMin : GBServer.globals.minBoot;
|
||||
activeMin = botNumber ? urlMin : toSwitchMin ? toSwitchMin : GBServer.globals.minBoot;
|
||||
|
||||
// If it is the first time for the user, tries to auto-execute
|
||||
// start dialog if any is specified in Config.xlsx.
|
||||
|
@ -1091,19 +1060,17 @@ export class WhatsappDirectLine extends GBService {
|
|||
if (user === null || user.hearOnDialog) {
|
||||
user = await sec.ensureUser(activeMin.instance.instanceId, id, senderName, '', 'whatsapp', senderName, null);
|
||||
|
||||
const startDialog = user.hearOnDialog ?
|
||||
user.hearOnDialog :
|
||||
activeMin.core.getParam(activeMin.instance, 'Start Dialog', null);
|
||||
const startDialog = user.hearOnDialog
|
||||
? user.hearOnDialog
|
||||
: activeMin.core.getParam(activeMin.instance, 'Start Dialog', null);
|
||||
|
||||
if (startDialog) {
|
||||
GBLog.info(`Calling /start to Auto start ${startDialog} for ${activeMin.instance.instanceId}...`);
|
||||
if (provider === "chatapi") {
|
||||
if (provider === 'chatapi') {
|
||||
req.body.messages[0].body = `/start`;
|
||||
}
|
||||
else if (provider === "maytapi") {
|
||||
} else if (provider === 'maytapi') {
|
||||
req.body.message = `/start`;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
req.body = `/start`;
|
||||
}
|
||||
|
||||
|
@ -1115,19 +1082,19 @@ export class WhatsappDirectLine extends GBService {
|
|||
} else {
|
||||
await (activeMin as any).whatsAppDirectLine.sendToDevice(
|
||||
id,
|
||||
`Olá! Seja bem-vinda(o)!\nMe chamo ${activeMin.instance.title}. Como posso ajudar? Pode me falar que eu te ouço, me manda um aúdio.`
|
||||
, null);
|
||||
`Olá! Seja bem-vinda(o)!\nMe chamo ${
|
||||
activeMin.instance.title
|
||||
}. Como posso ajudar? Pode me falar que eu te ouço, me manda um aúdio.`,
|
||||
null
|
||||
);
|
||||
if (res) {
|
||||
res.end();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// User wants to switch bots.
|
||||
|
||||
if (toSwitchMin !== undefined) {
|
||||
|
||||
// So gets the new bot instance information and prepares to
|
||||
// auto start dialog if any is specified.
|
||||
|
||||
|
@ -1136,16 +1103,13 @@ export class WhatsappDirectLine extends GBService {
|
|||
await (activeMin as any).whatsAppDirectLine.resetConversationId(activeMin.botId, id, '');
|
||||
const startDialog = activeMin.core.getParam(activeMin.instance, 'Start Dialog', null);
|
||||
|
||||
|
||||
if (startDialog) {
|
||||
GBLog.info(`Calling /start for Auto start : ${startDialog} for ${activeMin.instance.botId}...`);
|
||||
if (provider === "chatapi") {
|
||||
if (provider === 'chatapi') {
|
||||
req.body.messages[0].body = `/start`;
|
||||
}
|
||||
else if (provider === "maytapi") {
|
||||
} else if (provider === 'maytapi') {
|
||||
req.body.message = `/start`;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
req.body = `/start`;
|
||||
}
|
||||
|
||||
|
@ -1160,14 +1124,15 @@ export class WhatsappDirectLine extends GBService {
|
|||
if (res) {
|
||||
res.end();
|
||||
}
|
||||
|
||||
} else {
|
||||
activeMin = GBServer.globals.minInstances.filter(p => p.instance.instanceId === user.instanceId)[0];
|
||||
if (activeMin === undefined) {
|
||||
activeMin = GBServer.globals.minBoot;
|
||||
await (activeMin as any).whatsAppDirectLine.sendToDevice(
|
||||
id,
|
||||
`O outro Bot que você estava falando(${user.instanceId}), não está mais disponível. Agora você está falando comigo, ${activeMin.instance.title}...`
|
||||
`O outro Bot que você estava falando(${
|
||||
user.instanceId
|
||||
}), não está mais disponível. Agora você está falando comigo, ${activeMin.instance.title}...`
|
||||
);
|
||||
}
|
||||
await (activeMin as any).whatsAppDirectLine.received(req, res);
|
||||
|
@ -1178,13 +1143,11 @@ export class WhatsappDirectLine extends GBService {
|
|||
p => p.instance.botId.toLowerCase() === botId.toLowerCase()
|
||||
)[0];
|
||||
|
||||
|
||||
// Just pass the message to the receiver.
|
||||
|
||||
await minInstance.whatsAppDirectLine.received(req, res);
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
GBLog.error(`Error on Whatsapp callback: ${error.data ? error.data : error} ${error.stack}`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
export const Messages = {
|
||||
'en-US': {
|
||||
notify_end_transfer: (botName) => `Now talking to ${botName} again.`
|
||||
notify_end_transfer: botName => `Now talking to ${botName} again.`
|
||||
},
|
||||
'pt-BR': {
|
||||
notify_end_transfer: (botName) => `Falando com o bot ${botName} novamente.`
|
||||
notify_end_transfer: botName => `Falando com o bot ${botName} novamente.`
|
||||
}
|
||||
};
|
||||
|
|
32
src/app.ts
32
src/app.ts
|
@ -83,15 +83,12 @@ export class GBServer {
|
|||
*/
|
||||
|
||||
public static run () {
|
||||
|
||||
|
||||
GBLog.info(`The Bot Server is in STARTING mode...`);
|
||||
GBServer.globals = new RootData();
|
||||
GBConfigService.init();
|
||||
const port = GBConfigService.getServerPort();
|
||||
|
||||
if (process.env.TEST_SHELL)
|
||||
{
|
||||
if (process.env.TEST_SHELL) {
|
||||
GBLog.info(`Running TEST_SHELL: ${process.env.TEST_SHELL}...`);
|
||||
try {
|
||||
child_process.execSync(process.env.TEST_SHELL);
|
||||
|
@ -113,7 +110,6 @@ export class GBServer {
|
|||
server.use(bodyParser.json());
|
||||
server.use(bodyParser.urlencoded({ extended: true }));
|
||||
|
||||
|
||||
// Creates working directory.
|
||||
|
||||
const workDir = Path.join(process.env.PWD, 'work');
|
||||
|
@ -123,9 +119,7 @@ export class GBServer {
|
|||
|
||||
const mainCallback = () => {
|
||||
(async () => {
|
||||
|
||||
try {
|
||||
|
||||
GBLog.info(`Now accepting connections on ${port}...`);
|
||||
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
|
||||
|
||||
|
@ -160,9 +154,11 @@ export class GBServer {
|
|||
await core.initStorage();
|
||||
} catch (error) {
|
||||
GBLog.verbose(`Error initializing storage: ${error}`);
|
||||
GBServer.globals.bootInstance =
|
||||
await core.createBootInstance(core, azureDeployer, GBServer.globals.publicAddress);
|
||||
|
||||
GBServer.globals.bootInstance = await core.createBootInstance(
|
||||
core,
|
||||
azureDeployer,
|
||||
GBServer.globals.publicAddress
|
||||
);
|
||||
}
|
||||
|
||||
core.ensureAdminIsSecured();
|
||||
|
@ -190,7 +186,6 @@ export class GBServer {
|
|||
);
|
||||
|
||||
if (instances.length === 0) {
|
||||
|
||||
const instance = await importer.importIfNotExistsBotPackage(
|
||||
GBConfigService.get('BOT_ID'),
|
||||
'boot.gbot',
|
||||
|
@ -215,15 +210,15 @@ export class GBServer {
|
|||
await minService.buildMin(instances);
|
||||
|
||||
if (process.env.ENABLE_WEBLOG) {
|
||||
var admins = {
|
||||
'admin': { password: process.env.ADMIN_PASS },
|
||||
const admins = {
|
||||
admin: { password: process.env.ADMIN_PASS }
|
||||
};
|
||||
|
||||
// ... some not authenticated middlewares
|
||||
|
||||
server.use(async (req, res, next) => {
|
||||
if (req.originalUrl.startsWith('/logs')) {
|
||||
var user = auth(req);
|
||||
const user = auth(req);
|
||||
if (!user || !admins[user.name] || admins[user.name].password !== user.pass) {
|
||||
res.set('WWW-Authenticate', 'Basic realm="example"');
|
||||
return res.status(401).send();
|
||||
|
@ -239,7 +234,6 @@ export class GBServer {
|
|||
winston.default(server, loggers[1]);
|
||||
}
|
||||
|
||||
|
||||
GBLog.info(`The Bot Server is in RUNNING mode...`);
|
||||
|
||||
// Opens Navigator.
|
||||
|
@ -252,22 +246,20 @@ export class GBServer {
|
|||
})();
|
||||
};
|
||||
if (process.env.CERTIFICATE_PFX) {
|
||||
let options = {
|
||||
const options = {
|
||||
passphrase: process.env.CERTIFICATE_PASSPHRASE,
|
||||
pfx: Fs.readFileSync(process.env.CERTIFICATE_PFX)
|
||||
};
|
||||
const httpsServer = https.createServer(options, server).listen(port, mainCallback);
|
||||
|
||||
if (process.env.CERTIFICATE2_PFX) {
|
||||
let options = {
|
||||
const options = {
|
||||
passphrase: process.env.CERTIFICATE2_PASSPHRASE,
|
||||
pfx: Fs.readFileSync(process.env.CERTIFICATE2_PFX)
|
||||
};
|
||||
httpsServer.addContext(process.env.CERTIFICATE2_DOMAIN, options);
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
server.listen(port, mainCallback);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue