Compare commits

..

No commits in common. "27dde0f4f06166fbf7c0b9174f372cbde6c6a1ba" and "300b5dc258f8ec305d987801640540def4327a8b" have entirely different histories.

5 changed files with 222 additions and 107 deletions

30
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,30 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"sourceMaps": true,
"name": "Debug Program",
"runtimeExecutable": "node",
"program": "${workspaceRoot}/boot.mjs",
"cwd": "${workspaceRoot}",
"env": {
"NODE_ENV": "development",
"NODE_NO_WARNINGS": "1"
},
"args": [
"--require", "${workspaceRoot}/suppress-node-warnings.cjs"
],
"skipFiles": [
"node_modules/**/*.js",
"<node_internals>/**"
],
"outFiles": [
"${workspaceRoot}/dist/**/*.js"
],
"stopOnEntry": false,
"console": "integratedTerminal"
}
]
}

4
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,4 @@
{
"git.ignoreLimitWarning": true,
"cmake.ignoreCMakeListsMissing": true
}

30
.vscode/tasks.json vendored Normal file
View file

@ -0,0 +1,30 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"type": "typescript",
"tsconfig": "tsconfig.json",
"option": "watch",
"problemMatcher": [
"$tsc-watch"
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"type": "typescript",
"tsconfig": "tsconfig.json",
"problemMatcher": [
"$tsc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View file

@ -162,15 +162,16 @@ export class GBMinService {
// Servers default UI on root address '/' if web enabled. // Servers default UI on root address '/' if web enabled.
if (process.env.DISABLE_WEB !== 'true' || process.env.ENABLE_INSTANCE_ON_URL) { if (process.env.DISABLE_WEB !== 'true' || process.env.ENABLE_INSTANCE_ON_URL) {
// Servers the bot information object via HTTP so clients can get // Servers the bot information object via HTTP so clients can get
// instance information stored on server. // instance information stored on server.
GBServer.globals.server.use( GBServer.globals.server.use(cors({
cors({ origin: 'https://gb6.pragmatismo.com.br',
origin: 'https://gb6.pragmatismo.com.br', methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization', 'x-requested-with'
allowedHeaders: ['Content-Type', 'Authorization', 'x-requested-with', 'x-ms-bot-agent'] , 'x-ms-bot-agent'
}) ]
); }));
GBServer.globals.server.get('/instances/:botId', this.handleGetInstanceForClient.bind(this)); GBServer.globals.server.get('/instances/:botId', this.handleGetInstanceForClient.bind(this));
} }
@ -212,11 +213,14 @@ export class GBMinService {
const user = await sec.ensureUser(min, 'testuser', 'testuser', '', 'test', 'testuser', null); const user = await sec.ensureUser(min, 'testuser', 'testuser', '', 'test', 'testuser', null);
const pid = GBVMService.createProcessInfo(user, min, 'api', null); const pid = GBVMService.createProcessInfo(user, min, 'api', null);
const response = await client.apis.Conversations.Conversations_StartConversation({ const response = await client.apis.Conversations.Conversations_StartConversation(
userSystemId: user.userSystemId, {
userName: user.userName, userSystemId: user.userSystemId,
pid: pid userName: user.userName,
}); pid: pid
}
);
const conversationId = response.obj.conversationId; const conversationId = response.obj.conversationId;
GBServer.globals.debugConversationId = conversationId; GBServer.globals.debugConversationId = conversationId;
@ -235,7 +239,7 @@ export class GBMinService {
name: 'test', name: 'test',
channelIdEx: 'web', channelIdEx: 'web',
pid: pid pid: pid
} },
} }
}); });
@ -282,7 +286,7 @@ export class GBMinService {
/** /**
* Unmounts the bot web site (default.gbui) secure domain, if any. * Unmounts the bot web site (default.gbui) secure domain, if any.
*/ */
public async unloadDomain(instance: IGBInstance) {} public async unloadDomain(instance: IGBInstance) { }
/** /**
* Mount the instance by creating an BOT Framework bot object, * Mount the instance by creating an BOT Framework bot object,
@ -493,6 +497,7 @@ export class GBMinService {
</body> </body>
</html> </html>
`); `);
} else { } else {
GBLogEx.info(min, `Payment not completed for session ${sessionId}`); GBLogEx.info(min, `Payment not completed for session ${sessionId}`);
res.status(402).json({ res.status(402).json({
@ -506,6 +511,7 @@ export class GBMinService {
res.status(500).json({ res.status(500).json({
success: false, success: false,
error: error.message error: error.message
}); });
} }
}) })
@ -514,6 +520,7 @@ export class GBMinService {
GBServer.globals.server GBServer.globals.server
.all(`/${min.instance.botId}/whatsapp`, async (req, res) => { .all(`/${min.instance.botId}/whatsapp`, async (req, res) => {
const challenge = (min.core['getParam'] as any)(min.instance, `Meta Challenge`, null, true); const challenge = (min.core['getParam'] as any)(min.instance, `Meta Challenge`, null, true);
const status = req.body?.entry?.[0]?.changes?.[0]?.value?.statuses?.[0]; const status = req.body?.entry?.[0]?.changes?.[0]?.value?.statuses?.[0];
@ -523,6 +530,7 @@ export class GBMinService {
return; return;
} }
if (req.query['hub.mode'] === 'subscribe') { if (req.query['hub.mode'] === 'subscribe') {
const val = req.query['hub.verify_token']; const val = req.query['hub.verify_token'];
@ -542,10 +550,13 @@ export class GBMinService {
// Not meta, multiples bots on root bot. // Not meta, multiples bots on root bot.
if (!req.body.object) { if (!req.body.object) {
if (req.body.To) { if (req.body.To) {
const to = req.body.To.replace(/whatsapp\:\+/gi, ''); const to = req.body.To.replace(/whatsapp\:\+/gi, '');
whatsAppDirectLine = WhatsappDirectLine.botsByNumber[to]; whatsAppDirectLine = WhatsappDirectLine.botsByNumber[to];
} else { }
else {
const minBoot = GBServer.globals.minBoot as GBMinInstance; const minBoot = GBServer.globals.minBoot as GBMinInstance;
whatsAppDirectLine = minBoot.whatsAppDirectLine; whatsAppDirectLine = minBoot.whatsAppDirectLine;
} }
@ -557,49 +568,53 @@ export class GBMinService {
}) })
.bind(min); .bind(min);
GBServer.globals.server.all(`/${min.instance.botId}/meeting-token`, async (req, res) => { GBServer.globals.server
try { .all(`/${min.instance.botId}/meeting-token`, async (req, res) => {
// Add to your route handler
res.setHeader('Access-Control-Allow-Origin', '*');
// 1. Validate request try {
const { room, identity, name } = req.query; // Add to your route handler
GBLog.info(`Meeting token asked. ${room} ${identity} ${name}`); res.setHeader('Access-Control-Allow-Origin', '*');
if (!room || !identity) {
return res.status(400).json({ error: 'Missing required parameters: room, identity' }); // 1. Validate request
const { room, identity, name } = req.query;
GBLog.info(`Meeting token asked. ${room} ${identity} ${name}`);
if (!room || !identity) {
return res.status(400).json({ error: 'Missing required parameters: room, identity' });
}
// 2. Get API keys from config (replace with your actual config access)
const apiKey = process.env.LIVEKIT_API_KEY;
const apiSecret = process.env.LIVEKIT_API_SECRET;
if (!apiKey || !apiSecret) {
return res.status(500).json({ error: 'Server misconfigured' });
}
// 3. Generate token
const token = new AccessToken(apiKey, apiSecret, {
identity: identity.toString(),
name: name?.toString() || identity.toString()
});
// 4. Set permissions
token.addGrant({
roomJoin: true,
room: room.toString(),
canPublish: true,
canSubscribe: true,
canPublishData: true
});
// 6. Return JWT
const jwt = await token.toJwt();
res.json({ token: jwt });
} catch (err) {
GBLog.error(`Meeting token generation failed: ${err}`);
res.status(500).json({ error: 'Token generation failed' });
} }
});
// 2. Get API keys from config (replace with your actual config access)
const apiKey = process.env.LIVEKIT_API_KEY;
const apiSecret = process.env.LIVEKIT_API_SECRET;
if (!apiKey || !apiSecret) {
return res.status(500).json({ error: 'Server misconfigured' });
}
// 3. Generate token
const token = new AccessToken(apiKey, apiSecret, {
identity: identity.toString(),
name: name?.toString() || identity.toString()
});
// 4. Set permissions
token.addGrant({
roomJoin: true,
room: room.toString(),
canPublish: true,
canSubscribe: true,
canPublishData: true
});
// 6. Return JWT
const jwt = await token.toJwt();
res.json({ token: jwt });
} catch (err) {
GBLog.error(`Meeting token generation failed: ${err}`);
res.status(500).json({ error: 'Token generation failed' });
}
});
GBDeployer.mountGBKBAssets(`${botId}.gbkb`, botId, `${botId}.gbkb`); GBDeployer.mountGBKBAssets(`${botId}.gbkb`, botId, `${botId}.gbkb`);
@ -628,6 +643,8 @@ export class GBMinService {
private createCheckHealthAddress(server: any, min: GBMinInstance, instance: IGBInstance) { private createCheckHealthAddress(server: any, min: GBMinInstance, instance: IGBInstance) {
server.get(`/${min.instance.botId}/check`, async (req, res) => { server.get(`/${min.instance.botId}/check`, async (req, res) => {
try { try {
// GB is OK, so 200. // GB is OK, so 200.
res.status(200).send(`General Bot ${min.botId} is healthly.`); res.status(200).send(`General Bot ${min.botId} is healthly.`);
@ -769,9 +786,8 @@ export class GBMinService {
min.instance.authenticatorTenant, min.instance.authenticatorTenant,
'/oauth2/authorize' '/oauth2/authorize'
); );
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${ authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${min.instance.marketplaceId
min.instance.marketplaceId }&redirect_uri=${urlJoin(process.env.BOT_URL, min.instance.botId, 'token')}`;
}&redirect_uri=${urlJoin(process.env.BOT_URL, min.instance.botId, 'token')}`;
GBLogEx.info(min, `HandleOAuthRequests: ${authorizationUrl}.`); GBLogEx.info(min, `HandleOAuthRequests: ${authorizationUrl}.`);
res.redirect(authorizationUrl); res.redirect(authorizationUrl);
}); });
@ -809,7 +825,7 @@ export class GBMinService {
let logo = this.core.getParam(instance, 'Logo', null); let logo = this.core.getParam(instance, 'Logo', null);
logo = logo ? urlJoin(instance.botId, 'cache', logo) : 'https://pragmatismo.com.br/icons/general-bots-text.svg'; logo = logo ? urlJoin(instance.botId, 'cache', logo) : 'images/logo-gb.png';
let config = { let config = {
instanceId: instance.instanceId, instanceId: instance.instanceId,
@ -834,6 +850,7 @@ export class GBMinService {
? process.env.BOT_URL ? process.env.BOT_URL
: `http://localhost:${GBConfigService.get('PORT')}`; : `http://localhost:${GBConfigService.get('PORT')}`;
config['domain'] = urlJoin(url, 'directline', botId); config['domain'] = urlJoin(url, 'directline', botId);
} else { } else {
const webchatTokenContainer = await this.getWebchatToken(instance); const webchatTokenContainer = await this.getWebchatToken(instance);
config['conversationId'] = webchatTokenContainer.conversationId; config['conversationId'] = webchatTokenContainer.conversationId;
@ -905,7 +922,10 @@ export class GBMinService {
: GBConfigService.get('MARKETPLACE_SECRET') : GBConfigService.get('MARKETPLACE_SECRET')
}; };
if (GBConfigService.get('GB_MODE') !== 'legacy') { if (GBConfigService.get('GB_MODE') !== 'legacy') {
const url = process.env.BOT_URL || `http://localhost:${GBConfigService.get('PORT')}`;
const url =
process.env.BOT_URL ||
`http://localhost:${GBConfigService.get('PORT')}`;
startRouter(GBServer.globals.server, instance.botId); startRouter(GBServer.globals.server, instance.botId);
config['clientOptions'] = { baseUri: url }; config['clientOptions'] = { baseUri: url };
@ -960,7 +980,8 @@ export class GBMinService {
min.sandBoxMap = {}; min.sandBoxMap = {};
min['scheduleMap'] = {}; min['scheduleMap'] = {};
min['conversationWelcomed'] = {}; min['conversationWelcomed'] = {};
if ((await min.core.getParam(min.instance, 'Answer Mode', null)) && !min['vectorStore']) { if (await min.core.getParam(min.instance, 'Answer Mode', null) &&
!min['vectorStore']) {
const gbkbPath = GBUtil.getGBAIPath(min.botId, 'gbkb'); const gbkbPath = GBUtil.getGBAIPath(min.botId, 'gbkb');
min['vectorStorePath'] = path.join('work', gbkbPath, 'docs-vectorized'); min['vectorStorePath'] = path.join('work', gbkbPath, 'docs-vectorized');
min['vectorStore'] = await this.deployer.loadOrCreateEmptyVectorStore(min); min['vectorStore'] = await this.deployer.loadOrCreateEmptyVectorStore(min);
@ -1133,6 +1154,7 @@ export class GBMinService {
// Default activity processing and handler. // Default activity processing and handler.
const handler = async context => { const handler = async context => {
// Handle activity text issues. // Handle activity text issues.
if (!context.activity.text) { if (!context.activity.text) {
@ -1148,11 +1170,8 @@ export class GBMinService {
let member = context.activity.recipient; let member = context.activity.recipient;
if (context.activity.type === 'conversationUpdate') { if (context.activity.type === 'conversationUpdate') {
if ( if (context.activity.membersAdded && context.activity.membersAdded.length > 0 &&
context.activity.membersAdded && context.activity.membersAdded[0].id === context.activity.recipient.id) {
context.activity.membersAdded.length > 0 &&
context.activity.membersAdded[0].id === context.activity.recipient.id
) {
GBLogEx.info(min, `Bot added to conversation: ${member.name}`); GBLogEx.info(min, `Bot added to conversation: ${member.name}`);
return; return;
@ -1175,6 +1194,7 @@ export class GBMinService {
let pid = GBMinService.pidsConversation[conversationId]; let pid = GBMinService.pidsConversation[conversationId];
if (!pid) { if (!pid) {
pid = step.context.activity['pid']; pid = step.context.activity['pid'];
if (!pid) { if (!pid) {
pid = WhatsappDirectLine.pidByNumber[context.activity.from.id]; pid = WhatsappDirectLine.pidByNumber[context.activity.from.id];
@ -1189,14 +1209,20 @@ export class GBMinService {
const auth = min.core.getParam(min.instance, 'Enable Authentication', false); const auth = min.core.getParam(min.instance, 'Enable Authentication', false);
if (auth) { if (auth) {
const res = await t.find({ pid: pid, handle: 'users.csv', args: [`key={member.id}`] }); const res = await t.find({ pid: pid, handle: "users.csv", args: [`key={member.id}`] });
if (!res) { if (!res) {
await min.conversationalService.sendText(min, step, 'Sorry, not authorized.'); await min.conversationalService.sendText(
min,
step,
'Sorry, not authorized.'
);
res.end(); res.end();
} }
} }
// First time processing. // First time processing.
if (!params.loaded) { if (!params.loaded) {
@ -1232,6 +1258,8 @@ export class GBMinService {
await sec.updateConversationReferenceById(userId, conversationReference); await sec.updateConversationReferenceById(userId, conversationReference);
if (step.context.activity.channelId !== 'msteams') { if (step.context.activity.channelId !== 'msteams') {
const service = new KBService(min.core.sequelize); const service = new KBService(min.core.sequelize);
const data = await service.getFaqBySubjectArray(min.instance.instanceId, 'faq', undefined); const data = await service.getFaqBySubjectArray(min.instance.instanceId, 'faq', undefined);
if (data.length > 0) { if (data.length > 0) {
@ -1239,13 +1267,17 @@ export class GBMinService {
playerType: 'bullet', playerType: 'bullet',
data: data.slice(0, 10) data: data.slice(0, 10)
}); });
} }
} }
} }
const notes = min.core.getParam(min.instance, 'Notes', null); const notes = min.core.getParam(min.instance, 'Notes', null);
if (await this.handleUploads(min, step, user, params, notes != null)) { if (await this.handleUploads(min, step, user, params, notes != null)) {
return; return;
} }
// Required for MSTEAMS handling of persisted conversations. // Required for MSTEAMS handling of persisted conversations.
@ -1283,8 +1315,8 @@ export class GBMinService {
if (!(await sec.getParam(user, 'welcomed'))) { if (!(await sec.getParam(user, 'welcomed'))) {
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null); const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
if (startDialog) { if (startDialog) {
const t = new SystemKeywords(); const t = new SystemKeywords();
t.setMemoryContext({ pid: pid, erase: true }); t.setMemoryContext({pid:pid,erase:true});
await sec.setParam(userId, 'welcomed', 'true'); await sec.setParam(userId, 'welcomed', 'true');
GBLogEx.info( GBLogEx.info(
min, min,
@ -1303,7 +1335,8 @@ export class GBMinService {
if (context.activity.type === 'installationUpdate') { if (context.activity.type === 'installationUpdate') {
GBLogEx.info(min, `Bot installed on Teams.`); GBLogEx.info(min, `Bot installed on Teams.`);
} else if (context.activity.type === 'conversationUpdate') { } else if (context.activity.type === 'conversationUpdate' ){
// Calls onNewSession event on each .gbapp package. // Calls onNewSession event on each .gbapp package.
await CollectionUtil.asyncForEach(appPackages, async e => { await CollectionUtil.asyncForEach(appPackages, async e => {
@ -1317,10 +1350,14 @@ export class GBMinService {
await step.beginDialog('/'); await step.beginDialog('/');
} else { } else {
if (!GBMinService.userMobile(step) && !min['conversationWelcomed'][step.context.activity.conversation.id]) { if (
!GBMinService.userMobile(step) &&
!min['conversationWelcomed'][step.context.activity.conversation.id]
) {
const pid = GBVMService.createProcessInfo(user, min, step.context.activity.channelId, null, step); const pid = GBVMService.createProcessInfo(user, min, step.context.activity.channelId, null, step);
const t = new SystemKeywords(); const t = new SystemKeywords();
t.setMemoryContext({ pid: pid, erase: true }); t.setMemoryContext({pid:pid,erase:true});
step.context.activity['pid'] = pid; step.context.activity['pid'] = pid;
@ -1334,6 +1371,9 @@ export class GBMinService {
} }
} }
} else if (context.activity.type === 'message') { } else if (context.activity.type === 'message') {
// Required for F0 handling of persisted conversations. // Required for F0 handling of persisted conversations.
GBLogEx.info( GBLogEx.info(
@ -1341,6 +1381,7 @@ export class GBMinService {
`Human: pid:${pid} ${context.activity.from.id} ${GBUtil.toYAML(WhatsappDirectLine.pidByNumber)} ${context.activity.text} (type: ${context.activity.type}, name: ${context.activity.name}, channelId: ${context.activity.channelId})` `Human: pid:${pid} ${context.activity.from.id} ${GBUtil.toYAML(WhatsappDirectLine.pidByNumber)} ${context.activity.text} (type: ${context.activity.type}, name: ${context.activity.name}, channelId: ${context.activity.channelId})`
); );
// Processes messages activities. // Processes messages activities.
await this.processMessageActivity(context, min, step, pid); await this.processMessageActivity(context, min, step, pid);
@ -1399,13 +1440,12 @@ export class GBMinService {
); );
if (context.activity.name === 'showSubjects') { if (context.activity.name === 'showSubjects') {
await step.replaceDialog('/answer', { await step.replaceDialog('/answer', { query: `Show a list of subjects you can help me in ${contentLocale} language.` });
query: `Show a list of subjects you can help me in ${contentLocale} language.`
});
} else if (context.activity.name === 'showFAQ') { } else if (context.activity.name === 'showFAQ') {
await step.replaceDialog('/answer', { await step.replaceDialog('/answer', { query: `Show a FAQ for me about how can you help me in a bullet list, in ${contentLocale} language.` });
query: `Show a FAQ for me about how can you help me in a bullet list, in ${contentLocale} language.`
});
} else if (context.activity.name === 'answerEvent') { } else if (context.activity.name === 'answerEvent') {
await step.beginDialog('/answerEvent', <AskDialogArgs>{ await step.beginDialog('/answerEvent', <AskDialogArgs>{
questionId: context.activity.data, questionId: context.activity.data,
@ -1491,6 +1531,7 @@ export class GBMinService {
const successfulSaves = await Promise.all(promises); const successfulSaves = await Promise.all(promises);
async function replyForReceivedAttachments(attachmentData) { async function replyForReceivedAttachments(attachmentData) {
if (attachmentData) { if (attachmentData) {
// In case of not having HEAR activated before, it is // In case of not having HEAR activated before, it is
// a upload with no Dialog, so run Auto Save to .gbdrive. // a upload with no Dialog, so run Auto Save to .gbdrive.
@ -1534,16 +1575,16 @@ export class GBMinService {
name: string; name: string;
} }
const results = (await successfulSaves.reduce(async (accum: GBFile[], item) => { const results = await successfulSaves.reduce(async (accum: GBFile[], item) => {
const result: GBFile = { const result: GBFile = {
data: await fs.readFile(successfulSaves[0]['filename']), data: await fs.readFile(successfulSaves[0]['filename']),
filename: successfulSaves[0]['filename'], filename: successfulSaves[0]['filename'],
name: successfulSaves[0]['name'], name: successfulSaves[0]['name'],
url: successfulSaves[0]['url'] url: successfulSaves[0]['url'],
}; };
accum.push(result); accum.push(result);
return accum; return accum;
}, [])) as GBFile[]; }, []) as GBFile[];
if (min.cbMap[user.userId] && min.cbMap[user.userId].promise == '!GBHEAR') { if (min.cbMap[user.userId] && min.cbMap[user.userId].promise == '!GBHEAR') {
if (results.length > 1) { if (results.length > 1) {
@ -1652,7 +1693,7 @@ export class GBMinService {
) { ) {
await sec.setParam(userId, 'welcomed', 'true'); await sec.setParam(userId, 'welcomed', 'true');
const t = new SystemKeywords(); const t = new SystemKeywords();
t.setMemoryContext({ pid: pid, erase: true }); t.setMemoryContext({pid:pid,erase:true});
min['conversationWelcomed'][step.context.activity.conversation.id] = true; min['conversationWelcomed'][step.context.activity.conversation.id] = true;
GBLogEx.info( GBLogEx.info(
@ -1660,6 +1701,9 @@ export class GBMinService {
`Auto start (4) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...` `Auto start (4) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
); );
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid); await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
} }
} }
@ -1759,9 +1803,8 @@ export class GBMinService {
try { try {
await step.continueDialog(); await step.continueDialog();
} catch (error) { } catch (error) {
const msg = `ERROR: ${error.message} ${error.stack} ${error.error ? error.error.body : ''} ${ const msg = `ERROR: ${error.message} ${error.stack} ${error.error ? error.error.body : ''} ${error.error ? (error.error.stack ? error.error.stack : '') : ''
error.error ? (error.error.stack ? error.error.stack : '') : '' }`;
}`;
GBLog.error(msg); GBLog.error(msg);
await min.conversationalService.sendText( await min.conversationalService.sendText(
min, min,
@ -1884,10 +1927,10 @@ export class GBMinService {
pingSendTimeout: null, pingSendTimeout: null,
keepAliveTimeout: null, keepAliveTimeout: null,
listeners: { listeners: {
unsubscribed(subscriptions: number): void {}, unsubscribed(subscriptions: number): void { },
subscribed(subscriptions: number): void {}, subscribed(subscriptions: number): void { },
disconnected(remoteId: string, connections: number): void {}, disconnected(remoteId: string, connections: number): void { },
connected(remoteId: string, connections: number): void {}, connected(remoteId: string, connections: number): void { },
messageIn(...params): void { messageIn(...params): void {
params.shift(); params.shift();
}, },

View file

@ -28,51 +28,59 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
import React from 'react'; import React from "react";
class SideBarMenu extends React.Component { class SideBarMenu extends React.Component {
send(command) { send(command) {
window.botConnection.postActivity({ window.botConnection
type: 'event', .postActivity({
name: command, type: "event",
locale: 'en-us', name: command,
textFormat: 'plain', locale: "en-us",
timestamp: new Date().toISOString() textFormat: "plain",
}); timestamp: new Date().toISOString()
});
} }
render() { render() {
return ( return (
<div> <div>
<div className="titleSideBarMenu"> <div className="titleSideBarMenu">
<img className="pragmatismoLogo" width="64px" src={this.props.instance.logo} alt="General Bots Logo" /> <img
className="pragmatismoLogo"
src={this.props.instance.logo}
alt="General Bots Logo" />
</div> </div>
<div className="SidebarMenu"> <div className="SidebarMenu">
<div className="IconsMenu"> <div className="IconsMenu">
<div className="iconMenu"> <div className="iconMenu">
<span className="iconText" onClick={() => this.send('showFAQ')}> <span className="iconText" onClick={() => this.send("showFAQ")}>
FAQ FAQ
</span> </span>
</div> </div>
<div className="iconMenu"> <div className="iconMenu">
<span <span className="iconText"
className="iconText" onClick={() => window.open(`https://pragmatismo.sharepoint.com/sites/bots/Online/${this.props.instance.botId}.gbai`)}
onClick={() =>
window.open(`https://drive.pragmatismo.com.br/browser/${this.props.instance.botId}.gbai`)
}
> >
Drive Drive
</span> </span>
</div> </div>
<div className="iconMenu"> <div className="iconMenu">
<span className="iconText" onClick={() => this.send('showSubjects')}> <span
className="iconText"
onClick={() => this.send("showSubjects")}>
Subjects Subjects
</span> </span>
</div> </div>
<div className="iconMenu"> <div className="iconMenu">
<span className="iconText" onClick={() => window.open('mailto:talk@pragmatismo.com.br')}> <span
className="iconText"
onClick={() => window.open('mailto:talk@pragmatismo.com.br')}
>
Suggestions Suggestions
</span> </span>
</div> </div>
</div> </div>
</div> </div>