From c681814cca9a57887758b02f9e3ea949a249bdcb Mon Sep 17 00:00:00 2001 From: Rafael Lopes Date: Tue, 9 Jun 2026 18:14:55 -0300 Subject: [PATCH] =?UTF-8?q?CHORE:=20Release=20vers=C3=A3o=201.0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++- .../attendance-assignment.service.ts | 5 ++++ .../attendance-assignment.repository.ts | 4 +++ src/modules/whatsapp/whatsapp.controller.ts | 30 ++++++++++++++++++- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 286aa1f..05f5dde 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ https://chaleiradev.sothistelecom.com/Sothis/omnichannel-deploy - TypeScript - PostgreSQL - Socket.IO -- whatsapp-web.js +- whatsapp-web.js, com Puppeteer/Chrome para controlar o WhatsApp Web - JSON Web Token para autenticacao - LDAP/AD e Microsoft OAuth como provedores de login configuraveis @@ -49,6 +49,12 @@ cp .env.example .env.development Configure as variaveis de banco, JWT, CORS e integracoes no `.env.development`. +Para usar o canal WhatsApp, o backend tambem precisa conseguir iniciar Chrome/Chromium. + +O `whatsapp-web.js` usa Puppeteer para abrir o WhatsApp Web em modo headless, autenticar por QR Code e manter a sessao local em `whatsapp-session`. + +Em ambiente Docker/producao, persista esse diretorio em volume para nao perder a sessao a cada recriacao do container. + Execute em modo desenvolvimento: ```bash diff --git a/src/modules/attendance/attendance-assignment.service.ts b/src/modules/attendance/attendance-assignment.service.ts index 28fb35d..e30bfa5 100644 --- a/src/modules/attendance/attendance-assignment.service.ts +++ b/src/modules/attendance/attendance-assignment.service.ts @@ -791,6 +791,11 @@ export class AttendanceAssignmentService { private matchBuilderChild(message: string, children: BotFlowNode[]) { const normalized = this.normalize(message).trim(); + const selectedNumber = Number(normalized.match(/^\d+$/)?.[0] || 0); + if (selectedNumber > 0) { + return children.find((child) => Number(child.sort_order) === selectedNumber) || null; + } + return children.find((child) => { const keywords = String(child.keywords || '') .split(',') diff --git a/src/modules/attendance/repositories/attendance-assignment.repository.ts b/src/modules/attendance/repositories/attendance-assignment.repository.ts index 7cc746e..f5154cf 100644 --- a/src/modules/attendance/repositories/attendance-assignment.repository.ts +++ b/src/modules/attendance/repositories/attendance-assignment.repository.ts @@ -20,6 +20,8 @@ export class AttendanceAssignmentRepository { reserved_user_id = NULL, reserved_at = NULL, pause_released_at = NULL, + conversation_started_at = CURRENT_TIMESTAMP, + expires_at = CURRENT_TIMESTAMP + INTERVAL '24 hours', triage_flow_id = NULL, triage_audience_id = NULL, triage_intent_id = NULL, @@ -85,6 +87,8 @@ export class AttendanceAssignmentRepository { reserved_user_id = NULL, reserved_at = NULL, pause_released_at = NULL, + conversation_started_at = CURRENT_TIMESTAMP, + expires_at = CURRENT_TIMESTAMP + INTERVAL '24 hours', triage_flow_id = NULL, triage_audience_id = NULL, triage_intent_id = NULL, diff --git a/src/modules/whatsapp/whatsapp.controller.ts b/src/modules/whatsapp/whatsapp.controller.ts index 6635732..4d6ed89 100644 --- a/src/modules/whatsapp/whatsapp.controller.ts +++ b/src/modules/whatsapp/whatsapp.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Post, Body, Delete, Param } from '@nestjs/common'; +import { Controller, Get, Post, Body, Delete, Param, ForbiddenException, Query, RawBody } from '@nestjs/common'; import { ApiBody, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger'; import { WhatsappService } from './whatsapp.service'; import { AttendanceAssignmentService } from '../attendance/attendance-assignment.service'; @@ -12,6 +12,9 @@ import { UpdateWhatsappTemplateDto, } from './dto/whatsapp.dto'; import { WhatsappTemplateService } from './whatsapp-template.service'; +import { Public } from '../auth/decorators/public.decorator'; + + @ApiTags('WhatsApp') @Controller('whatsapp') @@ -268,4 +271,29 @@ export class WhatsappController { async deleteTemplate(@Param('id') id: string) { return this.whatsappTemplateService.deleteTemplate(Number(id)); } + + + @Public() + @ApiOperation({ summary: 'Verificação do webhook Meta' }) + @Get('webhook') + verifyWebhook( + @Query('hub.mode') mode: string, + @Query('hub.verify_token') token: string, + @Query('hub.challenge') challenge: string, + ) { + if (mode === 'subscribe' && token === process.env.META_WEBHOOK_TOKEN) { + return challenge; + } + throw new ForbiddenException('Token inválido'); +} + +@Public() +@ApiOperation({ summary: 'Recebe eventos do webhook Meta' }) +@Post('webhook') +async receiveWebhook(@Body() body: any) { + console.log('Webhook Meta:', JSON.stringify(body, null, 2)); + return { status: 'ok' }; +} + + }