MikoPBX
Модули
Перевод этой страницы:
MikoPBX
Модули
Периодически каждая компания сталкивается с проблемой поступления «спам» звонков. В связи с этим возникает потребность блокировки определенных номеров, чтобы звонки с этих номеров не поступали.
<?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); } }
[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» - это идентификатор приложения