pywhatsweb


Namepywhatsweb JSON
Version 0.5.3 PyPI version JSON
download
home_pageNone
SummaryBiblioteca Python para WhatsApp Web corporativo com sidecar Python integrado (padrão) ou Node.js (opcional)
upload_time2025-08-21 18:25:27
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords whatsapp whatsapp-web automation bot api corporate enterprise
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 🚀 PyWhatsWeb v0.5.1 - Guia para Desenvolvedores

## 📑 **ÍNDICE RÁPIDO**
- [🚀 **COMO FUNCIONA**](#-como-funciona-a-biblioteca) - Arquitetura e fluxo
- [📁 **ESTRUTURA**](#-estrutura-de-pastas-e-arquivos) - Pastas e arquivos
- [⚡ **QUICK START**](#-quick-start-5-minutos) - Começar em 5 minutos
- [🔧 **COMO USAR**](#-como-usar-a-biblioteca) - Guia completo
- [📊 **FUNCIONALIDADES**](#-funcionalidades-avançadas) - Recursos avançados
- [🚨 **TROUBLESHOOTING**](#-suporte-e-ajuda) - Problemas comuns

## 📋 **VISÃO GERAL**

**PyWhatsWeb** é uma biblioteca Python moderna para integração corporativa com WhatsApp Web. Diferente de soluções baseadas em Selenium, ela utiliza uma arquitetura **sidecar Python integrado** (padrão) ou **sidecar Node.js** (opcional) para operação headless e eventos em tempo real.

### 🎯 **O QUE A BIBLIOTECA FAZ AGORA (v0.5.1)**

✅ **Multi-sessão**: Gerencia múltiplas sessões WhatsApp simultaneamente  
✅ **Eventos em tempo real**: WebSocket para QR, mensagens, conexão, etc.  
✅ **Storage pluggable**: FileSystem ou Django ORM (opcional)  
✅ **Sistema Kanban**: Status NEW/ACTIVE/DONE para conversas  
✅ **API REST**: Comunicação HTTP com sidecar  
✅ **Sem navegador**: Operação completamente headless  
✅ **Multi-framework**: Funciona em Django, Flask, FastAPI, scripts Python  
✅ **Reconexão automática**: WebSocket com backoff exponencial  
✅ **Idempotência**: Sistema de deduplicação e rastreamento  
✅ **Health & Métricas**: Monitoramento completo do sistema  
✅ **Segurança**: API key, CORS, rate limiting, logs seguros  
✅ **Exemplo Django completo**: Dashboard funcional com WebSocket  
✅ **Autenticação WebSocket obrigatória**: Token obrigatório + multi-tenant  
✅ **Verificação de compatibilidade**: Fail-fast no boot (Python + qrcode[pil])  
✅ **Anti-loop**: Sistema de origem de mensagens (inbound/outbound)  
✅ **Normalização E.164**: Validação e formatação de números de telefone  
✅ **Catálogo de erros padronizados**: 50+ códigos com HTTP status e ações  
✅ **Métricas Prometheus**: Endpoint `/metrics` com histogramas e percentis  
✅ **Docker + Orquestração**: Dockerfile otimizado + docker-compose completo  
✅ **Runbooks de operação**: Procedimentos para cenários críticos em produção  
✅ **Python 3.13**: Suporte completo e compatibilidade total  
✅ **Dataclasses corrigidas**: Ordem de campos compatível com Python 3.13+  
✅ **Verificação automática**: Compatibilidade detectada no import  
✅ **Configurações centralizadas**: Todas as configurações em um local  
✅ **Auto-start do sidecar**: Inicia automaticamente sem intervenção manual  
✅ **Cleanup automático**: Gerencia ciclo de vida completo do sidecar  
✅ **Compatibilidade Windows**: Suporte nativo para Windows e Linux/Mac  
✅ **Sidecar Python integrado**: Opção de usar Python puro sem Node.js (PADRÃO)  
✅ **100% Python nativo**: Sem dependências externas por padrão  

---

## 🔄 **CHANGELOG - MUDANÇAS DA VERSÃO ATUAL**

### **📋 [v0.5.1] - 2025-01-XX - Lançamento Principal: Sidecar Python Integrado**

#### **🚀 LANÇAMENTO PRINCIPAL**
- **Versão 0.5.1**: Sidecar Python integrado como padrão
- **Eliminação completa**: Dependência Node.js removida por padrão
- **Biblioteca 100% Python**: Máxima compatibilidade e simplicidade

#### **✨ ADICIONADO**
- **Sidecar Python integrado**: Opção de usar Python puro sem Node.js (padrão)
- **Geração de QR Code nativo**: Usando biblioteca `qrcode[pil]` integrada
- **Simulação completa de WhatsApp**: Funcionalidade sem dependências externas
- **Opção de escolha de sidecar**: `sidecar_type="python"` ou `sidecar_type="nodejs"`
- **Auto-start inteligente**: Detecta tipo de sidecar e inicia automaticamente

#### **🔧 CORRIGIDO**
- **Manager agora suporta**: Múltiplos tipos de sidecar
- **Verificação automática**: Dependências para ambos os tipos
- **Compatibilidade mantida**: Com sidecar Node.js existente

#### **🚀 MELHORIAS**
- **Instalação mais simples**: Não precisa de Node.js por padrão
- **Dependências reduzidas**: Apenas Python + qrcode[pil]
- **Flexibilidade total**: Escolha entre Python puro ou Node.js completo

---

### **📋 [v0.4.8] - 2025-01-XX - Auto-start do Sidecar e Correções**

#### **✨ ADICIONADO**
- **Auto-start do sidecar**: WhatsWebManager agora inicia o sidecar automaticamente
- **Sidecar Python integrado**: Opção de usar Python puro sem Node.js (padrão)
- **Verificação automática**: Detecta dependências e inicia sidecar apropriado
- **Cleanup automático**: Para o sidecar quando o manager é destruído
- **Compatibilidade Windows**: Suporte completo para Windows com flags de processo

#### **🔧 CORRIGIDO**
- **Decorators de eventos**: Corrigida implementação dos handlers @session.on()
- **Cleanup de recursos**: Sistema de limpeza mais robusto para sessões e sidecar
- **Logging melhorado**: Mensagens mais claras durante inicialização e operação

#### **🚀 MELHORIAS**
- **Inicialização automática**: Sidecar inicia em background sem intervenção manual
- **Verificação de saúde**: Aguarda sidecar estar pronto antes de continuar
- **Gerenciamento de processos**: Controle completo do ciclo de vida do sidecar

---

### **📋 [v0.4.6] - 2025-01-XX - Correção Importações e Compatibilidade Total**

#### **🔧 CORRIGIDO**
- **Bug de dataclasses Python 3.13**: Corrigido erro `TypeError: non-default argument follows default argument`
- **Ordem de campos**: Reordenados campos obrigatórios antes de campos opcionais em todas as classes
- **Compatibilidade**: Todas as dataclasses agora funcionam perfeitamente com Python 3.13+
- **Herança**: Corrigida herança da classe `MediaMessage` da classe `Message`

#### **✨ ADICIONADO**
- **Estrutura de dados robusta**: Dataclasses com ordem correta de campos
- **Validação pós-inicialização**: Métodos `__post_init__` funcionando corretamente
- **Compatibilidade total**: Python 3.13 + websockets 15.0+ + dataclasses funcionando

#### **🚀 MELHORIAS**
- **Estrutura de dados**: Todas as classes agora seguem padrão Python 3.13+
- **Validação**: Sistema de validação mais robusto e compatível
- **Herança**: Sistema de herança funcionando perfeitamente

---

## 🚀 **COMO FUNCIONA A BIBLIOTECA**

### **🎯 TIPOS DE SIDECAR DISPONÍVEIS**

#### **🐍 Sidecar Python Integrado (PADRÃO)**
- **Sem Node.js**: Não precisa instalar Node.js
- **Sem dependências externas**: Apenas bibliotecas Python
- **QR Code nativo**: Gerado com biblioteca `qrcode[pil]`
- **Simulação completa**: WhatsApp funcionando sem navegador real
- **Compatibilidade total**: Funciona em qualquer ambiente Python

#### **📦 Sidecar Node.js (OPCIONAL)**
- **Funcionalidade completa**: WhatsApp Web real via Puppeteer
- **Eventos reais**: QR, mensagens, status em tempo real
- **Requer Node.js**: Precisa instalar Node.js 18+
- **Dependências externas**: npm install no diretório sidecar

### **🎯 FLUXO BÁSICO DE FUNCIONAMENTO**

```
1. INICIALIZAÇÃO
   ├── Python cria WhatsWebManager
   ├── Manager conecta com sidecar Node.js
   └── Sidecar inicia Puppeteer + whatsapp-web.js

2. CRIAÇÃO DE SESSÃO
   ├── Manager.create_session() gera ID único
   ├── Sidecar cria instância WhatsApp
   └── WebSocket estabelece conexão em tempo real

3. AUTENTICAÇÃO
   ├── Sidecar gera QR Code
   ├── WebSocket envia evento 'qr' para Python
   ├── Usuário escaneia QR no celular
   └── Evento 'ready' confirma autenticação

4. OPERAÇÃO
   ├── Eventos 'message' chegam via WebSocket
   ├── Python processa com handlers @session.on()
   ├── Envio via session.send_text() → HTTP API
   └── Sidecar envia via whatsapp-web.js
```

### **🔌 COMUNICAÇÃO ENTRE COMPONENTES**

- **Python ↔ Sidecar**: HTTP REST + WebSocket
- **Sidecar ↔ WhatsApp**: whatsapp-web.js + Puppeteer
- **Eventos**: Bidirecional via WebSocket (QR, mensagens, status)
- **Comandos**: Unidirecional Python → Sidecar (enviar, parar, etc.)

### **🔄 CICLO DE VIDA DA SESSÃO**

```
DISCONNECTED → CONNECTING → CONNECTED → READY → [OPERATION] → DISCONNECTED
     ↑                                                                  ↓
     └─────────────── RECONEXÃO AUTOMÁTICA ←───────────────────────────┘
```

---

## 🏗️ **ARQUITETURA DA BIBLIOTECA**

```
┌─────────────────────────────────────────────────────────────────┐
│                    SEU APP PYTHON                              │
│  ┌─────────────────┐    ┌─────────────────┐    ┌─────────────┐ │
│  │ WhatsWebManager │    │     Session     │    │   Storage   │ │
│  │   (Core)        │    │   (Individual)  │    │ (Pluggable) │ │
│  └─────────────────┘    └─────────────────┘    └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
                              │
                              │ HTTP + WebSocket
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                    SIDECAR NODE.JS                             │
│  ┌─────────────────┐    ┌─────────────────┐    ┌─────────────┐ │
│  │   Express API   │    │  WebSocket WS   │    │whatsapp-web.│ │
│  │   (REST)        │    │   (Events)      │    │     js      │ │
│  └─────────────────┘    └─────────────────┘    └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```

---

## 📁 **ESTRUTURA DE PASTAS E ARQUIVOS**

### **🎯 RESUMO DA ESTRUTURA**
```
pywhatsweb-lib/
├── 📂 pywhatsweb/           # 🐍 CORE PYTHON (biblioteca principal)
│   ├── __init__.py          # 🚪 Ponto de entrada e imports
│   ├── manager.py           # 🎮 Gerenciador de sessões
│   ├── session.py           # 💬 Sessão WhatsApp individual
│   ├── enums.py             # 📋 Enumerações e constantes
│   ├── models.py            # 🗃️ Modelos de dados
│   ├── exceptions.py        # 🚨 Exceções customizadas
│   └── storage/             # 💾 Sistema de persistência
│       ├── base.py          # 🔌 Interface base
│       ├── filesystem.py    # 📁 Storage em arquivo (padrão)
│       └── django.py        # �� Storage Django ORM (opcional)
├── 📂 sidecar/              # 🟢 SIDECAR NODE.JS (servidor)
│   ├── src/server.js        # 🖥️ Servidor principal
│   ├── package.json         # 📦 Dependências Node.js
│   └── Dockerfile           # 🐳 Container Docker
├── 📂 examples/             # 💡 EXEMPLOS DE USO
│   ├── basic_usage.py       # 🚀 Uso básico
│   └── django_complete.py   # 🎯 Exemplo Django completo
├── 📂 tests/                # 🧪 TESTES AUTOMATIZADOS
├── 📂 whatsapp_data/        # 💾 DADOS SALVOS (gerado automaticamente)
├── 📄 README.md             # 📖 Documentação para usuários
├── 📄 README-for-devs.md    # 🔧 Este arquivo (guia técnico)
├── 📄 requirements.txt      # 🐍 Dependências Python
└── 📄 docker-compose.yml    # 🐳 Orquestração Docker
```

### **📂 `pywhatsweb/utils.py` - UTILITÁRIOS E VALIDAÇÕES**

#### **Normalização de números E.164**
```python
from pywhatsweb.utils import normalize_phone_number, validate_phone_number

# Normalizar número para formato E.164
phone = normalize_phone_number("11999999999")  # +5511999999999
is_valid, normalized = validate_phone_number("11999999999")

# Informações detalhadas do número
from pywhatsweb.utils import get_phone_info, format_phone_for_display

info = get_phone_info("+5511999999999")
# {
#   'number': '+5511999999999',
#   'country_code': 55,
#   'region': 'BR',
#   'carrier': 'Vivo',
#   'timezone': 'America/Sao_Paulo'
# }

# Formatação para exibição
display = format_phone_for_display("+5511999999999", "NATIONAL")  # (11) 99999-9999
```

#### **Geração e validação de IDs**
```python
from pywhatsweb.utils import generate_session_id, validate_session_id

# Gerar ID único para sessão
session_id = generate_session_id("session", "tenant_123")  # session_tenant_123_1703000000_abc12345

# Validar formato
is_valid = validate_session_id("session_123")  # True/False
```

#### **Timezone e formatação**
```python
from pywhatsweb.utils import get_current_timezone, format_timestamp

current_tz = get_current_timezone()  # 'America/Sao_Paulo'
formatted = format_timestamp(datetime.now(), 'America/Sao_Paulo')  # '2024-12-19 10:30:00 BRT'
```

### **📂 `pywhatsweb/errors.py` - CATÁLOGO DE ERROS PADRONIZADOS**

#### **Sistema completo de códigos de erro**
```python
from pywhatsweb.errors import ErrorCode, ErrorSeverity, get_error_info, create_error_response

# Códigos de erro disponíveis
ErrorCode.E_SESSION_NOT_FOUND          # 404 - Sessão não encontrada
ErrorCode.E_AUTHENTICATION_FAILED      # 401 - Falha na autenticação
ErrorCode.E_MEDIA_TOO_LARGE           # 400 - Arquivo muito grande
ErrorCode.E_WHATSAPP_2FA_REQUIRED     # 400 - 2FA necessário
ErrorCode.E_WHATSAPP_BANNED           # 403 - WhatsApp banido

# Severidades
ErrorSeverity.LOW        # Aviso, não afeta funcionalidade
ErrorSeverity.MEDIUM     # Erro recuperável
ErrorSeverity.HIGH       # Erro crítico, afeta funcionalidade
ErrorSeverity.CRITICAL   # Erro fatal, sistema inoperante

# Obter informações do erro
error_info = get_error_info(ErrorCode.E_SESSION_NOT_FOUND)
# {
#   'error_code': 'SESSION_NOT_FOUND',
#   'http_status': 404,
#   'message': 'Sessão não encontrada',
#   'severity': 'medium',
#   'retryable': False,
#   'action': 'Verificar se o session_id está correto...'
# }

# Criar resposta de erro padronizada
error_response = create_error_response(ErrorCode.E_SESSION_NOT_FOUND, {'session_id': '123'})
```

#### **Filtros e consultas**
```python
from pywhatsweb.errors import get_retryable_errors, get_errors_by_severity

# Erros que podem ser tentados novamente
retryable = get_retryable_errors()

# Erros por severidade
critical = get_errors_by_severity(ErrorSeverity.CRITICAL)
high = get_errors_by_severity(ErrorSeverity.HIGH)
```

### **📂 `pywhatsweb/` - CORE DA BIBLIOTECA**

#### **`__init__.py`** - Ponto de entrada principal
```python
# Importa todas as classes principais
from pywhatsweb import WhatsWebManager, Session, FileSystemStore

# Exemplo de uso básico
manager = WhatsWebManager()
session = manager.create_session("minha_sessao")
```

**Funções expostas:**
- `WhatsWebManager`: Gerenciador principal
- `Session`: Sessão individual
- `BaseStore`, `FileSystemStore`, `DjangoORMStore`: Storage
- `SessionStatus`, `MessageType`, `KanbanStatus`: Enums
- Todas as exceções customizadas

#### **`manager.py`** - Gerenciador de sessões
```python
class WhatsWebManager:
    def __init__(self, sidecar_host="localhost", sidecar_port=3000, 
                 api_key="secret", storage=None):
        # Configuração do sidecar e storage
    
    def create_session(self, session_id: str, **kwargs) -> Session:
        # Cria nova sessão WhatsApp
    
    def get_session(self, session_id: str) -> Optional[Session]:
        # Recupera sessão existente
    
    def list_sessions(self) -> List[str]:
        # Lista todas as sessões ativas
    
    def remove_session(self, session_id: str) -> bool:
        # Remove sessão específica
```

**Métodos principais:**
- `create_session()`: Cria nova sessão
- `get_session()`: Recupera sessão existente
- `list_sessions()`: Lista todas as sessões
- `get_active_sessions()`: Sessões conectadas
- `close_all_sessions()`: Para todas as sessões
- `cleanup()`: Limpeza completa

#### **`session.py`** - Sessão WhatsApp individual
```python
class Session:
    def __init__(self, session_id: str, manager, **kwargs):
        # Inicializa sessão com ID único
    
    def start(self) -> bool:
        # Inicia conexão com sidecar
    
    def stop(self) -> bool:
        # Para a sessão
    
    def send_text(self, to: str, text: str) -> str:
        # Envia mensagem de texto
    
    def send_media(self, to: str, media_path: str, caption: str = "") -> str:
        # Envia arquivo de mídia
    
    def on(self, event: str, handler: Callable):
        # Registra handler para eventos
```

**Eventos disponíveis:**
- `qr`: QR Code para autenticação
- `authenticated`: Autenticação bem-sucedida
- `ready`: WhatsApp pronto para uso
- `message`: Nova mensagem recebida
- `disconnected`: Desconexão

**Funcionalidades avançadas:**
- **Reconexão automática**: Backoff exponencial (2^tentativas)
- **Heartbeat**: Ping/pong a cada 30s
- **Máximo 5 tentativas** de reconexão

**Exemplo de uso:**
```python
@session.on("qr")
def on_qr(data):
    print(f"QR Code: {data['qr']}")

@session.on("message")
def on_message(data):
    print(f"Nova mensagem: {data['body']}")

session.start()  # Inicia e aguarda QR
```

#### **`enums.py`** - Enumerações e contratos do sistema
```python
class SessionStatus(Enum):
    DISCONNECTED = "disconnected"    # Desconectado
    CONNECTING = "connecting"        # Conectando
    CONNECTED = "connected"          # Conectado
    READY = "ready"                  # Pronto para uso
    ERROR = "error"                  # Erro

class MessageType(Enum):
    TEXT = "text"                    # Texto
    IMAGE = "image"                  # Imagem
    AUDIO = "audio"                  # Áudio
    VIDEO = "video"                  # Vídeo
    DOCUMENT = "document"            # Documento

class KanbanStatus(Enum):
    NEW = "new"                      # Aguardando
    ACTIVE = "active"                # Em atendimento
    DONE = "done"                    # Concluídos

class MessageStatus(Enum):
    PENDING = "pending"              # Enfileirada
    SENT = "sent"                    # Enviada
    DELIVERED = "delivered"          # Entregue
    READ = "read"                    # Lida
    FAILED = "failed"                # Falhou
```

**Contratos de eventos padronizados:**
```python
@dataclass
class EventPayload:
    event: EventType                 # Tipo do evento
    session_id: str                  # ID da sessão
    timestamp: datetime              # Timestamp do evento
    trace_id: str                    # ID único para rastreamento
    data: Dict[str, Any]            # Dados específicos do evento

# Fábricas de eventos
create_qr_event(session_id, qr_data, expires_in=60)
create_message_event(session_id, message_data)
create_ready_event(session_id, phone_number, device_info)
create_error_event(session_id, error_code, error_message)
```

**Constantes do sistema:**
```python
# Configurações de mídia
MAX_MEDIA_SIZE = 16 * 1024 * 1024  # 16MB (limite WhatsApp)
SUPPORTED_IMAGE_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']

# Timeouts
CONNECTION_TIMEOUT = 30             # Timeout de conexão (segundos)
MESSAGE_TIMEOUT = 60                # Timeout de envio de mensagem (segundos)
QR_EXPIRATION = 60                  # Expiração do QR (segundos)

# Rate limits
MAX_MESSAGES_PER_MINUTE = 30        # Máximo de mensagens por minuto
MAX_SESSIONS_PER_IP = 10            # Máximo de sessões por IP
MAX_REQUESTS_PER_MINUTE = 100       # Máximo de requisições por minuto
```

#### **`exceptions.py`** - Exceções customizadas
```python
class WhatsAppError(Exception):      # Erro base
class SessionError(Exception):       # Erro de sessão
class ConnectionError(Exception):    # Erro de conexão
class MessageError(Exception):       # Erro de mensagem
class StorageError(Exception):       # Erro de storage
class AuthenticationError(Exception): # Erro de autenticação
class WebSocketError(Exception):     # Erro de WebSocket
class APIError(Exception):           # Erro de API
```

#### **`models.py`** - Modelos de dados com idempotência
```python
@dataclass
class Contact:
    phone: str                       # Número do telefone
    name: Optional[str]              # Nome do contato
    is_group: bool = False           # É grupo?
    is_business: bool = False        # É business?
    profile_picture: Optional[str]   # Foto do perfil
    status: Optional[str]            # Status do contato
    last_seen: Optional[datetime]    # Última vez visto
    created_at: datetime             # Data de criação
    updated_at: datetime             # Data de atualização

@dataclass
class Message:
    id: str                          # ID único da mensagem
    content: str                     # Conteúdo da mensagem
    sender: Contact                  # Remetente
    recipient: Contact               # Destinatário
    message_type: MessageType        # Tipo da mensagem
    timestamp: datetime              # Timestamp da mensagem
    status: MessageStatus            # Status de entrega
    metadata: Dict[str, Any]        # Metadados adicionais
    
    # Campos de idempotência e rastreamento
    trace_id: str                    # ID único para rastreamento
    producer_id: Optional[str]       # ID do produtor (para deduplicação)
    correlation_id: Optional[str]    # ID de correlação
    sequence_number: Optional[int]   # Número de sequência
    
    # Campos de auditoria
    created_at: datetime             # Data de criação
    updated_at: datetime             # Data de atualização

@dataclass
class Chat:
    chat_id: str                     # ID do chat
    status: KanbanStatus             # Status Kanban
    owner_id: Optional[str]          # Atendente responsável
    last_message_at: Optional[datetime]  # Última mensagem
    created_at: datetime             # Data de criação
    updated_at: datetime             # Data de atualização
    
    # Campos de rastreamento
    trace_id: str                    # ID único para rastreamento
    correlation_id: Optional[str]    # ID de correlação
    
    # Campos de auditoria
    assigned_at: Optional[datetime]  # Data de atribuição
    assigned_by: Optional[str]       # Quem atribuiu
    completed_at: Optional[datetime] # Data de conclusão
    completed_by: Optional[str]      # Quem concluiu
```

**Métodos de idempotência:**
```python
# Gerar chave de idempotência única
message.get_idempotency_key()       # producer_id:sequence_number ou trace_id:timestamp

# Marcar status de entrega
message.mark_as_sent()              # PENDING → SENT
message.mark_as_delivered()         # SENT → DELIVERED
message.mark_as_read()              # DELIVERED → READ
message.mark_as_failed(error)       # Qualquer → FAILED

# Gerenciar status Kanban
chat.assign_to(owner_id, assigned_by)  # NEW → ACTIVE
chat.mark_as_done(completed_by)        # ACTIVE → DONE
chat.reopen(reopened_by)               # DONE → NEW
```

### **📂 `pywhatsweb/storage/` - SISTEMA DE PERSISTÊNCIA**

#### **`base.py` - Interface base**
```python
class BaseStore(ABC):
    @abstractmethod
    def save_message(self, message: Message):
        # Salva mensagem
    
    @abstractmethod
    def get_chat_messages(self, chat_id: str, limit: int = 50) -> List[Message]:
        # Recupera mensagens do chat
    
    @abstractmethod
    def save_contact(self, contact: Contact):
        # Salva contato
    
    @abstractmethod
    def get_contact(self, phone: str) -> Optional[Contact]:
        # Recupera contato
    
    @abstractmethod
    def save_chat(self, chat: Chat):
        # Salva chat
    
    @abstractmethod
    def get_chat(self, chat_id: str) -> Optional[Chat]:
        # Recupera chat
```

#### **`filesystem.py` - Storage em arquivo**
```python
class FileSystemStore(BaseStore):
    def __init__(self, base_dir: str = "./whatsapp_data"):
        # Armazena dados em arquivos JSON
    
    def save_message(self, message: Message):
        # Salva em JSON
    
    def get_chat_messages(self, chat_id: str, limit: int = 50) -> List[Message]:
        # Lê de JSON
```

**Estrutura de arquivos:**
```
whatsapp_data/
├── messages/
│   ├── chat_5511999999999.json
│   └── chat_5511888888888.json
├── contacts/
│   └── contacts.json
├── groups/
│   └── groups.json
└── chats/
    └── chats.json
```

#### **`django.py` - Storage Django ORM (OPCIONAL)**
```python
class DjangoORMStore(BaseStore):
    def __init__(self):
        # Verifica se Django está disponível
    
    def set_models(self, session_model, message_model, contact_model, 
                   group_model, chat_model, event_model):
        # Usuário deve configurar os models Django
```

**IMPORTANTE**: Django é **OPCIONAL**! A biblioteca funciona perfeitamente sem Django.

---

## ⚡ **QUICK START (5 MINUTOS)**

### **🚀 INSTALAÇÃO RÁPIDA**

#### **🐍 Sidecar Python (Recomendado - Sem Node.js)**
```bash
# 1. Instalar biblioteca
pip install pywhatsweb

# 2. Testar (sidecar inicia automaticamente)
python examples/basic_usage.py
```

#### **📦 Sidecar Node.js (Opcional - Com Node.js)**
```bash
# 1. Clonar e entrar
git clone <repo> && cd pywhatsweb-lib

# 2. Instalar Python
pip install -r requirements.txt

# 3. Instalar Node.js e iniciar sidecar
cd sidecar && npm install && npm start

# 4. Em outro terminal, testar
python examples/basic_usage.py
```

### **💻 CÓDIGO MÍNIMO FUNCIONAL**

#### **🐍 Sidecar Python (Padrão)**
```python
from pywhatsweb import WhatsWebManager

# Criar manager com sidecar Python (padrão)
manager = WhatsWebManager(
    api_key="sua-chave",
    sidecar_type="python"  # Opcional, é o padrão
)

# Criar sessão
session = manager.create_session("teste")

# Handler para QR
@session.on("qr")
def on_qr(data):
    print(f"QR: {data['qr']}")  # Escanear no celular

# Handler para mensagens
@session.on("message")
def on_message(data):
    print(f"Msg: {data['body']} de {data['from']}")

# Iniciar e aguardar QR
session.start()
```

#### **📦 Sidecar Node.js (Opcional)**
```python
from pywhatsweb import WhatsWebManager

# Criar manager com sidecar Node.js
manager = WhatsWebManager(
    api_key="sua-chave",
    sidecar_type="nodejs"  # Especificar Node.js
)

# Criar sessão
session = manager.create_session("teste")

# Handler para QR
@session.on("qr")
def on_qr(data):
    print(f"QR: {data['qr']}")  # Escanear no celular

# Handler para mensagens
@session.on("message")
def on_message(data):
    print(f"Msg: {data['body']} de {data['from']}")

# Iniciar e aguardar QR
session.start()
```

### **✅ O QUE ACONTECE:**
1. **0-5s**: Sidecar inicia e cria sessão
2. **5-10s**: QR Code aparece no console
3. **10-30s**: Escanear QR no WhatsApp
4. **30s+**: Receber/enviar mensagens!

---

### **📂 `sidecar/` - SIDECAR NODE.JS**

#### **`package.json` - Dependências Node.js**
```json
{
  "dependencies": {
    "whatsapp-web.js": "^1.23.0",    // Biblioteca WhatsApp
    "express": "^4.18.2",            // API REST
    "ws": "^8.14.2",                 // WebSocket
    "qrcode": "^1.5.3",              // Geração de QR
    "helmet": "^7.1.0",              // Segurança
    "express-rate-limit": "^7.1.5",  // Rate limiting
    "morgan": "^1.10.0",             // Logging
    "cors": "^2.8.5"                 // CORS
  }
}
```

#### **`src/server.js` - Servidor principal com verificação de compatibilidade**

**Verificação de compatibilidade no boot (FAIL-FAST):**
```javascript
// Verifica automaticamente no startup
const REQUIRED_NODE_VERSION = '18.0.0';
const REQUIRED_WHATSAPP_WEB_JS_VERSION = '1.23.0';
const REQUIRED_PUPPETEER_VERSION = '21.0.0';

function checkCompatibility() {
    // Verificar Node.js
    const nodeVersion = process.version;
    if (!semver.gte(nodeVersion, REQUIRED_NODE_VERSION)) {
        console.error(`❌ Node.js ${REQUIRED_NODE_VERSION}+ é obrigatório. Atual: ${nodeVersion}`);
        process.exit(1);
    }
    
    // Verificar whatsapp-web.js
    const whatsappVersion = require('whatsapp-web.js/package.json').version;
    if (!semver.gte(whatsappVersion, REQUIRED_WHATSAPP_WEB_JS_VERSION)) {
        console.error(`❌ whatsapp-web.js ${REQUIRED_WHATSAPP_WEB_JS_VERSION}+ é obrigatório. Atual: ${whatsappVersion}`);
        process.exit(1);
    }
    
    console.log('✅ Compatibilidade verificada com sucesso');
}

// Executar verificação no startup
checkCompatibility();
```

---

### **🔗 MATRIZ DE COMPATIBILIDADE E VERIFICAÇÃO**

#### **Versões compatíveis e verificações**
| **Componente** | **Versão Mínima** | **Versão Recomendada** | **Verificação** | **Status** |
|----------------|-------------------|-------------------------|-----------------|------------|
| **Node.js** | 18.0.0 | 18.17.0+ (LTS) | `node --version` | ✅ Verificado |
| **whatsapp-web.js** | 1.23.0 | 1.23.0+ | `npm list whatsapp-web.js` | ✅ Verificado |
| **Python** | 3.8 | 3.9+ (3.13+ recomendado) | `python --version` | ✅ Verificado |
| **Sidecar** | v0.5.1 | v0.5.1+ | Health check `/health` | ✅ Verificado |
| **Puppeteer** | 21.0.0 | 21.0.0+ | `npm list puppeteer` | ✅ Verificado |

#### **Verificação Python no import (v0.5.1+)**
```python
# pywhatsweb/__init__.py - Verificação de compatibilidade aprimorada
import sys

def check_python_compatibility():
    """Verifica compatibilidade com versão do Python"""
    if sys.version_info < (3, 8):
        raise RuntimeError(
            "PyWhatsWeb requer Python 3.8 ou superior. "
            f"Versão atual: {sys.version}"
        )
    
    # Verificar versões recomendadas
    if sys.version_info >= (3, 13):
        print("✅ Python 3.13+ detectado - Suporte completo!")
    elif sys.version_info >= (3, 11):
        print("✅ Python 3.11+ detectado - Suporte completo!")
    elif sys.version_info >= (3, 8):
        print("✅ Python 3.8+ detectado - Suporte básico!")
    
    # Verificar dependências opcionais
    try:
        import django
        if django.VERSION >= (3, 2):
            print("✅ Django 3.2+ detectado - Suporte completo!")
        else:
            print("⚠️  Django < 3.2 detectado - Funcionalidades limitadas")
    except ImportError:
        print("ℹ️  Django não instalado - Use 'pip install pywhatsweb[django]'")
    
    try:
        import websockets
        if websockets.version_tuple >= (10, 0):
            print("✅ websockets 10.0+ detectado - Suporte completo!")
        else:
            print("⚠️  websockets < 10.0 detectado - Funcionalidades limitadas")
    except ImportError:
        print("ℹ️  websockets não instalado - Funcionalidades limitadas")

# Executar verificação de compatibilidade
check_python_compatibility()
```

#### **Teste de compatibilidade**
```bash
# Testar compatibilidade completa
pww test compatibility

# Verificar versões instaladas
pww version --all

# Teste de conectividade
pww test connectivity --sidecar --websocket --storage
```

**Resultado da verificação (v0.5.1):**
```
🔍 Verificação de Compatibilidade PyWhatsWeb v0.5.1
==================================================

✅ Node.js: v18.17.0 (requerido: 18.0.0+)
✅ whatsapp-web.js: v1.23.0 (requerido: 1.23.0+)
✅ Python: v3.13.0 (requerido: 3.8+, recomendado: 3.13+)
✅ Sidecar: v0.5.1 (requerido: v0.5.1+)
✅ Puppeteer: v21.0.0 (requerido: 21.0.0+)

🌐 Conectividade:
✅ Sidecar HTTP: http://localhost:3000
✅ Sidecar WebSocket: ws://localhost:3001
✅ Storage: FileSystem (./whatsapp_data)

🎯 Status: COMPATÍVEL ✅
🎯 Python 3.13: SUPORTE COMPLETO ✅
🎯 Websockets 15.0+: SUPORTE COMPLETO ✅
🎯 Dataclasses: SUPORTE COMPLETO ✅
```

**Autenticação WebSocket obrigatória:**
```javascript
// Token obrigatório na conexão
const wss = new WebSocket.Server({ 
    port: WS_PORT,
    verifyClient: (info) => {
        const token = info.req.headers['authorization'] || 
                     new URL(info.req.url, 'http://localhost').searchParams.get('token');
        
        if (!token || token !== `Bearer ${API_KEY}`) {
            return false; // Conexão rejeitada
        }
        
        // Suporte a multi-tenant
        const tenantId = info.req.headers['x-tenant-id'] || 
                        new URL(info.req.url, 'http://localhost').searchParams.get('tenant_id');
        
        if (tenantId) {
            info.req.tenantId = tenantId;
        }
        
        return true;
    }
});
```

**Sistema anti-loop:**
```javascript
client.on('message', (message) => {
    // Marcar origem da mensagem para evitar loops
    const messageOrigin = 'inbound'; // Mensagem recebida do WhatsApp
    const isFromSelf = message.fromMe;
    
    broadcastEvent('message', {
        // ... outros campos
        origin: messageOrigin,           // 'inbound' ou 'outbound'
        fromSelf: isFromSelf,            // true se enviada pelo próprio usuário
        correlationId: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
    });
});
```
```javascript
// API REST endpoints
app.post('/api/session/:id/start', startSession);
app.post('/api/session/:id/stop', stopSession);
app.get('/api/session/:id/status', getSessionStatus);
app.post('/api/session/:id/send-message', sendMessage);

// Health check e métricas
app.get('/health', healthCheck);
app.get('/metrics', getMetrics);

// WebSocket events
ws.on('message', (data) => {
  // Broadcast: qr, authenticated, ready, message, disconnected
});
```

**Endpoints disponíveis:**
- `GET /health` - Health check (sem autenticação)
- `GET /metrics` - Métricas Prometheus (requer API key)
- `GET /metrics.json` - Métricas JSON (requer API key)
- `POST /api/session/:id/start` - Inicia sessão
- `POST /api/session/:id/stop` - Para sessão
- `GET /api/session/:id/status` - Status da sessão
- `POST /api/session/:id/send-message` - Envia mensagem

**Eventos WebSocket:**
- `qr`: QR Code para autenticação
- `authenticated`: Autenticação bem-sucedida
- `ready`: WhatsApp pronto
- `message`: Nova mensagem
- `disconnected`: Desconexão

**Funcionalidades de segurança:**
- **Helmet**: Headers de segurança HTTP
- **CORS**: Controle de origens configurável
- **Rate Limiting**: 100 req/15min por IP
- **API Key**: Autenticação obrigatória para todas as operações
- **WebSocket Auth**: Token obrigatório na conexão
- **Multi-tenant**: Isolamento por tenant_id
- **Logging**: Com correlation ID e tenant ID para auditoria

### **📂 `sidecar/` - DOCKER E ORQUESTRAÇÃO**

#### **`Dockerfile` - Container otimizado**
```dockerfile
# Base Node.js 18 Alpine
FROM node:18-alpine

# Dependências do Puppeteer
RUN apk add --no-cache chromium nss freetype freetype-dev harfbuzz ca-certificates ttf-freefont

# Variáveis de ambiente para Puppeteer
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
    PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser \
    PUPPETEER_ARGS="--no-sandbox --disable-setuid-sandbox --disable-dev-shm-usage --disable-accelerated-2d-canvas --no-first-run --no-zygote --disable-gpu"

# Usuário não-root para segurança
USER node

# Health check automático
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD node -e "require('http').get('http://localhost:3000/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })"
```

#### **`docker-compose.yml` - Orquestração completa**
```yaml
services:
  # Sidecar principal
  pywhatsweb-sidecar:
    build: ./sidecar
    ports: ["3000:3000", "3001:3001"]
    environment:
      - API_KEY=${WHATSAPP_API_KEY}
      - ALLOWED_ORIGINS=${ALLOWED_ORIGINS}
    healthcheck:
      test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })"]
      interval: 30s
      timeout: 10s
      retries: 3

  # Prometheus para métricas
  prometheus:
    image: prom/prometheus:latest
    ports: ["9090:9090"]
    volumes: ["./prometheus:/etc/prometheus"]

  # Grafana para visualização
  grafana:
    image: grafana/grafana:latest
    ports: ["3002:3000"]
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
```

### **📂 `examples/` - EXEMPLOS DE USO**

### **📂 `RUNBOOKS.md` - OPERAÇÃO EM PRODUÇÃO**

#### **Cenários críticos documentados:**
- **Sessão expirada**: QR não aparece, mensagens não enviam
- **Autenticação 2FA**: QR escaneado mas não autentica
- **Ban/limites WhatsApp**: Mensagens não entregues
- **Sem QR Code**: Evento não disparado, Puppeteer com erro
- **Mídia falhou**: Upload falha, arquivo muito grande
- **WebSocket desconectado**: Eventos não chegam

#### **Procedimentos de manutenção:**
```bash
# Backup de sessões
curl -X POST -H "Authorization: Bearer ${API_KEY}" \
     http://localhost:3000/api/sessions/stop-all

# Atualização do sidecar
docker-compose build pywhatsweb-sidecar
docker-compose up -d pywhatsweb-sidecar

# Limpeza de dados antigos
find ./whatsapp_data -name "*.json" -mtime +30 -delete
```

#### **Monitoramento e alertas:**
```bash
# Health check automático
curl -f http://localhost:3000/health || echo "SIDECAR DOWN"

# Verificar sessões ativas
ACTIVE_SESSIONS=$(curl -s -H "Authorization: Bearer ${API_KEY}" \
    http://localhost:3000/metrics | jq -r '.sessions.active')

if [ "$ACTIVE_SESSIONS" -eq 0 ]; then
    echo "ALERTA: Nenhuma sessão ativa!"
fi
```

#### **`basic_usage.py` - Uso básico**
```python
from pywhatsweb import WhatsWebManager, FileSystemStore

# Criar manager
manager = WhatsWebManager(
    sidecar_host="localhost",
    sidecar_port=3000,
    api_key="sua-api-key"
)

# Criar sessão
session = manager.create_session("sessao_teste")

# Configurar eventos
@session.on("qr")
def on_qr(data):
    print(f"QR Code: {data['qr']}")

@session.on("message")
def on_message(data):
    print(f"Nova mensagem: {data['body']}")

# Iniciar sessão
session.start()

# Enviar mensagem
session.send_text("5511999999999", "Olá!")
```

#### **`django_complete_example.py` - Exemplo Django completo**

##### **View Django com template completo**
```python
# views.py - Views Django para WhatsApp
from django.views.generic import TemplateView
from django.http import JsonResponse
from pywhatsweb import WhatsWebManager, DjangoORMStore

class WhatsAppDashboardView(TemplateView):
    template_name = 'whatsapp/dashboard.html'
    
    def get_context_data(self, **kwargs):
        # Inicializar manager e configurar models Django
        manager = WhatsWebManager(
            sidecar_host=settings.WHATSAPP_SIDECAR_HOST,
            sidecar_port=settings.WHATSAPP_SIDECAR_PORT,
            api_key=settings.WHATSAPP_API_KEY,
            storage=DjangoORMStore()
        )
        
        # Configurar models Django
        manager.storage.set_models(
            session_model=WhatsAppSession,
            message_model=WhatsAppMessage,
            contact_model=WhatsAppContact
        )
        
        # Buscar sessões ativas
        active_sessions = manager.get_active_sessions()
        
        context = super().get_context_data(**kwargs)
        context['active_sessions'] = active_sessions
        context['manager'] = manager
        return context

# API para enviar mensagens
def send_message_api(request):
    if request.method == 'POST':
        session_id = request.POST.get('session_id')
        to = request.POST.get('to')
        text = request.POST.get('text')
        
        manager = WhatsWebManager()
        session = manager.get_session(session_id)
        
        try:
            message_id = session.send_text(to, text)
            return JsonResponse({'success': True, 'message_id': message_id})
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)})
```

##### **Template HTML com QR Code e JavaScript**
```html
<!-- whatsapp/dashboard.html -->
{% extends 'base.html' %}

{% block content %}
<div class="whatsapp-dashboard">
    <h1>Dashboard WhatsApp</h1>
    
    <!-- Lista de sessões -->
    <div class="sessions-list">
        {% for session in active_sessions %}
        <div class="session-card" data-session-id="{{ session.session_id }}">
            <h3>Sessão: {{ session.session_id }}</h3>
            <div class="session-status">
                Status: <span class="status-{{ session.status }}">{{ session.status }}</span>
            </div>
            
            <!-- Container do QR Code -->
            <div class="qr-container" id="qr-{{ session.session_id }}">
                <img id="qr-code-{{ session.session_id }}" src="" alt="QR Code WhatsApp" style="display: none;">
                <div id="qr-status-{{ session.session_id }}">Aguardando QR Code...</div>
            </div>
            
            <!-- Controles da sessão -->
            <div class="session-controls">
                <button onclick="startSession('{{ session.session_id }}')">Iniciar</button>
                <button onclick="stopSession('{{ session.session_id }}')">Parar</button>
                <button onclick="showQR('{{ session.session_id }}')">Mostrar QR</button>
            </div>
            
            <!-- Envio de mensagens -->
            <div class="message-form">
                <input type="text" id="to-{{ session.session_id }}" placeholder="Número (ex: 5511999999999)">
                <input type="text" id="text-{{ session.session_id }}" placeholder="Mensagem">
                <button onclick="sendMessage('{{ session.session_id }}')">Enviar</button>
            </div>
        </div>
        {% endfor %}
    </div>
</div>

<script>
// WebSocket para receber eventos WhatsApp
const ws = new WebSocket('ws://localhost:8000/ws/whatsapp/');

ws.onmessage = function(e) {
    const data = JSON.parse(e.data);
    const sessionId = data.session_id;
    
    if (data.type === 'qr') {
        // Mostrar QR Code
        const qrImg = document.getElementById(`qr-code-${sessionId}`);
        const qrStatus = document.getElementById(`qr-status-${sessionId}`);
        
        qrImg.src = data.qr;
        qrImg.style.display = 'block';
        qrStatus.textContent = 'Escaneie o QR Code';
        
    } else if (data.type === 'ready') {
        // WhatsApp conectado
        const qrImg = document.getElementById(`qr-code-${sessionId}`);
        const qrStatus = document.getElementById(`qr-status-${sessionId}`);
        
        qrImg.style.display = 'none';
        qrStatus.textContent = 'WhatsApp conectado!';
        
    } else if (data.type === 'message') {
        // Nova mensagem recebida
        console.log('Nova mensagem:', data);
        // Aqui você pode atualizar a interface
    }
};

// Funções para controlar sessões
function startSession(sessionId) {
    fetch(`/whatsapp/session/${sessionId}/start/`, {method: 'POST'})
        .then(response => response.json())
        .then(data => console.log('Sessão iniciada:', data));
}

function stopSession(sessionId) {
    fetch(`/whatsapp/session/${sessionId}/stop/`, {method: 'POST'})
        .then(response => response.json())
        .then(data => console.log('Sessão parada:', data));
}

function sendMessage(sessionId) {
    const to = document.getElementById(`to-${sessionId}`).value;
    const text = document.getElementById(`text-${sessionId}`).value;
    
    fetch('/whatsapp/send-message/', {
        method: 'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        body: `session_id=${sessionId}&to=${to}&text=${text}`
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            console.log('Mensagem enviada:', data.message_id);
        } else {
            console.error('Erro ao enviar:', data.error);
        }
    });
}
</script>
{% endblock %}
```

##### **Consumer WebSocket Django Channels**
```python
# consumers.py - Consumer WebSocket para Django Channels
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from pywhatsweb import WhatsWebManager

class WhatsAppWebSocketConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        await self.accept()
        print("Cliente WebSocket conectado")
        
        # Conectar ao WebSocket da sessão WhatsApp
        self.whatsapp_manager = WhatsWebManager()
        
    async def disconnect(self, close_code):
        print(f"Cliente WebSocket desconectado: {close_code}")
        
    async def receive(self, text_data):
        # Processar mensagens do cliente
        data = json.loads(text_data)
        
        if data['action'] == 'send_message':
            session_id = data['session_id']
            to = data['to']
            text = data['text']
            
            try:
                session = self.whatsapp_manager.get_session(session_id)
                message_id = await session.send_text(to, text)
                
                # Confirmar envio para o cliente
                await self.send(text_data=json.dumps({
                    'type': 'message_sent',
                    'message_id': message_id,
                    'to': to
                }))
                
            except Exception as e:
                await self.send(text_data=json.dumps({
                    'type': 'error',
                    'error': str(e)
                }))
                
    async def whatsapp_event(self, event):
        # Enviar eventos WhatsApp para o cliente
        await self.send(text_data=json.dumps({
            'type': event['event_type'],
            'session_id': event['session_id'],
            'data': event['data']
        }))
```

**Funcionalidades do exemplo Django:**
- ✅ Dashboard completo com sessões
- ✅ QR Code em tempo real com template HTML
- ✅ Sistema Kanban (NEW → ACTIVE → DONE)
- ✅ Envio de mensagens via API
- ✅ WebSocket para eventos em tempo real
- ✅ Template HTML responsivo com JavaScript
- ✅ Consumer WebSocket funcional
- ✅ Integração completa com models Django

### **📂 `tests/` - TESTES AUTOMATIZADOS**

#### **`test_imports.py` - Teste de imports**
```python
def test_imports():
    # Testa se todas as classes podem ser importadas
    from pywhatsweb import WhatsWebManager, Session
    from pywhatsweb import FileSystemStore, DjangoORMStore

def test_instanciacao():
    # Testa se as classes podem ser instanciadas
    manager = WhatsWebManager()
    storage = FileSystemStore("./test_data")
```

---

## 🚀 **COMO USAR A BIBLIOTECA**

### **1. INSTALAÇÃO**

```bash
# Clonar repositório
git clone <repo>
cd pywhatsweb-lib

# Instalar dependências Python
pip install -r requirements.txt

# Instalar dependências Node.js
cd sidecar
npm install
```

### **2. CONFIGURAÇÃO**

#### **Configurar sidecar**
```bash
cd sidecar
cp env.example .env
# Editar .env com suas configurações
npm start
```

#### **Configurar Python**
```python
from pywhatsweb import WhatsWebManager, FileSystemStore

manager = WhatsWebManager(
    sidecar_host="localhost",      # Host do sidecar
    sidecar_port=3000,            # Porta HTTP
    sidecar_ws_port=3001,         # Porta WebSocket
    api_key="sua-api-key",        # Chave de API
    storage=FileSystemStore("./whatsapp_data")  # Storage
)
```

### **3. USO BÁSICO**

```python
# Criar sessão
session = manager.create_session("sessao_123")

# Configurar eventos
@session.on("qr")
def on_qr(data):
    # Renderizar QR no template Django/Flask
    qr_data_url = data['qr']
    # <img src="{{ qr_data_url }}">

@session.on("ready")
def on_ready(data):
    print("WhatsApp está pronto!")

@session.on("message")
def on_message(data):
    # Processar mensagem recebida
    sender = data['from']
    content = data['body']
    
    # Auto-resposta
    if "oi" in content.lower():
        session.send_text(sender, "Oi! Como posso ajudar?")

# Iniciar sessão
session.start()
```

### **4. MÚLTIPLAS SESSÕES COM MULTI-TENANT**

```python
# Criar múltiplas sessões com tenant
sessao1 = manager.create_session("sessao_1", tenant_id="empresa_a")
sessao2 = manager.create_session("sessao_2", tenant_id="empresa_b")

# Cada sessão é independente e isolada por tenant
sessao1.start()
sessao2.start()

# Listar sessões ativas por tenant
active_sessions = manager.get_active_sessions(tenant_id="empresa_a")
print(f"Sessões ativas empresa A: {active_sessions}")
```

### **5. VALIDAÇÃO E NORMALIZAÇÃO**

```python
# Criar múltiplas sessões
sessao1 = manager.create_session("sessao_1", phone_number="5511999999999")
sessao2 = manager.create_session("sessao_2", phone_number="5511888888888")

# Cada sessão é independente
sessao1.start()
sessao2.start()

# Listar sessões ativas
active_sessions = manager.get_active_sessions()
print(f"Sessões ativas: {active_sessions}")
```

### **6. ENVIO DE MENSAGENS COM VALIDAÇÃO**

```python
# Texto
message_id = session.send_text("5511999999999", "Olá! Como vai?")

# Mídia
message_id = session.send_media(
    to="5511999999999",
    media_path="./imagem.jpg",
    caption="Veja esta imagem!"
)

# Verificar status
if session.is_active():
    print("Sessão está ativa e pronta")
```

### **7. 🗃️ STORAGE E PERSISTÊNCIA AVANÇADA**

#### **Storage pluggable com múltiplas opções**
```python
# FileSystem (padrão) - armazena em JSON
from pywhatsweb import FileSystemStore
storage = FileSystemStore("./whatsapp_data")

# Django ORM (opcional) - integração com banco de dados
from pywhatsweb import DjangoORMStore
storage = DjangoORMStore()

# Redis (futuro) - para alta performance
# from pywhatsweb import RedisStore
# storage = RedisStore(redis_url="redis://localhost:6379")

# PostgreSQL (futuro) - para dados estruturados
# from pywhatsweb import PostgreSQLStore
# storage = PostgreSQLStore(connection_string="postgresql://...")
```

#### **Configuração Django ORM com models + migrations**
```python
# models.py - Models Django para WhatsApp
from django.db import models
from pywhatsweb import KanbanStatus, MessageType

class WhatsAppSession(models.Model):
    session_id = models.CharField(max_length=100, unique=True)
    tenant_id = models.CharField(max_length=50, null=True)
    status = models.CharField(max_length=20, choices=KanbanStatus.choices())
    phone_number = models.CharField(max_length=20, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

class WhatsAppMessage(models.Model):
    message_id = models.CharField(max_length=100, unique=True)
    session = models.ForeignKey(WhatsAppSession, on_delete=models.CASCADE)
    content = models.TextField()
    sender = models.CharField(max_length=20)
    recipient = models.CharField(max_length=20)
    message_type = models.CharField(max_length=20, choices=MessageType.choices())
    status = models.CharField(max_length=20)
    trace_id = models.CharField(max_length=100)
    created_at = models.DateTimeField(auto_now_add=True)

# Configurar storage
storage.set_models(
    session_model=WhatsAppSession,
    message_model=WhatsAppMessage,
    contact_model=WhatsAppContact,
    chat_model=WhatsAppChat
)
```

### **📁 PIPELINE DE MÍDIA ROBUSTO**

#### **Validação e processamento de mídia**
```python
# Configurações de mídia
MEDIA_CONFIG = {
    'max_size': 16 * 1024 * 1024,  # 16MB (limite WhatsApp)
    'allowed_types': ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
    'timeout': 300,  # 5 minutos para upload
    'retry_count': 3,
    'storage_backend': 'local'  # 'local', 's3', 'minio'
}

# Envio com validação automática
try:
    message_id = session.send_media(
        to="5511999999999",
        media_path="./imagem.jpg",
        caption="Veja esta imagem!",
        validate_media=True,  # Validação automática
        compress_if_needed=True  # Compressão se necessário
    )
except MediaTooLargeError:
    print("Arquivo muito grande, comprimindo...")
    compressed_path = compress_image("./imagem.jpg")
    message_id = session.send_media(to="5511999999999", media_path=compressed_path)
```

#### **Storage de mídia configurável**
```python
# Configurar storage de mídia
manager = WhatsWebManager(
    media_storage={
        'backend': 's3',  # 'local', 's3', 'minio'
        'bucket': 'whatsapp-media',
        'region': 'us-east-1',
        'retention_days': 30,  # Retenção automática
        'encryption': True,  # Criptografia em repouso
        'cdn_enabled': True  # CDN para entrega rápida
    }
)

# Upload para S3/MinIO
media_url = session.upload_media_to_storage(
    file_path="./imagem.jpg",
    mime_type="image/jpeg",
    metadata={'session_id': 'sessao_123'}
)
```

### **🔒 POLÍTICA LGPD E RETENÇÃO**

#### **Configurações de retenção e privacidade**
```python
# Configurar política LGPD
manager = WhatsWebManager(
    lgpd_compliance={
        'data_retention_days': 90,  # Retenção de mensagens
        'media_retention_days': 30,  # Retenção de mídia
        'log_redaction': True,  # Redação de dados sensíveis
        'media_encryption': True,  # Criptografia de anexos
        'audit_trail': True,  # Rastreamento de ações
        'right_to_forget': True,  # Direito ao esquecimento
        'data_export': True  # Exportação de dados
    }
)

# Excluir dados de um usuário
storage.delete_user_data(
    phone_number="5511999999999",
    reason="direito_ao_esquecimento",
    audit_user="admin"
)

# Exportar dados para LGPD
user_data = storage.export_user_data("5511999999999")
# Retorna JSON com todas as mensagens, contatos, etc.
```

#### **Compliance e auditoria**
```python
# Logs sem conteúdo de mensagem (apenas metadados)
# [2024-12-19 10:30:00] [corr:req_456] [tenant:empresa_a] Mensagem enviada: ID=msg_123, Para=5511999999999, Tipo=texto

# Criptografia AES-256 em repouso para mídia
# Chaves gerenciadas por KMS ou variáveis de ambiente

# Rastreamento completo de acesso e modificações
audit_log = storage.get_audit_log(
    user_id="5511999999999",
    start_date="2024-12-01",
    end_date="2024-12-19"
)
```

---

## 🔧 **FUNCIONALIDADES AVANÇADAS**

### **🧱 SISTEMA KANBAN COM FLUXO INTELIGENTE**

#### **Estados do fluxo Kanban**
```python
from pywhatsweb import KanbanStatus

# Criar chat com status
chat = Chat(
    chat_id="5511999999999",
    status=KanbanStatus.NEW
)

# Atribuir para atendente
chat.assign_to("atendente_123", "sistema")
# Status muda para ACTIVE

# Marcar como concluído
chat.mark_as_done("atendente_123")
# Status muda para DONE

# Reabrir conversa
chat.reopen("sistema")
# Status volta para NEW
```

#### **Políticas automáticas recomendadas**
```python
# Auto-NEW em mensagem nova
@session.on("message")
def on_message(data):
    if data['origin'] == 'inbound':
        chat = storage.get_or_create_chat(data['from'])
        if chat.status == KanbanStatus.DONE:
            # Cliente respondeu após conclusão, reabrir
            chat.reopen("sistema", reason="cliente_respondeu")
            storage.save_chat(chat)

# Auto-DONE após N horas de inatividade
def auto_close_inactive_chats():
    from datetime import timedelta
    
    active_chats = storage.get_chats_by_status(KanbanStatus.ACTIVE)
    cutoff_time = datetime.now() - timedelta(hours=24)
    
    for chat in active_chats:
        if chat.last_message_at < cutoff_time:
            chat.mark_as_done("sistema", reason="inatividade_24h")
            storage.save_chat(chat)
```

### **📱 NORMALIZAÇÃO E VALIDAÇÃO DE NÚMEROS**

#### **Utilitário E.164 com phonenumbers**
```python
from pywhatsweb.utils import normalize_phone_number, validate_phone_number

# Normalização automática para formato E.164
phone = normalize_phone_number("11999999999")  # +5511999999999
phone = normalize_phone_number("(11) 99999-9999")  # +5511999999999
phone = normalize_phone_number("+55 11 99999 9999")  # +5511999999999

# Validação completa
is_valid, normalized, country_code, region = validate_phone_number("11999999999")
# (True, "+5511999999999", 55, "BR")

# Informações detalhadas do número
info = get_phone_info("+5511999999999")
# {
#   'number': '+5511999999999',
#   'country_code': 55,
#   'region': 'BR',
#   'carrier': 'Vivo',
#   'timezone': 'America/Sao_Paulo',
#   'is_valid': True,
#   'is_mobile': True
# }
```

#### **Formatação para exibição**
```python
# Formatação para diferentes regiões
display_national = format_phone_for_display("+5511999999999", "NATIONAL")   # (11) 99999-9999
display_international = format_phone_for_display("+5511999999999", "INTERNATIONAL")  # +55 11 99999-9999
display_e164 = format_phone_for_display("+5511999999999", "E164")  # +5511999999999
```

### **Context Manager e Tratamento de Erros**

#### **Context Manager**
```python
# Usar como context manager
with WhatsWebManager() as manager:
    session = manager.create_session("test")
    session.start()
    # ... usar sessão
    # Cleanup automático ao sair
```

### **Logging e Debug**
```python
import logging

# Configurar logging
logging.basicConfig(level=logging.DEBUG)

# Logs automáticos em todas as operações
manager = WhatsWebManager()
# Logs: "PyWhatsWeb Manager inicializado", "Sessão criada", etc.
```

### **🔄 RESILIÊNCIA E RECONEXÃO**

#### **Reconexão automática com backoff exponencial**
```python
# A sessão reconecta automaticamente com backoff exponencial
# Tentativa 1: 2s, Tentativa 2: 4s, Tentativa 3: 8s, etc.
# Máximo 5 tentativas

@session.on("disconnected")
def on_disconnected(data):
    print(f"Desconectado: {data['reason']}")
    # Reconexão automática em andamento

@session.on("ready")
def on_ready(data):
    print("Reconectado e pronto!")
```

#### **Heartbeat WebSocket para manter conexões ativas**
```python
# Ping/pong automático a cada 30 segundos
# Se falhar 3 vezes consecutivas, reconecta automaticamente

@session.on("heartbeat")
def on_heartbeat(data):
    print(f"Heartbeat: {data['latency']}ms")

@session.on("heartbeat_failed")
def on_heartbeat_failed(data):
    print("Heartbeat falhou, reconectando...")
```

### **📨 IDEMPOTÊNCIA E DEDUPLICAÇÃO**

#### **Sistema de idempotência com chaves únicas**
```python
# Gerar chave de idempotência única
message_id = session.send_text_with_idempotency(
    to="5511999999999",
    text="Mensagem importante",
    idempotency_key="msg_123_v1"  # Chave única
)

# Verificar se mensagem já foi enviada
if session.is_message_sent("msg_123_v1"):
    print("Mensagem já enviada, ignorando...")
```

#### **Marcar origem da mensagem para evitar loops**
```python
# Sistema anti-loop automático
@session.on("message")
def on_message(data):
    # data['origin'] = 'inbound' (recebida) ou 'outbound' (enviada)
    # data['fromSelf'] = True se enviada pelo próprio usuário
    
    if data['origin'] == 'inbound' and not data['fromSelf']:
        # Processar mensagem recebida
        process_incoming_message(data)
    else:
        # Ignorar mensagens próprias ou de saída
        print("Mensagem ignorada (loop prevention)")
```

### **📊 ESTADOS DE ENTREGA E MONITORAMENTO**

#### **Estados de envio/entrega quando suportado**
```python
# WhatsApp suporta alguns estados de entrega
@session.on("message_status")
def on_message_status(data):
    if data['status'] == 'sent':
        print("Mensagem enviada para servidor")
    elif data['status'] == 'delivered':
        print("Mensagem entregue ao destinatário")
    elif data['status'] == 'read':
        print("Mensagem lida pelo destinatário")
    elif data['status'] == 'failed':
        print(f"Mensagem falhou: {data['error']}")
```

#### **Limites e timeouts de entrega**
```python
# Configurações de entrega
MESSAGE_TIMEOUT = 60        # Timeout de envio (segundos)
DELIVERY_TIMEOUT = 300      # Timeout de entrega (segundos)
MAX_RETRIES = 3             # Máximo de tentativas
RETRY_DELAY = 5             # Delay entre tentativas (segundos)
```

@session.on("disconnected")
def on_disconnected(data):
    print(f"Desconectado: {data['reason']}")
    # Reconexão automática em andamento

@session.on("ready")
def on_ready(data):
    print("Reconectado e pronto!")
```

---

## 📊 **STATUS E MONITORAMENTO**

### **Informações da Sessão**
```python
# Status básico
status = session.get_status()
print(f"Status: {status.value}")

# Informações detalhadas
info = session.get_status_info()
print(f"Conectado desde: {info['created_at']}")
print(f"Última atividade: {info['last_activity']}")
print(f"Autenticado: {info['is_authenticated']}")
print(f"WebSocket conectado: {info['ws_connected']}")
print(f"Tentativas de reconexão: {info['reconnection_attempts']}")
```

### **Informações do Manager**
```python
# Listar todas as sessões
sessions = manager.list_sessions()
print(f"Sessões: {sessions}")

# Contar sessões
count = manager.get_session_count()
print(f"Total: {count}")

# Informações do sidecar
sidecar_info = manager.get_sidecar_info()
print(f"Sidecar: {sidecar_info['base_url']}")
```

### **📊 OBSERVABILIDADE E MONITORAMENTO**

#### **Health Check e Métricas**
```bash
# Health check básico
curl http://localhost:3000/health

# Métricas Prometheus (formato padrão)
curl -H "Authorization: Bearer sua-api-key" http://localhost:3000/metrics

# Métricas JSON (para dashboards customizados)
curl -H "Authorization: Bearer sua-api-key" http://localhost:3000/metrics.json
```

#### **Métricas Prometheus com histogramas e percentis**
```python
# Métricas-chave disponíveis
METRICS = {
    # Contadores
    'messages_in_total': 'Total de mensagens recebidas',
    'messages_out_total': 'Total de mensagens enviadas',
    'reconnections_total': 'Total de reconexões',
    'errors_total': 'Total de erros por código',
    
    # Gauges
    'sessions_active': 'Sessões ativas no momento',
    'sessions_total': 'Total de sessões criadas',
    'websocket_connections': 'Conexões WebSocket ativas',
    
    # Histogramas
    'message_latency_seconds': 'Latência de envio (p50, p95, p99)',
    'reconnection_delay_seconds': 'Delay de reconexão',
    'media_upload_duration_seconds': 'Duração de upload de mídia'
}

# Exemplo de métricas Prometheus
# whatsapp_messages_in_total{tenant="empresa_a",session="sessao_123"} 150
# whatsapp_message_latency_seconds_bucket{le="0.1"} 45
# whatsapp_message_latency_seconds_bucket{le="0.5"} 120
# whatsapp_message_latency_seconds_bucket{le="1.0"} 150
```

#### **Health checks por sessão e componente**
```python
# Health check completo do sistema
health_status = manager.get_health_status()
# {
#   'status': 'healthy',
#   'timestamp': '2024-12-19T10:30:00.000Z',
#   'uptime': 3600000,
#   'components': {
#     'sidecar': 'healthy',
#     'websocket': 'healthy',
#     'storage': 'healthy',
#     'sessions': 'healthy'
#   },
#   'sessions': {
#     'active': 2,
#     'total': 5,
#     'healthy': 2,
#     'unhealthy': 0
#   },
#   'metrics': {
#     'messagesIn': 150,
#     'messagesOut': 120,
#     'reconnections': 3,
#     'errors': 1
#   }
# }

# Health check de sessão específica
session_health = session.get_health_status()
# {
#   'status': 'healthy',
#   'websocket_connected': True,
#   'last_heartbeat': '2024-12-19T10:29:45.000Z',
#   'reconnection_attempts': 0,
#   'message_queue_size': 0
# }
```

#### **Alertas e monitoramento proativo**
```python
# Configurar alertas automáticos
manager.setup_alerts({
    'max_reconnection_attempts': 5,
    'max_message_latency_ms': 5000,
    'min_active_sessions': 1,
    'max_error_rate': 0.05  # 5% de erro
})

# Handler para alertas
@manager.on("alert")
def on_alert(alert_data):
    if alert_data['type'] == 'high_latency':
        print(f"ALERTA: Latência alta: {alert_data['latency']}ms")
        # Notificar equipe, escalar, etc.
    elif alert_data['type'] == 'session_down':
        print(f"ALERTA: Sessão {alert_data['session_id']} caiu")
        # Tentar reconexão automática
```

**Resposta do health check:**
```json
{
  "status": "healthy",
  "timestamp": "2024-12-19T10:30:00.000Z",
  "uptime": 3600000,
  "sessions": {
    "active": 2,
    "total": 5
  },
  "metrics": {
    "messagesIn": 150,
    "messagesOut": 120,
    "reconnections": 3,
    "errors": 1
  },
  "version": "0.3.2"
}
```

---

## 🚨 **TRATAMENTO DE ERROS**

### **Exceções comuns**
```python
try:
    session.start()
except SessionError as e:
    print(f"Erro de sessão: {e}")
except ConnectionError as e:
    print(f"Erro de conexão: {e}")
except AuthenticationError as e:
    print(f"Erro de autenticação: {e}")
except WebSocketError as e:
    print(f"Erro de WebSocket: {e}")
```

### **Verificação de status**
```python
if not session.is_connected():
    print("Sessão não está conectada")
    return

if not session.is_active():
    print("Sessão não está ativa")
    return

# Verificar reconexão
if session._reconnection_attempts > 0:
    print(f"Tentativas de reconexão: {session._reconnection_attempts}")
```

---

## 🔒 **SEGURANÇA E CONTROLE DE ACESSO**

### **🔐 AUTENTICAÇÃO E AUTORIZAÇÃO**

#### **API Key obrigatória**
```python
# Sempre use uma API key forte
manager = WhatsWebManager(
    api_key="sua-api-key-super-secreta-aqui"
)
```

#### **Token/JWT no WebSocket (obrigatório)**
```javascript
// Autenticação no handshake de conexão
const wss = new WebSocket.Server({ 
    port: WS_PORT,
    verifyClient: (info) => {
        const token = info.req.headers['authorization'] || 
                     new URL(info.req.url, 'http://localhost').searchParams.get('token');
        
        if (!token || token !== `Bearer ${API_KEY}`) {
            return false; // Conexão rejeitada imediatamente
        }
        
        // Validar tenant_id se fornecido
        const tenantId = info.req.headers['x-tenant-id'];
        if (tenantId && !isValidTenant(tenantId)) {
            return false;
        }
        
        return true;
    }
});
```

#### **Multi-tenant com isolamento**
```python
# Criar sessão com tenant específico
session = manager.create_session(
    "sessao_123", 
    tenant_id="empresa_a",
    correlation_id="req_456"
)

# Headers de correlação automáticos
# X-Correlation-Id: req_456
# X-Tenant-Id: empresa_a
# X-Session-Id: sessao_123
```

### **🛡️ CONTROLE DE ACESSO E AUDITORIA**

#### **Headers de correlação padronizados**
- **X-Correlation-Id**: ID único para rastrear operação
- **X-Tenant-Id**: Identificador do tenant (multi-tenancy)
- **X-Session-Id**: ID da sessão WhatsApp
- **X-Request-Id**: ID único da requisição HTTP

#### **Logs com rastreamento completo**
```python
# Logs automáticos com correlation ID
# [2024-12-19 10:30:00] [corr:req_456] [tenant:empresa_a] Sessão criada: sessao_123
# [2024-12-19 10:30:05] [corr:req_456] [tenant:empresa_a] QR Code gerado
# [2024-12-19 10:30:30] [corr:req_456] [tenant:empresa_a] WhatsApp autenticado
```

### **API Key**
```python
# Sempre use uma API key forte
manager = WhatsWebManager(
    api_key="sua-api-key-super-secreta-aqui"
)
```

### **Configuração de rede**
```python
# Restringir acesso por IP se necessário
manager = WhatsWebManager(
    sidecar_host="127.0.0.1",  # Apenas localhost
    sidecar_port=3000
)
```

### **Rate Limiting**
```javascript
// Configuração no sidecar
const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutos
    max: 100, // máximo 100 requisições por IP
    message: 'Muitas requisições deste IP, tente novamente mais tarde.'
});
```

---

## 📈 **CASOS DE USO**

### **1. Chatbot Automático**
```python
@session.on("message")
def auto_response(data):
    content = data['body'].lower()
    sender = data['from']
    
    if "preço" in content:
        session.send_text(sender, "Nossos preços: Produto A - R$ 50, Produto B - R$ 100")
    elif "contato" in content:
        session.send_text(sender, "Entre em contato: (11) 99999-9999")
    else:
        session.send_text(sender, "Como posso ajudar? Digite 'preço' ou 'contato'")
```

### **2. Sistema de Atendimento**
```python
# Atribuir chat para atendente
def assign_chat_to_attendant(chat_id, attendant_id):
    chat = storage.get_chat(chat_id)
    chat.assign_to(attendant_id, "sistema")
    storage.save_chat(chat)
    
    # Notificar atendente
    session.send_text(attendant_id, f"Novo chat atribuído: {chat_id}")
```

### **3. Monitoramento de Conversas**
```python
# Verificar conversas ativas
def monitor_active_chats():
    active_chats = storage.get_chats_by_status(KanbanStatus.ACTIVE)
    
    for chat in active_chats:
        # Verificar tempo de atendimento
        if chat.is_taking_too_long():
            # Escalar para supervisor
            escalate_chat(chat)
```

### **4. Sistema de Auditoria**
```python
# Rastrear todas as ações
def audit_action(action, user_id, details):
    event = SessionEvent(
        session_id=session.session_id,
        event_type=action,
        data=details,
        user_id=user_id,
        ip_address=request.META.get('REMOTE_ADDR'),
        user_agent=request.META.get('HTTP_USER_AGENT')
    )
    storage.save_event(event)
```

---

## 🧪 **TESTES E DESENVOLVIMENTO**

### **Executar testes**
```bash
# Teste de imports
python test_imports.py

# Teste com pytest
pytest tests/

# Teste com tox
tox
```

### **Desenvolvimento local**
```bash
# Instalar em modo desenvolvimento
pip install -e .

# Executar exemplos
python examples/basic_usage.py
python examples/django_complete_example.py
```

### **🖥️ CLI OPERACIONAL (pww)**

#### **Instalação e uso do CLI**
```bash
# Instalar CLI globalmente
pip install pywhatsweb[cli]

# Ou usar via Python
python -m pywhatsweb.cli session start --id teste

# Verificar versão
pww --version
```

#### **Comandos para suporte e diagnóstico**
```bash
# Gerenciar sessões
pww session start --id sessao_123 --tenant empresa_a
pww session status --id sessao_123
pww session stop --id sessao_123
pww session list --active
pww session list --all

# Mostrar QR Code
pww session qr --id sessao_123

# Enviar mensagem de teste
pww session send --id sessao_123 --to 5511999999999 --text "Teste CLI"

# Diagnóstico completo
pww diag --session sessao_123
pww diag --sidecar
pww diag --storage

# Ver logs em tempo real
pww logs --follow --session sessao_123
pww logs --level debug --tenant empresa_a

# Health check completo
pww health --sidecar --sessions --storage
pww health --format json
pww health --format prometheus
```

#### **Exemplos de uso do CLI**
```bash
# Iniciar múltiplas sessões
pww session start --id atendente_1 --tenant empresa_a
pww session start --id atendente_2 --tenant empresa_a
pww session start --id suporte --tenant empresa_b

# Monitorar sessões ativas
pww session list --active --format table
# +-------------+-----------+--------+---------------------+
# | Session ID  | Tenant    | Status | Last Activity      |
# +-------------+-----------+--------+---------------------+
# | atendente_1 | empresa_a | ready  | 2024-12-19 10:30:00 |
# | atendente_2 | empresa_a | ready  | 2024-12-19 10:29:45 |
# | suporte     | empresa_b | qr     | 2024-12-19 10:25:00 |
# +-------------+-----------+--------+---------------------+

# Diagnóstico de problemas
pww diag --session atendente_1 --verbose
# Sessão: atendente_1
# Status: ready
# WebSocket: connected
# Heartbeat: 45ms
# Última mensagem: 2 minutos atrás
# Reconexões: 0
# Erros: 0
```

### **Testar sidecar**
```bash
cd sidecar

# Instalar dependências
npm install

# Executar em modo desenvolvimento
npm run dev

# Testar endpoints
curl http://localhost:3000/health
curl -H "Authorization: Bearer sua-api-key" http://localhost:3000/metrics
```

---

## 📚 **RECURSOS ADICIONAIS**

### **Documentação**
- **README.md**: Visão geral para usuários
- **README-for-devs.md**: Este arquivo (guia técnico)
- **examples/**: Exemplos práticos
- **sidecar/README.md**: Documentação do sidecar

### **Ferramentas**
- **Makefile**: Comandos de automação
- **requirements.txt**: Dependências Python
- **sidecar/package.json**: Dependências Node.js

### **Configurações de ambiente**
```bash
# .env do sidecar
PORT=3000
WS_PORT=3001
API_KEY=sua-api-key-super-secreta
ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
PUPPETEER_ARGS=--no-sandbox --disable-setuid-sandbox
LOG_LEVEL=info
```

---

## 🎯 **PRÓXIMOS PASSOS**

### **v0.5.1 (Atual)**
- [ ] Interface web para supervisão
- [ ] Sistema de métricas e analytics avançado
- [ ] Orquestração multi-instância
- [ ] Integração com sistemas externos (CRM, ERP)
- [ ] Suporte a múltiplos números por sessão
- [ ] Sistema de templates de mensagem
- [ ] Backup e restore de sessões

### **Contribuições**
- [ ] Testes unitários completos
- [ ] Documentação adicional
- [ ] Novos tipos de storage (Redis, PostgreSQL)
- [ ] Melhorias de performance
- [ ] Novos tipos de mensagem (botões, listas)
- [ ] Sistema de webhooks

---

## 🚨 **SUPORTE E TROUBLESHOOTING**

### **🔍 PROBLEMAS COMUNS E SOLUÇÕES**

#### **1. Sidecar não inicia**
```bash
# ❌ Erro: "Node.js version must be 18.0.0 or higher"
# ✅ Solução: Atualizar Node.js
node --version  # Deve ser ≥18.0.0
nvm install 18  # ou baixar do nodejs.org

# ❌ Erro: "Cannot find module 'whatsapp-web.js'"
# ✅ Solução: Reinstalar dependências
cd sidecar && rm -rf node_modules package-lock.json
npm install
```

#### **2. QR Code não aparece**
```python
# ❌ Problema: Evento 'qr' não dispara
# ✅ Solução: Verificar WebSocket
import logging
logging.basicConfig(level=logging.DEBUG)

# Verificar se está conectando
@session.on("connecting")
def on_connecting(data):
    print("Conectando...")

@session.on("qr")
def on_qr(data):
    print(f"QR: {data['qr']}")  # Deve aparecer aqui
```

#### **3. Mensagens não enviam**
```python
# ❌ Problema: "Session not ready"
# ✅ Solução: Aguardar evento 'ready'
@session.on("ready")
def on_ready(data):
    print("WhatsApp pronto! Agora pode enviar")
    session.send_text("5511999999999", "Teste")

# ❌ Problema: "Rate limit exceeded"
# ✅ Solução: Aguardar e tentar novamente
import time
time.sleep(60)  # Aguardar 1 minuto
```

#### **4. WebSocket desconectado**
```python
# ❌ Problema: Eventos param de chegar
# ✅ Solução: Reconexão automática
@session.on("disconnected")
def on_disconnected(data):
    print(f"Desconectado: {data['reason']}")
    # Reconexão automática em andamento

@session.on("ready")
def on_ready(data):
    print("Reconectado!")
```

### **📊 DIAGNÓSTICO RÁPIDO**
```bash
# 1. Verificar sidecar
curl http://localhost:3000/health

# 2. Verificar sessões ativas
curl -H "Authorization: Bearer ${API_KEY}" \
     http://localhost:3000/metrics

# 3. Ver logs do sidecar
cd sidecar && npm run dev

# 4. Ver logs Python
python -c "import logging; logging.basicConfig(level=logging.DEBUG)"
```

### **🚨 CENÁRIOS CRÍTICOS**

#### **Sessão expirada (QR não aparece)**
```bash
# 1. Parar todas as sessões
curl -X POST -H "Authorization: Bearer ${API_KEY}" \
     http://localhost:3000/api/sessions/stop-all

# 2. Reiniciar sidecar
cd sidecar && npm restart

# 3. Recriar sessão
session = manager.create_session("nova_sessao")
session.start()
```

#### **WhatsApp banido/limitado**
```python
# ❌ Erro: "Account banned" ou "Too many requests"
# ✅ Solução: Aguardar e usar número diferente
import time

# Aguardar 24h para ban
time.sleep(24 * 60 * 60)

# Ou usar número alternativo
session2 = manager.create_session("sessao_2", phone_number="5511888888888")
```

### **Logs e debug**
```python
import logging
logging.basicConfig(level=logging.DEBUG)

# Logs detalhados de todas as operações
manager = WhatsWebManager()
```

### **Verificar health do sidecar**
```bash
# Health check
curl http://localhost:3000/health

# Ver logs do sidecar
cd sidecar
npm run dev
```

---

## 🎉 **CONCLUSÃO**

A **PyWhatsWeb v0.5.1** é uma biblioteca **completa e funcional** que oferece:

✅ **Arquitetura moderna** com sidecar Node.js  
✅ **Multi-sessão** para múltiplos atendentes  
✅ **Eventos em tempo real** via WebSocket  
✅ **Storage pluggable** (FileSystem ou Django)  
✅ **Sistema Kanban** para gestão de conversas  
✅ **API Python limpa** e fácil de usar  
✅ **Sem dependências** de navegador/Selenium  
✅ **Funciona em qualquer projeto Python**  
✅ **Reconexão automática** com backoff exponencial  
✅ **Sistema de idempotência** para deduplicação  
✅ **Health check e métricas** completas  
✅ **Segurança robusta** com rate limiting e CORS  
✅ **Exemplo Django completo** com dashboard funcional  

**Para começar agora:**
1. Inicie o sidecar: `cd sidecar && npm install && npm start`
2. Use a biblioteca Python em seu projeto
3. Configure eventos e handlers
4. Gerencie múltiplas sessões
5. Implemente o sistema Kanban
6. Monitore com health check e métricas

**A biblioteca está pronta para uso em produção com todas as funcionalidades essenciais implementadas!** 🚀

---

## 🔑 **FUNÇÕES PRINCIPAIS - RESUMO RÁPIDO**

### **🚀 CORE FUNCTIONS**
```python
# 1. MANAGER - Gerenciador principal
manager = WhatsWebManager(api_key="sua-chave")
manager.create_session("id")      # Criar sessão
manager.list_sessions()           # Listar todas
manager.get_active_sessions()     # Sessões ativas

# 2. SESSION - Sessão individual
session = manager.get_session("id")
session.start()                   # Iniciar conexão
session.stop()                    # Parar sessão
session.send_text(to, text)      # Enviar texto
session.send_media(to, path)     # Enviar arquivo

# 3. EVENTS - Sistema de eventos
@session.on("qr", handler)       # QR Code
@session.on("message", handler)  # Mensagem recebida
@session.on("ready", handler)    # WhatsApp pronto
@session.on("disconnected", handler)  # Desconectado
```

### **💾 STORAGE - Persistência de dados**
```python
# FileSystem (padrão)
storage = FileSystemStore("./data")

# Django ORM (opcional)
storage = DjangoORMStore()
storage.set_models(WhatsAppSession, WhatsAppMessage)

# Operações básicas
storage.save_message(message)
storage.get_chat_messages(chat_id)
storage.save_contact(contact)
```

### **🔧 UTILITIES - Ferramentas auxiliares**
```python
from pywhatsweb.utils import *

# Números de telefone
normalize_phone_number("11999999999")  # +5511999999999
validate_phone_number("11999999999")   # (True, "+5511999999999")

# IDs e timestamps
generate_session_id("session", "tenant")  # session_tenant_1703000000_abc123
format_timestamp(datetime.now(), "America/Sao_Paulo")
```

### **🚨 ERROR HANDLING - Tratamento de erros**
```python
from pywhatsweb.errors import *

# Códigos de erro padronizados
ErrorCode.E_SESSION_NOT_FOUND      # 404
ErrorCode.E_AUTHENTICATION_FAILED  # 401
ErrorCode.E_MEDIA_TOO_LARGE       # 400

# Criar resposta de erro
error_response = create_error_response(ErrorCode.E_SESSION_NOT_FOUND)
```

---

## 📋 **CHANGELOG v0.5.1**

### **🔧 CORRIGIDO**
- **Bug de compatibilidade Python 3.13**: Corrigido erro `TypeError: non-default argument follows default argument` em dataclasses
- **Ordem de campos**: Reordenados campos obrigatórios antes de campos opcionais em `MediaMessage` e `Chat`
- **Compatibilidade**: Todas as classes dataclass agora funcionam perfeitamente com Python 3.13+

### **✨ ADICIONADO**
- **Suporte explícito Python 3.13**: Verificação automática e mensagens informativas
- **Verificação de compatibilidade**: Detecta versão Python e dependências no import
- **Configurações centralizadas**: Todas as configurações padrão em `__default_config__`
- **Informações de versão**: Atributos `__python_support__`, `__dependencies__`, etc.

### **📚 DOCUMENTAÇÃO**
- **Matriz de compatibilidade atualizada**: Inclui Python 3.13 explicitamente
- **README atualizado**: Versão e funcionalidades da v0.5.1
- **CHANGELOG completo**: Todas as mudanças documentadas

### **🚀 MELHORIAS**
- **Import otimizado**: Verificação de compatibilidade automática
- **Mensagens informativas**: Feedback sobre versões suportadas
- **Estrutura de dados**: Dataclasses mais robustas e compatíveis

---

## 📋 **CHANGELOG v0.4.1**

### **✨ Novas Funcionalidades [LIB + README]**
- **Autenticação WebSocket obrigatória** com token + multi-tenant [LIB]
- **Endpoint /metrics Prometheus** para monitoramento avançado [LIB]
- **Sistema de idempotência reforçado** com outbox pattern [LIB]
- **Dockerfile e docker-compose** otimizados para produção [LIB]
- **Runbooks ampliados** para cenários críticos (2FA, ban, limites) [README]
- **CLI operacional** para suporte e diagnóstico [LIB + README]
- **Webhooks e SSE fallback** quando WebSocket não disponível [LIB + README]
- **Sistema de backpressure** com filas Redis/memória [LIB + README]
- **Política LGPD** com retenção configurável e criptografia [LIB + README]

### **🔧 Melhorias [LIB + README]**
- **Normalização E.164** e validação de números de telefone [LIB]
- **Catálogo de erros padronizados** com 50+ códigos HTTP [LIB]
- **Reconexão automática** com backoff exponencial e heartbeat [LIB]
- **Sistema Kanban** com rastreamento completo de conversas [LIB]
- **Exemplos Django** com template HTML e consumer WebSocket [README]
- **Matriz de compatibilidade** com verificação fail-fast [LIB + README]
- **Tabela de limites e timeouts** centralizada [README]
- **Headers de correlação** padronizados (X-Correlation-Id, X-Tenant-Id) [LIB + README]

### **🐛 Correções [LIB + README]**
- **Consolidação de segurança** (Helmet, CORS, Rate Limiting unificados) [LIB]
- **Ajustes de payloads de eventos** e status de sessão [LIB]
- **Endpoints /metrics duplicados** corrigidos (Prometheus + JSON) [LIB]
- **Dockerfile** com usuário correto (node em vez de nodejs) [LIB]
- **Versões inconsistentes** padronizadas para v0.5.1 [README]
- **WebSocket auth** com compatibilidade entre versões do ws [LIB]

### **📚 Documentação [README]**
- README-for-devs.md completo e atualizado
- Exemplos práticos para todos os casos de uso
- Guia de configuração e troubleshooting
- Documentação de segurança e boas práticas
- **Matriz de compatibilidade** com verificação automática
- **CLI operacional** com comandos de diagnóstico
- **Exemplo Django completo** com template HTML funcional

---

## 📋 **CHANGELOG v0.4.4**

### **🔧 CORRIGIDO**
- **Bug de compatibilidade websockets 15.0+**: Corrigido erro `AttributeError: module 'websockets' has no attribute 'version_tuple'`
- **Verificação de versão**: Implementado fallback robusto para diferentes versões de websockets
- **Compatibilidade**: Suporte total a websockets 15.0+ e Python 3.13

### **✨ ADICIONADO**
- **Suporte websockets modernos**: Compatibilidade com versões 15.0+ que não possuem `version_tuple`
- **Fallback automático**: Verificação de versão usando `__version__` quando `version_tuple` não está disponível
- **Verificação robusta**: Tratamento de erros para diferentes atributos de versão

### **🚀 MELHORIAS**
- **Compatibilidade total**: Python 3.13 + websockets 15.0+ funcionando perfeitamente
- **Verificação resiliente**: Sistema de compatibilidade mais robusto
- **Fallback inteligente**: Adaptação automática a diferentes versões de dependências

---

## 📋 **CHANGELOG v0.5.1**

### **🔧 CORRIGIDO**
- **Bug de dataclasses Python 3.13**: Corrigido erro `TypeError: non-default argument follows default argument`
- **Ordem de campos**: Reordenados campos obrigatórios antes de campos opcionais em todas as classes
- **Compatibilidade**: Todas as dataclasses agora funcionam perfeitamente com Python 3.13+
- **Herança**: Corrigida herança da classe `MediaMessage` da classe `Message`

### **✨ ADICIONADO**
- **Estrutura de dados robusta**: Dataclasses com ordem correta de campos
- **Validação pós-inicialização**: Métodos `__post_init__` funcionando corretamente
- **Compatibilidade total**: Python 3.13 + websockets 15.0+ + dataclasses funcionando

### **🚀 MELHORIAS**
- **Estrutura de dados**: Todas as classes agora seguem padrão Python 3.13+
- **Validação**: Sistema de validação mais robusto e compatível
- **Herança**: Sistema de herança funcionando perfeitamente

---

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "pywhatsweb",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "TI L\u00e9o Team <ti.leo@example.com>",
    "keywords": "whatsapp, whatsapp-web, automation, bot, api, corporate, enterprise",
    "author": null,
    "author_email": "TI L\u00e9o Team <ti.leo@example.com>",
    "download_url": "https://files.pythonhosted.org/packages/f3/59/d12716f6cbd10d39776c1b595342aed7ba7552de4facf4a4e4567aa9f62c/pywhatsweb-0.5.3.tar.gz",
    "platform": null,
    "description": "# \ud83d\ude80 PyWhatsWeb v0.5.1 - Guia para Desenvolvedores\r\n\r\n## \ud83d\udcd1 **\u00cdNDICE R\u00c1PIDO**\r\n- [\ud83d\ude80 **COMO FUNCIONA**](#-como-funciona-a-biblioteca) - Arquitetura e fluxo\r\n- [\ud83d\udcc1 **ESTRUTURA**](#-estrutura-de-pastas-e-arquivos) - Pastas e arquivos\r\n- [\u26a1 **QUICK START**](#-quick-start-5-minutos) - Come\u00e7ar em 5 minutos\r\n- [\ud83d\udd27 **COMO USAR**](#-como-usar-a-biblioteca) - Guia completo\r\n- [\ud83d\udcca **FUNCIONALIDADES**](#-funcionalidades-avan\u00e7adas) - Recursos avan\u00e7ados\r\n- [\ud83d\udea8 **TROUBLESHOOTING**](#-suporte-e-ajuda) - Problemas comuns\r\n\r\n## \ud83d\udccb **VIS\u00c3O GERAL**\r\n\r\n**PyWhatsWeb** \u00e9 uma biblioteca Python moderna para integra\u00e7\u00e3o corporativa com WhatsApp Web. Diferente de solu\u00e7\u00f5es baseadas em Selenium, ela utiliza uma arquitetura **sidecar Python integrado** (padr\u00e3o) ou **sidecar Node.js** (opcional) para opera\u00e7\u00e3o headless e eventos em tempo real.\r\n\r\n### \ud83c\udfaf **O QUE A BIBLIOTECA FAZ AGORA (v0.5.1)**\r\n\r\n\u2705 **Multi-sess\u00e3o**: Gerencia m\u00faltiplas sess\u00f5es WhatsApp simultaneamente  \r\n\u2705 **Eventos em tempo real**: WebSocket para QR, mensagens, conex\u00e3o, etc.  \r\n\u2705 **Storage pluggable**: FileSystem ou Django ORM (opcional)  \r\n\u2705 **Sistema Kanban**: Status NEW/ACTIVE/DONE para conversas  \r\n\u2705 **API REST**: Comunica\u00e7\u00e3o HTTP com sidecar  \r\n\u2705 **Sem navegador**: Opera\u00e7\u00e3o completamente headless  \r\n\u2705 **Multi-framework**: Funciona em Django, Flask, FastAPI, scripts Python  \r\n\u2705 **Reconex\u00e3o autom\u00e1tica**: WebSocket com backoff exponencial  \r\n\u2705 **Idempot\u00eancia**: Sistema de deduplica\u00e7\u00e3o e rastreamento  \r\n\u2705 **Health & M\u00e9tricas**: Monitoramento completo do sistema  \r\n\u2705 **Seguran\u00e7a**: API key, CORS, rate limiting, logs seguros  \r\n\u2705 **Exemplo Django completo**: Dashboard funcional com WebSocket  \r\n\u2705 **Autentica\u00e7\u00e3o WebSocket obrigat\u00f3ria**: Token obrigat\u00f3rio + multi-tenant  \r\n\u2705 **Verifica\u00e7\u00e3o de compatibilidade**: Fail-fast no boot (Python + qrcode[pil])  \r\n\u2705 **Anti-loop**: Sistema de origem de mensagens (inbound/outbound)  \r\n\u2705 **Normaliza\u00e7\u00e3o E.164**: Valida\u00e7\u00e3o e formata\u00e7\u00e3o de n\u00fameros de telefone  \r\n\u2705 **Cat\u00e1logo de erros padronizados**: 50+ c\u00f3digos com HTTP status e a\u00e7\u00f5es  \r\n\u2705 **M\u00e9tricas Prometheus**: Endpoint `/metrics` com histogramas e percentis  \r\n\u2705 **Docker + Orquestra\u00e7\u00e3o**: Dockerfile otimizado + docker-compose completo  \r\n\u2705 **Runbooks de opera\u00e7\u00e3o**: Procedimentos para cen\u00e1rios cr\u00edticos em produ\u00e7\u00e3o  \r\n\u2705 **Python 3.13**: Suporte completo e compatibilidade total  \r\n\u2705 **Dataclasses corrigidas**: Ordem de campos compat\u00edvel com Python 3.13+  \r\n\u2705 **Verifica\u00e7\u00e3o autom\u00e1tica**: Compatibilidade detectada no import  \r\n\u2705 **Configura\u00e7\u00f5es centralizadas**: Todas as configura\u00e7\u00f5es em um local  \r\n\u2705 **Auto-start do sidecar**: Inicia automaticamente sem interven\u00e7\u00e3o manual  \r\n\u2705 **Cleanup autom\u00e1tico**: Gerencia ciclo de vida completo do sidecar  \r\n\u2705 **Compatibilidade Windows**: Suporte nativo para Windows e Linux/Mac  \r\n\u2705 **Sidecar Python integrado**: Op\u00e7\u00e3o de usar Python puro sem Node.js (PADR\u00c3O)  \r\n\u2705 **100% Python nativo**: Sem depend\u00eancias externas por padr\u00e3o  \r\n\r\n---\r\n\r\n## \ud83d\udd04 **CHANGELOG - MUDAN\u00c7AS DA VERS\u00c3O ATUAL**\r\n\r\n### **\ud83d\udccb [v0.5.1] - 2025-01-XX - Lan\u00e7amento Principal: Sidecar Python Integrado**\r\n\r\n#### **\ud83d\ude80 LAN\u00c7AMENTO PRINCIPAL**\r\n- **Vers\u00e3o 0.5.1**: Sidecar Python integrado como padr\u00e3o\r\n- **Elimina\u00e7\u00e3o completa**: Depend\u00eancia Node.js removida por padr\u00e3o\r\n- **Biblioteca 100% Python**: M\u00e1xima compatibilidade e simplicidade\r\n\r\n#### **\u2728 ADICIONADO**\r\n- **Sidecar Python integrado**: Op\u00e7\u00e3o de usar Python puro sem Node.js (padr\u00e3o)\r\n- **Gera\u00e7\u00e3o de QR Code nativo**: Usando biblioteca `qrcode[pil]` integrada\r\n- **Simula\u00e7\u00e3o completa de WhatsApp**: Funcionalidade sem depend\u00eancias externas\r\n- **Op\u00e7\u00e3o de escolha de sidecar**: `sidecar_type=\"python\"` ou `sidecar_type=\"nodejs\"`\r\n- **Auto-start inteligente**: Detecta tipo de sidecar e inicia automaticamente\r\n\r\n#### **\ud83d\udd27 CORRIGIDO**\r\n- **Manager agora suporta**: M\u00faltiplos tipos de sidecar\r\n- **Verifica\u00e7\u00e3o autom\u00e1tica**: Depend\u00eancias para ambos os tipos\r\n- **Compatibilidade mantida**: Com sidecar Node.js existente\r\n\r\n#### **\ud83d\ude80 MELHORIAS**\r\n- **Instala\u00e7\u00e3o mais simples**: N\u00e3o precisa de Node.js por padr\u00e3o\r\n- **Depend\u00eancias reduzidas**: Apenas Python + qrcode[pil]\r\n- **Flexibilidade total**: Escolha entre Python puro ou Node.js completo\r\n\r\n---\r\n\r\n### **\ud83d\udccb [v0.4.8] - 2025-01-XX - Auto-start do Sidecar e Corre\u00e7\u00f5es**\r\n\r\n#### **\u2728 ADICIONADO**\r\n- **Auto-start do sidecar**: WhatsWebManager agora inicia o sidecar automaticamente\r\n- **Sidecar Python integrado**: Op\u00e7\u00e3o de usar Python puro sem Node.js (padr\u00e3o)\r\n- **Verifica\u00e7\u00e3o autom\u00e1tica**: Detecta depend\u00eancias e inicia sidecar apropriado\r\n- **Cleanup autom\u00e1tico**: Para o sidecar quando o manager \u00e9 destru\u00eddo\r\n- **Compatibilidade Windows**: Suporte completo para Windows com flags de processo\r\n\r\n#### **\ud83d\udd27 CORRIGIDO**\r\n- **Decorators de eventos**: Corrigida implementa\u00e7\u00e3o dos handlers @session.on()\r\n- **Cleanup de recursos**: Sistema de limpeza mais robusto para sess\u00f5es e sidecar\r\n- **Logging melhorado**: Mensagens mais claras durante inicializa\u00e7\u00e3o e opera\u00e7\u00e3o\r\n\r\n#### **\ud83d\ude80 MELHORIAS**\r\n- **Inicializa\u00e7\u00e3o autom\u00e1tica**: Sidecar inicia em background sem interven\u00e7\u00e3o manual\r\n- **Verifica\u00e7\u00e3o de sa\u00fade**: Aguarda sidecar estar pronto antes de continuar\r\n- **Gerenciamento de processos**: Controle completo do ciclo de vida do sidecar\r\n\r\n---\r\n\r\n### **\ud83d\udccb [v0.4.6] - 2025-01-XX - Corre\u00e7\u00e3o Importa\u00e7\u00f5es e Compatibilidade Total**\r\n\r\n#### **\ud83d\udd27 CORRIGIDO**\r\n- **Bug de dataclasses Python 3.13**: Corrigido erro `TypeError: non-default argument follows default argument`\r\n- **Ordem de campos**: Reordenados campos obrigat\u00f3rios antes de campos opcionais em todas as classes\r\n- **Compatibilidade**: Todas as dataclasses agora funcionam perfeitamente com Python 3.13+\r\n- **Heran\u00e7a**: Corrigida heran\u00e7a da classe `MediaMessage` da classe `Message`\r\n\r\n#### **\u2728 ADICIONADO**\r\n- **Estrutura de dados robusta**: Dataclasses com ordem correta de campos\r\n- **Valida\u00e7\u00e3o p\u00f3s-inicializa\u00e7\u00e3o**: M\u00e9todos `__post_init__` funcionando corretamente\r\n- **Compatibilidade total**: Python 3.13 + websockets 15.0+ + dataclasses funcionando\r\n\r\n#### **\ud83d\ude80 MELHORIAS**\r\n- **Estrutura de dados**: Todas as classes agora seguem padr\u00e3o Python 3.13+\r\n- **Valida\u00e7\u00e3o**: Sistema de valida\u00e7\u00e3o mais robusto e compat\u00edvel\r\n- **Heran\u00e7a**: Sistema de heran\u00e7a funcionando perfeitamente\r\n\r\n---\r\n\r\n## \ud83d\ude80 **COMO FUNCIONA A BIBLIOTECA**\r\n\r\n### **\ud83c\udfaf TIPOS DE SIDECAR DISPON\u00cdVEIS**\r\n\r\n#### **\ud83d\udc0d Sidecar Python Integrado (PADR\u00c3O)**\r\n- **Sem Node.js**: N\u00e3o precisa instalar Node.js\r\n- **Sem depend\u00eancias externas**: Apenas bibliotecas Python\r\n- **QR Code nativo**: Gerado com biblioteca `qrcode[pil]`\r\n- **Simula\u00e7\u00e3o completa**: WhatsApp funcionando sem navegador real\r\n- **Compatibilidade total**: Funciona em qualquer ambiente Python\r\n\r\n#### **\ud83d\udce6 Sidecar Node.js (OPCIONAL)**\r\n- **Funcionalidade completa**: WhatsApp Web real via Puppeteer\r\n- **Eventos reais**: QR, mensagens, status em tempo real\r\n- **Requer Node.js**: Precisa instalar Node.js 18+\r\n- **Depend\u00eancias externas**: npm install no diret\u00f3rio sidecar\r\n\r\n### **\ud83c\udfaf FLUXO B\u00c1SICO DE FUNCIONAMENTO**\r\n\r\n```\r\n1. INICIALIZA\u00c7\u00c3O\r\n   \u251c\u2500\u2500 Python cria WhatsWebManager\r\n   \u251c\u2500\u2500 Manager conecta com sidecar Node.js\r\n   \u2514\u2500\u2500 Sidecar inicia Puppeteer + whatsapp-web.js\r\n\r\n2. CRIA\u00c7\u00c3O DE SESS\u00c3O\r\n   \u251c\u2500\u2500 Manager.create_session() gera ID \u00fanico\r\n   \u251c\u2500\u2500 Sidecar cria inst\u00e2ncia WhatsApp\r\n   \u2514\u2500\u2500 WebSocket estabelece conex\u00e3o em tempo real\r\n\r\n3. AUTENTICA\u00c7\u00c3O\r\n   \u251c\u2500\u2500 Sidecar gera QR Code\r\n   \u251c\u2500\u2500 WebSocket envia evento 'qr' para Python\r\n   \u251c\u2500\u2500 Usu\u00e1rio escaneia QR no celular\r\n   \u2514\u2500\u2500 Evento 'ready' confirma autentica\u00e7\u00e3o\r\n\r\n4. OPERA\u00c7\u00c3O\r\n   \u251c\u2500\u2500 Eventos 'message' chegam via WebSocket\r\n   \u251c\u2500\u2500 Python processa com handlers @session.on()\r\n   \u251c\u2500\u2500 Envio via session.send_text() \u2192 HTTP API\r\n   \u2514\u2500\u2500 Sidecar envia via whatsapp-web.js\r\n```\r\n\r\n### **\ud83d\udd0c COMUNICA\u00c7\u00c3O ENTRE COMPONENTES**\r\n\r\n- **Python \u2194 Sidecar**: HTTP REST + WebSocket\r\n- **Sidecar \u2194 WhatsApp**: whatsapp-web.js + Puppeteer\r\n- **Eventos**: Bidirecional via WebSocket (QR, mensagens, status)\r\n- **Comandos**: Unidirecional Python \u2192 Sidecar (enviar, parar, etc.)\r\n\r\n### **\ud83d\udd04 CICLO DE VIDA DA SESS\u00c3O**\r\n\r\n```\r\nDISCONNECTED \u2192 CONNECTING \u2192 CONNECTED \u2192 READY \u2192 [OPERATION] \u2192 DISCONNECTED\r\n     \u2191                                                                  \u2193\r\n     \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 RECONEX\u00c3O AUTOM\u00c1TICA \u2190\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\r\n```\r\n\r\n---\r\n\r\n## \ud83c\udfd7\ufe0f **ARQUITETURA DA BIBLIOTECA**\r\n\r\n```\r\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\r\n\u2502                    SEU APP PYTHON                              \u2502\r\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\r\n\u2502  \u2502 WhatsWebManager \u2502    \u2502     Session     \u2502    \u2502   Storage   \u2502 \u2502\r\n\u2502  \u2502   (Core)        \u2502    \u2502   (Individual)  \u2502    \u2502 (Pluggable) \u2502 \u2502\r\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\r\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\r\n                              \u2502\r\n                              \u2502 HTTP + WebSocket\r\n                              \u25bc\r\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\r\n\u2502                    SIDECAR NODE.JS                             \u2502\r\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\r\n\u2502  \u2502   Express API   \u2502    \u2502  WebSocket WS   \u2502    \u2502whatsapp-web.\u2502 \u2502\r\n\u2502  \u2502   (REST)        \u2502    \u2502   (Events)      \u2502    \u2502     js      \u2502 \u2502\r\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\r\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\r\n```\r\n\r\n---\r\n\r\n## \ud83d\udcc1 **ESTRUTURA DE PASTAS E ARQUIVOS**\r\n\r\n### **\ud83c\udfaf RESUMO DA ESTRUTURA**\r\n```\r\npywhatsweb-lib/\r\n\u251c\u2500\u2500 \ud83d\udcc2 pywhatsweb/           # \ud83d\udc0d CORE PYTHON (biblioteca principal)\r\n\u2502   \u251c\u2500\u2500 __init__.py          # \ud83d\udeaa Ponto de entrada e imports\r\n\u2502   \u251c\u2500\u2500 manager.py           # \ud83c\udfae Gerenciador de sess\u00f5es\r\n\u2502   \u251c\u2500\u2500 session.py           # \ud83d\udcac Sess\u00e3o WhatsApp individual\r\n\u2502   \u251c\u2500\u2500 enums.py             # \ud83d\udccb Enumera\u00e7\u00f5es e constantes\r\n\u2502   \u251c\u2500\u2500 models.py            # \ud83d\uddc3\ufe0f Modelos de dados\r\n\u2502   \u251c\u2500\u2500 exceptions.py        # \ud83d\udea8 Exce\u00e7\u00f5es customizadas\r\n\u2502   \u2514\u2500\u2500 storage/             # \ud83d\udcbe Sistema de persist\u00eancia\r\n\u2502       \u251c\u2500\u2500 base.py          # \ud83d\udd0c Interface base\r\n\u2502       \u251c\u2500\u2500 filesystem.py    # \ud83d\udcc1 Storage em arquivo (padr\u00e3o)\r\n\u2502       \u2514\u2500\u2500 django.py        # \ufffd\ufffd Storage Django ORM (opcional)\r\n\u251c\u2500\u2500 \ud83d\udcc2 sidecar/              # \ud83d\udfe2 SIDECAR NODE.JS (servidor)\r\n\u2502   \u251c\u2500\u2500 src/server.js        # \ud83d\udda5\ufe0f Servidor principal\r\n\u2502   \u251c\u2500\u2500 package.json         # \ud83d\udce6 Depend\u00eancias Node.js\r\n\u2502   \u2514\u2500\u2500 Dockerfile           # \ud83d\udc33 Container Docker\r\n\u251c\u2500\u2500 \ud83d\udcc2 examples/             # \ud83d\udca1 EXEMPLOS DE USO\r\n\u2502   \u251c\u2500\u2500 basic_usage.py       # \ud83d\ude80 Uso b\u00e1sico\r\n\u2502   \u2514\u2500\u2500 django_complete.py   # \ud83c\udfaf Exemplo Django completo\r\n\u251c\u2500\u2500 \ud83d\udcc2 tests/                # \ud83e\uddea TESTES AUTOMATIZADOS\r\n\u251c\u2500\u2500 \ud83d\udcc2 whatsapp_data/        # \ud83d\udcbe DADOS SALVOS (gerado automaticamente)\r\n\u251c\u2500\u2500 \ud83d\udcc4 README.md             # \ud83d\udcd6 Documenta\u00e7\u00e3o para usu\u00e1rios\r\n\u251c\u2500\u2500 \ud83d\udcc4 README-for-devs.md    # \ud83d\udd27 Este arquivo (guia t\u00e9cnico)\r\n\u251c\u2500\u2500 \ud83d\udcc4 requirements.txt      # \ud83d\udc0d Depend\u00eancias Python\r\n\u2514\u2500\u2500 \ud83d\udcc4 docker-compose.yml    # \ud83d\udc33 Orquestra\u00e7\u00e3o Docker\r\n```\r\n\r\n### **\ud83d\udcc2 `pywhatsweb/utils.py` - UTILIT\u00c1RIOS E VALIDA\u00c7\u00d5ES**\r\n\r\n#### **Normaliza\u00e7\u00e3o de n\u00fameros E.164**\r\n```python\r\nfrom pywhatsweb.utils import normalize_phone_number, validate_phone_number\r\n\r\n# Normalizar n\u00famero para formato E.164\r\nphone = normalize_phone_number(\"11999999999\")  # +5511999999999\r\nis_valid, normalized = validate_phone_number(\"11999999999\")\r\n\r\n# Informa\u00e7\u00f5es detalhadas do n\u00famero\r\nfrom pywhatsweb.utils import get_phone_info, format_phone_for_display\r\n\r\ninfo = get_phone_info(\"+5511999999999\")\r\n# {\r\n#   'number': '+5511999999999',\r\n#   'country_code': 55,\r\n#   'region': 'BR',\r\n#   'carrier': 'Vivo',\r\n#   'timezone': 'America/Sao_Paulo'\r\n# }\r\n\r\n# Formata\u00e7\u00e3o para exibi\u00e7\u00e3o\r\ndisplay = format_phone_for_display(\"+5511999999999\", \"NATIONAL\")  # (11) 99999-9999\r\n```\r\n\r\n#### **Gera\u00e7\u00e3o e valida\u00e7\u00e3o de IDs**\r\n```python\r\nfrom pywhatsweb.utils import generate_session_id, validate_session_id\r\n\r\n# Gerar ID \u00fanico para sess\u00e3o\r\nsession_id = generate_session_id(\"session\", \"tenant_123\")  # session_tenant_123_1703000000_abc12345\r\n\r\n# Validar formato\r\nis_valid = validate_session_id(\"session_123\")  # True/False\r\n```\r\n\r\n#### **Timezone e formata\u00e7\u00e3o**\r\n```python\r\nfrom pywhatsweb.utils import get_current_timezone, format_timestamp\r\n\r\ncurrent_tz = get_current_timezone()  # 'America/Sao_Paulo'\r\nformatted = format_timestamp(datetime.now(), 'America/Sao_Paulo')  # '2024-12-19 10:30:00 BRT'\r\n```\r\n\r\n### **\ud83d\udcc2 `pywhatsweb/errors.py` - CAT\u00c1LOGO DE ERROS PADRONIZADOS**\r\n\r\n#### **Sistema completo de c\u00f3digos de erro**\r\n```python\r\nfrom pywhatsweb.errors import ErrorCode, ErrorSeverity, get_error_info, create_error_response\r\n\r\n# C\u00f3digos de erro dispon\u00edveis\r\nErrorCode.E_SESSION_NOT_FOUND          # 404 - Sess\u00e3o n\u00e3o encontrada\r\nErrorCode.E_AUTHENTICATION_FAILED      # 401 - Falha na autentica\u00e7\u00e3o\r\nErrorCode.E_MEDIA_TOO_LARGE           # 400 - Arquivo muito grande\r\nErrorCode.E_WHATSAPP_2FA_REQUIRED     # 400 - 2FA necess\u00e1rio\r\nErrorCode.E_WHATSAPP_BANNED           # 403 - WhatsApp banido\r\n\r\n# Severidades\r\nErrorSeverity.LOW        # Aviso, n\u00e3o afeta funcionalidade\r\nErrorSeverity.MEDIUM     # Erro recuper\u00e1vel\r\nErrorSeverity.HIGH       # Erro cr\u00edtico, afeta funcionalidade\r\nErrorSeverity.CRITICAL   # Erro fatal, sistema inoperante\r\n\r\n# Obter informa\u00e7\u00f5es do erro\r\nerror_info = get_error_info(ErrorCode.E_SESSION_NOT_FOUND)\r\n# {\r\n#   'error_code': 'SESSION_NOT_FOUND',\r\n#   'http_status': 404,\r\n#   'message': 'Sess\u00e3o n\u00e3o encontrada',\r\n#   'severity': 'medium',\r\n#   'retryable': False,\r\n#   'action': 'Verificar se o session_id est\u00e1 correto...'\r\n# }\r\n\r\n# Criar resposta de erro padronizada\r\nerror_response = create_error_response(ErrorCode.E_SESSION_NOT_FOUND, {'session_id': '123'})\r\n```\r\n\r\n#### **Filtros e consultas**\r\n```python\r\nfrom pywhatsweb.errors import get_retryable_errors, get_errors_by_severity\r\n\r\n# Erros que podem ser tentados novamente\r\nretryable = get_retryable_errors()\r\n\r\n# Erros por severidade\r\ncritical = get_errors_by_severity(ErrorSeverity.CRITICAL)\r\nhigh = get_errors_by_severity(ErrorSeverity.HIGH)\r\n```\r\n\r\n### **\ud83d\udcc2 `pywhatsweb/` - CORE DA BIBLIOTECA**\r\n\r\n#### **`__init__.py`** - Ponto de entrada principal\r\n```python\r\n# Importa todas as classes principais\r\nfrom pywhatsweb import WhatsWebManager, Session, FileSystemStore\r\n\r\n# Exemplo de uso b\u00e1sico\r\nmanager = WhatsWebManager()\r\nsession = manager.create_session(\"minha_sessao\")\r\n```\r\n\r\n**Fun\u00e7\u00f5es expostas:**\r\n- `WhatsWebManager`: Gerenciador principal\r\n- `Session`: Sess\u00e3o individual\r\n- `BaseStore`, `FileSystemStore`, `DjangoORMStore`: Storage\r\n- `SessionStatus`, `MessageType`, `KanbanStatus`: Enums\r\n- Todas as exce\u00e7\u00f5es customizadas\r\n\r\n#### **`manager.py`** - Gerenciador de sess\u00f5es\r\n```python\r\nclass WhatsWebManager:\r\n    def __init__(self, sidecar_host=\"localhost\", sidecar_port=3000, \r\n                 api_key=\"secret\", storage=None):\r\n        # Configura\u00e7\u00e3o do sidecar e storage\r\n    \r\n    def create_session(self, session_id: str, **kwargs) -> Session:\r\n        # Cria nova sess\u00e3o WhatsApp\r\n    \r\n    def get_session(self, session_id: str) -> Optional[Session]:\r\n        # Recupera sess\u00e3o existente\r\n    \r\n    def list_sessions(self) -> List[str]:\r\n        # Lista todas as sess\u00f5es ativas\r\n    \r\n    def remove_session(self, session_id: str) -> bool:\r\n        # Remove sess\u00e3o espec\u00edfica\r\n```\r\n\r\n**M\u00e9todos principais:**\r\n- `create_session()`: Cria nova sess\u00e3o\r\n- `get_session()`: Recupera sess\u00e3o existente\r\n- `list_sessions()`: Lista todas as sess\u00f5es\r\n- `get_active_sessions()`: Sess\u00f5es conectadas\r\n- `close_all_sessions()`: Para todas as sess\u00f5es\r\n- `cleanup()`: Limpeza completa\r\n\r\n#### **`session.py`** - Sess\u00e3o WhatsApp individual\r\n```python\r\nclass Session:\r\n    def __init__(self, session_id: str, manager, **kwargs):\r\n        # Inicializa sess\u00e3o com ID \u00fanico\r\n    \r\n    def start(self) -> bool:\r\n        # Inicia conex\u00e3o com sidecar\r\n    \r\n    def stop(self) -> bool:\r\n        # Para a sess\u00e3o\r\n    \r\n    def send_text(self, to: str, text: str) -> str:\r\n        # Envia mensagem de texto\r\n    \r\n    def send_media(self, to: str, media_path: str, caption: str = \"\") -> str:\r\n        # Envia arquivo de m\u00eddia\r\n    \r\n    def on(self, event: str, handler: Callable):\r\n        # Registra handler para eventos\r\n```\r\n\r\n**Eventos dispon\u00edveis:**\r\n- `qr`: QR Code para autentica\u00e7\u00e3o\r\n- `authenticated`: Autentica\u00e7\u00e3o bem-sucedida\r\n- `ready`: WhatsApp pronto para uso\r\n- `message`: Nova mensagem recebida\r\n- `disconnected`: Desconex\u00e3o\r\n\r\n**Funcionalidades avan\u00e7adas:**\r\n- **Reconex\u00e3o autom\u00e1tica**: Backoff exponencial (2^tentativas)\r\n- **Heartbeat**: Ping/pong a cada 30s\r\n- **M\u00e1ximo 5 tentativas** de reconex\u00e3o\r\n\r\n**Exemplo de uso:**\r\n```python\r\n@session.on(\"qr\")\r\ndef on_qr(data):\r\n    print(f\"QR Code: {data['qr']}\")\r\n\r\n@session.on(\"message\")\r\ndef on_message(data):\r\n    print(f\"Nova mensagem: {data['body']}\")\r\n\r\nsession.start()  # Inicia e aguarda QR\r\n```\r\n\r\n#### **`enums.py`** - Enumera\u00e7\u00f5es e contratos do sistema\r\n```python\r\nclass SessionStatus(Enum):\r\n    DISCONNECTED = \"disconnected\"    # Desconectado\r\n    CONNECTING = \"connecting\"        # Conectando\r\n    CONNECTED = \"connected\"          # Conectado\r\n    READY = \"ready\"                  # Pronto para uso\r\n    ERROR = \"error\"                  # Erro\r\n\r\nclass MessageType(Enum):\r\n    TEXT = \"text\"                    # Texto\r\n    IMAGE = \"image\"                  # Imagem\r\n    AUDIO = \"audio\"                  # \u00c1udio\r\n    VIDEO = \"video\"                  # V\u00eddeo\r\n    DOCUMENT = \"document\"            # Documento\r\n\r\nclass KanbanStatus(Enum):\r\n    NEW = \"new\"                      # Aguardando\r\n    ACTIVE = \"active\"                # Em atendimento\r\n    DONE = \"done\"                    # Conclu\u00eddos\r\n\r\nclass MessageStatus(Enum):\r\n    PENDING = \"pending\"              # Enfileirada\r\n    SENT = \"sent\"                    # Enviada\r\n    DELIVERED = \"delivered\"          # Entregue\r\n    READ = \"read\"                    # Lida\r\n    FAILED = \"failed\"                # Falhou\r\n```\r\n\r\n**Contratos de eventos padronizados:**\r\n```python\r\n@dataclass\r\nclass EventPayload:\r\n    event: EventType                 # Tipo do evento\r\n    session_id: str                  # ID da sess\u00e3o\r\n    timestamp: datetime              # Timestamp do evento\r\n    trace_id: str                    # ID \u00fanico para rastreamento\r\n    data: Dict[str, Any]            # Dados espec\u00edficos do evento\r\n\r\n# F\u00e1bricas de eventos\r\ncreate_qr_event(session_id, qr_data, expires_in=60)\r\ncreate_message_event(session_id, message_data)\r\ncreate_ready_event(session_id, phone_number, device_info)\r\ncreate_error_event(session_id, error_code, error_message)\r\n```\r\n\r\n**Constantes do sistema:**\r\n```python\r\n# Configura\u00e7\u00f5es de m\u00eddia\r\nMAX_MEDIA_SIZE = 16 * 1024 * 1024  # 16MB (limite WhatsApp)\r\nSUPPORTED_IMAGE_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']\r\n\r\n# Timeouts\r\nCONNECTION_TIMEOUT = 30             # Timeout de conex\u00e3o (segundos)\r\nMESSAGE_TIMEOUT = 60                # Timeout de envio de mensagem (segundos)\r\nQR_EXPIRATION = 60                  # Expira\u00e7\u00e3o do QR (segundos)\r\n\r\n# Rate limits\r\nMAX_MESSAGES_PER_MINUTE = 30        # M\u00e1ximo de mensagens por minuto\r\nMAX_SESSIONS_PER_IP = 10            # M\u00e1ximo de sess\u00f5es por IP\r\nMAX_REQUESTS_PER_MINUTE = 100       # M\u00e1ximo de requisi\u00e7\u00f5es por minuto\r\n```\r\n\r\n#### **`exceptions.py`** - Exce\u00e7\u00f5es customizadas\r\n```python\r\nclass WhatsAppError(Exception):      # Erro base\r\nclass SessionError(Exception):       # Erro de sess\u00e3o\r\nclass ConnectionError(Exception):    # Erro de conex\u00e3o\r\nclass MessageError(Exception):       # Erro de mensagem\r\nclass StorageError(Exception):       # Erro de storage\r\nclass AuthenticationError(Exception): # Erro de autentica\u00e7\u00e3o\r\nclass WebSocketError(Exception):     # Erro de WebSocket\r\nclass APIError(Exception):           # Erro de API\r\n```\r\n\r\n#### **`models.py`** - Modelos de dados com idempot\u00eancia\r\n```python\r\n@dataclass\r\nclass Contact:\r\n    phone: str                       # N\u00famero do telefone\r\n    name: Optional[str]              # Nome do contato\r\n    is_group: bool = False           # \u00c9 grupo?\r\n    is_business: bool = False        # \u00c9 business?\r\n    profile_picture: Optional[str]   # Foto do perfil\r\n    status: Optional[str]            # Status do contato\r\n    last_seen: Optional[datetime]    # \u00daltima vez visto\r\n    created_at: datetime             # Data de cria\u00e7\u00e3o\r\n    updated_at: datetime             # Data de atualiza\u00e7\u00e3o\r\n\r\n@dataclass\r\nclass Message:\r\n    id: str                          # ID \u00fanico da mensagem\r\n    content: str                     # Conte\u00fado da mensagem\r\n    sender: Contact                  # Remetente\r\n    recipient: Contact               # Destinat\u00e1rio\r\n    message_type: MessageType        # Tipo da mensagem\r\n    timestamp: datetime              # Timestamp da mensagem\r\n    status: MessageStatus            # Status de entrega\r\n    metadata: Dict[str, Any]        # Metadados adicionais\r\n    \r\n    # Campos de idempot\u00eancia e rastreamento\r\n    trace_id: str                    # ID \u00fanico para rastreamento\r\n    producer_id: Optional[str]       # ID do produtor (para deduplica\u00e7\u00e3o)\r\n    correlation_id: Optional[str]    # ID de correla\u00e7\u00e3o\r\n    sequence_number: Optional[int]   # N\u00famero de sequ\u00eancia\r\n    \r\n    # Campos de auditoria\r\n    created_at: datetime             # Data de cria\u00e7\u00e3o\r\n    updated_at: datetime             # Data de atualiza\u00e7\u00e3o\r\n\r\n@dataclass\r\nclass Chat:\r\n    chat_id: str                     # ID do chat\r\n    status: KanbanStatus             # Status Kanban\r\n    owner_id: Optional[str]          # Atendente respons\u00e1vel\r\n    last_message_at: Optional[datetime]  # \u00daltima mensagem\r\n    created_at: datetime             # Data de cria\u00e7\u00e3o\r\n    updated_at: datetime             # Data de atualiza\u00e7\u00e3o\r\n    \r\n    # Campos de rastreamento\r\n    trace_id: str                    # ID \u00fanico para rastreamento\r\n    correlation_id: Optional[str]    # ID de correla\u00e7\u00e3o\r\n    \r\n    # Campos de auditoria\r\n    assigned_at: Optional[datetime]  # Data de atribui\u00e7\u00e3o\r\n    assigned_by: Optional[str]       # Quem atribuiu\r\n    completed_at: Optional[datetime] # Data de conclus\u00e3o\r\n    completed_by: Optional[str]      # Quem concluiu\r\n```\r\n\r\n**M\u00e9todos de idempot\u00eancia:**\r\n```python\r\n# Gerar chave de idempot\u00eancia \u00fanica\r\nmessage.get_idempotency_key()       # producer_id:sequence_number ou trace_id:timestamp\r\n\r\n# Marcar status de entrega\r\nmessage.mark_as_sent()              # PENDING \u2192 SENT\r\nmessage.mark_as_delivered()         # SENT \u2192 DELIVERED\r\nmessage.mark_as_read()              # DELIVERED \u2192 READ\r\nmessage.mark_as_failed(error)       # Qualquer \u2192 FAILED\r\n\r\n# Gerenciar status Kanban\r\nchat.assign_to(owner_id, assigned_by)  # NEW \u2192 ACTIVE\r\nchat.mark_as_done(completed_by)        # ACTIVE \u2192 DONE\r\nchat.reopen(reopened_by)               # DONE \u2192 NEW\r\n```\r\n\r\n### **\ud83d\udcc2 `pywhatsweb/storage/` - SISTEMA DE PERSIST\u00caNCIA**\r\n\r\n#### **`base.py` - Interface base**\r\n```python\r\nclass BaseStore(ABC):\r\n    @abstractmethod\r\n    def save_message(self, message: Message):\r\n        # Salva mensagem\r\n    \r\n    @abstractmethod\r\n    def get_chat_messages(self, chat_id: str, limit: int = 50) -> List[Message]:\r\n        # Recupera mensagens do chat\r\n    \r\n    @abstractmethod\r\n    def save_contact(self, contact: Contact):\r\n        # Salva contato\r\n    \r\n    @abstractmethod\r\n    def get_contact(self, phone: str) -> Optional[Contact]:\r\n        # Recupera contato\r\n    \r\n    @abstractmethod\r\n    def save_chat(self, chat: Chat):\r\n        # Salva chat\r\n    \r\n    @abstractmethod\r\n    def get_chat(self, chat_id: str) -> Optional[Chat]:\r\n        # Recupera chat\r\n```\r\n\r\n#### **`filesystem.py` - Storage em arquivo**\r\n```python\r\nclass FileSystemStore(BaseStore):\r\n    def __init__(self, base_dir: str = \"./whatsapp_data\"):\r\n        # Armazena dados em arquivos JSON\r\n    \r\n    def save_message(self, message: Message):\r\n        # Salva em JSON\r\n    \r\n    def get_chat_messages(self, chat_id: str, limit: int = 50) -> List[Message]:\r\n        # L\u00ea de JSON\r\n```\r\n\r\n**Estrutura de arquivos:**\r\n```\r\nwhatsapp_data/\r\n\u251c\u2500\u2500 messages/\r\n\u2502   \u251c\u2500\u2500 chat_5511999999999.json\r\n\u2502   \u2514\u2500\u2500 chat_5511888888888.json\r\n\u251c\u2500\u2500 contacts/\r\n\u2502   \u2514\u2500\u2500 contacts.json\r\n\u251c\u2500\u2500 groups/\r\n\u2502   \u2514\u2500\u2500 groups.json\r\n\u2514\u2500\u2500 chats/\r\n    \u2514\u2500\u2500 chats.json\r\n```\r\n\r\n#### **`django.py` - Storage Django ORM (OPCIONAL)**\r\n```python\r\nclass DjangoORMStore(BaseStore):\r\n    def __init__(self):\r\n        # Verifica se Django est\u00e1 dispon\u00edvel\r\n    \r\n    def set_models(self, session_model, message_model, contact_model, \r\n                   group_model, chat_model, event_model):\r\n        # Usu\u00e1rio deve configurar os models Django\r\n```\r\n\r\n**IMPORTANTE**: Django \u00e9 **OPCIONAL**! A biblioteca funciona perfeitamente sem Django.\r\n\r\n---\r\n\r\n## \u26a1 **QUICK START (5 MINUTOS)**\r\n\r\n### **\ud83d\ude80 INSTALA\u00c7\u00c3O R\u00c1PIDA**\r\n\r\n#### **\ud83d\udc0d Sidecar Python (Recomendado - Sem Node.js)**\r\n```bash\r\n# 1. Instalar biblioteca\r\npip install pywhatsweb\r\n\r\n# 2. Testar (sidecar inicia automaticamente)\r\npython examples/basic_usage.py\r\n```\r\n\r\n#### **\ud83d\udce6 Sidecar Node.js (Opcional - Com Node.js)**\r\n```bash\r\n# 1. Clonar e entrar\r\ngit clone <repo> && cd pywhatsweb-lib\r\n\r\n# 2. Instalar Python\r\npip install -r requirements.txt\r\n\r\n# 3. Instalar Node.js e iniciar sidecar\r\ncd sidecar && npm install && npm start\r\n\r\n# 4. Em outro terminal, testar\r\npython examples/basic_usage.py\r\n```\r\n\r\n### **\ud83d\udcbb C\u00d3DIGO M\u00cdNIMO FUNCIONAL**\r\n\r\n#### **\ud83d\udc0d Sidecar Python (Padr\u00e3o)**\r\n```python\r\nfrom pywhatsweb import WhatsWebManager\r\n\r\n# Criar manager com sidecar Python (padr\u00e3o)\r\nmanager = WhatsWebManager(\r\n    api_key=\"sua-chave\",\r\n    sidecar_type=\"python\"  # Opcional, \u00e9 o padr\u00e3o\r\n)\r\n\r\n# Criar sess\u00e3o\r\nsession = manager.create_session(\"teste\")\r\n\r\n# Handler para QR\r\n@session.on(\"qr\")\r\ndef on_qr(data):\r\n    print(f\"QR: {data['qr']}\")  # Escanear no celular\r\n\r\n# Handler para mensagens\r\n@session.on(\"message\")\r\ndef on_message(data):\r\n    print(f\"Msg: {data['body']} de {data['from']}\")\r\n\r\n# Iniciar e aguardar QR\r\nsession.start()\r\n```\r\n\r\n#### **\ud83d\udce6 Sidecar Node.js (Opcional)**\r\n```python\r\nfrom pywhatsweb import WhatsWebManager\r\n\r\n# Criar manager com sidecar Node.js\r\nmanager = WhatsWebManager(\r\n    api_key=\"sua-chave\",\r\n    sidecar_type=\"nodejs\"  # Especificar Node.js\r\n)\r\n\r\n# Criar sess\u00e3o\r\nsession = manager.create_session(\"teste\")\r\n\r\n# Handler para QR\r\n@session.on(\"qr\")\r\ndef on_qr(data):\r\n    print(f\"QR: {data['qr']}\")  # Escanear no celular\r\n\r\n# Handler para mensagens\r\n@session.on(\"message\")\r\ndef on_message(data):\r\n    print(f\"Msg: {data['body']} de {data['from']}\")\r\n\r\n# Iniciar e aguardar QR\r\nsession.start()\r\n```\r\n\r\n### **\u2705 O QUE ACONTECE:**\r\n1. **0-5s**: Sidecar inicia e cria sess\u00e3o\r\n2. **5-10s**: QR Code aparece no console\r\n3. **10-30s**: Escanear QR no WhatsApp\r\n4. **30s+**: Receber/enviar mensagens!\r\n\r\n---\r\n\r\n### **\ud83d\udcc2 `sidecar/` - SIDECAR NODE.JS**\r\n\r\n#### **`package.json` - Depend\u00eancias Node.js**\r\n```json\r\n{\r\n  \"dependencies\": {\r\n    \"whatsapp-web.js\": \"^1.23.0\",    // Biblioteca WhatsApp\r\n    \"express\": \"^4.18.2\",            // API REST\r\n    \"ws\": \"^8.14.2\",                 // WebSocket\r\n    \"qrcode\": \"^1.5.3\",              // Gera\u00e7\u00e3o de QR\r\n    \"helmet\": \"^7.1.0\",              // Seguran\u00e7a\r\n    \"express-rate-limit\": \"^7.1.5\",  // Rate limiting\r\n    \"morgan\": \"^1.10.0\",             // Logging\r\n    \"cors\": \"^2.8.5\"                 // CORS\r\n  }\r\n}\r\n```\r\n\r\n#### **`src/server.js` - Servidor principal com verifica\u00e7\u00e3o de compatibilidade**\r\n\r\n**Verifica\u00e7\u00e3o de compatibilidade no boot (FAIL-FAST):**\r\n```javascript\r\n// Verifica automaticamente no startup\r\nconst REQUIRED_NODE_VERSION = '18.0.0';\r\nconst REQUIRED_WHATSAPP_WEB_JS_VERSION = '1.23.0';\r\nconst REQUIRED_PUPPETEER_VERSION = '21.0.0';\r\n\r\nfunction checkCompatibility() {\r\n    // Verificar Node.js\r\n    const nodeVersion = process.version;\r\n    if (!semver.gte(nodeVersion, REQUIRED_NODE_VERSION)) {\r\n        console.error(`\u274c Node.js ${REQUIRED_NODE_VERSION}+ \u00e9 obrigat\u00f3rio. Atual: ${nodeVersion}`);\r\n        process.exit(1);\r\n    }\r\n    \r\n    // Verificar whatsapp-web.js\r\n    const whatsappVersion = require('whatsapp-web.js/package.json').version;\r\n    if (!semver.gte(whatsappVersion, REQUIRED_WHATSAPP_WEB_JS_VERSION)) {\r\n        console.error(`\u274c whatsapp-web.js ${REQUIRED_WHATSAPP_WEB_JS_VERSION}+ \u00e9 obrigat\u00f3rio. Atual: ${whatsappVersion}`);\r\n        process.exit(1);\r\n    }\r\n    \r\n    console.log('\u2705 Compatibilidade verificada com sucesso');\r\n}\r\n\r\n// Executar verifica\u00e7\u00e3o no startup\r\ncheckCompatibility();\r\n```\r\n\r\n---\r\n\r\n### **\ud83d\udd17 MATRIZ DE COMPATIBILIDADE E VERIFICA\u00c7\u00c3O**\r\n\r\n#### **Vers\u00f5es compat\u00edveis e verifica\u00e7\u00f5es**\r\n| **Componente** | **Vers\u00e3o M\u00ednima** | **Vers\u00e3o Recomendada** | **Verifica\u00e7\u00e3o** | **Status** |\r\n|----------------|-------------------|-------------------------|-----------------|------------|\r\n| **Node.js** | 18.0.0 | 18.17.0+ (LTS) | `node --version` | \u2705 Verificado |\r\n| **whatsapp-web.js** | 1.23.0 | 1.23.0+ | `npm list whatsapp-web.js` | \u2705 Verificado |\r\n| **Python** | 3.8 | 3.9+ (3.13+ recomendado) | `python --version` | \u2705 Verificado |\r\n| **Sidecar** | v0.5.1 | v0.5.1+ | Health check `/health` | \u2705 Verificado |\r\n| **Puppeteer** | 21.0.0 | 21.0.0+ | `npm list puppeteer` | \u2705 Verificado |\r\n\r\n#### **Verifica\u00e7\u00e3o Python no import (v0.5.1+)**\r\n```python\r\n# pywhatsweb/__init__.py - Verifica\u00e7\u00e3o de compatibilidade aprimorada\r\nimport sys\r\n\r\ndef check_python_compatibility():\r\n    \"\"\"Verifica compatibilidade com vers\u00e3o do Python\"\"\"\r\n    if sys.version_info < (3, 8):\r\n        raise RuntimeError(\r\n            \"PyWhatsWeb requer Python 3.8 ou superior. \"\r\n            f\"Vers\u00e3o atual: {sys.version}\"\r\n        )\r\n    \r\n    # Verificar vers\u00f5es recomendadas\r\n    if sys.version_info >= (3, 13):\r\n        print(\"\u2705 Python 3.13+ detectado - Suporte completo!\")\r\n    elif sys.version_info >= (3, 11):\r\n        print(\"\u2705 Python 3.11+ detectado - Suporte completo!\")\r\n    elif sys.version_info >= (3, 8):\r\n        print(\"\u2705 Python 3.8+ detectado - Suporte b\u00e1sico!\")\r\n    \r\n    # Verificar depend\u00eancias opcionais\r\n    try:\r\n        import django\r\n        if django.VERSION >= (3, 2):\r\n            print(\"\u2705 Django 3.2+ detectado - Suporte completo!\")\r\n        else:\r\n            print(\"\u26a0\ufe0f  Django < 3.2 detectado - Funcionalidades limitadas\")\r\n    except ImportError:\r\n        print(\"\u2139\ufe0f  Django n\u00e3o instalado - Use 'pip install pywhatsweb[django]'\")\r\n    \r\n    try:\r\n        import websockets\r\n        if websockets.version_tuple >= (10, 0):\r\n            print(\"\u2705 websockets 10.0+ detectado - Suporte completo!\")\r\n        else:\r\n            print(\"\u26a0\ufe0f  websockets < 10.0 detectado - Funcionalidades limitadas\")\r\n    except ImportError:\r\n        print(\"\u2139\ufe0f  websockets n\u00e3o instalado - Funcionalidades limitadas\")\r\n\r\n# Executar verifica\u00e7\u00e3o de compatibilidade\r\ncheck_python_compatibility()\r\n```\r\n\r\n#### **Teste de compatibilidade**\r\n```bash\r\n# Testar compatibilidade completa\r\npww test compatibility\r\n\r\n# Verificar vers\u00f5es instaladas\r\npww version --all\r\n\r\n# Teste de conectividade\r\npww test connectivity --sidecar --websocket --storage\r\n```\r\n\r\n**Resultado da verifica\u00e7\u00e3o (v0.5.1):**\r\n```\r\n\ud83d\udd0d Verifica\u00e7\u00e3o de Compatibilidade PyWhatsWeb v0.5.1\r\n==================================================\r\n\r\n\u2705 Node.js: v18.17.0 (requerido: 18.0.0+)\r\n\u2705 whatsapp-web.js: v1.23.0 (requerido: 1.23.0+)\r\n\u2705 Python: v3.13.0 (requerido: 3.8+, recomendado: 3.13+)\r\n\u2705 Sidecar: v0.5.1 (requerido: v0.5.1+)\r\n\u2705 Puppeteer: v21.0.0 (requerido: 21.0.0+)\r\n\r\n\ud83c\udf10 Conectividade:\r\n\u2705 Sidecar HTTP: http://localhost:3000\r\n\u2705 Sidecar WebSocket: ws://localhost:3001\r\n\u2705 Storage: FileSystem (./whatsapp_data)\r\n\r\n\ud83c\udfaf Status: COMPAT\u00cdVEL \u2705\r\n\ud83c\udfaf Python 3.13: SUPORTE COMPLETO \u2705\r\n\ud83c\udfaf Websockets 15.0+: SUPORTE COMPLETO \u2705\r\n\ud83c\udfaf Dataclasses: SUPORTE COMPLETO \u2705\r\n```\r\n\r\n**Autentica\u00e7\u00e3o WebSocket obrigat\u00f3ria:**\r\n```javascript\r\n// Token obrigat\u00f3rio na conex\u00e3o\r\nconst wss = new WebSocket.Server({ \r\n    port: WS_PORT,\r\n    verifyClient: (info) => {\r\n        const token = info.req.headers['authorization'] || \r\n                     new URL(info.req.url, 'http://localhost').searchParams.get('token');\r\n        \r\n        if (!token || token !== `Bearer ${API_KEY}`) {\r\n            return false; // Conex\u00e3o rejeitada\r\n        }\r\n        \r\n        // Suporte a multi-tenant\r\n        const tenantId = info.req.headers['x-tenant-id'] || \r\n                        new URL(info.req.url, 'http://localhost').searchParams.get('tenant_id');\r\n        \r\n        if (tenantId) {\r\n            info.req.tenantId = tenantId;\r\n        }\r\n        \r\n        return true;\r\n    }\r\n});\r\n```\r\n\r\n**Sistema anti-loop:**\r\n```javascript\r\nclient.on('message', (message) => {\r\n    // Marcar origem da mensagem para evitar loops\r\n    const messageOrigin = 'inbound'; // Mensagem recebida do WhatsApp\r\n    const isFromSelf = message.fromMe;\r\n    \r\n    broadcastEvent('message', {\r\n        // ... outros campos\r\n        origin: messageOrigin,           // 'inbound' ou 'outbound'\r\n        fromSelf: isFromSelf,            // true se enviada pelo pr\u00f3prio usu\u00e1rio\r\n        correlationId: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\r\n    });\r\n});\r\n```\r\n```javascript\r\n// API REST endpoints\r\napp.post('/api/session/:id/start', startSession);\r\napp.post('/api/session/:id/stop', stopSession);\r\napp.get('/api/session/:id/status', getSessionStatus);\r\napp.post('/api/session/:id/send-message', sendMessage);\r\n\r\n// Health check e m\u00e9tricas\r\napp.get('/health', healthCheck);\r\napp.get('/metrics', getMetrics);\r\n\r\n// WebSocket events\r\nws.on('message', (data) => {\r\n  // Broadcast: qr, authenticated, ready, message, disconnected\r\n});\r\n```\r\n\r\n**Endpoints dispon\u00edveis:**\r\n- `GET /health` - Health check (sem autentica\u00e7\u00e3o)\r\n- `GET /metrics` - M\u00e9tricas Prometheus (requer API key)\r\n- `GET /metrics.json` - M\u00e9tricas JSON (requer API key)\r\n- `POST /api/session/:id/start` - Inicia sess\u00e3o\r\n- `POST /api/session/:id/stop` - Para sess\u00e3o\r\n- `GET /api/session/:id/status` - Status da sess\u00e3o\r\n- `POST /api/session/:id/send-message` - Envia mensagem\r\n\r\n**Eventos WebSocket:**\r\n- `qr`: QR Code para autentica\u00e7\u00e3o\r\n- `authenticated`: Autentica\u00e7\u00e3o bem-sucedida\r\n- `ready`: WhatsApp pronto\r\n- `message`: Nova mensagem\r\n- `disconnected`: Desconex\u00e3o\r\n\r\n**Funcionalidades de seguran\u00e7a:**\r\n- **Helmet**: Headers de seguran\u00e7a HTTP\r\n- **CORS**: Controle de origens configur\u00e1vel\r\n- **Rate Limiting**: 100 req/15min por IP\r\n- **API Key**: Autentica\u00e7\u00e3o obrigat\u00f3ria para todas as opera\u00e7\u00f5es\r\n- **WebSocket Auth**: Token obrigat\u00f3rio na conex\u00e3o\r\n- **Multi-tenant**: Isolamento por tenant_id\r\n- **Logging**: Com correlation ID e tenant ID para auditoria\r\n\r\n### **\ud83d\udcc2 `sidecar/` - DOCKER E ORQUESTRA\u00c7\u00c3O**\r\n\r\n#### **`Dockerfile` - Container otimizado**\r\n```dockerfile\r\n# Base Node.js 18 Alpine\r\nFROM node:18-alpine\r\n\r\n# Depend\u00eancias do Puppeteer\r\nRUN apk add --no-cache chromium nss freetype freetype-dev harfbuzz ca-certificates ttf-freefont\r\n\r\n# Vari\u00e1veis de ambiente para Puppeteer\r\nENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \\\r\n    PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser \\\r\n    PUPPETEER_ARGS=\"--no-sandbox --disable-setuid-sandbox --disable-dev-shm-usage --disable-accelerated-2d-canvas --no-first-run --no-zygote --disable-gpu\"\r\n\r\n# Usu\u00e1rio n\u00e3o-root para seguran\u00e7a\r\nUSER node\r\n\r\n# Health check autom\u00e1tico\r\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\r\n    CMD node -e \"require('http').get('http://localhost:3000/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })\"\r\n```\r\n\r\n#### **`docker-compose.yml` - Orquestra\u00e7\u00e3o completa**\r\n```yaml\r\nservices:\r\n  # Sidecar principal\r\n  pywhatsweb-sidecar:\r\n    build: ./sidecar\r\n    ports: [\"3000:3000\", \"3001:3001\"]\r\n    environment:\r\n      - API_KEY=${WHATSAPP_API_KEY}\r\n      - ALLOWED_ORIGINS=${ALLOWED_ORIGINS}\r\n    healthcheck:\r\n      test: [\"CMD\", \"node\", \"-e\", \"require('http').get('http://localhost:3000/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })\"]\r\n      interval: 30s\r\n      timeout: 10s\r\n      retries: 3\r\n\r\n  # Prometheus para m\u00e9tricas\r\n  prometheus:\r\n    image: prom/prometheus:latest\r\n    ports: [\"9090:9090\"]\r\n    volumes: [\"./prometheus:/etc/prometheus\"]\r\n\r\n  # Grafana para visualiza\u00e7\u00e3o\r\n  grafana:\r\n    image: grafana/grafana:latest\r\n    ports: [\"3002:3000\"]\r\n    environment:\r\n      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}\r\n```\r\n\r\n### **\ud83d\udcc2 `examples/` - EXEMPLOS DE USO**\r\n\r\n### **\ud83d\udcc2 `RUNBOOKS.md` - OPERA\u00c7\u00c3O EM PRODU\u00c7\u00c3O**\r\n\r\n#### **Cen\u00e1rios cr\u00edticos documentados:**\r\n- **Sess\u00e3o expirada**: QR n\u00e3o aparece, mensagens n\u00e3o enviam\r\n- **Autentica\u00e7\u00e3o 2FA**: QR escaneado mas n\u00e3o autentica\r\n- **Ban/limites WhatsApp**: Mensagens n\u00e3o entregues\r\n- **Sem QR Code**: Evento n\u00e3o disparado, Puppeteer com erro\r\n- **M\u00eddia falhou**: Upload falha, arquivo muito grande\r\n- **WebSocket desconectado**: Eventos n\u00e3o chegam\r\n\r\n#### **Procedimentos de manuten\u00e7\u00e3o:**\r\n```bash\r\n# Backup de sess\u00f5es\r\ncurl -X POST -H \"Authorization: Bearer ${API_KEY}\" \\\r\n     http://localhost:3000/api/sessions/stop-all\r\n\r\n# Atualiza\u00e7\u00e3o do sidecar\r\ndocker-compose build pywhatsweb-sidecar\r\ndocker-compose up -d pywhatsweb-sidecar\r\n\r\n# Limpeza de dados antigos\r\nfind ./whatsapp_data -name \"*.json\" -mtime +30 -delete\r\n```\r\n\r\n#### **Monitoramento e alertas:**\r\n```bash\r\n# Health check autom\u00e1tico\r\ncurl -f http://localhost:3000/health || echo \"SIDECAR DOWN\"\r\n\r\n# Verificar sess\u00f5es ativas\r\nACTIVE_SESSIONS=$(curl -s -H \"Authorization: Bearer ${API_KEY}\" \\\r\n    http://localhost:3000/metrics | jq -r '.sessions.active')\r\n\r\nif [ \"$ACTIVE_SESSIONS\" -eq 0 ]; then\r\n    echo \"ALERTA: Nenhuma sess\u00e3o ativa!\"\r\nfi\r\n```\r\n\r\n#### **`basic_usage.py` - Uso b\u00e1sico**\r\n```python\r\nfrom pywhatsweb import WhatsWebManager, FileSystemStore\r\n\r\n# Criar manager\r\nmanager = WhatsWebManager(\r\n    sidecar_host=\"localhost\",\r\n    sidecar_port=3000,\r\n    api_key=\"sua-api-key\"\r\n)\r\n\r\n# Criar sess\u00e3o\r\nsession = manager.create_session(\"sessao_teste\")\r\n\r\n# Configurar eventos\r\n@session.on(\"qr\")\r\ndef on_qr(data):\r\n    print(f\"QR Code: {data['qr']}\")\r\n\r\n@session.on(\"message\")\r\ndef on_message(data):\r\n    print(f\"Nova mensagem: {data['body']}\")\r\n\r\n# Iniciar sess\u00e3o\r\nsession.start()\r\n\r\n# Enviar mensagem\r\nsession.send_text(\"5511999999999\", \"Ol\u00e1!\")\r\n```\r\n\r\n#### **`django_complete_example.py` - Exemplo Django completo**\r\n\r\n##### **View Django com template completo**\r\n```python\r\n# views.py - Views Django para WhatsApp\r\nfrom django.views.generic import TemplateView\r\nfrom django.http import JsonResponse\r\nfrom pywhatsweb import WhatsWebManager, DjangoORMStore\r\n\r\nclass WhatsAppDashboardView(TemplateView):\r\n    template_name = 'whatsapp/dashboard.html'\r\n    \r\n    def get_context_data(self, **kwargs):\r\n        # Inicializar manager e configurar models Django\r\n        manager = WhatsWebManager(\r\n            sidecar_host=settings.WHATSAPP_SIDECAR_HOST,\r\n            sidecar_port=settings.WHATSAPP_SIDECAR_PORT,\r\n            api_key=settings.WHATSAPP_API_KEY,\r\n            storage=DjangoORMStore()\r\n        )\r\n        \r\n        # Configurar models Django\r\n        manager.storage.set_models(\r\n            session_model=WhatsAppSession,\r\n            message_model=WhatsAppMessage,\r\n            contact_model=WhatsAppContact\r\n        )\r\n        \r\n        # Buscar sess\u00f5es ativas\r\n        active_sessions = manager.get_active_sessions()\r\n        \r\n        context = super().get_context_data(**kwargs)\r\n        context['active_sessions'] = active_sessions\r\n        context['manager'] = manager\r\n        return context\r\n\r\n# API para enviar mensagens\r\ndef send_message_api(request):\r\n    if request.method == 'POST':\r\n        session_id = request.POST.get('session_id')\r\n        to = request.POST.get('to')\r\n        text = request.POST.get('text')\r\n        \r\n        manager = WhatsWebManager()\r\n        session = manager.get_session(session_id)\r\n        \r\n        try:\r\n            message_id = session.send_text(to, text)\r\n            return JsonResponse({'success': True, 'message_id': message_id})\r\n        except Exception as e:\r\n            return JsonResponse({'success': False, 'error': str(e)})\r\n```\r\n\r\n##### **Template HTML com QR Code e JavaScript**\r\n```html\r\n<!-- whatsapp/dashboard.html -->\r\n{% extends 'base.html' %}\r\n\r\n{% block content %}\r\n<div class=\"whatsapp-dashboard\">\r\n    <h1>Dashboard WhatsApp</h1>\r\n    \r\n    <!-- Lista de sess\u00f5es -->\r\n    <div class=\"sessions-list\">\r\n        {% for session in active_sessions %}\r\n        <div class=\"session-card\" data-session-id=\"{{ session.session_id }}\">\r\n            <h3>Sess\u00e3o: {{ session.session_id }}</h3>\r\n            <div class=\"session-status\">\r\n                Status: <span class=\"status-{{ session.status }}\">{{ session.status }}</span>\r\n            </div>\r\n            \r\n            <!-- Container do QR Code -->\r\n            <div class=\"qr-container\" id=\"qr-{{ session.session_id }}\">\r\n                <img id=\"qr-code-{{ session.session_id }}\" src=\"\" alt=\"QR Code WhatsApp\" style=\"display: none;\">\r\n                <div id=\"qr-status-{{ session.session_id }}\">Aguardando QR Code...</div>\r\n            </div>\r\n            \r\n            <!-- Controles da sess\u00e3o -->\r\n            <div class=\"session-controls\">\r\n                <button onclick=\"startSession('{{ session.session_id }}')\">Iniciar</button>\r\n                <button onclick=\"stopSession('{{ session.session_id }}')\">Parar</button>\r\n                <button onclick=\"showQR('{{ session.session_id }}')\">Mostrar QR</button>\r\n            </div>\r\n            \r\n            <!-- Envio de mensagens -->\r\n            <div class=\"message-form\">\r\n                <input type=\"text\" id=\"to-{{ session.session_id }}\" placeholder=\"N\u00famero (ex: 5511999999999)\">\r\n                <input type=\"text\" id=\"text-{{ session.session_id }}\" placeholder=\"Mensagem\">\r\n                <button onclick=\"sendMessage('{{ session.session_id }}')\">Enviar</button>\r\n            </div>\r\n        </div>\r\n        {% endfor %}\r\n    </div>\r\n</div>\r\n\r\n<script>\r\n// WebSocket para receber eventos WhatsApp\r\nconst ws = new WebSocket('ws://localhost:8000/ws/whatsapp/');\r\n\r\nws.onmessage = function(e) {\r\n    const data = JSON.parse(e.data);\r\n    const sessionId = data.session_id;\r\n    \r\n    if (data.type === 'qr') {\r\n        // Mostrar QR Code\r\n        const qrImg = document.getElementById(`qr-code-${sessionId}`);\r\n        const qrStatus = document.getElementById(`qr-status-${sessionId}`);\r\n        \r\n        qrImg.src = data.qr;\r\n        qrImg.style.display = 'block';\r\n        qrStatus.textContent = 'Escaneie o QR Code';\r\n        \r\n    } else if (data.type === 'ready') {\r\n        // WhatsApp conectado\r\n        const qrImg = document.getElementById(`qr-code-${sessionId}`);\r\n        const qrStatus = document.getElementById(`qr-status-${sessionId}`);\r\n        \r\n        qrImg.style.display = 'none';\r\n        qrStatus.textContent = 'WhatsApp conectado!';\r\n        \r\n    } else if (data.type === 'message') {\r\n        // Nova mensagem recebida\r\n        console.log('Nova mensagem:', data);\r\n        // Aqui voc\u00ea pode atualizar a interface\r\n    }\r\n};\r\n\r\n// Fun\u00e7\u00f5es para controlar sess\u00f5es\r\nfunction startSession(sessionId) {\r\n    fetch(`/whatsapp/session/${sessionId}/start/`, {method: 'POST'})\r\n        .then(response => response.json())\r\n        .then(data => console.log('Sess\u00e3o iniciada:', data));\r\n}\r\n\r\nfunction stopSession(sessionId) {\r\n    fetch(`/whatsapp/session/${sessionId}/stop/`, {method: 'POST'})\r\n        .then(response => response.json())\r\n        .then(data => console.log('Sess\u00e3o parada:', data));\r\n}\r\n\r\nfunction sendMessage(sessionId) {\r\n    const to = document.getElementById(`to-${sessionId}`).value;\r\n    const text = document.getElementById(`text-${sessionId}`).value;\r\n    \r\n    fetch('/whatsapp/send-message/', {\r\n        method: 'POST',\r\n        headers: {'Content-Type': 'application/x-www-form-urlencoded'},\r\n        body: `session_id=${sessionId}&to=${to}&text=${text}`\r\n    })\r\n    .then(response => response.json())\r\n    .then(data => {\r\n        if (data.success) {\r\n            console.log('Mensagem enviada:', data.message_id);\r\n        } else {\r\n            console.error('Erro ao enviar:', data.error);\r\n        }\r\n    });\r\n}\r\n</script>\r\n{% endblock %}\r\n```\r\n\r\n##### **Consumer WebSocket Django Channels**\r\n```python\r\n# consumers.py - Consumer WebSocket para Django Channels\r\nimport json\r\nfrom channels.generic.websocket import AsyncWebsocketConsumer\r\nfrom pywhatsweb import WhatsWebManager\r\n\r\nclass WhatsAppWebSocketConsumer(AsyncWebsocketConsumer):\r\n    async def connect(self):\r\n        await self.accept()\r\n        print(\"Cliente WebSocket conectado\")\r\n        \r\n        # Conectar ao WebSocket da sess\u00e3o WhatsApp\r\n        self.whatsapp_manager = WhatsWebManager()\r\n        \r\n    async def disconnect(self, close_code):\r\n        print(f\"Cliente WebSocket desconectado: {close_code}\")\r\n        \r\n    async def receive(self, text_data):\r\n        # Processar mensagens do cliente\r\n        data = json.loads(text_data)\r\n        \r\n        if data['action'] == 'send_message':\r\n            session_id = data['session_id']\r\n            to = data['to']\r\n            text = data['text']\r\n            \r\n            try:\r\n                session = self.whatsapp_manager.get_session(session_id)\r\n                message_id = await session.send_text(to, text)\r\n                \r\n                # Confirmar envio para o cliente\r\n                await self.send(text_data=json.dumps({\r\n                    'type': 'message_sent',\r\n                    'message_id': message_id,\r\n                    'to': to\r\n                }))\r\n                \r\n            except Exception as e:\r\n                await self.send(text_data=json.dumps({\r\n                    'type': 'error',\r\n                    'error': str(e)\r\n                }))\r\n                \r\n    async def whatsapp_event(self, event):\r\n        # Enviar eventos WhatsApp para o cliente\r\n        await self.send(text_data=json.dumps({\r\n            'type': event['event_type'],\r\n            'session_id': event['session_id'],\r\n            'data': event['data']\r\n        }))\r\n```\r\n\r\n**Funcionalidades do exemplo Django:**\r\n- \u2705 Dashboard completo com sess\u00f5es\r\n- \u2705 QR Code em tempo real com template HTML\r\n- \u2705 Sistema Kanban (NEW \u2192 ACTIVE \u2192 DONE)\r\n- \u2705 Envio de mensagens via API\r\n- \u2705 WebSocket para eventos em tempo real\r\n- \u2705 Template HTML responsivo com JavaScript\r\n- \u2705 Consumer WebSocket funcional\r\n- \u2705 Integra\u00e7\u00e3o completa com models Django\r\n\r\n### **\ud83d\udcc2 `tests/` - TESTES AUTOMATIZADOS**\r\n\r\n#### **`test_imports.py` - Teste de imports**\r\n```python\r\ndef test_imports():\r\n    # Testa se todas as classes podem ser importadas\r\n    from pywhatsweb import WhatsWebManager, Session\r\n    from pywhatsweb import FileSystemStore, DjangoORMStore\r\n\r\ndef test_instanciacao():\r\n    # Testa se as classes podem ser instanciadas\r\n    manager = WhatsWebManager()\r\n    storage = FileSystemStore(\"./test_data\")\r\n```\r\n\r\n---\r\n\r\n## \ud83d\ude80 **COMO USAR A BIBLIOTECA**\r\n\r\n### **1. INSTALA\u00c7\u00c3O**\r\n\r\n```bash\r\n# Clonar reposit\u00f3rio\r\ngit clone <repo>\r\ncd pywhatsweb-lib\r\n\r\n# Instalar depend\u00eancias Python\r\npip install -r requirements.txt\r\n\r\n# Instalar depend\u00eancias Node.js\r\ncd sidecar\r\nnpm install\r\n```\r\n\r\n### **2. CONFIGURA\u00c7\u00c3O**\r\n\r\n#### **Configurar sidecar**\r\n```bash\r\ncd sidecar\r\ncp env.example .env\r\n# Editar .env com suas configura\u00e7\u00f5es\r\nnpm start\r\n```\r\n\r\n#### **Configurar Python**\r\n```python\r\nfrom pywhatsweb import WhatsWebManager, FileSystemStore\r\n\r\nmanager = WhatsWebManager(\r\n    sidecar_host=\"localhost\",      # Host do sidecar\r\n    sidecar_port=3000,            # Porta HTTP\r\n    sidecar_ws_port=3001,         # Porta WebSocket\r\n    api_key=\"sua-api-key\",        # Chave de API\r\n    storage=FileSystemStore(\"./whatsapp_data\")  # Storage\r\n)\r\n```\r\n\r\n### **3. USO B\u00c1SICO**\r\n\r\n```python\r\n# Criar sess\u00e3o\r\nsession = manager.create_session(\"sessao_123\")\r\n\r\n# Configurar eventos\r\n@session.on(\"qr\")\r\ndef on_qr(data):\r\n    # Renderizar QR no template Django/Flask\r\n    qr_data_url = data['qr']\r\n    # <img src=\"{{ qr_data_url }}\">\r\n\r\n@session.on(\"ready\")\r\ndef on_ready(data):\r\n    print(\"WhatsApp est\u00e1 pronto!\")\r\n\r\n@session.on(\"message\")\r\ndef on_message(data):\r\n    # Processar mensagem recebida\r\n    sender = data['from']\r\n    content = data['body']\r\n    \r\n    # Auto-resposta\r\n    if \"oi\" in content.lower():\r\n        session.send_text(sender, \"Oi! Como posso ajudar?\")\r\n\r\n# Iniciar sess\u00e3o\r\nsession.start()\r\n```\r\n\r\n### **4. M\u00daLTIPLAS SESS\u00d5ES COM MULTI-TENANT**\r\n\r\n```python\r\n# Criar m\u00faltiplas sess\u00f5es com tenant\r\nsessao1 = manager.create_session(\"sessao_1\", tenant_id=\"empresa_a\")\r\nsessao2 = manager.create_session(\"sessao_2\", tenant_id=\"empresa_b\")\r\n\r\n# Cada sess\u00e3o \u00e9 independente e isolada por tenant\r\nsessao1.start()\r\nsessao2.start()\r\n\r\n# Listar sess\u00f5es ativas por tenant\r\nactive_sessions = manager.get_active_sessions(tenant_id=\"empresa_a\")\r\nprint(f\"Sess\u00f5es ativas empresa A: {active_sessions}\")\r\n```\r\n\r\n### **5. VALIDA\u00c7\u00c3O E NORMALIZA\u00c7\u00c3O**\r\n\r\n```python\r\n# Criar m\u00faltiplas sess\u00f5es\r\nsessao1 = manager.create_session(\"sessao_1\", phone_number=\"5511999999999\")\r\nsessao2 = manager.create_session(\"sessao_2\", phone_number=\"5511888888888\")\r\n\r\n# Cada sess\u00e3o \u00e9 independente\r\nsessao1.start()\r\nsessao2.start()\r\n\r\n# Listar sess\u00f5es ativas\r\nactive_sessions = manager.get_active_sessions()\r\nprint(f\"Sess\u00f5es ativas: {active_sessions}\")\r\n```\r\n\r\n### **6. ENVIO DE MENSAGENS COM VALIDA\u00c7\u00c3O**\r\n\r\n```python\r\n# Texto\r\nmessage_id = session.send_text(\"5511999999999\", \"Ol\u00e1! Como vai?\")\r\n\r\n# M\u00eddia\r\nmessage_id = session.send_media(\r\n    to=\"5511999999999\",\r\n    media_path=\"./imagem.jpg\",\r\n    caption=\"Veja esta imagem!\"\r\n)\r\n\r\n# Verificar status\r\nif session.is_active():\r\n    print(\"Sess\u00e3o est\u00e1 ativa e pronta\")\r\n```\r\n\r\n### **7. \ud83d\uddc3\ufe0f STORAGE E PERSIST\u00caNCIA AVAN\u00c7ADA**\r\n\r\n#### **Storage pluggable com m\u00faltiplas op\u00e7\u00f5es**\r\n```python\r\n# FileSystem (padr\u00e3o) - armazena em JSON\r\nfrom pywhatsweb import FileSystemStore\r\nstorage = FileSystemStore(\"./whatsapp_data\")\r\n\r\n# Django ORM (opcional) - integra\u00e7\u00e3o com banco de dados\r\nfrom pywhatsweb import DjangoORMStore\r\nstorage = DjangoORMStore()\r\n\r\n# Redis (futuro) - para alta performance\r\n# from pywhatsweb import RedisStore\r\n# storage = RedisStore(redis_url=\"redis://localhost:6379\")\r\n\r\n# PostgreSQL (futuro) - para dados estruturados\r\n# from pywhatsweb import PostgreSQLStore\r\n# storage = PostgreSQLStore(connection_string=\"postgresql://...\")\r\n```\r\n\r\n#### **Configura\u00e7\u00e3o Django ORM com models + migrations**\r\n```python\r\n# models.py - Models Django para WhatsApp\r\nfrom django.db import models\r\nfrom pywhatsweb import KanbanStatus, MessageType\r\n\r\nclass WhatsAppSession(models.Model):\r\n    session_id = models.CharField(max_length=100, unique=True)\r\n    tenant_id = models.CharField(max_length=50, null=True)\r\n    status = models.CharField(max_length=20, choices=KanbanStatus.choices())\r\n    phone_number = models.CharField(max_length=20, null=True)\r\n    created_at = models.DateTimeField(auto_now_add=True)\r\n    updated_at = models.DateTimeField(auto_now=True)\r\n\r\nclass WhatsAppMessage(models.Model):\r\n    message_id = models.CharField(max_length=100, unique=True)\r\n    session = models.ForeignKey(WhatsAppSession, on_delete=models.CASCADE)\r\n    content = models.TextField()\r\n    sender = models.CharField(max_length=20)\r\n    recipient = models.CharField(max_length=20)\r\n    message_type = models.CharField(max_length=20, choices=MessageType.choices())\r\n    status = models.CharField(max_length=20)\r\n    trace_id = models.CharField(max_length=100)\r\n    created_at = models.DateTimeField(auto_now_add=True)\r\n\r\n# Configurar storage\r\nstorage.set_models(\r\n    session_model=WhatsAppSession,\r\n    message_model=WhatsAppMessage,\r\n    contact_model=WhatsAppContact,\r\n    chat_model=WhatsAppChat\r\n)\r\n```\r\n\r\n### **\ud83d\udcc1 PIPELINE DE M\u00cdDIA ROBUSTO**\r\n\r\n#### **Valida\u00e7\u00e3o e processamento de m\u00eddia**\r\n```python\r\n# Configura\u00e7\u00f5es de m\u00eddia\r\nMEDIA_CONFIG = {\r\n    'max_size': 16 * 1024 * 1024,  # 16MB (limite WhatsApp)\r\n    'allowed_types': ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],\r\n    'timeout': 300,  # 5 minutos para upload\r\n    'retry_count': 3,\r\n    'storage_backend': 'local'  # 'local', 's3', 'minio'\r\n}\r\n\r\n# Envio com valida\u00e7\u00e3o autom\u00e1tica\r\ntry:\r\n    message_id = session.send_media(\r\n        to=\"5511999999999\",\r\n        media_path=\"./imagem.jpg\",\r\n        caption=\"Veja esta imagem!\",\r\n        validate_media=True,  # Valida\u00e7\u00e3o autom\u00e1tica\r\n        compress_if_needed=True  # Compress\u00e3o se necess\u00e1rio\r\n    )\r\nexcept MediaTooLargeError:\r\n    print(\"Arquivo muito grande, comprimindo...\")\r\n    compressed_path = compress_image(\"./imagem.jpg\")\r\n    message_id = session.send_media(to=\"5511999999999\", media_path=compressed_path)\r\n```\r\n\r\n#### **Storage de m\u00eddia configur\u00e1vel**\r\n```python\r\n# Configurar storage de m\u00eddia\r\nmanager = WhatsWebManager(\r\n    media_storage={\r\n        'backend': 's3',  # 'local', 's3', 'minio'\r\n        'bucket': 'whatsapp-media',\r\n        'region': 'us-east-1',\r\n        'retention_days': 30,  # Reten\u00e7\u00e3o autom\u00e1tica\r\n        'encryption': True,  # Criptografia em repouso\r\n        'cdn_enabled': True  # CDN para entrega r\u00e1pida\r\n    }\r\n)\r\n\r\n# Upload para S3/MinIO\r\nmedia_url = session.upload_media_to_storage(\r\n    file_path=\"./imagem.jpg\",\r\n    mime_type=\"image/jpeg\",\r\n    metadata={'session_id': 'sessao_123'}\r\n)\r\n```\r\n\r\n### **\ud83d\udd12 POL\u00cdTICA LGPD E RETEN\u00c7\u00c3O**\r\n\r\n#### **Configura\u00e7\u00f5es de reten\u00e7\u00e3o e privacidade**\r\n```python\r\n# Configurar pol\u00edtica LGPD\r\nmanager = WhatsWebManager(\r\n    lgpd_compliance={\r\n        'data_retention_days': 90,  # Reten\u00e7\u00e3o de mensagens\r\n        'media_retention_days': 30,  # Reten\u00e7\u00e3o de m\u00eddia\r\n        'log_redaction': True,  # Reda\u00e7\u00e3o de dados sens\u00edveis\r\n        'media_encryption': True,  # Criptografia de anexos\r\n        'audit_trail': True,  # Rastreamento de a\u00e7\u00f5es\r\n        'right_to_forget': True,  # Direito ao esquecimento\r\n        'data_export': True  # Exporta\u00e7\u00e3o de dados\r\n    }\r\n)\r\n\r\n# Excluir dados de um usu\u00e1rio\r\nstorage.delete_user_data(\r\n    phone_number=\"5511999999999\",\r\n    reason=\"direito_ao_esquecimento\",\r\n    audit_user=\"admin\"\r\n)\r\n\r\n# Exportar dados para LGPD\r\nuser_data = storage.export_user_data(\"5511999999999\")\r\n# Retorna JSON com todas as mensagens, contatos, etc.\r\n```\r\n\r\n#### **Compliance e auditoria**\r\n```python\r\n# Logs sem conte\u00fado de mensagem (apenas metadados)\r\n# [2024-12-19 10:30:00] [corr:req_456] [tenant:empresa_a] Mensagem enviada: ID=msg_123, Para=5511999999999, Tipo=texto\r\n\r\n# Criptografia AES-256 em repouso para m\u00eddia\r\n# Chaves gerenciadas por KMS ou vari\u00e1veis de ambiente\r\n\r\n# Rastreamento completo de acesso e modifica\u00e7\u00f5es\r\naudit_log = storage.get_audit_log(\r\n    user_id=\"5511999999999\",\r\n    start_date=\"2024-12-01\",\r\n    end_date=\"2024-12-19\"\r\n)\r\n```\r\n\r\n---\r\n\r\n## \ud83d\udd27 **FUNCIONALIDADES AVAN\u00c7ADAS**\r\n\r\n### **\ud83e\uddf1 SISTEMA KANBAN COM FLUXO INTELIGENTE**\r\n\r\n#### **Estados do fluxo Kanban**\r\n```python\r\nfrom pywhatsweb import KanbanStatus\r\n\r\n# Criar chat com status\r\nchat = Chat(\r\n    chat_id=\"5511999999999\",\r\n    status=KanbanStatus.NEW\r\n)\r\n\r\n# Atribuir para atendente\r\nchat.assign_to(\"atendente_123\", \"sistema\")\r\n# Status muda para ACTIVE\r\n\r\n# Marcar como conclu\u00eddo\r\nchat.mark_as_done(\"atendente_123\")\r\n# Status muda para DONE\r\n\r\n# Reabrir conversa\r\nchat.reopen(\"sistema\")\r\n# Status volta para NEW\r\n```\r\n\r\n#### **Pol\u00edticas autom\u00e1ticas recomendadas**\r\n```python\r\n# Auto-NEW em mensagem nova\r\n@session.on(\"message\")\r\ndef on_message(data):\r\n    if data['origin'] == 'inbound':\r\n        chat = storage.get_or_create_chat(data['from'])\r\n        if chat.status == KanbanStatus.DONE:\r\n            # Cliente respondeu ap\u00f3s conclus\u00e3o, reabrir\r\n            chat.reopen(\"sistema\", reason=\"cliente_respondeu\")\r\n            storage.save_chat(chat)\r\n\r\n# Auto-DONE ap\u00f3s N horas de inatividade\r\ndef auto_close_inactive_chats():\r\n    from datetime import timedelta\r\n    \r\n    active_chats = storage.get_chats_by_status(KanbanStatus.ACTIVE)\r\n    cutoff_time = datetime.now() - timedelta(hours=24)\r\n    \r\n    for chat in active_chats:\r\n        if chat.last_message_at < cutoff_time:\r\n            chat.mark_as_done(\"sistema\", reason=\"inatividade_24h\")\r\n            storage.save_chat(chat)\r\n```\r\n\r\n### **\ud83d\udcf1 NORMALIZA\u00c7\u00c3O E VALIDA\u00c7\u00c3O DE N\u00daMEROS**\r\n\r\n#### **Utilit\u00e1rio E.164 com phonenumbers**\r\n```python\r\nfrom pywhatsweb.utils import normalize_phone_number, validate_phone_number\r\n\r\n# Normaliza\u00e7\u00e3o autom\u00e1tica para formato E.164\r\nphone = normalize_phone_number(\"11999999999\")  # +5511999999999\r\nphone = normalize_phone_number(\"(11) 99999-9999\")  # +5511999999999\r\nphone = normalize_phone_number(\"+55 11 99999 9999\")  # +5511999999999\r\n\r\n# Valida\u00e7\u00e3o completa\r\nis_valid, normalized, country_code, region = validate_phone_number(\"11999999999\")\r\n# (True, \"+5511999999999\", 55, \"BR\")\r\n\r\n# Informa\u00e7\u00f5es detalhadas do n\u00famero\r\ninfo = get_phone_info(\"+5511999999999\")\r\n# {\r\n#   'number': '+5511999999999',\r\n#   'country_code': 55,\r\n#   'region': 'BR',\r\n#   'carrier': 'Vivo',\r\n#   'timezone': 'America/Sao_Paulo',\r\n#   'is_valid': True,\r\n#   'is_mobile': True\r\n# }\r\n```\r\n\r\n#### **Formata\u00e7\u00e3o para exibi\u00e7\u00e3o**\r\n```python\r\n# Formata\u00e7\u00e3o para diferentes regi\u00f5es\r\ndisplay_national = format_phone_for_display(\"+5511999999999\", \"NATIONAL\")   # (11) 99999-9999\r\ndisplay_international = format_phone_for_display(\"+5511999999999\", \"INTERNATIONAL\")  # +55 11 99999-9999\r\ndisplay_e164 = format_phone_for_display(\"+5511999999999\", \"E164\")  # +5511999999999\r\n```\r\n\r\n### **Context Manager e Tratamento de Erros**\r\n\r\n#### **Context Manager**\r\n```python\r\n# Usar como context manager\r\nwith WhatsWebManager() as manager:\r\n    session = manager.create_session(\"test\")\r\n    session.start()\r\n    # ... usar sess\u00e3o\r\n    # Cleanup autom\u00e1tico ao sair\r\n```\r\n\r\n### **Logging e Debug**\r\n```python\r\nimport logging\r\n\r\n# Configurar logging\r\nlogging.basicConfig(level=logging.DEBUG)\r\n\r\n# Logs autom\u00e1ticos em todas as opera\u00e7\u00f5es\r\nmanager = WhatsWebManager()\r\n# Logs: \"PyWhatsWeb Manager inicializado\", \"Sess\u00e3o criada\", etc.\r\n```\r\n\r\n### **\ud83d\udd04 RESILI\u00caNCIA E RECONEX\u00c3O**\r\n\r\n#### **Reconex\u00e3o autom\u00e1tica com backoff exponencial**\r\n```python\r\n# A sess\u00e3o reconecta automaticamente com backoff exponencial\r\n# Tentativa 1: 2s, Tentativa 2: 4s, Tentativa 3: 8s, etc.\r\n# M\u00e1ximo 5 tentativas\r\n\r\n@session.on(\"disconnected\")\r\ndef on_disconnected(data):\r\n    print(f\"Desconectado: {data['reason']}\")\r\n    # Reconex\u00e3o autom\u00e1tica em andamento\r\n\r\n@session.on(\"ready\")\r\ndef on_ready(data):\r\n    print(\"Reconectado e pronto!\")\r\n```\r\n\r\n#### **Heartbeat WebSocket para manter conex\u00f5es ativas**\r\n```python\r\n# Ping/pong autom\u00e1tico a cada 30 segundos\r\n# Se falhar 3 vezes consecutivas, reconecta automaticamente\r\n\r\n@session.on(\"heartbeat\")\r\ndef on_heartbeat(data):\r\n    print(f\"Heartbeat: {data['latency']}ms\")\r\n\r\n@session.on(\"heartbeat_failed\")\r\ndef on_heartbeat_failed(data):\r\n    print(\"Heartbeat falhou, reconectando...\")\r\n```\r\n\r\n### **\ud83d\udce8 IDEMPOT\u00caNCIA E DEDUPLICA\u00c7\u00c3O**\r\n\r\n#### **Sistema de idempot\u00eancia com chaves \u00fanicas**\r\n```python\r\n# Gerar chave de idempot\u00eancia \u00fanica\r\nmessage_id = session.send_text_with_idempotency(\r\n    to=\"5511999999999\",\r\n    text=\"Mensagem importante\",\r\n    idempotency_key=\"msg_123_v1\"  # Chave \u00fanica\r\n)\r\n\r\n# Verificar se mensagem j\u00e1 foi enviada\r\nif session.is_message_sent(\"msg_123_v1\"):\r\n    print(\"Mensagem j\u00e1 enviada, ignorando...\")\r\n```\r\n\r\n#### **Marcar origem da mensagem para evitar loops**\r\n```python\r\n# Sistema anti-loop autom\u00e1tico\r\n@session.on(\"message\")\r\ndef on_message(data):\r\n    # data['origin'] = 'inbound' (recebida) ou 'outbound' (enviada)\r\n    # data['fromSelf'] = True se enviada pelo pr\u00f3prio usu\u00e1rio\r\n    \r\n    if data['origin'] == 'inbound' and not data['fromSelf']:\r\n        # Processar mensagem recebida\r\n        process_incoming_message(data)\r\n    else:\r\n        # Ignorar mensagens pr\u00f3prias ou de sa\u00edda\r\n        print(\"Mensagem ignorada (loop prevention)\")\r\n```\r\n\r\n### **\ud83d\udcca ESTADOS DE ENTREGA E MONITORAMENTO**\r\n\r\n#### **Estados de envio/entrega quando suportado**\r\n```python\r\n# WhatsApp suporta alguns estados de entrega\r\n@session.on(\"message_status\")\r\ndef on_message_status(data):\r\n    if data['status'] == 'sent':\r\n        print(\"Mensagem enviada para servidor\")\r\n    elif data['status'] == 'delivered':\r\n        print(\"Mensagem entregue ao destinat\u00e1rio\")\r\n    elif data['status'] == 'read':\r\n        print(\"Mensagem lida pelo destinat\u00e1rio\")\r\n    elif data['status'] == 'failed':\r\n        print(f\"Mensagem falhou: {data['error']}\")\r\n```\r\n\r\n#### **Limites e timeouts de entrega**\r\n```python\r\n# Configura\u00e7\u00f5es de entrega\r\nMESSAGE_TIMEOUT = 60        # Timeout de envio (segundos)\r\nDELIVERY_TIMEOUT = 300      # Timeout de entrega (segundos)\r\nMAX_RETRIES = 3             # M\u00e1ximo de tentativas\r\nRETRY_DELAY = 5             # Delay entre tentativas (segundos)\r\n```\r\n\r\n@session.on(\"disconnected\")\r\ndef on_disconnected(data):\r\n    print(f\"Desconectado: {data['reason']}\")\r\n    # Reconex\u00e3o autom\u00e1tica em andamento\r\n\r\n@session.on(\"ready\")\r\ndef on_ready(data):\r\n    print(\"Reconectado e pronto!\")\r\n```\r\n\r\n---\r\n\r\n## \ud83d\udcca **STATUS E MONITORAMENTO**\r\n\r\n### **Informa\u00e7\u00f5es da Sess\u00e3o**\r\n```python\r\n# Status b\u00e1sico\r\nstatus = session.get_status()\r\nprint(f\"Status: {status.value}\")\r\n\r\n# Informa\u00e7\u00f5es detalhadas\r\ninfo = session.get_status_info()\r\nprint(f\"Conectado desde: {info['created_at']}\")\r\nprint(f\"\u00daltima atividade: {info['last_activity']}\")\r\nprint(f\"Autenticado: {info['is_authenticated']}\")\r\nprint(f\"WebSocket conectado: {info['ws_connected']}\")\r\nprint(f\"Tentativas de reconex\u00e3o: {info['reconnection_attempts']}\")\r\n```\r\n\r\n### **Informa\u00e7\u00f5es do Manager**\r\n```python\r\n# Listar todas as sess\u00f5es\r\nsessions = manager.list_sessions()\r\nprint(f\"Sess\u00f5es: {sessions}\")\r\n\r\n# Contar sess\u00f5es\r\ncount = manager.get_session_count()\r\nprint(f\"Total: {count}\")\r\n\r\n# Informa\u00e7\u00f5es do sidecar\r\nsidecar_info = manager.get_sidecar_info()\r\nprint(f\"Sidecar: {sidecar_info['base_url']}\")\r\n```\r\n\r\n### **\ud83d\udcca OBSERVABILIDADE E MONITORAMENTO**\r\n\r\n#### **Health Check e M\u00e9tricas**\r\n```bash\r\n# Health check b\u00e1sico\r\ncurl http://localhost:3000/health\r\n\r\n# M\u00e9tricas Prometheus (formato padr\u00e3o)\r\ncurl -H \"Authorization: Bearer sua-api-key\" http://localhost:3000/metrics\r\n\r\n# M\u00e9tricas JSON (para dashboards customizados)\r\ncurl -H \"Authorization: Bearer sua-api-key\" http://localhost:3000/metrics.json\r\n```\r\n\r\n#### **M\u00e9tricas Prometheus com histogramas e percentis**\r\n```python\r\n# M\u00e9tricas-chave dispon\u00edveis\r\nMETRICS = {\r\n    # Contadores\r\n    'messages_in_total': 'Total de mensagens recebidas',\r\n    'messages_out_total': 'Total de mensagens enviadas',\r\n    'reconnections_total': 'Total de reconex\u00f5es',\r\n    'errors_total': 'Total de erros por c\u00f3digo',\r\n    \r\n    # Gauges\r\n    'sessions_active': 'Sess\u00f5es ativas no momento',\r\n    'sessions_total': 'Total de sess\u00f5es criadas',\r\n    'websocket_connections': 'Conex\u00f5es WebSocket ativas',\r\n    \r\n    # Histogramas\r\n    'message_latency_seconds': 'Lat\u00eancia de envio (p50, p95, p99)',\r\n    'reconnection_delay_seconds': 'Delay de reconex\u00e3o',\r\n    'media_upload_duration_seconds': 'Dura\u00e7\u00e3o de upload de m\u00eddia'\r\n}\r\n\r\n# Exemplo de m\u00e9tricas Prometheus\r\n# whatsapp_messages_in_total{tenant=\"empresa_a\",session=\"sessao_123\"} 150\r\n# whatsapp_message_latency_seconds_bucket{le=\"0.1\"} 45\r\n# whatsapp_message_latency_seconds_bucket{le=\"0.5\"} 120\r\n# whatsapp_message_latency_seconds_bucket{le=\"1.0\"} 150\r\n```\r\n\r\n#### **Health checks por sess\u00e3o e componente**\r\n```python\r\n# Health check completo do sistema\r\nhealth_status = manager.get_health_status()\r\n# {\r\n#   'status': 'healthy',\r\n#   'timestamp': '2024-12-19T10:30:00.000Z',\r\n#   'uptime': 3600000,\r\n#   'components': {\r\n#     'sidecar': 'healthy',\r\n#     'websocket': 'healthy',\r\n#     'storage': 'healthy',\r\n#     'sessions': 'healthy'\r\n#   },\r\n#   'sessions': {\r\n#     'active': 2,\r\n#     'total': 5,\r\n#     'healthy': 2,\r\n#     'unhealthy': 0\r\n#   },\r\n#   'metrics': {\r\n#     'messagesIn': 150,\r\n#     'messagesOut': 120,\r\n#     'reconnections': 3,\r\n#     'errors': 1\r\n#   }\r\n# }\r\n\r\n# Health check de sess\u00e3o espec\u00edfica\r\nsession_health = session.get_health_status()\r\n# {\r\n#   'status': 'healthy',\r\n#   'websocket_connected': True,\r\n#   'last_heartbeat': '2024-12-19T10:29:45.000Z',\r\n#   'reconnection_attempts': 0,\r\n#   'message_queue_size': 0\r\n# }\r\n```\r\n\r\n#### **Alertas e monitoramento proativo**\r\n```python\r\n# Configurar alertas autom\u00e1ticos\r\nmanager.setup_alerts({\r\n    'max_reconnection_attempts': 5,\r\n    'max_message_latency_ms': 5000,\r\n    'min_active_sessions': 1,\r\n    'max_error_rate': 0.05  # 5% de erro\r\n})\r\n\r\n# Handler para alertas\r\n@manager.on(\"alert\")\r\ndef on_alert(alert_data):\r\n    if alert_data['type'] == 'high_latency':\r\n        print(f\"ALERTA: Lat\u00eancia alta: {alert_data['latency']}ms\")\r\n        # Notificar equipe, escalar, etc.\r\n    elif alert_data['type'] == 'session_down':\r\n        print(f\"ALERTA: Sess\u00e3o {alert_data['session_id']} caiu\")\r\n        # Tentar reconex\u00e3o autom\u00e1tica\r\n```\r\n\r\n**Resposta do health check:**\r\n```json\r\n{\r\n  \"status\": \"healthy\",\r\n  \"timestamp\": \"2024-12-19T10:30:00.000Z\",\r\n  \"uptime\": 3600000,\r\n  \"sessions\": {\r\n    \"active\": 2,\r\n    \"total\": 5\r\n  },\r\n  \"metrics\": {\r\n    \"messagesIn\": 150,\r\n    \"messagesOut\": 120,\r\n    \"reconnections\": 3,\r\n    \"errors\": 1\r\n  },\r\n  \"version\": \"0.3.2\"\r\n}\r\n```\r\n\r\n---\r\n\r\n## \ud83d\udea8 **TRATAMENTO DE ERROS**\r\n\r\n### **Exce\u00e7\u00f5es comuns**\r\n```python\r\ntry:\r\n    session.start()\r\nexcept SessionError as e:\r\n    print(f\"Erro de sess\u00e3o: {e}\")\r\nexcept ConnectionError as e:\r\n    print(f\"Erro de conex\u00e3o: {e}\")\r\nexcept AuthenticationError as e:\r\n    print(f\"Erro de autentica\u00e7\u00e3o: {e}\")\r\nexcept WebSocketError as e:\r\n    print(f\"Erro de WebSocket: {e}\")\r\n```\r\n\r\n### **Verifica\u00e7\u00e3o de status**\r\n```python\r\nif not session.is_connected():\r\n    print(\"Sess\u00e3o n\u00e3o est\u00e1 conectada\")\r\n    return\r\n\r\nif not session.is_active():\r\n    print(\"Sess\u00e3o n\u00e3o est\u00e1 ativa\")\r\n    return\r\n\r\n# Verificar reconex\u00e3o\r\nif session._reconnection_attempts > 0:\r\n    print(f\"Tentativas de reconex\u00e3o: {session._reconnection_attempts}\")\r\n```\r\n\r\n---\r\n\r\n## \ud83d\udd12 **SEGURAN\u00c7A E CONTROLE DE ACESSO**\r\n\r\n### **\ud83d\udd10 AUTENTICA\u00c7\u00c3O E AUTORIZA\u00c7\u00c3O**\r\n\r\n#### **API Key obrigat\u00f3ria**\r\n```python\r\n# Sempre use uma API key forte\r\nmanager = WhatsWebManager(\r\n    api_key=\"sua-api-key-super-secreta-aqui\"\r\n)\r\n```\r\n\r\n#### **Token/JWT no WebSocket (obrigat\u00f3rio)**\r\n```javascript\r\n// Autentica\u00e7\u00e3o no handshake de conex\u00e3o\r\nconst wss = new WebSocket.Server({ \r\n    port: WS_PORT,\r\n    verifyClient: (info) => {\r\n        const token = info.req.headers['authorization'] || \r\n                     new URL(info.req.url, 'http://localhost').searchParams.get('token');\r\n        \r\n        if (!token || token !== `Bearer ${API_KEY}`) {\r\n            return false; // Conex\u00e3o rejeitada imediatamente\r\n        }\r\n        \r\n        // Validar tenant_id se fornecido\r\n        const tenantId = info.req.headers['x-tenant-id'];\r\n        if (tenantId && !isValidTenant(tenantId)) {\r\n            return false;\r\n        }\r\n        \r\n        return true;\r\n    }\r\n});\r\n```\r\n\r\n#### **Multi-tenant com isolamento**\r\n```python\r\n# Criar sess\u00e3o com tenant espec\u00edfico\r\nsession = manager.create_session(\r\n    \"sessao_123\", \r\n    tenant_id=\"empresa_a\",\r\n    correlation_id=\"req_456\"\r\n)\r\n\r\n# Headers de correla\u00e7\u00e3o autom\u00e1ticos\r\n# X-Correlation-Id: req_456\r\n# X-Tenant-Id: empresa_a\r\n# X-Session-Id: sessao_123\r\n```\r\n\r\n### **\ud83d\udee1\ufe0f CONTROLE DE ACESSO E AUDITORIA**\r\n\r\n#### **Headers de correla\u00e7\u00e3o padronizados**\r\n- **X-Correlation-Id**: ID \u00fanico para rastrear opera\u00e7\u00e3o\r\n- **X-Tenant-Id**: Identificador do tenant (multi-tenancy)\r\n- **X-Session-Id**: ID da sess\u00e3o WhatsApp\r\n- **X-Request-Id**: ID \u00fanico da requisi\u00e7\u00e3o HTTP\r\n\r\n#### **Logs com rastreamento completo**\r\n```python\r\n# Logs autom\u00e1ticos com correlation ID\r\n# [2024-12-19 10:30:00] [corr:req_456] [tenant:empresa_a] Sess\u00e3o criada: sessao_123\r\n# [2024-12-19 10:30:05] [corr:req_456] [tenant:empresa_a] QR Code gerado\r\n# [2024-12-19 10:30:30] [corr:req_456] [tenant:empresa_a] WhatsApp autenticado\r\n```\r\n\r\n### **API Key**\r\n```python\r\n# Sempre use uma API key forte\r\nmanager = WhatsWebManager(\r\n    api_key=\"sua-api-key-super-secreta-aqui\"\r\n)\r\n```\r\n\r\n### **Configura\u00e7\u00e3o de rede**\r\n```python\r\n# Restringir acesso por IP se necess\u00e1rio\r\nmanager = WhatsWebManager(\r\n    sidecar_host=\"127.0.0.1\",  # Apenas localhost\r\n    sidecar_port=3000\r\n)\r\n```\r\n\r\n### **Rate Limiting**\r\n```javascript\r\n// Configura\u00e7\u00e3o no sidecar\r\nconst limiter = rateLimit({\r\n    windowMs: 15 * 60 * 1000, // 15 minutos\r\n    max: 100, // m\u00e1ximo 100 requisi\u00e7\u00f5es por IP\r\n    message: 'Muitas requisi\u00e7\u00f5es deste IP, tente novamente mais tarde.'\r\n});\r\n```\r\n\r\n---\r\n\r\n## \ud83d\udcc8 **CASOS DE USO**\r\n\r\n### **1. Chatbot Autom\u00e1tico**\r\n```python\r\n@session.on(\"message\")\r\ndef auto_response(data):\r\n    content = data['body'].lower()\r\n    sender = data['from']\r\n    \r\n    if \"pre\u00e7o\" in content:\r\n        session.send_text(sender, \"Nossos pre\u00e7os: Produto A - R$ 50, Produto B - R$ 100\")\r\n    elif \"contato\" in content:\r\n        session.send_text(sender, \"Entre em contato: (11) 99999-9999\")\r\n    else:\r\n        session.send_text(sender, \"Como posso ajudar? Digite 'pre\u00e7o' ou 'contato'\")\r\n```\r\n\r\n### **2. Sistema de Atendimento**\r\n```python\r\n# Atribuir chat para atendente\r\ndef assign_chat_to_attendant(chat_id, attendant_id):\r\n    chat = storage.get_chat(chat_id)\r\n    chat.assign_to(attendant_id, \"sistema\")\r\n    storage.save_chat(chat)\r\n    \r\n    # Notificar atendente\r\n    session.send_text(attendant_id, f\"Novo chat atribu\u00eddo: {chat_id}\")\r\n```\r\n\r\n### **3. Monitoramento de Conversas**\r\n```python\r\n# Verificar conversas ativas\r\ndef monitor_active_chats():\r\n    active_chats = storage.get_chats_by_status(KanbanStatus.ACTIVE)\r\n    \r\n    for chat in active_chats:\r\n        # Verificar tempo de atendimento\r\n        if chat.is_taking_too_long():\r\n            # Escalar para supervisor\r\n            escalate_chat(chat)\r\n```\r\n\r\n### **4. Sistema de Auditoria**\r\n```python\r\n# Rastrear todas as a\u00e7\u00f5es\r\ndef audit_action(action, user_id, details):\r\n    event = SessionEvent(\r\n        session_id=session.session_id,\r\n        event_type=action,\r\n        data=details,\r\n        user_id=user_id,\r\n        ip_address=request.META.get('REMOTE_ADDR'),\r\n        user_agent=request.META.get('HTTP_USER_AGENT')\r\n    )\r\n    storage.save_event(event)\r\n```\r\n\r\n---\r\n\r\n## \ud83e\uddea **TESTES E DESENVOLVIMENTO**\r\n\r\n### **Executar testes**\r\n```bash\r\n# Teste de imports\r\npython test_imports.py\r\n\r\n# Teste com pytest\r\npytest tests/\r\n\r\n# Teste com tox\r\ntox\r\n```\r\n\r\n### **Desenvolvimento local**\r\n```bash\r\n# Instalar em modo desenvolvimento\r\npip install -e .\r\n\r\n# Executar exemplos\r\npython examples/basic_usage.py\r\npython examples/django_complete_example.py\r\n```\r\n\r\n### **\ud83d\udda5\ufe0f CLI OPERACIONAL (pww)**\r\n\r\n#### **Instala\u00e7\u00e3o e uso do CLI**\r\n```bash\r\n# Instalar CLI globalmente\r\npip install pywhatsweb[cli]\r\n\r\n# Ou usar via Python\r\npython -m pywhatsweb.cli session start --id teste\r\n\r\n# Verificar vers\u00e3o\r\npww --version\r\n```\r\n\r\n#### **Comandos para suporte e diagn\u00f3stico**\r\n```bash\r\n# Gerenciar sess\u00f5es\r\npww session start --id sessao_123 --tenant empresa_a\r\npww session status --id sessao_123\r\npww session stop --id sessao_123\r\npww session list --active\r\npww session list --all\r\n\r\n# Mostrar QR Code\r\npww session qr --id sessao_123\r\n\r\n# Enviar mensagem de teste\r\npww session send --id sessao_123 --to 5511999999999 --text \"Teste CLI\"\r\n\r\n# Diagn\u00f3stico completo\r\npww diag --session sessao_123\r\npww diag --sidecar\r\npww diag --storage\r\n\r\n# Ver logs em tempo real\r\npww logs --follow --session sessao_123\r\npww logs --level debug --tenant empresa_a\r\n\r\n# Health check completo\r\npww health --sidecar --sessions --storage\r\npww health --format json\r\npww health --format prometheus\r\n```\r\n\r\n#### **Exemplos de uso do CLI**\r\n```bash\r\n# Iniciar m\u00faltiplas sess\u00f5es\r\npww session start --id atendente_1 --tenant empresa_a\r\npww session start --id atendente_2 --tenant empresa_a\r\npww session start --id suporte --tenant empresa_b\r\n\r\n# Monitorar sess\u00f5es ativas\r\npww session list --active --format table\r\n# +-------------+-----------+--------+---------------------+\r\n# | Session ID  | Tenant    | Status | Last Activity      |\r\n# +-------------+-----------+--------+---------------------+\r\n# | atendente_1 | empresa_a | ready  | 2024-12-19 10:30:00 |\r\n# | atendente_2 | empresa_a | ready  | 2024-12-19 10:29:45 |\r\n# | suporte     | empresa_b | qr     | 2024-12-19 10:25:00 |\r\n# +-------------+-----------+--------+---------------------+\r\n\r\n# Diagn\u00f3stico de problemas\r\npww diag --session atendente_1 --verbose\r\n# Sess\u00e3o: atendente_1\r\n# Status: ready\r\n# WebSocket: connected\r\n# Heartbeat: 45ms\r\n# \u00daltima mensagem: 2 minutos atr\u00e1s\r\n# Reconex\u00f5es: 0\r\n# Erros: 0\r\n```\r\n\r\n### **Testar sidecar**\r\n```bash\r\ncd sidecar\r\n\r\n# Instalar depend\u00eancias\r\nnpm install\r\n\r\n# Executar em modo desenvolvimento\r\nnpm run dev\r\n\r\n# Testar endpoints\r\ncurl http://localhost:3000/health\r\ncurl -H \"Authorization: Bearer sua-api-key\" http://localhost:3000/metrics\r\n```\r\n\r\n---\r\n\r\n## \ud83d\udcda **RECURSOS ADICIONAIS**\r\n\r\n### **Documenta\u00e7\u00e3o**\r\n- **README.md**: Vis\u00e3o geral para usu\u00e1rios\r\n- **README-for-devs.md**: Este arquivo (guia t\u00e9cnico)\r\n- **examples/**: Exemplos pr\u00e1ticos\r\n- **sidecar/README.md**: Documenta\u00e7\u00e3o do sidecar\r\n\r\n### **Ferramentas**\r\n- **Makefile**: Comandos de automa\u00e7\u00e3o\r\n- **requirements.txt**: Depend\u00eancias Python\r\n- **sidecar/package.json**: Depend\u00eancias Node.js\r\n\r\n### **Configura\u00e7\u00f5es de ambiente**\r\n```bash\r\n# .env do sidecar\r\nPORT=3000\r\nWS_PORT=3001\r\nAPI_KEY=sua-api-key-super-secreta\r\nALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000\r\nPUPPETEER_ARGS=--no-sandbox --disable-setuid-sandbox\r\nLOG_LEVEL=info\r\n```\r\n\r\n---\r\n\r\n## \ud83c\udfaf **PR\u00d3XIMOS PASSOS**\r\n\r\n### **v0.5.1 (Atual)**\r\n- [ ] Interface web para supervis\u00e3o\r\n- [ ] Sistema de m\u00e9tricas e analytics avan\u00e7ado\r\n- [ ] Orquestra\u00e7\u00e3o multi-inst\u00e2ncia\r\n- [ ] Integra\u00e7\u00e3o com sistemas externos (CRM, ERP)\r\n- [ ] Suporte a m\u00faltiplos n\u00fameros por sess\u00e3o\r\n- [ ] Sistema de templates de mensagem\r\n- [ ] Backup e restore de sess\u00f5es\r\n\r\n### **Contribui\u00e7\u00f5es**\r\n- [ ] Testes unit\u00e1rios completos\r\n- [ ] Documenta\u00e7\u00e3o adicional\r\n- [ ] Novos tipos de storage (Redis, PostgreSQL)\r\n- [ ] Melhorias de performance\r\n- [ ] Novos tipos de mensagem (bot\u00f5es, listas)\r\n- [ ] Sistema de webhooks\r\n\r\n---\r\n\r\n## \ud83d\udea8 **SUPORTE E TROUBLESHOOTING**\r\n\r\n### **\ud83d\udd0d PROBLEMAS COMUNS E SOLU\u00c7\u00d5ES**\r\n\r\n#### **1. Sidecar n\u00e3o inicia**\r\n```bash\r\n# \u274c Erro: \"Node.js version must be 18.0.0 or higher\"\r\n# \u2705 Solu\u00e7\u00e3o: Atualizar Node.js\r\nnode --version  # Deve ser \u226518.0.0\r\nnvm install 18  # ou baixar do nodejs.org\r\n\r\n# \u274c Erro: \"Cannot find module 'whatsapp-web.js'\"\r\n# \u2705 Solu\u00e7\u00e3o: Reinstalar depend\u00eancias\r\ncd sidecar && rm -rf node_modules package-lock.json\r\nnpm install\r\n```\r\n\r\n#### **2. QR Code n\u00e3o aparece**\r\n```python\r\n# \u274c Problema: Evento 'qr' n\u00e3o dispara\r\n# \u2705 Solu\u00e7\u00e3o: Verificar WebSocket\r\nimport logging\r\nlogging.basicConfig(level=logging.DEBUG)\r\n\r\n# Verificar se est\u00e1 conectando\r\n@session.on(\"connecting\")\r\ndef on_connecting(data):\r\n    print(\"Conectando...\")\r\n\r\n@session.on(\"qr\")\r\ndef on_qr(data):\r\n    print(f\"QR: {data['qr']}\")  # Deve aparecer aqui\r\n```\r\n\r\n#### **3. Mensagens n\u00e3o enviam**\r\n```python\r\n# \u274c Problema: \"Session not ready\"\r\n# \u2705 Solu\u00e7\u00e3o: Aguardar evento 'ready'\r\n@session.on(\"ready\")\r\ndef on_ready(data):\r\n    print(\"WhatsApp pronto! Agora pode enviar\")\r\n    session.send_text(\"5511999999999\", \"Teste\")\r\n\r\n# \u274c Problema: \"Rate limit exceeded\"\r\n# \u2705 Solu\u00e7\u00e3o: Aguardar e tentar novamente\r\nimport time\r\ntime.sleep(60)  # Aguardar 1 minuto\r\n```\r\n\r\n#### **4. WebSocket desconectado**\r\n```python\r\n# \u274c Problema: Eventos param de chegar\r\n# \u2705 Solu\u00e7\u00e3o: Reconex\u00e3o autom\u00e1tica\r\n@session.on(\"disconnected\")\r\ndef on_disconnected(data):\r\n    print(f\"Desconectado: {data['reason']}\")\r\n    # Reconex\u00e3o autom\u00e1tica em andamento\r\n\r\n@session.on(\"ready\")\r\ndef on_ready(data):\r\n    print(\"Reconectado!\")\r\n```\r\n\r\n### **\ud83d\udcca DIAGN\u00d3STICO R\u00c1PIDO**\r\n```bash\r\n# 1. Verificar sidecar\r\ncurl http://localhost:3000/health\r\n\r\n# 2. Verificar sess\u00f5es ativas\r\ncurl -H \"Authorization: Bearer ${API_KEY}\" \\\r\n     http://localhost:3000/metrics\r\n\r\n# 3. Ver logs do sidecar\r\ncd sidecar && npm run dev\r\n\r\n# 4. Ver logs Python\r\npython -c \"import logging; logging.basicConfig(level=logging.DEBUG)\"\r\n```\r\n\r\n### **\ud83d\udea8 CEN\u00c1RIOS CR\u00cdTICOS**\r\n\r\n#### **Sess\u00e3o expirada (QR n\u00e3o aparece)**\r\n```bash\r\n# 1. Parar todas as sess\u00f5es\r\ncurl -X POST -H \"Authorization: Bearer ${API_KEY}\" \\\r\n     http://localhost:3000/api/sessions/stop-all\r\n\r\n# 2. Reiniciar sidecar\r\ncd sidecar && npm restart\r\n\r\n# 3. Recriar sess\u00e3o\r\nsession = manager.create_session(\"nova_sessao\")\r\nsession.start()\r\n```\r\n\r\n#### **WhatsApp banido/limitado**\r\n```python\r\n# \u274c Erro: \"Account banned\" ou \"Too many requests\"\r\n# \u2705 Solu\u00e7\u00e3o: Aguardar e usar n\u00famero diferente\r\nimport time\r\n\r\n# Aguardar 24h para ban\r\ntime.sleep(24 * 60 * 60)\r\n\r\n# Ou usar n\u00famero alternativo\r\nsession2 = manager.create_session(\"sessao_2\", phone_number=\"5511888888888\")\r\n```\r\n\r\n### **Logs e debug**\r\n```python\r\nimport logging\r\nlogging.basicConfig(level=logging.DEBUG)\r\n\r\n# Logs detalhados de todas as opera\u00e7\u00f5es\r\nmanager = WhatsWebManager()\r\n```\r\n\r\n### **Verificar health do sidecar**\r\n```bash\r\n# Health check\r\ncurl http://localhost:3000/health\r\n\r\n# Ver logs do sidecar\r\ncd sidecar\r\nnpm run dev\r\n```\r\n\r\n---\r\n\r\n## \ud83c\udf89 **CONCLUS\u00c3O**\r\n\r\nA **PyWhatsWeb v0.5.1** \u00e9 uma biblioteca **completa e funcional** que oferece:\r\n\r\n\u2705 **Arquitetura moderna** com sidecar Node.js  \r\n\u2705 **Multi-sess\u00e3o** para m\u00faltiplos atendentes  \r\n\u2705 **Eventos em tempo real** via WebSocket  \r\n\u2705 **Storage pluggable** (FileSystem ou Django)  \r\n\u2705 **Sistema Kanban** para gest\u00e3o de conversas  \r\n\u2705 **API Python limpa** e f\u00e1cil de usar  \r\n\u2705 **Sem depend\u00eancias** de navegador/Selenium  \r\n\u2705 **Funciona em qualquer projeto Python**  \r\n\u2705 **Reconex\u00e3o autom\u00e1tica** com backoff exponencial  \r\n\u2705 **Sistema de idempot\u00eancia** para deduplica\u00e7\u00e3o  \r\n\u2705 **Health check e m\u00e9tricas** completas  \r\n\u2705 **Seguran\u00e7a robusta** com rate limiting e CORS  \r\n\u2705 **Exemplo Django completo** com dashboard funcional  \r\n\r\n**Para come\u00e7ar agora:**\r\n1. Inicie o sidecar: `cd sidecar && npm install && npm start`\r\n2. Use a biblioteca Python em seu projeto\r\n3. Configure eventos e handlers\r\n4. Gerencie m\u00faltiplas sess\u00f5es\r\n5. Implemente o sistema Kanban\r\n6. Monitore com health check e m\u00e9tricas\r\n\r\n**A biblioteca est\u00e1 pronta para uso em produ\u00e7\u00e3o com todas as funcionalidades essenciais implementadas!** \ud83d\ude80\r\n\r\n---\r\n\r\n## \ud83d\udd11 **FUN\u00c7\u00d5ES PRINCIPAIS - RESUMO R\u00c1PIDO**\r\n\r\n### **\ud83d\ude80 CORE FUNCTIONS**\r\n```python\r\n# 1. MANAGER - Gerenciador principal\r\nmanager = WhatsWebManager(api_key=\"sua-chave\")\r\nmanager.create_session(\"id\")      # Criar sess\u00e3o\r\nmanager.list_sessions()           # Listar todas\r\nmanager.get_active_sessions()     # Sess\u00f5es ativas\r\n\r\n# 2. SESSION - Sess\u00e3o individual\r\nsession = manager.get_session(\"id\")\r\nsession.start()                   # Iniciar conex\u00e3o\r\nsession.stop()                    # Parar sess\u00e3o\r\nsession.send_text(to, text)      # Enviar texto\r\nsession.send_media(to, path)     # Enviar arquivo\r\n\r\n# 3. EVENTS - Sistema de eventos\r\n@session.on(\"qr\", handler)       # QR Code\r\n@session.on(\"message\", handler)  # Mensagem recebida\r\n@session.on(\"ready\", handler)    # WhatsApp pronto\r\n@session.on(\"disconnected\", handler)  # Desconectado\r\n```\r\n\r\n### **\ud83d\udcbe STORAGE - Persist\u00eancia de dados**\r\n```python\r\n# FileSystem (padr\u00e3o)\r\nstorage = FileSystemStore(\"./data\")\r\n\r\n# Django ORM (opcional)\r\nstorage = DjangoORMStore()\r\nstorage.set_models(WhatsAppSession, WhatsAppMessage)\r\n\r\n# Opera\u00e7\u00f5es b\u00e1sicas\r\nstorage.save_message(message)\r\nstorage.get_chat_messages(chat_id)\r\nstorage.save_contact(contact)\r\n```\r\n\r\n### **\ud83d\udd27 UTILITIES - Ferramentas auxiliares**\r\n```python\r\nfrom pywhatsweb.utils import *\r\n\r\n# N\u00fameros de telefone\r\nnormalize_phone_number(\"11999999999\")  # +5511999999999\r\nvalidate_phone_number(\"11999999999\")   # (True, \"+5511999999999\")\r\n\r\n# IDs e timestamps\r\ngenerate_session_id(\"session\", \"tenant\")  # session_tenant_1703000000_abc123\r\nformat_timestamp(datetime.now(), \"America/Sao_Paulo\")\r\n```\r\n\r\n### **\ud83d\udea8 ERROR HANDLING - Tratamento de erros**\r\n```python\r\nfrom pywhatsweb.errors import *\r\n\r\n# C\u00f3digos de erro padronizados\r\nErrorCode.E_SESSION_NOT_FOUND      # 404\r\nErrorCode.E_AUTHENTICATION_FAILED  # 401\r\nErrorCode.E_MEDIA_TOO_LARGE       # 400\r\n\r\n# Criar resposta de erro\r\nerror_response = create_error_response(ErrorCode.E_SESSION_NOT_FOUND)\r\n```\r\n\r\n---\r\n\r\n## \ud83d\udccb **CHANGELOG v0.5.1**\r\n\r\n### **\ud83d\udd27 CORRIGIDO**\r\n- **Bug de compatibilidade Python 3.13**: Corrigido erro `TypeError: non-default argument follows default argument` em dataclasses\r\n- **Ordem de campos**: Reordenados campos obrigat\u00f3rios antes de campos opcionais em `MediaMessage` e `Chat`\r\n- **Compatibilidade**: Todas as classes dataclass agora funcionam perfeitamente com Python 3.13+\r\n\r\n### **\u2728 ADICIONADO**\r\n- **Suporte expl\u00edcito Python 3.13**: Verifica\u00e7\u00e3o autom\u00e1tica e mensagens informativas\r\n- **Verifica\u00e7\u00e3o de compatibilidade**: Detecta vers\u00e3o Python e depend\u00eancias no import\r\n- **Configura\u00e7\u00f5es centralizadas**: Todas as configura\u00e7\u00f5es padr\u00e3o em `__default_config__`\r\n- **Informa\u00e7\u00f5es de vers\u00e3o**: Atributos `__python_support__`, `__dependencies__`, etc.\r\n\r\n### **\ud83d\udcda DOCUMENTA\u00c7\u00c3O**\r\n- **Matriz de compatibilidade atualizada**: Inclui Python 3.13 explicitamente\r\n- **README atualizado**: Vers\u00e3o e funcionalidades da v0.5.1\r\n- **CHANGELOG completo**: Todas as mudan\u00e7as documentadas\r\n\r\n### **\ud83d\ude80 MELHORIAS**\r\n- **Import otimizado**: Verifica\u00e7\u00e3o de compatibilidade autom\u00e1tica\r\n- **Mensagens informativas**: Feedback sobre vers\u00f5es suportadas\r\n- **Estrutura de dados**: Dataclasses mais robustas e compat\u00edveis\r\n\r\n---\r\n\r\n## \ud83d\udccb **CHANGELOG v0.4.1**\r\n\r\n### **\u2728 Novas Funcionalidades [LIB + README]**\r\n- **Autentica\u00e7\u00e3o WebSocket obrigat\u00f3ria** com token + multi-tenant [LIB]\r\n- **Endpoint /metrics Prometheus** para monitoramento avan\u00e7ado [LIB]\r\n- **Sistema de idempot\u00eancia refor\u00e7ado** com outbox pattern [LIB]\r\n- **Dockerfile e docker-compose** otimizados para produ\u00e7\u00e3o [LIB]\r\n- **Runbooks ampliados** para cen\u00e1rios cr\u00edticos (2FA, ban, limites) [README]\r\n- **CLI operacional** para suporte e diagn\u00f3stico [LIB + README]\r\n- **Webhooks e SSE fallback** quando WebSocket n\u00e3o dispon\u00edvel [LIB + README]\r\n- **Sistema de backpressure** com filas Redis/mem\u00f3ria [LIB + README]\r\n- **Pol\u00edtica LGPD** com reten\u00e7\u00e3o configur\u00e1vel e criptografia [LIB + README]\r\n\r\n### **\ud83d\udd27 Melhorias [LIB + README]**\r\n- **Normaliza\u00e7\u00e3o E.164** e valida\u00e7\u00e3o de n\u00fameros de telefone [LIB]\r\n- **Cat\u00e1logo de erros padronizados** com 50+ c\u00f3digos HTTP [LIB]\r\n- **Reconex\u00e3o autom\u00e1tica** com backoff exponencial e heartbeat [LIB]\r\n- **Sistema Kanban** com rastreamento completo de conversas [LIB]\r\n- **Exemplos Django** com template HTML e consumer WebSocket [README]\r\n- **Matriz de compatibilidade** com verifica\u00e7\u00e3o fail-fast [LIB + README]\r\n- **Tabela de limites e timeouts** centralizada [README]\r\n- **Headers de correla\u00e7\u00e3o** padronizados (X-Correlation-Id, X-Tenant-Id) [LIB + README]\r\n\r\n### **\ud83d\udc1b Corre\u00e7\u00f5es [LIB + README]**\r\n- **Consolida\u00e7\u00e3o de seguran\u00e7a** (Helmet, CORS, Rate Limiting unificados) [LIB]\r\n- **Ajustes de payloads de eventos** e status de sess\u00e3o [LIB]\r\n- **Endpoints /metrics duplicados** corrigidos (Prometheus + JSON) [LIB]\r\n- **Dockerfile** com usu\u00e1rio correto (node em vez de nodejs) [LIB]\r\n- **Vers\u00f5es inconsistentes** padronizadas para v0.5.1 [README]\r\n- **WebSocket auth** com compatibilidade entre vers\u00f5es do ws [LIB]\r\n\r\n### **\ud83d\udcda Documenta\u00e7\u00e3o [README]**\r\n- README-for-devs.md completo e atualizado\r\n- Exemplos pr\u00e1ticos para todos os casos de uso\r\n- Guia de configura\u00e7\u00e3o e troubleshooting\r\n- Documenta\u00e7\u00e3o de seguran\u00e7a e boas pr\u00e1ticas\r\n- **Matriz de compatibilidade** com verifica\u00e7\u00e3o autom\u00e1tica\r\n- **CLI operacional** com comandos de diagn\u00f3stico\r\n- **Exemplo Django completo** com template HTML funcional\r\n\r\n---\r\n\r\n## \ud83d\udccb **CHANGELOG v0.4.4**\r\n\r\n### **\ud83d\udd27 CORRIGIDO**\r\n- **Bug de compatibilidade websockets 15.0+**: Corrigido erro `AttributeError: module 'websockets' has no attribute 'version_tuple'`\r\n- **Verifica\u00e7\u00e3o de vers\u00e3o**: Implementado fallback robusto para diferentes vers\u00f5es de websockets\r\n- **Compatibilidade**: Suporte total a websockets 15.0+ e Python 3.13\r\n\r\n### **\u2728 ADICIONADO**\r\n- **Suporte websockets modernos**: Compatibilidade com vers\u00f5es 15.0+ que n\u00e3o possuem `version_tuple`\r\n- **Fallback autom\u00e1tico**: Verifica\u00e7\u00e3o de vers\u00e3o usando `__version__` quando `version_tuple` n\u00e3o est\u00e1 dispon\u00edvel\r\n- **Verifica\u00e7\u00e3o robusta**: Tratamento de erros para diferentes atributos de vers\u00e3o\r\n\r\n### **\ud83d\ude80 MELHORIAS**\r\n- **Compatibilidade total**: Python 3.13 + websockets 15.0+ funcionando perfeitamente\r\n- **Verifica\u00e7\u00e3o resiliente**: Sistema de compatibilidade mais robusto\r\n- **Fallback inteligente**: Adapta\u00e7\u00e3o autom\u00e1tica a diferentes vers\u00f5es de depend\u00eancias\r\n\r\n---\r\n\r\n## \ud83d\udccb **CHANGELOG v0.5.1**\r\n\r\n### **\ud83d\udd27 CORRIGIDO**\r\n- **Bug de dataclasses Python 3.13**: Corrigido erro `TypeError: non-default argument follows default argument`\r\n- **Ordem de campos**: Reordenados campos obrigat\u00f3rios antes de campos opcionais em todas as classes\r\n- **Compatibilidade**: Todas as dataclasses agora funcionam perfeitamente com Python 3.13+\r\n- **Heran\u00e7a**: Corrigida heran\u00e7a da classe `MediaMessage` da classe `Message`\r\n\r\n### **\u2728 ADICIONADO**\r\n- **Estrutura de dados robusta**: Dataclasses com ordem correta de campos\r\n- **Valida\u00e7\u00e3o p\u00f3s-inicializa\u00e7\u00e3o**: M\u00e9todos `__post_init__` funcionando corretamente\r\n- **Compatibilidade total**: Python 3.13 + websockets 15.0+ + dataclasses funcionando\r\n\r\n### **\ud83d\ude80 MELHORIAS**\r\n- **Estrutura de dados**: Todas as classes agora seguem padr\u00e3o Python 3.13+\r\n- **Valida\u00e7\u00e3o**: Sistema de valida\u00e7\u00e3o mais robusto e compat\u00edvel\r\n- **Heran\u00e7a**: Sistema de heran\u00e7a funcionando perfeitamente\r\n\r\n---\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Biblioteca Python para WhatsApp Web corporativo com sidecar Python integrado (padr\u00e3o) ou Node.js (opcional)",
    "version": "0.5.3",
    "project_urls": {
        "Changelog": "https://github.com/ti-leo/pywhatsweb/blob/main/CHANGELOG.md",
        "Documentation": "https://github.com/ti-leo/pywhatsweb#readme",
        "Homepage": "https://github.com/ti-leo/pywhatsweb",
        "Issues": "https://github.com/ti-leo/pywhatsweb/issues",
        "Repository": "https://github.com/ti-leo/pywhatsweb"
    },
    "split_keywords": [
        "whatsapp",
        " whatsapp-web",
        " automation",
        " bot",
        " api",
        " corporate",
        " enterprise"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "4db572c85f708fe748f4fb60724408733836eda2c6547bdb56ceacbfcd7691a7",
                "md5": "9c92235656bcad5b3e998c1a4f5110b7",
                "sha256": "abd5eaec7acb8119866deaf9d86f1536c5dbc7d8c7fac42cd6e75cfa4688ba77"
            },
            "downloads": -1,
            "filename": "pywhatsweb-0.5.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "9c92235656bcad5b3e998c1a4f5110b7",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 63048,
            "upload_time": "2025-08-21T18:25:25",
            "upload_time_iso_8601": "2025-08-21T18:25:25.026353Z",
            "url": "https://files.pythonhosted.org/packages/4d/b5/72c85f708fe748f4fb60724408733836eda2c6547bdb56ceacbfcd7691a7/pywhatsweb-0.5.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f359d12716f6cbd10d39776c1b595342aed7ba7552de4facf4a4e4567aa9f62c",
                "md5": "93519d1b6d6a67c42f98808966685607",
                "sha256": "84d6f8eb65e8dbb0ecd39bfa0aa63434b3c61d42e82ffc0bcf00b884b65301ef"
            },
            "downloads": -1,
            "filename": "pywhatsweb-0.5.3.tar.gz",
            "has_sig": false,
            "md5_digest": "93519d1b6d6a67c42f98808966685607",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 121735,
            "upload_time": "2025-08-21T18:25:27",
            "upload_time_iso_8601": "2025-08-21T18:25:27.248440Z",
            "url": "https://files.pythonhosted.org/packages/f3/59/d12716f6cbd10d39776c1b595342aed7ba7552de4facf4a4e4567aa9f62c/pywhatsweb-0.5.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-21 18:25:27",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "ti-leo",
    "github_project": "pywhatsweb",
    "github_not_found": true,
    "lcname": "pywhatsweb"
}
        
Elapsed time: 1.16779s