From 368e03ce48e012009fd41c6328870769c4720960 Mon Sep 17 00:00:00 2001 From: Jeppe Bundgaard Date: Fri, 27 Mar 2026 11:15:27 +0100 Subject: [PATCH] Remove redundant methods and IVR handling logic from Bird voice call webhook route, focusing on streamlined call flow and improved maintainability. --- .../app/routes/birdVoiceWebhooksRoute.php | 225 ------------------ 1 file changed, 225 deletions(-) diff --git a/services/nginx/app/routes/birdVoiceWebhooksRoute.php b/services/nginx/app/routes/birdVoiceWebhooksRoute.php index 37d8f134..0eb4ac23 100644 --- a/services/nginx/app/routes/birdVoiceWebhooksRoute.php +++ b/services/nginx/app/routes/birdVoiceWebhooksRoute.php @@ -28,7 +28,6 @@ class birdVoiceWebhooksRoute $this->post('/bird/voice/calls/webhook/inbound', function () { global $response; - //self::requirePermission('modules_bird_voice_call_webhooks_trigger'); $client = new bird(); $ws = $this->normalizeOptionalString($this->fromRequest('workspaceId') ?? $this->fromQuery('workspaceId')); @@ -47,204 +46,11 @@ class birdVoiceWebhooksRoute $client->sayMessage($ws, $ch, $ci, [ 'text' => 'Hej! Tak for dit opkald. Vi vil nu guide dig gennem en menu for at aabne en port. Afslut hvert valg med firkantstasten.', ]); - // Tell options to the caller }, [ 'modules_bird_voice_call_webhooks_trigger' => 'Trigger a voice call via Bird webhooks', ]); } - public static function listDepartmentOptions(): array - { - $department_gates = array_unique((new department_gates_o())->getFields(['department'])); - $departments = array_map(function ($row) { - return (new departments_o())->select((int)($row['department'] ?? 0))['name'] ?? 'Afdeling ' . (string)($row['department'] ?? ''); - }, $department_gates); - $options = []; - foreach ($departments as $department) { - $options[] = [ - 'input' => 'text', - 'value' => $department, - 'label' => $department, - ]; - } - return $options; - } - - protected function handleGatherResponse( - bird $client, - string $ws, - string $ch, - string $callId, - string $digits, - int $countryCode, - int $phone, - array $departments - ): void { - $state = $this->readIvrState($callId); - if ($state === null || !$this->isStateForCaller($state, $countryCode, $phone)) { - $this->promptForDepartmentSelection($client, $ws, $ch, $callId, $departments, $countryCode, $phone); - return; - } - - $stage = (string)($state['stage'] ?? ''); - if ($stage === self::IVR_STAGE_DEPARTMENT_SELECT) { - $this->handleDepartmentSelectionDigit($client, $ws, $ch, $callId, $digits, $state, $countryCode, $phone); - return; - } - if ($stage === self::IVR_STAGE_GATE_TYPE_SELECT) { - $this->handleGateTypeSelectionDigit($client, $ws, $ch, $callId, $digits, $state); - return; - } - - $this->clearIvrState($callId); - $this->promptForDepartmentSelection($client, $ws, $ch, $callId, $departments, $countryCode, $phone); - } - - protected function handleDepartmentSelectionDigit( - bird $client, - string $ws, - string $ch, - string $callId, - string $digits, - array $state, - int $countryCode, - int $phone - ): void { - $optionMap = is_array($state['department_options'] ?? null) ? $state['department_options'] : []; - $selected = $this->resolveDepartmentIdByDigit($optionMap, $digits); - if ($selected === null) { - $this->promptForDepartmentRetry($client, $ws, $ch, $callId, $state); - return; - } - - $state['stage'] = self::IVR_STAGE_GATE_TYPE_SELECT; - $state['selected_department'] = $selected; - $state['country_code'] = $countryCode; - $state['phone'] = $phone; - $state['selected_department_name'] = $this->getDepartmentNameById($selected); - $this->saveIvrState($callId, $state); - - $this->promptForGateTypeSelection($client, $ws, $ch, $callId, $selected, (string)$state['selected_department_name']); - } - - protected function handleGateTypeSelectionDigit( - bird $client, - string $ws, - string $ch, - string $callId, - string $digits, - array $state - ): void { - $departmentId = (int)($state['selected_department'] ?? 0); - if ($departmentId <= 0) { - $this->clearIvrState($callId); - $this->say($client, $ws, $ch, $callId, 'Sessionen er udloeebet. Ring venligst op igen.', true); - return; - } - - $gateType = $this->resolveGateTypeByDigit($digits); - if ($gateType === null) { - $departmentName = (string)($state['selected_department_name'] ?? $this->getDepartmentNameById($departmentId)); - $this->promptForGateTypeRetry($client, $ws, $ch, $callId, $departmentId, $departmentName); - return; - } - - $gate = $gateType === self::IVR_GATE_TYPE_ENTRANCE - ? (new department_gates_o())->getEntranceGate($departmentId) - : (new department_gates_o())->getExitGate($departmentId); - - $this->clearIvrState($callId); - - if ($gate === null || !$gate->exists()) { - $directionLabel = $gateType === self::IVR_GATE_TYPE_ENTRANCE ? 'indgang' : 'udgang'; - $this->say($client, $ws, $ch, $callId, 'Vi kunne ikke finde en ' . $directionLabel . 'sport for den valgte afdeling.', true); - return; - } - - try { - $gate->openGate(); - $this->say($client, $ws, $ch, $callId, 'Aabner port: ' . $gate->name->value(), true); - return; - } catch (\Throwable) { - $this->say($client, $ws, $ch, $callId, 'Kunne ikke aktivere relaeet for ' . $gate->name->value() . '. Kontakt venligst support.', true); - } - } - - protected function getCallerDepartments(int $countryCode, int $phone): array - { - // Return all visible departments. - $tmp = (new departments_o())->getFieldsWhere([ - 'visible' => 1, - ], ['id']); - return array_map(function ($row) { - return (int)$row['id']; - }, $tmp); - } - - protected function promptForDepartmentSelection( - bird $client, - string $ws, - string $ch, - string $callId, - array $departments, - int $countryCode, - int $phone - ): void { - $optionMap = $this->buildDepartmentOptionMap($departments); - if (empty($optionMap)) { - $this->say($client, $ws, $ch, $callId, 'Der er ingen valgbare afdelinger lige nu. Kontakt venligst support.', true); - return; - } - - $state = [ - 'stage' => self::IVR_STAGE_DEPARTMENT_SELECT, - 'department_options' => $optionMap, - 'selected_department' => null, - 'country_code' => $countryCode, - 'phone' => $phone, - ]; - $this->saveIvrState($callId, $state); - - $text = $this->buildDepartmentPromptText($optionMap); - $this->gather($client, $ws, $ch, $callId, $text); - } - - protected function promptForDepartmentRetry(bird $client, string $ws, string $ch, string $callId, array $state): void - { - $optionMap = is_array($state['department_options'] ?? null) ? $state['department_options'] : []; - if (empty($optionMap)) { - $this->clearIvrState($callId); - $this->say($client, $ws, $ch, $callId, 'Sessionen er udloeebet. Ring venligst op igen.', true); - return; - } - $text = 'Ugyldigt valg. ' . $this->buildDepartmentPromptText($optionMap); - $this->gather($client, $ws, $ch, $callId, $text); - } - - protected function promptForGateTypeSelection( - bird $client, - string $ws, - string $ch, - string $callId, - int $departmentId, - string $departmentName - ): void { - $text = $this->buildGateTypePromptText($departmentName); - $this->gather($client, $ws, $ch, $callId, $text); - } - - protected function promptForGateTypeRetry( - bird $client, - string $ws, - string $ch, - string $callId, - int $departmentId, - string $departmentName - ): void { - $text = 'Ugyldigt valg. ' . $this->buildGateTypePromptText($departmentName); - $this->gather($client, $ws, $ch, $callId, $text); - } - protected function buildDepartmentOptionMap(array $departmentIds): array { $map = []; @@ -425,37 +231,6 @@ class birdVoiceWebhooksRoute } } - protected function extractCallerPhone(array $payload): ?array - { - $candidates = [ - $payload['phone_number'] ?? null, - $payload['source'] ?? null, - $payload['from'] ?? null, - ]; - - foreach ($candidates as $candidate) { - $normalized = department_gates_o::normalizePhoneCandidate($candidate); - if ($normalized !== null) { - return $normalized; - } - } - - return null; - } - - protected function isRegisteredCaller(int $countryCode, int $phone): bool - { - $userRows = (new users_o())->getFieldsWhere([ - 'phone_country_code' => $countryCode, - 'phone' => $phone, - ], ['id']); - if (!empty($userRows)) { - return true; - } - - return (new subusers_o())->getSubuserByPhone($countryCode, $phone) !== null; - } - protected function say(bird $client, string $ws, string $ch, string $callId, string $text, bool $hangup = false): void { if ($callId !== '') {