From 50f438caa96c0326667a316e6726359ee235c8d2 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Wed, 30 Apr 2025 14:18:32 -0300 Subject: [PATCH] fix(DialogKeywords): comment out unused email headers in mail options --- .forgejo/workflows/node.yaml | 2 +- .../basic.gblib/services/DialogKeywords.ts | 6 +- packages/saas.gbapp/service/GBOService.ts | 109 ++++++++---------- packages/saas.gbapp/service/MainService.ts | 54 ++++++++- 4 files changed, 105 insertions(+), 66 deletions(-) diff --git a/.forgejo/workflows/node.yaml b/.forgejo/workflows/node.yaml index 4c26533af..72e4cce1e 100644 --- a/.forgejo/workflows/node.yaml +++ b/.forgejo/workflows/node.yaml @@ -35,7 +35,7 @@ jobs: echo "[General Bots Deployer] Building BotServer..." # rm -rf /opt/gbo/bin/BotServer/node_modules cd /opt/gbo/bin/BotServer - sudo npm ci --production + #sudo npm ci --production npm run build-server # npm run build-gbui diff --git a/packages/basic.gblib/services/DialogKeywords.ts b/packages/basic.gblib/services/DialogKeywords.ts index 4ea783f6d..928136751 100644 --- a/packages/basic.gblib/services/DialogKeywords.ts +++ b/packages/basic.gblib/services/DialogKeywords.ts @@ -603,7 +603,11 @@ export class DialogKeywords { subject: subject, text: body, html: body, - }; + // headers: { + // 'List-Unsubscribe': ``, + // 'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click' + // } + }; await transporter.sendMail(mailOptions); GBLogEx.info(min, `E-mail ${to} (${subject}) sent via NodeMailer.`); diff --git a/packages/saas.gbapp/service/GBOService.ts b/packages/saas.gbapp/service/GBOService.ts index fa71e6af8..ebdb516ed 100755 --- a/packages/saas.gbapp/service/GBOService.ts +++ b/packages/saas.gbapp/service/GBOService.ts @@ -14,37 +14,9 @@ import { existsSync } from 'fs'; import { GBConfigService } from "../../core.gbapp/services/GBConfigService.js"; import path from "path"; import { Client } from "minio"; - - +import { GBLogEx } from "packages/core.gbapp/services/GBLogEx.js"; export class GBOService { - - - constructor() { - } - public async sendEmail(token: string, to: string, from: string, - subject: string, text: string, html: string) { - return new Promise((resolve, reject) => { - sgMail.setApiKey(token); - const msg = { - to: to, - from: from, - subject: subject, - text: text, - html: html - }; - sgMail.send(msg, false, (err, res) => { - if (err) { - reject(err) - } - else { - resolve(res); - } - }); - - }); - } - public async listTemplates(min: GBMinInstance) { if (GBConfigService.get('GB_MODE') === 'legacy') { @@ -154,8 +126,8 @@ export class GBOService { secretKey: process.env.DRIVE_SECRET, }); - - const bucketName = `${process.env.DRIVE_ORG_PREFIX}${botName}.gbai`.toLowerCase(); + + const bucketName = `${process.env.DRIVE_ORG_PREFIX}${botName}.gbai`.toLowerCase(); const packageName = `${templateName.split('.')[0]}.${kind}`; const localTemplatePath = path.join(process.env.PWD, 'templates', templateName, packageName); const minioDestinationPath = `${botName}.${kind}`; @@ -225,38 +197,57 @@ export class GBOService { } } + public async shareWithEmail(bucketName, folder, expiresInHours = 24 * 365) { + const minioClient = new Client({ + endPoint: process.env.DRIVE_SERVER || 'localhost', + port: parseInt(process.env.DRIVE_PORT || '9000', 10), + useSSL: process.env.DRIVE_USE_SSL === 'true', + accessKey: process.env.DRIVE_ACCESSKEY, + secretKey: process.env.DRIVE_SECRET, + }); + + // Generate a time-limited access link (default: 24 hours) + const presignedUrl = await minioClient.presignedGetObject( + bucketName, + folder, + expiresInHours * 60 * 60 // Convert hours to seconds + ); + return presignedUrl; + } + public async shareFolder(token: string, driveId: string, itemId: string, email: string) { - return new Promise((resolve, reject) => { - let client = MicrosoftGraph.Client.init({ - authProvider: done => { - done(null, token); - } - }); - const body = - { - "recipients": [ - { - "email": email - } - ], - "message": "General Bots Online - Packages folder", - "requireSignIn": true, - "sendInvitation": true, - "roles": ["write"] - }; - - client.api(`https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/invite`) - .post(body, (err, res) => { - if (err) { - GBLog.error('Sharing: ' + err); - reject(err) - } - else { - resolve(res); + return new Promise((resolve, reject) => { + let client = MicrosoftGraph.Client.init({ + authProvider: done => { + done(null, token); } }); - }); + + const body = + { + "recipients": [ + { + "email": email + } + ], + "message": "General Bots Online - Packages folder", + "requireSignIn": true, + "sendInvitation": true, + "roles": ["write"] + }; + + client.api(`https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/invite`) + .post(body, (err, res) => { + if (err) { + GBLog.error('Sharing: ' + err); + reject(err) + } + else { + resolve(res); + } + }); + }); } public kmpSearch(pattern, text) { diff --git a/packages/saas.gbapp/service/MainService.ts b/packages/saas.gbapp/service/MainService.ts index 8bb403aba..13c94cbe6 100644 --- a/packages/saas.gbapp/service/MainService.ts +++ b/packages/saas.gbapp/service/MainService.ts @@ -7,6 +7,7 @@ import { GBOService } from './GBOService.js'; import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js'; import Stripe from 'stripe'; import { GBUtil } from '../../../src/util.js'; +import { DialogKeywords } from '../../basic.gblib/services/DialogKeywords.js'; export class MainService { private gboService: GBOService; @@ -51,7 +52,7 @@ export class MainService { price: priceId, quantity: 1, }], - success_url: urlJoin(process.env.BOT_URL, min.botId, 'paymentSuccess?session_id={CHECKOUT_SESSION_ID}'), + success_url: urlJoin(process.env.BOT_URL, min.botId, 'paymentSuccess?session_id={CHECKOUT_SESSION_ID}'), mode: 'subscription', metadata: { subscriptionId: subscription.subscriptionId.toString(), @@ -77,7 +78,7 @@ export class MainService { templateName: string ): Promise { const startTime = Date.now(); - + while ((Date.now() - startTime) < this.PAYMENT_CHECK_TIMEOUT) { const subscription = await GBOnlineSubscription.findOne({ where: { subscriptionId } @@ -92,17 +93,17 @@ export class MainService { subscription.stripeSessionId, { expand: ['payment_intent'] } ); - + if (session.payment_status === 'paid') { await subscription.update({ status: 'active', activatedAt: new Date(), stripePaymentIntentId: (session.payment_intent as any)?.id }); - + return await this.createBotResources(min, subscription, templateName); } - + if (session.status === 'expired') { throw new Error('Payment failed or session expired. Please try again.'); } @@ -173,6 +174,49 @@ export class MainService { await min.core['setConfig'](min, instance.botId, 'WebDav Username', instance.botId); await min.core['setConfig'](min, instance.botId, 'WebDav Secret', instance.adminPass); + const botName = subscription.botName; + const language = subscription['customerLanguage'] || 'en-us'; + + const webUrl = this.gboService.shareWithEmail(`process.env.DRIVE_ORG_PREFIX${botName}.gbai`, '/'); + + urlJoin(process.env.DRIVE_WEB, 'browser',); + const botUrl = urlJoin(process.env.BOT_URL, botName); + const botId = instance.botId; + + let message = `Seu bot ${botName} está disponível no endereço: +
${urlJoin(process.env.BOT_URL, botName)}. +
+
Os pacotes do General Bots (ex: .gbkb, .gbtheme) para seu Bot devem ser editados no repositório de pacotes: +
+
${webUrl}. +
+
Digite /publish do seu WhatsApp para publicar os pacotes. Seu número está autorizado na pasta ${botName}.gbot/Config.xlsx +
+
O arquivo .zip em anexo pode ser importado no Teams conforme instruções em: +
https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/apps-upload. +
+
Log in to the Teams client with your Microsoft 365 account. +
Select Apps and choose Upload a custom app. +
Select this .zip file attached to this e-mail. An install dialog displays. +
Add your Bot to Teams. +
+
Atenciosamente, +
General Bots Online. +
https://gb.pragmatismo.com.br +
+
E-mail remetido por Pragmatismo. +
`; + + message = await min.conversationalService.translate( + min, + message, + language + ); + GBLog.info('Sending e-mails....'); + + const dk = new DialogKeywords(); + await dk.sendEmail({ pid: 0, to: subscription.customerEmail, subject: `Seu bot ${botName} está pronto!`, body: message }); + return { success: true, botUrl: urlJoin(process.env.BOT_URL, subscription.botName)