2021-05-25 12:43:59 +02:00
#!/usr/bin/perl
use strict ;
use warnings ;
use HTTP::Tiny ;
use DateTime ;
use JSON ;
use LWP::UserAgent ;
my % data = (
2021-07-13 20:53:54 +02:00
'Arena Berlin (Biontech)' = > '&visit_motive_ids=2495719&agenda_ids=457622-457619-457629-457626-457627-457610-457631-457621-457625-457611-457612-457620-457617-457623-457628-457616-457614-457618-457613-457615&insurance_sector=public&practice_ids=158431&destroy_temporary=true&limit=4' ,
'Messe Berlin (Biontech)' = > '&visit_motive_ids=2495719&agenda_ids=457415-457408-457411-457407-457504-457414-457511-457404-457412-457409-457405-457418&insurance_sector=public&practice_ids=158434&destroy_temporary=true&limit=4' ,
'Flughafen Berlin-Tegel (Biontech)' = > '&visit_motive_ids=2495719&agenda_ids=457363-457254-457331-457358-457349-457256-457263-457343&insurance_sector=public&practice_ids=158436&destroy_temporary=true&limit=4' ,
'Flughafen Berlin-Tegel (Moderna)' = > '&visit_motive_ids=2537716&agenda_ids=465619-465615-465609-465580-465601-466144-465582-466145-466151-465592-465594-465598-466143-466150-466152-466148-466146-466147-465584-466149&insurance_sector=public&practice_ids=158436&destroy_temporary=true&limit=4' ,
'Messe Berlin (Astra)' = > '&visit_motive_ids=2597576&agenda_ids=493350-493326-493328-493324-493331-493329-493334-493348-493352-493320-493322-493335-493338-493340-493333-493353-493343-493345-493339-493347&insurance_sector=public&practice_ids=195952&destroy_temporary=true&limit=4' ,
'Flughafen Tempelhof (Moderna)' = > '&visit_motive_ids=2537716&agenda_ids=499603-499605-499608-499615-499618-499620-499621-499623-499627-499629-499631-499633-499637-499639-499641-499647-499649-499651-499654-499657&insurance_sector=public&practice_ids=158433&destroy_temporary=true&limit=4' ,
'Velodrom Berlin (Biontech)' = > '&visit_motive_ids=2495719&agenda_ids=457299-457310-457304-457291-457319-457306-457315-457321-457217-457296-457288-457991-457312-457195-457205-457193-457211-457283-457201&insurance_sector=public&practice_ids=158435&destroy_temporary=true&limit=4' ,
'Erika-Heß-Eisstadion' = > '&visit_motive_ids=2537716&agenda_ids=457979-457966-457971-457975-457970-457955-457968-457953-457976-457963-457977-457946-457954-457956-457960-457973-457959-457944-457964-457961-457967&insurance_sector=public&practice_ids=158437&destroy_temporary=true&limit=4' ,
2021-05-25 12:43:59 +02:00
) ;
my $ url = 'https://www.doctolib.de/availabilities.json?start_date=' ;
my $ dt = DateTime - > now ;
my $ date = $ dt - > ymd ;
my $ epoch = $ dt - > epoch ;
foreach my $ station ( keys % data )
{
my $ json = decode_json do_request ( $ date , $ url , $ data { $ station } ) ;
if ( $ json - > { 'total' } > 20 )
{
if ( read_last_hit ( $ station , $ json - > { 'total' } , $ epoch ) == 0 )
{
print $ station . ": total => " . $ json - > { 'total' } . " @ " . $ date . "\n" ;
send_notification ( $ station . ": total => " . $ json - > { 'total' } . " @ " . $ date ) ;
}
write_last_hit ( $ station , $ json - > { 'total' } , $ epoch ) ;
}
elsif ( defined $ json - > { 'next_slot' } )
{
#print $station.": found next_slot\n";
#send_notification($station.": found next_slot");
my ( $ ns_year , $ ns_month , $ ns_day ) = split ( "-" , $ json - > { 'next_slot' } ) ;
my $ next_slot_dt = DateTime - > new ( year = > $ ns_year , month = > $ ns_month , day = > $ ns_day ) ;
my $ date_diff = $ dt - > delta_days ( $ next_slot_dt ) ;
my $ json2 = decode_json do_request ( $ json - > { 'next_slot' } , $ url , $ data { $ station } ) ;
if ( $ json2 - > { 'total' } > 20 and $ date_diff - > in_units ( 'days' ) > 1 and $ date_diff - > in_units ( 'days' ) < 40 )
{
if ( read_last_hit ( $ station , $ json2 - > { 'total' } , $ epoch ) == 0 )
{
print $ station . ": total => " . $ json2 - > { 'total' } . " @ " . $ json - > { 'next_slot' } . "\n" ;
send_notification ( $ station . ": total => " . $ json2 - > { 'total' } . " @ " . $ json - > { 'next_slot' } ) ;
}
write_last_hit ( $ station , $ json2 - > { 'total' } , $ epoch ) ;
}
elsif ( defined $ json2 - > { 'next_slot' } )
{
print "\t" . $ station . ": LOOP?\n" ;
send_notification ( $ station . ": LOOP?" ) ;
}
else
{
#print "\t".$station.": total => ".$json2->{'total'}." @ ".$json->{'next_slot'}."\n";
}
}
else
{
#print $station.": total => ".$json->{'total'}." @ ".$date."\n";
}
sleep 1 ;
}
sub write_last_hit
{
my ( $ station , $ hits , $ epoch ) = @ _ ;
open ( FILE_W , ">>" , "/tmp/search_for_date-last_hit.txt" ) or die "Can't open file: $!" ;
print FILE_W $ station . "::" . $ hits . "::" . $ epoch . "\n" ;
close ( FILE_W ) ;
}
sub read_last_hit
{
my ( $ station , $ hits , $ epoch ) = @ _ ;
my $ too_early = 0 ;
2021-07-13 20:53:54 +02:00
if ( ! - e "/tmp/search_for_date-last_hit.txt" )
{
open ( NEW_FILE , ">" , "/tmp/search_for_date-last_hit.txt" ) or die "Can't create file: $!" ;
close ( NEW_FILE ) ;
}
2021-05-25 12:43:59 +02:00
open ( FILE_R , "<" , "/tmp/search_for_date-last_hit.txt" ) or die "Can't open file: $!" ;
my @ array = <FILE_R> ;
close ( FILE_R ) ;
foreach my $ line ( @ array )
{
chomp ( $ line ) ;
if ( $ line =~ /^(.+)\:\:$hits\:\:(\d+)$/ )
{
my $ station_old = $ 1 ;
my $ epoch_old = $ 2 ;
$ epoch -= 120 ;
if ( $ station eq $ station_old and $ epoch < $ epoch_old )
{
#print $epoch." < ".$epoch_old."\n";
$ too_early = 1 ;
}
elsif ( $ station eq $ station_old and $ epoch >= $ epoch_old )
{
#print $epoch." > ".$epoch_old."\n";
}
else
{
#print $station." ne ".$station_old." | ".$epoch." != ".$epoch_old."\n";
}
}
}
return $ too_early ;
}
sub send_notification
{
my ( $ msg ) = @ _ ;
LWP::UserAgent - > new ( ) - > post (
"https://api.pushover.net/1/messages.json" , [
"token" = > "<API_TOKEn>" ,
"user" = > "<API_USER>" ,
"message" = > "Impfstation gefunden: " . $ msg ,
] ) ;
}
sub do_request
{
my ( $ date , $ url1 , $ url2 ) = @ _ ;
my $ url = $ url1 . $ date . $ url2 ;
my $ httptiny = HTTP::Tiny - > new ( "timeout" = > 20 ) ;
my $ response = $ httptiny - > request ( "GET" , $ url ) ;
return $ response - > { 'content' } ;
}