From 92c66c4b5503b0e09efc8aef795fba0e23972759 Mon Sep 17 00:00:00 2001 From: Wallace Martins Date: Mon, 8 Dec 2025 07:01:55 -0300 Subject: [PATCH] docs: add screenshots to README --- ARCHITECTURE.md | 2340 --------------------------------- README.md | 22 +- docs/images/principal.png | Bin 0 -> 96162 bytes docs/images/screenshot-01.png | Bin 0 -> 23828 bytes docs/images/screenshot-02.png | Bin 0 -> 39845 bytes docs/images/screenshot-03.png | Bin 0 -> 63855 bytes docs/images/screenshot-04.png | Bin 0 -> 115089 bytes docs/images/screenshot-05.png | Bin 0 -> 37518 bytes docs/images/screenshot-06.png | Bin 0 -> 46134 bytes docs/images/screenshot-07.png | Bin 0 -> 90407 bytes docs/images/screenshot-08.png | Bin 0 -> 62877 bytes 11 files changed, 19 insertions(+), 2343 deletions(-) delete mode 100644 ARCHITECTURE.md create mode 100644 docs/images/principal.png create mode 100644 docs/images/screenshot-01.png create mode 100644 docs/images/screenshot-02.png create mode 100644 docs/images/screenshot-03.png create mode 100644 docs/images/screenshot-04.png create mode 100644 docs/images/screenshot-05.png create mode 100644 docs/images/screenshot-06.png create mode 100644 docs/images/screenshot-07.png create mode 100644 docs/images/screenshot-08.png diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md deleted file mode 100644 index 1068879..0000000 --- a/ARCHITECTURE.md +++ /dev/null @@ -1,2340 +0,0 @@ -# Filament Evolution - Arquitetura do Plugin - -Plugin Filament para integraΓ§Γ£o com Evolution API v2 (WhatsApp). - ---- - -## 🏒 Multi-Tenancy - -> O plugin suporta **multi-tenancy nativo do Filament v4** atravΓ©s de configuraΓ§Γ£o dinΓ’mica. - -### CaracterΓ­sticas - -| Feature | DescriΓ§Γ£o | -|---------|-----------| -| **HabilitaΓ§Γ£o** | Via `config('filament-evolution.tenancy.enabled')` | -| **Coluna DinΓ’mica** | ConfigurΓ‘vel: `team_id`, `company_id`, `tenant_id`, etc. | -| **Tipo de Coluna** | Suporta `uuid` ou `id` (bigint) | -| **Scope AutomΓ‘tico** | Models aplicam filtro por tenant automaticamente | -| **Auto-fill** | Tenant ID Γ© preenchido automaticamente ao criar registros | - -### ConfiguraΓ§Γ£o RΓ‘pida - -```env -# .env -EVOLUTION_TENANCY_ENABLED=true -EVOLUTION_TENANT_COLUMN=team_id -EVOLUTION_TENANT_TABLE=teams -EVOLUTION_TENANT_MODEL=App\Models\Team -EVOLUTION_TENANT_COLUMN_TYPE=uuid -``` - -> πŸ“– Veja a seΓ§Γ£o **Models com Multi-Tenancy** para detalhes de implementaΓ§Γ£o. -``` - ---- - -## πŸ“Š AnΓ‘lise da Estrutura Atual - -### βœ… O que vocΓͺ JÁ TEM (e funciona bem): - -| Componente | Arquivo | Status | -|------------|---------|--------| -| **Config** | `config/filament-evolution.php` | πŸ”΅ NOVO - Config prΓ³pria do plugin | -| **Model** | `app/Models/WhatsappInstance.php` | βœ… Com UUID, casts, fillable | -| **Migration** | `create_whatsapp_instances_table.php` | βœ… Campos completos | -| **Enum** | `StatusConnectionEnum.php` | βœ… Com HasLabel, HasColor | -| **HTTP Client** | `EvolutionClientTrait.php` | βœ… Trait reutilizΓ‘vel | -| **Services Instance** | 6 services (Create, Connect, Delete, etc.) | βœ… Funcionais | -| **Services Message** | `SendMessageEvolutionService.php` | βœ… Funcional | -| **Webhook Controller** | `EvolutionWebhookController.php` | βœ… Switch por evento | -| **Filament Resource** | `WhatsappInstanceResource.php` | βœ… Com Form/Table/Infolist separados | -| **Livewire QR Code** | `EvolutionQrCode.php` | βœ… Com polling e countdown | -| **Views** | `evolution-qr-code.blade.php` | βœ… UI completa | - -### ❌ O que FALTA (para melhorar qualidade e manutenibilidade): - -| Componente | BenefΓ­cio | -|------------|-----------| -| **DTOs** | Tipagem forte, autocomplete, validaΓ§Γ£o | -| **Events** | Desacoplamento, extensibilidade | -| **Listeners** | ReaΓ§Γ£o a eventos de forma organizada | -| **Jobs** | Processamento em background | -| **Exceptions** | Tratamento de erro consistente | -| **Contracts/Interfaces** | Testabilidade, injeΓ§Γ£o de dependΓͺncia | -| **Testes** | Confiabilidade, refatoraΓ§Γ£o segura | - ---- - -## πŸ” Filosofia de SeguranΓ§a - -### Credenciais vs Dados Operacionais - -| Tipo | Onde Armazenar | Exemplo | -|------|----------------|---------| -| **Credenciais** | `.env` / Config | API Key, Webhook Secret, URL do servidor | -| **Dados Operacionais** | Banco de Dados | Nome da instΓ’ncia, status, nΓΊmero conectado | - -### Por que essa separaΓ§Γ£o? - -1. **SeguranΓ§a**: Credenciais no `.env` nΓ£o vazam em backups de banco -2. **ReutilizaΓ§Γ£o**: Mesma API Key para mΓΊltiplas instΓ’ncias -3. **Deploy**: Credenciais diferentes por ambiente (dev/staging/prod) -4. **Compliance**: Facilita auditoria e rotaΓ§Γ£o de chaves - -### Fluxo de AutenticaΓ§Γ£o - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Sua App │────▢│ Plugin │────▢│ Evolution API β”‚ -β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ -β”‚ Cria instΓ’ncia β”‚ β”‚ config/filament-evolution β”‚ β”‚ Valida API Key β”‚ -β”‚ "minha-loja" β”‚ β”‚ └── api.global_token β”‚ β”‚ Retorna dados β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Banco de Dados β”‚ - β”‚ β”‚ - β”‚ Salva apenas: β”‚ - β”‚ - team_id 🏒 β”‚ - β”‚ - name β”‚ - β”‚ - status β”‚ - β”‚ - number β”‚ - β”‚ - settings β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - ---- - -## πŸ“ Estrutura de DiretΓ³rios - -> 🟒 = JΓ‘ existe | 🟑 = Modificar | πŸ”΅ = Criar novo - -``` -app/ -β”œβ”€β”€ Enums/ -β”‚ └── Evolution/ -β”‚ β”œβ”€β”€ 🟒 StatusConnectionEnum.php # JΓ‘ existe - manter -β”‚ β”œβ”€β”€ πŸ”΅ MessageStatusEnum.php # NOVO: pending, sent, delivered, read, failed -β”‚ β”œβ”€β”€ πŸ”΅ MessageTypeEnum.php # NOVO: text, image, audio, video, document -β”‚ └── πŸ”΅ WebhookEventEnum.php # NOVO: Todos os eventos suportados -β”‚ -β”œβ”€β”€ Data/ # πŸ”΅ NOVO: DTOs com Spatie Data -β”‚ └── Evolution/ -β”‚ β”œβ”€β”€ InstanceData.php # Dados para criar instΓ’ncia -β”‚ β”œβ”€β”€ MessageData.php # Dados de mensagem -β”‚ β”œβ”€β”€ ContactData.php # Dados de contato -β”‚ β”œβ”€β”€ QrCodeData.php # QR Code + pairing code -β”‚ β”œβ”€β”€ ConnectionStatusData.php # Status de conexΓ£o -β”‚ └── Webhook/ -β”‚ β”œβ”€β”€ WebhookPayloadData.php # Payload base -β”‚ β”œβ”€β”€ QrCodeUpdatedData.php # Evento QRCODE_UPDATED -β”‚ β”œβ”€β”€ ConnectionUpdateData.php # Evento CONNECTION_UPDATE -β”‚ └── MessageUpsertData.php # Evento MESSAGES_UPSERT -β”‚ -β”œβ”€β”€ Events/ # πŸ”΅ NOVO: Eventos Laravel -β”‚ └── Evolution/ -β”‚ β”œβ”€β”€ InstanceCreated.php -β”‚ β”œβ”€β”€ InstanceConnected.php -β”‚ β”œβ”€β”€ InstanceDisconnected.php -β”‚ β”œβ”€β”€ QrCodeUpdated.php -β”‚ β”œβ”€β”€ MessageReceived.php -β”‚ β”œβ”€β”€ MessageSent.php -β”‚ └── MessageStatusUpdated.php -β”‚ -β”œβ”€β”€ Exceptions/ # πŸ”΅ NOVO: ExceΓ§Γ΅es customizadas -β”‚ └── Evolution/ -β”‚ β”œβ”€β”€ EvolutionException.php # Base -β”‚ β”œβ”€β”€ ConnectionException.php -β”‚ β”œβ”€β”€ InstanceNotFoundException.php -β”‚ └── MessageFailedException.php -β”‚ -β”œβ”€β”€ Filament/ -β”‚ └── Resources/ -β”‚ └── WhatsappInstances/ # 🟒 JΓ‘ existe - manter estrutura -β”‚ β”œβ”€β”€ Pages/ -β”‚ β”œβ”€β”€ Schemas/ -β”‚ β”œβ”€β”€ Tables/ -β”‚ └── WhatsappInstanceResource.php -β”‚ -β”œβ”€β”€ Http/ -β”‚ └── Controllers/ -β”‚ └── Webhook/ -β”‚ └── 🟑 EvolutionWebhookController.php # MODIFICAR: usar DTOs e Jobs -β”‚ -β”œβ”€β”€ Jobs/ # πŸ”΅ NOVO: Jobs para background -β”‚ └── Evolution/ -β”‚ β”œβ”€β”€ ProcessWebhookJob.php # Processa webhook -β”‚ β”œβ”€β”€ SendMessageJob.php # Envia mensagem -β”‚ β”œβ”€β”€ SendBulkMessagesJob.php # Envio em massa -β”‚ └── SyncInstanceStatusJob.php # Sincroniza status -β”‚ -β”œβ”€β”€ Listeners/ # πŸ”΅ NOVO: Listeners -β”‚ └── Evolution/ -β”‚ β”œβ”€β”€ LogMessageReceived.php -β”‚ β”œβ”€β”€ UpdateInstanceStatus.php -β”‚ β”œβ”€β”€ ClearQrCodeOnConnection.php -β”‚ └── NotifyOnDisconnection.php -β”‚ -β”œβ”€β”€ Livewire/ -β”‚ └── Evolution/ -β”‚ └── 🟒 EvolutionQrCode.php # JΓ‘ existe - manter -β”‚ -β”œβ”€β”€ Models/ -β”‚ β”œβ”€β”€ 🟒 WhatsappInstance.php # JΓ‘ existe - manter -β”‚ └── πŸ”΅ WhatsappMessage.php # NOVO: HistΓ³rico de mensagens -β”‚ -β”œβ”€β”€ Services/ -β”‚ β”œβ”€β”€ Traits/ -β”‚ β”‚ └── 🟑 EvolutionClientTrait.php # MODIFICAR: adicionar retry, exceptions -β”‚ └── Evolution/ -β”‚ β”œβ”€β”€ Instance/ -β”‚ β”‚ β”œβ”€β”€ 🟒 CreateEvolutionInstanceService.php # Manter -β”‚ β”‚ β”œβ”€β”€ 🟒 ConnectEvolutionInstanceService.php # Manter -β”‚ β”‚ β”œβ”€β”€ 🟒 DeleteEvolutionInstanceService.php # Manter -β”‚ β”‚ β”œβ”€β”€ 🟒 FetchEvolutionInstanceService.php # Manter -β”‚ β”‚ β”œβ”€β”€ 🟒 LogOutEvolutionInstanceService.php # Manter -β”‚ β”‚ └── 🟒 RestartEvolutionInstanceService.php # Manter -β”‚ β”œβ”€β”€ Message/ -β”‚ β”‚ β”œβ”€β”€ 🟒 SendMessageEvolutionService.php # Manter -β”‚ β”‚ β”œβ”€β”€ πŸ”΅ SendMediaEvolutionService.php # NOVO -β”‚ β”‚ β”œβ”€β”€ πŸ”΅ SendAudioEvolutionService.php # NOVO -β”‚ β”‚ └── πŸ”΅ SendDocumentEvolutionService.php # NOVO -β”‚ └── πŸ”΅ WebhookService.php # NOVO: Configurar webhook -β”‚ -β”œβ”€β”€ Contracts/ # πŸ”΅ NOVO: Interfaces -β”‚ └── Evolution/ -β”‚ β”œβ”€β”€ EvolutionClientInterface.php -β”‚ └── MessageServiceInterface.php -β”‚ -config/ -β”‚ └── 🟒 services.php # JΓ‘ existe com evolution key -β”‚ -database/ -β”‚ └── migrations/ -β”‚ β”œβ”€β”€ 🟒 create_whatsapp_instances_table.php # JΓ‘ existe -β”‚ β”œβ”€β”€ πŸ”΅ create_whatsapp_messages_table.php # NOVO -β”‚ └── πŸ”΅ create_whatsapp_webhooks_table.php # NOVO (log) -β”‚ -resources/ -β”‚ └── views/ -β”‚ β”œβ”€β”€ filament/app/pages/evolution/ -β”‚ β”‚ └── 🟒 qr-code-modal.blade.php # JΓ‘ existe -β”‚ └── livewire/evolution/ -β”‚ └── 🟒 evolution-qr-code.blade.php # JΓ‘ existe -β”‚ -routes/ -β”‚ └── 🟑 api.php ou web.php # Verificar rota do webhook -β”‚ -tests/ -β”‚ β”œβ”€β”€ Feature/ -β”‚ β”‚ └── Evolution/ -β”‚ β”‚ β”œβ”€β”€ πŸ”΅ InstanceResourceTest.php -β”‚ β”‚ β”œβ”€β”€ πŸ”΅ WebhookControllerTest.php -β”‚ β”‚ └── πŸ”΅ SendMessageTest.php -β”‚ └── Unit/ -β”‚ └── Evolution/ -β”‚ β”œβ”€β”€ πŸ”΅ EvolutionClientTest.php -β”‚ β”œβ”€β”€ πŸ”΅ InstanceServiceTest.php -β”‚ β”œβ”€β”€ πŸ”΅ WebhookPayloadDataTest.php -β”‚ └── πŸ”΅ StatusConnectionEnumTest.php -``` - ---- - -## πŸ—„οΈ Models e Migrations - -### WhatsappInstance (🟑 MODIFICAR - Adicionar suporte a tenant) - -```php -// database/migrations/xxxx_create_whatsapp_instances_table.php -use Illuminate\Database\Migrations\Migration; -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Support\Facades\Schema; - -return new class extends Migration -{ - public function up(): void - { - Schema::create('whatsapp_instances', function (Blueprint $table) { - $table->uuid('id')->primary(); - - // 🏒 Tenant column dinΓ’mico baseado na config - $this->addTenantColumn($table); - - $table->string('name'); - $table->string('number'); - $table->string('instance_id')->nullable(); - $table->string('profile_picture_url')->nullable(); - $table->string('status')->nullable(); - $table->boolean('reject_call')->default(true); - $table->string('msg_call')->nullable(); - $table->boolean('groups_ignore')->default(true); - $table->boolean('always_online')->default(true); - $table->boolean('read_messages')->default(true); - $table->boolean('read_status')->default(true); - $table->boolean('sync_full_history')->default(true); - $table->string('count')->nullable(); - $table->string('pairing_code')->nullable(); - $table->longText('qr_code')->nullable(); - $table->timestamps(); - $table->softDeletes(); - }); - } - - /** - * Adiciona coluna de tenant dinamicamente baseado na config - */ - private function addTenantColumn(Blueprint $table): void - { - if (!config('filament-evolution.tenancy.enabled', false)) { - return; - } - - $column = config('filament-evolution.tenancy.column', 'team_id'); - $tenantTable = config('filament-evolution.tenancy.table', 'teams'); - $columnType = config('filament-evolution.tenancy.column_type', 'uuid'); - - if ($columnType === 'uuid') { - $table->foreignUuid($column) - ->constrained($tenantTable) - ->cascadeOnDelete(); - } else { - $table->foreignId($column) - ->constrained($tenantTable) - ->cascadeOnDelete(); - } - - $table->index($column); - } -}; -``` - -### WhatsappMessage (πŸ”΅ NOVO - Com tenant dinΓ’mico) - -```php -// database/migrations/xxxx_create_whatsapp_messages_table.php -return new class extends Migration -{ - public function up(): void - { - Schema::create('whatsapp_messages', function (Blueprint $table) { - $table->uuid('id')->primary(); - - // 🏒 Tenant column dinΓ’mico - $this->addTenantColumn($table); - - $table->foreignUuid('instance_id')->constrained('whatsapp_instances')->cascadeOnDelete(); - $table->string('message_id')->index(); - $table->string('remote_jid'); - $table->string('phone'); - $table->enum('direction', ['incoming', 'outgoing']); - $table->string('type')->default('text'); - $table->text('content')->nullable(); - $table->json('media')->nullable(); - $table->string('status')->default('pending'); - $table->json('raw_payload')->nullable(); - $table->timestamp('sent_at')->nullable(); - $table->timestamp('delivered_at')->nullable(); - $table->timestamp('read_at')->nullable(); - $table->timestamps(); - - $table->index(['instance_id', 'phone']); - $table->index(['instance_id', 'created_at']); - }); - } - - private function addTenantColumn(Blueprint $table): void - { - // Mesmo mΓ©todo do WhatsappInstance - if (!config('filament-evolution.tenancy.enabled', false)) { - return; - } - - $column = config('filament-evolution.tenancy.column', 'team_id'); - $tenantTable = config('filament-evolution.tenancy.table', 'teams'); - $columnType = config('filament-evolution.tenancy.column_type', 'uuid'); - - if ($columnType === 'uuid') { - $table->foreignUuid($column)->constrained($tenantTable)->cascadeOnDelete(); - } else { - $table->foreignId($column)->constrained($tenantTable)->cascadeOnDelete(); - } - - $table->index($column); - } -}; -``` - -### WhatsappWebhook (πŸ”΅ NOVO - Log de webhooks com tenant) - -```php -// database/migrations/xxxx_create_whatsapp_webhooks_table.php -return new class extends Migration -{ - public function up(): void - { - Schema::create('whatsapp_webhooks', function (Blueprint $table) { - $table->id(); - - // 🏒 Tenant column dinΓ’mico - $this->addTenantColumn($table); - - $table->foreignUuid('instance_id')->nullable()->constrained('whatsapp_instances')->nullOnDelete(); - $table->string('event'); - $table->json('payload'); - $table->boolean('processed')->default(false); - $table->text('error')->nullable(); - $table->integer('processing_time_ms')->nullable(); - $table->timestamps(); - - $table->index(['event', 'processed']); - $table->index('created_at'); - }); - } - - private function addTenantColumn(Blueprint $table): void - { - // Mesmo mΓ©todo - if (!config('filament-evolution.tenancy.enabled', false)) { - return; - } - - $column = config('filament-evolution.tenancy.column', 'team_id'); - $tenantTable = config('filament-evolution.tenancy.table', 'teams'); - $columnType = config('filament-evolution.tenancy.column_type', 'uuid'); - - if ($columnType === 'uuid') { - $table->foreignUuid($column)->constrained($tenantTable)->cascadeOnDelete(); - } else { - $table->foreignId($column)->constrained($tenantTable)->cascadeOnDelete(); - } - - $table->index($column); - } -}; -``` - -### Trait para Migrations com Tenant - -```php -// src/Database/Migrations/Concerns/HasTenantColumn.php -namespace WallaceMartinss\FilamentEvolution\Database\Migrations\Concerns; - -use Illuminate\Database\Schema\Blueprint; - -trait HasTenantColumn -{ - protected function addTenantColumn(Blueprint $table): void - { - if (!config('filament-evolution.tenancy.enabled', false)) { - return; - } - - $column = config('filament-evolution.tenancy.column', 'team_id'); - $tenantTable = config('filament-evolution.tenancy.table', 'teams'); - $columnType = config('filament-evolution.tenancy.column_type', 'uuid'); - - if ($columnType === 'uuid') { - $table->foreignUuid($column) - ->constrained($tenantTable) - ->cascadeOnDelete(); - } else { - $table->foreignId($column) - ->constrained($tenantTable) - ->cascadeOnDelete(); - } - - $table->index($column); - } -} -``` - ---- - -## 🏒 Models com Multi-Tenancy - -### Trait para Models com Tenant - -```php -// src/Models/Concerns/HasTenant.php -namespace WallaceMartinss\FilamentEvolution\Models\Concerns; - -use Illuminate\Database\Eloquent\Builder; -use Illuminate\Database\Eloquent\Relations\BelongsTo; - -trait HasTenant -{ - public static function bootHasTenant(): void - { - if (!config('filament-evolution.tenancy.enabled', false)) { - return; - } - - // Global scope para filtrar por tenant - static::addGlobalScope('tenant', function (Builder $query) { - $tenantColumn = config('filament-evolution.tenancy.column', 'team_id'); - $tenant = filament()->getTenant(); - - if ($tenant) { - $query->where($tenantColumn, $tenant->getKey()); - } - }); - - // Auto-preenche tenant ao criar - static::creating(function ($model) { - $tenantColumn = config('filament-evolution.tenancy.column', 'team_id'); - $tenant = filament()->getTenant(); - - if ($tenant && empty($model->{$tenantColumn})) { - $model->{$tenantColumn} = $tenant->getKey(); - } - }); - } - - /** - * Relacionamento dinΓ’mico com o Tenant - */ - public function tenant(): ?BelongsTo - { - if (!config('filament-evolution.tenancy.enabled', false)) { - return null; - } - - $tenantColumn = config('filament-evolution.tenancy.column', 'team_id'); - $tenantModel = config('filament-evolution.tenancy.model', 'App\\Models\\Team'); - - return $this->belongsTo($tenantModel, $tenantColumn); - } - - /** - * Retorna o nome da coluna do tenant - */ - public function getTenantColumn(): ?string - { - if (!config('filament-evolution.tenancy.enabled', false)) { - return null; - } - - return config('filament-evolution.tenancy.column', 'team_id'); - } -} -``` - -### WhatsappInstance Model - -```php -// src/Models/WhatsappInstance.php -namespace WallaceMartinss\FilamentEvolution\Models; - -use Illuminate\Database\Eloquent\Concerns\HasUuids; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\SoftDeletes; -use WallaceMartinss\FilamentEvolution\Enums\StatusConnectionEnum; -use WallaceMartinss\FilamentEvolution\Models\Concerns\HasTenant; - -class WhatsappInstance extends Model -{ - use HasUuids; - use HasTenant; - use SoftDeletes; - - protected $fillable = [ - 'name', - 'number', - 'instance_id', - 'profile_picture_url', - 'status', - 'reject_call', - 'msg_call', - 'groups_ignore', - 'always_online', - 'read_messages', - 'read_status', - 'sync_full_history', - 'count', - 'pairing_code', - 'qr_code', - ]; - - protected function casts(): array - { - return [ - 'status' => StatusConnectionEnum::class, - 'reject_call' => 'boolean', - 'groups_ignore' => 'boolean', - 'always_online' => 'boolean', - 'read_messages' => 'boolean', - 'read_status' => 'boolean', - 'sync_full_history' => 'boolean', - ]; - } - - public function messages(): HasMany - { - return $this->hasMany(WhatsappMessage::class, 'instance_id'); - } - - public function webhooks(): HasMany - { - return $this->hasMany(WhatsappWebhook::class, 'instance_id'); - } - - public function isConnected(): bool - { - return $this->status === StatusConnectionEnum::OPEN; - } - - public function isDisconnected(): bool - { - return in_array($this->status, [ - StatusConnectionEnum::CLOSE, - StatusConnectionEnum::REFUSED, - ]); - } -} -``` - -### WhatsappMessage Model - -```php -// src/Models/WhatsappMessage.php -namespace WallaceMartinss\FilamentEvolution\Models; - -use Illuminate\Database\Eloquent\Concerns\HasUuids; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; -use WallaceMartinss\FilamentEvolution\Enums\MessageDirectionEnum; -use WallaceMartinss\FilamentEvolution\Enums\MessageStatusEnum; -use WallaceMartinss\FilamentEvolution\Enums\MessageTypeEnum; -use WallaceMartinss\FilamentEvolution\Models\Concerns\HasTenant; - -class WhatsappMessage extends Model -{ - use HasUuids; - use HasTenant; - - protected $fillable = [ - 'instance_id', - 'message_id', - 'remote_jid', - 'phone', - 'direction', - 'type', - 'content', - 'media', - 'status', - 'raw_payload', - 'sent_at', - 'delivered_at', - 'read_at', - ]; - - protected function casts(): array - { - return [ - 'direction' => MessageDirectionEnum::class, - 'type' => MessageTypeEnum::class, - 'status' => MessageStatusEnum::class, - 'media' => 'array', - 'raw_payload' => 'array', - 'sent_at' => 'datetime', - 'delivered_at' => 'datetime', - 'read_at' => 'datetime', - ]; - } - - public function instance(): BelongsTo - { - return $this->belongsTo(WhatsappInstance::class, 'instance_id'); - } - - public function isIncoming(): bool - { - return $this->direction === MessageDirectionEnum::INCOMING; - } - - public function isOutgoing(): bool - { - return $this->direction === MessageDirectionEnum::OUTGOING; - } -} -``` - ---- - -## πŸ“¦ DTOs (Data Transfer Objects) - -> Usando [Spatie Laravel Data](https://spatie.be/docs/laravel-data) para tipagem forte e validaΓ§Γ£o. - -### InstanceData - -```php -// app/Data/Evolution/InstanceData.php -namespace App\Data\Evolution; - -use Spatie\LaravelData\Data; - -class InstanceData extends Data -{ - public function __construct( - public string $name, - public string $number, - public bool $rejectCall = true, - public ?string $msgCall = null, - public bool $groupsIgnore = true, - public bool $alwaysOnline = true, - public bool $readMessages = true, - public bool $readStatus = true, - public bool $syncFullHistory = true, - ) {} - - public function toApiPayload(): array - { - return [ - 'instanceName' => $this->name, - 'number' => preg_replace('/\D/', '', $this->number), - 'qrcode' => true, - 'integration' => config('filament-evolution.instance.integration', 'WHATSAPP-BAILEYS'), - 'rejectCall' => $this->rejectCall, - 'msgCall' => $this->msgCall ?? '', - 'groupsIgnore' => $this->groupsIgnore, - 'alwaysOnline' => $this->alwaysOnline, - 'readMessages' => $this->readMessages, - 'readStatus' => $this->readStatus, - 'syncFullHistory' => $this->syncFullHistory, - 'webhook' => [ - 'url' => url(config('filament-evolution.webhook.path')), - 'byEvents' => false, - 'base64' => false, - 'events' => config('filament-evolution.webhook.events', [ - 'QRCODE_UPDATED', - 'CONNECTION_UPDATE', - 'MESSAGES_UPSERT', - ]), - ], - ]; - } -} -``` - -### QrCodeData - -```php -// app/Data/Evolution/QrCodeData.php -namespace App\Data\Evolution; - -use Spatie\LaravelData\Data; - -class QrCodeData extends Data -{ - public function __construct( - public ?string $base64 = null, - public ?string $pairingCode = null, - public ?string $code = null, - public ?int $count = null, - ) {} - - public static function fromApiResponse(array $response): self - { - return new self( - base64: $response['base64'] ?? $response['qrcode']['base64'] ?? null, - pairingCode: $response['pairingCode'] ?? $response['qrcode']['pairingCode'] ?? null, - code: $response['code'] ?? null, - count: $response['count'] ?? null, - ); - } - - public function isValid(): bool - { - return $this->base64 !== null; - } -} -``` - -### MessageData - -```php -// app/Data/Evolution/MessageData.php -namespace App\Data\Evolution; - -use App\Enums\Evolution\MessageTypeEnum; -use Spatie\LaravelData\Data; - -class MessageData extends Data -{ - public function __construct( - public string $number, - public string $content, - public MessageTypeEnum $type = MessageTypeEnum::TEXT, - public ?string $caption = null, - public ?string $mediaUrl = null, - public ?string $filename = null, - public ?int $delay = null, - ) {} - - public function toApiPayload(): array - { - $number = preg_replace('/\D/', '', $this->number); - - return match($this->type) { - MessageTypeEnum::TEXT => [ - 'number' => $number, - 'text' => $this->content, - ], - MessageTypeEnum::IMAGE, MessageTypeEnum::VIDEO => [ - 'number' => $number, - 'media' => $this->mediaUrl ?? $this->content, - 'caption' => $this->caption ?? '', - ], - MessageTypeEnum::AUDIO => [ - 'number' => $number, - 'audio' => $this->mediaUrl ?? $this->content, - ], - MessageTypeEnum::DOCUMENT => [ - 'number' => $number, - 'document' => $this->mediaUrl ?? $this->content, - 'filename' => $this->filename ?? 'document', - ], - default => ['number' => $number, 'text' => $this->content], - }; - } -} -``` - -### Webhook DTOs - -```php -// app/Data/Evolution/Webhook/ConnectionUpdateData.php -namespace App\Data\Evolution\Webhook; - -use App\Enums\Evolution\StatusConnectionEnum; -use Spatie\LaravelData\Data; - -class ConnectionUpdateData extends Data -{ - public function __construct( - public string $instance, - public string $state, - public ?int $statusReason = null, - ) {} - - public static function fromWebhook(array $payload): self - { - return new self( - instance: $payload['instance'], - state: $payload['data']['state'], - statusReason: $payload['data']['statusReason'] ?? null, - ); - } - - public function getStatus(): StatusConnectionEnum - { - return StatusConnectionEnum::tryFrom($this->state) - ?? StatusConnectionEnum::CLOSE; - } - - public function isConnected(): bool - { - return $this->state === 'open'; - } - - public function isDisconnected(): bool - { - return in_array($this->state, ['close', 'refused']); - } -} -``` - -```php -// app/Data/Evolution/Webhook/QrCodeUpdatedData.php -namespace App\Data\Evolution\Webhook; - -use App\Data\Evolution\QrCodeData; -use Spatie\LaravelData\Data; - -class QrCodeUpdatedData extends Data -{ - public function __construct( - public string $instance, - public QrCodeData $qrCode, - ) {} - - public static function fromWebhook(array $payload): self - { - return new self( - instance: $payload['instance'], - qrCode: new QrCodeData( - base64: $payload['data']['qrcode']['base64'] ?? null, - pairingCode: $payload['data']['qrcode']['pairingCode'] ?? null, - ), - ); - } -} -``` - -```php -// app/Data/Evolution/Webhook/MessageUpsertData.php -namespace App\Data\Evolution\Webhook; - -use Spatie\LaravelData\Data; -use Illuminate\Support\Str; - -class MessageUpsertData extends Data -{ - public function __construct( - public string $instance, - public string $messageId, - public string $remoteJid, - public string $phone, - public bool $fromMe, - public string $messageType, - public ?string $text = null, - public ?string $caption = null, - public ?array $media = null, - public ?int $timestamp = null, - ) {} - - public static function fromWebhook(array $payload): self - { - $data = $payload['data'] ?? []; - $key = $data['key'] ?? []; - $message = $data['message'] ?? []; - - return new self( - instance: $payload['instance'], - messageId: $key['id'] ?? '', - remoteJid: $key['remoteJid'] ?? '', - phone: Str::before($key['remoteJid'] ?? '', '@'), - fromMe: $key['fromMe'] ?? false, - messageType: $data['messageType'] ?? 'unknown', - text: $message['conversation'] - ?? $message['extendedTextMessage']['text'] - ?? null, - caption: $message['imageMessage']['caption'] - ?? $message['videoMessage']['caption'] - ?? null, - media: self::extractMedia($message), - timestamp: isset($data['messageTimestamp']) - ? (int) $data['messageTimestamp'] - : null, - ); - } - - private static function extractMedia(array $message): ?array - { - $mediaTypes = ['imageMessage', 'audioMessage', 'videoMessage', 'documentMessage']; - - foreach ($mediaTypes as $type) { - if (isset($message[$type])) { - return [ - 'type' => $type, - 'mimetype' => $message[$type]['mimetype'] ?? null, - 'url' => $message[$type]['url'] ?? null, - ]; - } - } - - return null; - } - - public function isIncoming(): bool - { - return !$this->fromMe; - } - - public function getContent(): ?string - { - return $this->text ?? $this->caption; - } -} -``` - ---- - -## βš™οΈ Arquivo de ConfiguraΓ§Γ£o - -> πŸ” **Todas as credenciais ficam aqui, nunca no banco de dados!** - -```php -// config/filament-evolution.php -return [ - /* - |-------------------------------------------------------------------------- - | Evolution API Connection (CREDENCIAIS SENSÍVEIS) - |-------------------------------------------------------------------------- - | - | Estas configuraΓ§Γ΅es sΓ£o obrigatΓ³rias e devem ser definidas no .env - | NUNCA armazene estas credenciais no banco de dados! - | - */ - 'api' => [ - 'base_url' => env('EVOLUTION_API_URL', 'http://localhost:8080'), - 'global_token' => env('EVOLUTION_API_KEY'), // πŸ” API Key global - 'timeout' => env('EVOLUTION_TIMEOUT', 30), - 'retry' => [ - 'times' => 3, - 'sleep' => 100, // ms - ], - ], - - /* - |-------------------------------------------------------------------------- - | Webhook Configuration (SEGURANΓ‡A) - |-------------------------------------------------------------------------- - | - | O secret Γ© usado para validar que os webhooks vΓͺm da Evolution API - | - */ - 'webhook' => [ - 'path' => env('EVOLUTION_WEBHOOK_PATH', 'api/evolution/webhook'), - 'secret' => env('EVOLUTION_WEBHOOK_SECRET'), // πŸ” Para validar origem - 'verify_signature' => env('EVOLUTION_VERIFY_SIGNATURE', true), - 'queue' => env('EVOLUTION_WEBHOOK_QUEUE', 'default'), - 'events' => [ - 'QRCODE_UPDATED', - 'CONNECTION_UPDATE', - 'MESSAGES_UPSERT', - 'MESSAGES_UPDATE', - 'MESSAGES_DELETE', - 'SEND_MESSAGE', - ], - ], - - /* - |-------------------------------------------------------------------------- - | Instance Defaults (ConfiguraΓ§Γ΅es padrΓ£o para novas instΓ’ncias) - |-------------------------------------------------------------------------- - */ - 'instance' => [ - 'integration' => env('EVOLUTION_INTEGRATION', 'WHATSAPP-BAILEYS'), - 'reject_call' => env('EVOLUTION_REJECT_CALL', false), - 'msg_call' => env('EVOLUTION_MSG_CALL', ''), - 'groups_ignore' => env('EVOLUTION_GROUPS_IGNORE', false), - 'always_online' => env('EVOLUTION_ALWAYS_ONLINE', false), - 'read_messages' => env('EVOLUTION_READ_MESSAGES', false), - 'read_status' => env('EVOLUTION_READ_STATUS', false), - 'sync_full_history' => env('EVOLUTION_SYNC_HISTORY', false), - ], - - /* - |-------------------------------------------------------------------------- - | Filament Configuration - |-------------------------------------------------------------------------- - */ - 'filament' => [ - 'navigation_group' => 'WhatsApp', - 'navigation_icon' => 'fab-whatsapp', - 'navigation_sort' => 100, - 'resource_label' => 'InstΓ’ncia', - 'resource_plural_label' => 'InstΓ’ncias', - ], - - /* - |-------------------------------------------------------------------------- - | Storage & Cache - |-------------------------------------------------------------------------- - */ - 'cache' => [ - 'enabled' => true, - 'ttl' => 60, // segundos - 'prefix' => 'evolution_', - ], - - /* - |-------------------------------------------------------------------------- - | Queue Configuration - |-------------------------------------------------------------------------- - */ - 'queue' => [ - 'connection' => env('EVOLUTION_QUEUE_CONNECTION', 'redis'), - 'messages' => env('EVOLUTION_QUEUE_MESSAGES', 'whatsapp'), - 'webhooks' => env('EVOLUTION_QUEUE_WEBHOOKS', 'default'), - ], - - /* - |-------------------------------------------------------------------------- - | Logging - |-------------------------------------------------------------------------- - */ - 'logging' => [ - 'enabled' => env('EVOLUTION_LOGGING', true), - 'channel' => env('EVOLUTION_LOG_CHANNEL', 'stack'), - 'log_payloads' => env('EVOLUTION_LOG_PAYLOADS', false), // Cuidado: pode conter dados sensΓ­veis - ], - - /* - |-------------------------------------------------------------------------- - | Multi-Tenancy Configuration - |-------------------------------------------------------------------------- - | - | ConfiguraΓ§Γ£o para suporte a mΓΊltiplos tenants no Filament. - | Se habilitado, as migrations incluirΓ£o a foreign key do tenant - | e os models aplicarΓ£o scope automΓ‘tico. - | - */ - 'tenancy' => [ - 'enabled' => env('EVOLUTION_TENANCY_ENABLED', false), - - // Nome da coluna de tenant nas tabelas (ex: 'team_id', 'company_id', 'tenant_id') - 'column' => env('EVOLUTION_TENANT_COLUMN', 'team_id'), - - // Tabela do tenant para a foreign key (ex: 'teams', 'companies', 'tenants') - 'table' => env('EVOLUTION_TENANT_TABLE', 'teams'), - - // Model do tenant (ex: App\Models\Team::class) - 'model' => env('EVOLUTION_TENANT_MODEL', 'App\\Models\\Team'), - - // Tipo da coluna do tenant ('uuid' ou 'id') - 'column_type' => env('EVOLUTION_TENANT_COLUMN_TYPE', 'uuid'), - ], -]; -``` - -### Exemplo de `.env` - -```env -# Evolution API - Credenciais (OBRIGATΓ“RIO) -EVOLUTION_API_URL=https://evolution.meudominio.com -EVOLUTION_API_KEY=seu_token_secreto_aqui - -# Webhook -EVOLUTION_WEBHOOK_SECRET=meu_secret_para_validar_webhooks -EVOLUTION_WEBHOOK_PATH=api/evolution/webhook - -# ConfiguraΓ§Γ΅es opcionais -EVOLUTION_INTEGRATION=WHATSAPP-BAILEYS -EVOLUTION_TIMEOUT=30 -EVOLUTION_REJECT_CALL=false -EVOLUTION_GROUPS_IGNORE=false -EVOLUTION_ALWAYS_ONLINE=false - -# Queue -EVOLUTION_QUEUE_CONNECTION=redis -EVOLUTION_QUEUE_MESSAGES=whatsapp - -# Logging -EVOLUTION_LOGGING=true -EVOLUTION_LOG_PAYLOADS=false - -# Multi-Tenancy (opcional) -EVOLUTION_TENANCY_ENABLED=true -EVOLUTION_TENANT_COLUMN=team_id -EVOLUTION_TENANT_TABLE=teams -EVOLUTION_TENANT_MODEL=App\Models\Team -EVOLUTION_TENANT_COLUMN_TYPE=uuid -``` - ---- - -## πŸ“‘ Events (Eventos Laravel) - -> Eventos permitem desacoplar a lΓ³gica e facilitar extensΓ΅es. - -```php -// app/Events/Evolution/InstanceConnected.php -namespace App\Events\Evolution; - -use App\Models\WhatsappInstance; -use Illuminate\Foundation\Events\Dispatchable; -use Illuminate\Queue\SerializesModels; - -class InstanceConnected -{ - use Dispatchable, SerializesModels; - - public function __construct( - public WhatsappInstance $instance, - ) {} -} - -// app/Events/Evolution/InstanceDisconnected.php -class InstanceDisconnected -{ - use Dispatchable, SerializesModels; - - public function __construct( - public WhatsappInstance $instance, - public string $reason = 'unknown', - ) {} -} - -// app/Events/Evolution/QrCodeUpdated.php -use App\Data\Evolution\QrCodeData; - -class QrCodeUpdated -{ - use Dispatchable, SerializesModels; - - public function __construct( - public WhatsappInstance $instance, - public QrCodeData $qrCode, - ) {} -} - -// app/Events/Evolution/MessageReceived.php -use App\Data\Evolution\Webhook\MessageUpsertData; - -class MessageReceived -{ - use Dispatchable, SerializesModels; - - public function __construct( - public WhatsappInstance $instance, - public MessageUpsertData $message, - ) {} -} - -// app/Events/Evolution/MessageSent.php -class MessageSent -{ - use Dispatchable, SerializesModels; - - public function __construct( - public WhatsappInstance $instance, - public string $phone, - public string $messageId, - public string $content, - ) {} -} -``` - ---- - -## πŸ‘‚ Listeners - -```php -// app/Listeners/Evolution/UpdateInstanceStatus.php -namespace App\Listeners\Evolution; - -use App\Events\Evolution\{InstanceConnected, InstanceDisconnected}; -use App\Services\Evolution\Instance\FetchEvolutionInstanceService; - -class UpdateInstanceStatus -{ - public function handleConnected(InstanceConnected $event): void - { - $event->instance->update([ - 'status' => 'open', - 'qr_code' => null, - 'pairing_code' => null, - ]); - - // Buscar foto de perfil - app(FetchEvolutionInstanceService::class)->fetchInstance($event->instance->name); - } - - public function handleDisconnected(InstanceDisconnected $event): void - { - $event->instance->update([ - 'status' => 'close', - ]); - } -} - -// app/Listeners/Evolution/ClearQrCodeOnConnection.php -class ClearQrCodeOnConnection -{ - public function handle(InstanceConnected $event): void - { - $event->instance->update([ - 'qr_code' => null, - 'pairing_code' => null, - ]); - } -} - -// app/Listeners/Evolution/LogMessageReceived.php -use App\Events\Evolution\MessageReceived; -use App\Models\WhatsappMessage; - -class LogMessageReceived -{ - public function handle(MessageReceived $event): void - { - WhatsappMessage::create([ - 'instance_id' => $event->instance->id, - 'message_id' => $event->message->messageId, - 'remote_jid' => $event->message->remoteJid, - 'phone' => $event->message->phone, - 'direction' => 'incoming', - 'type' => $event->message->messageType, - 'content' => $event->message->getContent(), - 'media' => $event->message->media, - 'status' => 'received', - ]); - } -} -``` - -### Registrar Listeners (EventServiceProvider) - -```php -// app/Providers/EventServiceProvider.php -protected $listen = [ - \App\Events\Evolution\InstanceConnected::class => [ - \App\Listeners\Evolution\UpdateInstanceStatus::class . '@handleConnected', - \App\Listeners\Evolution\ClearQrCodeOnConnection::class, - ], - \App\Events\Evolution\InstanceDisconnected::class => [ - \App\Listeners\Evolution\UpdateInstanceStatus::class . '@handleDisconnected', - ], - \App\Events\Evolution\MessageReceived::class => [ - \App\Listeners\Evolution\LogMessageReceived::class, - ], -]; -``` - ---- - -## ⚑ Jobs (Processamento em Background) - -```php -// app/Jobs/Evolution/ProcessWebhookJob.php -namespace App\Jobs\Evolution; - -use App\Data\Evolution\Webhook\{ConnectionUpdateData, MessageUpsertData, QrCodeUpdatedData}; -use App\Enums\Evolution\WebhookEventEnum; -use App\Events\Evolution\{InstanceConnected, InstanceDisconnected, MessageReceived, QrCodeUpdated}; -use App\Models\{WhatsappInstance, WhatsappWebhook}; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Foundation\Bus\Dispatchable; -use Illuminate\Queue\{InteractsWithQueue, SerializesModels}; - -class ProcessWebhookJob implements ShouldQueue -{ - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - - public function __construct( - public string $event, - public array $payload, - ) {} - - public function handle(): void - { - $startTime = microtime(true); - $webhookLog = null; - - try { - $instance = WhatsappInstance::where('name', $this->payload['instance'] ?? null)->first(); - - // Log do webhook - $webhookLog = WhatsappWebhook::create([ - 'instance_id' => $instance?->id, - 'event' => $this->event, - 'payload' => $this->payload, - 'processed' => false, - ]); - - match($this->event) { - 'connection.update' => $this->handleConnectionUpdate($instance), - 'qrcode.updated' => $this->handleQrCodeUpdated($instance), - 'messages.upsert' => $this->handleMessageUpsert($instance), - default => null, - }; - - $webhookLog->update([ - 'processed' => true, - 'processing_time_ms' => (int) ((microtime(true) - $startTime) * 1000), - ]); - - } catch (\Throwable $e) { - $webhookLog?->update([ - 'error' => $e->getMessage(), - 'processing_time_ms' => (int) ((microtime(true) - $startTime) * 1000), - ]); - - throw $e; - } - } - - private function handleConnectionUpdate(?WhatsappInstance $instance): void - { - if (!$instance) return; - - $data = ConnectionUpdateData::fromWebhook($this->payload); - - if ($data->isConnected()) { - event(new InstanceConnected($instance)); - } elseif ($data->isDisconnected()) { - event(new InstanceDisconnected($instance, $data->state)); - } - - $instance->update(['status' => $data->state]); - } - - private function handleQrCodeUpdated(?WhatsappInstance $instance): void - { - if (!$instance) return; - - $data = QrCodeUpdatedData::fromWebhook($this->payload); - - $instance->update([ - 'qr_code' => $data->qrCode->base64, - 'pairing_code' => $data->qrCode->pairingCode, - ]); - - event(new QrCodeUpdated($instance, $data->qrCode)); - } - - private function handleMessageUpsert(?WhatsappInstance $instance): void - { - if (!$instance) return; - - $data = MessageUpsertData::fromWebhook($this->payload); - - if ($data->isIncoming()) { - event(new MessageReceived($instance, $data)); - } - } -} -``` - -```php -// app/Jobs/Evolution/SendMessageJob.php -namespace App\Jobs\Evolution; - -use App\Data\Evolution\MessageData; -use App\Events\Evolution\MessageSent; -use App\Models\{WhatsappInstance, WhatsappMessage}; -use App\Services\Evolution\Message\SendMessageEvolutionService; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Foundation\Bus\Dispatchable; -use Illuminate\Queue\{InteractsWithQueue, SerializesModels}; - -class SendMessageJob implements ShouldQueue -{ - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - - public int $tries = 3; - public int $backoff = 5; - - public function __construct( - public WhatsappInstance $instance, - public MessageData $message, - ) {} - - public function handle(SendMessageEvolutionService $service): void - { - $response = $service->sendMessage($this->instance->name, [ - 'number_whatsapp' => $this->message->number, - 'message' => $this->message->content, - ]); - - if (isset($response['error'])) { - throw new \Exception($response['error']); - } - - // Salvar mensagem enviada - WhatsappMessage::create([ - 'instance_id' => $this->instance->id, - 'message_id' => $response['key']['id'] ?? '', - 'remote_jid' => $response['key']['remoteJid'] ?? '', - 'phone' => $this->message->number, - 'direction' => 'outgoing', - 'type' => 'text', - 'content' => $this->message->content, - 'status' => $response['status'] ?? 'pending', - 'sent_at' => now(), - ]); - - event(new MessageSent( - $this->instance, - $this->message->number, - $response['key']['id'] ?? '', - $this->message->content, - )); - } -} -``` - ---- - -## πŸ”„ Webhook Controller Refatorado - -```php -// app/Http/Controllers/Webhook/EvolutionWebhookController.php -namespace App\Http\Controllers\Webhook; - -use App\Http\Controllers\Controller; -use App\Jobs\Evolution\ProcessWebhookJob; -use Illuminate\Http\{JsonResponse, Request}; - -class EvolutionWebhookController extends Controller -{ - public function handle(Request $request): JsonResponse - { - $event = $request->input('event'); - $payload = $request->all(); - - // Despacha para processamento em background - ProcessWebhookJob::dispatch($event, $payload) - ->onQueue(config('services.evolution.webhook_queue', 'default')); - - return response()->json(['status' => 'queued']); - } -} -``` - ---- - -## 🎯 Enums - -### StatusConnectionEnum (🟒 JÁ EXISTE - Perfeito!) - -```php -// Seu enum atual - PERFEITO, nΓ£o precisa mudar -namespace App\Enums\Evolution; - -use Filament\Support\Contracts\{HasColor, HasLabel}; - -enum StatusConnectionEnum: string implements HasLabel, HasColor -{ - case CLOSE = 'close'; - case OPEN = 'open'; - case CONNECTING = 'connecting'; - case REFUSED = 'refused'; - - public function getLabel(): string - { - return match ($this) { - self::OPEN => 'Conectado', - self::CONNECTING => 'Conectando', - self::CLOSE => 'Desconectado', - self::REFUSED => 'Recusado', - }; - } - - public function getColor(): string|array|null - { - return match ($this) { - self::OPEN => 'success', - self::CONNECTING => 'warning', - self::CLOSE => 'danger', - self::REFUSED => 'danger', - }; - } -} -``` - -### MessageTypeEnum (πŸ”΅ NOVO) - -```php -// app/Enums/Evolution/MessageTypeEnum.php -namespace App\Enums\Evolution; - -use Filament\Support\Contracts\{HasColor, HasIcon, HasLabel}; - -enum MessageTypeEnum: string implements HasLabel, HasColor, HasIcon -{ - case TEXT = 'text'; - case IMAGE = 'image'; - case AUDIO = 'audio'; - case VIDEO = 'video'; - case DOCUMENT = 'document'; - case LOCATION = 'location'; - case CONTACT = 'contact'; - case STICKER = 'sticker'; - - public function getLabel(): string - { - return match ($this) { - self::TEXT => 'Texto', - self::IMAGE => 'Imagem', - self::AUDIO => 'Áudio', - self::VIDEO => 'VΓ­deo', - self::DOCUMENT => 'Documento', - self::LOCATION => 'LocalizaΓ§Γ£o', - self::CONTACT => 'Contato', - self::STICKER => 'Figurinha', - }; - } - - public function getColor(): string|array|null - { - return match ($this) { - self::TEXT => 'gray', - self::IMAGE => 'success', - self::AUDIO => 'warning', - self::VIDEO => 'info', - self::DOCUMENT => 'primary', - self::LOCATION => 'danger', - self::CONTACT => 'secondary', - self::STICKER => 'warning', - }; - } - - public function getIcon(): ?string - { - return match ($this) { - self::TEXT => 'heroicon-o-chat-bubble-left', - self::IMAGE => 'heroicon-o-photo', - self::AUDIO => 'heroicon-o-microphone', - self::VIDEO => 'heroicon-o-video-camera', - self::DOCUMENT => 'heroicon-o-document', - self::LOCATION => 'heroicon-o-map-pin', - self::CONTACT => 'heroicon-o-user', - self::STICKER => 'heroicon-o-face-smile', - }; - } -} -``` - -### MessageDirectionEnum (πŸ”΅ NOVO) - -```php -// src/Enums/MessageDirectionEnum.php -namespace WallaceMartinss\FilamentEvolution\Enums; - -use Filament\Support\Contracts\{HasColor, HasIcon, HasLabel}; - -enum MessageDirectionEnum: string implements HasLabel, HasColor, HasIcon -{ - case INCOMING = 'incoming'; - case OUTGOING = 'outgoing'; - - public function getLabel(): string - { - return match ($this) { - self::INCOMING => 'Recebida', - self::OUTGOING => 'Enviada', - }; - } - - public function getColor(): string|array|null - { - return match ($this) { - self::INCOMING => 'info', - self::OUTGOING => 'success', - }; - } - - public function getIcon(): ?string - { - return match ($this) { - self::INCOMING => 'heroicon-o-arrow-down-left', - self::OUTGOING => 'heroicon-o-arrow-up-right', - }; - } -} -``` - -### MessageStatusEnum (πŸ”΅ NOVO) - -```php -// app/Enums/Evolution/MessageStatusEnum.php -namespace App\Enums\Evolution; - -use Filament\Support\Contracts\{HasColor, HasIcon, HasLabel}; - -enum MessageStatusEnum: string implements HasLabel, HasColor, HasIcon -{ - case PENDING = 'pending'; - case SENT = 'sent'; - case DELIVERED = 'delivered'; - case READ = 'read'; - case FAILED = 'failed'; - - public function getLabel(): string - { - return match ($this) { - self::PENDING => 'Pendente', - self::SENT => 'Enviado', - self::DELIVERED => 'Entregue', - self::READ => 'Lido', - self::FAILED => 'Falhou', - }; - } - - public function getColor(): string|array|null - { - return match ($this) { - self::PENDING => 'gray', - self::SENT => 'info', - self::DELIVERED => 'warning', - self::READ => 'success', - self::FAILED => 'danger', - }; - } - - public function getIcon(): ?string - { - return match ($this) { - self::PENDING => 'heroicon-o-clock', - self::SENT => 'heroicon-o-check', - self::DELIVERED => 'heroicon-o-check', // βœ“βœ“ - self::READ => 'heroicon-o-check', // βœ“βœ“ azul - self::FAILED => 'heroicon-o-x-circle', - }; - } -} -``` - -### WebhookEventEnum (πŸ”΅ NOVO) - -```php -// app/Enums/Evolution/WebhookEventEnum.php -namespace App\Enums\Evolution; - -enum WebhookEventEnum: string -{ - case APPLICATION_STARTUP = 'application.startup'; - case QRCODE_UPDATED = 'qrcode.updated'; - case CONNECTION_UPDATE = 'connection.update'; - case MESSAGES_SET = 'messages.set'; - case MESSAGES_UPSERT = 'messages.upsert'; - case MESSAGES_UPDATE = 'messages.update'; - case MESSAGES_DELETE = 'messages.delete'; - case SEND_MESSAGE = 'send.message'; - case PRESENCE_UPDATE = 'presence.update'; - case NEW_TOKEN = 'new.token'; - case LOGOUT_INSTANCE = 'logout.instance'; - case REMOVE_INSTANCE = 'remove.instance'; - - public function label(): string - { - return match($this) { - self::QRCODE_UPDATED => 'QR Code Atualizado', - self::CONNECTION_UPDATE => 'Status de ConexΓ£o', - self::MESSAGES_UPSERT => 'Mensagem Recebida', - self::MESSAGES_UPDATE => 'Mensagem Atualizada', - self::SEND_MESSAGE => 'Mensagem Enviada', - self::LOGOUT_INSTANCE => 'Logout da InstΓ’ncia', - self::REMOVE_INSTANCE => 'InstΓ’ncia Removida', - default => $this->value, - }; - } - - public function shouldProcess(): bool - { - return in_array($this, [ - self::QRCODE_UPDATED, - self::CONNECTION_UPDATE, - self::MESSAGES_UPSERT, - self::SEND_MESSAGE, - ]); - } -} -``` - ---- - -## πŸ”Œ Services (🟒 MANTER os existentes) - -> Seus services atuais estΓ£o funcionais. SugestΓ£o: adicionar tipagem com DTOs. - -### Melhoria no EvolutionClientTrait - -```php -// app/Services/Traits/EvolutionClientTrait.php -namespace App\Services\Traits; - -use App\Exceptions\Evolution\{ConnectionException, EvolutionException}; -use Illuminate\Support\Facades\Http; - -trait EvolutionClientTrait -{ - protected string $apiKey; - protected string $apiUrl; - - public function __construct() - { - $this->apiKey = config('services.evolution.key'); - $this->apiUrl = config('services.evolution.url'); - - if (empty($this->apiKey) || empty($this->apiUrl)) { - throw new EvolutionException('Evolution API nΓ£o configurada. Verifique EVOLUTION_API_KEY e EVOLUTION_URL no .env'); - } - } - - protected function makeRequest(string $endpoint, string $method = 'GET', array $data = []): array - { - try { - $response = Http::withHeaders([ - 'Content-Type' => 'application/json', - 'apikey' => $this->apiKey, - ]) - ->timeout(config('services.evolution.timeout', 30)) - ->retry(3, 100) - ->{strtolower($method)}($this->apiUrl . $endpoint, $data); - - if ($response->failed()) { - throw new ConnectionException( - "Erro na API Evolution: " . ($response->json()['message'] ?? $response->status()) - ); - } - - return $response->json(); - - } catch (\Illuminate\Http\Client\ConnectionException $e) { - throw new ConnectionException("NΓ£o foi possΓ­vel conectar Γ  API Evolution: " . $e->getMessage()); - } - } -} -``` - ---- - -## πŸ§ͺ Estrutura de Testes - -### Testes UnitΓ‘rios - -```php -// tests/Unit/Evolution/StatusConnectionEnumTest.php -namespace Tests\Unit\Evolution; - -use App\Enums\Evolution\StatusConnectionEnum; -use PHPUnit\Framework\Attributes\Test; -use Tests\TestCase; - -class StatusConnectionEnumTest extends TestCase -{ - #[Test] - public function it_returns_correct_labels(): void - { - $this->assertEquals('Conectado', StatusConnectionEnum::OPEN->getLabel()); - $this->assertEquals('Desconectado', StatusConnectionEnum::CLOSE->getLabel()); - $this->assertEquals('Conectando', StatusConnectionEnum::CONNECTING->getLabel()); - } - - #[Test] - public function it_returns_correct_colors(): void - { - $this->assertEquals('success', StatusConnectionEnum::OPEN->getColor()); - $this->assertEquals('danger', StatusConnectionEnum::CLOSE->getColor()); - $this->assertEquals('warning', StatusConnectionEnum::CONNECTING->getColor()); - } - - #[Test] - public function it_can_be_created_from_string(): void - { - $this->assertEquals(StatusConnectionEnum::OPEN, StatusConnectionEnum::from('open')); - $this->assertEquals(StatusConnectionEnum::CLOSE, StatusConnectionEnum::from('close')); - } -} - -// tests/Unit/Evolution/InstanceDataTest.php -namespace Tests\Unit\Evolution; - -use App\Data\Evolution\InstanceData; -use PHPUnit\Framework\Attributes\Test; -use Tests\TestCase; - -class InstanceDataTest extends TestCase -{ - #[Test] - public function it_creates_instance_data(): void - { - $data = new InstanceData( - name: 'test-instance', - number: '5511999999999', - ); - - $this->assertEquals('test-instance', $data->name); - $this->assertEquals('5511999999999', $data->number); - } - - #[Test] - public function it_converts_to_api_payload(): void - { - $data = new InstanceData( - name: 'test-instance', - number: '+55 (11) 99999-9999', - rejectCall: true, - ); - - $payload = $data->toApiPayload(); - - $this->assertEquals('test-instance', $payload['instanceName']); - $this->assertEquals('5511999999999', $payload['number']); // Formatado - $this->assertTrue($payload['rejectCall']); - $this->assertArrayHasKey('webhook', $payload); - } -} - -// tests/Unit/Evolution/ConnectionUpdateDataTest.php -namespace Tests\Unit\Evolution; - -use App\Data\Evolution\Webhook\ConnectionUpdateData; -use App\Enums\Evolution\StatusConnectionEnum; -use PHPUnit\Framework\Attributes\Test; -use Tests\TestCase; - -class ConnectionUpdateDataTest extends TestCase -{ - #[Test] - public function it_parses_webhook_payload(): void - { - $payload = [ - 'instance' => 'test-instance', - 'data' => [ - 'state' => 'open', - 'statusReason' => 200, - ], - ]; - - $data = ConnectionUpdateData::fromWebhook($payload); - - $this->assertEquals('test-instance', $data->instance); - $this->assertEquals('open', $data->state); - $this->assertTrue($data->isConnected()); - $this->assertFalse($data->isDisconnected()); - } - - #[Test] - public function it_detects_disconnection(): void - { - $payload = [ - 'instance' => 'test-instance', - 'data' => ['state' => 'close'], - ]; - - $data = ConnectionUpdateData::fromWebhook($payload); - - $this->assertTrue($data->isDisconnected()); - $this->assertEquals(StatusConnectionEnum::CLOSE, $data->getStatus()); - } -} - -// tests/Unit/Evolution/MessageUpsertDataTest.php -namespace Tests\Unit\Evolution; - -use App\Data\Evolution\Webhook\MessageUpsertData; -use PHPUnit\Framework\Attributes\Test; -use Tests\TestCase; - -class MessageUpsertDataTest extends TestCase -{ - #[Test] - public function it_parses_text_message(): void - { - $payload = $this->getFixture('messages-upsert.json'); - - $data = MessageUpsertData::fromWebhook($payload); - - $this->assertEquals('test-instance', $data->instance); - $this->assertEquals('5511999999999', $data->phone); - $this->assertEquals('OlΓ‘, tudo bem?', $data->text); - $this->assertTrue($data->isIncoming()); - } - - #[Test] - public function it_extracts_caption_from_image(): void - { - $payload = [ - 'instance' => 'test', - 'data' => [ - 'key' => ['id' => '123', 'remoteJid' => '5511@s.whatsapp.net', 'fromMe' => false], - 'messageType' => 'imageMessage', - 'message' => [ - 'imageMessage' => [ - 'caption' => 'Foto do produto', - 'mimetype' => 'image/jpeg', - ], - ], - ], - ]; - - $data = MessageUpsertData::fromWebhook($payload); - - $this->assertEquals('Foto do produto', $data->caption); - $this->assertEquals('Foto do produto', $data->getContent()); - } - - private function getFixture(string $name): array - { - return json_decode( - file_get_contents(base_path("tests/Fixtures/webhook-payloads/{$name}")), - true - ); - } -} -``` - -### Testes de Feature - -```php -// tests/Feature/Evolution/WhatsappInstanceResourceTest.php -namespace Tests\Feature\Evolution; - -use App\Filament\Resources\WhatsappInstances\WhatsappInstanceResource; -use App\Filament\Resources\WhatsappInstances\Pages\ListWhatsappInstances; -use App\Models\WhatsappInstance; -use Filament\Actions\DeleteAction; -use Livewire\Livewire; -use PHPUnit\Framework\Attributes\Test; -use Tests\TestCase; - -class WhatsappInstanceResourceTest extends TestCase -{ - #[Test] - public function it_can_render_list_page(): void - { - $this->get(WhatsappInstanceResource::getUrl('index')) - ->assertSuccessful(); - } - - #[Test] - public function it_can_list_instances(): void - { - $instances = WhatsappInstance::factory()->count(3)->create(); - - Livewire::test(ListWhatsappInstances::class) - ->assertCanSeeTableRecords($instances); - } - - #[Test] - public function it_can_create_instance(): void - { - // Mock da API Evolution - Http::fake([ - '*/instance/create' => Http::response([ - 'instance' => ['instanceId' => 'uuid-123', 'status' => 'created'], - 'hash' => 'abc123', - 'qrcode' => ['base64' => 'data:image/png;base64,...'], - ]), - ]); - - Livewire::test(CreateWhatsappInstance::class) - ->fillForm([ - 'name' => 'nova-instancia', - 'number' => '5511999999999', - ]) - ->call('create') - ->assertHasNoFormErrors(); - - $this->assertDatabaseHas('whatsapp_instances', [ - 'name' => 'nova-instancia', - ]); - } -} - -// tests/Feature/Evolution/WebhookControllerTest.php -namespace Tests\Feature\Evolution; - -use App\Jobs\Evolution\ProcessWebhookJob; -use App\Models\WhatsappInstance; -use Illuminate\Support\Facades\Queue; -use PHPUnit\Framework\Attributes\Test; -use Tests\TestCase; - -class WebhookControllerTest extends TestCase -{ - #[Test] - public function it_queues_webhook_for_processing(): void - { - Queue::fake(); - - $response = $this->postJson('/api/evolution/webhook', [ - 'event' => 'connection.update', - 'instance' => 'test-instance', - 'data' => ['state' => 'open'], - ]); - - $response->assertOk(); - Queue::assertPushed(ProcessWebhookJob::class); - } - - #[Test] - public function it_processes_connection_update(): void - { - $instance = WhatsappInstance::factory()->create([ - 'name' => 'test-instance', - 'status' => 'connecting', - ]); - - $job = new ProcessWebhookJob('connection.update', [ - 'instance' => 'test-instance', - 'data' => ['state' => 'open'], - ]); - - $job->handle(); - - $this->assertEquals('open', $instance->fresh()->status->value); - } - - #[Test] - public function it_processes_qrcode_updated(): void - { - $instance = WhatsappInstance::factory()->create([ - 'name' => 'test-instance', - ]); - - $job = new ProcessWebhookJob('qrcode.updated', [ - 'instance' => 'test-instance', - 'data' => [ - 'qrcode' => [ - 'base64' => 'data:image/png;base64,abc123', - 'pairingCode' => 'ABCD1234', - ], - ], - ]); - - $job->handle(); - - $instance->refresh(); - $this->assertNotNull($instance->qr_code); - $this->assertEquals('ABCD1234', $instance->pairing_code); - } - - #[Test] - public function it_logs_webhook_to_database(): void - { - $instance = WhatsappInstance::factory()->create(['name' => 'test']); - - $job = new ProcessWebhookJob('connection.update', [ - 'instance' => 'test', - 'data' => ['state' => 'open'], - ]); - - $job->handle(); - - $this->assertDatabaseHas('whatsapp_webhooks', [ - 'event' => 'connection.update', - 'processed' => true, - ]); - } -} - -// tests/Feature/Evolution/SendMessageTest.php -namespace Tests\Feature\Evolution; - -use App\Data\Evolution\MessageData; -use App\Jobs\Evolution\SendMessageJob; -use App\Models\WhatsappInstance; -use Illuminate\Support\Facades\Http; -use PHPUnit\Framework\Attributes\Test; -use Tests\TestCase; - -class SendMessageTest extends TestCase -{ - #[Test] - public function it_sends_text_message(): void - { - Http::fake([ - '*/message/sendText/*' => Http::response([ - 'key' => ['id' => 'msg-123', 'remoteJid' => '5511@s.whatsapp.net'], - 'status' => 'PENDING', - ]), - ]); - - $instance = WhatsappInstance::factory()->create(['status' => 'open']); - $message = new MessageData( - number: '5511999999999', - content: 'OlΓ‘, teste!', - ); - - $job = new SendMessageJob($instance, $message); - $job->handle(app(\App\Services\Evolution\Message\SendMessageEvolutionService::class)); - - $this->assertDatabaseHas('whatsapp_messages', [ - 'instance_id' => $instance->id, - 'phone' => '5511999999999', - 'content' => 'OlΓ‘, teste!', - 'direction' => 'outgoing', - ]); - } - - #[Test] - public function it_retries_on_failure(): void - { - Http::fake([ - '*/message/sendText/*' => Http::response(['error' => 'timeout'], 500), - ]); - - $instance = WhatsappInstance::factory()->create(); - $message = new MessageData(number: '5511999999999', content: 'Test'); - - $job = new SendMessageJob($instance, $message); - - $this->expectException(\Exception::class); - $job->handle(app(\App\Services\Evolution\Message\SendMessageEvolutionService::class)); - } -} -``` - -### Fixtures - -``` -tests/ -└── Fixtures/ - └── webhook-payloads/ - β”œβ”€β”€ connection-update-open.json - β”œβ”€β”€ connection-update-close.json - β”œβ”€β”€ qrcode-updated.json - β”œβ”€β”€ messages-upsert-text.json - β”œβ”€β”€ messages-upsert-image.json - └── send-message.json -``` - -```json -// tests/Fixtures/webhook-payloads/messages-upsert-text.json -{ - "event": "messages.upsert", - "instance": "test-instance", - "data": { - "key": { - "remoteJid": "5511999999999@s.whatsapp.net", - "fromMe": false, - "id": "BAE594145F4C59B4" - }, - "messageType": "conversation", - "message": { - "conversation": "OlΓ‘, tudo bem?" - }, - "messageTimestamp": "1717689097" - } -} -``` - ---- - -## πŸ“‹ Checklist de ImplementaΓ§Γ£o - -### Fase 0 - Setup do Package -- [ ] Criar estrutura do package (`packages/wallacemartinss/filament-evolution/`) -- [ ] Criar `composer.json` do package -- [ ] Criar `FilamentEvolutionServiceProvider.php` -- [ ] Criar `FilamentEvolutionPlugin.php` (Filament Panel Plugin) -- [ ] Criar `config/filament-evolution.php` com todas as configuraΓ§Γ΅es -- [ ] Publicar config via Service Provider - -### Fase 1 - Multi-Tenancy e Infraestrutura Base -- [ ] Criar Traits - - [ ] `src/Models/Concerns/HasTenant.php` - - [ ] `src/Database/Migrations/Concerns/HasTenantColumn.php` -- [ ] Criar Migrations com tenant dinΓ’mico - - [ ] `create_whatsapp_instances_table.php` - - [ ] `create_whatsapp_messages_table.php` - - [ ] `create_whatsapp_webhooks_table.php` -- [ ] Criar Models com HasTenant - - [ ] `WhatsappInstance.php` - - [ ] `WhatsappMessage.php` - - [ ] `WhatsappWebhook.php` -- [ ] Testes de Multi-Tenancy - -### Fase 2 - DTOs (Data Transfer Objects) -- [ ] Instalar `spatie/laravel-data` -- [ ] Criar DTOs (`src/Data/`) - - [ ] `InstanceData.php` - - [ ] `MessageData.php` - - [ ] `QrCodeData.php` - - [ ] `ContactData.php` - - [ ] `Webhook/ConnectionUpdateData.php` - - [ ] `Webhook/QrCodeUpdatedData.php` - - [ ] `Webhook/MessageUpsertData.php` -- [ ] Testes unitΓ‘rios de DTOs - -### Fase 3 - Eventos, Jobs e Listeners -- [ ] Criar Events (`src/Events/`) - - [ ] `InstanceConnected.php` - - [ ] `InstanceDisconnected.php` - - [ ] `MessageReceived.php` - - [ ] `MessageSent.php` - - [ ] `QrCodeUpdated.php` -- [ ] Criar Jobs (`src/Jobs/`) - - [ ] `ProcessWebhookJob.php` - - [ ] `SendMessageJob.php` - - [ ] `SendBulkMessagesJob.php` -- [ ] Criar Listeners (`src/Listeners/`) - - [ ] `UpdateInstanceStatus.php` - - [ ] `LogMessageReceived.php` - - [ ] `NotifyMessageReceived.php` -- [ ] Registrar Events/Listeners no Service Provider -- [ ] Testes de Jobs e Listeners - -### Fase 4 - Enums -- [ ] Criar novos Enums (`src/Enums/`) - - [ ] `StatusConnectionEnum.php` - - [ ] `WebhookEventEnum.php` - - [ ] `MessageTypeEnum.php` - - [ ] `MessageDirectionEnum.php` - - [ ] `MessageStatusEnum.php` -- [ ] Criar Migrations - - [ ] `create_whatsapp_messages_table.php` - - [ ] `create_whatsapp_webhooks_table.php` -- [ ] Criar Models - - [ ] `WhatsappMessage.php` - - [ ] `WhatsappWebhook.php` -- [ ] Factories para os novos Models -- [ ] Testes dos Models - -### Fase 5 - Refatorar WebhookController -- [ ] Usar DTOs em vez de arrays raw -- [ ] Dispatch Job ao invΓ©s de processar inline -- [ ] Disparar Events para extensibilidade -- [ ] Adicionar logging estruturado -- [ ] Testes de integraΓ§Γ£o de webhooks - -### Fase 6 - Filament UI -- [ ] Criar `WhatsappInstanceResource` no plugin -- [ ] Criar `EvolutionQrCode` Livewire Component -- [ ] Adicionar Widget de estatΓ­sticas -- [ ] Adicionar pΓ‘gina de logs de webhooks -- [ ] Testes de Feature do Resource - -### Fase 7 - Services -- [ ] Criar `EvolutionClient` (HTTP Client) -- [ ] Criar Instance Services (Create, Connect, Delete, etc.) -- [ ] Criar Message Services (SendText, SendMedia, etc.) -- [ ] Testes de envio de mensagens - -### Fase 8 - Polimento -- [ ] TraduΓ§Γ΅es (pt_BR, en) -- [ ] DocumentaΓ§Γ£o (README.md) -- [ ] Cache de status de instΓ’ncias -- [ ] Logging estruturado -- [ ] GitHub Actions CI/CD -- [ ] Publicar no Packagist - ---- - -## πŸ“Š Resumo de Arquivos - -### CΓ³digo Existente (🟒 ReferΓͺncia do seu projeto) -| Arquivo | DescriΓ§Γ£o | -|---------|-----------| -| `WhatsappInstance` Model | UUID, name, number, status, settings | -| `StatusConnectionEnum` | CLOSE/OPEN/CONNECTING/REFUSED | -| `EvolutionClientTrait` | HTTP client com makeRequest() | -| 6 Instance Services | Create, Connect, Delete, Fetch, LogOut, Restart | -| `SendMessageEvolutionService` | Envio de mensagens texto | -| `EvolutionWebhookController` | Handler de webhooks | -| `EvolutionQrCode` Livewire | Componente QR com polling | -| `WhatsappInstanceResource` | Filament Resource completo | - -### Novos Arquivos do Plugin (πŸ”΅ Criar) -| Arquivo | DescriΓ§Γ£o | -|---------|-----------| -| `config/filament-evolution.php` | Config completa (API, webhook, tenancy, etc.) | -| 4 DTOs Core | InstanceData, MessageData, QrCodeData, ContactData | -| 3 DTOs Webhook | ConnectionUpdateData, QrCodeUpdatedData, MessageUpsertData | -| 5 Events | InstanceConnected, InstanceDisconnected, MessageReceived, MessageSent, QrCodeUpdated | -| 3 Jobs | ProcessWebhookJob, SendMessageJob, SendBulkMessagesJob | -| 3 Listeners | UpdateInstanceStatus, LogMessageReceived, NotifyMessageReceived | -| 4 Enums | WebhookEventEnum, MessageTypeEnum, MessageDirectionEnum, MessageStatusEnum | -| 3 Migrations | whatsapp_instances, whatsapp_messages, whatsapp_webhooks (com tenant dinΓ’mico) | -| 2 Models | WhatsappMessage, WhatsappWebhook (com HasTenant trait) | -| 2 Traits | HasTenant (model), HasTenantColumn (migration) | -| 1 Config | config/filament-evolution.php | -| 47+ Testes | Unit + Feature com fixtures | - -### Total Estimado -- **Arquivos existentes**: ~15 arquivos -- **Novos arquivos**: ~35 arquivos -- **Total de testes**: 47+ casos de teste - ---- - -## πŸ“ Notas Importantes - -1. **SeguranΓ§a do Webhook**: Sempre validar a origem do webhook usando secret/signature -2. **Rate Limiting**: A Evolution API pode ter limites, implementar retry com backoff -3. **Queue**: Webhooks e envios devem ser processados em background -4. **Soft Deletes**: InstΓ’ncias usam soft delete para manter histΓ³rico -5. **Multi-tenancy**: βœ… Suporte completo via `config('filament-evolution.tenancy')` -6. **Config PrΓ³pria**: βœ… Plugin usa `config/filament-evolution.php` (nΓ£o `services.php`) diff --git a/README.md b/README.md index aa82584..63778f1 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ A Filament v4 plugin for WhatsApp integration using [Evolution API v2](https://doc.evolution-api.com/). +![Filament Evolution - WhatsApp Connector](docs/images/principal.png) + ## Features - πŸ”Œ **Easy Integration** - Connect your WhatsApp with Evolution API v2 @@ -15,14 +17,28 @@ A Filament v4 plugin for WhatsApp integration using [Evolution API v2](https://d - 🎯 **Filament Action** - Ready-to-use action for sending messages from anywhere - πŸ”§ **Service Trait** - Easily integrate message sending into your own services - πŸ” **Secure** - Credentials stored in config/env, never in database -- 🎨 **Filament v4 Native** - Beautiful UI with Filament components and Heroicons +- 🎨 **Filament v4 Native** - Beautiful UI with Filament components - 🌍 **Translations** - Full i18n support (English and Portuguese included) -- ⚑ **Real-time** - Livewire-powered components with Alpine.js countdown +- ⚑ **Real-time** - Livewire-powered components with Alpine.js + +## Screenshots + +
+πŸ“Έ Click to view screenshots + +| | | +|:---:|:---:| +| ![Screenshot 1](docs/images/screenshot-01.png) | ![Screenshot 2](docs/images/screenshot-02.png) | +| ![Screenshot 3](docs/images/screenshot-03.png) | ![Screenshot 4](docs/images/screenshot-04.png) | +| ![Screenshot 5](docs/images/screenshot-05.png) | ![Screenshot 6](docs/images/screenshot-06.png) | +| ![Screenshot 7](docs/images/screenshot-07.png) | ![Screenshot 8](docs/images/screenshot-08.png) | + +
## Requirements - PHP 8.2+ -- Laravel 11+ +- Laravel 11.x or 12.x - Filament v4 - Evolution API v2 instance diff --git a/docs/images/principal.png b/docs/images/principal.png new file mode 100644 index 0000000000000000000000000000000000000000..5b4e2a36230955bb803fb8ab83e6dce80adf6184 GIT binary patch literal 96162 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 D7nF6( literal 0 HcmV?d00001 diff --git a/docs/images/screenshot-01.png b/docs/images/screenshot-01.png new file mode 100644 index 0000000000000000000000000000000000000000..990562f74722b20417555defe01893f7c4ae55d0 GIT binary patch literal 23828 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 literal 0 HcmV?d00001 diff --git a/docs/images/screenshot-02.png b/docs/images/screenshot-02.png new file mode 100644 index 0000000000000000000000000000000000000000..b20b0ecc91a05e71d9112bca771c566915838b3d GIT binary patch literal 39845 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