Removal of semicolon.

This commit is contained in:
Rodrigo Rodriguez 2018-09-11 19:40:53 -03:00
parent d07b6350a0
commit 576b9581ab
34 changed files with 1016 additions and 1016 deletions

View file

@ -106,9 +106,9 @@ export class AdminDialog extends IGBDialog {
await dc.context.sendActivity(`Deploying package ... (It may take a few seconds)`) await dc.context.sendActivity(`Deploying package ... (It may take a few seconds)`)
await AdminDialog.deployPackageCommand("deployPackage ProjectOnline.gbkb", dc, deployer, min) await AdminDialog.deployPackageCommand("deployPackage ProjectOnline.gbkb", dc, deployer, min)
await dc.endAll(); await dc.endAll()
}]); }])
min.dialogs.add("/admin1", [ min.dialogs.add("/admin1", [
@ -141,7 +141,7 @@ export class AdminDialog extends IGBDialog {
user.authenticated = false user.authenticated = false
await dc.replace("/") await dc.replace("/")
} else if (text === "sync") { } else if (text === "sync") {
await min.core.syncDatabaseStructure(); await min.core.syncDatabaseStructure()
await dc.context.sendActivity("Sync started...") await dc.context.sendActivity("Sync started...")
await dc.replace("/admin", { firstRun: false }) await dc.replace("/admin", { firstRun: false })
} else if (text.split(" ")[0] === "rebuildIndex") { } else if (text.split(" ")[0] === "rebuildIndex") {
@ -160,7 +160,7 @@ export class AdminDialog extends IGBDialog {
await dc.replace("/admin", { firstRun: false }) await dc.replace("/admin", { firstRun: false })
} else if (text.split(" ")[0] === "applyPackage") { } else if (text.split(" ")[0] === "applyPackage") {
await dc.context.sendActivity("Applying in progress...") await dc.context.sendActivity("Applying in progress...")
await min.core.loadInstance(text.split(" ")[1]); await min.core.loadInstance(text.split(" ")[1])
await dc.context.sendActivity("Applying done...") await dc.context.sendActivity("Applying done...")
await dc.replace("/admin", { firstRun: false }) await dc.replace("/admin", { firstRun: false })
} else if (text.split(" ")[0] === "rat") { } else if (text.split(" ")[0] === "rat") {

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,17 +30,17 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
'use strict'; 'use strict'
const UrlJoin = require('url-join'); const UrlJoin = require('url-join')
import { AdminDialog } from './dialogs/AdminDialog'; import { AdminDialog } from './dialogs/AdminDialog'
import { GBMinInstance, IGBPackage, IGBCoreService } from 'botlib'; import { GBMinInstance, IGBPackage, IGBCoreService } from 'botlib'
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript'
export class GBAdminPackage implements IGBPackage { export class GBAdminPackage implements IGBPackage {
sysPackages: IGBPackage[] = null; sysPackages: IGBPackage[] = null
loadPackage(core: IGBCoreService, sequelize: Sequelize): void { loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
} }
@ -49,7 +49,7 @@ export class GBAdminPackage implements IGBPackage {
} }
loadBot(min: GBMinInstance): void { loadBot(min: GBMinInstance): void {
AdminDialog.setup(min.bot, min); AdminDialog.setup(min.bot, min)
} }
unloadBot(min: GBMinInstance): void { unloadBot(min: GBMinInstance): void {

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,19 +30,19 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"; import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"
import { Sequelize } from "sequelize-typescript"; import { Sequelize } from "sequelize-typescript"
export class GBAnalyticsPackage implements IGBPackage { export class GBAnalyticsPackage implements IGBPackage {
sysPackages: IGBPackage[] = null; sysPackages: IGBPackage[] = null
loadPackage(core: IGBCoreService, sequelize: Sequelize): void { loadPackage(core: IGBCoreService, sequelize: Sequelize): void {

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,14 +30,14 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
import { import {
DataTypes, DataTypes,
DataTypeUUIDv4, DataTypeUUIDv4,
DataTypeDate, DataTypeDate,
DataTypeDecimal DataTypeDecimal
} from "sequelize"; } from "sequelize"
import { import {
Sequelize, Sequelize,
@ -55,11 +55,11 @@ import {
IsUUID, IsUUID,
PrimaryKey, PrimaryKey,
AutoIncrement AutoIncrement
} from "sequelize-typescript"; } from "sequelize-typescript"
import { GuaribasSubject } from "../../kb.gbapp/models"; import { GuaribasSubject } from "../../kb.gbapp/models"
import { GuaribasUser } from "../../security.gblib/models"; import { GuaribasUser } from "../../security.gblib/models"
import { GuaribasChannel, GuaribasInstance } from "../../core.gbapp/models/GBModel"; import { GuaribasChannel, GuaribasInstance } from "../../core.gbapp/models/GBModel"
@Table @Table
export class GuaribasConversation extends Model<GuaribasConversation> { export class GuaribasConversation extends Model<GuaribasConversation> {
@ -67,40 +67,40 @@ export class GuaribasConversation extends Model<GuaribasConversation> {
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
conversationId: number; conversationId: number
@ForeignKey(() => GuaribasSubject) @ForeignKey(() => GuaribasSubject)
@Column @Column
startSubjectId: number; startSubjectId: number
@BelongsTo(() => GuaribasSubject) @BelongsTo(() => GuaribasSubject)
startSubject: GuaribasSubject; startSubject: GuaribasSubject
@ForeignKey(() => GuaribasChannel) @ForeignKey(() => GuaribasChannel)
@Column @Column
channelId: string; channelId: string
@Column rateDate: Date; @Column rateDate: Date
@Column(DataType.FLOAT) @Column(DataType.FLOAT)
@Column @Column
rate: number; rate: number
@Column @Column
@CreatedAt @CreatedAt
createdAt: Date; createdAt: Date
@Column text: string; @Column text: string
@HasMany(() => GuaribasConversationMessage) @HasMany(() => GuaribasConversationMessage)
conversationMessage: GuaribasConversationMessage[]; conversationMessage: GuaribasConversationMessage[]
@ForeignKey(() => GuaribasUser) @ForeignKey(() => GuaribasUser)
@Column @Column
startedByUserId: number; startedByUserId: number
@BelongsTo(() => GuaribasUser) @BelongsTo(() => GuaribasUser)
startedBy: GuaribasUser; startedBy: GuaribasUser
} }
@Table @Table
@ -109,38 +109,38 @@ export class GuaribasConversationMessage extends Model<GuaribasConversationMessa
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
conversationMessageId: number; conversationMessageId: number
@ForeignKey(() => GuaribasSubject) @ForeignKey(() => GuaribasSubject)
@Column @Column
subjectId: number; subjectId: number
@Column(DataType.TEXT) @Column(DataType.TEXT)
content: string; content: string
@Column @Column
@CreatedAt @CreatedAt
createdAt: Date; createdAt: Date
@Column @Column
@UpdatedAt @UpdatedAt
updatedAt: Date; updatedAt: Date
@ForeignKey(() => GuaribasConversation) @ForeignKey(() => GuaribasConversation)
@Column @Column
conversationId: number; conversationId: number
@BelongsTo(() => GuaribasConversation) @BelongsTo(() => GuaribasConversation)
conversation: GuaribasConversation; conversation: GuaribasConversation
@ForeignKey(() => GuaribasInstance) @ForeignKey(() => GuaribasInstance)
@Column @Column
instanceId: number; instanceId: number
@ForeignKey(() => GuaribasUser) @ForeignKey(() => GuaribasUser)
@Column @Column
userId: number; userId: number
@BelongsTo(() => GuaribasUser) @BelongsTo(() => GuaribasUser)
user: GuaribasUser; user: GuaribasUser
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,8 +30,8 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
import { GuaribasUser } from "../../security.gblib/models"; import { GuaribasUser } from "../../security.gblib/models"
import { GuaribasConversation, GuaribasConversationMessage } from "../models"; import { GuaribasConversation, GuaribasConversationMessage } from "../models"
export class AnalyticsService { export class AnalyticsService {
async createConversation( async createConversation(
@ -39,13 +39,13 @@ export class AnalyticsService {
): Promise<GuaribasConversation> { ): Promise<GuaribasConversation> {
return new Promise<GuaribasConversation>( return new Promise<GuaribasConversation>(
(resolve, reject) => { (resolve, reject) => {
let conversation = new GuaribasConversation(); let conversation = new GuaribasConversation()
conversation.startedBy = user; conversation.startedBy = user
conversation.startedByUserId = user.userId; conversation.startedByUserId = user.userId
conversation.save().then((value: GuaribasConversation) => { conversation.save().then((value: GuaribasConversation) => {
resolve(value); resolve(value)
}); })
}); })
} }
createMessage( createMessage(
@ -55,13 +55,13 @@ export class AnalyticsService {
): Promise<GuaribasConversationMessage> { ): Promise<GuaribasConversationMessage> {
return new Promise<GuaribasConversationMessage>( return new Promise<GuaribasConversationMessage>(
(resolve, reject) => { (resolve, reject) => {
let message = GuaribasConversationMessage.build(); let message = GuaribasConversationMessage.build()
message.conversation = conversation; message.conversation = conversation
message.user = user; message.user = user
message.content = content; message.content = content
message.save().then((value: GuaribasConversationMessage) => { message.save().then((value: GuaribasConversationMessage) => {
resolve(value); resolve(value)
}); })
}); })
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,18 +30,18 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"; import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript'
import { ConsoleDirectLine } from "./services/ConsoleDirectLine"; import { ConsoleDirectLine } from "./services/ConsoleDirectLine"
export class GBConsolePackage implements IGBPackage { export class GBConsolePackage implements IGBPackage {
sysPackages: IGBPackage[] = null; sysPackages: IGBPackage[] = null
channel: ConsoleDirectLine; channel: ConsoleDirectLine
loadPackage(core: IGBCoreService, sequelize: Sequelize): void { loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
} }
@ -50,7 +50,7 @@ export class GBConsolePackage implements IGBPackage {
} }
loadBot(min: GBMinInstance): void { loadBot(min: GBMinInstance): void {
this.channel = new ConsoleDirectLine(min.instance.webchatKey); this.channel = new ConsoleDirectLine(min.instance.webchatKey)
} }
unloadBot(min: GBMinInstance): void { unloadBot(min: GBMinInstance): void {

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,29 +30,29 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
const Path = require("path"); const Path = require("path")
const Fs = require("fs"); const Fs = require("fs")
const _ = require("lodash"); const _ = require("lodash")
const Parse = require("csv-parse"); const Parse = require("csv-parse")
const Async = require("async"); const Async = require("async")
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
const Walk = require("fs-walk"); const Walk = require("fs-walk")
const logger = require("../../../src/logger"); const logger = require("../../../src/logger")
const Swagger = require('swagger-client'); const Swagger = require('swagger-client')
const rp = require('request-promise'); const rp = require('request-promise')
import { GBService } from "botlib"; import { GBService } from "botlib"
export class ConsoleDirectLine extends GBService { export class ConsoleDirectLine extends GBService {
pollInterval = 1000; pollInterval = 1000
directLineSecret = ''; directLineSecret = ''
directLineClientName = 'DirectLineClient'; directLineClientName = 'DirectLineClient'
directLineSpecUrl = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json'; directLineSpecUrl = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json'
constructor(directLineSecret) { constructor(directLineSecret) {
super(); super()
this.directLineSecret = directLineSecret; this.directLineSecret = directLineSecret
// TODO: Migrate to Swagger 3. // TODO: Migrate to Swagger 3.
@ -61,45 +61,45 @@ export class ConsoleDirectLine extends GBService {
return new Swagger({ return new Swagger({
spec: JSON.parse(spec.trim()), spec: JSON.parse(spec.trim()),
usePromise: true usePromise: true
}); })
}) })
.then(function (client) { .then(function (client) {
client.clientAuthorizations.add('AuthorizationBotConnector', client.clientAuthorizations.add('AuthorizationBotConnector',
new Swagger.ApiKeyAuthorization('Authorization', 'Bearer ' + directLineSecret, 'header')); new Swagger.ApiKeyAuthorization('Authorization', 'Bearer ' + directLineSecret, 'header'))
return client; return client
}) })
.catch(function (err) { .catch(function (err) {
console.error('Error initializing DirectLine client', err); console.error('Error initializing DirectLine client', err)
}); })
// TODO: Remove *this* issue. // TODO: Remove *this* issue.
let _this_ = this; let _this_ = this
directLineClient.then((client)=> { directLineClient.then((client)=> {
client.Conversations.Conversations_StartConversation() client.Conversations.Conversations_StartConversation()
.then(function (response) { .then(function (response) {
return response.obj.conversationId; return response.obj.conversationId
}) })
.then(function (conversationId) { .then(function (conversationId) {
_this_.sendMessagesFromConsole(client, conversationId); _this_.sendMessagesFromConsole(client, conversationId)
_this_.pollMessages(client, conversationId); _this_.pollMessages(client, conversationId)
}) })
.catch(function (err) { .catch(function (err) {
console.error('Error starting conversation', err); console.error('Error starting conversation', err)
}); })
}); })
} }
sendMessagesFromConsole(client, conversationId) { sendMessagesFromConsole(client, conversationId) {
let _this_ = this; let _this_ = this
process.stdin.resume(); process.stdin.resume()
var stdin = process.stdin; var stdin = process.stdin
process.stdout.write('Command> '); process.stdout.write('Command> ')
stdin.addListener('data', function (e) { stdin.addListener('data', function (e) {
var input = e.toString().trim(); var input = e.toString().trim()
if (input) { if (input) {
// exit // exit
if (input.toLowerCase() === 'exit') { if (input.toLowerCase() === 'exit') {
return process.exit(); return process.exit()
} }
client.Conversations.Conversations_PostActivity( client.Conversations.Conversations_PostActivity(
@ -115,80 +115,80 @@ export class ConsoleDirectLine extends GBService {
} }
} }
}).catch(function (err) { }).catch(function (err) {
console.error('Error sending message:', err); console.error('Error sending message:', err)
}); })
process.stdout.write('Command> '); process.stdout.write('Command> ')
} }
}); })
} }
/** TBD: Poll Messages from conversation using DirectLine client */ /** TBD: Poll Messages from conversation using DirectLine client */
pollMessages(client, conversationId) { pollMessages(client, conversationId) {
let _this_ = this; let _this_ = this
console.log('Starting polling message for conversationId: ' + conversationId); console.log('Starting polling message for conversationId: ' + conversationId)
var watermark = null; var watermark = null
setInterval(function () { setInterval(function () {
client.Conversations.Conversations_GetActivities({ conversationId: conversationId, watermark: watermark }) client.Conversations.Conversations_GetActivities({ conversationId: conversationId, watermark: watermark })
.then(function (response) { .then(function (response) {
watermark = response.obj.watermark; // use watermark so subsequent requests skip old messages watermark = response.obj.watermark // use watermark so subsequent requests skip old messages
return response.obj.activities; return response.obj.activities
}) })
.then(_this_.printMessages, _this_.directLineClientName); .then(_this_.printMessages, _this_.directLineClientName)
}, this.pollInterval); }, this.pollInterval)
} }
printMessages(activities, directLineClientName) { printMessages(activities, directLineClientName) {
if (activities && activities.length) { if (activities && activities.length) {
// ignore own messages // ignore own messages
activities = activities.filter(function (m) { return m.from.id !== directLineClientName }); activities = activities.filter(function (m) { return m.from.id !== directLineClientName })
if (activities.length) { if (activities.length) {
// print other messages // print other messages
activities.forEach(activity => { activities.forEach(activity => {
console.log(activity.text); console.log(activity.text)
}, this); }, this)
process.stdout.write('Command> '); process.stdout.write('Command> ')
} }
} }
} }
printMessage(activity) { printMessage(activity) {
if (activity.text) { if (activity.text) {
console.log(activity.text); console.log(activity.text)
} }
if (activity.attachments) { if (activity.attachments) {
activity.attachments.forEach(function (attachment) { activity.attachments.forEach(function (attachment) {
switch (attachment.contentType) { switch (attachment.contentType) {
case "application/vnd.microsoft.card.hero": case "application/vnd.microsoft.card.hero":
this.renderHeroCard(attachment); this.renderHeroCard(attachment)
break; break
case "image/png": case "image/png":
console.log('Opening the requested image ' + attachment.contentUrl); console.log('Opening the requested image ' + attachment.contentUrl)
open(attachment.contentUrl); open(attachment.contentUrl)
break; break
} }
}); })
} }
} }
renderHeroCard(attachment) { renderHeroCard(attachment) {
var width = 70; var width = 70
var contentLine = function (content) { var contentLine = function (content) {
return ' '.repeat((width - content.length) / 2) + return ' '.repeat((width - content.length) / 2) +
content + content +
' '.repeat((width - content.length) / 2); ' '.repeat((width - content.length) / 2)
} }
console.log('/' + '*'.repeat(width + 1)); console.log('/' + '*'.repeat(width + 1))
console.log('*' + contentLine(attachment.content.title) + '*'); console.log('*' + contentLine(attachment.content.title) + '*')
console.log('*' + ' '.repeat(width) + '*'); console.log('*' + ' '.repeat(width) + '*')
console.log('*' + contentLine(attachment.content.text) + '*'); console.log('*' + contentLine(attachment.content.text) + '*')
console.log('*'.repeat(width + 1) + '/'); console.log('*'.repeat(width + 1) + '/')
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,14 +30,14 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const WaitUntil = require("wait-until"); const WaitUntil = require("wait-until")
import { GBCoreService } from "../services/GBCoreService"; import { GBCoreService } from "../services/GBCoreService"
import { IGBDialog } from "botlib"; import { IGBDialog } from "botlib"
import { GBConversationalService } from "../services/GBConversationalService"; import { GBConversationalService } from "../services/GBConversationalService"
import { GBMinInstance } from "botlib"; import { GBMinInstance } from "botlib"
import { BotAdapter } from "botbuilder"; import { BotAdapter } from "botbuilder"
export class WelcomeDialog extends IGBDialog { export class WelcomeDialog extends IGBDialog {
/** /**
@ -52,24 +52,24 @@ export class WelcomeDialog extends IGBDialog {
async (dc, args) => { async (dc, args) => {
const user = min.userState.get(dc.context); const user = min.userState.get(dc.context)
if (!user.once) { if (!user.once) {
user.once = true; user.once = true
var a = new Date(); var a = new Date()
const date = a.getHours(); const date = a.getHours()
var msg = var msg =
date < 12 ? "bom dia" : date < 18 ? "boa tarde" : "boa noite"; date < 12 ? "bom dia" : date < 18 ? "boa tarde" : "boa noite"
let messages = [`Oi, ${msg}.`, `Oi!`, `Olá, ${msg}`, `Olá!`]; let messages = [`Oi, ${msg}.`, `Oi!`, `Olá, ${msg}`, `Olá!`]
await dc.context.sendActivity(messages[0]); await dc.context.sendActivity(messages[0])
if (dc.context.activity && dc.context.activity.type == "message" && if (dc.context.activity && dc.context.activity.type == "message" &&
dc.context.activity.text != "") { dc.context.activity.text != "") {
await dc.replace("/answer", { query: dc.context.activity.text }); await dc.replace("/answer", { query: dc.context.activity.text })
} }
} }
} }
]); ])
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,13 +30,13 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
import { GBConversationalService } from "./../services/GBConversationalService"; import { GBConversationalService } from "./../services/GBConversationalService"
import { GBCoreService } from "../services/GBCoreService"; import { GBCoreService } from "../services/GBCoreService"
import { IGBDialog } from "botlib"; import { IGBDialog } from "botlib"
import { GBMinInstance } from "botlib"; import { GBMinInstance } from "botlib"
import { BotAdapter } from "botbuilder"; import { BotAdapter } from "botbuilder"
export class WhoAmIDialog extends IGBDialog { export class WhoAmIDialog extends IGBDialog {
@ -51,18 +51,18 @@ export class WhoAmIDialog extends IGBDialog {
min.dialogs.add("/whoAmI", [ min.dialogs.add("/whoAmI", [
async (dc, args) => { async (dc, args) => {
await dc.context.sendActivity(`${min.instance.description}`); await dc.context.sendActivity(`${min.instance.description}`)
if (min.instance.whoAmIVideo) { if (min.instance.whoAmIVideo) {
await dc.context.sendActivity(`Vou te mostrar um vídeo. Por favor, aguarde...`); await dc.context.sendActivity(`Vou te mostrar um vídeo. Por favor, aguarde...`)
await min.conversationalService.sendEvent(dc, "play", { await min.conversationalService.sendEvent(dc, "play", {
playerType: "video", playerType: "video",
data: min.instance.whoAmIVideo.trim() data: min.instance.whoAmIVideo.trim()
}); })
} }
await dc.replace('/ask', { isReturning: true }); await dc.replace('/ask', { isReturning: true })
} }
]); ])
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,20 +30,20 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
import { GBMinInstance, IGBPackage } from "botlib"; import { GBMinInstance, IGBPackage } from "botlib"
import { WelcomeDialog } from "./dialogs/WelcomeDialog"; import { WelcomeDialog } from "./dialogs/WelcomeDialog"
import { WhoAmIDialog } from "./dialogs/WhoAmIDialog"; import { WhoAmIDialog } from "./dialogs/WhoAmIDialog"
import { IGBCoreService} from "botlib"; import { IGBCoreService} from "botlib"
import { Sequelize } from "sequelize-typescript"; import { Sequelize } from "sequelize-typescript"
import { GuaribasInstance, GuaribasException, GuaribasPackage, GuaribasChannel } from "./models/GBModel"; import { GuaribasInstance, GuaribasException, GuaribasPackage, GuaribasChannel } from "./models/GBModel"
export class GBCorePackage implements IGBPackage { export class GBCorePackage implements IGBPackage {
sysPackages: IGBPackage[] = null; sysPackages: IGBPackage[] = null
loadPackage(core: IGBCoreService, sequelize: Sequelize): void { loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
core.sequelize.addModels([ core.sequelize.addModels([
@ -51,7 +51,7 @@ export class GBCorePackage implements IGBPackage {
GuaribasPackage, GuaribasPackage,
GuaribasChannel, GuaribasChannel,
GuaribasException, GuaribasException,
]); ])
} }
unloadPackage(core: IGBCoreService): void { unloadPackage(core: IGBCoreService): void {
@ -59,8 +59,8 @@ export class GBCorePackage implements IGBPackage {
} }
loadBot(min: GBMinInstance): void { loadBot(min: GBMinInstance): void {
WelcomeDialog.setup(min.bot, min); WelcomeDialog.setup(min.bot, min)
WhoAmIDialog.setup(min.bot, min); WhoAmIDialog.setup(min.bot, min)
} }
unloadBot(min: GBMinInstance): void { unloadBot(min: GBMinInstance): void {

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,14 +30,14 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
import { import {
DataTypes, DataTypes,
DataTypeUUIDv4, DataTypeUUIDv4,
DataTypeDate, DataTypeDate,
DataTypeDecimal DataTypeDecimal
} from "sequelize"; } from "sequelize"
import { import {
Sequelize, Sequelize,
@ -54,9 +54,9 @@ import {
DataType, DataType,
PrimaryKey, PrimaryKey,
AutoIncrement AutoIncrement
} from "sequelize-typescript"; } from "sequelize-typescript"
import { IGBInstance } from "botlib"; import { IGBInstance } from "botlib"
@Table @Table
export class GuaribasInstance extends Model<GuaribasInstance> implements IGBInstance { export class GuaribasInstance extends Model<GuaribasInstance> implements IGBInstance {
@ -64,90 +64,90 @@ export class GuaribasInstance extends Model<GuaribasInstance> implements IGBInst
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
instanceId: number; instanceId: number
@Column applicationPrincipal: string; @Column applicationPrincipal: string
@Column @Column
whoAmIVideo: string; whoAmIVideo: string
@Column botId: string; @Column botId: string
@Column title: string; @Column title: string
@Column description: string; @Column description: string
@Column version: string; @Column version: string
@Column enabledAdmin: boolean; @Column enabledAdmin: boolean
/* Services section on bot.json */ /* Services section on bot.json */
@Column engineName: string; @Column engineName: string
@Column marketplaceId: string; @Column marketplaceId: string
@Column textAnalyticsKey: string; @Column textAnalyticsKey: string
@Column textAnalyticsServerUrl: string; @Column textAnalyticsServerUrl: string
@Column marketplacePassword: string; @Column marketplacePassword: string
@Column webchatKey: string; @Column webchatKey: string
@Column whatsappBotKey: string; @Column whatsappBotKey: string
@Column whatsappServiceKey: string; @Column whatsappServiceKey: string
@Column whatsappServiceNumber: string; @Column whatsappServiceNumber: string
@Column whatsappServiceUrl: string; @Column whatsappServiceUrl: string
@Column whatsappServiceWebhookUrl: string; @Column whatsappServiceWebhookUrl: string
@Column speechKey: string; @Column speechKey: string
@Column spellcheckerKey: string; @Column spellcheckerKey: string
@Column theme: string; @Column theme: string
@Column ui: string; @Column ui: string
@Column kb: string; @Column kb: string
@Column @Column
nlpAppId: string; nlpAppId: string
@Column @Column
nlpSubscriptionKey: string; nlpSubscriptionKey: string
@Column @Column
@Column({ type: DataType.STRING(512) }) @Column({ type: DataType.STRING(512) })
nlpServerUrl: string; nlpServerUrl: string
@Column searchHost: string; @Column searchHost: string
@Column searchKey: string; @Column searchKey: string
@Column searchIndex: string; @Column searchIndex: string
@Column searchIndexer: string; @Column searchIndexer: string
/* Settings section of bot.json */ /* Settings section of bot.json */
@Column(DataType.FLOAT) nlpVsSearch: number; @Column(DataType.FLOAT) nlpVsSearch: number
@Column(DataType.FLOAT) searchScore: number; @Column(DataType.FLOAT) searchScore: number
@Column(DataType.FLOAT) nlpScore: number; @Column(DataType.FLOAT) nlpScore: number
@Column @Column
@CreatedAt @CreatedAt
createdAt: Date; createdAt: Date
@Column @Column
@UpdatedAt @UpdatedAt
updatedAt: Date; updatedAt: Date
} }
@Table @Table
@ -156,25 +156,25 @@ export class GuaribasPackage extends Model<GuaribasPackage> {
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
packageId: number; packageId: number
@Column @Column
packageName: string; packageName: string
@ForeignKey(() => GuaribasInstance) @ForeignKey(() => GuaribasInstance)
@Column @Column
instanceId: number; instanceId: number
@BelongsTo(() => GuaribasInstance) @BelongsTo(() => GuaribasInstance)
instance: GuaribasInstance; instance: GuaribasInstance
@Column @Column
@CreatedAt @CreatedAt
createdAt: Date; createdAt: Date
@Column @Column
@UpdatedAt @UpdatedAt
updatedAt: Date; updatedAt: Date
} }
@Table @Table
@ -183,17 +183,17 @@ export class GuaribasChannel extends Model<GuaribasChannel> {
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
channelId: number; channelId: number
@Column title: string; @Column title: string
@Column @Column
@CreatedAt @CreatedAt
createdAt: Date; createdAt: Date
@Column @Column
@UpdatedAt @UpdatedAt
updatedAt: Date; updatedAt: Date
} }
@Table @Table
@ -202,22 +202,22 @@ export class GuaribasException extends Model<GuaribasException> {
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
exceptionId: number; exceptionId: number
@Column message: string; @Column message: string
@ForeignKey(() => GuaribasInstance) @ForeignKey(() => GuaribasInstance)
@Column @Column
instanceId: number; instanceId: number
@BelongsTo(() => GuaribasInstance) @BelongsTo(() => GuaribasInstance)
instance: GuaribasInstance; instance: GuaribasInstance
@Column @Column
@CreatedAt @CreatedAt
createdAt: Date; createdAt: Date
@Column @Column
@UpdatedAt @UpdatedAt
updatedAt: Date; updatedAt: Date
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,9 +30,9 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
const logger = require("../../../src/logger"); const logger = require("../../../src/logger")
"use strict"; "use strict"
export class GBConfigService { export class GBConfigService {
static init(): any { static init(): any {
@ -42,55 +42,55 @@ export class GBConfigService {
errorOnMissing: true, errorOnMissing: true,
errorOnExtra: false, errorOnExtra: false,
overrideProcessEnv: true overrideProcessEnv: true
}); })
} catch (e) { } catch (e) {
console.error(e.message); console.error(e.message)
process.exit(3); process.exit(3)
} }
} }
static get(key: string): string | undefined { static get(key: string): string | undefined {
let value = process.env["container:" + key]; let value = process.env["container:" + key]
if (!value) { if (!value) {
value = process.env[key]; value = process.env[key]
} }
if (!value) { if (!value) {
switch (key) { switch (key) {
case "DATABASE_DIALECT": case "DATABASE_DIALECT":
value = "sqlite"; value = "sqlite"
break; break
case "DATABASE_STORAGE": case "DATABASE_STORAGE":
value = "./guaribas.sqlite"; value = "./guaribas.sqlite"
break; break
case "ADDITIONAL_DEPLOY_PATH": case "ADDITIONAL_DEPLOY_PATH":
value = undefined; value = undefined
break; break
case "DATABASE_SYNC": case "DATABASE_SYNC":
case "DATABASE_SYNC_ALTER": case "DATABASE_SYNC_ALTER":
case "DATABASE_SYNC_FORCE": case "DATABASE_SYNC_FORCE":
value = "false"; value = "false"
break; break
case "DATABASE_LOGGING": case "DATABASE_LOGGING":
value = "false"; value = "false"
break; break
case "DATABASE_ENCRYPT": case "DATABASE_ENCRYPT":
value = "true"; value = "true"
break; break
default: default:
logger.info( logger.info(
`Guaribas General Error: Invalid key on .env file: '${key}'` `Guaribas General Error: Invalid key on .env file: '${key}'`
); )
break; break
} }
} }
return value; return value
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,38 +30,38 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const logger = require("../../../src/logger"); const logger = require("../../../src/logger")
import { GBCoreService } from "./GBCoreService"; import { GBCoreService } from "./GBCoreService"
import { IGBConversationalService } from "botlib"; import { IGBConversationalService } from "botlib"
import { GBMinInstance } from "botlib"; import { GBMinInstance } from "botlib"
import { LuisRecognizer } from "botbuilder-ai"; import { LuisRecognizer } from "botbuilder-ai"
import { MessageFactory } from "botbuilder"; import { MessageFactory } from "botbuilder"
export interface LanguagePickerSettings { export interface LanguagePickerSettings {
defaultLocale?: string; defaultLocale?: string
supportedLocales?: string[]; supportedLocales?: string[]
} }
export class GBConversationalService implements IGBConversationalService { export class GBConversationalService implements IGBConversationalService {
coreService: GBCoreService; coreService: GBCoreService
constructor(coreService: GBCoreService) { constructor(coreService: GBCoreService) {
this.coreService = coreService; this.coreService = coreService
} }
getCurrentLanguage(dc: any) { getCurrentLanguage(dc: any) {
return dc.context.activity.locale; return dc.context.activity.locale
} }
async sendEvent(dc: any, name: string, value: any): Promise<any> { async sendEvent(dc: any, name: string, value: any): Promise<any> {
const msg = MessageFactory.text(""); const msg = MessageFactory.text("")
msg.value = value; msg.value = value
msg.type = "event"; msg.type = "event"
msg.name = name; msg.name = name
return dc.context.sendActivity(msg); return dc.context.sendActivity(msg)
} }
async runNLP(dc: any, min: GBMinInstance, text: string): Promise<any> { async runNLP(dc: any, min: GBMinInstance, text: string): Promise<any> {
@ -71,36 +71,36 @@ export class GBConversationalService implements IGBConversationalService {
appId: min.instance.nlpAppId, appId: min.instance.nlpAppId,
subscriptionKey: min.instance.nlpSubscriptionKey, subscriptionKey: min.instance.nlpSubscriptionKey,
serviceEndpoint: min.instance.nlpServerUrl serviceEndpoint: min.instance.nlpServerUrl
}); })
let res = await model.recognize(dc.context); let res = await model.recognize(dc.context)
// Resolves intents returned from LUIS. // Resolves intents returned from LUIS.
let topIntent = LuisRecognizer.topIntent(res); let topIntent = LuisRecognizer.topIntent(res)
if (topIntent) { if (topIntent) {
var intent = topIntent; var intent = topIntent
var entity = var entity =
res.entities && res.entities.length > 0 res.entities && res.entities.length > 0
? res.entities[0].entity.toUpperCase() ? res.entities[0].entity.toUpperCase()
: null; : null
logger.info("luis: intent: [" + intent + "] entity: [" + entity + "]"); logger.info("luis: intent: [" + intent + "] entity: [" + entity + "]")
try { try {
await dc.replace("/" + intent); await dc.replace("/" + intent)
} catch (error) { } catch (error) {
logger.info("error: intent: [" + intent + "] error: [" + error + "]"); logger.info("error: intent: [" + intent + "] error: [" + error + "]")
await dc.context.sendActivity( await dc.context.sendActivity(
"Desculpe-me, não encontrei nada a respeito..." "Desculpe-me, não encontrei nada a respeito..."
); )
await dc.replace("/ask", { isReturning: true }); await dc.replace("/ask", { isReturning: true })
} }
return Promise.resolve({ intent, entities: res.entities }); return Promise.resolve({ intent, entities: res.entities })
} else { } else {
await dc.context.sendActivity("Lamento, não achei nada a respeito..."); await dc.context.sendActivity("Lamento, não achei nada a respeito...")
await dc.replace("/ask", { isReturning: true }); await dc.replace("/ask", { isReturning: true })
return Promise.resolve(null); return Promise.resolve(null)
} }
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,13 +30,13 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const logger = require("../../../src/logger"); const logger = require("../../../src/logger")
import { Sequelize } from "sequelize-typescript"; import { Sequelize } from "sequelize-typescript"
import { GBConfigService } from "./GBConfigService"; import { GBConfigService } from "./GBConfigService"
import { IGBInstance, IGBCoreService } from "botlib"; import { IGBInstance, IGBCoreService } from "botlib"
import { GuaribasInstance } from "../models/GBModel"; import { GuaribasInstance } from "../models/GBModel"
/** /**
* Core service layer. * Core service layer.
@ -45,33 +45,33 @@ export class GBCoreService implements IGBCoreService {
/** /**
* Data access layer instance. * Data access layer instance.
*/ */
public sequelize: Sequelize; public sequelize: Sequelize
/** /**
* Allows filtering on SQL generated before send to the database. * Allows filtering on SQL generated before send to the database.
*/ */
private queryGenerator: any; private queryGenerator: any
/** /**
* Custom create table query. * Custom create table query.
*/ */
private createTableQuery: (tableName, attributes, options) => string; private createTableQuery: (tableName, attributes, options) => string
/** /**
* Custom change column query. * Custom change column query.
*/ */
private changeColumnQuery: (tableName, attributes) => string; private changeColumnQuery: (tableName, attributes) => string
/** /**
* Dialect used. Tested: mssql and sqlite. * Dialect used. Tested: mssql and sqlite.
*/ */
private dialect: string; private dialect: string
/** /**
* Constructor retrieves default values. * Constructor retrieves default values.
*/ */
constructor() { constructor() {
this.dialect = GBConfigService.get("DATABASE_DIALECT"); this.dialect = GBConfigService.get("DATABASE_DIALECT")
} }
/** /**
@ -80,29 +80,29 @@ export class GBCoreService implements IGBCoreService {
async initDatabase() { async initDatabase() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
let host: string | undefined; let host: string | undefined
let database: string | undefined; let database: string | undefined
let username: string | undefined; let username: string | undefined
let password: string | undefined; let password: string | undefined
let storage: string | undefined; let storage: string | undefined
if (this.dialect === "mssql") { if (this.dialect === "mssql") {
host = GBConfigService.get("DATABASE_HOST"); host = GBConfigService.get("DATABASE_HOST")
database = GBConfigService.get("DATABASE_NAME"); database = GBConfigService.get("DATABASE_NAME")
username = GBConfigService.get("DATABASE_USERNAME"); username = GBConfigService.get("DATABASE_USERNAME")
password = GBConfigService.get("DATABASE_PASSWORD"); password = GBConfigService.get("DATABASE_PASSWORD")
} else if (this.dialect === "sqlite") { } else if (this.dialect === "sqlite") {
storage = GBConfigService.get("DATABASE_STORAGE"); storage = GBConfigService.get("DATABASE_STORAGE")
} }
let logging = let logging =
GBConfigService.get("DATABASE_LOGGING") === "true" GBConfigService.get("DATABASE_LOGGING") === "true"
? (str: string) => { ? (str: string) => {
logger.info(str); logger.info(str)
} }
: false; : false
let encrypt = GBConfigService.get("DATABASE_ENCRYPT") === "true"; let encrypt = GBConfigService.get("DATABASE_ENCRYPT") === "true"
this.sequelize = new Sequelize({ this.sequelize = new Sequelize({
host: host, host: host,
@ -123,25 +123,25 @@ export class GBCoreService implements IGBCoreService {
evict: 40000, evict: 40000,
acquire: 40000 acquire: 40000
} }
}); })
if (this.dialect === "mssql") { if (this.dialect === "mssql") {
this.queryGenerator = this.sequelize.getQueryInterface().QueryGenerator; this.queryGenerator = this.sequelize.getQueryInterface().QueryGenerator
this.createTableQuery = this.queryGenerator.createTableQuery; this.createTableQuery = this.queryGenerator.createTableQuery
this.queryGenerator.createTableQuery = ( this.queryGenerator.createTableQuery = (
tableName, tableName,
attributes, attributes,
options options
) => this.createTableQueryOverride(tableName, attributes, options); ) => this.createTableQueryOverride(tableName, attributes, options)
this.changeColumnQuery = this.queryGenerator.changeColumnQuery; this.changeColumnQuery = this.queryGenerator.changeColumnQuery
this.queryGenerator.changeColumnQuery = (tableName, attributes) => this.queryGenerator.changeColumnQuery = (tableName, attributes) =>
this.changeColumnQueryOverride(tableName, attributes); this.changeColumnQueryOverride(tableName, attributes)
} }
resolve(); resolve()
} catch (error) { } catch (error) {
reject(error); reject(error)
} }
}); })
} }
/** /**
@ -157,42 +157,42 @@ export class GBCoreService implements IGBCoreService {
* // ' PRIMARY KEY ([id1], [id2]),\n' + * // ' PRIMARY KEY ([id1], [id2]),\n' +
* // ' FOREIGN KEY ([userId1], [userId2], [userId3]) REFERENCES [User] ([userId1], [userId2], [userId3]) ON DELETE NO ACTION,\n' + * // ' FOREIGN KEY ([userId1], [userId2], [userId3]) REFERENCES [User] ([userId1], [userId2], [userId3]) ON DELETE NO ACTION,\n' +
* // ' FOREIGN KEY ([groupId1], [groupId2]) REFERENCES [Group] ([groupId1], [groupId1]) ON DELETE NO ACTION,\n' + * // ' FOREIGN KEY ([groupId1], [groupId2]) REFERENCES [Group] ([groupId1], [groupId1]) ON DELETE NO ACTION,\n' +
* // ' FOREIGN KEY ([instanceId]) REFERENCES [Instance] ([instanceId]) ON DELETE NO ACTION);'; * // ' FOREIGN KEY ([instanceId]) REFERENCES [Instance] ([instanceId]) ON DELETE NO ACTION)'
*/ */
private createTableQueryOverride(tableName, attributes, options): string { private createTableQueryOverride(tableName, attributes, options): string {
let sql: string = this.createTableQuery.apply(this.queryGenerator, [ let sql: string = this.createTableQuery.apply(this.queryGenerator, [
tableName, tableName,
attributes, attributes,
options options
]); ])
const re1 = /CREATE\s+TABLE\s+\[([^\]]*)\]/; const re1 = /CREATE\s+TABLE\s+\[([^\]]*)\]/
const matches = re1.exec(sql); const matches = re1.exec(sql)
if (matches) { if (matches) {
const table = matches[1]; const table = matches[1]
const re2 = /PRIMARY\s+KEY\s+\(\[[^\]]*\](?:,\s*\[[^\]]*\])*\)/; const re2 = /PRIMARY\s+KEY\s+\(\[[^\]]*\](?:,\s*\[[^\]]*\])*\)/
sql = sql.replace( sql = sql.replace(
re2, re2,
(match: string, ...args: any[]): string => { (match: string, ...args: any[]): string => {
return "CONSTRAINT [" + table + "_pk] " + match; return "CONSTRAINT [" + table + "_pk] " + match
} }
); )
const re3 = /FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g; const re3 = /FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g
const re4 = /\[([^\]]*)\]/g; const re4 = /\[([^\]]*)\]/g
sql = sql.replace( sql = sql.replace(
re3, re3,
(match: string, ...args: any[]): string => { (match: string, ...args: any[]): string => {
const fkcols = args[0]; const fkcols = args[0]
let fkname = table; let fkname = table
let matches = re4.exec(fkcols); let matches = re4.exec(fkcols)
while (matches != null) { while (matches != null) {
fkname += "_" + matches[1]; fkname += "_" + matches[1]
matches = re4.exec(fkcols); matches = re4.exec(fkcols)
} }
return "CONSTRAINT [" + fkname + "_fk] FOREIGN KEY (" + fkcols + ")"; return "CONSTRAINT [" + fkname + "_fk] FOREIGN KEY (" + fkcols + ")"
} }
); )
} }
return sql; return sql
} }
@ -202,28 +202,28 @@ export class GBCoreService implements IGBCoreService {
* 'ALTER TABLE [UserGroup]\n' + * 'ALTER TABLE [UserGroup]\n' +
* ' ADD CONSTRAINT [invalid1] FOREIGN KEY ([userId1], [userId2], [userId3]) REFERENCES [User] ([userId1], [userId2], [userId3]) ON DELETE NO ACTION,\n' + * ' ADD CONSTRAINT [invalid1] FOREIGN KEY ([userId1], [userId2], [userId3]) REFERENCES [User] ([userId1], [userId2], [userId3]) ON DELETE NO ACTION,\n' +
* ' CONSTRAINT [invalid2] FOREIGN KEY ([groupId1], [groupId2]) REFERENCES [Group] ([groupId1], [groupId2]) ON DELETE NO ACTION, \n' + * ' CONSTRAINT [invalid2] FOREIGN KEY ([groupId1], [groupId2]) REFERENCES [Group] ([groupId1], [groupId2]) ON DELETE NO ACTION, \n' +
* ' CONSTRAINT [invalid3] FOREIGN KEY ([instanceId1]) REFERENCES [Instance] ([instanceId1]) ON DELETE NO ACTION;\n'; * ' CONSTRAINT [invalid3] FOREIGN KEY ([instanceId1]) REFERENCES [Instance] ([instanceId1]) ON DELETE NO ACTION\n'
*/ */
private changeColumnQueryOverride(tableName, attributes): string { private changeColumnQueryOverride(tableName, attributes): string {
let sql: string = this.changeColumnQuery.apply(this.queryGenerator, [ let sql: string = this.changeColumnQuery.apply(this.queryGenerator, [
tableName, tableName,
attributes attributes
]); ])
const re1 = /ALTER\s+TABLE\s+\[([^\]]*)\]/; const re1 = /ALTER\s+TABLE\s+\[([^\]]*)\]/
const matches = re1.exec(sql); const matches = re1.exec(sql)
if (matches) { if (matches) {
const table = matches[1]; const table = matches[1]
const re2 = /(ADD\s+)?CONSTRAINT\s+\[([^\]]*)\]\s+FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g; const re2 = /(ADD\s+)?CONSTRAINT\s+\[([^\]]*)\]\s+FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g
const re3 = /\[([^\]]*)\]/g; const re3 = /\[([^\]]*)\]/g
sql = sql.replace( sql = sql.replace(
re2, re2,
(match: string, ...args: any[]): string => { (match: string, ...args: any[]): string => {
const fkcols = args[2]; const fkcols = args[2]
let fkname = table; let fkname = table
let matches = re3.exec(fkcols); let matches = re3.exec(fkcols)
while (matches != null) { while (matches != null) {
fkname += "_" + matches[1]; fkname += "_" + matches[1]
matches = re3.exec(fkcols); matches = re3.exec(fkcols)
} }
return ( return (
(args[0] ? args[0] : "") + (args[0] ? args[0] : "") +
@ -232,19 +232,19 @@ export class GBCoreService implements IGBCoreService {
"_fk] FOREIGN KEY (" + "_fk] FOREIGN KEY (" +
fkcols + fkcols +
")" ")"
); )
} }
); )
} }
return sql; return sql
} }
async syncDatabaseStructure() { async syncDatabaseStructure() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (GBConfigService.get("DATABASE_SYNC") === "true") { if (GBConfigService.get("DATABASE_SYNC") === "true") {
const alter = GBConfigService.get("DATABASE_SYNC_ALTER") === "true"; const alter = GBConfigService.get("DATABASE_SYNC_ALTER") === "true"
const force = GBConfigService.get("DATABASE_SYNC_FORCE") === "true"; const force = GBConfigService.get("DATABASE_SYNC_FORCE") === "true"
logger.info("Syncing database..."); logger.info("Syncing database...")
this.sequelize this.sequelize
.sync({ .sync({
alter: alter, alter: alter,
@ -252,16 +252,16 @@ export class GBCoreService implements IGBCoreService {
}) })
.then( .then(
value => { value => {
logger.info("Database synced."); logger.info("Database synced.")
resolve(value); resolve(value)
}, },
err => reject(err) err => reject(err)
); )
} else { } else {
logger.info("Database synchronization is disabled."); logger.info("Database synchronization is disabled.")
resolve(); resolve()
} }
}); })
} }
/** /**
@ -271,23 +271,23 @@ export class GBCoreService implements IGBCoreService {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
GuaribasInstance.findAll({}) GuaribasInstance.findAll({})
.then((items: IGBInstance[]) => { .then((items: IGBInstance[]) => {
if (!items) items = []; if (!items) items = []
if (items.length == 0) { if (items.length == 0) {
resolve([]); resolve([])
} else { } else {
resolve(items); resolve(items)
} }
}) })
.catch(reason => { .catch(reason => {
if (reason.message.indexOf("no such table: GuaribasInstance") != -1) { if (reason.message.indexOf("no such table: GuaribasInstance") != -1) {
resolve([]); resolve([])
} else { } else {
logger.info(`GuaribasServiceError: ${reason}`); logger.info(`GuaribasServiceError: ${reason}`)
reject(reason); reject(reason)
} }
}); })
}); })
} }
/** /**
@ -295,24 +295,24 @@ export class GBCoreService implements IGBCoreService {
*/ */
async loadInstance(botId: string): Promise<IGBInstance> { async loadInstance(botId: string): Promise<IGBInstance> {
return new Promise<IGBInstance>((resolve, reject) => { return new Promise<IGBInstance>((resolve, reject) => {
let options = { where: {} }; let options = { where: {} }
if (botId != "[default]") { if (botId != "[default]") {
options.where = { botId: botId }; options.where = { botId: botId }
} }
GuaribasInstance.findOne(options) GuaribasInstance.findOne(options)
.then((instance: IGBInstance) => { .then((instance: IGBInstance) => {
if (instance) { if (instance) {
resolve(instance); resolve(instance)
} else { } else {
resolve(null); resolve(null)
} }
}) })
.catch(err => { .catch(err => {
logger.info(`GuaribasServiceError: ${err}`); logger.info(`GuaribasServiceError: ${err}`)
reject(err); reject(err)
}); })
}); })
} }
} }

