package CalDAV::Simple;
use 5.006;
use strict;
use warnings;
use Moo 1.006;
use Carp qw/ croak /;
use CalDAV::Simple::Task;
our $VERSION = '0.01';
has ua => (
is => 'ro',
default => sub {
require HTTP::Tiny;
require IO::Socket::SSL;
return HTTP::Tiny->new(agent => __PACKAGE__.'/'.$VERSION);
},
);
has calendar => (is => 'ro');
has username => (is => 'ro');
has password => (is => 'ro');
has croak_on_failure => (is => 'ro', default => sub { 1 });
has _url => (is => 'lazy');
sub _build__url
{
my $self = shift;
# This is a hack for doing basic auth
if ($self->calendar =~ m!^(https?://)(.*)$!) {
return $1.$self->username.':'.$self->password.'@'.$2;
}
else {
# This is probably my fault :-)
croak sprintf("unexpected format calendar '%s'\n",
$self->calendar);
}
}
my $request = sub {
my $self = shift;
my $param = shift;
return $self->ua->request($param->{verb}, $param->{url},
{
headers => $param->{headers},
content => $param->{content},
});
};
sub tasks
{
my $self = shift;
my $body = '';
my $response = $self->$request({
verb => 'REPORT',
url => $self->_url,
content => $body,
headers => {
'Depth' => 1,
'Prefer' => 'return-minimal',
'Content-Type' => 'application/xml; charset=utf-8',
},
});
if ($response->{success}) {
my @tasks;
while ($response->{content} =~ m!(.*?)!msg) {
push(@tasks, CalDAV::Simple::Task->new(vcal_string => $1));
}
return @tasks;
}
else {
return undef unless $self->croak_on_failure;
# TODO: make some effort to determine what kind of failure :-)
croak "failed to get tasks\n";
}
}
sub delete_task
{
my ($self, $task) = @_;
my $response = $self->$request({
verb => 'DELETE',
url => $self->_url.'/'.$task->uid.'.ics',
headers => {
'If-Match' => $task->etag,
'Content-Type' => 'application/xml; charset=utf-8',
},
});
}
1;
=head1 NAME
CalDAV::Simple - a simple interface to calendar services via a subset of CalDAV
=head1 SYNOPSIS
use CalDAV::Simple;
my $cal = CalDAV::Simple->new(
username => $username,
password => $password,
calendar => $url,
);
my @tasks = $cal->tasks;
foreach my $task (@tasks) {
printf "task '%s' is due '%s'\n", $task->summary, $task->due;
}
=head1 DESCRIPTION
This is a ALPHA quality module for talking to a CalDAV server.
Currently it just provides an interface for getting tasks
and deleting individual tasks.
This distribution is currently a lash-up: I hacked together something to
solve a problem. It does things the quick dirty way, and the interface
is likely to change from release to release. So far I've only tested it
against L's CalDAV server: I've no idea if
it will work with other servers yet. Please let me know either way.
=head1 METHODS
=head2 new
This expects three attributes: username, password, and calendar.
The latter is the URL for your calendar.
=head2 tasks
Returns a list of all tasks in the calendar.
Each entry in the list is an instance of L.
Look at the document for that module to see what attributes are provided.
=head2 delete_task
Takes a task (instance of L) and deletes it
from the calendar.
=head1 LIMITATIONS
This is very much alpha quality and has only been tested against one CalDAV server.
The XML returned by the server is currently handled with regular expressions,
and I haven't read any specs to find out what range of results I can expect.
In short: your mileage may vary :-)
=head1 SEE ALSO
L - instances of this are returned by the C method,
and expected as the argument to the C method.
L -
documentation about CalDAV, which I've been using as a guide when hacking this up.
L - about CalDAV.
=head1 REPOSITORY
L
=head1 AUTHOR
Neil Bowers Eneilb@cpan.orgE
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2015 by Neil Bowers .
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut