Здесь показаны различия между двумя версиями данной страницы.
— |
faq:interactive-ivr-settings [2024/01/24 11:00] (текущий) Портнов Алексей создано |
||
---|---|---|---|
Строка 1: | Строка 1: | ||
+ | ====== Интерактивное упраление АТС (пример) ====== | ||
+ | |||
+ | [[faq:|Обратно к инструкциям]] | ||
+ | <note tip>Опишием скрипт, который позволит сотрудникам позвонить на номер приложения или с мобильного на номер компании для настройки длительности звонка на внутренний номер перед переадресацией на мобильный. </note> | ||
+ | Периодически каждая компания сталкивается с проблемой поступления «спам» звонков. В связи с этим возникает потребность блокировки определенных номеров, чтобы звонки с этих номеров не поступали. | ||
+ | |||
+ | - Создайте новое "[[:dialplan-applications|Приложение диалплан]]" | ||
+ | - Укажите произвольное название, к примеру **User settings** | ||
+ | - Выберите "**Тип кода**" - "**PHP AGI Скрипт**" | ||
+ | - На вкладке "**Программный код**" вставьте: <code><?php | ||
+ | require_once('Globals.php'); | ||
+ | |||
+ | use MikoPBX\Core\System\Util; | ||
+ | use MikoPBX\Core\Asterisk\AGI; | ||
+ | use MikoPBX\Common\Models\Extensions; | ||
+ | use MikoPBX\Common\Models\ExtensionForwardingRights; | ||
+ | class YandexSynthesize | ||
+ | { | ||
+ | public const TTS_DIR = '/storage/usbdisk1/mikopbx/media/yandex-tts'; | ||
+ | public const API_KEY = ''; | ||
+ | private string $voice = 'alena'; | ||
+ | |||
+ | public function __construct() | ||
+ | { | ||
+ | if(!file_exists(self::TTS_DIR)){ | ||
+ | Util::mwMkdir(self::TTS_DIR); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Генерирует и скачивает в на внешний диск файл с речью. | ||
+ | * | ||
+ | * @param $text_to_speech - генерируемый текст | ||
+ | * @param $voice - голос | ||
+ | * | ||
+ | * @return null|string | ||
+ | * | ||
+ | * https://tts.api.cloud.yandex.net/speech/v1/tts:synthesize | ||
+ | */ | ||
+ | public function makeSpeechFromText($text_to_speech): ?string | ||
+ | { | ||
+ | $speech_extension = '.raw'; | ||
+ | $result_extension = '.wav'; | ||
+ | $speech_filename = md5($text_to_speech . $this->voice); | ||
+ | $fullFileName = self::TTS_DIR .'/'. $speech_filename . $result_extension; | ||
+ | $fullFileNameFromService = self::TTS_DIR .'/'. $speech_filename . $speech_extension; | ||
+ | |||
+ | // Проверим вдург мы ранее уже генерировали такой файл. | ||
+ | if (file_exists($fullFileName) && filesize($fullFileName) > 0) { | ||
+ | return self::TTS_DIR .'/'. $speech_filename; | ||
+ | } | ||
+ | |||
+ | // Файла нет в кеше, будем генерировать новый. | ||
+ | $post_vars = [ | ||
+ | 'lang' => 'ru-RU', | ||
+ | 'format' => 'lpcm', | ||
+ | 'speed' => '1.0', | ||
+ | 'sampleRateHertz' => '8000', | ||
+ | 'voice' => $this->voice, | ||
+ | 'text' => urldecode($text_to_speech), | ||
+ | ]; | ||
+ | |||
+ | $fp = fopen($fullFileNameFromService, 'wb'); | ||
+ | $curl = curl_init(); | ||
+ | curl_setopt($curl, CURLOPT_HTTPHEADER, ["Authorization: Api-Key ".self::API_KEY]); | ||
+ | curl_setopt($curl, CURLOPT_FILE, $fp); | ||
+ | curl_setopt($curl, CURLOPT_POST, true); | ||
+ | curl_setopt($curl, CURLOPT_TIMEOUT, 4); | ||
+ | curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post_vars)); | ||
+ | curl_setopt($curl, CURLOPT_URL, 'https://tts.api.cloud.yandex.net/speech/v1/tts:synthesize'); | ||
+ | curl_exec($curl); | ||
+ | $http_code = (int)curl_getinfo($curl, CURLINFO_HTTP_CODE); | ||
+ | curl_close($curl); | ||
+ | fclose($fp); | ||
+ | |||
+ | if (200 === $http_code && file_exists($fullFileNameFromService) && filesize($fullFileNameFromService) > 0) { | ||
+ | exec("sox -r 8000 -e signed-integer -b 16 -c 1 -t raw $fullFileNameFromService $fullFileName"); | ||
+ | if (file_exists($fullFileName)) { | ||
+ | // Удалим raw файл. | ||
+ | @unlink($fullFileNameFromService); | ||
+ | // Файл успешно сгененрирован | ||
+ | return self::TTS_DIR.'/'.$speech_filename; | ||
+ | } | ||
+ | } elseif (file_exists($fullFileNameFromService)) { | ||
+ | @unlink($fullFileNameFromService); | ||
+ | } | ||
+ | return null; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | $agi = new AGI(); | ||
+ | $agi->set_variable('AGIEXITONHANGUP', 'yes'); | ||
+ | $agi->set_variable('AGISIGHUP', 'yes'); | ||
+ | $agi->set_variable('__ENDCALLONANSWER', 'yes'); | ||
+ | $agi->answer(); | ||
+ | |||
+ | $userPhone = $agi->request['agi_callerid']; | ||
+ | |||
+ | $userData = Extensions::findFirst("number='$userPhone'"); | ||
+ | if(!$userData || !empty($userData->userid)){ | ||
+ | exit(0); | ||
+ | } | ||
+ | |||
+ | $ys = new YandexSynthesize(); | ||
+ | $filenameAlert = $ys->makeSpeechFromText('Добрый день '); | ||
+ | $agi->exec('Playback', $filenameAlert); | ||
+ | $filenameAlert = $ys->makeSpeechFromText($userData->callerid); | ||
+ | $agi->exec('Playback', $filenameAlert); | ||
+ | |||
+ | $filenameCheck = $ys->makeSpeechFromText('Нажмите 1, чтобы настроить длительность вызова на внутренний номер. Нажмите 0, если желаете продолжить вызов.'); | ||
+ | $result = $agi->getData($filenameCheck, 3000, 1); | ||
+ | $selectedNum = $result['result']??''; | ||
+ | if($selectedNum !== '1'){ | ||
+ | exit(0); | ||
+ | } | ||
+ | $filenameCheck = $ys->makeSpeechFromText('Укажитель длительность вызова, значение от 3 до 99'); | ||
+ | $result = $agi->getData($filenameCheck, 3000, 2); | ||
+ | $selectedNum = $result['result']??''; | ||
+ | |||
+ | if(is_numeric($selectedNum)){ | ||
+ | $selectedNum = max(3, (int)$selectedNum); | ||
+ | $filenameAlert = $ys->makeSpeechFromText('Устанавливаем значение '.$selectedNum); | ||
+ | $agi->exec('Playback', $filenameAlert); | ||
+ | |||
+ | $userData = Extensions::findFirst("userid='$userData->userid' AND type='SIP'"); | ||
+ | if($userData){ | ||
+ | $forward = ExtensionForwardingRights::findFirst("extension='$userData->number'"); | ||
+ | if($forward){ | ||
+ | $forward->ringlength = $selectedNum; | ||
+ | } | ||
+ | $forward->save(); | ||
+ | $agi->hangup(); | ||
+ | }else{ | ||
+ | $filenameAlert = $ys->makeSpeechFromText('Ошибка, не найден внутренний номер'); | ||
+ | $agi->exec('Playback', $filenameAlert); | ||
+ | } | ||
+ | }</code> | ||
+ | - В скрипте задайте значение константы **API_KEY**, см. [[https://wiki.miko.ru/smartivr:yandextts|инструкции]] | ||
+ | - Сохраните изменения и скопируйте идентификатор приложения из адресной строки браузера | ||
+ | - Перейдите в раздел **Система** -> **Кастомизация системных файлов**, откройте для редактирования файл **extensions.conf** {{ :providers:2018-12-11_170112.png |}} | ||
+ | - Выберите режим **"Добавлять в конец файла"**, внизу в черное поле для редактирования вставьте следующие строки:<code> | ||
+ | [add-trim-prefix-clid-custom] | ||
+ | exten => _[0-9*#+a-zA-Z][0-9*#+a-zA-Z]!,1,NoOp(start check blacklist) | ||
+ | same => n,AGI(DIALPLAN-APP-BE22D80F2A270C0020A1192B001A6653.php) | ||
+ | same => n,Return()</code>, где "**DIALPLAN-APP-BE22D80F2A270C0020A1192B001A665**" - это идентификатор приложения | ||
+ | - Сохраните изменения! | ||
+ | |||
+ | [[faq:|Обратно к инструкциям]] | ||