#!/usr/bin/perl

our $username = "dejah";
our $password = "thoris";
our $vorwahl  = "0441";
our $phonelog = "/tmp/fritz.log";
our $prowlkey  = "bd814edc6bc1c840e226c9340f9b34c8853f3023";

# ab hier sollte kein config mehr sein 

use strict;

# Das sind alles Pakete, die man problemlos mit apt-cache search findet, falls
# sie noch nicht installiert sind
use XML::Simple;
use Data::Dumper;
use Date::Parse;
use Digest::MD5 qw(md5_hex);
use Encode qw/encode decode/;


sub checkLog();
sub getChallenge();
sub getSID($$);
sub generateResponse($$);
sub getLogfile($);
sub getGreencount($);
sub keepSilent();
sub timestring($);
sub seconds_since_midnight($);
			   

			   


# mittels challenge response holt man sich eine session id. die braucht man dann für jeden 
# Seitenaufruf
my $challenge = getChallenge();     
my $response  = generateResponse($challenge,$password);
my $sessionid = getSID($response,$username);


# schreibt auch den logfile, haengt auch an, wenn was doppelt ist.
getLogfile($sessionid);

# welche anschluesse gibt es. $message wird nicht mehr benutzt, das ist jetzt nur noch output
# aber drin werden fake-logeinträge erzeut der form
# 2014-09-03T21-14-23 04417520432 1 Fax
# stamp nummer status name_des_anschluss

my ($greencount,$message) = getGreencount($sessionid);

# mal aufraeumen
`sort  -u "$phonelog" > /tmp/$$.fritz`;
`mv  /tmp/$$.fritz "$phonelog"`;

# nachts keine nachricht
exit if keepSilent();

# prueft das logfile und generiert ggf eine message wenn eine message
# gesendet wurde, gibt es einen fake-eintrag im Logfile, der zugleich
# marker ist, ob eine message geschickt werden muss


checkLog();




exit;

sub getChallenge()
{
    my $data = `curl -s http://fritz.box/login_sid.lua`;
    my $ref = XMLin($data);
    return $ref->{Challenge};
}



sub  getSID($$)
{
    my $response = shift;
    my $username = shift;
    my $sessionid;
    open CURL, "curl -s -i http://fritz.box/login.lua -d response=$response -d username=$username -d page=/home/home.lua |";
    while (<CURL>)
    {
	chomp;
	next unless /sid=(\S+)/;
	$sessionid = $1;
    }
    close CURL;
    return $sessionid;
}

sub generateResponse($$)
{
    my $challenge = shift;
    my $password  = shift;
    return  $challenge . '-' . md5_hex(encode("UCS-2LE",$challenge . '-' . $password));    
}


sub getLogfile($)
{
    my $sessionid  = shift;
    open FON, ">>$phonelog";
    open CURL, "curl -s http://fritz.box/system/syslog.lua?sid=$sessionid|";
    while (<CURL>)
    {
	next unless /<tr><td>/;
	next unless /$vorwahl|telefon/;
	my ($date) = m|(\d\d.\d\d.\d\d)</td>|;
	my ($time) = m|(\d\d:\d\d:\d\d)</td>|;
	my ($text) = m|.*>(.*)</a>|;
	$date =~ s/(..).(..).(..)/20$3-$2-$1/;
	$time =~ s/:/-/g;
	
	print FON "${date}T$time $text\n";
    }
    close FON;
    close CURL;
}
sub getGreencount($)
{
    my $sessionid = shift;
    my $greencount;
    my $isonow = isoNow();
    open FON, ">>$phonelog";

    my @names;
    open CURL, "curl -s http://fritz.box/fon_num/fon_num_list.lua?sid=$sessionid|";
    while (<CURL>)
    {
	next unless /$vorwahl/;
	next unless /td/;
        my ($color) = m/led_(\w+)/;
        my ($name,$nummer) = m/.*title="(.*?)">($vorwahl\d+)/;
	next unless $nummer;
	my $status = 1;
        if ($color eq 'gray' )
	{
	    push @names,$name;
	    $status = 0;
	}
        print STDERR "$color $name $nummer\n";
	
	print FON "$isonow $nummer $status $name\n";
	
        next unless /green/;

	$greencount++;
    }
    close CURL;
    close FON;
    return ($greencount,
	    join ", " , @names
	);
}


sub keepSilent()
{
    my ($sec,$min,$hour) =  localtime();

    my $time = $hour + $min/60;

    return 1 if  $time > 22;
    return 0 if  $time >= 6;
    return 1;
}



checkLog();

