FreePBX: Biz abonentni u allaqachon gaplashgan operatorga qaytaramiz.

Odatdagi qo’ng’iroqlar markazidagi vaziyat: Abonent kompaniyaga qo’ng’iroq qiladi; operator javob beradi; qo’ng’iroq biron sababga ko’ra uzilib qoladi (ehtimol, abonent biror narsa qilishi va keyin qayta qo’ng’iroq qilishi kerak) va voy! Abonent qayta qo’ng’iroq qiladi va butunlay boshqa operatorga ulanadi, unga hamma narsani qayta tushuntirish kerak bo’ladi. Abonent qayta qo’ng’iroq qilgandan keyin har doim bir xil operatorni olishini ta’minlash odatiy vazifa bo’lib tuyuladi. Lekin nega bu muammoga yechim ombor paketida yoki hatto pullik modullarda ham yo’q?

«Yo’q, mayli!» deb o’yladim va bu kamchilikni qoplash uchun o’ziga xos protez yasashga qaror qildim.
Menga qarshi chiqishingiz mumkin, lekin men sevimli PHP-imda qolaman. Ayniqsa, u har doim FreePBX serverida mavjud bo’lgani uchun! Aytgancha, men internetda deyarli tayyor yechim topdim, lekin uning qanday ishlashi haqida hech narsa tushunmadim va undan foydalana olmadim. :)) Menimcha, ushbu maqola shunga o’xshash tuzoqlarga tushib qolganlar uchun foydali bo’ladi.

Biz qilishimiz kerak bo’lgan birinchi narsa — Asteriskning AGI skriptlari joylashgan katalogni topish. Bu /var/lib/asterisk/agi-bin/ yoki mening uy serverimdagi kabi /usr/share/asterisk/agi-bin/ bo’lishi mumkin. Asosan, siz agi-bin ni qidirishingiz kerak. Ushbu papkada skript yarating, masalan , mymanager.php va unga quyidagi tarkibni joylashtiring:

 <pre class="wp-block-syntaxhighlighter-code">#!/usr/bin/php -q
<?php
$prio = true; // Приоритет исходящих от операторов звонков (true|false)
$interval = 24; // Период, после которого фиксация абонента за определённым менеджером будет снята (в часах)
$timeout = 15; // Сколько секунд абоненту ждать ответа оператора?
$queue = 199; // Номер очереди, куда нужно вернуть абонента, если звонок на его оператора не удался.

// Подготавливаем PDO и подключаемся к базе
	$user = 'freepbxuser';
	$pass = 'Пароль юзера базы'; // Настройки базы обычно лежат в /etc/freepbx.conf. Копируем их оттуда.
	
	$dsn = "mysql:host=localhost;dbname=asteriskcdrdb;charset=utf8";
	$opt = [
		PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
		PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
		PDO::ATTR_EMULATE_PREPARES   => false,
	];
	try {$pdo = new PDO($dsn, $user, $pass, $opt);} catch (PDOException $e) { die('DB connection failed: ' . $e->getMessage());}

require('phpagi.php'); // Цепляем класс работы с AGI. Он есть в папке agi-bin "из коробки"
$agi = new AGI();
$cid = $agi->request['agi_callerid'];
		
if(strlen($cid) > 8){ // на всякий случай, проверяем, что за звонок к нам прилетел. Внешние, по идее, не могут быть короче 9 символов.
	 $cid = $agi->request['agi_callerid']; // забираем CID звонящего
	 // Ищем в базе CDR, не звонил ли нам этот номер ранее, но не позднее указанного в настройках интервала. Нас интересуют состоявшиеся звонки, длительностью не короче 5 секунд (можно увеличить).
	 $stmt = $pdo->prepare('select dst from cdr where calldate > now() - interval ? hour and cnum = ? and disposition="ANSWERED" and duration > 5 and lastapp = "Dial" and dcontext = "ext-local" order by `calldate` desc limit 1');
	 $stmt->execute(Array($interval,$cid));
	 if($row = $stmt->fetch()){
		$operator = $row['dst'];
	 } else {
		 $prio = true;
	 }
	 // А теперь проверяем, не звонил ли сам оператор на этот номер? В настройке выше можно включить или выключить приоритет полученных из исходящих звонков данных
	 if($prio == true){
		 $stmt = $pdo->prepare('select cnum from cdr where calldate > now() - interval ? hour and dst = ?  and lastapp = "Dial" order by `calldate` desc limit 1;');
		 $stmt->execute(Array($interval,$cid));
		 if($row = $stmt->fetch()){
			if($row['cnum'] > 0){
				$operator = $row['cnum'];
			}
		 }
	 }
	// Если мы получили номер какого-либо оператора - пытаемся его вызвать.
	 if($operator > 0){
		$agi->exec('Dial',"Local/".$operator."@from-internal,".$timeout.",g");
	 }
	 // Если ничего не получилось, или если оператор сам сбросил звонок, либо по заранее указанному таймауту, передаём звонок в заранее указанную очередь к другим операторам. 
	 $dialstatus = $agi->get_variable('DIALSTATUS');
	if ( $dialstatus != 'ANSWERED' ) {
	   $agi->exec('Goto',"ext-queues,".$queue.",1");
	}
} 
// Говорим астериску, что всё норм и скрипт выполнился без ошибок.
exit(0);
?>
</pre> 

Biz bu skriptni yulduzcha bilan belgilangan foydalanuvchi va o’qish va bajarish huquqlariga ega guruhga uzatamiz. Endi uni PBXga ulashimiz kerak.

Agar sizda «Misc Destinations» moduli o’rnatilmagan bo’lsa, uni Module Admin bo’limiga o’rnating.

Ilovalar > Turli manzillar bo’limiga o’ting va yangi manzil qo’shing. Ismga xohlagan narsangizni kiriting va «Telefon raqami » maydoniga keyinroq kontekstda ishlatiladigan bepul manzil raqamini kiriting. Aytaylik, men 96 dan foydalanaman.

Endi biz /etc/asterisk/extensions_custom.conf faylini ochishimiz va u yerga quyidagilarni qo’shishimiz kerak:

 [from-internal]
exten => 96,1,Noop(Running miscapp 1: mymanager)
exten => 96,n,AGI(mymanager.php, ${CALLERID(number)})
exten => 96,n,Hangup() 

Saqlang, «Konfiguratsiyani qo’llash» tugmasini kuting, sinab ko’ring va administratorga bir shisha pivo bilan qovuring. ;)