#!/usr/bin/perl
#(c)michal grezl under GPL v3+ 

use DBI;
use File::Basename;
use File::Copy;
use Mail::Message;
use Mail::Message::Body::Multipart;
use POSIX qw(strftime);
use IPC::Cmd qw[can_run run];
use FileHandle; 
use IPC::Open2; 

$gpl = "Copyright (C) 2010 Michal Grezl
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Michal Grezl.
";

$version = "0.2";
$emergency_number = "602252333";

my $dbfile = '/usr/local/lib/sms/smsqueue.sqlite';

$curl_date = strftime "%Y%m%d%H%M%S", localtime;

if ($ARGV[0] eq "version") {
print "
$0 $version parametry:
$gpl
";
exit 0;
}

if ($ARGV[0] eq "help") {
print "
$gpl
$0 $version parametry:
help
version
showqueue- zobrazi queue
daemon - fork, obstarava queue
sluzba - cislo z webu
subject - cislo v subj
mail ######### - mail bez subj, cislo parametr
wholemail ######### - cely mail, cislo parametr
";
exit 0; 

}

if ($ARGV[0] eq "showqueue") {
  &show_queue();
  exit 0;
} elsif ($ARGV[0] eq "daemon") {
  $pid = fork();
  if ($pid) {
    # I'm the father
    print ("forked $pid\n");
    system("/bin/logger -p local5.info -t sms daemon started");

    close(DATA);
    exit 1;
  } else {
    open(DATA,">>/tmp/newsendsms-".$curl_date."-".$$.".log") or die;
    print DATA "##[START]################################################\n";
    &process_queue();
  }
}

if ($ARGV[0] eq "") {
 die "no number, died";
}

my $from = "";

while (<STDIN>) {
  if ($_ =~ "From.*") {
    $from = $_;
  } else {
    $m .= $_;
  }
}

if ($ARGV[0] eq "sluzba") {
  $number = `curl --silent --insecure https://dokumenty.hasici-ol.cz/sluzba/detail.php?date=$curl_date`;
#fixme - pokud neni vyplnena sluzba, neco udelej
  chomp $number;
  if ($number eq "") {
    $number = $emergency_number;
  }
  
  ($nic, $sms) = &read_mail($m);
} elsif ($ARGV[0] eq "subject") {
  ($number, $sms) = &read_mail($m);
} elsif ($ARGV[0] eq "mail") {
  ($nic, $sms) = &read_mail($m);
  if ($ARGV[1] ne "") {
    $number = $ARGV[1];
  } else {
    die "neni cislo u mail, died at";
  }
} elsif ($ARGV[0] eq "wholemail") {
  ($subj, $sms) = &read_mail($m);
  $sms = $subj." ".$sms;
  if ($ARGV[1] ne "") {
    $number = $ARGV[1];
  } else {
    die "neni cislo u mail, died at";
  }
} else {
  $number = $ARGV[0];
  $sms = $m;
}

$sms =~ s/\n/ /g;

$curl_date = strftime "%Y%m%d%H%M%S", localtime;
print DATA "date:$curl_date\n";
print DATA "number:($number)\n";
print DATA "input:\n--8<--\n".$m."\n--8<--\n";


if ($sms eq "") {
  print DATA "no sms\n";
  die "no sms, died";
}

if ($number eq "") {
  print DATA "no number\n";
  die "no number, died";
}

add_to_queue($number, $sms);

################################################################################
sub try_to_send_sms()
################################################################################
{
  my ($number, $sms) = @_;

  if ($number eq "" ) {
    system("/bin/logger -p local5.info -t sms no number specified");
    print DATA "cislo nezadano\n";
    $number = $emergency_number;
  }
  
  $curl_date = strftime "%Y%m%d%H%M%S", localtime;
  print DATA "date:$curl_date\n";
  
  for (my $i = 0; $i < 20; $i++) {
    system("/bin/logger -p local5.info -t sms sending to $number, try $i");
    print DATA "Try #$i, number:$number, sms:$sms. Sleeping for 10s\n";
    sleep(10);
    if (&send_sms($number, $sms) == 1) {
      print DATA "##[NEXT]################################################\n";
      return 1;
    }
    print DATA "Sleeping for 10s.\n";
    sleep(10);
  }
  print DATA "!![ERROR]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
  print DATA "##[NEXT]################################################\n";
  return 0;
}