sub checkLog()
{
    use Date::Parse;
    my $hash;
    open LOG, "$phonelog";
    
    while (<LOG>)
    {
        chomp;
        next if /^\#/;
        my ($stamp) = split / /;
        
        if (my ($nummer) =  m/$stamp Message (\d+)/ )
        {
            $hash->{$nummer}->{message} = $stamp;
        }
        if ( my ($nummer,$status,$name) =  m/$stamp (\d+) (\d) (.*)/ )
        {
            $hash->{$nummer}->{name} = $name;
            $hash->{$nummer}->{status} = $status;
            if ($status) 
            {
                $hash->{$nummer}->{okay} = $stamp;
                delete $hash->{$nummer}->{fail};
            }
            else
            {
                $hash->{$nummer}->{fail}->{last} = $stamp;
            }
        }
        
        

        if (my ($nummer,$reason) =  m/Anmeldung der Internetrufnummer (\d+)\D+(\d+)/ )
        {
            #print "FAIL $nummer  $stamp $reason\n";
            $hash->{$nummer}->{fail}->{last} = $stamp;
            $hash->{$nummer}->{status} = 0;
            if ( ! $hash->{$nummer}->{fail}->{first})
            {
            $hash->{$nummer}->{fail}->{first} = $stamp;
            }
        }
    }
    

#    print Dumper $hash;
    
    my $mhash;
    
    foreach my $nummer ( keys %$hash )
    {
        my $e = $hash->{$nummer};
        my $name = $e->{name};
        my $message = $e->{message};
        
        if ( $e->{status} )
        {
            if ( $e->{message} < $e->{okay})
            {
                $mhash->{$nummer}->{status}   = 1;
                $mhash->{$nummer}->{priority}   = 2;
                $mhash->{$nummer}->{name}     = $name;

            }
            next;
        }
        my $ausfall = $e->{fail}->{first};
        my $time = str2time($ausfall);
        my $seit = timestring(seconds_since_midnight(str2time($ausfall)));
        my $now = time;
        my $diff = timestring($now - $time);
        
        my $priority=-2;
        if ($message < $ausfall )
        {
            $priority=2;
        }
        print STDERR "Ausfall $name seit $seit  ($diff) P: $priority\n";
        

        $mhash->{$nummer}->{status}   = 0;
        $mhash->{$nummer}->{since}    = $seit;
        $mhash->{$nummer}->{name}     = $name;
        $mhash->{$nummer}->{delta}    = $diff;
        $mhash->{$nummer}->{priority} = $priority;
        
    }
    #print STDERR Dumper $mhash;

    my $p = -2;
    my @t = ();
    foreach my $nummer ( sort keys %$mhash ) 
    {
        my $status = $mhash->{$nummer}->{status};
        my $name  =  $mhash->{$nummer}->{name};
        my $delta =  $mhash->{$nummer}->{delta};
        my $seit  =  $mhash->{$nummer}->{since};
        my $priority     = $mhash->{$nummer}->{priority};
        
        if ($priority > 0 ) { $p = 2 };
        
        if ($status)
        {
            push @t,  "$name online";
        }
        else
        {
            push @t,  "$name $seit ($delta)";;
        }
	my $isonow = isoNow();
        open  FON, ">>$phonelog";
        print FON "$isonow Message $nummer $name $status $seit $delta $p\n"; 
        close FON;
    }

    my $t = join "\n", @t;
    
    if (@t)
    {
        print STDERR  "Send mit $p:\n$t\n";
        message("VOIP","Status",$t,$p );
    }
    
}



sub timestring($)
{

    
    my $s = shift ; 

    my $minus = "";
    if ($s < 0 )
    {
        $s *= -1;
        $minus = "-";
    }
    my $h = int($s/3600);     $s = $s % 3600;
    my $m = int($s/60);       $s = $s % 60;
    return sprintf "%s%02d:%02d",$minus,$h,$m,$s;
}


sub seconds_since_midnight($)
{
    my $time = shift;
    my ($sec,$min,$hour) =  localtime($time);
    return  $hour * 60 * 60 + $min * 60 + $sec;
}




sub message
{

    my $key  = "85f30332cbc1e840bed814dc2626c3940f9b34c8";

    my ($links,$rechts,$notification,$prio) = @_;

    $links  =~  s/\[(\d\d:\d\d)\]/$1/;
    $rechts =~  s/<(.*?)>/$1/;

    $notification =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
    $links =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
    $rechts =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;

    curl($key,$links,$rechts,,$notification,$prio,0);

    return;
}   

sub curl
{

    my ($apikey,
	$links,
	$rechts,
	$notification,
	$prio,
	$debug) = @_;
    
    

    my $requestURL = sprintf("https://prowl.weks.net/publicapi/add?apikey=%s&application=%s&event=%s&description=%s&priority=%d",
			     $apikey,
			     $links,
			     $rechts,
			     $notification,
			     $prio);
    
    my $x =  join '', `curl -k -s "$requestURL"`; 

}

sub  isoNow()
{
    my ($sec,$min,$hour,$day,$month,$year,$dow,$yday,$isdst) =  localtime();
    $month++;
    $year += 1900;

    return sprintf("%04d-%02d-%02dT%02d-%02d-%02d",$year,$month,$day,$hour,$min,$sec);
    
}


1;



__DATA__
    http://192.168.178.1/system/syslog.lua?sid=6c1ea053f03393c2

    http://192.168.178.1/system/syslog.lua?sid=6c1ea053f03393c2&tab=telefon

