Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
06d876c
Change translations, change error message if no connection to 1C
jorikfon Sep 27, 2023
91beda7
Translated using Weblate (English)
weblate Sep 27, 2023
f3fe553
Translated using Weblate (Czech)
weblate Sep 27, 2023
caf866c
Translated using Weblate (Danish)
weblate Sep 27, 2023
22f24dd
Translated using Weblate (German)
weblate Sep 27, 2023
398b10f
Translated using Weblate (Spanish)
weblate Sep 27, 2023
c12c4d5
Translated using Weblate (French)
weblate Sep 27, 2023
d11fe9f
Translated using Weblate (Italian)
weblate Sep 27, 2023
a7c9c09
Translated using Weblate (Japanese)
weblate Sep 27, 2023
10b8b98
Translated using Weblate (Polish)
weblate Sep 27, 2023
d3a5967
Translated using Weblate (Portuguese)
weblate Sep 27, 2023
898e564
Translated using Weblate (Swedish)
weblate Sep 27, 2023
4cd1359
Translated using Weblate (Turkish)
weblate Sep 27, 2023
be867a7
Translated using Weblate (Ukrainian)
weblate Sep 27, 2023
88f6cfe
Translated using Weblate (Vietnamese)
weblate Sep 27, 2023
0f0c617
Translated using Weblate (Chinese (Simplified))
weblate Sep 27, 2023
63f29b9
Translated using Weblate (Georgian)
weblate Sep 27, 2023
47cc882
Translated using Weblate (Portuguese (Brazil))
weblate Sep 27, 2023
090a368
Translated using Weblate (Greek)
weblate Sep 27, 2023
174cf93
Translated using Weblate (Azerbaijani)
weblate Sep 27, 2023
0452d54
Translated using Weblate (Dutch)
weblate Sep 27, 2023
43ad5fa
Translated using Weblate (Romanian)
weblate Sep 27, 2023
9b4478b
Added translation using Weblate (Thai)
weblate Feb 23, 2024
1a5f8a0
Translated using Weblate (Thai)
weblate Feb 23, 2024
0c96fc1
Added translation using Weblate (Hungarian)
weblate Jul 30, 2024
c5b43e0
Translated using Weblate (Hungarian)
Korfa84 Jul 30, 2024
3cf8756
Translated using Weblate (Hungarian)
weblate Aug 12, 2024
e0600c1
Added translation using Weblate (Finnish)
weblate Sep 6, 2024
cd3a10e
Translated using Weblate (Finnish)
weblate Sep 6, 2024
ffa9d80
Added translation using Weblate (languages (generated) (languages))
weblate Sep 16, 2024
9f8013e
Update for PHP 8.3 and Phalcon 5.8
jorikfon Oct 1, 2024
facdc48
Update for PHP 8.3 and Phalcon 5.8
jorikfon Oct 7, 2024
1ead05a
Refactor checkbox usage
jorikfon Oct 16, 2024
085a904
Added translation using Weblate (Croatian)
weblate Nov 18, 2024
938a0d5
Translated using Weblate (Croatian)
weblate Nov 18, 2024
6d48686
Implement message length and count limits in AGICallLogic; update err…
jorikfon May 27, 2025
f88fad5
Add release settings to module.json
jorikfon Jun 5, 2025
6017d30
Translated using Weblate (Japanese)
Mai-Shinano Aug 28, 2025
1abbe52
Added translation using Weblate (Hebrew)
weblate Sep 29, 2025
5bbc81e
Added translation using Weblate (Persian)
weblate Sep 30, 2025
d2f85ea
Добавил возможность генерации речи через сервисы МИКО
boffart Nov 1, 2025
413bd17
Поправил вывод информации в лог
boffart Nov 1, 2025
024c256
Реализована поддержка телефонии 5.0
boffart Nov 7, 2025
5803f53
Реализована поддержка телефонии 5.0
boffart Nov 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Build and Publish

on:
push:
branches:
- master
- develop
workflow_dispatch:

jobs:
build:
uses: mikopbx/.github-workflows/.github/workflows/extension-publish.yml@master
with:
initial_version: "1.113"
secrets: inherit
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.DS_Store
5 changes: 5 additions & 0 deletions App/Controllers/ModuleSmartIVRController.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ public function indexAction(): void
];
$this->view->moduleCTI2Installed = PbxExtensionModules::count($parameters)>0;

$parameters = [
'conditions'=>'uniqid="ModuleCTIClientV5" and disabled!="1"'
];
$this->view->moduleCTI5Installed = PbxExtensionModules::count($parameters)>0;

$options = [
'extensions' => $forwardingExtensions
];
Expand Down
81 changes: 53 additions & 28 deletions App/Forms/ModuleSmartIVRForm.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
<?php
/**
* Copyright © MIKO LLC - All Rights Reserved
* Unauthorized copying of this file, via any medium is strictly prohibited
* Proprietary and confidential
* Written by Alexey Portnov, 2 2019
*/

/*
* MikoPBX - free phone system for small business
* Copyright © 2017-2024 Alexey Portnov and Nikolay Beketov
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*/
namespace Modules\ModuleSmartIVR\App\Forms;

use Phalcon\Forms\Element\Check;
Expand All @@ -15,10 +26,8 @@
use Phalcon\Forms\Element\Text;
use Phalcon\Forms\Form;


class ModuleSmartIVRForm extends Form
{

public function initialize($entity = null, $options = null)
{
$this->add(new Text('server1chost'));
Expand All @@ -28,75 +37,91 @@ public function initialize($entity = null, $options = null)
$this->add(new Text('database'));
$this->add(
new Numeric(
'number_of_repeat', [
'number_of_repeat',
[
'maxlength' => 2,
'style' => 'width: 80px;',
'defaultValue' => 1,
]
]
)
);

// UseSSL
$checkAr = ['value' => null];
if ($entity->useSSL) {
$checkAr = ['checked' => 'checked', 'value' => null];
}
$this->add(new Check('useSSL', $checkAr));
$this->addCheckBox('useSSL', intval($entity->useSSL) === 1);

// Library
$arrLibraryType = [
'1.0' => $this->translation->_('module_smivr_LibraryVer1'),
'2.0' => $this->translation->_('module_smivr_LibraryVer2'),
'5.0' => $this->translation->_('module_smivr_LibraryVer5'),
];

$library = new Select(
'library_1c', $arrLibraryType, [
'library_1c',
$arrLibraryType,
[
'using' => [
'id',
'name',
],
'useEmpty' => false,
'value' => $entity->library_1c,
'class' => 'ui selection dropdown library-type-select',
]
]
);
$this->add($library);

// FailOver Extension
$extension = new Select(
'failover_extension', $options['extensions'], [
'failover_extension',
$options['extensions'],
[
'using' => [
'id',
'name',
],
'useEmpty' => false,
'class' => 'ui selection dropdown search forwarding-select',
]
]
);
$this->add($extension);

// Timeout Extension
$extension = new Select(
'timeout_extension', $options['extensions'], [
'timeout_extension',
$options['extensions'],
[
'using' => [
'id',
'name',
],
'useEmpty' => false,
'class' => 'ui selection dropdown search forwarding-select',
]
]
);
$this->add($extension);

// debug_mode
$checkAr = ['value' => null];
if ($entity->debug_mode) {
$checkAr = ['checked' => 'checked', 'value' => null];
}
$this->add(new Check('debug_mode', $checkAr));
$this->addCheckBox('debug_mode', intval($entity->debug_mode) === 1);

$this->add(new Numeric('last_responsible_time'));
$this->add(new Numeric('last_responsible_duration'));
}

/**
* Adds a checkbox to the form field with the given name.
* Can be deleted if the module depends on MikoPBX later than 2024.3.0
*
* @param string $fieldName The name of the form field.
* @param bool $checked Indicates whether the checkbox is checked by default.
* @param string $checkedValue The value assigned to the checkbox when it is checked.
* @return void
*/
public function addCheckBox(string $fieldName, bool $checked, string $checkedValue = 'on'): void
{
$checkAr = ['value' => null];
if ($checked) {
$checkAr = ['checked' => $checkedValue,'value' => $checkedValue];
}
$this->add(new Check($fieldName, $checkAr));
}
}
}
5 changes: 5 additions & 0 deletions App/Views/index.volt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<label>{{ t._('module_smivr_Library1CType') }}</label>
{{ form.render('library_1c') }}
</div>
{% if moduleCTI5Installed %}
<div class="ui positive message only-five-generation">{{ t._("module_smivr_WeGetSettingsFromCTIClientV5") }}</div>
{% else %}
<div class="ui negative message only-five-generation">{{ t._("module_smivr_LibraryVer5NotInstalled") }}</div>
{% endif %}
{% if moduleCTI2Installed %}
<div class="ui positive message only-second-generation">{{ t._("module_smivr_WeGetSettingsFromCTIClient") }}</div>
{% else %}
Expand Down
90 changes: 55 additions & 35 deletions Lib/AGICallLogic.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class AGICallLogic extends PbxExtensionBase
private string $contextInternal = 'internal';
private string $number;
private array $messages = [];
private int $maxMessagesCount = 100; // Maximum number of messages to store
private int $maxMessageLength = 1024; // Maximum length of each message
private WebService1C $web_service_1C;
private $count_of_repeat_ivr;
private $timeout_extension;
Expand Down Expand Up @@ -271,12 +273,17 @@ private function text2speech($arr_text_to_speech): ?string
'logger' => $this->logger,
];

