HomeLabContactFor HireCodeArticles/Blog /0/0 52.201.244.140
< >

Asterisk Call Hunting with Subscription

2018-03-28 by: meuon
#!/usr/bin/php
<? php

#HUNTRESS.PHP
#mikes very simple public sharable version of a call/extension hunt manager. 
#actually knows what extensions are avalable or not, randomly selects an available phone. 
#inspired by https://www.voip-info.org/wiki/view/Asterisk+Hunting+Groups+for+incoming+calls
#but works with PHP 7 and Asterisk 13+ using good AGI 
#contact me at geeklabs.com or ring-u.com if you have questions. 
#---------------
#commands for testing
#huntress.php 400-101-add  #adds extension 101 to pack 400
#huntress.php 400-101-del  #remove extension 101 to pack 400
#huntress.php 400--get  #gets an available extension for pack 400
# sets an asterisk variable called CDR(hunter) in the channel that calls this script 
#In extensions.conf:
#---------------
#exten => 408,1,answer
# same => n,agi(huntress.php,400-${CALLERID(num)}-add) 
# same => n,Background(added)
# same => n,hangup
#exten => 409,1,answer
# same => n,agi(huntress.php,400-${CALLERID(num)}-del) 
# same => n,Background(removed)
# same => n,SayDigits(400)
# same => n,hangup
#exten => 400,1,answer
# same => n,agi(huntress.php,400-${CALLERID(num)}-get) 
# same => n,Goto(Dial-Users,${CDR(hunter)},1)
# same => n,hangup
#-----------------
#If the above is in [Features] it gets called (from an IVR or Receptionist) like:
# same = n,Goto(Features,400,1)
#-----------------
#note you must have AMI running, configure the login,password and port below. 
#it is possible to do some call balancing and other things, but this works suprisingly well just using random selection

require("/var/lib/asterisk/agi-bin/phpagi.php"); #commonly available somewhere.. 
$agi = new AGI();
$input = $argv[1] ; 
list($pack,$extension,$action,$data) = preg_split("/-/",$input) ;   

#####uncomment for debug log:
#$fileout = fopen("/tmp/huntress.log", "a");
#fputs($fileout, "INPUT: $input
 Pack: $pack Extension: $extension Action: $action Data: $data
");
#fclose($fileout);

if($action == 'add' and $pack > 1) { 
  $string = file_get_contents("/tmp/pack.$pack");
  if(empty($string)) { 
    $p = array() ; 
    $string = json_encode($p) ; 
  } ; 
    $p=json_decode($string) ; 
    array_push($p, $extension);
    $string = json_encode($p); 
    $packfile = fopen("/tmp/pack.$pack", "w");
    fputs($packfile, "$string");
    fclose($packfile);
} ; 
if($action == 'del' and $pack > 1) { 
  $pp = array() ; 
  $string = file_get_contents("/tmp/pack.$pack");
  if(empty($string)) { 
    $p = array() ; 
    $string = json_encode($p) ; 
  } ; 
    $p=json_decode($string) ; 
    foreach($p as $z) { #this is crude, because unset is b0rken for objects. 
      if($z == $extension) { } else { array_push($pp,$z) ; } ; 
    } ; 
    $string = json_encode($pp); 
    $packfile = fopen("/tmp/pack.$pack", "w");
    fputs($packfile, "$string");
    fclose($packfile);
} ; 

if($action == 'get' and $pack > 1) {             
#gets next available caller, 
  $string = file_get_contents("/tmp/pack.$pack");
  if(empty($string)) { 
    $p = array() ; 
    $string = json_encode($p) ; 
#    print "No-one available: 100
" ; 
#    using extension 100 as a catch-all, 
    $agi->set_variable("CDR(hunter)", '100');
    return ; 
  } ; 
   $p=json_decode($string) ; 
   $timeout = 90 ; 
   $return = '' ; 
   $socket = fsockopen("127.0.0.1","5011", $errno, $errstr, $timeout);
   if($errno == '0') {
   fputs($socket, "Action: Login
");
   fputs($socket, "UserName: YOURLOGINHERE
");
   fputs($socket, "Secret: YOURSECRETPASSWORDHERE

");
   fputs($socket, "Action: PJSIPShowEndpoints

");
   fputs($socket, "Action: Logoff

");
     while (!feof($socket)) {
       $return .= fread($socket, 8192);
     }
   fclose($socket);
   } else { 
    $return = "AMI Error: $errno $errstr" ; 
   } ; 
#--------------------I used this block for multiple things, and cut and pasted it here to get $available. Overkill, but works.
$array = preg_split ('/$R?^/m', $return);
$l = 0 ; 
$u = 0 ; 
$i = 0 ; 
$c = 0 ; 
foreach($array as $a) { 
    #build 3 arrays; local and upstream and available you may have to change some things. 
    $strip = array('/ /','/s+/', '/$/', '/
/', '/
/', '/
/', '/,/', '/;/','/@/','/\%/','/0x/');
    $a = preg_replace($strip, '', $a);
    if(strlen($a) > 2) {
        #print "$key = $val
" ; list($key,$val) = preg_split ('/:/', $a); $temp[$key] = $val ; } else { if($temp['ObjectType'] == 'endpoint' and empty($temp['OutboundAuths']) ) { #local? if($temp['DeviceState'] == 'Notinuse') { $available[$i] = $temp['ObjectName'] ; } ; $local[$l] = $temp ; $l++; } elseif ($temp['ObjectType'] == 'endpoint' and !empty($temp['OutboundAuths'])) { $upstream[$u] = $temp ; $u++ ; } elseif ($temp['Event'] == 'CoreShowChannel') { $channel[$c] = $temp ; $c++ ; } else { } ; $i++ ; unset($temp) ; } ; } ; $avail = array_intersect($p, $available); $selected = array_rand ($avail,1) ; $extension = $avail[$selected] ; if(empty($extension)) { # print "None Available:--------- 100 " ; $agi->set_variable("CDR(hunter)", $extension); } else { # print "Send to: $extension " ; $agi->set_variable("CDR(hunter)", $extension); } ; ###uncomment for debugging #$fileout = fopen("/tmp/huntress.log", "a"); #fputs($fileout, "Chosen EXTEN: $extension "); #fclose($fileout); } ; ?>