diff --git a/app/switch/resources/scripts/app/voicemail/index.lua b/app/switch/resources/scripts/app/voicemail/index.lua index 8435936c8..d7e81bf41 100644 --- a/app/switch/resources/scripts/app/voicemail/index.lua +++ b/app/switch/resources/scripts/app/voicemail/index.lua @@ -503,6 +503,61 @@ --valid voicemail if (voicemail_uuid ~= nil) then + --check for an alternate voicemail location on this voicemail box; when + --enabled, divert the caller to that destination instead of leaving a + --message. caller id is preserved (session:transfer keeps channel vars). + -- + --this is a per-voicemail-box setting (v_voicemails table) — it only + --fires when a call actually reaches this script with action=save, so + --it does NOT interfere with the dialplan's forward-on-no-answer or + --with call-center/ring-group/fifo no-answer handling. Those paths + --never enter this script in the first place if they're configured to + --route elsewhere before voicemail. + -- + --the cc_side / ring_group_uuid / fifo_role / dialed_extension guard + --is kept as a safety net: if for any reason a call-center or + --ring-group leg lands here, we don't want a session:transfer to yank + --it out of the queue's control. + do + local group_signals = { + cc_side = session:getVariable("cc_side"), + cc_queue = session:getVariable("cc_queue"), + dialed_extension = session:getVariable("dialed_extension"), + ring_group_uuid = session:getVariable("ring_group_uuid"), + fifo_role = session:getVariable("fifo_role"), + }; + local in_group_call = false; + for signal_name, signal_value in pairs(group_signals) do + if (signal_value ~= nil and signal_value ~= '') then + in_group_call = true; + freeswitch.consoleLog("notice", "[voicemail] alternate voicemail divert skipped: " .. signal_name .. "=" .. tostring(signal_value) .. " (call-center / ring-group / fifo leg)\n"); + break; + end + end + if (not in_group_call) then + local alt_sql = [[SELECT + cast(alternate_voicemail_enabled as text) as alt_enabled, + alternate_voicemail_destination + FROM v_voicemails + WHERE voicemail_uuid = :voicemail_uuid + LIMIT 1]]; + local alt_params = {voicemail_uuid = voicemail_uuid}; + local alt_enabled = false; + local alt_destination = nil; + dbh:query(alt_sql, alt_params, function(row) + alt_enabled = (row["alt_enabled"] == "true"); + alt_destination = row["alternate_voicemail_destination"]; + end); + if (alt_enabled and alt_destination ~= nil and alt_destination ~= '') then + freeswitch.consoleLog("notice", "[voicemail] alternate voicemail location enabled — diverting caller " .. (caller_id_number or '') .. " to " .. alt_destination .. " instead of leaving a message for " .. voicemail_id .. "\n"); + if (session ~= nil and session:ready()) then + session:transfer(alt_destination, "XML", context); + end + return; + end + end + end + --play the greeting timeouts = 0; play_greeting(); diff --git a/app/voicemails/app_config.php b/app/voicemails/app_config.php index 96593d4a2..eb0d5df5d 100644 --- a/app/voicemails/app_config.php +++ b/app/voicemails/app_config.php @@ -501,6 +501,14 @@ $apps[$x]['db'][$y]['fields'][$z]['search'] = 'true'; $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "Enter the description."; $z++; + $apps[$x]['db'][$y]['fields'][$z]['name'] = "alternate_voicemail_destination"; + $apps[$x]['db'][$y]['fields'][$z]['type'] = "text"; + $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "When set together with alternate_voicemail_enabled, callers reaching this voicemail box are transferred to this destination before the greeting plays. Caller ID is preserved."; + $z++; + $apps[$x]['db'][$y]['fields'][$z]['name'] = "alternate_voicemail_enabled"; + $apps[$x]['db'][$y]['fields'][$z]['type'] = "boolean"; + $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "When true and alternate_voicemail_destination is set, the call is diverted instead of leaving a message."; + $z++; $apps[$x]['db'][$y]['fields'][$z]['name'] = "voicemail_name_base64"; $apps[$x]['db'][$y]['fields'][$z]['type'] = "text"; $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = ""; diff --git a/app/voicemails/app_languages.php b/app/voicemails/app_languages.php index 0b1f9520e..f8aaebc7b 100644 --- a/app/voicemails/app_languages.php +++ b/app/voicemails/app_languages.php @@ -2672,4 +2672,10 @@ $text['message-emails_resent']['zh-cn'] = "电子邮件已重新发送"; $text['message-emails_resent']['ja-jp'] = "再送信メール"; $text['message-emails_resent']['ko-kr'] = "이메일 재전송"; +$text['label-alternate_voicemail']['en-us'] = "Alternate Voicemail Location"; +$text['label-alternate_voicemail']['en-gb'] = "Alternate Voicemail Location"; + +$text['description-alternate_voicemail']['en-us'] = "When enabled, callers reaching this voicemail box are routed to this destination instead of leaving a message. The original Caller ID is preserved."; +$text['description-alternate_voicemail']['en-gb'] = "When enabled, callers reaching this voicemail box are routed to this destination instead of leaving a message. The original Caller ID is preserved."; + ?> \ No newline at end of file diff --git a/app/voicemails/voicemail_edit.php b/app/voicemails/voicemail_edit.php index 6cce718f8..c55916f46 100644 --- a/app/voicemails/voicemail_edit.php +++ b/app/voicemails/voicemail_edit.php @@ -60,6 +60,8 @@ $voicemail_option_digits = ''; $voicemail_option_description = ''; $voicemail_mail_to = ''; + $alternate_voicemail_enabled = false; + $alternate_voicemail_destination = ''; $transcribe_enabled = $settings->get('transcribe', 'enabled', false); // Set variables from http GET parameters @@ -130,6 +132,8 @@ $voicemail_destination = $_POST["voicemail_destination"]; $voicemail_enabled = $_POST["voicemail_enabled"]; $voicemail_description = $_POST["voicemail_description"]; + $alternate_voicemail_enabled = filter_var($_POST["alternate_voicemail_enabled"] ?? false, FILTER_VALIDATE_BOOLEAN); + $alternate_voicemail_destination = $_POST["alternate_voicemail_destination"] ?? ''; $voicemail_tutorial = $_POST["voicemail_tutorial"]; $voicemail_recording_instructions = $_POST["voicemail_recording_instructions"]; $voicemail_recording_options = $_POST["voicemail_recording_options"]; @@ -138,6 +142,9 @@ //remove the space $voicemail_mail_to = str_replace(" ", "", $voicemail_mail_to); + + //sanitise the alternate voicemail destination — digits and * only (matches forward_*_destination) + $alternate_voicemail_destination = preg_replace('#[^\*0-9]#', '', $alternate_voicemail_destination); } //process the data @@ -212,6 +219,8 @@ } $array['voicemails'][0]['voicemail_enabled'] = $voicemail_enabled; $array['voicemails'][0]['voicemail_description'] = $voicemail_description; + $array['voicemails'][0]['alternate_voicemail_enabled'] = $alternate_voicemail_enabled ? 'true' : 'false'; + $array['voicemails'][0]['alternate_voicemail_destination'] = $alternate_voicemail_destination; //create permissions object $p = permissions::new(); @@ -367,7 +376,9 @@ $sql .= "voicemail_file, "; $sql .= "voicemail_local_after_email, "; $sql .= "voicemail_enabled, "; - $sql .= "voicemail_description "; + $sql .= "voicemail_description, "; + $sql .= "alternate_voicemail_enabled, "; + $sql .= "alternate_voicemail_destination "; $sql .= "from v_voicemails "; $sql .= "where domain_uuid = :domain_uuid "; $sql .= "and voicemail_uuid = :voicemail_uuid "; @@ -389,6 +400,8 @@ $voicemail_local_after_email = $row["voicemail_local_after_email"]; $voicemail_enabled = $row["voicemail_enabled"]; $voicemail_description = $row["voicemail_description"]; + $alternate_voicemail_enabled = filter_var($row["alternate_voicemail_enabled"] ?? false, FILTER_VALIDATE_BOOLEAN); + $alternate_voicemail_destination = $row["alternate_voicemail_destination"] ?? ''; } unset($sql, $parameters, $row); } @@ -854,6 +867,28 @@ echo "\n"; echo "\n"; + echo "