#!/usr/bin/perl
use strict;
use warnings;
use Text::vFile::asData;
use Digest::MD5 qw(md5_hex);
use DateTime;
use CGI;
my $file = -e 'SystemsSupportRota' ? 'SystemsSupportRota' : 'http://intranet.fotango.private/index.php?title=Systems_Support_Rota&action=raw';
=head1 NAME
rota_ical.cgi - scrape the SystemsSupportRota wiki page into ics
=head1 DESCRIPTION
=cut
my @tasks;
my %rrule;
sub make_events {
my $when = shift;
my %who;
@who{ @tasks } = @_;
my $year = DateTime->now->year;
return unless $when =~ m{(\S+)\s+(\d+)\s*/\s*(\d+)};
my ($weekday, $day, $month) = ($1, $2, $3);
my $start = DateTime->new( year => $year, month => $month, day => $day );
my $end = $start->clone->add( days => 1 );
my $is_rrule;
if ($when =~ /From/) {
# establish an rrule for that weekday
push @{ $rrule{$weekday} }, {
start => $start->epoch,
map { $_ => md5_hex( "$when $who{$_} $_" ) } @tasks,
};
$is_rrule = 1;
}
# find the latest rrule that covers this date
my ($rrule) = grep { $start->epoch >= $_->{start} } sort { $a->{start} <=> $b->{start} } @{ $rrule{ $weekday } || [] };
return map +{
type => 'VEVENT',
properties => {
SUMMARY => [ { value => "$who{$_} $_" } ],
DESCRIPTION => [ { value => "$when $who{$_} $_" } ],
DTSTART => [ { value => $start->ymd(''),
param => { VALUE => 'DATE' },
} ],
DTEND => [ { value => $end->ymd(''),
param => { VALUE => 'DATE' },
} ],
UID => [ { value => $rrule ? $rrule->{ $_ } : md5_hex( "$when $who{$_} $_" ) } ],
($is_rrule ? ( RRULE => [ { value => "FREQ=WEEKLY;INTERVAL=1" } ] )
: $rrule ? ( 'RECURRENCE-ID' => [ { param => { VALUE => "DATE" }, value => $start->ymd('') } ] ) : ()),
},
}, sort grep { $who{$_} } @tasks;
}
my $cal = {
type => 'VCALENDAR',
properties => {
'X-WR-CALNAME' => [ { value => "Systems Rota" } ],
},
objects => [],
};
# sometimes, we want to use a url so wrap read_file as get_lines
sub get_lines {
my $file = shift;
if ($file =~ m{^https?://}) {
# s'really a url
require LWP::Simple;
my $content = LWP::Simple::get( $file );
return split $/, $content;
}
require File::Slurp;
return File::Slurp::read_file( $file );
}
sub parse_tables {
my (@rows, @row, $in_table);
for (@_) {
chomp;
/^{\|/ and do { $in_table = 1; next };
/^\|}/ and do { $in_table = 0; next };
next unless $in_table;
/^\|-/ and do {
push @rows, [@row] if @row;
@row = ();
next;
};
/^\| (.*)/ and do {
push @row, $1;
next;
};
print "Didn't expect: $_\n";
}
return @rows, (@row ? [@row] : ());
}
for (parse_tables( get_lines( $file ) )) {
$_->[0] =~ /Date/ and do {
(undef, @tasks) = @$_;
next;
};
push @{ $cal->{objects} }, make_events( @$_ );
}
print CGI->header('text/calendar');
print map "$_\n", Text::vFile::asData->generate_lines( $cal );