From 2c185177a8ceee30e4e29513daefd9ef5ef0566c Mon Sep 17 00:00:00 2001 From: Rodrigo Rodriguez Date: Fri, 8 Mar 2019 17:05:58 -0300 Subject: [PATCH] fix(general): tslint being applied in all sources. --- package.json | 2 +- packages/admin.gbapp/index.ts | 2 +- packages/analytics.gblib/index.ts | 2 +- packages/azuredeployer.gbapp/index.ts | 2 +- .../services/AzureDeployerService.ts | 22 +- packages/console.gblib/index.ts | 2 +- .../services/ConsoleDirectLine.ts | 303 ++++++++---------- packages/core.gbapp/dialogs/WhoAmIDialog.ts | 2 +- packages/core.gbapp/index.ts | 2 +- .../core.gbapp/services/GBConfigService.ts | 4 +- .../services/GBConversationalService.ts | 42 ++- packages/core.gbapp/services/GBCoreService.ts | 98 +++--- packages/core.gbapp/services/GBDeployer.ts | 42 +-- packages/core.gbapp/services/GBMinService.ts | 28 +- packages/core.gbapp/services/GBVMService.ts | 11 +- packages/core.gbapp/services/TSCompiler.ts | 6 +- .../dialogs/FeedbackDialog.ts | 2 +- .../dialogs/QualityDialog.ts | 4 +- packages/customer-satisfaction.gbapp/index.ts | 2 +- packages/kb.gbapp/dialogs/AskDialog.ts | 14 +- packages/kb.gbapp/dialogs/FaqDialog.ts | 5 +- packages/kb.gbapp/dialogs/MenuDialog.ts | 2 +- packages/kb.gbapp/index.ts | 2 +- packages/kb.gbapp/services/KBService.ts | 18 +- packages/security.gblib/index.ts | 2 +- packages/whatsapp.gblib/index.ts | 2 +- .../services/WhatsappDirectLine.ts | 20 +- src/app.ts | 14 +- src/logger.ts | 76 ----- tslint.json | 79 +++-- 30 files changed, 357 insertions(+), 455 deletions(-) delete mode 100644 src/logger.ts diff --git a/package.json b/package.json index f44c5c26..810157d2 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ }, "scripts": { "clean": "shx rm -rf node_modules/ dist/ docs/reference", - "tslint": "tslint --fix ./src/*.ts ./packages/**/*.ts -t verbose", + "tslint": "tslint --fix ./src/*.ts ./packages/**/*.ts -t verbose -e ./packages/default.gbui/**/* -e ./packages/**/*.gbdialog/**/*", "build": "npm install && npm run build-server && npm run build-gbui && npm run build-docs", "build-server": "tsc", "build-gbui": "cd packages/default.gbui && echo SKIP_PREFLIGHT_CHECK=true >.env && npm install && npm run build", diff --git a/packages/admin.gbapp/index.ts b/packages/admin.gbapp/index.ts index d3c5aef7..802fa41b 100644 --- a/packages/admin.gbapp/index.ts +++ b/packages/admin.gbapp/index.ts @@ -47,7 +47,7 @@ export class GBAdminPackage implements IGBPackage { public unloadPackage(core: IGBCoreService): void {} public getDialogs(min: GBMinInstance) {} public unloadBot(min: GBMinInstance): void {} - public onNewSession(min: GBMinInstance, step: any): void {} + public onNewSession(min: GBMinInstance, step: GBDialogStep): void {} public loadPackage(core: IGBCoreService, sequelize: Sequelize): void { core.sequelize.addModels([GuaribasAdmin]); diff --git a/packages/analytics.gblib/index.ts b/packages/analytics.gblib/index.ts index 3e0860b4..0c3e33f8 100644 --- a/packages/analytics.gblib/index.ts +++ b/packages/analytics.gblib/index.ts @@ -49,5 +49,5 @@ export class GBAnalyticsPackage implements IGBPackage { public unloadPackage(core: IGBCoreService): void {} public loadBot(min: GBMinInstance): void {} public unloadBot(min: GBMinInstance): void {} - public onNewSession(min: GBMinInstance, step: any): void {} + public onNewSession(min: GBMinInstance, step: GBDialogStep): void {} } diff --git a/packages/azuredeployer.gbapp/index.ts b/packages/azuredeployer.gbapp/index.ts index 66d85906..905b43cd 100644 --- a/packages/azuredeployer.gbapp/index.ts +++ b/packages/azuredeployer.gbapp/index.ts @@ -50,5 +50,5 @@ export class GBAzureDeployerPackage implements IGBPackage { public loadBot(min: GBMinInstance): void {} public unloadBot(min: GBMinInstance): void {} - public onNewSession(min: GBMinInstance, step: any): void {} + public onNewSession(min: GBMinInstance, step: GBDialogStep): void {} } diff --git a/packages/azuredeployer.gbapp/services/AzureDeployerService.ts b/packages/azuredeployer.gbapp/services/AzureDeployerService.ts index 10cd564a..c0584c00 100644 --- a/packages/azuredeployer.gbapp/services/AzureDeployerService.ts +++ b/packages/azuredeployer.gbapp/services/AzureDeployerService.ts @@ -51,7 +51,7 @@ import { GBConfigService } from '../../../packages/core.gbapp/services/GBConfigS import { GBDeployer } from '../../../packages/core.gbapp/services/GBDeployer'; const Spinner = require('cli-spinner').Spinner; -const logger = require('../../../src/logger'); + const UrlJoin = require('url-join'); const iconUrl = 'https://github.com/pragmatismo-io/BotServer/blob/master/docs/images/generalbots-logo-squared.png'; const publicIp = require('public-ip'); @@ -221,7 +221,7 @@ export class AzureDeployerService implements IGBInstallationDeployer { if (!(res.bodyAsJson as any).id) { throw res.bodyAsText; } - logger.info(`Bot proxy updated at: ${endpoint}.`); + GBLog.info(`Bot proxy updated at: ${endpoint}.`); } public async openStorageFirewall(groupName, serverName) { @@ -258,14 +258,14 @@ export class AzureDeployerService implements IGBInstallationDeployer { let keys: any; const name = instance.botId; - logger.info(`Deploying Deploy Group (It may take a few minutes)...`); + GBLog.info(`Deploying Deploy Group (It may take a few minutes)...`); await this.createDeployGroup(name, instance.cloudLocation); - logger.info(`Deploying Bot Server...`); + GBLog.info(`Deploying Bot Server...`); const serverFarm = await this.createHostingPlan(name, `${name}-server-plan`, instance.cloudLocation); await this.createServer(serverFarm.id, name, `${name}-server`, instance.cloudLocation); - logger.info(`Deploying Bot Storage...`); + GBLog.info(`Deploying Bot Storage...`); const administratorLogin = `sa${GBAdminService.getRndReadableIdentifier()}`; const administratorPassword = GBAdminService.getRndPassword(); const storageServer = `${name.toLowerCase()}-storage-server`; @@ -285,7 +285,7 @@ export class AzureDeployerService implements IGBInstallationDeployer { instance.storageDialect = 'mssql'; instance.storageServer = storageServer; - logger.info(`Deploying Search...`); + GBLog.info(`Deploying Search...`); const searchName = `${name}-search`.toLowerCase(); await this.createSearch(name, searchName, instance.cloudLocation); const searchKeys = await this.searchClient.adminKeys.get(name, searchName); @@ -295,19 +295,19 @@ export class AzureDeployerService implements IGBInstallationDeployer { instance.searchKey = searchKeys.primaryKey; this.deployer.rebuildIndex(instance, this.deployer); - logger.info(`Deploying Speech...`); + GBLog.info(`Deploying Speech...`); const speech = await this.createSpeech(name, `${name}-speech`, instance.cloudLocation); keys = await this.cognitiveClient.accounts.listKeys(name, speech.name); instance.speechEndpoint = speech.endpoint; instance.speechKey = keys.key1; - logger.info(`Deploying SpellChecker...`); + GBLog.info(`Deploying SpellChecker...`); const spellChecker = await this.createSpellChecker(name, `${name}-spellchecker`); keys = await this.cognitiveClient.accounts.listKeys(name, spellChecker.name); instance.spellcheckerKey = keys.key1; instance.spellcheckerEndpoint = spellChecker.endpoint; - logger.info(`Deploying Text Analytics...`); + GBLog.info(`Deploying Text Analytics...`); const textAnalytics = await this.createTextAnalytics(name, `${name}-textanalytics`, instance.cloudLocation); keys = await this.cognitiveClient.accounts.listKeys(name, textAnalytics.name); instance.textAnalyticsEndpoint = textAnalytics.endpoint; @@ -315,7 +315,7 @@ export class AzureDeployerService implements IGBInstallationDeployer { // TODO: Check quotes being added when NLP field is filled. - logger.info(`Deploying NLP...`); + GBLog.info(`Deploying NLP...`); const nlp = await this.createNLP(name, `${name}-nlp`, instance.cloudLocation); keys = await this.cognitiveClient.accounts.listKeys(name, nlp.name); const nlpAppId = await this.createNLPService(name, name, instance.cloudLocation, culture, instance.nlpAuthoringKey); @@ -324,7 +324,7 @@ export class AzureDeployerService implements IGBInstallationDeployer { instance.nlpKey = keys.key1; instance.nlpAppId = nlpAppId; - logger.info(`Deploying Bot...`); + GBLog.info(`Deploying Bot...`); instance.botEndpoint = this.defaultEndPoint; instance = await this.internalDeployBot( diff --git a/packages/console.gblib/index.ts b/packages/console.gblib/index.ts index 35fd8129..1ee62f9a 100644 --- a/packages/console.gblib/index.ts +++ b/packages/console.gblib/index.ts @@ -59,5 +59,5 @@ export class GBConsolePackage implements IGBPackage { public unloadBot(min: GBMinInstance): void {} - public onNewSession(min: GBMinInstance, step: any): void {} + public onNewSession(min: GBMinInstance, step: GBDialogStep): void {} } diff --git a/packages/console.gblib/services/ConsoleDirectLine.ts b/packages/console.gblib/services/ConsoleDirectLine.ts index ede2e837..56be12e8 100644 --- a/packages/console.gblib/services/ConsoleDirectLine.ts +++ b/packages/console.gblib/services/ConsoleDirectLine.ts @@ -1,193 +1,152 @@ -/*****************************************************************************\ -| ( )_ _ | -| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ | -| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ | -| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) | -| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' | -| | | ( )_) | | -| (_) \___/' | -| | -| General Bots Copyright (c) Pragmatismo.io. All rights reserved. | -| Licensed under the AGPL-3.0. | -| | -| According to our dual licensing model, this program can be used either | -| under the terms of the GNU Affero General Public License, version 3, | -| or under a proprietary license. | -| | -| The texts of the GNU Affero General Public License with an additional | -| permission and of our proprietary license can be found at and | -| in the LICENSE file you have received along with this program. | -| | -| This program is distributed in the hope that it will be useful, | -| but WITHOUT ANY WARRANTY, without even the implied warranty of | -| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -| GNU Affero General Public License for more details. | -| | -| "General Bots" is a registered trademark of Pragmatismo.io. | -| The licensing of the program under the AGPLv3 does not imply a | -| trademark license. Therefore any rights, title and interest in | -| our trademarks remain entirely with us. | -| | -\*****************************************************************************/ - -const Path = require('path'); -const Fs = require('fs'); -const _ = require('lodash'); -const Parse = require('csv-parse'); -const Async = require('async'); -const UrlJoin = require('url-join'); -const logger = require('../../../src/logger'); const Swagger = require('swagger-client'); const rp = require('request-promise'); import { GBService } from 'botlib'; export class ConsoleDirectLine extends GBService { + public pollInterval = 1000; + public directLineSecret = ''; + public directLineClientName = 'DirectLineClient'; + public directLineSpecUrl = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json'; - public pollInterval = 1000; - public directLineSecret = ''; - public directLineClientName = 'DirectLineClient'; - public directLineSpecUrl = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json'; + constructor(directLineSecret) { + super(); - constructor(directLineSecret) { - super(); + this.directLineSecret = directLineSecret; - this.directLineSecret = directLineSecret; - - // TODO: Migrate to Swagger 3. - const directLineClient = rp(this.directLineSpecUrl) - .then(function (spec) { - return new Swagger({ - spec: JSON.parse(spec.trim()), - usePromise: true - }); - }) - .then(function (client) { - client.clientAuthorizations.add('AuthorizationBotConnector', - new Swagger.ApiKeyAuthorization('Authorization', 'Bearer ' + directLineSecret, 'header')); - - return client; - }) - .catch(function (err) { - console.error('Error initializing DirectLine client', err); - }); - - // TODO: Remove *this* issue. - const _this_ = this; - directLineClient.then((client) => { - client.Conversations.Conversations_StartConversation() - .then(function (response) { - return response.obj.conversationId; - }) - .then(function (conversationId) { - _this_.sendMessagesFromConsole(client, conversationId); - _this_.pollMessages(client, conversationId); - }) - .catch(function (err) { - console.error('Error starting conversation', err); - }); + const directLineClient = rp(this.directLineSpecUrl) + .then(function(spec) { + return new Swagger({ + spec: JSON.parse(spec.trim()), + usePromise: true + }); + }) + .then(function(client) { + client.clientAuthorizations.add( + 'AuthorizationBotConnector', + new Swagger.ApiKeyAuthorization('Authorization', 'Bearer ' + directLineSecret, 'header') + ); + + return client; + }) + .catch(function(err) { + console.error('Error initializing DirectLine client', err); + }); + + // TODO: Remove *this* issue. + const _this_ = this; + directLineClient.then(client => { + client.Conversations.Conversations_StartConversation() + .then(function(response) { + return response.obj.conversationId; + }) + .then(function(conversationId) { + _this_.sendMessagesFromConsole(client, conversationId); + _this_.pollMessages(client, conversationId); + }) + .catch(function(err) { + console.error('Error starting conversation', err); + }); + }); + } + + public sendMessagesFromConsole(client, conversationId) { + const _this_ = this; + process.stdin.resume(); + const stdin = process.stdin; + process.stdout.write('Command> '); + stdin.addListener('data', function(e) { + const input = e.toString().trim(); + if (input) { + // exit + if (input.toLowerCase() === 'exit') { + return process.exit(); + } + + client.Conversations.Conversations_PostActivity({ + conversationId: conversationId, + activity: { + textFormat: 'plain', + text: input, + type: 'message', + from: { + id: _this_.directLineClientName, + name: _this_.directLineClientName + } + } + }).catch(function(err) { + console.error('Error sending message:', err); }); - } - public sendMessagesFromConsole(client, conversationId) { - const _this_ = this; - process.stdin.resume(); - const stdin = process.stdin; process.stdout.write('Command> '); - stdin.addListener('data', function (e) { - const input = e.toString().trim(); - if (input) { - // exit - if (input.toLowerCase() === 'exit') { - return process.exit(); - } + } + }); + } - client.Conversations.Conversations_PostActivity( - { - conversationId: conversationId, - activity: { - textFormat: 'plain', - text: input, - type: 'message', - from: { - id: _this_.directLineClientName, - name: _this_.directLineClientName - } - } - }).catch(function (err) { - console.error('Error sending message:', err); - }); + /** TBD: Poll Messages from conversation using DirectLine client */ + public pollMessages(client, conversationId) { + const _this_ = this; + console.log('Starting polling message for conversationId: ' + conversationId); + let watermark = null; + setInterval(function() { + client.Conversations.Conversations_GetActivities({ conversationId: conversationId, watermark: watermark }) + .then(function(response) { + watermark = response.obj.watermark; - process.stdout.write('Command> '); - } - }); + return response.obj.activities; + }) + .then(_this_.printMessages, _this_.directLineClientName); + }, this.pollInterval); + } + + public printMessages(activities, directLineClientName) { + if (activities && activities.length) { + // ignore own messages + activities = activities.filter(function(m) { + return m.from.id !== directLineClientName; + }); + + if (activities.length) { + // print other messages + activities.forEach(activity => { + console.log(activity.text); + }, this); + + process.stdout.write('Command> '); + } + } + } + + public printMessage(activity) { + if (activity.text) { + console.log(activity.text); } - /** TBD: Poll Messages from conversation using DirectLine client */ - public pollMessages(client, conversationId) { - const _this_ = this; - console.log('Starting polling message for conversationId: ' + conversationId); - let watermark = null; - setInterval(function () { - client.Conversations.Conversations_GetActivities({ conversationId: conversationId, watermark: watermark }) - .then(function (response) { - watermark = response.obj.watermark; - return response.obj.activities; - }) - .then(_this_.printMessages, _this_.directLineClientName); - }, this.pollInterval); - } + if (activity.attachments) { + activity.attachments.forEach(function(attachment) { + switch (attachment.contentType) { + case 'application/vnd.microsoft.card.hero': + this.renderHeroCard(attachment); + break; - public printMessages(activities, directLineClientName) { - - if (activities && activities.length) { - // ignore own messages - activities = activities.filter(function (m) { return m.from.id !== directLineClientName; }); - - if (activities.length) { - - // print other messages - activities.forEach(activity => { - console.log(activity.text); - }, this); - - process.stdout.write('Command> '); - } + case 'image/png': + console.log('Opening the requested image ' + attachment.contentUrl); + open(attachment.contentUrl); + break; } + }); } + } - public printMessage(activity) { - if (activity.text) { - console.log(activity.text); - } + public renderHeroCard(attachment) { + const width = 70; + const contentLine = function(content) { + return ' '.repeat((width - content.length) / 2) + content + ' '.repeat((width - content.length) / 2); + }; - if (activity.attachments) { - activity.attachments.forEach(function (attachment) { - switch (attachment.contentType) { - case 'application/vnd.microsoft.card.hero': - this.renderHeroCard(attachment); - break; - - case 'image/png': - console.log('Opening the requested image ' + attachment.contentUrl); - open(attachment.contentUrl); - break; - } - }); - } - } - - public renderHeroCard(attachment) { - const width = 70; - const contentLine = function (content) { - return ' '.repeat((width - content.length) / 2) + - content + - ' '.repeat((width - content.length) / 2); - }; - - console.log('/' + '*'.repeat(width + 1)); - console.log('*' + contentLine(attachment.content.title) + '*'); - console.log('*' + ' '.repeat(width) + '*'); - console.log('*' + contentLine(attachment.content.text) + '*'); - console.log('*'.repeat(width + 1) + '/'); - } + console.log('/' + '*'.repeat(width + 1)); + console.log('*' + contentLine(attachment.content.title) + '*'); + console.log('*' + ' '.repeat(width) + '*'); + console.log('*' + contentLine(attachment.content.text) + '*'); + console.log('*'.repeat(width + 1) + '/'); + } } diff --git a/packages/core.gbapp/dialogs/WhoAmIDialog.ts b/packages/core.gbapp/dialogs/WhoAmIDialog.ts index 20d7162e..7b20eddc 100644 --- a/packages/core.gbapp/dialogs/WhoAmIDialog.ts +++ b/packages/core.gbapp/dialogs/WhoAmIDialog.ts @@ -57,7 +57,7 @@ export class WhoAmIDialog extends IGBDialog { if (min.instance.whoAmIVideo) { await step.context.sendActivity(Messages[locale].show_video); - await min.conversationalService.sendEvent(step, 'play', { + await min.conversationalService.sendEvent(step: GBDialogStep, 'play', { playerType: 'video', data: min.instance.whoAmIVideo.trim() }); diff --git a/packages/core.gbapp/index.ts b/packages/core.gbapp/index.ts index 7166bfa6..3e73cba4 100644 --- a/packages/core.gbapp/index.ts +++ b/packages/core.gbapp/index.ts @@ -63,5 +63,5 @@ export class GBCorePackage implements IGBPackage { } public unloadBot(min: GBMinInstance): void {} - public onNewSession(min: GBMinInstance, step: any): void {} + public onNewSession(min: GBMinInstance, step: GBDialogStep): void {} } diff --git a/packages/core.gbapp/services/GBConfigService.ts b/packages/core.gbapp/services/GBConfigService.ts index e0a6fd65..e3e58e0e 100644 --- a/packages/core.gbapp/services/GBConfigService.ts +++ b/packages/core.gbapp/services/GBConfigService.ts @@ -30,7 +30,7 @@ | | \*****************************************************************************/ -const logger = require('../../../src/logger'); + import * as fs from 'fs'; /** @@ -108,7 +108,7 @@ export class GBConfigService { value = 'true'; break; default: - logger.warn(`Invalid key on .env file: '${key}'`); + GBLog.warn(`Invalid key on .env file: '${key}'`); break; } } diff --git a/packages/core.gbapp/services/GBConversationalService.ts b/packages/core.gbapp/services/GBConversationalService.ts index 3c83c608..5d4e501a 100644 --- a/packages/core.gbapp/services/GBConversationalService.ts +++ b/packages/core.gbapp/services/GBConversationalService.ts @@ -36,13 +36,11 @@ 'use strict'; -const logger = require('../../../src/logger'); -import { MessageFactory } from 'botbuilder'; +import { MessageFactory, RecognizerResult } from 'botbuilder'; import { LuisRecognizer } from 'botbuilder-ai'; -import { GBMinInstance, IGBConversationalService, IGBCoreService } from 'botlib'; +import { GBDialogStep, GBLog, GBMinInstance, IGBConversationalService, IGBCoreService } from 'botlib'; import { AzureText } from 'pragmatismo-io-framework'; import { Messages } from '../strings'; -import { GBCoreService } from './GBCoreService'; const Nexmo = require('nexmo'); export interface LanguagePickerSettings { @@ -50,19 +48,22 @@ export interface LanguagePickerSettings { supportedLocales?: string[]; } +/** + * Provides basic services for handling messages and dispatching to back-end + * services like NLP or Search. + */ export class GBConversationalService implements IGBConversationalService { - public coreService: IGBCoreService; constructor(coreService: IGBCoreService) { this.coreService = coreService; } - public getCurrentLanguage(step: any) { + public getCurrentLanguage(step: GBDialogStep) { return step.context.activity.locale; } - public async sendEvent(step: any, name: string, value: any): Promise { + public async sendEvent(step: GBDialogStep, name: string, value: any): Promise { if (step.context.activity.channelId === 'webchat') { const msg = MessageFactory.text(''); msg.value = value; @@ -73,6 +74,7 @@ export class GBConversationalService implements IGBConversationalService { } } + // tslint:disable:no-unsafe-any due to Nexmo. public async sendSms(min: GBMinInstance, mobile: string, text: string): Promise { return new Promise( (resolve: any, reject: any): any => { @@ -80,6 +82,7 @@ export class GBConversationalService implements IGBConversationalService { apiKey: min.instance.smsKey, apiSecret: min.instance.smsSecret }); + // tslint:disable-next-line:no-unsafe-any nexmo.message.sendSms(min.instance.smsServiceNumber, mobile, text, (err, data) => { if (err) { reject(err); @@ -90,8 +93,9 @@ export class GBConversationalService implements IGBConversationalService { } ); } + // tslint:enable:no-unsafe-any - public async routeNLP(step: any, min: GBMinInstance, text: string): Promise { + public async routeNLP(step: GBDialogStep, min: GBMinInstance, text: string): Promise { // Invokes LUIS. const endpoint = min.instance.nlpEndpoint.replace('/luis/v2.0', ''); @@ -102,38 +106,42 @@ export class GBConversationalService implements IGBConversationalService { endpoint: endpoint }); - let nlp: any; + let nlp: RecognizerResult; try { nlp = await model.recognize(step.context); } catch (error) { + // tslint:disable:no-unsafe-any if (error.statusCode === 404) { - logger.warn('NLP application still not publish and there are no other options for answering.'); + GBLog.warn('NLP application still not publish and there are no other options for answering.'); return Promise.resolve(false); } else { const msg = `Error calling NLP, check if you have a published model and assigned keys. Error: ${ error.statusCode ? error.statusCode : '' - } ${error.message}`; + } {error.message; }`; return Promise.reject(new Error(msg)); } + // tslint:enable:no-unsafe-any } // Resolves intents returned from LUIS. const topIntent = LuisRecognizer.topIntent(nlp); - if (topIntent) { + if (topIntent !== undefined) { const intent = topIntent; - const entity = nlp.entities && nlp.entities.length > 0 ? nlp.entities[0].entity.toUpperCase() : null; + // tslint:disable:no-unsafe-any + const firstEntity = nlp.entities && nlp.entities.length > 0 ? nlp.entities[0].entity.toUpperCase() : undefined; + // tslint:ensable:no-unsafe-any if (intent === 'None') { return Promise.resolve(false); } - logger.info(`NLP called: ${intent}, ${entity}`); + GBLog.info(`NLP called: ${intent} ${firstEntity}`); try { - await step.replaceDialog(`/${intent}`, nlp.entities); + await step.replaceDialog(` /${intent}`, nlp.entities); return Promise.resolve(true); } catch (error) { @@ -146,7 +154,7 @@ export class GBConversationalService implements IGBConversationalService { return Promise.resolve(false); } - public async checkLanguage(step, min, text) { + public async checkLanguage(step: GBDialogStep, min, text) { const locale = await AzureText.getLocale(min.instance.textAnalyticsKey, min.instance.textAnalyticsEndpoint, text); if (locale !== step.context.activity.locale.split('-')[0]) { switch (locale) { @@ -159,7 +167,7 @@ export class GBConversationalService implements IGBConversationalService { await step.context.sendActivity(Messages[locale].changing_language); break; default: - await step.context.sendActivity(`Unknown language: ${locale}`); + await step.context.sendActivity(`; Unknown; language: $;{locale;}`); break; } } diff --git a/packages/core.gbapp/services/GBCoreService.ts b/packages/core.gbapp/services/GBCoreService.ts index 72c0c1b2..07a7fd94 100644 --- a/packages/core.gbapp/services/GBCoreService.ts +++ b/packages/core.gbapp/services/GBCoreService.ts @@ -36,14 +36,13 @@ 'use strict'; -import { IGBCoreService, IGBInstallationDeployer, IGBInstance, IGBPackage } from 'botlib'; +import { GBLog, IGBCoreService, IGBInstallationDeployer, IGBInstance, IGBPackage } from 'botlib'; import * as fs from 'fs'; import { Sequelize } from 'sequelize-typescript'; import { GBAdminPackage } from '../../admin.gbapp/index'; import { GBAdminService } from '../../admin.gbapp/services/GBAdminService'; import { GBAnalyticsPackage } from '../../analytics.gblib'; import { StartDialog } from '../../azuredeployer.gbapp/dialogs/StartDialog'; -import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService'; import { GBCorePackage } from '../../core.gbapp'; import { GBCustomerSatisfactionPackage } from '../../customer-satisfaction.gbapp'; import { GBKBPackage } from '../../kb.gbapp'; @@ -52,14 +51,12 @@ import { GBWhatsappPackage } from '../../whatsapp.gblib/index'; import { GuaribasInstance } from '../models/GBModel'; import { GBConfigService } from './GBConfigService'; -const logger = require('../../../src/logger'); const opn = require('opn'); /** * Core service layer. */ export class GBCoreService implements IGBCoreService { - /** * Data access layer instance. */ @@ -121,10 +118,10 @@ export class GBCoreService implements IGBCoreService { throw new Error(`Unknown dialect: ${this.dialect}.`); } - const logging: any = + const logging: boolean | Function = GBConfigService.get('STORAGE_LOGGING') === 'true' ? (str: string): void => { - logger.info(str); + GBLog.info(str); } : false; @@ -153,12 +150,14 @@ export class GBCoreService implements IGBCoreService { if (this.dialect === 'mssql') { this.queryGenerator = this.sequelize.getQueryInterface().QueryGenerator; + // tslint:disable:no-unsafe-any this.createTableQuery = this.queryGenerator.createTableQuery; this.queryGenerator.createTableQuery = (tableName, attributes, options) => this.createTableQueryOverride(tableName, attributes, options); this.changeColumnQuery = this.queryGenerator.changeColumnQuery; this.queryGenerator.changeColumnQuery = (tableName, attributes) => this.changeColumnQueryOverride(tableName, attributes); + // tslint:enable:no-unsafe-any } } @@ -166,19 +165,21 @@ export class GBCoreService implements IGBCoreService { try { await this.sequelize.authenticate(); } catch (error) { - logger.info('Opening storage firewall on infrastructure...'); + GBLog.info('Opening storage firewall on infrastructure...'); + // tslint:disable:no-unsafe-any if (error.parent.code === 'ELOGIN') { await this.openStorageFrontier(installationDeployer); } else { throw error; } + // tslint:ensable:no-unsafe-any } } public async syncDatabaseStructure() { if (GBConfigService.get('STORAGE_SYNC') === 'true') { const alter = GBConfigService.get('STORAGE_SYNC_ALTER') === 'true'; - logger.info('Syncing database...'); + GBLog.info('Syncing database...'); return this.sequelize.sync({ alter: alter, @@ -186,7 +187,7 @@ export class GBCoreService implements IGBCoreService { }); } else { const msg = `Database synchronization is disabled.`; - logger.info(msg); + GBLog.info(msg); } } @@ -245,14 +246,14 @@ STORAGE_SYNC=true return await ngrok.connect({ port: port }); } else { - logger.warn('ngrok executable not found. Check installation or node_modules folder.'); + GBLog.warn('ngrok executable not found. Check installation or node_modules folder.'); return 'localhost'; } } catch (error) { // There are false positive from ngrok regarding to no memory, but it's just // lack of connection. - logger.verbose(error); + GBLog.verbose(error); throw new Error('Error connecting to remote ngrok server, please check network connection.'); } } @@ -274,14 +275,18 @@ STORAGE_SYNC=true * @param azureDeployer * @param proxyAddress */ - public async loadAllInstances(core: IGBCoreService, installationDeployer: IGBInstallationDeployer, proxyAddress: string) { - logger.info(`Loading instances from storage...`); + public async loadAllInstances( + core: IGBCoreService, + installationDeployer: IGBInstallationDeployer, + proxyAddress: string + ) { + GBLog.info(`Loading instances from storage...`); let instances: IGBInstance[]; try { instances = await core.loadInstances(); const instance = instances[0]; if (process.env.NODE_ENV === 'development') { - logger.info(`Updating bot endpoint to local reverse proxy (ngrok)...`); + GBLog.info(`Updating bot endpoint to local reverse proxy (ngrok)...`); await installationDeployer.updateBotProxy( instance.botId, instance.botId, @@ -290,15 +295,15 @@ STORAGE_SYNC=true } } catch (error) { // Check if storage is empty and needs formatting. - const isInvalidObject = error.parent.number == 208 || error.parent.errno == 1; // MSSQL or SQLITE. + const isInvalidObject = error.parent.number === 208 || error.parent.errno === 1; // MSSQL or SQLITE. if (isInvalidObject) { - if (GBConfigService.get('STORAGE_SYNC') != 'true') { + if (GBConfigService.get('STORAGE_SYNC') !== 'true') { throw new Error( `Operating storage is out of sync or there is a storage connection error. Try setting STORAGE_SYNC to true in .env file. Error: ${error.message}.` ); } else { - logger.info(`Storage is empty. After collecting storage structure from all .gbapps it will get synced.`); + GBLog.info(`Storage is empty. After collecting storage structure from all .gbapps it will get synced.`); } } else { throw new Error(`Cannot connect to operating storage: ${error.message}.`); @@ -316,7 +321,7 @@ STORAGE_SYNC=true * @param core */ public async ensureInstances(instances: IGBInstance[], bootInstance: any, core: IGBCoreService) { - if (!instances) { + if (instances === undefined) { const instance = new GuaribasInstance(); await instance.save(); instances = await core.loadInstances(); @@ -339,7 +344,7 @@ STORAGE_SYNC=true GBCustomerSatisfactionPackage, GBWhatsappPackage ].forEach(e => { - logger.info(`Loading sys package: ${e.name}...`); + GBLog.info(`Loading sys package: ${e.name}...`); const p = Object.create(e.prototype) as IGBPackage; p.loadPackage(core, core.sequelize); }); @@ -354,19 +359,27 @@ STORAGE_SYNC=true } } - public async createBootInstance(core: GBCoreService, installationDeployer: IGBInstallationDeployer, proxyAddress: string) { - - logger.info(`Deploying cognitive infrastructure (on the cloud / on premises)...`); + public async createBootInstance( + core: GBCoreService, + installationDeployer: IGBInstallationDeployer, + proxyAddress: string + ) { + GBLog.info(`Deploying cognitive infrastructure (on the cloud / on premises)...`); try { - let { instance, credentials, subscriptionId } = await StartDialog.createBaseInstance(installationDeployer); - instance = await installationDeployer.deployFarm(proxyAddress, instance, credentials, subscriptionId); - core.writeEnv(instance); - logger.info(`File .env written, starting General Bots...`); + const { instance, credentials, subscriptionId } = await StartDialog.createBaseInstance(installationDeployer); + const changedInstance = await installationDeployer.deployFarm( + proxyAddress, + instance, + credentials, + subscriptionId + ); + core.writeEnv(changedInstance); + GBLog.info(`File .env written, starting General Bots...`); GBConfigService.init(); - return instance; + return changedInstance; } catch (error) { - logger.warn( + GBLog.warn( `In case of error, please cleanup any infrastructure objects created during this procedure and .env before running again.` ); @@ -399,13 +412,13 @@ STORAGE_SYNC=true let sql: string = this.createTableQuery.apply(this.queryGenerator, [tableName, attributes, options]); const re1 = /CREATE\s+TABLE\s+\[([^\]]*)\]/; const matches = re1.exec(sql); - if (matches) { + if (matches !== null) { const table = matches[1]; const re2 = /PRIMARY\s+KEY\s+\(\[[^\]]*\](?:,\s*\[[^\]]*\])*\)/; sql = sql.replace( re2, (match: string, ...args: any[]): string => { - return 'CONSTRAINT [' + table + '_pk] ' + match; + return `CONSTRAINT [${table}_pk] ${match}`; } ); const re3 = /FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g; @@ -415,13 +428,13 @@ STORAGE_SYNC=true (match: string, ...args: any[]): string => { const fkcols = args[0]; let fkname = table; - let matches = re4.exec(fkcols); - while (matches != undefined) { - fkname += '_' + matches[1]; - matches = re4.exec(fkcols); + let matches2 = re4.exec(fkcols); + while (matches2 !== undefined) { + fkname += `_${matches2[1]}`; + matches2 = re4.exec(fkcols); } - return 'CONSTRAINT [' + fkname + '_fk] FOREIGN KEY (' + fkcols + ')'; + return `CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`; } ); } @@ -441,7 +454,7 @@ STORAGE_SYNC=true let sql: string = this.changeColumnQuery.apply(this.queryGenerator, [tableName, attributes]); const re1 = /ALTER\s+TABLE\s+\[([^\]]*)\]/; const matches = re1.exec(sql); - if (matches) { + if (matches !== null) { const table = matches[1]; const re2 = /(ADD\s+)?CONSTRAINT\s+\[([^\]]*)\]\s+FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g; const re3 = /\[([^\]]*)\]/g; @@ -450,13 +463,13 @@ STORAGE_SYNC=true (match: string, ...args: any[]): string => { const fkcols = args[2]; let fkname = table; - let matches = re3.exec(fkcols); - while (matches != undefined) { - fkname += '_' + matches[1]; - matches = re3.exec(fkcols); + let matches2 = re3.exec(fkcols); + while (matches2 !== undefined) { + fkname += `_${matches2[1]}`; + matches2 = re3.exec(fkcols); } - return (args[0] ? args[0] : '') + 'CONSTRAINT [' + fkname + '_fk] FOREIGN KEY (' + fkcols + ')'; + return `${args[0] ? args[0] : ''}CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`; } ); } @@ -471,7 +484,8 @@ STORAGE_SYNC=true */ private async openStorageFrontier(installationDeployer: IGBInstallationDeployer) { const group = GBConfigService.get('CLOUD_GROUP'); - const serverName = GBConfigService.get('STORAGE_SERVER').split('.database.windows.net')[0]; + const serverName = GBConfigService.get('STORAGE_SERVER') + .split('.database.windows.net')[0]; await installationDeployer.openStorageFirewall(group, serverName); } } diff --git a/packages/core.gbapp/services/GBDeployer.ts b/packages/core.gbapp/services/GBDeployer.ts index b75c49ea..c5dd11f0 100644 --- a/packages/core.gbapp/services/GBDeployer.ts +++ b/packages/core.gbapp/services/GBDeployer.ts @@ -36,7 +36,7 @@ 'use strict'; -const logger = require('../../../src/logger'); + const Path = require('path'); const UrlJoin = require('url-join'); const Fs = require('fs'); @@ -109,7 +109,7 @@ export class GBDeployer { const dirs = getDirectories(path); dirs.forEach(element => { if (element.startsWith('.')) { - logger.info(`Ignoring ${element}...`); + GBLog.info(`Ignoring ${element}...`); } else { if (element.endsWith('.gbot')) { botPackages.push(element); @@ -122,9 +122,9 @@ export class GBDeployer { }); } - logger.info(`Starting looking for packages (.gbot, .gbtheme, .gbkb, .gbapp)...`); + GBLog.info(`Starting looking for packages (.gbot, .gbtheme, .gbkb, .gbapp)...`); paths.forEach(e => { - logger.info(`Looking in: ${e}...`); + GBLog.info(`Looking in: ${e}...`); doIt(e); }); @@ -136,11 +136,11 @@ export class GBDeployer { .interval(1000) .times(10) .condition(cb => { - logger.info(`Waiting for app package deployment...`); + GBLog.info(`Waiting for app package deployment...`); cb(appPackagesProcessed === gbappPackages.length); }) .done(async result => { - logger.info(`App Package deployment done.`); + GBLog.info(`App Package deployment done.`); ({ generalPackages, totalPackages } = await this.deployDataPackages( core, @@ -319,7 +319,7 @@ export class GBDeployer { public runOnce() { const root = 'packages/default.gbui'; if (!Fs.existsSync(`${root}/build`)) { - logger.info(`Preparing default.gbui (it may take some additional time for the first time)...`); + GBLog.info(`Preparing default.gbui (it may take some additional time for the first time)...`); Fs.writeFileSync(`${root}/.env`, 'SKIP_PREFLIGHT_CHECK=true'); child_process.execSync('npm install', { cwd: root }); child_process.execSync('npm run build', { cwd: root }); @@ -346,9 +346,9 @@ export class GBDeployer { botPackages.forEach(e => { if (e !== 'packages\\boot.gbot') { - logger.info(`Deploying bot: ${e}...`); + GBLog.info(`Deploying bot: ${e}...`); _this.deployBot(e); - logger.info(`Bot: ${e} deployed...`); + GBLog.info(`Bot: ${e} deployed...`); } }); @@ -357,7 +357,7 @@ export class GBDeployer { generalPackages = generalPackages.filter(p => !p.endsWith('.git')); generalPackages.forEach(filename => { const filenameOnly = Path.basename(filename); - logger.info(`Deploying package: ${filename}...`); + GBLog.info(`Deploying package: ${filename}...`); // Handles apps for general bots - .gbapp must stay out of deploy folder. @@ -365,10 +365,10 @@ export class GBDeployer { // Themes for bots. } else if (Path.extname(filename) === '.gbtheme') { server.use('/themes/' + filenameOnly, express.static(filename)); - logger.info(`Theme (.gbtheme) assets accessible at: ${'/themes/' + filenameOnly}.`); + GBLog.info(`Theme (.gbtheme) assets accessible at: ${'/themes/' + filenameOnly}.`); } else if (Path.extname(filename) === '.gbkb') { server.use('/kb/' + filenameOnly + '/subjects', express.static(UrlJoin(filename, 'subjects'))); - logger.info(`KB (.gbkb) assets accessible at: ${'/kb/' + filenameOnly}.`); + GBLog.info(`KB (.gbkb) assets accessible at: ${'/kb/' + filenameOnly}.`); } else if (Path.extname(filename) === '.gbui') { // Already Handled } else if (Path.extname(filename) === '.gbdialog') { @@ -385,14 +385,14 @@ export class GBDeployer { .interval(100) .times(5) .condition(cb => { - logger.info(`Waiting for package deployment...`); + GBLog.info(`Waiting for package deployment...`); cb(totalPackages === generalPackages.length); }) .done(result => { if (botPackages.length === 0) { - logger.info('Use ADDITIONAL_DEPLOY_PATH to point to a .gbai package folder (no external packages).'); + GBLog.info('Use ADDITIONAL_DEPLOY_PATH to point to a .gbai package folder (no external packages).'); } else { - logger.info(`Package deployment done.`); + GBLog.info(`Package deployment done.`); } resolve(); }); @@ -405,17 +405,17 @@ export class GBDeployer { gbappPackages.forEach(e => { // Skips .gbapp inside deploy folder. if (!e.startsWith('packages')) { - logger.info(`Deploying app: ${e}...`); + GBLog.info(`Deploying app: ${e}...`); let folder = Path.join(e, 'node_modules'); if (!Fs.existsSync(folder)) { - logger.info(`Installing modules for ${e}...`); + GBLog.info(`Installing modules for ${e}...`); child_process.execSync('npm install', { cwd: e }); } folder = Path.join(e, 'dist'); if (!Fs.existsSync()) { - logger.info(`Compiling ${e}...`); + GBLog.info(`Compiling ${e}...`); try { child_process.execSync(Path.join(e, 'node_modules/.bin/tsc'), { cwd: e }); @@ -424,15 +424,15 @@ export class GBDeployer { const p = new m.Package(); p.loadPackage(core, core.sequelize); appPackages.push(p); - logger.info(`App (.gbapp) deployed: ${e}.`); + GBLog.info(`App (.gbapp) deployed: ${e}.`); appPackagesProcessed++; }) .catch(err => { - logger.error(`Error deploying .gbapp package: ${e}\n${err}`); + GBLog.error(`Error deploying .gbapp package: ${e}\n${err}`); appPackagesProcessed++; }); } catch (error) { - logger.error(`Error compiling .gbapp package ${e}:\n${error.stdout.toString()}`); + GBLog.error(`Error compiling .gbapp package ${e}:\n${error.stdout.toString()}`); appPackagesProcessed++; } } diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index 6722f8c8..862c54f5 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -39,14 +39,14 @@ const { DialogSet, TextPrompt } = require('botbuilder-dialogs'); const UrlJoin = require('url-join'); const express = require('express'); -const logger = require('../../../src/logger'); + const request = require('request-promise-native'); const AuthenticationContext = require('adal-node').AuthenticationContext; import { AutoSaveStateMiddleware, BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } from 'botbuilder'; import { ConfirmPrompt, WaterfallDialog } from 'botbuilder-dialogs'; -import { GBMinInstance, IGBAdminService, IGBConversationalService, IGBCoreService, IGBInstance, IGBPackage } from 'botlib'; +import { GBDialogStep, GBLog, GBMinInstance, IGBAdminService, IGBConversationalService, IGBCoreService, IGBInstance, IGBPackage } from 'botlib'; import { GBAnalyticsPackage } from '../../analytics.gblib'; import { GBCorePackage } from '../../core.gbapp'; import { GBCustomerSatisfactionPackage } from '../../customer-satisfaction.gbapp'; @@ -141,14 +141,14 @@ export class GBMinService { server.post(url, async (req, res) => { await this.receiver(adapter, req, res, conversationState, min, instance, appPackages); }); - logger.info(`GeneralBots(${instance.engineName}) listening on: ${url}.`); + GBLog.info(`GeneralBots(${instance.engineName}) listening on: ${url}.`); // Serves individual URL for each bot user interface. const uiUrl = `/${instance.botId}`; server.use(uiUrl, express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, 'build'))); - logger.info(`Bot UI ${uiPackage} accessible at: ${uiUrl}.`); + GBLog.info(`Bot UI ${uiPackage} accessible at: ${uiUrl}.`); const state = `${instance.instanceId}${Math.floor(Math.random() * 1000000000)}`; // Clients get redirected here in order to create an OAuth authorize url and redirect them to AAD. @@ -171,7 +171,7 @@ export class GBMinService { const state = await min.adminService.getValue(instance.instanceId, 'AntiCSRFAttackState'); if (req.query.state !== state) { const msg = 'WARNING: state field was not provided as anti-CSRF token'; - logger.error(msg); + GBLog.error(msg); throw new Error(msg); } const authenticationContext = new AuthenticationContext( @@ -187,7 +187,7 @@ export class GBMinService { async (err, token) => { if (err) { const msg = `Error acquiring token: ${err}`; - logger.error(msg); + GBLog.error(msg); res.send(msg); } else { await this.adminService.setValue(instance.instanceId, 'refreshToken', token.refreshToken); @@ -245,7 +245,7 @@ export class GBMinService { } else { const error = `Instance not found: ${botId}.`; res.sendStatus(error); - logger.error(error); + GBLog.error(error); } } @@ -354,7 +354,7 @@ export class GBMinService { if (sysPackage.name === 'GBWhatsappPackage') { const url = '/instances/:botId/whatsapp'; server.post(url, (req, res) => { - p.channel.received(req, res); + p['channel'].received(req, res); }); } }, this); @@ -405,7 +405,7 @@ export class GBMinService { await min.userProfile.set(step.context, user); } - logger.info( + GBLog.info( `User>: ${context.activity.text} (${context.activity.type}, ${context.activity.name}, ${ context.activity.channelId }, {context.activity.value})` @@ -413,7 +413,7 @@ export class GBMinService { if (context.activity.type === 'conversationUpdate' && context.activity.membersAdded.length > 0) { const member = context.activity.membersAdded[0]; if (member.name === 'GeneralBots') { - logger.info(`Bot added to conversation, starting chat...`); + GBLog.info(`Bot added to conversation, starting chat...`); appPackages.forEach(e => { e.onNewSession(min, step); }); @@ -421,7 +421,7 @@ export class GBMinService { await step.beginDialog('/'); } else { - logger.info(`Member added to conversation: ${member.name}`); + GBLog.info(`Member added to conversation: ${member.name}`); } // Processes messages. @@ -440,7 +440,7 @@ export class GBMinService { await conversationState.saveChanges(context, true); } catch (error) { const msg = `ERROR: ${error.message} ${error.stack ? error.stack : ''}`; - logger.error(msg); + GBLog.error(msg); await step.context.sendActivity(Messages[step.context.activity.locale].very_sorry_about_error); await step.beginDialog('/ask', { isReturning: true }); @@ -448,7 +448,7 @@ export class GBMinService { }); } - private async processEventActivity(context, step: any) { + private async processEventActivity(context, step: GBDialogStep) { if (context.activity.name === 'whoAmI') { await step.beginDialog('/whoAmI'); } else if (context.activity.name === 'showSubjects') { @@ -476,7 +476,7 @@ export class GBMinService { } } - private async processMessageActivity(context, min: GBMinInstance, step: any) { + private async processMessageActivity(context, min: GBMinInstance, step: GBDialogStep) { // Direct script invoking by itent name. const isVMCall = Object.keys(min.scriptMap).find(key => min.scriptMap[key] === context.activity.text) !== undefined; diff --git a/packages/core.gbapp/services/GBVMService.ts b/packages/core.gbapp/services/GBVMService.ts index 8690a607..35e477c8 100644 --- a/packages/core.gbapp/services/GBVMService.ts +++ b/packages/core.gbapp/services/GBVMService.ts @@ -33,20 +33,19 @@ 'use strict'; import { WaterfallDialog } from 'botbuilder-dialogs'; -import { GBMinInstance, GBService, IGBCoreService } from 'botlib'; +import { GBLog, GBMinInstance, GBService, IGBCoreService } from 'botlib'; import * as fs from 'fs'; -import GBAPIService from './GBAPIService'; -import GBAPIService from './GBAPIService'; import { GBDeployer } from './GBDeployer'; import { TSCompiler } from './TSCompiler'; const walkPromise = require('walk-promise'); -const logger = require('../../../src/logger'); + const vm = require('vm'); const UrlJoin = require('url-join'); const vb2ts = require('vbscript-to-typescript/dist/converter'); const beautify = require('js-beautify').js; + /** * @fileoverview Virtualization services for emulation of BASIC. * This alpha version is using a hack in form of converter to @@ -220,7 +219,7 @@ export class GBVMService extends GBService { vm.runInContext(parsedCode, context); min.sandBoxMap[mainName] = sandbox; await deployer.deployScriptToStorage(1, filename); // TODO: Per bot storage. - logger.info(`[GBVMService] Finished loading of ${filename}`); + GBLog.info(`[GBVMService] Finished loading of ${filename}`); } } @@ -260,7 +259,7 @@ export class GBVMService extends GBService { const cbId = step.activeDialog.state.cbId; const cb = min.cbMap[cbId]; - cb.bind({ step: step, context: step.context }); // TODO: Necessary or min.sandbox? + cb.bind({ step: step: GBDialogStep, context: step.context }); // TODO: Necessary or min.sandbox? await step.endDialog(); diff --git a/packages/core.gbapp/services/TSCompiler.ts b/packages/core.gbapp/services/TSCompiler.ts index 942e82b0..c1cc88da 100644 --- a/packages/core.gbapp/services/TSCompiler.ts +++ b/packages/core.gbapp/services/TSCompiler.ts @@ -37,7 +37,7 @@ 'use strict'; import * as ts from 'typescript'; -const logger = require('../../../src/logger'); + export class TSCompiler { @@ -77,9 +77,9 @@ export class TSCompiler { if (diagnostic.file) { const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); - logger.error(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); + GBLog.error(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); } else { - logger.error(`${message}`); + GBLog.error(`${message}`); } } }); diff --git a/packages/customer-satisfaction.gbapp/dialogs/FeedbackDialog.ts b/packages/customer-satisfaction.gbapp/dialogs/FeedbackDialog.ts index e66d26e7..96cdd6e7 100644 --- a/packages/customer-satisfaction.gbapp/dialogs/FeedbackDialog.ts +++ b/packages/customer-satisfaction.gbapp/dialogs/FeedbackDialog.ts @@ -86,7 +86,7 @@ export class FeedbackDialog extends IGBDialog { const locale = step.context.activity.locale; await step.context.sendActivity(Messages[locale].about_suggestions); - step.activeDialog.state.cbId = step.options.id; + step.activeDialog.state.cbId = step.options['id']; return await step.prompt('textPrompt', Messages[locale].what_about_service); }, diff --git a/packages/customer-satisfaction.gbapp/dialogs/QualityDialog.ts b/packages/customer-satisfaction.gbapp/dialogs/QualityDialog.ts index 186259fe..21b8bc01 100644 --- a/packages/customer-satisfaction.gbapp/dialogs/QualityDialog.ts +++ b/packages/customer-satisfaction.gbapp/dialogs/QualityDialog.ts @@ -43,7 +43,7 @@ import { WaterfallDialog } from 'botbuilder-dialogs'; import { GBMinInstance } from 'botlib'; import { CSService } from '../services/CSService'; import { Messages } from '../strings'; -const logger = require('../../../src/logger'); + export class QualityDialog extends IGBDialog { /** @@ -63,7 +63,7 @@ export class QualityDialog extends IGBDialog { const score = step.result; setTimeout( - () => min.conversationalService.sendEvent(step, 'stop', null), + () => min.conversationalService.sendEvent(step: GBDialogStep, 'stop', null), 400 ); diff --git a/packages/customer-satisfaction.gbapp/index.ts b/packages/customer-satisfaction.gbapp/index.ts index 33782cf6..42898ba7 100644 --- a/packages/customer-satisfaction.gbapp/index.ts +++ b/packages/customer-satisfaction.gbapp/index.ts @@ -57,5 +57,5 @@ export class GBCustomerSatisfactionPackage implements IGBPackage { QualityDialog.setup(min.bot, min); } public unloadBot(min: GBMinInstance): void {} - public onNewSession(min: GBMinInstance, step: any): void {} + public onNewSession(min: GBMinInstance, step: GBDialogStep): void {} } diff --git a/packages/kb.gbapp/dialogs/AskDialog.ts b/packages/kb.gbapp/dialogs/AskDialog.ts index f517a96c..fc95465d 100644 --- a/packages/kb.gbapp/dialogs/AskDialog.ts +++ b/packages/kb.gbapp/dialogs/AskDialog.ts @@ -44,7 +44,7 @@ import { AzureText } from 'pragmatismo-io-framework'; import { Messages } from '../strings'; import { KBService } from './../services/KBService'; -const logger = require('../../../src/logger'); + export class AskDialog extends IGBDialog { /** @@ -65,7 +65,7 @@ export class AskDialog extends IGBDialog { // Sends the answer to all outputs, including projector. - await service.sendAnswer(min.conversationalService, step, answer); + await service.sendAnswer(min.conversationalService, step: GBDialogStep, answer); await step.replaceDialog('/ask', { isReturning: true }); } @@ -88,7 +88,7 @@ export class AskDialog extends IGBDialog { // Stops any content on projector. - await min.conversationalService.sendEvent(step, 'stop', null); + await min.conversationalService.sendEvent(step: GBDialogStep, 'stop', null); // Handle extra text from FAQ. @@ -104,7 +104,7 @@ export class AskDialog extends IGBDialog { const data = await AzureText.getSpelledText(min.instance.spellcheckerKey, text); if (data != text) { - logger.info(`Spelling corrected: ${data}`); + GBLog.info(`Spelling corrected: ${data}`); text = data; } } @@ -126,7 +126,7 @@ export class AskDialog extends IGBDialog { // Sends the answer to all outputs, including projector. - await service.sendAnswer(min.conversationalService, step, resultsA.answer); + await service.sendAnswer(min.conversationalService, step: GBDialogStep, resultsA.answer); // Goes to ask loop, again. @@ -155,11 +155,11 @@ export class AskDialog extends IGBDialog { // Sends the answer to all outputs, including projector. - await service.sendAnswer(min.conversationalService, step, resultsB.answer); + await service.sendAnswer(min.conversationalService, step: GBDialogStep, resultsB.answer); return await step.replaceDialog('/ask', { isReturning: true }); } else { - if (!(await min.conversationalService.routeNLP(step, min, text))) { + if (!(await min.conversationalService.routeNLP(step: GBDialogStep, min, text))) { await step.context.sendActivity(Messages[locale].did_not_find); return await step.replaceDialog('/ask', { isReturning: true }); diff --git a/packages/kb.gbapp/dialogs/FaqDialog.ts b/packages/kb.gbapp/dialogs/FaqDialog.ts index 142a0c14..f837e4cd 100644 --- a/packages/kb.gbapp/dialogs/FaqDialog.ts +++ b/packages/kb.gbapp/dialogs/FaqDialog.ts @@ -59,12 +59,13 @@ export class FaqDialog extends IGBDialog { const data = await service.getFaqBySubjectArray('faq', null); const locale = step.context.activity.locale; if (data) { - await min.conversationalService.sendEvent(step, 'play', { + await min.conversationalService.sendEvent(step: GBDialogStep, 'play', { playerType: 'bullet', data: data.slice(0, 10) }); - await step.context.sendActivity(Messages[locale].see_faq); + await step.context.sendActivity(Messages[locale].see_faq); + return await step.next(); } } diff --git a/packages/kb.gbapp/dialogs/MenuDialog.ts b/packages/kb.gbapp/dialogs/MenuDialog.ts index 0d34eaa5..6505ccfe 100644 --- a/packages/kb.gbapp/dialogs/MenuDialog.ts +++ b/packages/kb.gbapp/dialogs/MenuDialog.ts @@ -89,7 +89,7 @@ export class MenuDialog extends IGBDialog { 'menu', user.subjects ); - await min.conversationalService.sendEvent(step, 'play', { + await min.conversationalService.sendEvent(step: GBDialogStep, 'play', { playerType: 'bullet', data: data.slice(0, 10) }); diff --git a/packages/kb.gbapp/index.ts b/packages/kb.gbapp/index.ts index 9eba17b8..4f5af31a 100644 --- a/packages/kb.gbapp/index.ts +++ b/packages/kb.gbapp/index.ts @@ -61,5 +61,5 @@ export class GBKBPackage implements IGBPackage { MenuDialog.setup(min.bot, min); } public unloadBot(min: GBMinInstance): void {} - public onNewSession(min: GBMinInstance, step: any): void {} + public onNewSession(min: GBMinInstance, step: GBDialogStep): void {} } diff --git a/packages/kb.gbapp/services/KBService.ts b/packages/kb.gbapp/services/KBService.ts index c81113d6..c6ceda5d 100644 --- a/packages/kb.gbapp/services/KBService.ts +++ b/packages/kb.gbapp/services/KBService.ts @@ -34,7 +34,7 @@ * @fileoverview Knowledge base services and logic. */ -const logger = require('../../../src/logger'); + const Path = require('path'); const Fs = require('fs'); @@ -276,7 +276,7 @@ export class KBService { answer = Fs.readFileSync(mediaFilename, 'utf8'); format = '.md'; } else { - logger.info(`[GBImporter] File not found: ${mediaFilename}.`); + GBLog.info(`[GBImporter] File not found: ${mediaFilename}.`); answer = ''; } } @@ -341,9 +341,9 @@ export class KBService { }); } - public async sendAnswer(conversationalService: IGBConversationalService, step: any, answer: GuaribasAnswer) { + public async sendAnswer(conversationalService: IGBConversationalService, step: GBDialogStep, answer: GuaribasAnswer) { if (answer.content.endsWith('.mp4')) { - await conversationalService.sendEvent(step, 'play', { + await conversationalService.sendEvent(step: GBDialogStep, 'play', { playerType: 'video', data: answer.content }); @@ -367,7 +367,7 @@ export class KBService { }); html = marked(answer.content); } - await conversationalService.sendEvent(step, 'play', { + await conversationalService.sendEvent(step: GBDialogStep, 'play', { playerType: 'markdown', data: { content: html, @@ -378,7 +378,7 @@ export class KBService { }); } else { await step.context.sendActivity(answer.content); - await conversationalService.sendEvent(step, 'stop', null); + await conversationalService.sendEvent(step: GBDialogStep, 'stop', null); } } @@ -462,15 +462,15 @@ export class KBService { public async deployKb(core: IGBCoreService, deployer: GBDeployer, localPath: string) { const packageType = Path.extname(localPath); const packageName = Path.basename(localPath); - logger.info(`[GBDeployer] Opening package: ${localPath}`); + GBLog.info(`[GBDeployer] Opening package: ${localPath}`); const packageObject = JSON.parse(Fs.readFileSync(UrlJoin(localPath, 'package.json'), 'utf8')); const instance = await core.loadInstance(packageObject.botId); - logger.info(`[GBDeployer] Importing: ${localPath}`); + GBLog.info(`[GBDeployer] Importing: ${localPath}`); const p = await deployer.deployPackageToStorage(instance.instanceId, packageName); await this.importKbPackage(localPath, p, instance); deployer.rebuildIndex(instance, new AzureDeployerService(deployer).getKBSearchSchema(instance.searchIndex)); - logger.info(`[GBDeployer] Finished import of ${localPath}`); + GBLog.info(`[GBDeployer] Finished import of ${localPath}`); } } diff --git a/packages/security.gblib/index.ts b/packages/security.gblib/index.ts index 0ae9674a..12133320 100644 --- a/packages/security.gblib/index.ts +++ b/packages/security.gblib/index.ts @@ -56,5 +56,5 @@ export class GBSecurityPackage implements IGBPackage { public loadBot(min: GBMinInstance): void {} public unloadBot(min: GBMinInstance): void {} - public onNewSession(min: GBMinInstance, step: any): void {} + public onNewSession(min: GBMinInstance, step: GBDialogStep): void {} } diff --git a/packages/whatsapp.gblib/index.ts b/packages/whatsapp.gblib/index.ts index 4f06006e..6a0ca8a9 100644 --- a/packages/whatsapp.gblib/index.ts +++ b/packages/whatsapp.gblib/index.ts @@ -69,5 +69,5 @@ export class GBWhatsappPackage implements IGBPackage { } public unloadBot(min: GBMinInstance): void {} - public onNewSession(min: GBMinInstance, step: any): void {} + public onNewSession(min: GBMinInstance, step: GBDialogStep): void {} } diff --git a/packages/whatsapp.gblib/services/WhatsappDirectLine.ts b/packages/whatsapp.gblib/services/WhatsappDirectLine.ts index 4c5506a6..befb941c 100644 --- a/packages/whatsapp.gblib/services/WhatsappDirectLine.ts +++ b/packages/whatsapp.gblib/services/WhatsappDirectLine.ts @@ -1,5 +1,5 @@ const UrlJoin = require('url-join'); -const logger = require('../../../src/logger'); + const Swagger = require('swagger-client'); const rp = require('request-promise'); import { GBService } from 'botlib'; @@ -65,15 +65,15 @@ export class WhatsappDirectLine extends GBService { try { const result = await request.post(options); - logger.info(result); + GBLog.info(result); } catch (error) { - logger.error('Error initializing 3rd party Whatsapp provider.', error); + GBLog.error('Error initializing 3rd party Whatsapp provider.', error); } return client; }) .catch(err => { - logger.error('Error initializing DirectLine client', err); + GBLog.error('Error initializing DirectLine client', err); }); } @@ -86,13 +86,13 @@ export class WhatsappDirectLine extends GBService { return; // Exit here. } - logger.info(`GBWhatsapp: Hook called. from: ${from}(${fromName}), text: ${text})`); + GBLog.info(`GBWhatsapp: Hook called. from: ${from}(${fromName}), text: ${text})`); const conversationId = this.conversationIds[from]; this.directLineClient.then(client => { if (this.conversationIds[from] == undefined) { - logger.info(`GBWhatsapp: Starting new conversation on Bot.`); + GBLog.info(`GBWhatsapp: Starting new conversation on Bot.`); client.Conversations.Conversations_StartConversation() .then(response => { return response.obj.conversationId; @@ -127,12 +127,12 @@ export class WhatsappDirectLine extends GBService { replyToId: from } }).catch(err => { - logger.error(`GBWhatsapp: Error receiving message: ${err}.`); + GBLog.error(`GBWhatsapp: Error receiving message: ${err}.`); }); } public pollMessages(client, conversationId, from, fromName) { - logger.info(`GBWhatsapp: Starting polling message for conversationId: + GBLog.info(`GBWhatsapp: Starting polling message for conversationId: ${conversationId}.`); setInterval(() => { @@ -171,7 +171,7 @@ export class WhatsappDirectLine extends GBService { let output = ''; if (activity.text) { - logger.info(`GBWhatsapp: MSG: ${activity.text}`); + GBLog.info(`GBWhatsapp: MSG: ${activity.text}`); output = activity.text; } @@ -183,7 +183,7 @@ export class WhatsappDirectLine extends GBService { break; case 'image/png': - logger.info('Opening the requested image ' + attachment.contentUrl); + GBLog.info('Opening the requested image ' + attachment.contentUrl); output += `\n${attachment.contentUrl}`; break; } diff --git a/src/app.ts b/src/app.ts index 7a1750fd..3f913f5e 100644 --- a/src/app.ts +++ b/src/app.ts @@ -62,7 +62,7 @@ export class GBServer { */ public static run() { - logger.info(`The Bot Server is in STARTING mode...`); + GBLog.info(`The Bot Server is in STARTING mode...`); // Creates a basic HTTP server that will serve several URL, one for each // bot instance. This allows the same server to attend multiple Bot on @@ -83,7 +83,7 @@ export class GBServer { server.listen(port, () => { (async () => { try { - logger.info(`Now accepting connections on ${port}...`); + GBLog.info(`Now accepting connections on ${port}...`); // Reads basic configuration, initialize minimal services. @@ -98,7 +98,7 @@ export class GBServer { // Ensure that local development proxy is setup. - logger.info(`Establishing a development local proxy (ngrok)...`); + GBLog.info(`Establishing a development local proxy (ngrok)...`); const proxyAddress: string = await core.ensureProxy(port); // Creates a boot instance or load it from storage. @@ -115,14 +115,14 @@ export class GBServer { // Deploys system and user packages. - logger.info(`Deploying packages...`); + GBLog.info(`Deploying packages...`); core.loadSysPackages(core); await core.checkStorage(azureDeployer); await deployer.deployPackages(core, server, appPackages); // Loads all bot instances. - logger.info(`Publishing instances...`); + GBLog.info(`Publishing instances...`); const packageInstance = await importer.importIfNotExistsBotPackage( GBConfigService.get('CLOUD_GROUP'), 'boot.gbot', @@ -145,13 +145,13 @@ export class GBServer { deployer.runOnce(); - logger.info(`The Bot Server is in RUNNING mode...`); + GBLog.info(`The Bot Server is in RUNNING mode...`); // Opens Navigator. core.openBrowserInDevelopment(); } catch (err) { - logger.error(`STOP: ${err} ${err.stack ? err.stack : ''}`); + GBLog.error(`STOP: ${err} ${err.stack ? err.stack : ''}`); process.exit(1); } })(); diff --git a/src/logger.ts b/src/logger.ts deleted file mode 100644 index ee201a78..00000000 --- a/src/logger.ts +++ /dev/null @@ -1,76 +0,0 @@ -/*****************************************************************************\ -| ( )_ _ | -| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ | -| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ | -| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) | -| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' | -| | | ( )_) | | -| (_) \___/' | -| | -| General Bots Copyright (c) Pragmatismo.io. All rights reserved. | -| Licensed under the AGPL-3.0. | -| | -| According to our dual licensing model, this program can be used either | -| under the terms of the GNU Affero General Public License, version 3, | -| or under a proprietary license. | -| | -| The texts of the GNU Affero General Public License with an additional | -| permission and of our proprietary license can be found at and | -| in the LICENSE file you have received along with this program. | -| | -| This program is distributed in the hope that it will be useful, | -| but WITHOUT ANY WARRANTY, without even the implied warranty of | -| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -| GNU Affero General Public License for more details. | -| | -| "General Bots" is a registered trademark of Pragmatismo.io. | -| The licensing of the program under the AGPLv3 does not imply a | -| trademark license. Therefore any rights, title and interest in | -| our trademarks remain entirely with us. | -| | -\*****************************************************************************/ - -/** - * @fileoverview Logging support. - */ - -const { createLogger, format, transports } = require('winston'); - -const config = { - levels: { - error: 0, - debug: 1, - warn: 2, - data: 3, - info: 4, - verbose: 5, - silly: 6, - custom: 7 - }, - colors: { - error: 'red', - debug: 'blue', - warn: 'yellow', - data: 'grey', - info: 'green', - verbose: 'cyan', - silly: 'magenta', - custom: 'yellow' - } -}; - -const logger = createLogger({ - format: format.combine( - format.colorize(), - format.simple(), - format.label({ label: 'GeneralBots' }), - format.timestamp(), - format.printf(nfo => { - return `${nfo.timestamp} [${nfo.label}] ${nfo.level}: ${nfo.message}`; - }) - ), - levels: config.levels, - transports: [new transports.Console()] -}); - -module.exports = logger; diff --git a/tslint.json b/tslint.json index 3ed5212b..7480486c 100644 --- a/tslint.json +++ b/tslint.json @@ -1,43 +1,40 @@ { - "defaultSeverity": "warning", - "extends": [ - "tslint:recommended", - "tslint-microsoft-contrib" - ], - "linterOptions": { - "exclude":[ - "libraries/botframework-connector/src/generated/**/*", - "libraries/botframework-schema/**/*" - ] - }, - "rulesDirectory": [ - "node_modules/tslint-microsoft-contrib" - ], - "jsRules": {}, - "rules": { - "no-floating-promises": false, - "no-var-requires":false, - "typedef":false, - "variable-name": false, - "no-parameter-properties": false, - "no-reserved-keywords": false, - "no-unnecessary-class":false, - "no-require-imports": false, - "function-name": false, - "no-redundant-jsdoc": false, - "no-return-await": false, - "prefer-type-cast": false, - "no-object-literal-type-assertion":false, - "no-increment-decrement":false, - "no-any":false, - "interface-name":false, - "no-this-assignment":false, - "switch-final-break":false, - "no-parameter-reassignment":false, - "export-name":false, - "no-relative-imports": false, - "no-backbone-get-set-outside-model": false, - "max-line-length": [true,{"limit":120,"ignore-pattern":"^\\s+\\*"}], - "await-promise": [true, "Bluebird"] - } + "defaultSeverity": "warning", + "extends": ["tslint:recommended", "tslint-microsoft-contrib"], + "linterOptions": { + "exclude": [ + "libraries/botframework-connector/src/generated/**/*", + "libraries/botframework-schema/**/*", + "./packages/default.gbui/**/*", + "./packages/**/*.gbdialog" + ] + }, + "rulesDirectory": ["node_modules/tslint-microsoft-contrib"], + "jsRules": {}, + "rules": { + "no-floating-promises": false, + "no-var-requires": false, + "typedef": false, + "variable-name": false, + "no-parameter-properties": false, + "no-reserved-keywords": false, + "no-unnecessary-class": false, + "no-require-imports": false, + "function-name": false, + "no-redundant-jsdoc": false, + "no-return-await": false, + "prefer-type-cast": false, + "no-object-literal-type-assertion": false, + "no-increment-decrement": false, + "no-any": false, + "interface-name": false, + "no-this-assignment": false, + "switch-final-break": false, + "no-parameter-reassignment": false, + "export-name": false, + "no-relative-imports": false, + "no-backbone-get-set-outside-model": false, + "max-line-length": [true, { "limit": 120, "ignore-pattern": "^\\s+\\*" }], + "await-promise": [true, "Bluebird"] + } }