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); } ; ?>