ci: add GitHub Actions workflow for tests and code style
This commit is contained in:
71
.github/workflows/tests.yml
vendored
Normal file
71
.github/workflows/tests.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [dev, v1, main]
|
||||
pull_request:
|
||||
branches: [dev, v1, main]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
php: [8.2, 8.3, 8.4]
|
||||
laravel: [11.*, 12.*]
|
||||
stability: [prefer-stable]
|
||||
include:
|
||||
- laravel: 11.*
|
||||
testbench: 9.*
|
||||
- laravel: 12.*
|
||||
testbench: 10.*
|
||||
|
||||
name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} - ${{ matrix.stability }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv
|
||||
coverage: none
|
||||
|
||||
- name: Setup problem matchers
|
||||
run: |
|
||||
echo "::add-matcher::${{ runner.tool_cache }}/php.json"
|
||||
echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
|
||||
composer update --${{ matrix.stability }} --prefer-dist --no-interaction
|
||||
|
||||
- name: Execute tests
|
||||
run: vendor/bin/phpunit --testdox
|
||||
|
||||
code-style:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
name: Code Style
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 8.3
|
||||
extensions: dom, curl, libxml, mbstring, zip
|
||||
coverage: none
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --no-interaction --prefer-dist
|
||||
|
||||
- name: Check code style
|
||||
run: vendor/bin/pint --test
|
||||
@@ -66,7 +66,7 @@ class SendWhatsappMessageAction extends Action
|
||||
|
||||
$this->modalWidth('lg');
|
||||
|
||||
$this->form(fn(): array => $this->getFormSchema());
|
||||
$this->form(fn (): array => $this->getFormSchema());
|
||||
|
||||
$this->action(function (array $data): void {
|
||||
$this->sendMessage($data);
|
||||
@@ -238,21 +238,21 @@ class SendWhatsappMessageAction extends Action
|
||||
$this->getLatitudeInput(),
|
||||
$this->getLongitudeInput(),
|
||||
])
|
||||
->visible(fn(Get $get): bool => $get('type') === MessageTypeEnum::LOCATION->value),
|
||||
->visible(fn (Get $get): bool => $get('type') === MessageTypeEnum::LOCATION->value),
|
||||
|
||||
Grid::make(2)
|
||||
->schema([
|
||||
$this->getLocationNameInput(),
|
||||
$this->getLocationAddressInput(),
|
||||
])
|
||||
->visible(fn(Get $get): bool => $get('type') === MessageTypeEnum::LOCATION->value),
|
||||
->visible(fn (Get $get): bool => $get('type') === MessageTypeEnum::LOCATION->value),
|
||||
|
||||
Grid::make(2)
|
||||
->schema([
|
||||
$this->getContactNameInput(),
|
||||
$this->getContactNumberInput(),
|
||||
])
|
||||
->visible(fn(Get $get): bool => $get('type') === MessageTypeEnum::CONTACT->value),
|
||||
->visible(fn (Get $get): bool => $get('type') === MessageTypeEnum::CONTACT->value),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ class SendWhatsappMessageAction extends Action
|
||||
$types = ! empty($this->allowedTypes) ? $this->allowedTypes : $allTypes;
|
||||
|
||||
return collect($types)
|
||||
->mapWithKeys(fn(MessageTypeEnum $type) => [$type->value => $type->getLabel()])
|
||||
->mapWithKeys(fn (MessageTypeEnum $type) => [$type->value => $type->getLabel()])
|
||||
->toArray();
|
||||
}
|
||||
|
||||
@@ -346,8 +346,8 @@ class SendWhatsappMessageAction extends Action
|
||||
return Textarea::make('message')
|
||||
->label(__('filament-evolution::action.message'))
|
||||
->default($this->defaultMessage)
|
||||
->required(fn(Get $get): bool => $get('type') === MessageTypeEnum::TEXT->value)
|
||||
->visible(fn(Get $get): bool => $get('type') === MessageTypeEnum::TEXT->value)
|
||||
->required(fn (Get $get): bool => $get('type') === MessageTypeEnum::TEXT->value)
|
||||
->visible(fn (Get $get): bool => $get('type') === MessageTypeEnum::TEXT->value)
|
||||
->rows(4)
|
||||
->placeholder(__('filament-evolution::action.message_placeholder'));
|
||||
}
|
||||
@@ -356,7 +356,7 @@ class SendWhatsappMessageAction extends Action
|
||||
{
|
||||
return Textarea::make('caption')
|
||||
->label(__('filament-evolution::action.caption'))
|
||||
->visible(fn(Get $get): bool => in_array($get('type'), [
|
||||
->visible(fn (Get $get): bool => in_array($get('type'), [
|
||||
MessageTypeEnum::IMAGE->value,
|
||||
MessageTypeEnum::VIDEO->value,
|
||||
MessageTypeEnum::DOCUMENT->value,
|
||||
@@ -369,13 +369,13 @@ class SendWhatsappMessageAction extends Action
|
||||
{
|
||||
return FileUpload::make('media')
|
||||
->label(__('filament-evolution::action.media'))
|
||||
->required(fn(Get $get): bool => in_array($get('type'), [
|
||||
->required(fn (Get $get): bool => in_array($get('type'), [
|
||||
MessageTypeEnum::IMAGE->value,
|
||||
MessageTypeEnum::VIDEO->value,
|
||||
MessageTypeEnum::AUDIO->value,
|
||||
MessageTypeEnum::DOCUMENT->value,
|
||||
]))
|
||||
->visible(fn(Get $get): bool => in_array($get('type'), [
|
||||
->visible(fn (Get $get): bool => in_array($get('type'), [
|
||||
MessageTypeEnum::IMAGE->value,
|
||||
MessageTypeEnum::VIDEO->value,
|
||||
MessageTypeEnum::AUDIO->value,
|
||||
@@ -383,7 +383,7 @@ class SendWhatsappMessageAction extends Action
|
||||
]))
|
||||
->disk($this->mediaDisk ?? config('filament-evolution.media.disk', 'public'))
|
||||
->directory(config('filament-evolution.media.directory', 'whatsapp-media'))
|
||||
->acceptedFileTypes(fn(Get $get): array => $this->getAcceptedFileTypes($get('type')))
|
||||
->acceptedFileTypes(fn (Get $get): array => $this->getAcceptedFileTypes($get('type')))
|
||||
->maxSize(config('filament-evolution.media.max_size', 16384))
|
||||
->helperText(__('filament-evolution::action.media_helper'));
|
||||
}
|
||||
@@ -411,7 +411,7 @@ class SendWhatsappMessageAction extends Action
|
||||
{
|
||||
return TextInput::make('latitude')
|
||||
->label(__('filament-evolution::action.latitude'))
|
||||
->required(fn(Get $get): bool => $get('type') === MessageTypeEnum::LOCATION->value)
|
||||
->required(fn (Get $get): bool => $get('type') === MessageTypeEnum::LOCATION->value)
|
||||
->numeric()
|
||||
->step(0.000001)
|
||||
->placeholder('-23.5505');
|
||||
@@ -421,7 +421,7 @@ class SendWhatsappMessageAction extends Action
|
||||
{
|
||||
return TextInput::make('longitude')
|
||||
->label(__('filament-evolution::action.longitude'))
|
||||
->required(fn(Get $get): bool => $get('type') === MessageTypeEnum::LOCATION->value)
|
||||
->required(fn (Get $get): bool => $get('type') === MessageTypeEnum::LOCATION->value)
|
||||
->numeric()
|
||||
->step(0.000001)
|
||||
->placeholder('-46.6333');
|
||||
@@ -445,7 +445,7 @@ class SendWhatsappMessageAction extends Action
|
||||
{
|
||||
return TextInput::make('contact_name')
|
||||
->label(__('filament-evolution::action.contact_name'))
|
||||
->required(fn(Get $get): bool => $get('type') === MessageTypeEnum::CONTACT->value)
|
||||
->required(fn (Get $get): bool => $get('type') === MessageTypeEnum::CONTACT->value)
|
||||
->placeholder('John Doe');
|
||||
}
|
||||
|
||||
@@ -453,7 +453,7 @@ class SendWhatsappMessageAction extends Action
|
||||
{
|
||||
return TextInput::make('contact_number')
|
||||
->label(__('filament-evolution::action.contact_number'))
|
||||
->required(fn(Get $get): bool => $get('type') === MessageTypeEnum::CONTACT->value)
|
||||
->required(fn (Get $get): bool => $get('type') === MessageTypeEnum::CONTACT->value)
|
||||
->tel()
|
||||
->placeholder('5511999999999');
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ class InstanceData extends Data
|
||||
'read_messages' => $this->readMessages,
|
||||
'read_status' => $this->readStatus,
|
||||
'sync_full_history' => $this->syncFullHistory,
|
||||
], fn($value) => $value !== null && $value !== false && $value !== '');
|
||||
], fn ($value) => $value !== null && $value !== false && $value !== '');
|
||||
|
||||
if (! empty($settings)) {
|
||||
$payload = array_merge($payload, $settings);
|
||||
|
||||
@@ -10,7 +10,6 @@ use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Actions\ViewAction;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Toggle;
|
||||
use Filament\Forms\Components\ToggleButtons;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Components\Section;
|
||||
@@ -140,7 +139,7 @@ class WhatsappInstanceResource extends Resource
|
||||
TextInput::make('msg_call')
|
||||
->label(__('filament-evolution::resource.fields.msg_call'))
|
||||
->helperText(__('filament-evolution::resource.fields.msg_call_helper'))
|
||||
->hidden(fn($get) => $get('reject_call') == false)
|
||||
->hidden(fn ($get) => $get('reject_call') == false)
|
||||
->maxLength(255)
|
||||
->default(config('filament-evolution.instance.msg_call', ''))
|
||||
->columnSpanFull(),
|
||||
@@ -160,7 +159,7 @@ class WhatsappInstanceResource extends Resource
|
||||
->label('')
|
||||
->alignCenter()
|
||||
->circular()
|
||||
->defaultImageUrl(fn() => 'https://ui-avatars.com/api/?name=WA&color=7F9CF5&background=EBF4FF'),
|
||||
->defaultImageUrl(fn () => 'https://ui-avatars.com/api/?name=WA&color=7F9CF5&background=EBF4FF'),
|
||||
|
||||
TextColumn::make('name')
|
||||
->label(__('filament-evolution::resource.fields.name'))
|
||||
@@ -200,8 +199,8 @@ class WhatsappInstanceResource extends Resource
|
||||
->label(__('filament-evolution::resource.actions.connect'))
|
||||
->icon(Heroicon::QrCode)
|
||||
->color('success')
|
||||
->action(fn($record, $livewire) => $livewire->openConnectModal((string) $record->id))
|
||||
->hidden(fn($record): bool => $record->status === StatusConnectionEnum::OPEN),
|
||||
->action(fn ($record, $livewire) => $livewire->openConnectModal((string) $record->id))
|
||||
->hidden(fn ($record): bool => $record->status === StatusConnectionEnum::OPEN),
|
||||
ViewAction::make(),
|
||||
EditAction::make(),
|
||||
])
|
||||
|
||||
@@ -51,7 +51,7 @@ class CreateWhatsappInstance extends CreateRecord
|
||||
Notification::make()
|
||||
->warning()
|
||||
->title(__('filament-evolution::resource.messages.created'))
|
||||
->body('Instance saved locally. API sync failed: ' . $e->getMessage())
|
||||
->body('Instance saved locally. API sync failed: '.$e->getMessage())
|
||||
->send();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace WallaceMartinss\FilamentEvolution\Filament\Resources\WhatsappInstanceResource\Pages;
|
||||
|
||||
use Filament\Actions\{Action, DeleteAction, EditAction};
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Resources\Pages\ViewRecord;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
@@ -24,9 +26,9 @@ class ViewWhatsappInstance extends ViewRecord
|
||||
->label(__('filament-evolution::resource.actions.connect'))
|
||||
->icon(Heroicon::QrCode)
|
||||
->color('success')
|
||||
->visible(fn() => $this->record->status !== StatusConnectionEnum::OPEN)
|
||||
->visible(fn () => $this->record->status !== StatusConnectionEnum::OPEN)
|
||||
->modalHeading(__('filament-evolution::resource.actions.view_qrcode'))
|
||||
->modalContent(fn() => view('filament-evolution::components.qr-code-modal', [
|
||||
->modalContent(fn () => view('filament-evolution::components.qr-code-modal', [
|
||||
'instance' => $this->record,
|
||||
]))
|
||||
->modalWidth('md')
|
||||
@@ -37,7 +39,7 @@ class ViewWhatsappInstance extends ViewRecord
|
||||
->label(__('filament-evolution::resource.actions.disconnect'))
|
||||
->icon(Heroicon::XCircle)
|
||||
->color('danger')
|
||||
->visible(fn() => $this->record->status === StatusConnectionEnum::OPEN)
|
||||
->visible(fn () => $this->record->status === StatusConnectionEnum::OPEN)
|
||||
->requiresConfirmation()
|
||||
->action(function () {
|
||||
try {
|
||||
@@ -89,7 +91,7 @@ class ViewWhatsappInstance extends ViewRecord
|
||||
}
|
||||
|
||||
// Extract profile picture URL from fetchInstance response
|
||||
$instanceData = is_array($instances) ? ($instances[0] ?? $instances) : $instances;
|
||||
$instanceData = is_array($instances) ? ($instances[0] ?? $instances) : $instances;
|
||||
$profilePictureUrl = $instanceData['profilePicUrl']
|
||||
?? $instanceData['instance']['profilePicUrl']
|
||||
?? null;
|
||||
@@ -98,20 +100,20 @@ class ViewWhatsappInstance extends ViewRecord
|
||||
$state = $client->getConnectionState($this->record->name);
|
||||
|
||||
$connectionState = $state['state'] ?? $state['instance']['state'] ?? 'close';
|
||||
$status = match (strtolower($connectionState)) {
|
||||
$status = match (strtolower($connectionState)) {
|
||||
'open', 'connected' => StatusConnectionEnum::OPEN,
|
||||
'connecting' => StatusConnectionEnum::CONNECTING,
|
||||
default => StatusConnectionEnum::CLOSE,
|
||||
default => StatusConnectionEnum::CLOSE,
|
||||
};
|
||||
|
||||
$this->record->update([
|
||||
'status' => $status,
|
||||
'status' => $status,
|
||||
'profile_picture_url' => $profilePictureUrl,
|
||||
]);
|
||||
|
||||
Notification::make()
|
||||
->success()
|
||||
->title(__('filament-evolution::resource.fields.status') . ': ' . $status->getLabel())
|
||||
->title(__('filament-evolution::resource.fields.status').': '.$status->getLabel())
|
||||
->send();
|
||||
} catch (EvolutionApiException $e) {
|
||||
// If 404, instance doesn't exist - try to create it
|
||||
|
||||
@@ -10,7 +10,9 @@ use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Filters\SelectFilter;
|
||||
use Filament\Tables\Table;
|
||||
use WallaceMartinss\FilamentEvolution\Enums\{MessageDirectionEnum, MessageStatusEnum, MessageTypeEnum};
|
||||
use WallaceMartinss\FilamentEvolution\Enums\MessageDirectionEnum;
|
||||
use WallaceMartinss\FilamentEvolution\Enums\MessageStatusEnum;
|
||||
use WallaceMartinss\FilamentEvolution\Enums\MessageTypeEnum;
|
||||
use WallaceMartinss\FilamentEvolution\Filament\Resources\WhatsappMessageResource\Pages;
|
||||
use WallaceMartinss\FilamentEvolution\Models\WhatsappMessage;
|
||||
|
||||
@@ -95,7 +97,7 @@ class WhatsappMessageResource extends Resource
|
||||
TextColumn::make('content.text')
|
||||
->label(__('filament-evolution::message.fields.content'))
|
||||
->limit(50)
|
||||
->tooltip(fn($state) => $state)
|
||||
->tooltip(fn ($state) => $state)
|
||||
->searchable(query: function ($query, string $search) {
|
||||
return $query->whereRaw("JSON_UNQUOTE(JSON_EXTRACT(content, '$.text')) LIKE ?", ["%{$search}%"]);
|
||||
}),
|
||||
@@ -136,7 +138,7 @@ class WhatsappMessageResource extends Resource
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListWhatsappMessages::route('/'),
|
||||
'view' => Pages\ViewWhatsappMessage::route('/{record}'),
|
||||
'view' => Pages\ViewWhatsappMessage::route('/{record}'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,27 +57,27 @@ class ViewWhatsappMessage extends ViewRecord
|
||||
TextEntry::make('content.media_caption')
|
||||
->label(__('filament-evolution::message.fields.media_caption'))
|
||||
->columnSpanFull()
|
||||
->visible(fn($record) => !empty($record->content['media_caption'])),
|
||||
->visible(fn ($record) => ! empty($record->content['media_caption'])),
|
||||
|
||||
TextEntry::make('content.media_url')
|
||||
->label(__('filament-evolution::message.fields.media_url'))
|
||||
->columnSpanFull()
|
||||
->url(fn($state) => $state)
|
||||
->visible(fn($record) => !empty($record->content['media_url'])),
|
||||
->url(fn ($state) => $state)
|
||||
->visible(fn ($record) => ! empty($record->content['media_url'])),
|
||||
|
||||
TextEntry::make('location')
|
||||
->label(__('filament-evolution::message.fields.location'))
|
||||
->state(fn($record) => $record->content['latitude'] && $record->content['longitude']
|
||||
->state(fn ($record) => $record->content['latitude'] && $record->content['longitude']
|
||||
? "Lat: {$record->content['latitude']}, Lng: {$record->content['longitude']}"
|
||||
: null)
|
||||
->visible(fn($record) => !empty($record->content['latitude']) && !empty($record->content['longitude'])),
|
||||
->visible(fn ($record) => ! empty($record->content['latitude']) && ! empty($record->content['longitude'])),
|
||||
|
||||
TextEntry::make('media')
|
||||
->label(__('filament-evolution::message.fields.media'))
|
||||
->columnSpanFull()
|
||||
->state(fn($record) => $this->formatPayloadAsHtml($record->media))
|
||||
->state(fn ($record) => $this->formatPayloadAsHtml($record->media))
|
||||
->html()
|
||||
->visible(fn($record) => !empty($record->media)),
|
||||
->visible(fn ($record) => ! empty($record->media)),
|
||||
]),
|
||||
|
||||
Section::make(__('filament-evolution::message.sections.timestamps'))
|
||||
@@ -104,10 +104,10 @@ class ViewWhatsappMessage extends ViewRecord
|
||||
->schema([
|
||||
TextEntry::make('raw_payload_display')
|
||||
->hiddenLabel()
|
||||
->state(fn($record) => $this->formatPayloadAsHtml($record->raw_payload))
|
||||
->state(fn ($record) => $this->formatPayloadAsHtml($record->raw_payload))
|
||||
->html()
|
||||
->copyable()
|
||||
->copyableState(fn($record) => $this->formatPayloadAsText($record->raw_payload))
|
||||
->copyableState(fn ($record) => $this->formatPayloadAsText($record->raw_payload))
|
||||
->copyMessage('Payload copiado!')
|
||||
->copyMessageDuration(1500),
|
||||
])
|
||||
@@ -152,7 +152,7 @@ class ViewWhatsappMessage extends ViewRecord
|
||||
// Colore null
|
||||
$highlighted = preg_replace('/:\s*(null)/', ': <span style="color: #c084fc;">$1</span>', $highlighted);
|
||||
|
||||
return '<pre class="language-json p-4 rounded-lg overflow-x-auto m-0 border" style="background-color: #1e293b; color: #e2e8f0; border-color: #334155;"><code style="font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.875rem; line-height: 1.5; white-space: pre; display: block;">' . $highlighted . '</code></pre>';
|
||||
return '<pre class="language-json p-4 rounded-lg overflow-x-auto m-0 border" style="background-color: #1e293b; color: #e2e8f0; border-color: #334155;"><code style="font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.875rem; line-height: 1.5; white-space: pre; display: block;">'.$highlighted.'</code></pre>';
|
||||
}
|
||||
|
||||
protected function formatPayloadAsText(mixed $payload): string
|
||||
|
||||
@@ -119,8 +119,8 @@ class WhatsappWebhookResource extends Resource
|
||||
TernaryFilter::make('has_error')
|
||||
->label(__('filament-evolution::webhook.fields.has_error'))
|
||||
->queries(
|
||||
true: fn($query) => $query->whereNotNull('error'),
|
||||
false: fn($query) => $query->whereNull('error'),
|
||||
true: fn ($query) => $query->whereNotNull('error'),
|
||||
false: fn ($query) => $query->whereNull('error'),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ class ViewWhatsappWebhook extends ViewRecord
|
||||
TextEntry::make('processed')
|
||||
->label(__('filament-evolution::webhook.fields.processed'))
|
||||
->badge()
|
||||
->formatStateUsing(fn($state) => $state ? __('filament-evolution::webhook.status.yes') : __('filament-evolution::webhook.status.no'))
|
||||
->color(fn($state) => $state ? 'success' : 'warning'),
|
||||
->formatStateUsing(fn ($state) => $state ? __('filament-evolution::webhook.status.yes') : __('filament-evolution::webhook.status.no'))
|
||||
->color(fn ($state) => $state ? 'success' : 'warning'),
|
||||
|
||||
TextEntry::make('processing_time_ms')
|
||||
->label(__('filament-evolution::webhook.fields.processing_time'))
|
||||
@@ -58,16 +58,16 @@ class ViewWhatsappWebhook extends ViewRecord
|
||||
->prose()
|
||||
->color('danger'),
|
||||
])
|
||||
->visible(fn($record) => ! empty($record->error)),
|
||||
->visible(fn ($record) => ! empty($record->error)),
|
||||
|
||||
Section::make(__('filament-evolution::webhook.sections.payload'))
|
||||
->schema([
|
||||
TextEntry::make('payload_display')
|
||||
->hiddenLabel()
|
||||
->state(fn($record) => $this->formatPayloadAsHtml($record->payload))
|
||||
->state(fn ($record) => $this->formatPayloadAsHtml($record->payload))
|
||||
->html()
|
||||
->copyable()
|
||||
->copyableState(fn($record) => $this->formatPayloadAsText($record->payload))
|
||||
->copyableState(fn ($record) => $this->formatPayloadAsText($record->payload))
|
||||
->copyMessage('Payload copiado!')
|
||||
->copyMessageDuration(1500),
|
||||
])
|
||||
@@ -111,7 +111,7 @@ class ViewWhatsappWebhook extends ViewRecord
|
||||
// Colore null
|
||||
$highlighted = preg_replace('/:\s*(null)/', ': <span style="color: #c084fc;">$1</span>', $highlighted);
|
||||
|
||||
return '<pre class="language-json p-4 rounded-lg overflow-x-auto m-0 border" style="background-color: #1e293b; color: #e2e8f0; border-color: #334155;"><code style="font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.875rem; line-height: 1.5; white-space: pre; display: block;">' . $highlighted . '</code></pre>';
|
||||
return '<pre class="language-json p-4 rounded-lg overflow-x-auto m-0 border" style="background-color: #1e293b; color: #e2e8f0; border-color: #334155;"><code style="font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.875rem; line-height: 1.5; white-space: pre; display: block;">'.$highlighted.'</code></pre>';
|
||||
}
|
||||
|
||||
protected function formatPayloadAsText(mixed $payload): string
|
||||
|
||||
@@ -7,12 +7,19 @@ namespace WallaceMartinss\FilamentEvolution\Jobs;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\{InteractsWithQueue, SerializesModels};
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use WallaceMartinss\FilamentEvolution\Data\Webhooks\{ConnectionUpdateData, MessageUpsertData, QrCodeUpdatedData};
|
||||
use WallaceMartinss\FilamentEvolution\Data\Webhooks\ConnectionUpdateData;
|
||||
use WallaceMartinss\FilamentEvolution\Data\Webhooks\MessageUpsertData;
|
||||
use WallaceMartinss\FilamentEvolution\Data\Webhooks\QrCodeUpdatedData;
|
||||
use WallaceMartinss\FilamentEvolution\Enums\WebhookEventEnum;
|
||||
use WallaceMartinss\FilamentEvolution\Events\{InstanceConnected, InstanceDisconnected, MessageReceived, QrCodeUpdated};
|
||||
use WallaceMartinss\FilamentEvolution\Models\{WhatsappInstance, WhatsappWebhook};
|
||||
use WallaceMartinss\FilamentEvolution\Events\InstanceConnected;
|
||||
use WallaceMartinss\FilamentEvolution\Events\InstanceDisconnected;
|
||||
use WallaceMartinss\FilamentEvolution\Events\MessageReceived;
|
||||
use WallaceMartinss\FilamentEvolution\Events\QrCodeUpdated;
|
||||
use WallaceMartinss\FilamentEvolution\Models\WhatsappInstance;
|
||||
use WallaceMartinss\FilamentEvolution\Models\WhatsappWebhook;
|
||||
|
||||
class ProcessWebhookJob implements ShouldQueue
|
||||
{
|
||||
@@ -38,7 +45,7 @@ class ProcessWebhookJob implements ShouldQueue
|
||||
try {
|
||||
$instanceName = $this->payload['instance'] ?? $this->payload['instanceName'] ?? null;
|
||||
|
||||
if (!$instanceName) {
|
||||
if (! $instanceName) {
|
||||
$this->markWebhookFailed('No instance name in payload');
|
||||
|
||||
return;
|
||||
@@ -46,7 +53,7 @@ class ProcessWebhookJob implements ShouldQueue
|
||||
|
||||
$instance = WhatsappInstance::where('name', $instanceName)->first();
|
||||
|
||||
if (!$instance) {
|
||||
if (! $instance) {
|
||||
$this->markWebhookFailed("Instance not found: {$instanceName}");
|
||||
|
||||
return;
|
||||
@@ -60,8 +67,8 @@ class ProcessWebhookJob implements ShouldQueue
|
||||
if (config('filament-evolution.logging.webhook_errors', true)) {
|
||||
Log::channel(config('filament-evolution.logging.channel', 'stack'))
|
||||
->error('Webhook processing failed', [
|
||||
'event' => $this->event,
|
||||
'error' => $e->getMessage(),
|
||||
'event' => $this->event,
|
||||
'error' => $e->getMessage(),
|
||||
'payload' => $this->payload,
|
||||
]);
|
||||
}
|
||||
@@ -76,10 +83,10 @@ class ProcessWebhookJob implements ShouldQueue
|
||||
|
||||
match ($eventEnum) {
|
||||
WebhookEventEnum::CONNECTION_UPDATE => $this->handleConnectionUpdate($instance),
|
||||
WebhookEventEnum::QRCODE_UPDATED => $this->handleQrCodeUpdated($instance),
|
||||
WebhookEventEnum::MESSAGES_UPSERT => $this->handleMessageUpsert($instance),
|
||||
WebhookEventEnum::MESSAGES_UPDATE => $this->handleMessageUpdate($instance),
|
||||
default => $this->handleUnknownEvent($instance),
|
||||
WebhookEventEnum::QRCODE_UPDATED => $this->handleQrCodeUpdated($instance),
|
||||
WebhookEventEnum::MESSAGES_UPSERT => $this->handleMessageUpsert($instance),
|
||||
WebhookEventEnum::MESSAGES_UPDATE => $this->handleMessageUpdate($instance),
|
||||
default => $this->handleUnknownEvent($instance),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -103,8 +110,8 @@ class ProcessWebhookJob implements ShouldQueue
|
||||
$data = QrCodeUpdatedData::fromWebhook($this->payload);
|
||||
|
||||
$instance->update([
|
||||
'qr_code' => $data->base64,
|
||||
'pairing_code' => $data->pairingCode,
|
||||
'qr_code' => $data->base64,
|
||||
'pairing_code' => $data->pairingCode,
|
||||
'qr_code_updated_at' => now(),
|
||||
]);
|
||||
|
||||
@@ -126,23 +133,23 @@ class ProcessWebhookJob implements ShouldQueue
|
||||
if (config('filament-evolution.storage.messages', true)) {
|
||||
// Extract remoteJid from payload
|
||||
$messageData = $this->payload['data'] ?? $this->payload;
|
||||
$key = $messageData['key'] ?? [];
|
||||
$remoteJid = $key['remoteJid'] ?? $data->message->phone;
|
||||
$key = $messageData['key'] ?? [];
|
||||
$remoteJid = $key['remoteJid'] ?? $data->message->phone;
|
||||
|
||||
$instance->messages()->create([
|
||||
'message_id' => $data->message->messageId,
|
||||
'remote_jid' => $remoteJid,
|
||||
'phone' => $data->message->phone,
|
||||
'direction' => $data->message->direction,
|
||||
'type' => $data->message->type,
|
||||
'content' => [
|
||||
'text' => $data->message->text,
|
||||
'media_url' => $data->message->mediaUrl,
|
||||
'phone' => $data->message->phone,
|
||||
'direction' => $data->message->direction,
|
||||
'type' => $data->message->type,
|
||||
'content' => [
|
||||
'text' => $data->message->text,
|
||||
'media_url' => $data->message->mediaUrl,
|
||||
'media_caption' => $data->message->mediaCaption,
|
||||
'latitude' => $data->message->latitude,
|
||||
'longitude' => $data->message->longitude,
|
||||
'latitude' => $data->message->latitude,
|
||||
'longitude' => $data->message->longitude,
|
||||
],
|
||||
'status' => $data->message->status,
|
||||
'status' => $data->message->status,
|
||||
'raw_payload' => $this->payload,
|
||||
]);
|
||||
}
|
||||
@@ -153,13 +160,13 @@ class ProcessWebhookJob implements ShouldQueue
|
||||
protected function handleMessageUpdate(WhatsappInstance $instance): void
|
||||
{
|
||||
// Only update if message storage is enabled
|
||||
if (!config('filament-evolution.storage.messages', true)) {
|
||||
if (! config('filament-evolution.storage.messages', true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$messageData = $this->payload['data'] ?? $this->payload;
|
||||
$key = $messageData['key'] ?? [];
|
||||
$update = $messageData['update'] ?? [];
|
||||
$key = $messageData['key'] ?? [];
|
||||
$update = $messageData['update'] ?? [];
|
||||
|
||||
if (isset($key['id']) && isset($update['status'])) {
|
||||
$instance->messages()
|
||||
@@ -175,7 +182,7 @@ class ProcessWebhookJob implements ShouldQueue
|
||||
if (config('filament-evolution.logging.webhook_events', false)) {
|
||||
Log::channel(config('filament-evolution.logging.channel', 'stack'))
|
||||
->info('Unknown webhook event received', [
|
||||
'event' => $this->event,
|
||||
'event' => $this->event,
|
||||
'instance' => $instance->name,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use WallaceMartinss\FilamentEvolution\Enums\{MessageDirectionEnum, MessageStatusEnum, MessageTypeEnum};
|
||||
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
|
||||
@@ -38,15 +40,15 @@ class WhatsappMessage extends Model
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'direction' => MessageDirectionEnum::class,
|
||||
'type' => MessageTypeEnum::class,
|
||||
'status' => MessageStatusEnum::class,
|
||||
'content' => 'array',
|
||||
'media' => 'array',
|
||||
'raw_payload' => 'array',
|
||||
'sent_at' => 'datetime',
|
||||
'direction' => MessageDirectionEnum::class,
|
||||
'type' => MessageTypeEnum::class,
|
||||
'status' => MessageStatusEnum::class,
|
||||
'content' => 'array',
|
||||
'media' => 'array',
|
||||
'raw_payload' => 'array',
|
||||
'sent_at' => 'datetime',
|
||||
'delivered_at' => 'datetime',
|
||||
'read_at' => 'datetime',
|
||||
'read_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -93,7 +95,7 @@ class WhatsappMessage extends Model
|
||||
public function markAsSent(): void
|
||||
{
|
||||
$this->update([
|
||||
'status' => MessageStatusEnum::SENT,
|
||||
'status' => MessageStatusEnum::SENT,
|
||||
'sent_at' => now(),
|
||||
]);
|
||||
}
|
||||
@@ -101,7 +103,7 @@ class WhatsappMessage extends Model
|
||||
public function markAsDelivered(): void
|
||||
{
|
||||
$this->update([
|
||||
'status' => MessageStatusEnum::DELIVERED,
|
||||
'status' => MessageStatusEnum::DELIVERED,
|
||||
'delivered_at' => now(),
|
||||
]);
|
||||
}
|
||||
@@ -109,7 +111,7 @@ class WhatsappMessage extends Model
|
||||
public function markAsRead(): void
|
||||
{
|
||||
$this->update([
|
||||
'status' => MessageStatusEnum::READ,
|
||||
'status' => MessageStatusEnum::READ,
|
||||
'read_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class WhatsappService
|
||||
|
||||
// If Brazilian number without country code, add it
|
||||
if (strlen($number) === 10 || strlen($number) === 11) {
|
||||
$number = '55' . $number;
|
||||
$number = '55'.$number;
|
||||
}
|
||||
|
||||
return $number;
|
||||
|
||||
Reference in New Issue
Block a user