Инструменты пользователя

Инструменты сайта


faq:interactive-ivr-settings

Интерактивное упраление АТС (пример)

Обратно к инструкциям

Опишием скрипт, который позволит сотрудникам позвонить на номер приложения или с мобильного на номер компании для настройки длительности звонка на внутренний номер перед переадресацией на мобильный.

Периодически каждая компания сталкивается с проблемой поступления «спам» звонков. В связи с этим возникает потребность блокировки определенных номеров, чтобы звонки с этих номеров не поступали.

  1. Создайте новое «Приложение диалплан»
  2. Укажите произвольное название, к примеру User settings
  3. Выберите «Тип кода» - «PHP AGI Скрипт»
  4. На вкладке «Программный код» вставьте:
    <?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);
        }
    }
  5. В скрипте задайте значение константы API_KEY, см. инструкции
  6. Сохраните изменения и скопируйте идентификатор приложения из адресной строки браузера
  7. Перейдите в раздел СистемаКастомизация системных файлов, откройте для редактирования файл extensions.conf
  8. Выберите режим «Добавлять в конец файла», внизу в черное поле для редактирования вставьте следующие строки:
    [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()

    , где «DIALPLAN-APP-BE22D80F2A270C0020A1192B001A665» - это идентификатор приложения

  9. Сохраните изменения!

Обратно к инструкциям

faq/interactive-ivr-settings.txt · Последние изменения: 2024/01/24 11:00 — Портнов Алексей