#!/usr/bin/perl # # AST_vm_update.pl version 0.4 *DBI-version* # # DESCRIPTION: # uses the Asterisk Manager interface and Net::MySQL to update the count of # voicemail messages for each mailbox (in the phone table) in the voicemail # table list is used by client apps for voicemail notification # # SUMMARY: # This program was designed for people using the Asterisk PBX with voicemail # # For the client program to notify of new messaged, this program must be in the # cron running every minute # # For this program to work you need to have the "asterisk" MySQL database # created and create the tables listed in the CONF_MySQL.txt file, also make sure # that the machine running this program has read/write/update/delete access # to that database # # It is recommended that you run this program on the local Asterisk machine # # If this script is run ever minute there is a theoretical limit of # 600 mailboxes that it can check due to the wait interval. If you have # more than this either change the cron when this script is run or change the # wait interval below # # Copyright (C) 2006 Matt Florell LICENSE: GPLv2 # # 50823-1422 - Added database server variable definitions lookup # 50823-1452 - Added commandline arguments for debug at runtime # 60717-1204 - changed to DBI by Marin Blu # # constants $DB=0; # Debug flag, set to 0 for no debug messages per minute $US='__'; $MT[0]=''; ### begin parsing run-time options ### if (length($ARGV[0])>1) { $i=0; while ($#ARGV >= $i) { $args = "$args $ARGV[$i]"; $i++; } if ($args =~ /--help/i) { print "allowed run time options:\n [-t] = test\n [-debug] = verbose debug messages\n\n"; } else { if ($args =~ /-debug/i) { $DB=1; # Debug flag } if ($args =~ /-t/i) { $TEST=1; $T=1; } } } else { # print "no command line options set\n"; } ### end parsing run-time options ### ### Make sure this file is in a libs path or put the absolute path to it require("/home/cron/AST_SERVER_conf.pl"); # local configuration file if (!$DB_port) {$DB_port='3306';} use lib './lib', '../lib'; use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second use DBI; use Net::Telnet (); $dbhA = DBI->connect("DBI:mysql:$DB_database:$DB_server:$DB_port", "$DB_user", "$DB_pass") or die "Couldn't connect to database: " . DBI->errstr; ### Grab Server values from the database $stmtA = "SELECT telnet_host,telnet_port,ASTmgrUSERNAME,ASTmgrSECRET,ASTmgrUSERNAMEupdate,ASTmgrUSERNAMElisten,ASTmgrUSERNAMEsend,max_vicidial_trunks,answer_transfer_agent,local_gmt,ext_context FROM servers where server_ip = '$server_ip';"; $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; if ($DB) {print "|$stmtA|\n";} $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; $sthArows=$sthA->rows; $rec_count=0; if ($sthArows > 0) { @aryA = $sthA->fetchrow_array; $DBtelnet_host = "$aryA[0]"; $DBtelnet_port = "$aryA[1]"; $DBASTmgrUSERNAME = "$aryA[2]"; $DBASTmgrSECRET = "$aryA[3]"; $DBASTmgrUSERNAMEupdate = "$aryA[4]"; $DBASTmgrUSERNAMElisten = "$aryA[5]"; $DBASTmgrUSERNAMEsend = "$aryA[6]"; $DBmax_vicidial_trunks = "$aryA[7]"; $DBanswer_transfer_agent= "$aryA[8]"; $DBSERVER_GMT = "$aryA[9]"; $DBext_context = "$aryA[10]"; if ($DBtelnet_host) {$telnet_host = $DBtelnet_host;} if ($DBtelnet_port) {$telnet_port = $DBtelnet_port;} if ($DBASTmgrUSERNAME) {$ASTmgrUSERNAME = $DBASTmgrUSERNAME;} if ($DBASTmgrSECRET) {$ASTmgrSECRET = $DBASTmgrSECRET;} if ($DBASTmgrUSERNAMEupdate) {$ASTmgrUSERNAMEupdate = $DBASTmgrUSERNAMEupdate;} if ($DBASTmgrUSERNAMElisten) {$ASTmgrUSERNAMElisten = $DBASTmgrUSERNAMElisten;} if ($DBASTmgrUSERNAMEsend) {$ASTmgrUSERNAMEsend = $DBASTmgrUSERNAMEsend;} if ($DBmax_vicidial_trunks) {$max_vicidial_trunks = $DBmax_vicidial_trunks;} if ($DBanswer_transfer_agent) {$answer_transfer_agent = $DBanswer_transfer_agent;} if ($DBSERVER_GMT) {$SERVER_GMT = $DBSERVER_GMT;} if ($DBext_context) {$ext_context = $DBext_context;} } $sthA->finish(); @PTextensions=@MT; @PTvoicemail_ids=@MT; @PTmessages=@MT; @PTold_messages=@MT; @NEW_messages=@MT; @OLD_messages=@MT; $stmtA = "SELECT extension,voicemail_id,messages,old_messages from phones where server_ip='$server_ip'"; if ($DB) {print "|$stmtA|\n";} $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; $sthArows=$sthA->rows; $rec_count=0; while ($sthArows > $rec_count) { @aryA = $sthA->fetchrow_array; $PTextensions[$rec_count] = "$aryA[0]"; $PTvoicemail_ids[$rec_count] = "$aryA[1]"; $PTmessages[$rec_count] = "$aryA[2]"; $PTold_messages[$rec_count] = "$aryA[3]"; $rec_count++; } $sthA->finish(); ### connect to asterisk manager through telnet $t = new Net::Telnet (Port => 5038, Prompt => '/.*[\$%#>] $/', Output_record_separator => '',); #$fh = $t->dump_log("$telnetlog"); # uncomment for telnet log if (length($ASTmgrUSERNAMEsend) > 3) {$telnet_login = $ASTmgrUSERNAMEsend;} else {$telnet_login = $ASTmgrUSERNAME;} $t->open("$telnet_host"); $t->waitfor('/0\n$/'); # print login $t->print("Action: Login\nUsername: $telnet_login\nSecret: $ASTmgrSECRET\n\n"); $t->waitfor('/Authentication accepted/'); # waitfor auth accepted $i=0; foreach(@PTextensions) { @list_channels=@MT; $t->buffer_empty; @list_channels = $t->cmd(String => "Action: MailboxCount\nMailbox: $PTvoicemail_ids[$i]\n\nAction: Ping\n\n", Prompt => '/Response: Pong.*/'); $j=0; foreach(@list_channels) { if ($list_channels[$j] =~ /Mailbox: $PTvoicemail_ids[$i]/) { $NEW_messages[$i] = "$list_channels[$j+1]"; $NEW_messages[$i] =~ s/NewMessages: |\n//gi; $OLD_messages[$i] = "$list_channels[$j+2]"; $OLD_messages[$i] =~ s/OldMessages: |\n//gi; } $j++; } if($DB){print "MailboxCount- $PTvoicemail_ids[$i] NEW:|$NEW_messages[$i]| OLD:|$OLD_messages[$i]| ";} if ( ($NEW_messages[$i] eq $PTmessages[$i]) && ($OLD_messages[$i] eq $PTold_messages[$i]) ) { if($DB){print "MESSAGE COUNT UNCHANGED, DOING NOTHING FOR THIS MAILBOX\n";} } else { $stmtA = "UPDATE phones set messages='$NEW_messages[$i]', old_messages='$OLD_messages[$i]' where server_ip='$server_ip' and extension='$PTextensions[$i]'"; if($DB){print STDERR "\n|$stmtA|\n";} $affected_rows = $dbhA->do($stmtA); # or die "Couldn't execute query:|$stmtA|\n"; } $i++; ### sleep for 10 hundredths of a second usleep(1*100*1000); } $t->buffer_empty; @hangup = $t->cmd(String => "Action: Logoff\n\n", Prompt => "/.*/"); $t->buffer_empty; $ok = $t->close; $dbhA->disconnect(); if($DB){print "DONE... Exiting... Goodbye... See you later... \n";} exit;