App-MergeCal

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

bin/mergecal
Changes.md
lib/App/MergeCal.pm
Makefile.PL
MANIFEST
MANIFEST.SKIP
MYMETA.yml
pm_to_blib
t/00-load.t
t/01-basic.t
t/02-clean-calendars.t
t/pod.t
t/pod_coverage.t
META.yml                                 Module YAML meta-data (added by MakeMaker)
META.json                                Module JSON meta-data (added by MakeMaker)

lib/App/MergeCal.pm  view on Meta::CPAN

=head1 NAME

App::MergeCal

=head1 ABSTRACT

Command line program that merges iCal files into a single calendar.

=head1 SYNOPSIS

    use App::MergeCal;

    my $app = App::MergeCal->new;
    $app->run;

    # Or, more likely, use the mergecal program

lib/App/MergeCal.pm  view on Meta::CPAN


  use Encode 'encode_utf8';
  use Text::vFile::asData;
  use LWP::Simple;
  use JSON;
  use URI;

  field $vfile_parser :param = Text::vFile::asData->new;
  field $title :param;
  field $output :param = '';
  field $calendars :param;
  field $objects;

=head1 METHODS

=head2 $app->calendars, $app->title, $app->output

Accessors for fields.

=cut

  method calendars { return $calendars }
  method title     { return $title }
  method output    { return $title }

=head2 $app->run

Main driver method.

=cut

  method run {
    $self->gather;
    $self->render;
  }

=head2 $app->gather

Access all of the calendars and gather their contents into $objects.

=cut

  method gather {
    $self->clean_calendars;
    for (@$calendars) {
      my $ics = get($_) or die "Can't get " . $_->as_string . "\n";
      $ics = encode_utf8($ics);
      open my $fh, '<', \$ics or die $!;
      my $data = $vfile_parser->parse( $fh );

      push @$objects, @{ $data->{objects}[0]{objects} };
    }
  }

=head2 $app->render

lib/App/MergeCal.pm  view on Meta::CPAN

    my $out_fh;
    if ($output) {
      open $out_fh, '>', $output
        or die "Cannot open output file [$output]: $!\n";
      select $out_fh;
    }

    say "$_\r" for Text::vFile::asData->generate_lines($combined);
  }

=head2 $app->clean_calendars

Ensure that all of the calendars are URIs. If a calendar doesn't have a scheme
then it is assumed to be a file URI.

=cut

  method clean_calendars {
    for (@$calendars) {
      $_ = URI->new($_) unless ref $_;
      if (! $_->scheme) {
        $_ = URI->new('file://' . $_);
      }
    }
  }

=head2 App::MergeCal->new, App::MergeCal->new_from_json, App::MergeCal->new_from_json_file

Constructor methods.

lib/App/MergeCal.pm  view on Meta::CPAN

}

=head1 CONFIGURATION

The behaviour of the program is controlled by a JSON file. The default name
for this file is C<config.json>. The contents of the file will look something
like this:

    {
      "title":"My Combined Calendar",
      "output":"my_calendar.ics",
      "calendars":[
        "https://example.com/some_calendar.ics",
        "https://example.com/some_other_calendar.ics",
      ]
    }

This configuration will read the the calendars from the URLs listed and
combine their contents into a file called C<my_calendar.ics> (which you will
presumably make available on the internet).

The <output> configuration option is optional. If it is omitted, then the
output will be written to C<STDOUT>.

=head1 AUTHOR

Dave Cross <dave@perlhacks.com>

=head1 LICENSE

t/01-basic.t  view on Meta::CPAN

use strict;
use warnings;

use Test::More;

use App::MergeCal;

ok(my $app = App::MergeCal->new(
  title     => 'Test',
  calendars => [
    'http://example.com/1.ics',
    'http://example.com/2.ics',
  ],
), 'Got an object');

isa_ok($app, 'App::MergeCal');

can_ok($app, qw[run gather render]);

is($app->calendars->@*, 2, 'Correct number of calendars');
is($app->title, 'Test', 'Correct title');

done_testing;

t/02-clean-calendars.t  view on Meta::CPAN

use strict;
use warnings;

use Test::More;

use App::MergeCal;

my $app = App::MergeCal->new(
  title     => 'Test',
  calendars => [
    'http://example.com/1.ics',
    '2.ics',
  ],
);

$app->clean_calendars;

for ($app->calendars->@*) {
  isa_ok($_, 'URI');
}

is $app->calendars->[0]->scheme, 'http', 'First calendar is an HTTP URI';
is $app->calendars->[1]->scheme, 'file', 'Second calendar is a file URI';

done_testing;



( run in 0.394 second using v1.01-cache-2.11-cpan-c333fce770f )