fix(all): TODO items removed or moved to ALM.

This commit is contained in:
rodrigorodriguez 2023-01-01 14:24:53 -03:00
parent 7344a8e7dd
commit 7348c54894
5 changed files with 145 additions and 156 deletions

View file

@ -123,7 +123,7 @@ export class GBMinService {
/**
* Static initialization of minimal instance.
*/
constructor (
constructor(
core: IGBCoreService,
conversationalService: IGBConversationalService,
adminService: IGBAdminService,
@ -138,7 +138,7 @@ export class GBMinService {
/**
* Constructs a new minimal instance for each bot.
*/
public async buildMin (instances: IGBInstance[]) {
public async buildMin(instances: IGBInstance[]) {
// Servers default UI on root address '/' if web enabled.
if (process.env.DISABLE_WEB !== 'true') {
@ -184,7 +184,7 @@ export class GBMinService {
const MAX_IN_PROCESS = 20;
const results = new Array(promises.length);
async function doBlock (startIndex) {
async function doBlock(startIndex) {
// Shallow-copy a block of promises to work on
const currBlock = promises.slice(startIndex, startIndex + MAX_IN_PROCESS);
// Await the completion. If any fail, it will throw and that's good.
@ -233,7 +233,7 @@ export class GBMinService {
* Removes bot endpoint from web listeners and remove bot instance
* from list of global server bot instances.
*/
public async unmountBot (botId: string) {
public async unmountBot(botId: string) {
const url = `/api/messages/${botId}`;
removeRoute(GBServer.globals.server, url);
@ -248,7 +248,7 @@ export class GBMinService {
* serving bot endpoint in several URL like WhatsApp endpoint, .gbkb assets,
* installing all BASIC artifacts from .gbdialog and OAuth2.
*/
public async mountBot (instance: IGBInstance) {
public async mountBot(instance: IGBInstance) {
// Build bot adapter.
const { min, adapter, conversationState } = await this.buildBotAdapter(
@ -256,7 +256,7 @@ export class GBMinService {
GBServer.globals.sysPackages,
GBServer.globals.appPackages
);
// https://github.com/GeneralBots/BotServer/issues/286
// min['groupCache'] = await KBService.getGroupReplies(instance.instanceId);
@ -411,7 +411,7 @@ export class GBMinService {
GBDeployer.mountGBKBAssets(`${instance.botId}.gbkb`, instance.botId, `${instance.botId}.gbkb`);
}
public static isChatAPI (req, res) {
public static isChatAPI(req, res) {
if (!res) {
return 'GeneralBots';
}
@ -422,7 +422,7 @@ export class GBMinService {
* Creates a listener that can be used by external monitors to check
* bot instance health.
*/
private createCheckHealthAddress (server: any, min: GBMinInstance, instance: IGBInstance) {
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.
@ -453,7 +453,7 @@ export class GBMinService {
* Handle OAuth2 web service calls for token requests
* on https://<gbhost>/<BotId>/token URL.
*/
private handleOAuthTokenRequests (server: any, min: GBMinInstance, instance: IGBInstance) {
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.
@ -502,7 +502,7 @@ export class GBMinService {
* Handle OAuth2 web service calls for authorization requests
* on https://<gbhost>/<BotId>/auth URL.
*/
private handleOAuthRequests (server: any, min: GBMinInstance) {
private handleOAuthRequests(server: any, min: GBMinInstance) {
server.get(`/${min.instance.botId}/auth`, (req, res) => {
let authorizationUrl = urlJoin(
min.instance.authenticatorAuthorityHostUrl,
@ -520,7 +520,7 @@ export class GBMinService {
/**
* Returns the instance object to clients requesting bot info.
*/
private async handleGetInstanceForClient (req: any, res: any) {
private async handleGetInstanceForClient(req: any, res: any) {
// Translates the requested botId.
let botId = req.params.botId;
@ -577,7 +577,7 @@ export class GBMinService {
/**
* Gets Webchat token from Bot Service.
*/
private async getWebchatToken (instance: any) {
private async getWebchatToken(instance: any) {
const url = 'https://directline.botframework.com/v3/directline/tokens/generate';
const options = {
method: 'POST',
@ -600,7 +600,7 @@ export class GBMinService {
/**
* Gets a Speech to Text / Text to Speech token from the provider.
*/
private async getSTSToken (instance: any) {
private async getSTSToken(instance: any) {
const options = {
method: 'POST',
headers: {
@ -620,7 +620,7 @@ export class GBMinService {
/**
* Builds the BOT Framework & GB infrastructures.
*/
private async buildBotAdapter (instance: any, sysPackages: IGBPackage[], appPackages: IGBPackage[]) {
private async buildBotAdapter(instance: any, sysPackages: IGBPackage[], appPackages: IGBPackage[]) {
// MSFT stuff.
const adapter = new BotFrameworkAdapter({
@ -715,7 +715,7 @@ export class GBMinService {
await min.whatsAppDirectLine.setup(true);
} else {
const minBoot = GBServer.globals.minBoot as any;
if(minBoot.whatsappServiceKey){
if (minBoot.whatsappServiceKey) {
min.whatsAppDirectLine = new WhatsappDirectLine(
min,
min.botId,
@ -755,7 +755,7 @@ export class GBMinService {
/**
* Performs calling of loadBot event in all .gbapps.
*/
private async invokeLoadBot (appPackages: IGBPackage[], sysPackages: IGBPackage[], min: GBMinInstance) {
private async invokeLoadBot(appPackages: IGBPackage[], sysPackages: IGBPackage[], min: GBMinInstance) {
// Calls loadBot event in all .gbapp packages.
await CollectionUtil.asyncForEach(sysPackages, async p => {
@ -789,7 +789,7 @@ export class GBMinService {
}
// https://github.com/GeneralBots/BotServer/issues/313
public static userMobile (step) {
public static userMobile(step) {
let mobile = WhatsappDirectLine.mobiles[step.context.activity.conversation.id];
if (!mobile && step) {
@ -802,7 +802,7 @@ export class GBMinService {
/**
* BOT Framework web service hook method.
*/
private async receiver (
private async receiver(
req: any,
res: any,
conversationState: ConversationState,
@ -937,9 +937,7 @@ 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})`
`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.
@ -1030,7 +1028,7 @@ export class GBMinService {
/**
* Called to handle all event sent by .gbui clients.
*/
private async processEventActivity (min, user, context, step: GBDialogStep) {
private async processEventActivity(min, user, context, step: GBDialogStep) {
if (context.activity.name === 'whoAmI') {
await step.beginDialog('/whoAmI');
} else if (context.activity.name === 'showSubjects') {
@ -1065,10 +1063,20 @@ export class GBMinService {
}
}
/**
*
* Checks for global exit kewywords cancelling any active dialogs.
*
* */
public static isGlobalQuitUtterance(locale, utterance) {
return utterance.match(Messages.global_quit);
}
/**
* Called to handle all text messages sent and received by the bot.
*/
private async processMessageActivity (context, min: GBMinInstance, step: GBDialogStep) {
private async processMessageActivity(context, min: GBMinInstance, step: GBDialogStep) {
const sec = new SecService();
if (!context.activity.text) {
@ -1109,12 +1117,6 @@ export class GBMinService {
}
}
// Checks for global exit kewywords cancelling any active dialogs.
const globalQuit = (locale, utterance) => {
return utterance.match(Messages.global_quit);
};
// Files in .gbdialog can be called directly by typing its name normalized into JS .
const isVMCall = Object.keys(min.scriptMap).find(key => min.scriptMap[key] === context.activity.text) !== undefined;
@ -1142,7 +1144,7 @@ export class GBMinService {
} else {
await step.beginDialog(cmdOrDialogName, { args: args });
}
} else if (globalQuit(step.context.activity.locale, context.activity.text)) {
} else if (GBMinService.isGlobalQuitUtterance(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') {

View file

@ -54,9 +54,6 @@ else
talk "The maximum number of payments is 60"
end if
' TODO: This must be reviewed in terms of financing logic.
nInstallments = parseInt(installments)
vamount = parseFloat(amount)
initialPayment = vamount * 0.3 ' 30% of the value

View file

@ -185,7 +185,6 @@ export class SecService extends GBService {
item !== userSystemId &&
!(await this.isAgentSystemId(item))
) {
// TODO: Optimize loop.
agentSystemId = item;
}
});

View file

@ -34,7 +34,7 @@ import urlJoin from 'url-join';
import Swagger from 'swagger-client';
import Path from 'path';
import Fs from 'fs';
import { GBLog, GBMinInstance, GBService, IGBPackage } from 'botlib';
import { GBError, GBLog, GBMinInstance, GBService, IGBPackage } from 'botlib';
import { CollectionUtil } from 'pragmatismo-io-framework';
import { GBServer } from '../../../src/app.js';
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService.js';
@ -130,123 +130,123 @@ export class WhatsappDirectLine extends GBService {
case 'GeneralBots':
const minBoot = GBServer.globals.minBoot as any;
// Initialize the browser using a local profile for each bot.
// Initialize the browser using a local profile for each bot.
const gbaiName = `${this.min.botId}.gbai`;
const localName = Path.join('work', gbaiName, 'profile');
const gbaiName = `${this.min.botId}.gbai`;
const localName = Path.join('work', gbaiName, 'profile');
const createClient = async browserWSEndpoint => {
let puppeteer: any = {
headless: false,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--no-first-run',
'--no-zygote',
'--single-process',
'--disable-gpu',
'--disable-infobars',
'--disable-features=site-per-process',
`--user-data-dir=${localName}`
]
};
if (browserWSEndpoint) {
puppeteer = { browserWSEndpoint: browserWSEndpoint };
}
const createClient = async browserWSEndpoint => {
let puppeteer: any = {
headless: false,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--no-first-run',
'--no-zygote',
'--single-process',
'--disable-gpu',
'--disable-infobars',
'--disable-features=site-per-process',
`--user-data-dir=${localName}`
]
};
if (browserWSEndpoint) {
puppeteer = { browserWSEndpoint: browserWSEndpoint };
}
const client = (this.customClient = new wpp.Client({
authStrategy: new wpp.LocalAuth({
clientId: this.min.botId,
dataPath: localName
}),
puppeteer: puppeteer
}));
const client = (this.customClient = new wpp.Client({
authStrategy: new wpp.LocalAuth({
clientId: this.min.botId,
dataPath: localName
}),
puppeteer: puppeteer
}));
client.on(
'message',
(async message => {
await this.WhatsAppCallback(message, null);
}).bind(this)
);
client.on(
'message',
(async message => {
await this.WhatsAppCallback(message, null);
}).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);
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);
// Sends QR Code to boot bot admin.
// Sends QR Code to boot bot admin.
const msg = `Please, scan QR Code with for bot ${this.botId}.`;
GBLog.info(msg);
qrcode.generate(qr, { small: true, scale: 0.5 });
const msg = `Please, scan QR Code with for bot ${this.botId}.`;
GBLog.info(msg);
qrcode.generate(qr, { small: true, scale: 0.5 });
// While handling other bots uses boot instance of this class to send QR Codes.
// While handling other bots uses boot instance of this class to send QR Codes.
const s = new DialogKeywords(this.min, null, null);
const qrBuf = await s.getQRCode(qr);
const gbaiName = `${this.min.botId}.gbai`;
const localName = Path.join(
'work',
gbaiName,
'cache',
`qr${GBAdminService.getRndReadableIdentifier()}.png`
);
Fs.writeFileSync(localName, qrBuf);
const url = urlJoin(GBServer.globals.publicAddress, this.min.botId, 'cache', Path.basename(localName));
GBServer.globals.minBoot.whatsAppDirectLine.sendFileToDevice(
adminNumber,
url,
Path.basename(localName),
msg
);
s.sendEmail({ to: adminEmail, subject: `Check your WhatsApp for bot ${this.botId}`, body: msg });
}).bind(this)
);
client.on('authenticated', async () => {
this.browserWSEndpoint = client.pupBrowser.wsEndpoint();
GBLog.verbose(`GBWhatsApp: QR Code authenticated for ${this.botId}.`);
});
client.on('ready', async () => {
client.pupBrowser.on(
'disconnected',
(async () => {
GBLog.info(`Browser terminated. Restarting ${this.min.botId} WhatsApp native provider.`);
await createClient.bind(this)(null);
}).bind(this)
const s = new DialogKeywords(this.min, null, null);
const qrBuf = await s.getQRCode(qr);
const gbaiName = `${this.min.botId}.gbai`;
const localName = Path.join(
'work',
gbaiName,
'cache',
`qr${GBAdminService.getRndReadableIdentifier()}.png`
);
Fs.writeFileSync(localName, qrBuf);
const url = urlJoin(GBServer.globals.publicAddress, this.min.botId, 'cache', Path.basename(localName));
GBServer.globals.minBoot.whatsAppDirectLine.sendFileToDevice(
adminNumber,
url,
Path.basename(localName),
msg
);
GBLog.verbose(`GBWhatsApp: Emptying chat list for ${this.botId}...`);
s.sendEmail({ to: adminEmail, subject: `Check your WhatsApp for bot ${this.botId}`, body: msg });
}).bind(this)
);
// Keeps the chat list cleaned.
client.on('authenticated', async () => {
this.browserWSEndpoint = client.pupBrowser.wsEndpoint();
GBLog.verbose(`GBWhatsApp: QR Code authenticated for ${this.botId}.`);
});
const chats = await client.getChats();
await CollectionUtil.asyncForEach(chats, async chat => {
const sleep = ms => {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
};
const wait = Math.floor(Math.random() * 5000) + 1000;
await sleep(wait);
if (chat.isGroup) {
await chat.clearMessages();
} else if (!chat.pinned) {
await chat.delete();
}
});
client.on('ready', async () => {
client.pupBrowser.on(
'disconnected',
(async () => {
GBLog.info(`Browser terminated. Restarting ${this.min.botId} WhatsApp native provider.`);
await createClient.bind(this)(null);
}).bind(this)
);
GBLog.verbose(`GBWhatsApp: Emptying chat list for ${this.botId}...`);
// Keeps the chat list cleaned.
const chats = await client.getChats();
await CollectionUtil.asyncForEach(chats, async chat => {
const sleep = ms => {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
};
const wait = Math.floor(Math.random() * 5000) + 1000;
await sleep(wait);
if (chat.isGroup) {
await chat.clearMessages();
} else if (!chat.pinned) {
await chat.delete();
}
});
});
client.initialize();
};
await createClient.bind(this)(this.browserWSEndpoint);
client.initialize();
};
await createClient.bind(this)(this.browserWSEndpoint);
setUrl = false;
setUrl = false;
break;
@ -310,10 +310,8 @@ export class WhatsappDirectLine extends GBService {
public async check() {
switch (this.provider) {
case 'GeneralBots':
return this.customClient.getState() === 'CONNECTED';
// TODO: Verify if browser is OK.
return true;
default:
GBLog.verbose(`GBWhatsapp: Checking server...`);
let url = urlJoin(this.whatsappServiceUrl, 'status') + `?token=${this.min.instance.whatsappServiceKey}`;
@ -323,8 +321,8 @@ export class WhatsappDirectLine extends GBService {
};
const res = await fetch(url, options);
const json = (await res.json());
return json ['accountStatus'] === 'authenticated';
const json = await res.json();
return json['accountStatus'] === 'authenticated';
}
}
@ -538,7 +536,6 @@ export class WhatsappDirectLine extends GBService {
await this.min.conversationalService.sendMarkdownToMobile(this.min, null, user.userSystemId, message);
}
} else if (text === '/qt') {
// https://github.com/GeneralBots/BotServer/issues/307
await this.sendToDeviceEx(
@ -579,8 +576,7 @@ export class WhatsappDirectLine extends GBService {
locale,
null
);
} else if (text === '/qt' || text === 'Sair' || text === 'Fechar') {
// TODO: Transfers only in pt-br for now.
} else if (text === '/qt' || GBMinService.isGlobalQuitUtterance(locale, text)) {
await this.endTransfer(from, locale, user, agent, sec);
} else {
GBLog.info(`USER (${from}) TO AGENT ${agent.userSystemId}: ${text}`);
@ -836,9 +832,7 @@ export class WhatsappDirectLine extends GBService {
break;
case 'maytapi':
options = {}; // TODO: Code Maytapi.
break;
throw GBError.create('Sending audio in Maytapi not supported.');
}
if (options) {
@ -920,8 +914,6 @@ export class WhatsappDirectLine extends GBService {
await fetch(url, options);
} catch (error) {
GBLog.error(`Error sending message to Whatsapp provider ${error.message}`);
// TODO: Handle Error: socket hang up and retry.
}
}
}

View file

@ -66,7 +66,7 @@ export class GBServer {
* Program entry-point.
*/
public static run () {
public static run() {
GBLog.info(`The Bot Server is in STARTING mode...`);
GBServer.globals = new RootData();
GBConfigService.init();
@ -127,7 +127,6 @@ export class GBServer {
if (proxy !== undefined) {
GBServer.globals.publicAddress = proxy;
} else {
// Ensure that local development proxy is setup.
GBLog.info(`Establishing a development local proxy (ngrok)...`);
@ -224,15 +223,15 @@ export class GBServer {
const loggers = GBLog.getLogger();
winston.default(server, loggers[1]);
}
GBLog.info(`The Bot Server is in RUNNING mode...`);
// Opens Navigator.
// TODO: Config: core.openBrowserInDevelopment();
if (process.env.DEV_OPEN_BROWSER) {
core.openBrowserInDevelopment();
}
} catch (err) {
GBLog.error(`STOP: ${err.message ? err.message : err} ${err.stack ? err.stack : ''}`);
process.exit(1);
@ -240,8 +239,8 @@ export class GBServer {
})();
};
// TODO: Move to .gbot folder myown.com pointing to generalbots.ai/myown.
//
if (process.env.CERTIFICATE_PFX) {
const options1 = {
passphrase: process.env.CERTIFICATE_PASSPHRASE,