View file

@ -1,4 +1,4 @@
import { IGBPackage } from "botlib"; import { IGBPackage } from "botlib"
/*****************************************************************************\ /*****************************************************************************\
| ( )_ _ | | ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ | | _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
@ -20,7 +20,7 @@ import { IGBPackage } from "botlib";
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -31,35 +31,35 @@ import { IGBPackage } from "botlib";
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const logger = require("../../../src/logger"); const logger = require("../../../src/logger")
const Path = require("path"); const Path = require("path")
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
const Fs = require("fs"); const Fs = require("fs")
const WaitUntil = require("wait-until"); const WaitUntil = require("wait-until")
const express = require("express"); const express = require("express")
import { KBService } from "./../../kb.gbapp/services/KBService"; import { KBService } from "./../../kb.gbapp/services/KBService"
import { GBImporter } from "./GBImporter"; import { GBImporter } from "./GBImporter"
import { IGBCoreService, IGBInstance } from "botlib"; import { IGBCoreService, IGBInstance } from "botlib"
import { GBConfigService } from "./GBConfigService"; import { GBConfigService } from "./GBConfigService"
import { GBError } from "botlib"; import { GBError } from "botlib"
import { GuaribasPackage } from "../models/GBModel"; import { GuaribasPackage } from "../models/GBModel"
/** Deployer service for bots, themes, ai and more. */ /** Deployer service for bots, themes, ai and more. */
export class GBDeployer { export class GBDeployer {
core: IGBCoreService; core: IGBCoreService
importer: GBImporter; importer: GBImporter
workDir: string = "./work"; workDir: string = "./work"
static deployFolder = "deploy"; static deployFolder = "deploy"
constructor(core: IGBCoreService, importer: GBImporter) { constructor(core: IGBCoreService, importer: GBImporter) {
this.core = core; this.core = core
this.importer = importer; this.importer = importer
} }
/** /**
@ -72,101 +72,101 @@ export class GBDeployer {
server: any, server: any,
appPackages: Array<IGBPackage> appPackages: Array<IGBPackage>
) { ) {
let _this = this; let _this = this
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
let totalPackages = 0; let totalPackages = 0
let additionalPath = GBConfigService.get("ADDITIONAL_DEPLOY_PATH"); let additionalPath = GBConfigService.get("ADDITIONAL_DEPLOY_PATH")
let paths = [GBDeployer.deployFolder]; let paths = [GBDeployer.deployFolder]
if (additionalPath) { if (additionalPath) {
paths = paths.concat(additionalPath.toLowerCase().split(";")); paths = paths.concat(additionalPath.toLowerCase().split(""))
} }
let botPackages = new Array<string>(); let botPackages = new Array<string>()
let gbappPackages = new Array<string>(); let gbappPackages = new Array<string>()
let generalPackages = new Array<string>(); let generalPackages = new Array<string>()
function doIt(path) { function doIt(path) {
const isDirectory = source => Fs.lstatSync(source).isDirectory(); const isDirectory = source => Fs.lstatSync(source).isDirectory()
const getDirectories = source => const getDirectories = source =>
Fs.readdirSync(source) Fs.readdirSync(source)
.map(name => Path.join(source, name)) .map(name => Path.join(source, name))
.filter(isDirectory); .filter(isDirectory)
let dirs = getDirectories(path); let dirs = getDirectories(path)
dirs.forEach(element => { dirs.forEach(element => {
if (element.startsWith(".")) { if (element.startsWith(".")) {
logger.info(`Ignoring ${element}...`); logger.info(`Ignoring ${element}...`)
} else { } else {
if (element.endsWith(".gbot")) { if (element.endsWith(".gbot")) {
botPackages.push(element); botPackages.push(element)
} else if (element.endsWith(".gbapp")) { } else if (element.endsWith(".gbapp")) {
gbappPackages.push(element); gbappPackages.push(element)
} else { } else {
generalPackages.push(element); generalPackages.push(element)
} }
} }
}); })
} }
logger.info( logger.info(
`Starting looking for packages (.gbot, .gbtheme, .gbkb, .gbapp)...` `Starting looking for packages (.gbot, .gbtheme, .gbkb, .gbapp)...`
); )
paths.forEach(e => { paths.forEach(e => {
logger.info(`Looking in: ${e}...`); logger.info(`Looking in: ${e}...`)
doIt(e); doIt(e)
}); })
/** Deploys all .gbapp files first. */ /** Deploys all .gbapp files first. */
let appPackagesProcessed = 0; let appPackagesProcessed = 0
gbappPackages.forEach(e => { gbappPackages.forEach(e => {
logger.info(`Deploying app: ${e}...`); logger.info(`Deploying app: ${e}...`)
// Skips .gbapp inside deploy folder. // Skips .gbapp inside deploy folder.
if (!e.startsWith("deploy")) { if (!e.startsWith("deploy")) {
import(e) import(e)
.then(m => { .then(m => {
let p = new m.Package(); let p = new m.Package()
p.loadPackage(core, core.sequelize); p.loadPackage(core, core.sequelize)
appPackages.push(p); appPackages.push(p)
logger.info(`App (.gbapp) deployed: ${e}.`); logger.info(`App (.gbapp) deployed: ${e}.`)
appPackagesProcessed++; appPackagesProcessed++
}) })
.catch(err => { .catch(err => {
logger.info(`Error deploying App (.gbapp): ${e}: ${err}`); logger.info(`Error deploying App (.gbapp): ${e}: ${err}`)
appPackagesProcessed++; appPackagesProcessed++
}); })
} else { } else {
appPackagesProcessed++; appPackagesProcessed++
} }
}); })
WaitUntil() WaitUntil()
.interval(1000) .interval(1000)
.times(10) .times(10)
.condition(function(cb) { .condition(function(cb) {
logger.info(`Waiting for app package deployment...`); logger.info(`Waiting for app package deployment...`)
cb(appPackagesProcessed == gbappPackages.length); cb(appPackagesProcessed == gbappPackages.length)
}) })
.done(function(result) { .done(function(result) {
logger.info(`App Package deployment done.`); logger.info(`App Package deployment done.`)
core.syncDatabaseStructure(); core.syncDatabaseStructure()
/** Deploys all .gbot files first. */ /** Deploys all .gbot files first. */
botPackages.forEach(e => { botPackages.forEach(e => {
logger.info(`Deploying bot: ${e}...`); logger.info(`Deploying bot: ${e}...`)
_this.deployBot(e); _this.deployBot(e)
logger.info(`Bot: ${e} deployed...`); logger.info(`Bot: ${e} deployed...`)
}); })
/** Then all remaining generalPackages are loaded. */ /** Then all remaining generalPackages are loaded. */
generalPackages.forEach(filename => { generalPackages.forEach(filename => {
let filenameOnly = Path.basename(filename); let filenameOnly = Path.basename(filename)
logger.info(`Deploying package: ${filename}...`); logger.info(`Deploying package: ${filename}...`)
/** Handles apps for general bots - .gbapp must stay out of deploy folder. */ /** Handles apps for general bots - .gbapp must stay out of deploy folder. */
@ -176,21 +176,21 @@ export class GBDeployer {
) { ) {
/** Themes for bots. */ /** Themes for bots. */
} else if (Path.extname(filename) === ".gbtheme") { } else if (Path.extname(filename) === ".gbtheme") {
server.use("/themes/" + filenameOnly, express.static(filename)); server.use("/themes/" + filenameOnly, express.static(filename))
logger.info( logger.info(
`Theme (.gbtheme) assets accessible at: ${"/themes/" + `Theme (.gbtheme) assets accessible at: ${"/themes/" +
filenameOnly}.` filenameOnly}.`
); )
/** Knowledge base for bots. */ /** Knowledge base for bots. */
} else if (Path.extname(filename) === ".gbkb") { } else if (Path.extname(filename) === ".gbkb") {
server.use( server.use(
"/kb/" + filenameOnly + "/subjects", "/kb/" + filenameOnly + "/subjects",
express.static(UrlJoin(filename, "subjects")) express.static(UrlJoin(filename, "subjects"))
); )
logger.info( logger.info(
`KB (.gbkb) assets accessible at: ${"/kb/" + filenameOnly}.` `KB (.gbkb) assets accessible at: ${"/kb/" + filenameOnly}.`
); )
} else if ( } else if (
Path.extname(filename) === ".gbui" || Path.extname(filename) === ".gbui" ||
filename.endsWith(".git") filename.endsWith(".git")
@ -198,35 +198,35 @@ export class GBDeployer {
// Already Handled // Already Handled
} else { } else {
/** Unknown package format. */ /** Unknown package format. */
let err = new Error(`Package type not handled: ${filename}.`); let err = new Error(`Package type not handled: ${filename}.`)
reject(err); reject(err)
} }
totalPackages++; totalPackages++
}); })
WaitUntil() WaitUntil()
.interval(1000) .interval(1000)
.times(5) .times(5)
.condition(function(cb) { .condition(function(cb) {
logger.info(`Waiting for package deployment...`); logger.info(`Waiting for package deployment...`)
cb(totalPackages == generalPackages.length); cb(totalPackages == generalPackages.length)
}) })
.done(function(result) { .done(function(result) {
if (botPackages.length === 0) { if (botPackages.length === 0) {
logger.info( logger.info(
"The server is running with no bot instances, at least one .gbot file must be deployed." "The server is running with no bot instances, at least one .gbot file must be deployed."
); )
} else { } else {
logger.info(`Package deployment done.`); logger.info(`Package deployment done.`)
} }
resolve(); resolve()
}); })
}); })
} catch (err) { } catch (err) {
logger.error(err); logger.error(err)
reject(err); reject(err)
} }
}); })
} }
/** /**
@ -234,13 +234,13 @@ export class GBDeployer {
*/ */
async deployBot(localPath: string): Promise<IGBInstance> { async deployBot(localPath: string): Promise<IGBInstance> {
let packageType = Path.extname(localPath); let packageType = Path.extname(localPath)
let packageName = Path.basename(localPath); let packageName = Path.basename(localPath)
let instance = await this.importer.importIfNotExistsBotPackage( let instance = await this.importer.importIfNotExistsBotPackage(
packageName, packageName,
localPath localPath
); )
return instance; return instance
} }
async deployPackageToStorage( async deployPackageToStorage(
@ -250,7 +250,7 @@ export class GBDeployer {
return GuaribasPackage.create({ return GuaribasPackage.create({
packageName: packageName, packageName: packageName,
instanceId: instanceId instanceId: instanceId
}); })
} }
deployTheme(localPath: string) { deployTheme(localPath: string) {
@ -261,65 +261,65 @@ export class GBDeployer {
// .catch(err => { // .catch(err => {
// var gberr = GBError.create( // var gberr = GBError.create(
// `GuaribasBusinessError: Error copying package: ${localPath}.` // `GuaribasBusinessError: Error copying package: ${localPath}.`
// ); // )
// }); // })
} }
async deployPackageFromLocalPath(localPath: string) { async deployPackageFromLocalPath(localPath: string) {
let packageType = Path.extname(localPath); let packageType = Path.extname(localPath)
switch (packageType) { switch (packageType) {
case ".gbot": case ".gbot":
return this.deployBot(localPath); return this.deployBot(localPath)
case ".gbtheme": case ".gbtheme":
return this.deployTheme(localPath); return this.deployTheme(localPath)
// PACKAGE: Put in package logic. // PACKAGE: Put in package logic.
case ".gbkb": case ".gbkb":
let service = new KBService(this.core.sequelize); let service = new KBService(this.core.sequelize)
return service.deployKb(this.core, this, localPath); return service.deployKb(this.core, this, localPath)
case ".gbui": case ".gbui":
break; break
default: default:
var err = GBError.create( var err = GBError.create(
`GuaribasBusinessError: Unknow package type: ${packageType}.` `GuaribasBusinessError: Unknow package type: ${packageType}.`
); )
Promise.reject(err); Promise.reject(err)
break; break
} }
} }
async undeployPackageFromLocalPath(instance: IGBInstance, localPath: string) { async undeployPackageFromLocalPath(instance: IGBInstance, localPath: string) {
let packageType = Path.extname(localPath); let packageType = Path.extname(localPath)
let packageName = Path.basename(localPath); let packageName = Path.basename(localPath)
let p = await this.getPackageByName(instance.instanceId, packageName); let p = await this.getPackageByName(instance.instanceId, packageName)
switch (packageType) { switch (packageType) {
case ".gbot": case ".gbot":
// TODO: this.undeployBot(packageName, localPath); // TODO: this.undeployBot(packageName, localPath)
break; break
case ".gbtheme": case ".gbtheme":
// TODO: this.undeployTheme(packageName, localPath); // TODO: this.undeployTheme(packageName, localPath)
break; break
case ".gbkb": case ".gbkb":
let service = new KBService(this.core.sequelize); let service = new KBService(this.core.sequelize)
return service.undeployKbFromStorage(instance, p.packageId); return service.undeployKbFromStorage(instance, p.packageId)
case ".gbui": case ".gbui":
break; break
default: default:
var err = GBError.create( var err = GBError.create(
`GuaribasBusinessError: Unknown package type: ${packageType}.` `GuaribasBusinessError: Unknown package type: ${packageType}.`
); )
Promise.reject(err); Promise.reject(err)
break; break
} }
} }
@ -327,10 +327,10 @@ export class GBDeployer {
instanceId: number, instanceId: number,
packageName: string packageName: string
): Promise<GuaribasPackage> { ): Promise<GuaribasPackage> {
var where = { packageName: packageName, instanceId: instanceId }; var where = { packageName: packageName, instanceId: instanceId }
return GuaribasPackage.findOne({ return GuaribasPackage.findOne({
where: where where: where
}); })
} }
/** /**
@ -339,15 +339,15 @@ export class GBDeployer {
* *
*/ */
async scanBootPackage() { async scanBootPackage() {
const deployFolder = "deploy"; const deployFolder = "deploy"
let bootPackage = GBConfigService.get("BOOT_PACKAGE"); let bootPackage = GBConfigService.get("BOOT_PACKAGE")
if (bootPackage === "none") { if (bootPackage === "none") {
return Promise.resolve(true); return Promise.resolve(true)
} else { } else {
return this.deployPackageFromLocalPath( return this.deployPackageFromLocalPath(
UrlJoin(deployFolder, bootPackage) UrlJoin(deployFolder, bootPackage)
); )
} }
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -31,20 +31,20 @@
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
import Fs = require("fs"); import Fs = require("fs")
import Path = require("path"); import Path = require("path")
import { IGBCoreService, IGBInstance } from "botlib"; import { IGBCoreService, IGBInstance } from "botlib"
import { SecService } from "../../security.gblib/services/SecService"; import { SecService } from "../../security.gblib/services/SecService"
import { GuaribasInstance } from "../models/GBModel"; import { GuaribasInstance } from "../models/GBModel"
export class GBImporter { export class GBImporter {
core: IGBCoreService; core: IGBCoreService
constructor(core: IGBCoreService) { constructor(core: IGBCoreService) {
this.core = core; this.core = core
} }
async importIfNotExistsBotPackage( async importIfNotExistsBotPackage(
@ -53,15 +53,15 @@ export class GBImporter {
let packageJson = JSON.parse( let packageJson = JSON.parse(
Fs.readFileSync(UrlJoin(localPath, "package.json"), "utf8") Fs.readFileSync(UrlJoin(localPath, "package.json"), "utf8")
); )
let botId = packageJson.botId; let botId = packageJson.botId
let instance = await this.core.loadInstance(botId); let instance = await this.core.loadInstance(botId)
if (instance) { if (instance) {
return Promise.resolve(instance); return Promise.resolve(instance)
} else { } else {
return this.createInstanceInternal(packageName, localPath, packageJson); return this.createInstanceInternal(packageName, localPath, packageJson)
} }
} }
@ -72,19 +72,19 @@ export class GBImporter {
) { ) {
const settings = JSON.parse( const settings = JSON.parse(
Fs.readFileSync(UrlJoin(localPath, "settings.json"), "utf8") Fs.readFileSync(UrlJoin(localPath, "settings.json"), "utf8")
); )
const servicesJson = JSON.parse( const servicesJson = JSON.parse(
Fs.readFileSync(UrlJoin(localPath, "services.json"), "utf8") Fs.readFileSync(UrlJoin(localPath, "services.json"), "utf8")
); )
packageJson = Object.assign(packageJson, settings, servicesJson); packageJson = Object.assign(packageJson, settings, servicesJson)
GuaribasInstance.create(packageJson).then((instance: IGBInstance) => { GuaribasInstance.create(packageJson).then((instance: IGBInstance) => {
let service = new SecService(); let service = new SecService()
// TODO: service.importSecurityFile(localPath, instance); // TODO: service.importSecurityFile(localPath, instance)
Promise.resolve(instance); Promise.resolve(instance)
}); })
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,12 +30,12 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const { TextPrompt } = require("botbuilder-dialogs"); const { TextPrompt } = require("botbuilder-dialogs")
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
const express = require("express"); const express = require("express")
const logger = require("../../../src/logger"); const logger = require("../../../src/logger")
import { import {
BotFrameworkAdapter, BotFrameworkAdapter,
@ -43,32 +43,32 @@ import {
ConversationState, ConversationState,
MemoryStorage, MemoryStorage,
UserState UserState
} from "botbuilder"; } from "botbuilder"
import { GBCoreService } from "./GBCoreService"; import { GBCoreService } from "./GBCoreService"
import { GBConversationalService } from "./GBConversationalService"; import { GBConversationalService } from "./GBConversationalService"
import * as request from "request-promise-native"; import * as request from "request-promise-native"
import { import {
GBMinInstance, GBMinInstance,
IGBPackage, IGBPackage,
} from "botlib"; } from "botlib"
import { GBAnalyticsPackage } from "../../analytics.gblib"; import { GBAnalyticsPackage } from "../../analytics.gblib"
import { GBCorePackage } from "../../core.gbapp"; import { GBCorePackage } from "../../core.gbapp"
import { GBKBPackage } from "../../kb.gbapp"; import { GBKBPackage } from "../../kb.gbapp"
import { GBDeployer } from "./GBDeployer"; import { GBDeployer } from "./GBDeployer"
import { GBSecurityPackage } from "../../security.gblib"; import { GBSecurityPackage } from "../../security.gblib"
import { GBAdminPackage } from "./../../admin.gbapp/index"; import { GBAdminPackage } from "./../../admin.gbapp/index"
import { GBCustomerSatisfactionPackage } from "../../customer-satisfaction.gbapp"; import { GBCustomerSatisfactionPackage } from "../../customer-satisfaction.gbapp"
import { GBWhatsappPackage } from "../../whatsapp.gblib"; import { GBWhatsappPackage } from "../../whatsapp.gblib"
/** Minimal service layer for a bot. */ /** Minimal service layer for a bot. */
export class GBMinService { export class GBMinService {
core: GBCoreService; core: GBCoreService
conversationalService: GBConversationalService; conversationalService: GBConversationalService
deployer: GBDeployer; deployer: GBDeployer
corePackage = "core.gbai"; corePackage = "core.gbai"
/** /**
* Static initialization of minimal instance. * Static initialization of minimal instance.
@ -80,9 +80,9 @@ export class GBMinService {
conversationalService: GBConversationalService, conversationalService: GBConversationalService,
deployer: GBDeployer deployer: GBDeployer
) { ) {
this.core = core; this.core = core
this.conversationalService = conversationalService; this.conversationalService = conversationalService
this.deployer = deployer; this.deployer = deployer
} }
/** /**
@ -102,20 +102,20 @@ export class GBMinService {
): Promise<GBMinInstance> { ): Promise<GBMinInstance> {
// Serves default UI on root address '/'. // Serves default UI on root address '/'.
let uiPackage = "default.gbui"; let uiPackage = "default.gbui"
server.use( server.use(
"/", "/",
express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, "build")) express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, "build"))
); )
// Loads all bot instances from storage and starting loading them. // Loads all bot instances from storage and starting loading them.
let instances = await this.core.loadInstances(); let instances = await this.core.loadInstances()
Promise.all( Promise.all(
instances.map(async instance => { instances.map(async instance => {
// Gets the authorization key for each instance from Bot Service. // Gets the authorization key for each instance from Bot Service.
let webchatToken = await this.getWebchatToken(instance); let webchatToken = await this.getWebchatToken(instance)
// Serves the bot information object via HTTP so clients can get // Serves the bot information object via HTTP so clients can get
// instance information stored on server. // instance information stored on server.
@ -124,10 +124,10 @@ export class GBMinService {
(async () => { (async () => {
// Returns the instance object to clients requesting bot info. // Returns the instance object to clients requesting bot info.
let botId = req.params.botId; let botId = req.params.botId
let instance = await this.core.loadInstance(botId); let instance = await this.core.loadInstance(botId)
if (instance) { if (instance) {
let speechToken = await this.getSTSToken(instance); let speechToken = await this.getSTSToken(instance)
res.send( res.send(
JSON.stringify({ JSON.stringify({
@ -138,28 +138,28 @@ export class GBMinService {
speechToken: speechToken, speechToken: speechToken,
conversationId: webchatToken.conversationId conversationId: webchatToken.conversationId
}) })
); )
} else { } else {
let error = `Instance not found: ${botId}.`; let error = `Instance not found: ${botId}.`
res.sendStatus(error); res.sendStatus(error)
logger.error(error); logger.error(error)
} }
})(); })()
}); })
// Build bot adapter. // Build bot adapter.
var { min, adapter, conversationState } = await this.buildBotAdapter( var { min, adapter, conversationState } = await this.buildBotAdapter(
instance instance
); )
// Call the loadBot context.activity for all packages. // Call the loadBot context.activity for all packages.
this.invokeLoadBot(appPackages, min, server); this.invokeLoadBot(appPackages, min, server)
// Serves individual URL for each bot conversational interface... // Serves individual URL for each bot conversational interface...
let url = `/api/messages/${instance.botId}`; let url = `/api/messages/${instance.botId}`
server.post(url, async (req, res) => { server.post(url, async (req, res) => {
return this.receiver( return this.receiver(
adapter, adapter,
@ -169,67 +169,67 @@ export class GBMinService {
min, min,
instance, instance,
appPackages appPackages
); )
}); })
logger.info( logger.info(
`GeneralBots(${instance.engineName}) listening on: ${url}.` `GeneralBots(${instance.engineName}) listening on: ${url}.`
); )
// Serves individual URL for each bot user interface. // Serves individual URL for each bot user interface.
let uiUrl = `/${instance.botId}`; let uiUrl = `/${instance.botId}`
server.use( server.use(
uiUrl, uiUrl,
express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, "build")) express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, "build"))
); )
logger.info(`Bot UI ${uiPackage} acessible at: ${uiUrl}.`); logger.info(`Bot UI ${uiPackage} acessible at: ${uiUrl}.`)
// Setups handlers. // Setups handlers.
// send: function (context.activity, next) { // send: function (context.activity, next) {
// logger.info( // logger.info(
// `[SND]: ChannelID: ${context.activity.address.channelId}, ConversationID: ${context.activity.address.conversation}, // `[SND]: ChannelID: ${context.activity.address.channelId}, ConversationID: ${context.activity.address.conversation},
// Type: ${context.activity.type} `); // Type: ${context.activity.type} `)
// this.core.createMessage( // this.core.createMessage(
// this.min.conversation, // this.min.conversation,
// this.min.conversation.startedBy, // this.min.conversation.startedBy,
// context.activity.source, // context.activity.source,
// (data, err) => { // (data, err) => {
// logger.info(context.activity.source); // logger.info(context.activity.source)
// } // }
// ); // )
// next(); // next()
}) })
); )
} }
private async buildBotAdapter(instance: any) { private async buildBotAdapter(instance: any) {
let adapter = new BotFrameworkAdapter({ let adapter = new BotFrameworkAdapter({
appId: instance.marketplaceId, appId: instance.marketplaceId,
appPassword: instance.marketplacePassword appPassword: instance.marketplacePassword
}); })
const storage = new MemoryStorage(); const storage = new MemoryStorage()
const conversationState = new ConversationState(storage); const conversationState = new ConversationState(storage)
const userState = new UserState(storage); const userState = new UserState(storage)
adapter.use(new BotStateSet(conversationState, userState)); adapter.use(new BotStateSet(conversationState, userState))
// The minimal bot is built here. // The minimal bot is built here.
let min = new GBMinInstance(); let min = new GBMinInstance()
min.botId = instance.botId; min.botId = instance.botId
min.bot = adapter; min.bot = adapter
min.userState = userState; min.userState = userState
min.core = this.core; min.core = this.core
min.conversationalService = this.conversationalService; min.conversationalService = this.conversationalService
min.instance = await this.core.loadInstance(min.botId); min.instance = await this.core.loadInstance(min.botId)
min.dialogs.add("textPrompt", new TextPrompt()); min.dialogs.add("textPrompt", new TextPrompt())
return { min, adapter, conversationState }; return { min, adapter, conversationState }
} }
private invokeLoadBot(appPackages: any[], min: any, server: any) { private invokeLoadBot(appPackages: any[], min: any, server: any) {
appPackages.forEach(e => { appPackages.forEach(e => {
e.sysPackages = new Array<IGBPackage>(); e.sysPackages = new Array<IGBPackage>()
[ [
GBAdminPackage, GBAdminPackage,
GBAnalyticsPackage, GBAnalyticsPackage,
@ -239,19 +239,19 @@ export class GBMinService {
GBCustomerSatisfactionPackage, GBCustomerSatisfactionPackage,
GBWhatsappPackage GBWhatsappPackage
].forEach(sysPackage => { ].forEach(sysPackage => {
logger.info(`Loading sys package: ${sysPackage.name}...`); logger.info(`Loading sys package: ${sysPackage.name}...`)
let p = Object.create(sysPackage.prototype) as IGBPackage; let p = Object.create(sysPackage.prototype) as IGBPackage
p.loadBot(min); p.loadBot(min)
e.sysPackages.push(p); e.sysPackages.push(p)
if (sysPackage.name === "GBWhatsappPackage") { if (sysPackage.name === "GBWhatsappPackage") {
let url = "/instances/:botId/whatsapp"; let url = "/instances/:botId/whatsapp"
server.post(url, (req, res) => { server.post(url, (req, res) => {
p["channel"].received(req, res); p["channel"].received(req, res)
}); })
} }
}, this); }, this)
e.loadBot(min); e.loadBot(min)
}, this); }, this)
} }
/** /**
@ -267,18 +267,18 @@ export class GBMinService {
appPackages: any[] appPackages: any[]
) { ) {
return adapter.processActivity(req, res, async context => { return adapter.processActivity(req, res, async context => {
const state = conversationState.get(context); const state = conversationState.get(context)
const dc = min.dialogs.createContext(context, state); const dc = min.dialogs.createContext(context, state)
const user = min.userState.get(dc.context); const user = min.userState.get(dc.context)
if (!user.loaded) { if (!user.loaded) {
await min.conversationalService.sendEvent(dc, "loadInstance", { await min.conversationalService.sendEvent(dc, "loadInstance", {
instanceId: instance.instanceId, instanceId: instance.instanceId,
botId: instance.botId, botId: instance.botId,
theme: instance.theme, theme: instance.theme,
secret: instance.webchatKey secret: instance.webchatKey
}); })
user.loaded = true; user.loaded = true
user.subjects = []; user.subjects = []
} }
logger.info(`[RCV]: ${context.activity.type}, ChannelID: ${ logger.info(`[RCV]: ${context.activity.type}, ChannelID: ${
context.activity.channelId context.activity.channelId
@ -286,54 +286,54 @@ export class GBMinService {
ConversationID: ${context.activity.conversation.id}, ConversationID: ${context.activity.conversation.id},
Name: ${context.activity.name}, Text: ${ Name: ${context.activity.name}, Text: ${
context.activity.text context.activity.text
}.`); }.`)
if ( if (
context.activity.type === "conversationUpdate" && context.activity.type === "conversationUpdate" &&
context.activity.membersAdded.length > 0 context.activity.membersAdded.length > 0
) { ) {
let member = context.activity.membersAdded[0]; let member = context.activity.membersAdded[0]
if (member.name === "GeneralBots") { if (member.name === "GeneralBots") {
logger.info(`Bot added to conversation, starting chat...`); logger.info(`Bot added to conversation, starting chat...`)
appPackages.forEach(e => { appPackages.forEach(e => {
e.onNewSession(min, dc); e.onNewSession(min, dc)
}); })
await dc.begin("/"); await dc.begin("/")
} else { } else {
logger.info(`Member added to conversation: ${member.name}`); logger.info(`Member added to conversation: ${member.name}`)
} }
} else if (context.activity.type === "message") { } else if (context.activity.type === "message") {
// Check to see if anyone replied. If not then start echo dialog // Check to see if anyone replied. If not then start echo dialog
if (context.activity.text === "admin") { if (context.activity.text === "admin") {
await dc.begin("/admin"); await dc.begin("/admin")
} else { } else {
await dc.continue(); await dc.continue()
} }
} else if (context.activity.type === "event") { } else if (context.activity.type === "event") {
if (context.activity.name === "whoAmI") { if (context.activity.name === "whoAmI") {
await dc.begin("/whoAmI"); await dc.begin("/whoAmI")
} else if (context.activity.name === "showSubjects") { } else if (context.activity.name === "showSubjects") {
await dc.begin("/menu"); await dc.begin("/menu")
} else if (context.activity.name === "giveFeedback") { } else if (context.activity.name === "giveFeedback") {
await dc.begin("/feedback", { await dc.begin("/feedback", {
fromMenu: true fromMenu: true
}); })
} else if (context.activity.name === "showFAQ") { } else if (context.activity.name === "showFAQ") {
await dc.begin("/faq"); await dc.begin("/faq")
} else if (context.activity.name === "ask") { } else if (context.activity.name === "ask") {
await dc.begin("/answer", { await dc.begin("/answer", {
query: (context.activity as any).data, query: (context.activity as any).data,
fromFaq: true fromFaq: true
}); })
} else if (context.activity.name === "quality") { } else if (context.activity.name === "quality") {
await dc.begin("/quality", { await dc.begin("/quality", {
// TODO: score: context.activity.data // TODO: score: context.activity.data
}); })
} else { } else {
await dc.continue(); await dc.continue()
} }
} }
}); })
} }
/** /**
@ -349,15 +349,15 @@ export class GBMinService {
headers: { headers: {
Authorization: `Bearer ${instance.webchatKey}` Authorization: `Bearer ${instance.webchatKey}`
} }
}; }
try { try {
let json = await request(options); let json = await request(options)
return Promise.resolve(JSON.parse(json)); return Promise.resolve(JSON.parse(json))
} catch (error) { } catch (error) {
let msg = `Error calling Direct Line client, verify Bot endpoint on the cloud. Error is: ${error}.`; let msg = `Error calling Direct Line client, verify Bot endpoint on the cloud. Error is: ${error}.`
logger.error(msg); logger.error(msg)
return Promise.reject(msg); return Promise.reject(msg)
} }
} }
@ -376,14 +376,14 @@ export class GBMinService {
headers: { headers: {
"Ocp-Apim-Subscription-Key": instance.speechKey "Ocp-Apim-Subscription-Key": instance.speechKey
} }
}; }
try { try {
return await request(options); return await request(options)
} catch (error) { } catch (error) {
let msg = `Error calling Speech to Text client. Error is: ${error}.`; let msg = `Error calling Speech to Text client. Error is: ${error}.`
logger.error(msg); logger.error(msg)
return Promise.reject(msg); return Promise.reject(msg)
} }
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,14 +30,14 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
import { IGBDialog } from "botlib"; import { IGBDialog } from "botlib"
import { GBMinInstance } from "botlib"; import { GBMinInstance } from "botlib"
import { CSService } from "../services/CSService"; import { CSService } from "../services/CSService"
import { BotAdapter } from "botbuilder"; import { BotAdapter } from "botbuilder"
const logger = require("../../../src/logger"); const logger = require("../../../src/logger")
export class QualityDialog extends IGBDialog { export class QualityDialog extends IGBDialog {
@ -49,42 +49,42 @@ export class QualityDialog extends IGBDialog {
*/ */
static setup(bot: BotAdapter, min: GBMinInstance) { static setup(bot: BotAdapter, min: GBMinInstance) {
const service = new CSService(); const service = new CSService()
min.dialogs.add("/quality", [ min.dialogs.add("/quality", [
async (dc, args) => { async (dc, args) => {
const user = min.userState.get(dc.context); const user = min.userState.get(dc.context)
var score = args.score; var score = args.score
setTimeout( setTimeout(
() => min.conversationalService.sendEvent(dc, "stop", null), () => min.conversationalService.sendEvent(dc, "stop", null),
400 400
); )
if (score == 0) { if (score == 0) {
let msg = [ let msg = [
"Desculpe-me, vamos tentar novamente.", "Desculpe-me, vamos tentar novamente.",
"Lamento... Vamos tentar novamente!", "Lamento... Vamos tentar novamente!",
"Desculpe-me. Por favor, tente escrever de outra forma?" "Desculpe-me. Por favor, tente escrever de outra forma?"
]; ]
await dc.context.sendActivity(msg[0]); await dc.context.sendActivity(msg[0])
} else { } else {
let msg = [ let msg = [
"Ótimo, obrigado por contribuir com sua resposta.", "Ótimo, obrigado por contribuir com sua resposta.",
"Certo, obrigado pela informação.", "Certo, obrigado pela informação.",
"Obrigado pela contribuição." "Obrigado pela contribuição."
]; ]
await dc.context.sendActivity(msg[0]); await dc.context.sendActivity(msg[0])
await service.insertQuestionAlternate( await service.insertQuestionAlternate(
min.instance.instanceId, min.instance.instanceId,
user.lastQuestion, user.lastQuestion,
user.lastQuestionId user.lastQuestionId
); )
await dc.replace('/ask', {isReturning: true}); await dc.replace('/ask', {isReturning: true})
} }
} }
]); ])
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,29 +30,29 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
import { GuaribasQuestionAlternate } from './models/index'; import { GuaribasQuestionAlternate } from './models/index'
import { QualityDialog } from './dialogs/QualityDialog'; import { QualityDialog } from './dialogs/QualityDialog'
import { FeedbackDialog } from './dialogs/FeedbackDialog'; import { FeedbackDialog } from './dialogs/FeedbackDialog'
import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"; import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript'
export class GBCustomerSatisfactionPackage implements IGBPackage { export class GBCustomerSatisfactionPackage implements IGBPackage {
sysPackages: IGBPackage[] = null; sysPackages: IGBPackage[] = null
loadPackage(core: IGBCoreService, sequelize: Sequelize): void { loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
core.sequelize.addModels([ core.sequelize.addModels([
GuaribasQuestionAlternate GuaribasQuestionAlternate
]); ])
} }
unloadPackage(core: IGBCoreService): void { unloadPackage(core: IGBCoreService): void {
} }
loadBot(min: GBMinInstance): void { loadBot(min: GBMinInstance): void {
FeedbackDialog.setup(min.bot, min); FeedbackDialog.setup(min.bot, min)
QualityDialog.setup(min.bot, min); QualityDialog.setup(min.bot, min)
} }
unloadBot(min: GBMinInstance): void { unloadBot(min: GBMinInstance): void {

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,14 +30,14 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
import { import {
DataTypes, DataTypes,
DataTypeUUIDv4, DataTypeUUIDv4,
DataTypeDate, DataTypeDate,
DataTypeDecimal DataTypeDecimal
} from "sequelize"; } from "sequelize"
import { import {
Sequelize, Sequelize,
@ -55,9 +55,9 @@ import {
IsUUID, IsUUID,
PrimaryKey, PrimaryKey,
AutoIncrement AutoIncrement
} from "sequelize-typescript"; } from "sequelize-typescript"
import { GuaribasInstance } from "../../core.gbapp/models/GBModel"; import { GuaribasInstance } from "../../core.gbapp/models/GBModel"
@Table @Table
export class GuaribasQuestionAlternate extends Model<GuaribasQuestionAlternate> { export class GuaribasQuestionAlternate extends Model<GuaribasQuestionAlternate> {
@ -65,16 +65,16 @@ export class GuaribasQuestionAlternate extends Model<GuaribasQuestionAlternate>
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
quickAnswerId: number; quickAnswerId: number
@Column questionTyped: string; @Column questionTyped: string
@Column questionText: string; @Column questionText: string
@ForeignKey(() => GuaribasInstance) @ForeignKey(() => GuaribasInstance)
@Column @Column
instanceId: number; instanceId: number
@BelongsTo(() => GuaribasInstance) @BelongsTo(() => GuaribasInstance)
instance: GuaribasInstance; instance: GuaribasInstance
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,8 +30,8 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
import { GuaribasQuestionAlternate } from '../models'; import { GuaribasQuestionAlternate } from '../models'
import { GuaribasConversation } from '../../analytics.gblib/models'; import { GuaribasConversation } from '../../analytics.gblib/models'
export class CSService { export class CSService {
@ -61,7 +61,7 @@ export class CSService {
conversation: GuaribasConversation, conversation: GuaribasConversation,
rate: number rate: number
): Promise<GuaribasConversation> { ): Promise<GuaribasConversation> {
conversation.rate = rate; conversation.rate = rate
return conversation.save() return conversation.save()
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -80,16 +80,16 @@ export class AskDialog extends IGBDialog {
switch(locale) switch(locale)
{ {
case "pt": case "pt":
await dc.context.sendActivity("OK, mundando de idioma para o Português..."); await dc.context.sendActivity("OK, mundando de idioma para o Português...")
dc.context.activity.locale = "pt-BR"; dc.context.activity.locale = "pt-BR"
break; break
case "en": case "en":
await dc.context.sendActivity("OK, changing language to English..."); await dc.context.sendActivity("OK, changing language to English...")
dc.context.activity.locale = "en-US"; dc.context.activity.locale = "en-US"
break; break
default: default:
await dc.context.sendActivity(`Unknown language: ${locale}`); await dc.context.sendActivity(`Unknown language: ${locale}`)
break; break
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,12 +30,12 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
import { KBService } from './../services/KBService'; import { KBService } from './../services/KBService'
import { IGBDialog } from "botlib"; import { IGBDialog } from "botlib"
import { BotAdapter } from "botbuilder"; import { BotAdapter } from "botbuilder"
import { GBMinInstance } from "botlib"; import { GBMinInstance } from "botlib"
export class FaqDialog extends IGBDialog { export class FaqDialog extends IGBDialog {
/** /**
@ -46,11 +46,11 @@ export class FaqDialog extends IGBDialog {
*/ */
static setup(bot: BotAdapter, min: GBMinInstance) { static setup(bot: BotAdapter, min: GBMinInstance) {
const service = new KBService(min.core.sequelize); const service = new KBService(min.core.sequelize)
min.dialogs.add("/faq", [ min.dialogs.add("/faq", [
async (dc, args) => { async (dc, args) => {
let data = await service.getFaqBySubjectArray("faq", null); let data = await service.getFaqBySubjectArray("faq", null)
if (data) { if (data) {
await min.conversationalService.sendEvent(dc, "play", { await min.conversationalService.sendEvent(dc, "play", {
playerType: "bullet", playerType: "bullet",
@ -63,10 +63,10 @@ export class FaqDialog extends IGBDialog {
"Veja a lista que eu preparei logo aí na tela..." "Veja a lista que eu preparei logo aí na tela..."
] ]
await dc.context.sendActivity(messages[0]); // TODO: RND messages. await dc.context.sendActivity(messages[0]) // TODO: RND messages.
await dc.endAll(); await dc.endAll()
} }
} }
]); ])
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,15 +30,15 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
import { BotAdapter, CardFactory, MessageFactory } from "botbuilder"; import { BotAdapter, CardFactory, MessageFactory } from "botbuilder"
import { IGBDialog } from "botlib"; import { IGBDialog } from "botlib"
import { GBMinInstance } from "botlib"; import { GBMinInstance } from "botlib"
import { GuaribasSubject } from '../models'; import { GuaribasSubject } from '../models'
import { KBService } from "../services/KBService"; import { KBService } from "../services/KBService"
export class MenuDialog extends IGBDialog { export class MenuDialog extends IGBDialog {
@ -50,66 +50,66 @@ export class MenuDialog extends IGBDialog {
*/ */
static setup(bot: BotAdapter, min: GBMinInstance) { static setup(bot: BotAdapter, min: GBMinInstance) {
var service = new KBService(min.core.sequelize); var service = new KBService(min.core.sequelize)
bot bot
min.dialogs.add("/menu", [ min.dialogs.add("/menu", [
async (dc, args) => { async (dc, args) => {
var rootSubjectId = null; var rootSubjectId = null
// var msg = dc.message; TODO: message from Where in V4? // var msg = dc.message TODO: message from Where in V4?
// if (msg.attachments && msg.attachments.length > 0) { // if (msg.attachments && msg.attachments.length > 0) {
// var attachment = msg.attachments[0]; // var attachment = msg.attachments[0]
// } // }
if (args && args.data) { if (args && args.data) {
var subject = JSON.parse(args.data); // ? var subject = JSON.parse(args.data) // ?
// If there is a shortcut specified as subject destination, go there. // If there is a shortcut specified as subject destination, go there.
if (subject.to) { if (subject.to) {
let dialog = subject.to.split(":")[1]; let dialog = subject.to.split(":")[1]
await dc.replace("/" + dialog); await dc.replace("/" + dialog)
await dc.end(); await dc.end()
return; return
} }
const user = min.userState.get(dc.context); const user = min.userState.get(dc.context)
user.subjects.push(subject); user.subjects.push(subject)
rootSubjectId = subject.subjectId; rootSubjectId = subject.subjectId
if (user.subjects.length > 0) { if (user.subjects.length > 0) {
let data = await service.getFaqBySubjectArray("menu", user.subjects); let data = await service.getFaqBySubjectArray("menu", user.subjects)
await min.conversationalService.sendEvent(dc, "play", { await min.conversationalService.sendEvent(dc, "play", {
playerType: "bullet", playerType: "bullet",
data: data.slice(0, 6) data: data.slice(0, 6)
}); })
} }
} else { } else {
const user = min.userState.get(dc.context); const user = min.userState.get(dc.context)
user.subjects = []; user.subjects = []
let messages = [ let messages = [
"Aqui estão algumas categorias de assuntos...", "Aqui estão algumas categorias de assuntos...",
"Selecionando o assunto você pode me ajudar a encontrar a resposta certa...", "Selecionando o assunto você pode me ajudar a encontrar a resposta certa...",
"Você pode selecionar algum dos assuntos abaixo e perguntar algo..." "Você pode selecionar algum dos assuntos abaixo e perguntar algo..."
]; ]
await dc.context.sendActivity(messages[0]); // TODO: Handle rnd. await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
user.isAsking = false; user.isAsking = false
} }
const msg = MessageFactory.text(''); const msg = MessageFactory.text('')
var attachments = []; var attachments = []
let data = await service.getSubjectItems( let data = await service.getSubjectItems(
min.instance.instanceId, min.instance.instanceId,
rootSubjectId); rootSubjectId)
msg.attachmentLayout = 'carousel'; msg.attachmentLayout = 'carousel'
data.forEach(function (item: GuaribasSubject) { data.forEach(function (item: GuaribasSubject) {
var subject = item; var subject = item
var card = CardFactory.heroCard( var card = CardFactory.heroCard(
subject.title, subject.title,
CardFactory.images([UrlJoin( CardFactory.images([UrlJoin(
@ -127,39 +127,39 @@ export class MenuDialog extends IGBDialog {
subjectId: subject.subjectId, subjectId: subject.subjectId,
to: subject.to to: subject.to
}) })
}])); }]))
attachments.push(card); attachments.push(card)
}); })
if (attachments.length == 0) { if (attachments.length == 0) {
const user = min.userState.get(dc.context); const user = min.userState.get(dc.context)
if (user.subjects && user.subjects.length > 0) { if (user.subjects && user.subjects.length > 0) {
await dc.context.sendActivity( await dc.context.sendActivity(
`Vamos pesquisar sobre ${KBService.getFormattedSubjectItems( `Vamos pesquisar sobre ${KBService.getFormattedSubjectItems(
user.subjects user.subjects
)}?` )}?`
); )
} }
await dc.replace("/ask", {}); await dc.replace("/ask", {})
} else { } else {
msg.attachments = attachments; msg.attachments = attachments
await dc.context.sendActivity(msg); await dc.context.sendActivity(msg)
} }
const user = min.userState.get(dc.context); const user = min.userState.get(dc.context)
user.isAsking = true; user.isAsking = true
}, },
async (dc, value) => { async (dc, value) => {
var text = value; var text = value
if (text === "no" || text === "n") { // TODO: Migrate to a common. if (text === "no" || text === "n") { // TODO: Migrate to a common.
await dc.replace("/feedback"); await dc.replace("/feedback")
} else { } else {
await dc.replace("/ask"); await dc.replace("/ask")
} }
} }
]); ])
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,29 +30,29 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
import { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from './models/index'; import { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from './models/index'
import { GBMinInstance, IGBPackage } from "botlib"; import { GBMinInstance, IGBPackage } from "botlib"
import { AskDialog } from "./dialogs/AskDialog"; import { AskDialog } from "./dialogs/AskDialog"
import { FaqDialog } from "./dialogs/FaqDialog"; import { FaqDialog } from "./dialogs/FaqDialog"
import { MenuDialog } from "./dialogs/MenuDialog"; import { MenuDialog } from "./dialogs/MenuDialog"
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript'
import { IGBCoreService } from 'botlib'; import { IGBCoreService } from 'botlib'
export class GBKBPackage implements IGBPackage { export class GBKBPackage implements IGBPackage {
sysPackages: IGBPackage[] = null; sysPackages: IGBPackage[] = null
loadPackage(core: IGBCoreService, sequelize: Sequelize): void { loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
core.sequelize.addModels([ core.sequelize.addModels([
GuaribasAnswer, GuaribasAnswer,
GuaribasQuestion, GuaribasQuestion,
GuaribasSubject GuaribasSubject
]); ])
} }
unloadPackage(core: IGBCoreService): void { unloadPackage(core: IGBCoreService): void {
@ -60,9 +60,9 @@ export class GBKBPackage implements IGBPackage {
} }
loadBot(min: GBMinInstance): void { loadBot(min: GBMinInstance): void {
AskDialog.setup(min.bot, min); AskDialog.setup(min.bot, min)
FaqDialog.setup(min.bot, min); FaqDialog.setup(min.bot, min)
MenuDialog.setup(min.bot, min); MenuDialog.setup(min.bot, min)
} }
unloadBot(min: GBMinInstance): void { unloadBot(min: GBMinInstance): void {

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,14 +30,14 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
import { import {
DataTypes, DataTypes,
DataTypeUUIDv4, DataTypeUUIDv4,
DataTypeDate, DataTypeDate,
DataTypeDecimal DataTypeDecimal
} from "sequelize"; } from "sequelize"
import { import {
Sequelize, Sequelize,
@ -55,58 +55,58 @@ import {
IsUUID, IsUUID,
PrimaryKey, PrimaryKey,
AutoIncrement AutoIncrement
} from "sequelize-typescript"; } from "sequelize-typescript"
import { GuaribasUser } from "../../security.gblib/models"; import { GuaribasUser } from "../../security.gblib/models"
import { GuaribasInstance, GuaribasPackage } from "../../core.gbapp/models/GBModel"; import { GuaribasInstance, GuaribasPackage } from "../../core.gbapp/models/GBModel"
@Table @Table
export class GuaribasSubject extends Model<GuaribasSubject> { export class GuaribasSubject extends Model<GuaribasSubject> {
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
subjectId: number; subjectId: number
@Column internalId: string; @Column internalId: string
@Column title: string; @Column title: string
@Column description: string; @Column description: string
@Column from: string; @Column from: string
@Column to: string; @Column to: string
@ForeignKey(() => GuaribasSubject) @ForeignKey(() => GuaribasSubject)
@Column @Column
parentSubjectId: number; parentSubjectId: number
@BelongsTo(() => GuaribasSubject, "parentSubjectId") @BelongsTo(() => GuaribasSubject, "parentSubjectId")
parentSubject: GuaribasSubject; parentSubject: GuaribasSubject
@HasMany(() => GuaribasSubject, { foreignKey: "parentSubjectId" }) @HasMany(() => GuaribasSubject, { foreignKey: "parentSubjectId" })
childrenSubjects: GuaribasSubject[]; childrenSubjects: GuaribasSubject[]
@ForeignKey(() => GuaribasInstance) @ForeignKey(() => GuaribasInstance)
@Column @Column
instanceId: number; instanceId: number
@BelongsTo(() => GuaribasInstance) @BelongsTo(() => GuaribasInstance)
instance: GuaribasInstance; instance: GuaribasInstance
@ForeignKey(() => GuaribasUser) @ForeignKey(() => GuaribasUser)
@Column @Column
responsibleUserId: number; responsibleUserId: number
@BelongsTo(() => GuaribasUser) @BelongsTo(() => GuaribasUser)
responsibleUser: GuaribasUser; responsibleUser: GuaribasUser
@ForeignKey(() => GuaribasPackage) @ForeignKey(() => GuaribasPackage)
@Column @Column
packageId: number; packageId: number
@BelongsTo(() => GuaribasPackage) @BelongsTo(() => GuaribasPackage)
package: GuaribasPackage; package: GuaribasPackage
} }
@Table @Table
@ -114,62 +114,62 @@ export class GuaribasQuestion extends Model<GuaribasQuestion> {
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
questionId: number; questionId: number
@Column(DataType.STRING(64)) @Column(DataType.STRING(64))
@Column @Column
subject1: string; subject1: string
@Column(DataType.STRING(64)) @Column(DataType.STRING(64))
@Column @Column
subject2: string; subject2: string
@Column(DataType.STRING(64)) @Column(DataType.STRING(64))
@Column @Column
subject3: string; subject3: string
@Column(DataType.STRING(64)) @Column(DataType.STRING(64))
@Column @Column
subject4: string; subject4: string
@Column(DataType.STRING(1024)) @Column(DataType.STRING(1024))
@Column @Column
keywords: string; keywords: string
@Column(DataType.STRING(512)) @Column(DataType.STRING(512))
from: string; from: string
@Column(DataType.STRING(512)) @Column(DataType.STRING(512))
to: string; to: string
@Column(DataType.TEXT) @Column(DataType.TEXT)
content: string; content: string
@Column @Column
@CreatedAt @CreatedAt
createdAt: Date; createdAt: Date
@Column @Column
@UpdatedAt @UpdatedAt
updatedAt: Date; updatedAt: Date
@ForeignKey(() => GuaribasAnswer) @ForeignKey(() => GuaribasAnswer)
@Column @Column
answerId: number; answerId: number
@BelongsTo(() => GuaribasInstance) @BelongsTo(() => GuaribasInstance)
instance: GuaribasInstance; instance: GuaribasInstance
@ForeignKey(() => GuaribasInstance) @ForeignKey(() => GuaribasInstance)
@Column @Column
instanceId: number; instanceId: number
@ForeignKey(() => GuaribasPackage) @ForeignKey(() => GuaribasPackage)
@Column @Column
packageId: number; packageId: number
@BelongsTo(() => GuaribasPackage) @BelongsTo(() => GuaribasPackage)
package: GuaribasPackage; package: GuaribasPackage
} }
@Table @Table
@ -177,39 +177,39 @@ export class GuaribasAnswer extends Model<GuaribasAnswer> {
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
answerId: number; answerId: number
@Length({ min: 0, max: 512 }) @Length({ min: 0, max: 512 })
@Column @Column
media: string; media: string
@Length({ min: 0, max: 12 }) @Length({ min: 0, max: 12 })
@Column @Column
format: string; format: string
@Column(DataType.TEXT) @Column(DataType.TEXT)
content: string; content: string
@Column @Column
@CreatedAt @CreatedAt
createdAt: Date; createdAt: Date
@Column @Column
@UpdatedAt @UpdatedAt
updatedAt: Date; updatedAt: Date
@HasMany(() => GuaribasQuestion) @HasMany(() => GuaribasQuestion)
questions: GuaribasQuestion[]; questions: GuaribasQuestion[]
@ForeignKey(() => GuaribasInstance) @ForeignKey(() => GuaribasInstance)
@Column @Column
instanceId: number; instanceId: number
@ForeignKey(() => GuaribasPackage) @ForeignKey(() => GuaribasPackage)
@Column @Column
packageId: number; packageId: number
@BelongsTo(() => GuaribasPackage) @BelongsTo(() => GuaribasPackage)
package: GuaribasPackage; package: GuaribasPackage
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -505,7 +505,7 @@ export class KBService {
await this.importSubjectFile( await this.importSubjectFile(
packageStorage.packageId, packageStorage.packageId,
UrlJoin(localPath, "subjects.json"), UrlJoin(localPath, "subjects.json"),
instance); instance)
// Import all .tsv files in the tabular directory. // Import all .tsv files in the tabular directory.

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,24 +30,24 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"; import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"
import { Sequelize } from "sequelize-typescript"; import { Sequelize } from "sequelize-typescript"
import { GuaribasUser, GuaribasGroup, GuaribasUserGroup } from "./models"; import { GuaribasUser, GuaribasGroup, GuaribasUserGroup } from "./models"
export class GBSecurityPackage implements IGBPackage { export class GBSecurityPackage implements IGBPackage {
sysPackages: IGBPackage[] = null; sysPackages: IGBPackage[] = null
loadPackage(core: IGBCoreService, sequelize: Sequelize): void { loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
core.sequelize.addModels([ core.sequelize.addModels([
GuaribasGroup, GuaribasGroup,
GuaribasUser, GuaribasUser,
GuaribasUserGroup GuaribasUserGroup
]); ])
} }
unloadPackage(core: IGBCoreService): void { unloadPackage(core: IGBCoreService): void {

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,14 +30,14 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
import { import {
DataTypes, DataTypes,
DataTypeUUIDv4, DataTypeUUIDv4,
DataTypeDate, DataTypeDate,
DataTypeDecimal DataTypeDecimal
} from "sequelize"; } from "sequelize"
import { import {
Sequelize, Sequelize,
@ -55,35 +55,35 @@ import {
IsUUID, IsUUID,
PrimaryKey, PrimaryKey,
AutoIncrement AutoIncrement
} from "sequelize-typescript"; } from "sequelize-typescript"
import { GuaribasInstance } from "../../core.gbapp/models/GBModel"; import { GuaribasInstance } from "../../core.gbapp/models/GBModel"
@Table @Table
export class GuaribasUser extends Model<GuaribasUser> { export class GuaribasUser extends Model<GuaribasUser> {
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
userId: number; userId: number
@Column displayName: string; @Column displayName: string
@Column userSystemId: string; @Column userSystemId: string
@Column userName: string; @Column userName: string
@Column defaultChannel: string; @Column defaultChannel: string
@Column email: string; @Column email: string
@Column(DataType.STRING(512)) @Column(DataType.STRING(512))
internalAddress: string; internalAddress: string
@ForeignKey(() => GuaribasInstance) @ForeignKey(() => GuaribasInstance)
@Column @Column
instanceId: number; instanceId: number
@BelongsTo(() => GuaribasInstance) @BelongsTo(() => GuaribasInstance)
instance: GuaribasInstance; instance: GuaribasInstance
} }
@Table @Table
@ -91,40 +91,40 @@ export class GuaribasGroup extends Model<GuaribasGroup> {
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
groupId: number; groupId: number
@Length({ min: 0, max: 512 }) @Length({ min: 0, max: 512 })
@Column @Column
displayName: string; displayName: string
@ForeignKey(() => GuaribasInstance) @ForeignKey(() => GuaribasInstance)
@Column @Column
instanceId: number; instanceId: number
@BelongsTo(() => GuaribasInstance) @BelongsTo(() => GuaribasInstance)
instance: GuaribasInstance; instance: GuaribasInstance
} }
@Table @Table
export class GuaribasUserGroup extends Model<GuaribasUserGroup> { export class GuaribasUserGroup extends Model<GuaribasUserGroup> {
@ForeignKey(() => GuaribasUser) @ForeignKey(() => GuaribasUser)
@Column @Column
userId: number; userId: number
@ForeignKey(() => GuaribasGroup) @ForeignKey(() => GuaribasGroup)
@Column @Column
groupId: number; groupId: number
@ForeignKey(() => GuaribasInstance) @ForeignKey(() => GuaribasInstance)
@Column @Column
instanceId: number; instanceId: number
@BelongsTo(() => GuaribasInstance) @BelongsTo(() => GuaribasInstance)
instance: GuaribasInstance; instance: GuaribasInstance
@BelongsTo(() => GuaribasGroup) @BelongsTo(() => GuaribasGroup)
group: GuaribasGroup; group: GuaribasGroup
@BelongsTo(() => GuaribasUser) @BelongsTo(() => GuaribasUser)
user: GuaribasUser; user: GuaribasUser
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,45 +30,45 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
const Path = require("path"); const Path = require("path")
const Fs = require("fs"); const Fs = require("fs")
const _ = require("lodash"); const _ = require("lodash")
const Parse = require("csv-parse"); const Parse = require("csv-parse")
const Async = require("async"); const Async = require("async")
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
const Walk = require("fs-walk"); const Walk = require("fs-walk")
const logger = require("../../../src/logger"); const logger = require("../../../src/logger")
import { GBServiceCallback, GBService, IGBInstance } from "botlib"; import { GBServiceCallback, GBService, IGBInstance } from "botlib"
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from "../models"; import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from "../models"
export class SecService extends GBService { export class SecService extends GBService {
async importSecurityFile(localPath: string, instance: IGBInstance) { async importSecurityFile(localPath: string, instance: IGBInstance) {
let security = JSON.parse( let security = JSON.parse(
Fs.readFileSync(UrlJoin(localPath, "security.json"), "utf8") Fs.readFileSync(UrlJoin(localPath, "security.json"), "utf8")
); )
security.groups.forEach(group => { security.groups.forEach(group => {
let groupDb = GuaribasGroup.build({ let groupDb = GuaribasGroup.build({
instanceId: instance.instanceId, instanceId: instance.instanceId,
displayName: group.displayName displayName: group.displayName
}); })
groupDb.save().then(groupDb => { groupDb.save().then(groupDb => {
group.users.forEach(user => { group.users.forEach(user => {
let userDb = GuaribasUser.build({ let userDb = GuaribasUser.build({
instanceId: instance.instanceId, instanceId: instance.instanceId,
groupId: groupDb.groupId, groupId: groupDb.groupId,
userName: user.userName userName: user.userName
}); })
userDb.save().then(userDb => { userDb.save().then(userDb => {
let userGroup = GuaribasUserGroup.build(); let userGroup = GuaribasUserGroup.build()
userGroup.groupId = groupDb.groupId; userGroup.groupId = groupDb.groupId
userGroup.userId = userDb.userId; userGroup.userId = userDb.userId
userGroup.save(); userGroup.save()
}); })
}); })
}); })
}); })
} }
async ensureUser( async ensureUser(
@ -90,17 +90,17 @@ export class SecService extends GBService {
} }
}).then(user => { }).then(user => {
if (!user) { if (!user) {
user = GuaribasUser.build(); user = GuaribasUser.build()
} }
user.userSystemId = userSystemId; user.userSystemId = userSystemId
user.userName = userName; user.userName = userName
user.displayName = displayName; user.displayName = displayName
user.internalAddress = address; user.internalAddress = address
user.email = userName; user.email = userName
user.defaultChannel = channelName; user.defaultChannel = channelName
user.save(); user.save()
resolve(user); resolve(user)
}).error(reason => reject(reason)); }).error(reason => reject(reason))
}); })
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,21 +30,21 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"; import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"
import { Sequelize } from "sequelize-typescript"; import { Sequelize } from "sequelize-typescript"
import { WhatsappDirectLine } from "./services/WhatsappDirectLine"; import { WhatsappDirectLine } from "./services/WhatsappDirectLine"
export class GBWhatsappPackage implements IGBPackage { export class GBWhatsappPackage implements IGBPackage {
sysPackages: IGBPackage[] = null; sysPackages: IGBPackage[] = null
channel: WhatsappDirectLine; channel: WhatsappDirectLine
loadPackage(core: IGBCoreService, sequelize: Sequelize): void { loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
} }
@ -59,7 +59,7 @@ export class GBWhatsappPackage implements IGBPackage {
if (min.instance.whatsappBotKey != "") { if (min.instance.whatsappBotKey != "") {
this.channel = new WhatsappDirectLine(min.botId, min.instance.whatsappBotKey, min.instance.whatsappServiceKey, this.channel = new WhatsappDirectLine(min.botId, min.instance.whatsappBotKey, min.instance.whatsappServiceKey,
min.instance.whatsappServiceNumber, min.instance.whatsappServiceUrl, min.instance.whatsappServiceWebhookUrl); min.instance.whatsappServiceNumber, min.instance.whatsappServiceUrl, min.instance.whatsappServiceWebhookUrl)
} }
} }

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,45 +30,45 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
const Path = require("path"); const Path = require("path")
const Fs = require("fs"); const Fs = require("fs")
const _ = require("lodash"); const _ = require("lodash")
const Parse = require("csv-parse"); const Parse = require("csv-parse")
const Async = require("async"); const Async = require("async")
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
const Walk = require("fs-walk"); const Walk = require("fs-walk")
const logger = require("../../../src/logger"); const logger = require("../../../src/logger")
const Swagger = require('swagger-client'); const Swagger = require('swagger-client')
const rp = require('request-promise'); const rp = require('request-promise')
import * as request from "request-promise-native"; import * as request from "request-promise-native"
import { GBServiceCallback, GBService, IGBInstance } from "botlib"; import { GBServiceCallback, GBService, IGBInstance } from "botlib"
export class WhatsappDirectLine extends GBService { export class WhatsappDirectLine extends GBService {
pollInterval = 1000; pollInterval = 1000
directLineClientName = 'DirectLineClient'; directLineClientName = 'DirectLineClient'
directLineSpecUrl = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json'; directLineSpecUrl = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json'
directLineClient: any; directLineClient: any
whatsappServiceKey: string; whatsappServiceKey: string
whatsappServiceNumber: string; whatsappServiceNumber: string
whatsappServiceUrl: string; whatsappServiceUrl: string
whatsappServiceWebhookUrl: string; whatsappServiceWebhookUrl: string
botId: string; botId: string
watermark: string = null; watermark: string = null
conversationIds = {}; conversationIds = {}
constructor(botId, directLineSecret, whatsappServiceKey, whatsappServiceNumber, whatsappServiceUrl, whatsappServiceWebhookUrl) { constructor(botId, directLineSecret, whatsappServiceKey, whatsappServiceNumber, whatsappServiceUrl, whatsappServiceWebhookUrl) {
super(); super()
this.botId = botId; this.botId = botId
this.whatsappServiceKey = whatsappServiceKey; this.whatsappServiceKey = whatsappServiceKey
this.whatsappServiceNumber = whatsappServiceNumber; this.whatsappServiceNumber = whatsappServiceNumber
this.whatsappServiceUrl = whatsappServiceUrl; this.whatsappServiceUrl = whatsappServiceUrl
this.whatsappServiceWebhookUrl = whatsappServiceWebhookUrl; this.whatsappServiceWebhookUrl = whatsappServiceWebhookUrl
// TODO: Migrate to Swagger 3. // TODO: Migrate to Swagger 3.
this.directLineClient = rp(this.directLineSpecUrl) this.directLineClient = rp(this.directLineSpecUrl)
@ -76,12 +76,12 @@ export class WhatsappDirectLine extends GBService {
return new Swagger({ return new Swagger({
spec: JSON.parse(spec.trim()), spec: JSON.parse(spec.trim()),
usePromise: true usePromise: true
}); })
}) })
.then(async (client) => { .then(async (client) => {
client.clientAuthorizations.add('AuthorizationBotConnector', client.clientAuthorizations.add('AuthorizationBotConnector',
new Swagger.ApiKeyAuthorization('Authorization', 'Bearer ' + new Swagger.ApiKeyAuthorization('Authorization', 'Bearer ' +
directLineSecret, 'header')); directLineSecret, 'header'))
var options = { var options = {
method: 'POST', method: 'POST',
@ -96,63 +96,63 @@ export class WhatsappDirectLine extends GBService {
{ {
'cache-control': 'no-cache' 'cache-control': 'no-cache'
} }
};
try {
const result = await request.post(options);
logger.info(result);
} catch (error) {
logger.error('Error initializing 3rd party Whatsapp provider.', error);
} }
return client; try {
const result = await request.post(options)
logger.info(result)
} catch (error) {
logger.error('Error initializing 3rd party Whatsapp provider.', error)
}
return client
}) })
.catch((err) => { .catch((err) => {
logger.error('Error initializing DirectLine client', err); logger.error('Error initializing DirectLine client', err)
}); })
} }
received(req, res) { received(req, res) {
let text = req.body.messages[0].body; let text = req.body.messages[0].body
let from = req.body.messages[0].author.split('@')[0]; let from = req.body.messages[0].author.split('@')[0]
let fromName = req.body.messages[0].senderName; let fromName = req.body.messages[0].senderName
if (req.body.messages[0].fromMe) { if (req.body.messages[0].fromMe) {
return; // Exit here. return // Exit here.
} }
logger.info(`GBWhatsapp: Hook called. from: ${from}(${fromName}), text: ${text})`); logger.info(`GBWhatsapp: Hook called. from: ${from}(${fromName}), text: ${text})`)
let conversationId = this.conversationIds[from]; let conversationId = this.conversationIds[from]
this.directLineClient.then((client) => { this.directLineClient.then((client) => {
if (this.conversationIds[from] == null) { if (this.conversationIds[from] == null) {
logger.info(`GBWhatsapp: Starting new conversation on Bot.`); logger.info(`GBWhatsapp: Starting new conversation on Bot.`)
client.Conversations.Conversations_StartConversation() client.Conversations.Conversations_StartConversation()
.then((response) => { .then((response) => {
return response.obj.conversationId; return response.obj.conversationId
}) })
.then((conversationId) => { .then((conversationId) => {
this.conversationIds[from] = conversationId; this.conversationIds[from] = conversationId
this.inputMessage(client, conversationId, text, this.inputMessage(client, conversationId, text,
from, fromName); from, fromName)
this.pollMessages(client, conversationId, from, fromName); this.pollMessages(client, conversationId, from, fromName)
}) })
.catch((err) => { .catch((err) => {
console.error('Error starting conversation', err); console.error('Error starting conversation', err)
}); })
} else { } else {
this.inputMessage(client, conversationId, text, this.inputMessage(client, conversationId, text,
from, fromName); from, fromName)
} }
res.end(); res.end()
}); })
} }
@ -172,15 +172,15 @@ export class WhatsappDirectLine extends GBService {
replyToId: from replyToId: from
} }
}).catch((err) => { }).catch((err) => {
logger.error(`GBWhatsapp: Error receiving message: ${err}.`); logger.error(`GBWhatsapp: Error receiving message: ${err}.`)
}); })
} }
pollMessages(client, conversationId, from, fromName) { pollMessages(client, conversationId, from, fromName) {
logger.info(`GBWhatsapp: Starting polling message for conversationId: logger.info(`GBWhatsapp: Starting polling message for conversationId:
${conversationId}.`); ${conversationId}.`)
setInterval(() => { setInterval(() => {
client.Conversations.Conversations_GetActivities({ client.Conversations.Conversations_GetActivities({
@ -188,13 +188,13 @@ export class WhatsappDirectLine extends GBService {
conversationId, watermark: this.watermark conversationId, watermark: this.watermark
}) })
.then((response) => { .then((response) => {
this.watermark = response.obj.watermark; this.watermark = response.obj.watermark
return response.obj.activities; return response.obj.activities
}) })
.then((activities) => { .then((activities) => {
this.printMessages(activities, conversationId, from, fromName); this.printMessages(activities, conversationId, from, fromName)
}); })
}, this.pollInterval); }, this.pollInterval)
} }
printMessages(activities, conversationId, from, fromName) { printMessages(activities, conversationId, from, fromName) {
@ -203,48 +203,48 @@ export class WhatsappDirectLine extends GBService {
// Ignore own messages. // Ignore own messages.
// TODO: this.botId instead of "general-bot-9672a8d3" // TODO: this.botId instead of "general-bot-9672a8d3"
activities = activities.filter((m) => { return (m.from.id === "GeneralBots") && m.type === "message" }); activities = activities.filter((m) => { return (m.from.id === "GeneralBots") && m.type === "message" })
if (activities.length) { if (activities.length) {
// Print other messages. // Print other messages.
activities.forEach(activity => { activities.forEach(activity => {
this.printMessage(activity, conversationId, from, fromName); this.printMessage(activity, conversationId, from, fromName)
}); })
} }
} }
} }
printMessage(activity, conversationId, from, fromName) { printMessage(activity, conversationId, from, fromName) {
let output = ""; let output = ""
if (activity.text) { if (activity.text) {
logger.info(`GBWhatsapp: MSG: ${activity.text}`); logger.info(`GBWhatsapp: MSG: ${activity.text}`)
output = activity.text; output = activity.text
} }
if (activity.attachments) { if (activity.attachments) {
activity.attachments.forEach((attachment) => { activity.attachments.forEach((attachment) => {
switch (attachment.contentType) { switch (attachment.contentType) {
case "application/vnd.microsoft.card.hero": case "application/vnd.microsoft.card.hero":
output += `\n${this.renderHeroCard(attachment)}`; output += `\n${this.renderHeroCard(attachment)}`
break; break
case "image/png": case "image/png":
logger.info('Opening the requested image ' + attachment.contentUrl); logger.info('Opening the requested image ' + attachment.contentUrl)
output += `\n${attachment.contentUrl}`; output += `\n${attachment.contentUrl}`
break; break
} }
}); })
} }
this.sendToDevice(conversationId, from, fromName, output); this.sendToDevice(conversationId, from, fromName, output)
} }
renderHeroCard(attachment) { renderHeroCard(attachment) {
return `${attachment.content.title} - ${attachment.content.text}`; return `${attachment.content.title} - ${attachment.content.text}`
} }
async sendToDevice(conversationId, to, toName, msg) { async sendToDevice(conversationId, to, toName, msg) {
@ -261,8 +261,8 @@ export class WhatsappDirectLine extends GBService {
{ {
'cache-control': 'no-cache' 'cache-control': 'no-cache'
} }
}; }
const result = await request.get(options); const result = await request.get(options)
} }
} }

View file

@ -20,7 +20,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -31,30 +31,30 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict"; "use strict"
const UrlJoin = require("url-join"); const UrlJoin = require("url-join")
const logger = require("./logger"); const logger = require("./logger")
const express = require("express"); const express = require("express")
const bodyParser = require("body-parser"); const bodyParser = require("body-parser")
import { Sequelize } from "sequelize-typescript"; import { Sequelize } from "sequelize-typescript"
import { GBConfigService } from "../deploy/core.gbapp/services/GBConfigService"; import { GBConfigService } from "../deploy/core.gbapp/services/GBConfigService"
import { GBConversationalService } from "../deploy/core.gbapp/services/GBConversationalService"; import { GBConversationalService } from "../deploy/core.gbapp/services/GBConversationalService"
import { GBMinService } from "../deploy/core.gbapp/services/GBMinService"; import { GBMinService } from "../deploy/core.gbapp/services/GBMinService"
import { GBDeployer } from "../deploy/core.gbapp/services/GBDeployer"; import { GBDeployer } from "../deploy/core.gbapp/services/GBDeployer"
import { GBWhatsappPackage } from './../deploy/whatsapp.gblib/index'; import { GBWhatsappPackage } from './../deploy/whatsapp.gblib/index'
import { GBCoreService } from "../deploy/core.gbapp/services/GBCoreService"; import { GBCoreService } from "../deploy/core.gbapp/services/GBCoreService"
import { GBImporter } from "../deploy/core.gbapp/services/GBImporter"; import { GBImporter } from "../deploy/core.gbapp/services/GBImporter"
import { GBAnalyticsPackage } from "../deploy/analytics.gblib"; import { GBAnalyticsPackage } from "../deploy/analytics.gblib"
import { GBCorePackage } from "../deploy/core.gbapp"; import { GBCorePackage } from "../deploy/core.gbapp"
import { GBKBPackage } from '../deploy/kb.gbapp'; import { GBKBPackage } from '../deploy/kb.gbapp'
import { GBSecurityPackage } from '../deploy/security.gblib'; import { GBSecurityPackage } from '../deploy/security.gblib'
import { GBAdminPackage } from '../deploy/admin.gbapp/index'; import { GBAdminPackage } from '../deploy/admin.gbapp/index'
import { GBCustomerSatisfactionPackage } from "../deploy/customer-satisfaction.gbapp"; import { GBCustomerSatisfactionPackage } from "../deploy/customer-satisfaction.gbapp"
import { IGBPackage } from 'botlib'; import { IGBPackage } from 'botlib'
let appPackages = new Array<IGBPackage>(); let appPackages = new Array<IGBPackage>()
/** /**
* General Bots open-core entry point. * General Bots open-core entry point.
@ -68,60 +68,60 @@ export class GBServer {
// bot instance. This allows the same server to attend multiple Bot on // bot instance. This allows the same server to attend multiple Bot on
// the Marketplace until GB get serverless. // the Marketplace until GB get serverless.
let port = process.env.port || process.env.PORT || 4242; let port = process.env.port || process.env.PORT || 4242
logger.info(`The Bot Server is in STARTING mode...`); logger.info(`The Bot Server is in STARTING mode...`)
let server = express(); let server = express()
server.use(bodyParser.json()); // to support JSON-encoded bodies server.use(bodyParser.json()) // to support JSON-encoded bodies
server.use(bodyParser.urlencoded({ // to support URL-encoded bodies server.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true extended: true
})); }))
server.listen(port, () => { server.listen(port, () => {
(async () => { (async () => {
try { try {
logger.info(`Accepting connections on ${port}...`); logger.info(`Accepting connections on ${port}...`)
logger.info(`Starting instances...`); logger.info(`Starting instances...`)
// Reads basic configuration, initialize minimal services. // Reads basic configuration, initialize minimal services.
GBConfigService.init(); GBConfigService.init()
let core = new GBCoreService(); let core = new GBCoreService()
await core.initDatabase(); await core.initDatabase()
// Boot a bot package if any. // Boot a bot package if any.
let deployer = new GBDeployer(core, new GBImporter(core)); let deployer = new GBDeployer(core, new GBImporter(core))
// Build a minimal bot instance for each .gbot deployment. // Build a minimal bot instance for each .gbot deployment.
let conversationalService = new GBConversationalService(core); let conversationalService = new GBConversationalService(core)
let minService = new GBMinService(core, conversationalService, deployer); let minService = new GBMinService(core, conversationalService, deployer)
[GBAdminPackage, GBAnalyticsPackage, GBCorePackage, GBSecurityPackage, [GBAdminPackage, GBAnalyticsPackage, GBCorePackage, GBSecurityPackage,
GBKBPackage, GBCustomerSatisfactionPackage, GBWhatsappPackage].forEach(e => { GBKBPackage, GBCustomerSatisfactionPackage, GBWhatsappPackage].forEach(e => {
logger.info(`Loading sys package: ${e.name}...`); logger.info(`Loading sys package: ${e.name}...`)
let p = Object.create(e.prototype) as IGBPackage; let p = Object.create(e.prototype) as IGBPackage
p.loadPackage(core, core.sequelize); p.loadPackage(core, core.sequelize)
}); })
await deployer.deployPackages(core, server, appPackages); await deployer.deployPackages(core, server, appPackages)
logger.info(`The Bot Server is in RUNNING mode...`); logger.info(`The Bot Server is in RUNNING mode...`)
let instance = await minService.buildMin(server, appPackages); let instance = await minService.buildMin(server, appPackages)
logger.info(`Instance loaded: ${instance.botId}...`); logger.info(`Instance loaded: ${instance.botId}...`)
return core; return core
} catch (err) { } catch (err) {
logger.info(err); logger.info(err)
} }
})() })()
}); })
} }
} }
// First line to run. // First line to run.
GBServer.run(); GBServer.run()

View file

@ -19,7 +19,7 @@
| in the LICENSE file you have received along with this program. | | in the LICENSE file you have received along with this program. |
| | | |
| This program is distributed in the hope that it will be useful, | | This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. | | GNU Affero General Public License for more details. |
| | | |
@ -30,7 +30,7 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
const { createLogger, format, transports } = require('winston'); const { createLogger, format, transports } = require('winston')
const config = { const config = {
levels: { levels: {
@ -53,7 +53,7 @@ const config = {
silly: 'magenta', silly: 'magenta',
custom: 'yellow' custom: 'yellow'
} }
}; }
const logger = createLogger({ const logger = createLogger({
format: format.combine( format: format.combine(
@ -62,11 +62,11 @@ const logger = createLogger({
format.label({ label: 'GeneralBots' }), format.label({ label: 'GeneralBots' }),
format.timestamp(), format.timestamp(),
format.printf(nfo => { format.printf(nfo => {
return `${nfo.timestamp} [${nfo.label}] ${nfo.level}: ${nfo.message}`; return `${nfo.timestamp} [${nfo.label}] ${nfo.level}: ${nfo.message}`
}) })
), ),
levels: config.levels, levels: config.levels,
transports: [new transports.Console()] transports: [new transports.Console()]
}); })
module.exports=logger; module.exports=logger