$payload */ public function handle(string $event, array $payload): void { $room = (array) ($payload['room'] ?? []); $source = (array) ($room['source'] ?? []); if (($source['app'] ?? '') !== 'events') { return; } $eventId = (int) ($source['event_id'] ?? 0); $sessionId = (string) ($source['entity_id'] ?? ''); if ($eventId <= 0 || $sessionId === '') { return; } $qrCode = QrCode::find($eventId); if (! $qrCode || $qrCode->type !== QrCode::TYPE_EVENT) { return; } $content = $qrCode->content(); $sessions = (array) ($content['virtual_sessions'] ?? []); $updated = false; foreach ($sessions as $index => $session) { if (! is_array($session) || ($session['id'] ?? '') !== $sessionId) { continue; } $sessions[$index] = array_merge($session, $this->patchForEvent($event, $payload, $room)); $updated = true; break; } if (! $updated) { return; } $payloadData = (array) ($qrCode->payload ?? []); $payloadData['content'] = array_merge($content, ['virtual_sessions' => array_values($sessions)]); $qrCode->update(['payload' => $payloadData]); Log::info('Events Meet lifecycle applied', ['event' => $event, 'event_id' => $eventId, 'session_id' => $sessionId]); } /** @return array */ private function patchForEvent(string $event, array $payload, array $room): array { return match ($event) { 'meeting.started' => ['meet_status' => 'live', 'meet_live_at' => now()->toIso8601String()], 'meeting.ended' => ['meet_status' => 'ended', 'meet_ended_at' => now()->toIso8601String()], 'meeting.cancelled' => ['meet_status' => 'cancelled'], 'recording.ready' => [ 'recording_url' => (string) (($payload['recording']['download_url'] ?? '') ?: ''), 'recording_ready_at' => now()->toIso8601String(), ], default => [], }; } }