aboutsummaryrefslogtreecommitdiff
path: root/bin/events2md.pl
blob: e9ef842477386594ec3c172674d6899e2bc2e182 (plain)
  1. #!/usr/bin/perl
  2. use v5.36;
  3. use utf8;
  4. use open qw(:std :encoding(UTF-8));
  5. use Feature::Compat::Try;
  6. use FindBin qw($Bin);
  7. use lib "$Bin/../lib";
  8. use IO::Interactive::Tiny;
  9. use Log::Any qw($log);
  10. use Log::Any::Adapter;
  11. use URI;
  12. use DateTime;
  13. use Path::Tiny;
  14. use Text::Xslate;
  15. use Object::Groupware::DAV;
  16. use Object::Groupware::Calendar;
  17. if ( IO::Interactive::Tiny::is_interactive() ) {
  18. Log::Any::Adapter->set( 'Screen', default_level => 'info' );
  19. }
  20. # set defaults and parse command-line options
  21. my ( $BASE_URI, $CALENDAR_URI, $SKELDIR, $OUTPUT_FILE );
  22. $BASE_URI = $ENV{CAL_DAV_URL_BASE};
  23. $CALENDAR_URI = $ENV{CAL_DAV_URL_CALENDAR};
  24. $SKELDIR = $ENV{SKELDIR} || "$Bin/../templates";
  25. $BASE_URI ||= shift @ARGV
  26. if @ARGV;
  27. $CALENDAR_URI ||= shift @ARGV
  28. if @ARGV;
  29. $OUTPUT_FILE = shift @ARGV
  30. if @ARGV;
  31. # resolve calendar URIs
  32. my ( $base_uri, $calendar_uri, $calendar );
  33. $base_uri = URI->new($BASE_URI)
  34. if ($BASE_URI);
  35. $base_uri
  36. or $log->fatal('required base URI not provided') && exit 2;
  37. $base_uri->scheme
  38. or $base_uri->scheme('file');
  39. if ( $base_uri->scheme eq 'http' or $base_uri->scheme eq 'https' ) {
  40. $log->infof( 'will use base URI %s', $base_uri );
  41. $calendar_uri = URI->new( $CALENDAR_URI || $base_uri );
  42. $calendar_uri and $calendar_uri->authority
  43. or $log->fatal('bad calendar URI: must be an internet URI') && exit 2;
  44. $base_uri->eq($calendar_uri) and $calendar_uri = undef
  45. or $log->infof( 'will use calendar URI %s', $calendar_uri );
  46. my $session = Object::Groupware::DAV->new(
  47. user => $ENV{CAL_DAV_USER},
  48. pass => $ENV{CAL_DAV_PASS},
  49. uri => $base_uri,
  50. );
  51. $calendar = $session->get($calendar_uri);
  52. }
  53. elsif ( $base_uri->scheme eq 'file' ) {
  54. defined $base_uri->file
  55. or $log->fatal('bad base URI: cannot open file') && exit 2;
  56. $log->infof( 'will use base URI %s', $base_uri );
  57. # parse local calendar data
  58. $log->debug('parse local calendar data...');
  59. my $path = path( $base_uri->file );
  60. if ( $path->is_file ) {
  61. $calendar = Object::Groupware::Calendar->new( filename => "$path" );
  62. }
  63. else {
  64. my $data;
  65. $path->visit( sub { $data .= $_->slurp_raw if $_->is_file } );
  66. $calendar = Object::Groupware::Calendar->new( data => $data );
  67. }
  68. }
  69. if ( $log->is_trace ) {
  70. use DDP;
  71. p $calendar;
  72. }
  73. # select subset of calendar events
  74. $log->debug('serialize calendar events...');
  75. my $start;
  76. if ( $ENV{CAL_DAV_NOW} ) {
  77. try { require DateTimeX::Easy }
  78. catch ($e) {
  79. $log->fatalf( 'failed parsing CAL_DAV_NOW: %s', $e ) && exit 2
  80. }
  81. $start = DateTimeX::Easy->new( $ENV{CAL_DAV_NOW} );
  82. $log->fatalf(
  83. 'failed parsing CAL_DAV_NOW: unknown start time "%s"',
  84. $ENV{CAL_DAV_NOW}
  85. )
  86. && exit 2
  87. unless defined $start;
  88. }
  89. $start ||= DateTime->now;
  90. my $end = $start->clone->add( months => 6 );
  91. my $span = DateTime::Span->from_datetimes( start => $start, end => $end );
  92. my @events = $calendar->events($span);
  93. # serialize calendar view
  94. my $output_path;
  95. if ($OUTPUT_FILE) {
  96. $output_path = path($OUTPUT_FILE);
  97. $output_path->parent->mkpath;
  98. $output_path->remove;
  99. }
  100. my %vars;
  101. for (@events) {
  102. next unless $_->summary;
  103. push @{ $vars{events} }, $_;
  104. }
  105. my %tmpl;
  106. $tmpl{list} = path($SKELDIR)->child('list.md')->slurp_utf8;
  107. my $template = Text::Xslate->new(
  108. path => \%tmpl,
  109. syntax => 'TTerse',
  110. type => 'text',
  111. );
  112. my $content = $template->render( 'list', \%vars );
  113. if ($output_path) {
  114. $output_path->append_utf8($content);
  115. }
  116. else {
  117. print $content;
  118. }
  119. 1;