asterisk/wakeup.agi

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

mercurial