diff --git a/deploy-vps.sh b/deploy-vps.sh new file mode 100644 index 00000000..5c5ee61c --- /dev/null +++ b/deploy-vps.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# =========================================== +# SCRIPT DE DEPLOY - Evolution API Multi-Device +# =========================================== + +set -e + +echo "🚀 Iniciando deploy da Evolution API com Multi-Device fix..." + +# Cores para output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Verificar se está no diretório correto +if [ ! -f "docker-compose.prod.yaml" ]; then + echo -e "${RED}❌ Erro: Execute este script no diretório da Evolution API${NC}" + exit 1 +fi + +# Backup do docker-compose atual (se existir) +if [ -f "docker-compose.yaml" ]; then + echo -e "${YELLOW}📦 Fazendo backup do docker-compose.yaml atual...${NC}" + cp docker-compose.yaml docker-compose.yaml.backup.$(date +%Y%m%d_%H%M%S) +fi + +# Parar containers existentes (mantém volumes) +echo -e "${YELLOW}⏹️ Parando containers existentes...${NC}" +docker compose -f docker-compose.prod.yaml down 2>/dev/null || docker-compose -f docker-compose.prod.yaml down 2>/dev/null || true + +# Build da nova imagem +echo -e "${YELLOW}🔨 Buildando imagem com Multi-Device fix...${NC}" +docker compose -f docker-compose.prod.yaml build --no-cache api + +# Subir containers +echo -e "${YELLOW}🚀 Iniciando containers...${NC}" +docker compose -f docker-compose.prod.yaml up -d + +# Aguardar API iniciar +echo -e "${YELLOW}⏳ Aguardando API iniciar...${NC}" +sleep 10 + +# Verificar status +echo -e "${GREEN}✅ Deploy concluído!${NC}" +echo "" +echo "📊 Status dos containers:" +docker compose -f docker-compose.prod.yaml ps + +echo "" +echo "📋 Últimos logs da API:" +docker compose -f docker-compose.prod.yaml logs api --tail 20 + +echo "" +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN}🎉 Evolution API Multi-Device está rodando!${NC}" +echo -e "${GREEN}========================================${NC}" +echo "" +echo "🔗 Acesse: http://SEU_IP:8080" +echo "📚 Docs: http://SEU_IP:8080/docs" +echo "🖥️ Manager: http://SEU_IP:8080/manager" +echo "" +echo "💡 Para ver logs em tempo real:" +echo " docker compose -f docker-compose.prod.yaml logs -f api" + diff --git a/docker-compose.local.yaml b/docker-compose.local.yaml new file mode 100644 index 00000000..1c68ee40 --- /dev/null +++ b/docker-compose.local.yaml @@ -0,0 +1,120 @@ +version: "3.8" + +services: + api: + container_name: evolution_api_local + build: + context: . + dockerfile: Dockerfile + restart: unless-stopped + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_started + ports: + - "8080:8080" + volumes: + - evolution_instances:/evolution/instances + networks: + - evolution-local + environment: + # Servidor + - SERVER_NAME=evolution + - SERVER_TYPE=http + - SERVER_PORT=8080 + - SERVER_URL=http://localhost:8080 + - SERVER_DISABLE_DOCS=false + - SERVER_DISABLE_MANAGER=false + + # Banco de dados + - DATABASE_PROVIDER=postgresql + - DATABASE_CONNECTION_URI=postgresql://evolution:evolution123@postgres:5432/evolution + - DATABASE_CONNECTION_CLIENT_NAME=evolution + - DATABASE_SAVE_DATA_INSTANCE=true + - DATABASE_SAVE_DATA_NEW_MESSAGE=true + - DATABASE_SAVE_MESSAGE_UPDATE=true + - DATABASE_SAVE_DATA_CONTACTS=true + - DATABASE_SAVE_DATA_CHATS=true + - DATABASE_SAVE_DATA_HISTORIC=true + - DATABASE_SAVE_DATA_LABELS=true + - DATABASE_SAVE_IS_ON_WHATSAPP=true + - DATABASE_SAVE_IS_ON_WHATSAPP_DAYS=7 + + # Redis + - CACHE_REDIS_ENABLED=true + - CACHE_REDIS_URI=redis://redis:6379 + - CACHE_REDIS_PREFIX_KEY=evolution-cache + - CACHE_REDIS_TTL=604800 + - CACHE_REDIS_SAVE_INSTANCES=true + - CACHE_LOCAL_ENABLED=true + + # Autenticação + - AUTHENTICATION_API_KEY=sua-api-key-aqui + - AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=false + + # Logs + - LOG_LEVEL=ERROR,WARN,DEBUG,INFO,LOG,VERBOSE,WEBHOOKS,WEBSOCKET + - LOG_COLOR=true + - LOG_BAILEYS=error + + # Instâncias + - DEL_INSTANCE=false + - DEL_TEMP_INSTANCES=true + + # Idioma + - LANGUAGE=pt-BR + + # WebSocket + - WEBSOCKET_ENABLED=true + - WEBSOCKET_GLOBAL_EVENTS=true + + # QR Code + - QRCODE_LIMIT=30 + - QRCODE_COLOR=#198754 + + # Telemetria + - TELEMETRY_ENABLED=false + + postgres: + container_name: evolution_postgres_local + image: postgres:15-alpine + restart: unless-stopped + environment: + - POSTGRES_DB=evolution + - POSTGRES_USER=evolution + - POSTGRES_PASSWORD=evolution123 + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - evolution-local + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U evolution -d evolution"] + interval: 5s + timeout: 5s + retries: 5 + + redis: + container_name: evolution_redis_local + image: redis:7-alpine + restart: unless-stopped + command: redis-server --appendonly yes + volumes: + - redis_data:/data + networks: + - evolution-local + ports: + - "6379:6379" + +volumes: + evolution_instances: + postgres_data: + redis_data: + +networks: + evolution-local: + name: evolution-local + driver: bridge + diff --git a/docker-compose.prod.yaml b/docker-compose.prod.yaml new file mode 100644 index 00000000..7f05d11c --- /dev/null +++ b/docker-compose.prod.yaml @@ -0,0 +1,64 @@ +services: + api: + container_name: evolution_api + # Build local com as alterações do Multi-Device + build: + context: . + dockerfile: Dockerfile + image: evolution-api:v2.3.4-multidevice + restart: always + depends_on: + - redis + - postgres + ports: + - 8080:8080 + volumes: + - evolution_instances:/evolution/instances + networks: + - evolution-net + env_file: + - .env + expose: + - 8080 + + redis: + image: redis:latest + networks: + - evolution-net + container_name: redis + command: > + redis-server --port 6379 --appendonly yes + volumes: + - evolution_redis:/data + ports: + - 6379:6379 + + postgres: + container_name: postgres + image: postgres:15 + networks: + - evolution-net + command: ["postgres", "-c", "max_connections=1000", "-c", "listen_addresses=*"] + restart: always + ports: + - 5432:5432 + environment: + - POSTGRES_USER=caio + - POSTGRES_PASSWORD=caio123 + - POSTGRES_DB=evolution + - POSTGRES_HOST_AUTH_METHOD=trust + volumes: + - postgres_data:/var/lib/postgresql/data + expose: + - 5432 + +volumes: + evolution_instances: + evolution_redis: + postgres_data: + +networks: + evolution-net: + name: evolution-net + driver: bridge + diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 4db8146c..6957c2d4 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -67,7 +67,6 @@ import { Chatwoot, ConfigService, configService, - ConfigSessionPhone, Database, Log, Openai, @@ -124,7 +123,6 @@ import makeWASocket, { Product, proto, UserFacingSocketConfig, - WABrowserDescription, WAMediaUpload, WAMessage, WAMessageKey, @@ -143,7 +141,6 @@ import Long from 'long'; import mimeTypes from 'mime-types'; import NodeCache from 'node-cache'; import cron from 'node-cron'; -import { release } from 'os'; import { join } from 'path'; import P from 'pino'; import qrcode, { QRCodeToDataURLOptions } from 'qrcode'; @@ -624,21 +621,16 @@ export class BaileysStartupService extends ChannelStartupService { private async createClient(number?: string): Promise { this.instance.authState = await this.defineAuthState(); - const session = this.configService.get('CONFIG_SESSION_PHONE'); - - let browserOptions = {}; - if (number || this.phoneNumber) { this.phoneNumber = number; this.logger.info(`Phone number: ${number}`); - } else { - const browser: WABrowserDescription = [session.CLIENT, session.NAME, release()]; - browserOptions = { browser }; - - this.logger.info(`Browser: ${browser}`); } + // Multi-Device mode: não definimos browser para evitar ser tratado como WebClient + // Isso faz o Baileys usar o modo MD nativo, que não conflita com outras sessões + this.logger.info('Using Multi-Device native mode (no browser identification)'); + // Fetch latest WhatsApp Web version automatically const baileysVersion = await fetchLatestWaWebVersion({}); const version = baileysVersion.version; @@ -697,7 +689,7 @@ export class BaileysStartupService extends ChannelStartupService { msgRetryCounterCache: this.msgRetryCounterCache, generateHighQualityLinkPreview: true, getMessage: async (key) => (await this.getMessage(key)) as Promise, - ...browserOptions, + // Removido browserOptions para usar Multi-Device nativo (não WebClient) markOnlineOnConnect: this.localSettings.alwaysOnline, retryRequestDelayMs: 350, maxMsgRetryCount: 4,