package WWW::Spinn3r::Synced;
use WWW::Spinn3r;
use DateTime;
use DateTime::Duration;
use DateTime::Format::ISO8601;
use Data::Dumper;
use DB_File;
use Fcntl;
use File::Temp qw(tempfile);
use Storable qw(freeze thaw);
my $iso8601 = DateTime::Format::ISO8601->new;
sub new {
my $p = shift;
my %param = @_;
exists $param{api} and die "don't pass api to WWW::Spinn3r::Synced, use WWW::Spinn3r instead if you want a specific api";
delete $param{api};
my $match_range = delete($param{match_range}) || 30;
my %pparam = %param;
my $self = bless {
permalink => WWW::Spinn3r->new(api => 'permalink3.getDelta', %pparam),
fi => { },
last_ftime => undef,
match_range => $match_range,
orig_param => \%param,
}, $p;
$self
}
sub feed_begin {
my ($self, $after) = @_;
my %param = %{$self->{orig_param}};
$param{params}->{after} = $after;
$self->{feed} = WWW::Spinn3r->new(api => 'feed3.getDelta', %param);
$self->{feed}->next();
}
sub feed_next {
my $self = shift;
$self->{feed}->next(@_);
}
sub permalink_next {
my $self = shift;
$self->{permalink}->next(@_);
}
sub next {
my $self = shift;
my $fi = $self->{fi};
my $match_range = $self->{match_range};
my $pitem = $self->permalink_next;
return unless $pitem;
my $ptime = $pitem->{t} = $iso8601->parse_datetime($pitem->{'post:date_found'})->epoch;
my $min_t = $ptime - $match_range;
my $max_t = $ptime + $match_range;
my $link = $$pitem{link};
unless ($self->{feed}) {
$self->feed_begin($iso8601->parse_datetime($pitem->{'post:date_found'}) - DateTime::Duration->new(seconds => $match_range));
}
my $feed_count = 0;
while ($self->{last_ftime} <= $max_t and $feed_count < 1024) {
my $fitem = $self->feed_next;
my $ftime = $fitem->{t} = $iso8601->parse_datetime($fitem->{'post:date_found'})->epoch;
$$fi{$$fitem{link}} = $fitem;
$self->{last_ftime} = $ftime;
$feed_count++;
}
# this feed item, if defined, goes with this permalink
my $fitem = delete $$fi{$link};
# remove feed items which don't refer to permalink items
for my $flink (keys %$fi) {
my $fitem = $$fi{$flink};
my $ftime = $$fitem{t};
$ftime < $min_t and delete $$fi{$flink};
}
return [$pitem, $fitem];
}
1;
=head1 NAME
WWW::Spinn3r::Synced - A interface that provides synced access to
permalink and feed APIs.
=head1 SYNOPOSIS
use WWW::Spinn3r::Synced;
use DateTime;
my $API = {
vendor => 'acme', # required
limit => 5,
after => DateTime->now()->subtract(hours => 48),
};
my $spnr = new WWW::Spinn3r::Synced (params => $API, debug => 1);
while(1) {
my ($p, $f) = @{ $spnr->next };
if ($p and $f) {
print "both! $$p{link}\n"
} else {
print "permalink only! $$p{link}\n"
}
}
=head1 DESCRIPTION
WWW::Spinn3r::Synced synchronizes the C<permalink3.getDelta> and
C<feed3.getDelta> APIs provided by Spinn3r such that next() returns both
the permalink and feed items associated with a link.
=head1 B<new()>
The same as new() in WWW::Spinn3r but doesn't accept an C<api> key, since
both APIs are used internally by this module.
=head1 next()
Returns an arrayref, the first element is the permalink item and the
second element is the feed item. When a feed item is not available,
the permalink is returned as first item, and the second item is set
to undef.
=head1 SEE ALSO
examples/synced.pl, WWW::Spinn3r
=head1 AUTHOR
Dan Brumleve <opensource@slaant.com>
=cut