- #!/usr/bin/perl
- use v5.36;
- use utf8;
- use open qw(:std :encoding(UTF-8));
- use Feature::Compat::Try;
- use FindBin qw($Bin);
- use lib "$Bin/../lib";
- use IO::Interactive::Tiny;
- use Log::Any qw($log);
- use Log::Any::Adapter;
- use URI;
- use DateTime;
- use Path::Tiny;
- use Text::Xslate;
- use Object::Groupware::DAV;
- use Object::Groupware::Calendar;
- if ( IO::Interactive::Tiny::is_interactive() ) {
- Log::Any::Adapter->set( 'Screen', default_level => 'info' );
- }
- # set defaults and parse command-line options
- my ( $BASE_URI, $CALENDAR_URI, $SKELDIR, $OUTPUT_FILE );
- $BASE_URI = $ENV{CAL_DAV_URL_BASE};
- $CALENDAR_URI = $ENV{CAL_DAV_URL_CALENDAR};
- $SKELDIR = $ENV{SKELDIR} || "$Bin/../templates";
- $BASE_URI ||= shift @ARGV
- if @ARGV;
- $CALENDAR_URI ||= shift @ARGV
- if @ARGV;
- $OUTPUT_FILE = shift @ARGV
- if @ARGV;
- # resolve calendar URIs
- my ( $base_uri, $calendar_uri, $calendar );
- $base_uri = URI->new($BASE_URI)
- if ($BASE_URI);
- $base_uri
- or $log->fatal('required base URI not provided') && exit 2;
- $base_uri->scheme
- or $base_uri->scheme('file');
- if ( $base_uri->scheme eq 'http' or $base_uri->scheme eq 'https' ) {
- $log->infof( 'will use base URI %s', $base_uri );
- $calendar_uri = URI->new( $CALENDAR_URI || $base_uri );
- $calendar_uri and $calendar_uri->authority
- or $log->fatal('bad calendar URI: must be an internet URI') && exit 2;
- $base_uri->eq($calendar_uri) and $calendar_uri = undef
- or $log->infof( 'will use calendar URI %s', $calendar_uri );
- my $session = Object::Groupware::DAV->new(
- user => $ENV{CAL_DAV_USER},
- pass => $ENV{CAL_DAV_PASS},
- uri => $base_uri,
- );
- $calendar = $session->get($calendar_uri);
- }
- elsif ( $base_uri->scheme eq 'file' ) {
- defined $base_uri->file
- or $log->fatal('bad base URI: cannot open file') && exit 2;
- $log->infof( 'will use base URI %s', $base_uri );
- # parse local calendar data
- $log->debug('parse local calendar data...');
- my $path = path( $base_uri->file );
- if ( $path->is_file ) {
- $calendar = Object::Groupware::Calendar->new( filename => "$path" );
- }
- else {
- my $data;
- $path->visit( sub { $data .= $_->slurp_raw if $_->is_file } );
- $calendar = Object::Groupware::Calendar->new( data => $data );
- }
- }
- if ( $log->is_trace ) {
- use DDP;
- p $calendar;
- }
- # select subset of calendar events
- $log->debug('serialize calendar events...');
- my $start;
- if ( $ENV{CAL_DAV_NOW} ) {
- try { require DateTimeX::Easy }
- catch ($e) {
- $log->fatalf( 'failed parsing CAL_DAV_NOW: %s', $e ) && exit 2
- }
- $start = DateTimeX::Easy->new( $ENV{CAL_DAV_NOW} );
- $log->fatalf(
- 'failed parsing CAL_DAV_NOW: unknown start time "%s"',
- $ENV{CAL_DAV_NOW}
- )
- && exit 2
- unless defined $start;
- }
- $start ||= DateTime->now;
- my $end = $start->clone->add( months => 6 );
- my $span = DateTime::Span->from_datetimes( start => $start, end => $end );
- my @events = $calendar->events($span);
- # serialize calendar view
- my $output_path;
- if ($OUTPUT_FILE) {
- $output_path = path($OUTPUT_FILE);
- $output_path->parent->mkpath;
- $output_path->remove;
- }
- my %vars;
- for (@events) {
- next unless $_->summary;
- push @{ $vars{events} }, $_;
- }
- my %tmpl;
- $tmpl{list} = path($SKELDIR)->child('list.md')->slurp_utf8;
- my $template = Text::Xslate->new(
- path => \%tmpl,
- syntax => 'TTerse',
- type => 'text',
- );
- my $content = $template->render( 'list', \%vars );
- if ($output_path) {
- $output_path->append_utf8($content);
- }
- else {
- print $content;
- }
- 1;
|