switch ($ttsSettings->tts_service) {
case 'Yandex':
switch (strtoupper($ttsSettings->tts_service)) {
case 'YANDEX':
{
$tts = new YandexTTS($settings);
break;
}
case 'MIKO':
{
$tts = new MikoTTS($settings);
break;
}
case 'CRT':
{
$tts = new SpeechProTTS($settings);
Expand Down Expand Up @@ -306,9 +313,20 @@ private function text2speech($arr_text_to_speech): ?string
*/
public function Verbose($value): void
{
// Truncate value if it's a string and too long
if (is_string($value) && strlen($value) > $this->maxMessageLength) {
$value = substr($value, 0, $this->maxMessageLength) . '... [truncated]';
}

// Add to messages array, keeping only the most recent ones
$this->messages[] = $value;
if (count($this->messages) > $this->maxMessagesCount) {
array_shift($this->messages);
}

if ($this->agi !== null) {
$this->agi->verbose('SMART IVR VERBOSE: ' . escapeshellarg($value), 3);
$truncated_value = is_string($value) ? $value : json_encode($value);
$this->agi->verbose('SMART IVR VERBOSE: ' . escapeshellarg($truncated_value), 3);
}
}

Expand Down Expand Up @@ -397,42 +415,44 @@ private function getIVRPhrase($phraseId, $extension = null): string
}
case 'ConnectionToExtension':
{
$parameters = [
'models' => [
'Extensions' => Extensions::class,
],
'columns' => [
'username' => 'Users.username',
],
'conditions' => 'Extensions.number = :extension: AND Extensions.is_general_user_number=1',
'bind' => [
'extension' => $extension,
],
'joins' => [
'Users' => [
0 => Users::class,
1 => 'Users.id=Extensions.userid',
2 => 'Users',
3 => 'INNER',
$userName = $this->web_service_1C->getUserInfoV5($extension);
if($userName === null){
$parameters = [
'models' => [
'Extensions' => Extensions::class,
],
],
'limit' => 1,
];
$query = $this->di->get('modelsManager')->createBuilder($parameters)->getQuery();
$extensions = $query->execute();
$extensionRecord = null;
foreach ($extensions as $record) {
$extensionRecord = $record;
break;
}
$abonentName = '';
if ($extensionRecord) {
$abonentName = $extensionRecord->username;
'columns' => [
'username' => 'Users.username',
],
'conditions' => 'Extensions.number = :extension: AND Extensions.is_general_user_number=1',
'bind' => [
'extension' => $extension,
],
'joins' => [
'Users' => [
0 => Users::class,
1 => 'Users.id=Extensions.userid',
2 => 'Users',
3 => 'INNER',
],
],
'limit' => 1,
];
$query = $this->di->get('modelsManager')->createBuilder($parameters)->getQuery();
$extensions = $query->execute();
$extensionRecord = null;
foreach ($extensions as $record) {
$extensionRecord = $record;
break;
}
if ($extensionRecord) {
$userName = $extensionRecord->username;
}
}
if (empty($abonentName)) {
if (empty($userName)) {
$resultText = 'Соединяю с номером ' . $extension;
} else {
$resultText = 'Соединяю с сотрудником ' . $abonentName;
$resultText = 'Соединяю с сотрудником ' . $userName;
}
break;
}
Expand Down
Loading