From 04a989313011203eb8dfe6f92bae6c7adc3a4d1a Mon Sep 17 00:00:00 2001 From: Antonio Fernandez Date: Mon, 27 Apr 2026 11:06:57 -0400 Subject: [PATCH] Added Wait Announcements to Ring Groups (#7919) --- app/ring_groups/app_config.php | 8 ++ app/ring_groups/app_languages.php | 112 +++++++++++++++++- app/ring_groups/ring_group_edit.php | 104 ++++++++++++++++ .../scripts/app/ring_groups/index.lua | 24 +++- .../resources/scripts/wait_announcement.lua | 70 +++++++++++ 5 files changed, 315 insertions(+), 3 deletions(-) create mode 100644 app/switch/resources/scripts/app/ring_groups/resources/scripts/wait_announcement.lua diff --git a/app/ring_groups/app_config.php b/app/ring_groups/app_config.php index d4419eebb..b8a554c98 100644 --- a/app/ring_groups/app_config.php +++ b/app/ring_groups/app_config.php @@ -403,6 +403,14 @@ $apps[$x]['db'][$y]['fields'][$z]['type'] = "text"; $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "Toll Allow for Ring Group Forward."; $z++; + $apps[$x]['db'][$y]['fields'][$z]['name'] = "ring_group_wait_announcement"; + $apps[$x]['db'][$y]['fields'][$z]['type'] = "text"; + $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "Select the wait announcement audio file."; + $z++; + $apps[$x]['db'][$y]['fields'][$z]['name'] = "ring_group_wait_interval"; + $apps[$x]['db'][$y]['fields'][$z]['type'] = "numeric"; + $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "Enter the interval in seconds between announcements."; + $z++; $apps[$x]['db'][$y]['fields'][$z]['name'] = "insert_date"; $apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = 'timestamptz'; $apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = 'date'; diff --git a/app/ring_groups/app_languages.php b/app/ring_groups/app_languages.php index 7dbb97fb6..c36c121c4 100644 --- a/app/ring_groups/app_languages.php +++ b/app/ring_groups/app_languages.php @@ -729,6 +729,60 @@ $text['label-strategy']['zh-cn'] = "战略"; $text['label-strategy']['ja-jp'] = "ストラテジー"; $text['label-strategy']['ko-kr'] = "전략"; +$text['label-wait_announcement']['en-us'] = "Wait Announcement"; +$text['label-wait_announcement']['en-gb'] = "Wait Announcement"; +$text['label-wait_announcement']['ar-eg'] = "إعلان الانتظار"; +$text['label-wait_announcement']['de-at'] = "Warteansage"; +$text['label-wait_announcement']['de-ch'] = "Warteansage"; +$text['label-wait_announcement']['de-de'] = "Warteansage"; +$text['label-wait_announcement']['el-gr'] = "Αναγγελία αναμονής"; +$text['label-wait_announcement']['es-cl'] = "Anuncio de espera"; +$text['label-wait_announcement']['es-mx'] = "Anuncio de espera"; +$text['label-wait_announcement']['fr-ca'] = "Annonce d'attente"; +$text['label-wait_announcement']['fr-fr'] = "Annonce d'attente"; +$text['label-wait_announcement']['he-il'] = "הודעת המתנה"; +$text['label-wait_announcement']['it-it'] = "Annuncio di attesa"; +$text['label-wait_announcement']['ka-ge'] = "ლოდინის განცხადება"; +$text['label-wait_announcement']['nl-nl'] = "Wachtmelding"; +$text['label-wait_announcement']['pl-pl'] = "Komunikat oczekiwania"; +$text['label-wait_announcement']['pt-br'] = "Anúncio de espera"; +$text['label-wait_announcement']['pt-pt'] = "Anúncio de espera"; +$text['label-wait_announcement']['ro-ro'] = "Anunț de așteptare"; +$text['label-wait_announcement']['ru-ru'] = "Объявление ожидания"; +$text['label-wait_announcement']['sv-se'] = "Väntmeddelande"; +$text['label-wait_announcement']['uk-ua'] = "Оголошення очікування"; +$text['label-wait_announcement']['tr-tr'] = "Bekleme Anonsu"; +$text['label-wait_announcement']['zh-cn'] = "等待公告"; +$text['label-wait_announcement']['ja-jp'] = "待機アナウンス"; +$text['label-wait_announcement']['ko-kr'] = "대기 안내"; + +$text['label-wait_interval']['en-us'] = "Wait Interval"; +$text['label-wait_interval']['en-gb'] = "Wait Interval"; +$text['label-wait_interval']['ar-eg'] = "فاصل الانتظار"; +$text['label-wait_interval']['de-at'] = "Warteintervall"; +$text['label-wait_interval']['de-ch'] = "Warteintervall"; +$text['label-wait_interval']['de-de'] = "Warteintervall"; +$text['label-wait_interval']['el-gr'] = "Διάστημα αναμονής"; +$text['label-wait_interval']['es-cl'] = "Intervalo de espera"; +$text['label-wait_interval']['es-mx'] = "Intervalo de espera"; +$text['label-wait_interval']['fr-ca'] = "Intervalle d'attente"; +$text['label-wait_interval']['fr-fr'] = "Intervalle d'attente"; +$text['label-wait_interval']['he-il'] = "מרווח המתנה"; +$text['label-wait_interval']['it-it'] = "Intervallo di attesa"; +$text['label-wait_interval']['ka-ge'] = "ლოდინის ინტერვალი"; +$text['label-wait_interval']['nl-nl'] = "Wachtinterval"; +$text['label-wait_interval']['pl-pl'] = "Interwał oczekiwania"; +$text['label-wait_interval']['pt-br'] = "Intervalo de espera"; +$text['label-wait_interval']['pt-pt'] = "Intervalo de espera"; +$text['label-wait_interval']['ro-ro'] = "Interval de așteptare"; +$text['label-wait_interval']['ru-ru'] = "Интервал ожидания"; +$text['label-wait_interval']['sv-se'] = "Väntintervall"; +$text['label-wait_interval']['uk-ua'] = "Інтервал очікування"; +$text['label-wait_interval']['tr-tr'] = "Bekleme Aralığı"; +$text['label-wait_interval']['zh-cn'] = "等待间隔"; +$text['label-wait_interval']['ja-jp'] = "待機間隔"; +$text['label-wait_interval']['ko-kr'] = "대기 간격"; + $text['label-ringback']['en-us'] = "Ring Back"; $text['label-ringback']['en-gb'] = "Ring Back"; $text['label-ringback']['ar-eg'] = "العودة"; @@ -1804,8 +1858,62 @@ $text['description-strategy']['sv-se'] = "Välj strategi för ringflöde."; $text['description-strategy']['uk-ua'] = "Виберіть стратегію кільця."; $text['description-strategy']['tr-tr'] = "Zil stratejisini seçin."; $text['description-strategy']['zh-cn'] = "选择响铃策略。"; -$text['description-strategy']['ja-jp'] = "リング戦略を選択します。"; -$text['description-strategy']['ko-kr'] = "링 전략을 선택합니다."; + $text['description-strategy']['ja-jp'] = "リング戦略を選択します。"; + $text['description-strategy']['ko-kr'] = "링 전략을 선택합니다."; + + $text['description-wait_announcement']['en-us'] = "Select an audio file to play as an announcement while waiting."; + $text['description-wait_announcement']['en-gb'] = "Select an audio file to play as an announcement while waiting."; + $text['description-wait_announcement']['ar-eg'] = "حدد ملفًا صوتيًا ليتم تشغيله كإعلان أثناء الانتظار."; + $text['description-wait_announcement']['de-at'] = "Wählen Sie eine Audiodatei aus, die während der Wartezeit als Ansage abgespielt wird."; + $text['description-wait_announcement']['de-ch'] = "Wählen Sie eine Audiodatei aus, die während der Wartezeit als Ansage abgespielt wird."; + $text['description-wait_announcement']['de-de'] = "Wählen Sie eine Audiodatei aus, die während der Wartezeit als Ansage abgespielt wird."; + $text['description-wait_announcement']['el-gr'] = "Επιλέξτε ένα αρχείο ήχου για αναπαραγωγή ως ανακοίνωση κατά την αναμονή."; + $text['description-wait_announcement']['es-cl'] = "Seleccione un archivo de audio para reproducirlo como anuncio mientras espera."; + $text['description-wait_announcement']['es-mx'] = "Seleccione un archivo de audio para reproducirlo como anuncio mientras espera."; + $text['description-wait_announcement']['fr-ca'] = "Sélectionnez un fichier audio à lire comme annonce pendant l'attente."; + $text['description-wait_announcement']['fr-fr'] = "Sélectionnez un fichier audio à lire comme annonce pendant l'attente."; + $text['description-wait_announcement']['he-il'] = "בחר קובץ שמע שיושמע כהודעה בזמן ההמתנה."; + $text['description-wait_announcement']['it-it'] = "Seleziona un file audio da riprodurre come annuncio durante l'attesa."; + $text['description-wait_announcement']['ka-ge'] = "აირჩიეთ აუდიო ფაილი, რომელიც ლოდინის დროს გამოცხადებად დაკვრდება."; + $text['description-wait_announcement']['nl-nl'] = "Selecteer een audiobestand dat tijdens het wachten als aankondiging wordt afgespeeld."; + $text['description-wait_announcement']['pl-pl'] = "Wybierz plik audio, który ma być odtwarzany jako komunikat podczas oczekiwania."; + $text['description-wait_announcement']['pt-br'] = "Selecione um arquivo de áudio para ser reproduzido como anúncio durante a espera."; + $text['description-wait_announcement']['pt-pt'] = "Selecione um ficheiro de áudio para ser reproduzido como anúncio durante a espera."; + $text['description-wait_announcement']['ro-ro'] = "Selectați un fișier audio care să fie redat ca anunț în timpul așteptării."; + $text['description-wait_announcement']['ru-ru'] = "Выберите аудиофайл, который будет воспроизводиться как объявление во время ожидания."; + $text['description-wait_announcement']['sv-se'] = "Välj en ljudfil som ska spelas upp som meddelande under väntetiden."; + $text['description-wait_announcement']['uk-ua'] = "Виберіть аудіофайл, який відтворюватиметься як оголошення під час очікування."; + $text['description-wait_announcement']['tr-tr'] = "Bekleme sırasında anons olarak çalınacak bir ses dosyası seçin."; + $text['description-wait_announcement']['zh-cn'] = "选择一个音频文件,在等待时作为公告播放。"; + $text['description-wait_announcement']['ja-jp'] = "待機中にアナウンスとして再生する音声ファイルを選択します。"; + $text['description-wait_announcement']['ko-kr'] = "대기 중 안내 방송으로 재생할 오디오 파일을 선택하세요."; + + $text['description-wait_interval']['en-us'] = "Interval in seconds between announcement plays. If blank, 30 will be used."; + $text['description-wait_interval']['en-gb'] = "Interval in seconds between announcement plays. If blank, 30 will be used."; + $text['description-wait_interval']['ar-eg'] = "الفاصل الزمني بالثواني بين تشغيل الإعلانات."; + $text['description-wait_interval']['de-at'] = "Intervall in Sekunden zwischen den Ansagen."; + $text['description-wait_interval']['de-ch'] = "Intervall in Sekunden zwischen den Ansagen."; + $text['description-wait_interval']['de-de'] = "Intervall in Sekunden zwischen den Ansagen."; + $text['description-wait_interval']['el-gr'] = "Διάστημα σε δευτερόλεπτα μεταξύ των αναπαραγωγών της ανακοίνωσης."; + $text['description-wait_interval']['es-cl'] = "Intervalo en segundos entre cada reproducción del anuncio."; + $text['description-wait_interval']['es-mx'] = "Intervalo en segundos entre cada reproducción del anuncio."; + $text['description-wait_interval']['fr-ca'] = "Intervalle en secondes entre les lectures de l'annonce."; + $text['description-wait_interval']['fr-fr'] = "Intervalle en secondes entre les lectures de l'annonce."; + $text['description-wait_interval']['he-il'] = "המרווח בשניות בין השמעות ההודעה."; + $text['description-wait_interval']['it-it'] = "Intervallo in secondi tra le riproduzioni dell'annuncio."; + $text['description-wait_interval']['ka-ge'] = "ინტერვალი წამებში განცხადებების დაკვრებს შორის."; + $text['description-wait_interval']['nl-nl'] = "Interval in seconden tussen het afspelen van de aankondiging."; + $text['description-wait_interval']['pl-pl'] = "Odstęp w sekundach między odtworzeniami komunikatu."; + $text['description-wait_interval']['pt-br'] = "Intervalo em segundos entre as reproduções do anúncio."; + $text['description-wait_interval']['pt-pt'] = "Intervalo em segundos entre as reproduções do anúncio."; + $text['description-wait_interval']['ro-ro'] = "Intervalul în secunde dintre redările anunțului."; + $text['description-wait_interval']['ru-ru'] = "Интервал в секундах между воспроизведениями объявления."; + $text['description-wait_interval']['sv-se'] = "Intervall i sekunder mellan uppspelningarna av meddelandet."; + $text['description-wait_interval']['uk-ua'] = "Інтервал у секундах між відтвореннями оголошення."; + $text['description-wait_interval']['tr-tr'] = "Anons çalmaları arasındaki saniye cinsinden aralık."; + $text['description-wait_interval']['zh-cn'] = "公告播放之间的间隔秒数。"; + $text['description-wait_interval']['ja-jp'] = "アナウンス再生間の秒数です。"; + $text['description-wait_interval']['ko-kr'] = "안내 방송 재생 사이의 간격(초)입니다."; $text['description-skip_active']['en-us'] = "Skip destinations with active calls."; $text['description-skip_active']['en-gb'] = "Skip destinations with active calls."; diff --git a/app/ring_groups/ring_group_edit.php b/app/ring_groups/ring_group_edit.php index 74a99e4eb..738acd4bd 100644 --- a/app/ring_groups/ring_group_edit.php +++ b/app/ring_groups/ring_group_edit.php @@ -58,6 +58,8 @@ $ring_group_forward_destination = ''; $ring_group_forward_toll_allow = ''; $ring_group_description = ''; + $ring_group_wait_announcement = ''; + $ring_group_wait_interval = ''; $onkeyup = ''; $total_ring_groups = '0'; $ring_group_ringback = $settings->get('ring_group', 'default_ringback', ''); @@ -209,6 +211,8 @@ $ring_group_name = $_POST["ring_group_name"]; $ring_group_extension = $_POST["ring_group_extension"]; $ring_group_greeting = $_POST["ring_group_greeting"]; + $ring_group_wait_announcement = $_POST["ring_group_wait_announcement"]; + $ring_group_wait_interval = $_POST["ring_group_wait_interval"]; $ring_group_strategy = $_POST["ring_group_strategy"]; $ring_group_destinations = $_POST["ring_group_destinations"]; $ring_group_timeout_action = $_POST["ring_group_timeout_action"]; @@ -392,6 +396,8 @@ $array['ring_groups'][0]["ring_group_name"] = $ring_group_name; $array['ring_groups'][0]["ring_group_extension"] = $ring_group_extension; $array['ring_groups'][0]["ring_group_greeting"] = $ring_group_greeting; + $array['ring_groups'][0]["ring_group_wait_announcement"] = $ring_group_wait_announcement; + $array['ring_groups'][0]["ring_group_wait_interval"] = $ring_group_wait_interval; $array['ring_groups'][0]["ring_group_strategy"] = $ring_group_strategy; $array["ring_groups"][0]["ring_group_exit_key"] = $ring_group_exit_key; $array["ring_groups"][0]["ring_group_call_timeout"] = $ring_group_call_timeout; @@ -586,6 +592,8 @@ $ring_group_name = $row["ring_group_name"]; $ring_group_extension = $row["ring_group_extension"]; $ring_group_greeting = $row["ring_group_greeting"]; + $ring_group_wait_announcement = $row["ring_group_wait_announcement"]; + $ring_group_wait_interval = $row["ring_group_wait_interval"]; $ring_group_strategy = $row["ring_group_strategy"]; $ring_group_timeout_app = $row["ring_group_timeout_app"]; $ring_group_timeout_data = $row["ring_group_timeout_data"]; @@ -620,6 +628,8 @@ $ring_group_exit_key = $ring_group_exit_key ?? ''; $ring_group_call_timeout = $ring_group_call_timeout ?? '30'; $ring_group_greeting = $ring_group_greeting ?? ''; + $ring_group_wait_announcement = $ring_group_wait_announcement ?? ''; + $ring_group_wait_interval = $ring_group_wait_interval ?? ''; $ring_group_forward_enabled = $ring_group_forward_enabled ?? false; $ring_group_context = $ring_group_context ?? $domain_name; $ring_group_enabled = $ring_group_enabled ?? true; @@ -910,6 +920,100 @@ echo "\n"; echo "\n"; + $instance_id = 'ring_group_wait_announcement'; + $instance_label = 'wait_announcement'; + $instance_value = $ring_group_wait_announcement; + echo "\n"; + echo "\n"; + echo " ".$text['label-wait_announcement']."\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + if (if_group("superadmin")) { + echo ""; + } + if ((permission_exists('recording_play') || permission_exists('recording_download')) && (!empty($playable) || empty($instance_value))) { + switch (pathinfo($playable, PATHINFO_EXTENSION)) { + case 'wav' : $mime_type = 'audio/wav'; break; + case 'mp3' : $mime_type = 'audio/mpeg'; break; + case 'ogg' : $mime_type = 'audio/ogg'; break; + } + echo ""; + echo button::create(['type'=>'button','title'=>$text['label-play'].' / '.$text['label-pause'],'icon'=>$settings->get('theme', 'button_icon_play'),'id'=>'recording_button_'.$instance_id,'style'=>'display: '.(!empty($mime_type) ? 'inline' : 'none'),'onclick'=>"recording_play('".$instance_id."', document.getElementById('".$instance_id."').value, document.getElementById('".$instance_id."').options[document.getElementById('".$instance_id."').selectedIndex].parentNode.getAttribute('data-type'))"]); + unset($playable, $mime_type); + } + echo "
\n"; + echo $text['description-wait_announcement']."\n"; + echo "\n"; + echo "\n"; + + echo "\n"; + echo "\n"; + echo " ".$text['label-wait_interval']."\n"; + echo "\n"; + echo "\n"; + echo " \n"; + echo "
\n"; + echo $text['description-wait_interval']."\n"; + echo "\n"; + echo "\n"; + echo "\n"; echo "\n"; echo " ".$text['label-strategy']."\n"; diff --git a/app/switch/resources/scripts/app/ring_groups/index.lua b/app/switch/resources/scripts/app/ring_groups/index.lua index df71dfe1e..583bb9e52 100644 --- a/app/switch/resources/scripts/app/ring_groups/index.lua +++ b/app/switch/resources/scripts/app/ring_groups/index.lua @@ -250,7 +250,9 @@ sql = sql .. "cast(r.ring_group_call_forward_enabled as text), "; sql = sql .. "cast(r.ring_group_follow_me_enabled as text), "; sql = sql .. "r.ring_group_missed_call_app, "; - sql = sql .. "r.ring_group_missed_call_data "; + sql = sql .. "r.ring_group_missed_call_data, "; + sql = sql .. "r.ring_group_wait_announcement, "; + sql = sql .. "r.ring_group_wait_interval "; sql = sql .. "FROM v_ring_groups as r, v_domains as d "; sql = sql .. "WHERE r.ring_group_uuid = :ring_group_uuid "; sql = sql .. "AND r.domain_uuid = d.domain_uuid "; @@ -277,6 +279,8 @@ ring_group_follow_me_enabled = row["ring_group_follow_me_enabled"]; missed_call_app = row["ring_group_missed_call_app"]; missed_call_data = row["ring_group_missed_call_data"]; + ring_group_wait_announcement = row["ring_group_wait_announcement"]; + ring_group_wait_interval = row["ring_group_wait_interval"]; end); --create the settings object @@ -346,6 +350,24 @@ end end +--answer the call if not answered and there is wait announcement + if (ring_group_wait_announcement and #ring_group_wait_announcement > 0 and not session_answer) then + session:answer(); + session_answer = true; + end + +--schedule wait announcements + if (ring_group_wait_announcement and #ring_group_wait_announcement > 0) then + local interval = ring_group_wait_interval or 30; + session:setVariable("ring_group_wait_announcement", ring_group_wait_announcement); + session:setVariable("ring_group_wait_interval", tostring(interval)); + session:setVariable("ring_group_wait_domain_name", domain_name); + session:setVariable("ring_group_wait_domain_uuid", domain_uuid); + local wait_announcement_script = scripts_dir:gsub('\\','/') .. "/app/ring_groups/resources/scripts/wait_announcement.lua"; + local command = "sched_api +" .. interval .. " " .. uuid .. " lua " .. wait_announcement_script .. " " .. uuid; + api:executeString(command); + end + --call screen enabled if (ring_group_call_screen_enabled == 'true') then diff --git a/app/switch/resources/scripts/app/ring_groups/resources/scripts/wait_announcement.lua b/app/switch/resources/scripts/app/ring_groups/resources/scripts/wait_announcement.lua new file mode 100644 index 000000000..9891a1446 --- /dev/null +++ b/app/switch/resources/scripts/app/ring_groups/resources/scripts/wait_announcement.lua @@ -0,0 +1,70 @@ +--include config.lua + require "resources.functions.config"; + +--prepare the api + api = freeswitch.API(); + +--define the trim function + require "resources.functions.trim"; + require "resources.functions.file_exists"; + +--include functions + local basename = require "resources.functions.basename"; + +--get the argv values + script_name = argv[0]; + uuid = argv[1]; + announcement = (trim(api:executeString("uuid_getvar " .. uuid .. " ring_group_wait_announcement"))); + interval = tonumber((trim(api:executeString("uuid_getvar " .. uuid .. " ring_group_wait_interval")))) or 30; + domain_name = (trim(api:executeString("uuid_getvar " .. uuid .. " ring_group_wait_domain_name"))); + domain_uuid = (trim(api:executeString("uuid_getvar " .. uuid .. " ring_group_wait_domain_uuid"))); + +--resolve the announcement to something uuid_broadcast can play + local function resolve_announcement(file_name) + if not file_name or #file_name == 0 then + return nil + end + + if string.sub(file_name, 1, 1) == "/" or string.match(file_name, "^[a-z]+:") then + return file_name + end + + if basename(file_name) == file_name then + local recording_path = recordings_dir .. "/" .. domain_name .. "/" .. file_name; + if file_exists(recording_path) then + return recording_path + end + + local sounds_dir = (trim(api:executeString("uuid_getvar " .. uuid .. " sounds_dir"))); + local default_language = (trim(api:executeString("uuid_getvar " .. uuid .. " default_language"))); + local default_dialect = (trim(api:executeString("uuid_getvar " .. uuid .. " default_dialect"))); + local default_voice = (trim(api:executeString("uuid_getvar " .. uuid .. " default_voice"))); + + if not default_language or #default_language == 0 then default_language = 'en'; end + if not default_dialect or #default_dialect == 0 then default_dialect = 'us'; end + if not default_voice or #default_voice == 0 then default_voice = 'callie'; end + + if sounds_dir and #sounds_dir > 0 then + local sound_path = sounds_dir .. "/" .. default_language .. "/" .. default_dialect .. "/" .. default_voice .. "/" .. file_name; + if file_exists(sound_path) then + return sound_path + end + end + end + + return file_name + end + +--play the wait announcement and reschedule while the call is still active + if trim(api:executeString("uuid_exists " .. uuid)) == "true" then + local media_path = resolve_announcement(announcement); + if media_path and #media_path > 0 then + api:executeString("uuid_setvar " .. uuid .. " ringback "); + api:executeString("uuid_setvar " .. uuid .. " transfer_ringback "); + api:executeString("uuid_broadcast " .. uuid .. " " .. media_path .. " aleg"); + end + + wait_announcement_script = scripts_dir:gsub('\\','/') .. "/app/ring_groups/resources/scripts/wait_announcement.lua"; + command = "sched_api +" .. interval .. " " .. uuid .. " lua " .. wait_announcement_script .. " " .. uuid; + api:executeString(command); + end