################################################################################
sub connect_to_db()
################################################################################
{
  my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile","","",{ RaiseError => 1 },);
  if (!$dbh) {
    print DATA "connect_to_db():open database error\n";
    system("/bin/logger -p local5.info -t sms cannot open database");
    die $DBI::errstr;
  }
  return $dbh;
}

################################################################################
sub process_queue()
################################################################################
{
  print DATA "process_queue():start\n";

  while (1) {
    $i = $ARGV[0];
    $author = $ARGV[1];
    $new_location = $ARGV[2];
    
    $dbh = &connect_to_db();
    my $all = $dbh->selectall_arrayref("SELECT * FROM smsqueue");
    
    foreach my $row (@$all) {
      my ($id, $number, $sms) = @$row;
      if (&try_to_send_sms($number, $sms)) {
        $q = "delete from smsqueue where id=$id";
          print DATA "process_queue():sms send sms was successful, deleting $q\n";
        if ($dbh->do($q)) {
          print DATA "process_queue():ok\n";
        } else {
          print DATA "process_queue():error\n";
          system("/bin/logger -p local5.info -t sms cannot do query $q exiting");
          die;
        }
      }  
    }
  
    $dbh->disconnect();
    sleep 5;
  }

  print DATA "process_queue():end\n";
  close DATA;

  exit 0;
}

################################################################################
sub show_queue()
################################################################################
{
  my $dbh = &connect_to_db();

  my $all = $dbh->selectall_arrayref("SELECT * FROM smsqueue");
  
  print "Queue:\n";
  foreach my $row (@$all) {
    my ($id, $number, $sms) = @$row;
    print "$id|$number|$sms\n";
  }
  print "------\n";
  $dbh->disconnect();
}

################################################################################
sub add_to_queue()
################################################################################
{

  print DATA "add_to_queue():\n";

  my ($number, $sms) = @_;
  ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
  $id = 1;
  $random_number = int(rand(100));

  $id = join ("",
  $year-100,
  sprintf("%02d", $mon),
  $mday,
  $hour,
  $min,
  $sec,
  sprintf("%03d", $random_number));
  
  my $dbh = &connect_to_db();

  $q = "insert into smsqueue values ($id, '$number', '$sms')";
  $dbh->do($q) or die;
  print DATA "add_to_queue(): added $q\n";
  $dbh->disconnect();
}

################################################################################
sub fill_database()
################################################################################
{
  &add_to_queue(123454,"n1zdar");
  &add_to_queue(223454,"n2zdar");
  &add_to_queue(323454,"n3zdar");
  &add_to_queue(423454,"n4zdar");
  &add_to_queue(523454,"n5zdar");
  &add_to_queue(623454,"n6zdar");
  &add_to_queue(723454,"n7zdar");
  &add_to_queue(999954,"n8zdar");
}


################################################################################
sub send_sms()
################################################################################
{
  my ($number, $sms) = @_;

  $command = "/usr/bin/gnokii --config /etc/gnokii/gnokiirc --sendsms $number";

  my $date = strftime "%Y%m%d%H%M%S", localtime;

  print DATA "send_sms():
  date:$date
  number:($number)
  sms:($sms)
  command:($command)\n";

  system("/bin/logger -p local5.info -t sms sending to $number ");

  my $cmd = "echo \"$sms\" | $command";

  my($success, $error_code, $full_buf, $stdout_buf, $stderr_buf) = run(command => $cmd, verbose => 0);

  if ($success) {
    system("/bin/logger -p local5.info -t sms send ok");
    print DATA "ok:\n";
    print DATA join "", @$full_buf;
    return 1;
  } else {
    system("/bin/logger -p local5.info -t sms send failed");
    print DATA "error: $error_code\n";
    print DATA join "", @$stderr_buf;
    return 0;
  }
  return 0;
}


################################################################################
sub read_mail() 
################################################################################
{
  my($m) = @_;

  print DATA "read_mail():\n";

  $msg = Mail::Message->read($m);
  my $subject = $msg->subject;
  my $body = $msg->body;
  my $mbody;

  if($body->isMultipart) {
    my @attachments = $body->parts;
    foreach $part (@attachments) {
      if ($part->contentType eq "text/plain") {
        $mbody = $part->body;
      }
    }      
  }  else {
    $mbody = $msg->body;
  }
  
  $sms = substr($mbody, 0, 160);

  print DATA "read_mail():returned $subject, $sms\n";

  return ($subject, $sms);
}
