In case folks don't read the TPF blog, I need someone to help me out with a script that grabs info from the Perl calendar on Google calendar. I've got it started, just don't have the time right now to polish it.
Re:Same thing I posted earlier?
cbrandtbuffalo on 2007-07-02T15:10:22
I modified it a bit from that starter. After reading some of the docs, I think I can get data ranges and possibly specify the search as part of the request. Here's the script after my mods:
#!/usr/bin/perl
use strict;
use Data::Dumper;
use Template;
use DateTime;
use Net::Google::Calendar;
my $url = "http://www.google.com/calendar/feeds/ngctmrd1cac35061mrjt3hpgng%40group.calenda r.google.com/public/full";
my $cal = Net::Google::Calendar->new( url => $url );
my $dt = DateTime->now();
my @entries = ();
# Here, I want events that contain:
# YAPC, Workshop(s), Conference(s), Hackathon(s)
# Multiple hits to Google with get_events? Need to prevent dupes.
# Way to do it with one hit and and 'OR'?
foreach my $event ( $cal->get_events(
'q' => "YAPC",
'start-min' => $dt,
)
)
{
my $hash = {};
my $title = $event->title();
$hash->{title} = $event->title;
my $body = $event->content->body;
# warn $body, "\n\n\n";
$body =~ s/ //g;
# This stuff doesn't seem to work for the 'full' style feed.
# Need to figure out how to get these details out of the $event
# object we get back.
# Default something sensible if we get nothing.
$hash->{description} = do { $body =~ s/(?:
\s*)*Event Description:\s+(.*)\s*//; $1 };
$hash->{status} = do { $body =~ s/(?:
\s*)*Event Status:\s+(.*)\s*//; $1 };
$hash->{where} = do { $body =~ s/(?:
\s*)*Where:\s+(.*)\s*//; $1 };
$hash->{when} = do { $body =~ s/When:\s+(.*)\s*//; $1 };
$hash->{when} =~ s/
Replaces.*//;
push @entries, $hash;
}
print Dumper (\@entries);Net::Google::Calendar is seriously broken
Limbic Region on 2007-07-06T06:08:58
I have already provided working code to Jim, but I figured I would share for those following along at home:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use DateTime;
use Getopt::Std;
use Net::Google::Calendar;
use XML::Atom::Util 'iso2dt';
my %opt;
get_args(\%opt);
my (%data, %seen);
my $cal = Net::Google::Calendar->new(url => $opt{url});
# Google Calendar supports OR'd category queries
# Google Calendar supports AND'd search string queries
# Multiple fetches are required for OR'd search string queries
# A different approach would be to pull all events and filter in perl land
for my $item (get_items($opt{search})) {
for my $event ($cal->get_events('q' => $item, 'start-min' => $opt{datetime})) {
# Since the same event may be found from different search strings
# Store only one copy of the meta data but sym link as appropriate
my $id = $event->id;
if ($seen{$id}) {
$data{$item}{$id} = $seen{$id};
}
else {
$data{$item}{$id} = {};
$seen{$id} = $data{$item}{$id};
}
my $entry = $data{$item}{$id};
$entry->{title} = $event->title || 'Unknown Title';
$entry->{description} = $event->content->body || 'Unknown Description';
$entry->{status} = get_status($event) || 'Unknown Status';
$entry->{where} = get_location($event) || 'Unknown Location';
$entry->{author} = get_author($event) || {};
$entry->{when} = get_when($event) || {};
}
}
print Dumper(\%data);
sub get_author {
my ($event) = @_;
my $author = $event->author;
my $name = $author->name || 'Unknown';
my $email = $author->email || 'Unknown';
my $weburl = $author->homepage || 'Unknown';
return {name => $name, email => $email, homepage => $weburl};
}
sub get_status {
my ($event) = @_;
my $ns = XML::Atom::Namespace->new(gd => 'http://schemas.google.com/g/2005');
my $elem = $event->elem;
my $node = ($elem->getElementsByTagNameNS($ns->{uri}, 'eventStatus'))[0];
my $val = $node->getAttribute('value');
$val =~ s!^http://schemas.google.com/g/2005#event\.!!;
return $val;
}
sub get_location {
my ($event) = @_;
my $ns = XML::Atom::Namespace->new(gd => 'http://schemas.google.com/g/2005');
my $elem = $event->elem;
my $node = ($elem->getElementsByTagNameNS($ns->{uri}, 'where'))[0];
my $val = $node->getAttribute('valueString');
return $val;
}
sub get_when {
my ($event) = @_;
my $ns = XML::Atom::Namespace->new(gd => 'http://schemas.google.com/g/2005');
my $elem = $event->elem;
my $node = ($elem->getElementsByTagNameNS($ns->{uri}, 'when'))[0];
my $beg = $node->getAttribute('startTime');
my $end = $node->getAttribute('endTime');
for ($beg, $end) {
$_ = defined($_) ? iso2dt($_)->strftime("%Y-%m-%d") : 'Unknown';
}
return {start => $beg, end => $end};
}
sub get_items {
my ($search_string) = @_;
return grep {defined($_) && length($_)} split/\|/, $search_string;
}
sub get_args {
my ($opt) = @_;
my $Usage = qq{Usage: $0 [options]
-h : This help message
-u : The (u)rl of the calendar to fetch
Default: Full feed of The Perl Review
-s : The date/time (s)tamp of when to fetch from
Format: RFC 3339. For example: 2005-08-09T10:57:00-08:00
Default: now
-i : The (i)tems to query
Format: 'item1|item2|item3'
Default: 'YAPC|workshop|conference|hackathon'
} . "\n";
getopts('hu:s:', $opt) or die $Usage;
die $Usage if $opt->{h};
$opt->{datetime} = $opt->{s} || DateTime->now();
$opt->{url} = $opt->{u} || 'http://www.google.com/calendar/feeds/ngctmrd1cac35061mrjt3hpgng%40group.calenda r.google.com/public/full';
$opt->{search} = $opt->{i} || 'YAPC|workshop|conference|hackathon'
}
__END__
TODO
1. Support parsing various different strings for -s
2. Support advanced query items '(item1&item2)|item3'
3. Provide patches to Net::Google::Calendar
4. Provide more better tests to Net::Google::Calender (use test only)
5. Extract links from the description when available
6. Use Template for the outputRe:Net::Google::Calendar is seriously broken
kyloe on 2009-12-18T12:18:39
Hi - been trying to use this (and other) code, but cant seem to get any sense out of it - it logs on OK and seems to create a 'feed' object - but whatever I do the feed is empty - i.e. I can get the version - but no entries or calendars... anyone seen this before - its got me stumped (am busy picking my way thorugh the ATOM code ... but its a bit out of my league ...)