From 855c24f38db7ab9bc13d635b55c25864b3b58164 Mon Sep 17 00:00:00 2001 From: pedro-php Date: Wed, 14 May 2025 16:12:31 -0300 Subject: [PATCH] new_feature_lottieMessage_healthCheck --- docker-compose.yaml | 8 +-- src/api/controllers/chat.controller.ts | 1 - src/api/controllers/health.controller.ts | 23 ++++++++ .../whatsapp/whatsapp.baileys.service.ts | 59 +++++++++++++------ .../chatwoot/services/chatwoot.service.ts | 2 + .../chatwoot/utils/chatwoot-import-helper.ts | 4 ++ src/api/routes/health.router.ts | 18 ++++++ src/api/routes/index.router.ts | 4 ++ src/api/server.module.ts | 4 ++ src/api/services/channel.service.ts | 5 ++ src/api/types/wa.types.ts | 1 + 11 files changed, 105 insertions(+), 24 deletions(-) create mode 100644 src/api/controllers/health.controller.ts create mode 100644 src/api/routes/health.router.ts diff --git a/docker-compose.yaml b/docker-compose.yaml index a02d35ac..3db8ffff 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -2,7 +2,7 @@ services: api: container_name: evolution_api_${ENVIROMNENT} build: . - #image: evoapicloud/evolution-api:latest + image: adaptweb/evolution-api:1.2.1 restart: always depends_on: - redis @@ -24,11 +24,11 @@ services: - evolution-net container_name: redis_${ENVIROMNENT} command: > - redis-server --port 6379 --appendonly yes + redis-server --port 11235 --appendonly yes volumes: - evolution_redis:/data ports: - - ${REDIS_PORT}:6379 + - ${REDIS_PORT}:11235 postgres: container_name: postgres_${ENVIROMNENT} @@ -38,7 +38,7 @@ services: command: ["postgres", "-c", "max_connections=1000", "-c", "listen_addresses=*"] restart: always ports: - - ${DATABASE_PORT}:5432 + - ${DATABASE_PORT}:11234 environment: - POSTGRES_USER=user - POSTGRES_PASSWORD=pass diff --git a/src/api/controllers/chat.controller.ts b/src/api/controllers/chat.controller.ts index d60f9f75..207d8ba5 100644 --- a/src/api/controllers/chat.controller.ts +++ b/src/api/controllers/chat.controller.ts @@ -43,7 +43,6 @@ export class ChatController { } public async fetchProfilePicture({ instanceName }: InstanceDto, data: NumberDto) { - console.dir("Fetching profile picture..."); return await this.waMonitor.waInstances[instanceName].profilePicture(data.number); } diff --git a/src/api/controllers/health.controller.ts b/src/api/controllers/health.controller.ts new file mode 100644 index 00000000..74f10f0b --- /dev/null +++ b/src/api/controllers/health.controller.ts @@ -0,0 +1,23 @@ +import { WAMonitoringService } from '@api/services/monitor.service'; + +import { UnauthorizedException } from '../../exceptions'; +import { PrismaRepository } from '../repository/repository.service'; + +export class HealthController { + constructor( + private readonly waMonitor: WAMonitoringService, + private readonly prismaRepository: PrismaRepository, + ) {} + + public async checkHealth() { + const instancesByKey = await this.prismaRepository.instance.findMany(); + + if (instancesByKey.length > 0) { + const names = instancesByKey.map((instance) => instance.name); + + return this.waMonitor.instanceInfo(names); + } else { + return []; + } + } +} diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 98eb1a83..edd61e0d 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -98,6 +98,7 @@ import makeWASocket, { Contact, delay, DisconnectReason, + downloadContentFromMessage, downloadMediaMessage, fetchLatestBaileysVersion, generateWAMessageFromContent, @@ -1248,6 +1249,7 @@ export class BaileysStartupService extends ChannelStartupService { received?.message?.imageMessage || received?.message?.videoMessage || received?.message?.stickerMessage || + received?.message?.lottieStickerMessage || received?.message?.documentMessage || received?.message?.documentWithCaptionMessage || received?.message?.ptvMessage || @@ -1362,20 +1364,41 @@ export class BaileysStartupService extends ChannelStartupService { } } } - - if (this.localWebhook.enabled) { - if (isMedia && this.localWebhook.webhookBase64) { + if (1/* this.localWebhook.enabled */) { + if (1/* isMedia && this.localWebhook.webhookBase64 */) { try { - const buffer = await downloadMediaMessage( - { key: received.key, message: received?.message }, - 'buffer', - {}, - { - logger: P({ level: 'error' }) as any, - reuploadRequest: this.client.updateMediaMessage, - }, - ); + let buffer : Buffer = null; + console.dir({received}, {depth: null}); + if ((received.message.stickerMessage && received.message.stickerMessage.url === 'https://web.whatsapp.net') + || (received.message.lottieStickerMessage && received.message.lottieStickerMessage.message.stickerMessage.url)) { /*Fixing broken URLs from sticker messages*/ + const newUrl = `https://mmg.whatsapp.net${received.message.lottieStickerMessage ? received.message.lottieStickerMessage.message.stickerMessage.directPath : received.message.stickerMessage.directPath }`; + const stream = await downloadContentFromMessage( + { + mediaKey: received.message?.stickerMessage?.mediaKey || received.message.lottieStickerMessage?.message?.stickerMessage?.mediaKey, + directPath: received.message?.stickerMessage?.directPath || received.message.lottieStickerMessage?.message?.stickerMessage?.directPath, + url: newUrl + }, + 'sticker', + {}, + ) + const chunks = []; + for await (const chunk of stream) { + chunks.push(chunk); + } + buffer = Buffer.concat(chunks); + messageRaw.message.url = newUrl; + } else { + buffer = await downloadMediaMessage( + { key: received.key, message: received?.message }, + 'buffer', + {}, + { + logger: P({ level: 'error' }) as any, + reuploadRequest: this.client.updateMediaMessage, + }, + ); + } messageRaw.message.base64 = buffer ? buffer.toString('base64') : undefined; } catch (error) { this.logger.error(['Error converting media to base64', error?.message]); @@ -1383,6 +1406,7 @@ export class BaileysStartupService extends ChannelStartupService { } } + console.dir({webhookMessage: messageRaw}, {depth: null}) this.logger.log(messageRaw); this.sendDataWebhook(Events.MESSAGES_UPSERT, messageRaw); @@ -1508,13 +1532,11 @@ export class BaileysStartupService extends ChannelStartupService { }, }); - if (!findMessage) { continue; } if (update.message === null && update.status === undefined) { - const deletedMessage = { id: findMessage.id, instanceId: this.instanceId, @@ -1526,7 +1548,7 @@ export class BaileysStartupService extends ChannelStartupService { pushName: findMessage.pushName, participant: findMessage.participant, message: findMessage.message, - } + }; this.sendDataWebhook(Events.MESSAGES_DELETE, deletedMessage); @@ -1756,7 +1778,7 @@ export class BaileysStartupService extends ChannelStartupService { } if (events['messages.upsert']) { - const payload = events['messages.upsert']; + const payload = events['messages.upsert'] this.messageHandle['messages.upsert'](payload, settings); } @@ -1880,12 +1902,10 @@ export class BaileysStartupService extends ChannelStartupService { } public async profilePicture(number: string) { - console.dir(`converting jid:${number}`); const jid = createJid(number); try { const profilePictureUrl = await this.client.profilePictureUrl(jid, 'image'); - console.dir({ profilePictureUrl }); return { wuid: jid, @@ -2280,7 +2300,8 @@ export class BaileysStartupService extends ChannelStartupService { messageSent?.message?.documentMessage || messageSent?.message?.documentWithCaptionMessage || messageSent?.message?.ptvMessage || - messageSent?.message?.audioMessage; + messageSent?.message?.audioMessage || + messageSent?.message?.lottieStickerMessage; if (this.configService.get('CHATWOOT').ENABLED && this.localChatwoot?.enabled && !isIntegration) { this.chatwootService.eventWhatsapp( diff --git a/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts b/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts index ed3f1899..2c983674 100644 --- a/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts +++ b/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts @@ -1597,6 +1597,7 @@ export class ChatwootService { 'audioMessage', 'videoMessage', 'stickerMessage', + 'lottieStickerMessage', 'viewOnceMessageV2', ]; @@ -1651,6 +1652,7 @@ export class ChatwootService { extendedTextMessage: msg.extendedTextMessage?.text, messageContextInfo: msg.messageContextInfo?.stanzaId, stickerMessage: undefined, + lottieStickerMessage: undefined, documentMessage: msg.documentMessage?.caption, documentWithCaptionMessage: msg.documentWithCaptionMessage?.message?.documentMessage?.caption, audioMessage: msg.audioMessage?.caption, diff --git a/src/api/integrations/chatbot/chatwoot/utils/chatwoot-import-helper.ts b/src/api/integrations/chatbot/chatwoot/utils/chatwoot-import-helper.ts index 52453f59..f32f6dd8 100644 --- a/src/api/integrations/chatbot/chatwoot/utils/chatwoot-import-helper.ts +++ b/src/api/integrations/chatbot/chatwoot/utils/chatwoot-import-helper.ts @@ -497,6 +497,7 @@ class ChatwootImport { videoMessage: msg.message.videoMessage, audioMessage: msg.message.audioMessage, stickerMessage: msg.message.stickerMessage, + lottieStickerMessage: msg.message.lottieStickerMessage, templateMessage: msg.message.templateMessage?.hydratedTemplate?.hydratedContentText, }; const typeKey = Object.keys(types).find((key) => types[key] !== undefined); @@ -531,6 +532,9 @@ class ChatwootImport { case 'stickerMessage': return '__'; + case 'lottieStickerMessage': + return '__'; + default: return ''; } diff --git a/src/api/routes/health.router.ts b/src/api/routes/health.router.ts new file mode 100644 index 00000000..344bad29 --- /dev/null +++ b/src/api/routes/health.router.ts @@ -0,0 +1,18 @@ +import { RequestHandler, Router } from "express"; +import { RouterBroker } from "../abstract/abstract.router"; +import { HttpStatus } from "./index.router"; +import { healthController } from "@api/server.module"; + + +export class HealthRouter extends RouterBroker { + constructor() { + super(); + this.router + .get(this.routerPath('healthz', false), async (req, res) => { + await healthController.checkHealth(); + return res.status(HttpStatus.OK).json({msg: 'healthy'}); + }) + } + + public readonly router: Router = Router(); +} \ No newline at end of file diff --git a/src/api/routes/index.router.ts b/src/api/routes/index.router.ts index 9c0ecd13..fbd108e2 100644 --- a/src/api/routes/index.router.ts +++ b/src/api/routes/index.router.ts @@ -22,6 +22,7 @@ import { MessageRouter } from './sendMessage.router'; import { SettingsRouter } from './settings.router'; import { TemplateRouter } from './template.router'; import { ViewsRouter } from './view.router'; +import { HealthRouter} from './health.router'; enum HttpStatus { OK = 200, @@ -57,6 +58,8 @@ router.get('/assets/*', (req, res) => { } }); +console.dir(new HealthRouter().router, { depth: null }); + router .use((req, res, next) => telemetry.collectTelemetry(req, res, next)) @@ -79,6 +82,7 @@ router facebookUserToken: process.env.FACEBOOK_USER_TOKEN, }); }) + .use('', new HealthRouter().router) .use('/instance', new InstanceRouter(configService, ...guards).router) .use('/message', new MessageRouter(...guards).router) .use('/call', new CallRouter(...guards).router) diff --git a/src/api/server.module.ts b/src/api/server.module.ts index 9d8df8a6..49210529 100644 --- a/src/api/server.module.ts +++ b/src/api/server.module.ts @@ -40,6 +40,7 @@ import { WAMonitoringService } from './services/monitor.service'; import { ProxyService } from './services/proxy.service'; import { SettingsService } from './services/settings.service'; import { TemplateService } from './services/template.service'; +import { HealthController } from './controllers/health.controller'; const logger = new Logger('WA MODULE'); @@ -107,6 +108,9 @@ export const eventManager = new EventManager(prismaRepository, waMonitor); export const chatbotController = new ChatbotController(prismaRepository, waMonitor); export const channelController = new ChannelController(prismaRepository, waMonitor); +//Health check +export const healthController = new HealthController(waMonitor, prismaRepository); + // channels export const evolutionController = new EvolutionController(prismaRepository, waMonitor); export const metaController = new MetaController(prismaRepository, waMonitor); diff --git a/src/api/services/channel.service.ts b/src/api/services/channel.service.ts index 6d03856e..1c919c99 100644 --- a/src/api/services/channel.service.ts +++ b/src/api/services/channel.service.ts @@ -552,6 +552,11 @@ export class ChannelStartupService { cleanedMessage.message.stickerMessage = {}; } + // Limpa LottieStickerMessage + if(cleanedMessage.message.lottieStickerMessage) { + cleanedMessage.message.lottieStickerMessage = {}; + } + // Limpa documentMessage if (cleanedMessage.message.documentMessage) { cleanedMessage.message.documentMessage = { diff --git a/src/api/types/wa.types.ts b/src/api/types/wa.types.ts index 2bb3dc1e..32e53a17 100644 --- a/src/api/types/wa.types.ts +++ b/src/api/types/wa.types.ts @@ -139,6 +139,7 @@ export const TypeMediaMessage = [ 'audioMessage', 'videoMessage', 'stickerMessage', + 'lottieStickerMessage', 'ptvMessage', ];