App-MergeCal
view release on metacpan or search on metacpan
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 1.213 second using v1.01-cache-2.11-cpan-39bf76dae61 )