Mon, 17 Sep 2012 19:10:10 +0200
Update to new version of vendor software although Oracle fails to deliver.
More specifically, newer db(3) patch revisions exist but Oracle has
removed them from the canonical download server URI for Berkely DB.
1 #! @l_prefix@/bin/perl
2 #
3 # wakeup.agi 1.1
4 #
5 # A wakeup agi script for Asterisk
6 #
7 # Copyright (C) 2007
8 #
9 # Jonas Arndt <jonas_arndt@comcast.net>
10 #
11 # This program is free software, distributed under the terms of the
12 # GNU General Public License v2.
13 #
14 #
15 # This program is free software: you can redistribute it and/or modify
16 # it under the terms of the GNU General Public License as published by
17 # the Free Software Foundation, either version 3 of the License, or
18 # (at your option) any later version.
19 #
20 # This program is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 # GNU General Public License for more details.
24 #
25 # You should have received a copy of the GNU General Public License
26 # along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #
29 use strict;
30 use Time::Local;
31 $|=1;
32 # Setup some variables
33 my %AGI; my $DEBUG=0;
34 # Some constants
35 my $OUTDIR="@l_prefix@/var/asterisk/spool/outgoing";
36 my $WAKEDIR="@l_prefix@/var/asterisk/spool/tmp";
37 my $debugfile="@l_prefix@/var/asterisk/spool/tmp/wakeup.log";
38 my $DEBUGOUT = "filehandle";
39 my $CALL = "filehandle";
40 my $TOUCH = "/usr/bin/touch";
42 ############ check_result ##########
43 # Use this to check the result of #
44 # a sent command #
45 # I pretty much stole this from #
46 # the regular agi-test.agi #
47 ####################################
48 sub checkresult {
49 my ($res) = @_;
50 my $retval;
51 chomp $res;
52 if ($res =~ /^200/) {
53 $res =~ /result=(-?\d+)/;
54 if (!length($1)) {
55 print DEBUGOUT "FAIL ($res)\n";
56 exit(1);
57 } elsif ($DEBUG=1) {
58 print DEBUGOUT "PASS ($1)\n";
59 }
60 } else {
61 print STDERR "FAIL (unexpected result '$res')\n";
62 exit(1);
63 }
64 }
66 ############ send_file ####
67 # Use this to send a wave #
68 # file on the channel #
69 ###########################
70 sub send_file {
71 my ($myfile) = @_;
72 chomp($myfile);
73 if ($DEBUG == 1 ) {
74 print DEBUGOUT "Sending stream $myfile \n";
75 }
76 print "STREAM FILE $myfile \"0123456789\"\n";
77 my $result = <STDIN>;
78 &checkresult($result);
79 $result =~ /result=(-?\d+)/;
80 return $1;
81 }
83 ############ hangup ###############
84 # Use this to hang up a channel #
85 ####################################
86 sub hangup {
87 if ($DEBUG == 1 ) {
88 print DEBUGOUT "Hanging up \n";
89 }
90 print "HANGUP \"\" \n";
91 my $result = <STDIN>;
92 &checkresult($result);
93 }
95 ############ say_number ############
96 # Use this to say a number #
97 # over the channel #
98 # #
99 ####################################
100 sub say_number {
101 my ($mynumber) = @_;
102 chomp($mynumber);
103 if ($DEBUG == 1 ) {
104 print DEBUGOUT "Saying number $mynumber \n";
105 }
106 print "SAY NUMBER $mynumber \"0123456789\"\n";
107 my $result = <STDIN>;
108 &checkresult($result);
109 $result =~ /result=(-?\d+)/;
110 return $1;
111 }
113 ############ say_digits ###################
114 # Use this to say digits over the channel #
115 ###########################################
116 sub say_digits {
117 my ($mynumber) = @_;
118 chomp($mynumber);
119 if ($DEBUG == 1 ) {
120 print DEBUGOUT "Saying digits $mynumber \n";
121 }
122 print "SAY DIGITS $mynumber \"0123456789\"\n";
123 my $result = <STDIN>;
124 &checkresult($result);
125 }
127 ######## get_choice ############
128 # Use this to receive a DTMF #
129 # choice from the channel #
130 ################################
131 sub get_choice {
132 if ($DEBUG == 1 ) {
133 print DEBUGOUT "Getting choice \n";
134 }
135 print "WAIT FOR DIGIT 15000\n";
136 my $result = <STDIN>;
137 &checkresult($result);
138 $result =~ /result=(-?\d+)/;
139 return $1;
140 }
142 ###### answer ######
143 # Anser the channel #
144 #####################
145 sub answer {
146 if ($DEBUG == 1 ) {
147 print DEBUGOUT "Answering the channel \n";
148 }
149 print "ANSWER\n";
150 my $result = <STDIN>;
151 &checkresult($result);
152 $result =~ /result=(-?\d+)/;
153 return $1;
154 }
156 ######## get_data ##################
157 # Feed with (file, maxnumbers) #
158 # where file is the sound file #
159 # to be played and maxnumbers is #
160 # the maximum amount of digits to #
161 # allow in the answer #
162 ####################################
163 sub get_data {
164 my @mydata = @_;
165 my $myfile = $mydata[0];
166 my $mymax = $mydata[1];
167 if ($DEBUG == 1 ) {
168 print DEBUGOUT "Getting data \n";
169 }
170 print "GET DATA $myfile 15000 $mymax \n";
171 my $result = <STDIN>;
172 &checkresult($result);
173 $result =~ /result=(-?\d+)/;
174 return $1;
175 }
177 ###### check_outstanding_calls #####
178 # Are there any outstanding wakeup #
179 # calls for this extensions? #
180 # Pass the extension to the #
181 # function. The function returns #
182 # a list of files #
183 ####################################
184 sub check_outstanding_calls {
185 my $myext = @_;
186 #opendir DIR, $WAKEDIR;
187 opendir DIR, $OUTDIR;
188 my @files = grep {/$myext/} readdir(DIR);
189 closedir DIR;
190 return @files;
191 }
193 ######## get_extension #############
194 # Receive the AIG variable and #
195 # return the extension #
196 ####################################
197 sub get_extension {
198 my (@aig) = @_;
199 if ($aig[11] == '') {
200 print STDERR "No extension found in function get_exension \n";
201 return "FAIL";
202 }
203 my $myext = $aig[11];
204 return $myext;
205 }
207 ######## get_context ###############
208 # Receive the AIG variable and #
209 # return the context #
210 ####################################
211 sub get_context {
212 my (@aig) = @_;
213 if ($aig[8] == '') {
214 print STDERR "No extension found in function get_exension \n";
215 return "FAIL";
216 }
217 my $mycont = $aig[8];
218 return $mycont;
219 }
221 ########### get_clid ###############
222 # Receive the AIG variable and #
223 # return the clid #
224 ####################################
225 sub get_clid {
226 my (@aig) = @_;
227 if ($aig[1] == '') {
228 print STDERR "No clid found in function get_clid \n";
229 return "FAIL";
230 }
231 my $myext = $aig[1];
232 return $myext;
233 }
235 ############### init_agi ##################
236 # Use this to initialize the AGI variable #
237 ###########################################
238 sub init_agi {
239 while(<STDIN>) {
240 chomp;
241 last unless length($_);
242 if (/^agi_(\w+)\:\s+(.*)$/) {
243 $AGI{$1} = $2;
244 }
245 }
246 }
248 ######### ascii2num ##########
249 # Removes 48 to get a number #
250 # out of the asciss return #
251 ##############################
252 sub ascii2num {
253 my ($asc) = @_;
254 my $ret;
255 $ret = $asc - 48;
256 return $ret;
257 }
259 ############# Welcome ##############
260 # This is the welcome menu #
261 ####################################
262 sub welcome {
263 my $ret = 0;
264 $ret = &send_file("welcome");
265 if ($ret == 0) {
266 $ret = &send_file("for-wakeup-call");
267 }
268 if ($ret == 0) {
269 $ret = &send_file("press-1");
270 }
271 if ($ret == 0) {
272 $ret = &send_file("for-a-list-of");
273 }
274 if ($ret == 0) {
275 $ret = &send_file("or");
276 }
277 if ($ret == 0) {
278 $ret = &send_file("to-cancel-wakeup");
279 }
280 if ($ret != 0) {
281 $ret = &ascii2num($ret);
282 }
283 if ($ret == 0) {
284 $ret = &get_data("press-2",1);
285 }
286 if ($ret == 1) {
287 $ret = &schedule_new();
288 } elsif ($ret == 2) {
289 &manage_calls();
290 } else {
291 $ret = &send_file("goodbye");
292 }
293 }
295 ######### manage_calls #############
296 # This is what is called if you #
297 # want to manage already scheduled #
298 # wakeup calls #
299 ####################################
300 sub manage_calls {
301 my $checker = "false";
302 my @calls;
303 my $del;
304 #my $ret;
305 my $hours;
306 my $minutes;
307 # Send out a welcome message and ask for return
308 @calls = &check_outstanding_calls($AGI{callerid});
309 if ($#calls + 1 == 0) {
310 $del = &send_file("not-rqsted-wakeup");
311 $del = &send_file("goodbye");
312 } else {
313 foreach (@calls) {
314 $del = 0;
315 my $wakefile = $_;
316 my @wakeup = split /\./, $_;
317 my $time = $wakeup[0];
318 $_ = $time;
319 /(^[0-9][0-9])/;
320 my $hours = $1;
321 /^[0-9][0-9]([0-9][0-9])/;
322 my $minutes = $1;
323 $del = &send_file("rqsted-wakeup-for");
324 if ($del == 0) {
325 $del = &say_number($hours);
326 }
327 if ($del == 0) {
328 if ($minutes >= 10 ) {
329 $del = &say_number($minutes);
330 } elsif ($minutes > 0 && $minutes < 10) {
331 $del = &send_file("digits/oh");
332 $del = &say_number($minutes);
333 }
334 }
335 if ($del == 0) {
336 $del = &send_file("digits/oclock");
337 }
338 if ($del == 0) {
339 $del = &send_file("to-cancel-wakeup");
340 }
341 if ($del == 0) {
342 $del = &send_file("press-1");
343 }
344 if ($del == 0) {
345 $del = &send_file("otherwise-press");
346 }
347 if ($del != 0) {
348 $del = &ascii2num($del);
349 }
350 if ($del == 0) {
351 $del = &get_data("digits/2",1);
352 }
353 if ($del == 1) {
354 my @sysargs = ("rm", "-f", "$WAKEDIR/$wakefile", "$OUTDIR/$wakefile");
355 system(@sysargs) == 0
356 or die "system @sysargs failed: $?";
357 $del = &send_file("cancelled");
358 }
359 }
360 $del = &send_file("goodbye");
361 }
362 }
364 ######## schedule_new ##########
365 # This is the menu to schedule #
366 # a new wakeup call #
367 ################################
368 sub schedule_new {
369 my $checker = "false";
370 my $ret_var;
371 my $ret_dummy = 0;
372 my $time;
373 my $perm;
374 my $file;
375 my $calltype;
376 my $extension;
377 my $context;
378 my $hours;
379 my $minutes;
380 if ($DEBUG == 1 ) {
381 print DEBUGOUT "From schedule_new\n";
382 }
383 while ( $checker eq "false" ) {
384 $ret_var = &send_file("to-rqst-wakeup-call");
385 if ($ret_var != 0) {
386 my $tmp = &get_data("silence/1",3);
387 $ret_var = &ascii2num($ret_var);
388 $ret_var = $ret_var . $tmp;
389 } else {
390 $ret_var = &get_data("enter-a-time",4);
391 }
392 # if ($ret_var < 1300 && $ret_var >= 0100) {
393 # my $pm = &get_data("1-for-am-2-for-pm",1);
394 # if ($pm == 2 && $ret_var <= 1159) {
395 # $ret_var = $ret_var + 1200;
396 # $checker = "true";
397 # } elsif ($pm == 1 && $ret_var > 1159) {
398 # $ret_var = $ret_var - 1200;
399 # # Fix the zero
400 # $ret_var = "00" . $ret_var;
401 # $checker = "true";
402 # } else {
403 # $checker = "true";
404 # }
405 # } elsif ($ret_var > 2359) {
406 # $ret_dummy = &send_file("please-try-again");
407 # } else {
408 # $checker = "true";
409 # }
410 if ($ret_var > 2359) {
411 $ret_dummy = &send_file("please-try-again");
412 } else {
413 $checker = "true";
414 }
415 }
416 $perm = 0;
417 $perm = &send_file("wakeup-for-one-time");
418 if ($perm == 0) {
419 $perm = &send_file("press-1");
420 }
421 if ($perm == 0) {
422 $perm = &send_file("for-a-daily-wakeup-call");
423 }
424 if ($perm != 0) {
425 $perm = &ascii2num($perm);
426 }
427 if ($perm == 0) {
428 $perm = $perm = &get_data("press-2",1);
429 }
430 # Open the file and populate it with data
431 $extension = $AGI{callerid};
432 $context = $AGI{context};
433 if ($perm == 2) {
434 $file = "$WAKEDIR/$ret_var.perm.1.$extension.call";
435 $calltype = "perm";
436 open (CALL, '>', $file) or die "Cannot open call file for write :$!";
437 } else {
438 $file = "$WAKEDIR/$ret_var.temp.1.$extension.call";
439 $calltype = "temp";
440 open (CALL, '>', $file) or die "Cannot open call file for write :$!";
441 }
442 my $myprint = "channel: Local" . "/" . $extension . "@" . $context . "\n";
443 print CALL $myprint;
444 print CALL "maxretries: 3\n";
445 print CALL "retrytime: 60\n";
446 print CALL "waittime: 60\n";
447 print CALL "callerid: \"AsterPBX Weckruf\" <$AGI{extension}>\n";
448 print CALL "application: AGI\n";
449 print CALL "data: wakeup|$ret_var.$calltype.1.$extension.call\n";
450 close ($CALL);
451 # Now touch the file
452 # Get the time variable
453 $time = get_time_string($ret_var);
454 my @command = ("$TOUCH", "-t", "$time", "${file}");
455 system(@command) == 0
456 or die "system @command failed: $?";
457 # Move it to the OUT directory
458 my @command = ("mv", "${file}", "${OUTDIR}/");
459 system(@command) == 0
460 or die "system @command failed: $?";
462 # Stream out the wakeup
463 $_ = $ret_var;
464 /(^[0-9][0-9])/;
465 my $hours = $1;
466 /^[0-9][0-9]([0-9][0-9])/;
467 my $minutes = $1;
468 $ret_dummy = &send_file("rqsted-wakeup-for");
469 $ret_dummy = &say_number($hours);
470 if ($minutes >= 10 ) {
471 &say_number($minutes);
472 } elsif ($minutes > 0 && $minutes < 10) {
473 &send_file("digits/oh");
474 &say_number($minutes);
475 }
476 $ret_dummy = &send_file("digits/oclock");
477 $ret_dummy = &send_file("goodbye");
478 return $ret_var;
479 }
481 ######## get_time_string ###########
482 # This will return the time string #
483 # when inputing a string like hhmi #
484 ####################################
485 sub get_time_string {
486 my ($intime) = @_;
487 my $minutes = substr($intime, 2, 4);
488 my $hours = substr($intime, 0, 2);
489 my $tmpepoch;
490 my $day;
491 my $month;
492 my $ret_val;
493 my $epoch = time();
494 my @timedata = localtime($epoch);
495 # Insert the minutes and hours from input
496 $timedata[1] = $minutes;
497 $timedata[2] = $hours;
498 # Get tmpepoch
499 $tmpepoch = timelocal(@timedata);
500 #Now compare them
501 if ($tmpepoch < $epoch) { # Means it is tomorrow
502 $tmpepoch += 86400; # Add 24 hours
503 }
504 # Now get the new timedata
505 my @timedata = localtime($tmpepoch);
506 $minutes = $timedata[1];
507 $hours = $timedata[2];
508 $day = $timedata[3];
509 $month = $timedata[4] + 1;
510 #Correct the "First hour after midnight" problem
511 if ($minutes < 10) {
512 $minutes = "0" . $minutes;
513 }
514 if ($hours < 10) {
515 $hours = "0" . $hours;
516 }
517 if ($day < 10) {
518 $day = "0" . $day;
519 }
520 if ($month < 10) {
521 $month = "0" . $month;
522 }
523 $ret_val = $month . $day . $hours . $minutes;
524 return $ret_val;
525 }
527 ############ new_time ################
528 # This will return the time string #
529 # with a time set 10 minute into #
530 # the future. The string is MMDDhhmi #
531 ######################################
532 sub new_time {
533 my ($input) = @_;
534 my @timedata;
535 my $minutes;
536 my $hours;
537 my $day;
538 my $month;
539 my $ret_val;
540 my $epoc = time();
541 if ($input eq "10m") {
542 # add 10 minutes
543 $epoc += 600;
544 #$epoc += 120; #just for debugs
545 } else {
546 # add 24 hours
547 $epoc += 86400;
548 }
549 @timedata = localtime($epoc);
550 $minutes = $timedata[1];
551 $hours = $timedata[2];
552 $day = $timedata[3];
553 $month = $timedata[4] + 1;
554 #Correct the "First hour after midnight" problem
555 if ($minutes < 10) {
556 $minutes = "0" . $minutes;
557 }
558 if ($hours < 10) {
559 $hours = "0" . $hours;
560 }
561 if ($day < 10) {
562 $day = "0" . $day;
563 }
564 if ($month < 10) {
565 $month = "0" . $month;
566 }
567 $ret_val = $month . $day . $hours . $minutes;
568 return $ret_val;
569 }
571 ########### snooze ##########
572 # This is the menu to snooze #
573 # the wakeup call #
574 ##############################
575 sub snooze {
576 my ($oldfile) = @_;
577 my $newfile;
578 my $extension;
579 my $context;
580 my @filestore = split (/\./, $oldfile);
581 my @permstore = split (/\./, $oldfile);
582 my $time;
583 my $ret_var = 0;
584 my $ret_dummy;
585 my $myprint;
586 # Answer the channel
587 &answer();
588 # Is this a reoccuring call, then add 24h
589 if ($permstore[1] eq "perm") {
590 $permstore[2] += 1; #Just to get a new file name
591 $newfile = join(".",@permstore);
592 $extension = $AGI{extension};
593 $context = $AGI{context};
594 # Open the file
595 open (CALL, '>', "${WAKEDIR}/${newfile}") or die "Cannot open call file for write :$!";
596 $myprint = "channel: Local" . "/" . $extension . "@" . $context . "\n";
597 print CALL $myprint;
598 print CALL "maxretries: 3\n";
599 print CALL "retrytime: 60\n";
600 print CALL "waittime: 60\n";
601 print CALL "callerid: \"AsterPBX Weckruf\" <$AGI{callerid}>\n";
602 print CALL "application: AGI\n";
603 print CALL "data: wakeup|$newfile\n";
604 close ($CALL);
605 # Get a time 24h from now
606 $time = &new_time("24h");
607 # Touch the file with the new time
608 my @command = ("$TOUCH", "-t", "$time", "${WAKEDIR}/${newfile}");
609 system(@command) == 0
610 or die "system @command failed: $?";
611 # Now move it
612 my @command = ("mv", "${WAKEDIR}/${newfile}", "${OUTDIR}/${newfile}");
613 system(@command) == 0
614 or die "system @command failed: $?";
615 }
616 #Replace the file name time with snooze
617 $filestore[1] = "snooze";
618 # Also add 10 minutes to the name
619 $time = new_time("10m");
620 $filestore[0] = substr($time, 4, 8);
621 # Get the new file name
622 $newfile = join(".",@filestore);
623 $ret_var = &send_file("this-is-yr-wakeup-call");
624 if ($ret_var == 0 ) {
625 $ret_var = &send_file("to-confirm-wakeup");
626 }
627 if ($ret_var == 0 ) {
628 $ret_var = &send_file("press-1");
629 }
630 if ($ret_var == 0 ) {
631 $ret_var = &send_file("to-snooze-for");
632 }
633 if ($ret_var == 0 ) {
634 $ret_var = &send_file("digits/10");
635 }
636 if ($ret_var == 0 ) {
637 $ret_var = &send_file("minutes");
638 }
639 if ($ret_var != 0 ) {
640 $ret_var = &ascii2num($ret_var);
641 }
642 if ($ret_var == 0 ) {
643 $ret_var = &get_data("press-2",1);
644 }
645 if ($ret_var == 2 ) {
646 # Populate some variables
647 $time = &new_time("10m");
648 $extension = $AGI{extension};
649 $context = $AGI{context};
650 # Open the file
651 open (CALL, '>', "${WAKEDIR}/${newfile}") or die "Cannot open call file for write :$!";
652 $myprint = "channel: Local" . "/" . $extension . "@" . $context . "\n";
653 print CALL $myprint;
654 print CALL "maxretries: 3\n";
655 print CALL "retrytime: 60\n";
656 print CALL "waittime: 60\n";
657 print CALL "callerid: \"AsterPBX Weckruf\" <$AGI{callerid}>\n";
658 print CALL "application: AGI\n";
659 print CALL "data: wakeup|$newfile\n";
660 close ($CALL);
661 # Touch the file with the new time
662 my @command = ("$TOUCH", "-t", "$time", "${WAKEDIR}/${newfile}");
663 system(@command) == 0
664 or die "system @command failed: $?";
665 # Now move it
666 my @command = ("mv", "${WAKEDIR}/${newfile}", "${OUTDIR}/${newfile}");
667 system(@command) == 0
668 or die "system @command failed: $?";
669 $ret_dummy = &send_file("goodbye");
671 } elsif ($ret_var == 1) {
672 $ret_dummy = &send_file("goodbye");
673 } else {
674 $ret_dummy = &send_file("goodbye");
675 }
677 # Stream out the wakeup
678 return 0;
679 }
681 ######## main program ########
682 # Here goes the main program #
683 ##############################
684 my $numargs = $#ARGV + 1;
685 if ($DEBUG == 1) {
686 open (DEBUGOUT, '>', $debugfile) or die "Cannot open $debugfile for write :$!";
687 }
689 # Start by reading in the stuff Asterisk is sending
690 &init_agi(); # Comment out in case of debug outside Asterisk
692 # If DEBUG is set, dump the AGI variable
693 if ($DEBUG == 1) {
694 foreach my $i (sort keys %AGI) {
695 print DEBUGOUT " -- $i = $AGI{$i}\n";
696 }
697 }
699 if ( $numargs == 0 ) {
700 &welcome();
701 &hangup();
702 exit(0);
703 } elsif ( $ARGV[0] eq "move" ) {
704 &move();
705 &hangup();
706 exit(0);
707 } else {
708 &snooze($ARGV[0]);
709 &hangup();
710 exit(0);
711 }
713 if ($DEBUG ==1) {
714 close $DEBUGOUT;
715 }