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

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


faq:interactive-ivr-settings

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

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:​|Обратно к инструкциям]]
  
faq/interactive-ivr-settings.txt · Последние изменения: 2024/01/24 11:00 — Портнов Алексей