root/freepbx/trunk/amp_conf/bin/archive_recordings

Revision 2090, 12.4 kB (checked in by qldrob, 7 years ago)

Fix hardcoded executable paths, use /usr/bin/env, as per #759

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!/usr/bin/env php
2 <?php
3
4 define("AMP_CONF", "/etc/amportal.conf");
5 define("PHP_ASMANAGER", "/var/lib/asterisk/bin/php-asmanager.php");
6 define("MONITOR_DIR", "/var/spool/asterisk/monitor");
7
8 function out($text) {
9   echo $text."\n";
10 }
11
12 function outn($text) {
13   echo $text;
14 }
15
16 function error($text) {
17   echo "[ERROR] ".$text."\n";
18 }
19
20 function fatal($text) {
21   echo "[FATAL] ".$text."\n";
22   exit(1);
23 }
24
25 function debug($text) {
26   global $debug;
27  
28   if ($debug) echo "[DEBUG] ".$text."\n";
29 }
30
31 function showHelp() {
32   out("This script will archive all monitor recordings in ".MONITOR_DIR."/.");
33   out("Optional parameters:");
34   out("  --help, -h, -?           Show this help");
35   out("  --debug                  Enable debug output");
36   out("  --dry-run                Don't actually do anything");
37   out("  --mp3            Recursively convert all .WAV to .mp3");
38   out("  --delwav         Use with --mp3 to delete orignal files after converting to .mp3");
39 }
40
41 function parse_amportal_conf($filename) {
42   $file = file($filename);
43   foreach ($file as $line) {
44     if (preg_match("/^\s*([a-zA-Z0-9]+)\s*=\s*(.*)\s*([;#].*)?/",$line,$matches)) {
45       $conf[ $matches[1] ] = $matches[2];
46     }
47   }
48   return $conf;
49 }
50
51 /** creates directory tree recursively
52  */
53 function makeDirs($strPath, $mode = 0770) {
54   return is_dir($strPath) or ( makeDirs(dirname($strPath), $mode) and mkdir($strPath, $mode) );
55 }
56
57
58 /** processes all recordings in MONITOR_DIR
59  */
60 function process_files() {
61   global $dryrun;
62   global $debug;
63  
64   if (is_dir(MONITOR_DIR)) {
65     $dir = opendir(MONITOR_DIR);
66     while ($file = readdir($dir)) {
67       $calltype="";
68       if (($file[0] != ".") && is_file(MONITOR_DIR."/".$file)) {
69         if($debug) {
70             debug("Processing file ".$file);         
71         }
72         if ((strtolower(substr($file,-4)) == ".WAV") || (strtolower(substr($file,-4)) == ".wav") || (strtolower(substr($file,-4)) == ".gsm")) {
73           // check if recording is from a queue, ringgroup or outbound
74           // queue recordings saved like q<queue#>-<date>-<time>-<uniqueid>.wav
75           // ringgroup recordings saved like g<rg#>-<date>-<time>-<uniqueid>.wav
76           // outbound call recordings saved like OUT<exten>-<date>-<time>-<uniqueid>.wav
77           // all other call recordings saved like <date>-<time>-<uniqueid>.wav
78           if(!(strpos($file,"OUT") === false)) {  //outbound
79             $outbound=substr($file,3,(strpos($file,"-")-3));
80             $calltype="out-".$outbound;
81             $uniqueid = substr($file,strrpos($file,"-")+1,-4);
82             $datetime = substr($file,strpos($file,"-")+1,strrpos($file,"-")-strlen($outbound)-4);
83           } else if(strpos($file,"q") === 0) {   //queue
84             $queue=substr($file,1,(strpos($file,"-")-1));
85             $calltype="queue-".$queue;
86             $uniqueid = substr($file,strrpos($file,"-")+1,-4);
87             $datetime = substr($file,strpos($file,"-")+1,strrpos($file,"-")-strlen($queue)-2);
88           } else if(strpos($file,"g") === 0) {   //ringgroup
89             $ringgroup=substr($file,1,(strpos($file,"-")-1));
90             $calltype="ringgroup-".$ringgroup;
91             $uniqueid = substr($file,strrpos($file,"-")+1,-4);
92             $datetime = substr($file,strpos($file,"-")+1,strrpos($file,"-")-strlen($ringgroup)-2);
93           } else {  //direct inbound
94             $calltype="in";
95             $uniqueid = substr($file,strrpos($file,"-")+1,-4);
96             $datetime = substr($file,0,strrpos($file,"-"));
97           }
98           outn("-> Looking for \"".$calltype."\" type CDR for ".$uniqueid.".. ");
99           $cdrRecord = get_cdr($datetime,$uniqueid,$calltype);
100           if(isset($cdrRecord['extension'])) {
101             $calldate = strtok($cdrRecord['calldate']," ");
102             if ($debug) debug("Calldate is ".$calldate);
103             $calltime = strtok(" ");
104             if ($debug) debug("Calltime is ".$calltime);
105             $filepath = MONITOR_DIR."/".str_replace("-","/",$calldate)."/".$cdrRecord['extension']."/".$cdrRecord['direction'];
106             if ($debug) debug("Preparing directory ".$filepath);
107             if(!$dryrun) {
108               makeDirs($filepath);
109             }
110
111             out("Storing recording to ".$filepath);
112             if(!$dryrun) {
113               exec("mv ".MONITOR_DIR."/".$file." ".$filepath."/".$file);
114             }
115           } else {
116             out("Storing recording as an orphan");
117             if(!$dryrun) {
118               makeDirs(MONITOR_DIR."/orphans");
119               exec("mv ".MONITOR_DIR."/".$file." ".MONITOR_DIR."/orphans/");
120             }
121           }
122         } else {
123           error("Don't know what to do with ".$file);
124         }
125       }
126     }
127   } else {
128     fatal(MONITOR_DIR." does not exist!");
129   }
130 }
131
132 function check_table() {
133   global $db;
134   global $debug;
135   outn("Verifying CDR 'uniqueid' field exisits..");
136   $sql = "SELECT uniqueid FROM cdr WHERE NOT uniqueid=\"\"";
137   if ($debug) {out(""); debug("Query: ".$sql);}
138   $result = $db->query($sql);
139   if(DB::IsError($result)) {     
140     fatal($result->getDebugInfo()."\" while running ".$sql."\n");
141   }
142   if (count($result) > 0) {
143     out("OK");
144   } else {
145     out("FAILED");
146     fatal("No unique IDs have been logged in your CDR Table.\n\nIn /usr/src/asterisk-addons:\n1. Add a CFLAGS+=-DMYSQL_LOGUNIQUEID to the top of the Makefile.\n2. Perform the usual make clean, make, make install.\n3. Restart Asterisk");
147   }
148   return($result);
149 }
150
151 // makes "20050502-162120" look like "2005-05-02 16:21:20"
152 function fix_datetime($datetime) {
153   $datetime = str_replace("-"," ",$datetime);
154   $year = substr($datetime,0,4);
155   $month = substr($datetime,4,2);
156   $day = substr($datetime,6,2);
157   $hours = substr($datetime,9,2);
158   $minutes = substr($datetime,11,2);
159   $seconds = substr($datetime,13,2);
160   $allowance = substr(($seconds - 1) + 100,1); //we allow a slight movement in the CDR timestamp for execution of dialparties.agi, etc
161   if($allowance<0) {
162     $allowance="59";
163     $minutes=substr(($minutes-1 - 1) + 100,1);
164   }
165   $datetimes['exact'] = "$year-$month-$day $hours:$minutes:$seconds";
166   $datetimes['allow'] = "$year-$month-$day $hours:$minutes:$allowance";
167   return $datetimes;
168 }
169
170 function get_cdr($datetime,$uniqueid,$calltype) {
171   global $db;
172   global $debug;
173   $datetimes = fix_datetime($datetime);
174   $sql = "SELECT * FROM cdr WHERE uniqueid = '$uniqueid' AND calldate BETWEEN '".$datetimes['allow']."' AND '".$datetimes['exact']."'";
175   if ($debug) {out(""); debug("Query: ".$sql);}
176   $result = $db->getRow($sql);
177   if(DB::IsError($result)) {     
178     fatal($result->getDebugInfo()."\" while running ".$sql."\n");
179   }
180   if (count($result) > 0) {
181     out("Found");
182   } else {
183     out("Not Found");
184   }
185   $cdrRecord['calldate']=$result[0];
186   $cdrRecord['clid']=$result[1];
187   $cdrRecord['src']=$result[2];
188   $cdrRecord['dst']=$result[3];
189   $cdrRecord['dcontext']=$result[4];
190   $cdrRecord['channel']=$result[5];
191   $cdrRecord['dstchannel']=$result[6];
192   $cdrRecord['lastapp']=$result[7];
193   $cdrRecord['lastdata']=$result[8];
194   $cdrRecord['duration']=$result[9];
195   $cdrRecord['billsec']=$result[10];
196   $cdrRecord['disposition']=$result[11];
197   $cdrRecord['amaflags']=$result[12];
198   $cdrRecord['accountcode']=$result[13];
199   $cdrRecord['uniqueid']=$result[14];
200   $cdrRecord['userfield']=$result[15];
201   if (strpos($calltype,"in") === 0) {
202     if($debug) debug("Getting incoming destination from dst: ".$cdrRecord['dst']);
203     $cdrRecord['extension']=$cdrRecord['dst'];
204     $cdrRecord['direction']="in";
205   } else if(strpos($calltype,"out") === 0) {
206     if($debug) debug("Getting outgoing origination from calltype: ".$calltype);
207     $cdrRecord['extension']=ltrim($calltype,"out-");
208     $cdrRecord['direction']="out";
209   } else if (strpos($calltype,"ringgroup") === 0) {
210     if($debug) debug("Getting group destination from dstchannel: ".$cdrRecord['dstchannel']);
211     $cdrRecord['extension']=substr($cdrRecord['dstchannel'],strpos($cdrRecord['dstchannel'],"/")+1,(strpos($cdrRecord['dstchannel'],"-")-strpos($cdrRecord['dstchannel'],"/")-1)); //cut out the channel number
212     outn("Checking if ".$cdrRecord['extension']." has recordings enabled..");
213     $extrecord = check_recording_option($cdrRecord['extension']);
214     $cdrRecord['direction']="in";
215     if ($extrecord == "ENABLED") {
216       out("YES");
217     } else {
218       out("NO");
219       unset($cdrRecord['extension']);
220     }
221   } else if (strpos($calltype,"queue") === 0) {
222     if($debug) debug("Getting queue destination from dst: ".$cdrRecord['dst']);
223     $cdrRecord['extension']=$cdrRecord['dst'];
224     $cdrRecord['direction']="in";
225   }
226   if (empty($cdrRecord['extension'])) {
227     if($debug) debug(".. no owner for ".$uniqueid);
228   } else {
229     if($debug) debug(".. recording owned by ".$cdrRecord['extension']);
230   }
231   return($cdrRecord);
232 }
233
234
235 function check_recording_option($extension) {
236   global $amp_conf;
237   $astman = new AGI_AsteriskManager();
238   if ($res = $astman->connect("127.0.0.1", $amp_conf["AMPMGRUSER"] , $amp_conf["AMPMGRPASS"])) {
239     return $astman->database_get("RECORD-IN",$extension);
240   } else {
241     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
242   }
243 }
244
245
246 // Create list of all files
247 function make_tree($path){
248   $handle=opendir($path);
249   while($a=readdir($handle)){
250     if(!preg_match('/^\./',$a)){
251       $full_path="$path/$a";
252       if(is_file($full_path)){ $list[]=$full_path; } // only files //$list[]=$full_path;
253         if(is_dir($full_path)){
254           $recursive=make_tree($full_path);
255           for($n=0; $n<count($recursive); $n++){
256             $list[]=$recursive[$n];
257           }
258         }
259       }
260   }
261   closedir($handle);
262   return $list;
263 }
264
265 function convert_files() {
266   global $debug;
267   global $dryrun;
268   global $delwav;
269   outn("-> Converting files to mp3..");
270   $files = make_tree(MONITOR_DIR);
271   foreach ($files as $file) {
272     if ((substr($file,-4) == ".WAV")) {
273       $newfile = substr($file,0,strlen($file)-3)."mp3";
274       $lamecmd="lame --cbr -m m -t -F \"".$file."\" \"".$newfile."\""; //this doesn't work
275       if($debug) debug($lamecmd);
276       if (!$dryrun) {
277         exec($lamecmd);
278         if($delwav) {
279           exec("rm -f ".$file);
280         }
281       }
282     }
283   }
284   out("OK");
285 }
286 /********************************************************************************************************************/
287
288 // **** Make sure we have STDIN etc
289
290 // from  ben-php dot net at efros dot com   at  php.net/install.unix.commandline
291 if (version_compare(phpversion(),'4.3.0','<') || !defined("STDIN")) {
292   define('STDIN',fopen("php://stdin","r"));
293   define('STDOUT',fopen("php://stdout","r"));
294   define('STDERR',fopen("php://stderr","r"));
295   register_shutdown_function( create_function( '' , 'fclose(STDIN); fclose(STDOUT); fclose(STDERR); return true;' ) );
296 }
297    
298    
299 // **** Make sure we have PEAR's DB.php, and include it
300
301 outn("Checking for PEAR DB..");
302 if (! @ include('DB.php')) {
303   out("FAILED");
304   fatal("PEAR must be installed (requires DB.php). Include path: ".ini_get("include_path"));
305 }
306 out("OK");
307
308
309 // **** Make sure we have PEAR's GetOpts.php, and include it
310
311 outn("Checking for PEAR Console::Getopt..");
312 if (! @ include("Console/Getopt.php")) {
313   out("FAILED");
314   fatal("PEAR must be installed (requires Console/Getopt.php). Include path: ".ini_get("include_path"));
315 }
316 out("OK");
317
318 // **** Make sure we have php-asmanager.php, and include it
319
320 outn("Checking for PHP_ASMANAGER..");
321 if (! @ include(PHP_ASMANAGER)) {
322   out("FAILED");
323   fatal("Cannot include ".PHP_ASMANAGER);
324 }
325 out("OK");
326
327 // **** Parse out command-line options
328
329 $shortopts = "h?u:p:";
330 $longopts = array("help","debug","dry-run","mp3");
331
332 $args = Console_Getopt::getopt(Console_Getopt::readPHPArgv(), $shortopts, $longopts);
333 if (is_object($args)) {
334   // assume it's PEAR_ERROR
335   out($args->message);
336   exit(255);
337 }
338
339 $debug = false;
340 $dryrun = false;
341 $mp3= false;
342
343 foreach ($args[0] as $arg) {
344   switch ($arg[0]) {
345     case "--help": case "h": case "?":
346       showHelp();
347       exit(10);
348     break;
349     case "--dry-run":
350       out("Dry-run only, nothing will be changed");
351       $dryrun = true;
352     break;
353     case "--debug":
354       $debug = true;
355       debug("Debug mode enabled");
356     break;
357     case "--mp3":
358       $mp3 = true;
359       debug("MP3 conversion enabled");
360     break;
361     case "--delwav":
362       $delwav = true;
363       debug("Will delete wav after converting to mp3");
364     break;
365   }
366 }
367
368
369 // **** Look for user = root
370
371 outn("Checking user..");
372 $current_user=(isset($_ENV["USER"]) ? $_ENV["USER"] : exec('whoami',$output));
373 if ($current_user != "root"){
374   out("FAILED");
375   fatal($argv[0]." must be run as root");
376 }
377 out("OK");
378
379
380 // **** read amportal.conf
381
382 outn("Reading ".AMP_CONF."..");
383 $amp_conf = parse_amportal_conf(AMP_CONF);
384 if (count($amp_conf) == 0) {
385   fatal("FAILED");
386 }
387 out("OK");
388
389
390 // **** Connect to database
391
392 outn("Connecting to database..");
393
394 $db_user = $amp_conf["AMPDBUSER"];
395 $db_pass = $amp_conf["AMPDBPASS"];
396 $db_host = 'localhost';
397 $db_name = 'asteriskcdrdb';
398 $db_engine = 'mysql';
399
400 $datasource = $db_engine.'://'.$db_user.':'.$db_pass.'@'.$db_host.'/'.$db_name;
401
402 $db = DB::connect($datasource); // attempt connection
403
404 if(DB::isError($db)) {
405   out("FAILED");
406   debug($db->userinfo);
407   fatal("Cannot connect to database");
408  
409 }
410 out("OK");
411
412 check_table();
413 process_files();
414 if($mp3) {
415   convert_files();
416 }
Note: See TracBrowser for help on using the browser.