package Plagger::Plugin::Subscription::OPML;
use strict;
use base qw( Plagger::Plugin );
use Plagger::Util;
use URI;
use XML::OPML;
our $HAS_LIBERAL;
BEGIN {
eval { require XML::Liberal; $HAS_LIBERAL = 1 };
}
sub register {
my($self, $context) = @_;
$context->register_hook(
$self,
'subscription.load' => \&load,
);
}
sub load {
my($self, $context) = @_;
my $uri = URI->new($self->conf->{url})
or $context->error("config 'url' is missing");
$self->load_opml($context, $uri);
}
sub load_opml {
my($self, $context, $uri) = @_;
my $xml = Plagger::Util::load_uri($uri, $self);
if ($HAS_LIBERAL) {
my $parser = XML::Liberal->new('LibXML');
my $doc = $parser->parse_string($xml);
$xml = $doc->toString;
}
my $opml = XML::OPML->new;
$opml->parse($xml);
for my $outline (@{ $opml->outline }) {
$self->walk_down($outline, $context, 0, []);
}
}
sub walk_down {
my($self, $outline, $context, $depth, $containers) = @_;
if (delete $outline->{opmlvalue}) {
my $title = delete $outline->{title};
push @$containers, $title if $title ne 'Subscriptions';
for my $channel (values %$outline) {
$self->walk_down($channel, $context, $depth + 1, $containers);
}
pop @$containers if $title ne 'Subscriptions';
} else {
my $feed = Plagger::Feed->new;
$feed->url($outline->{xmlUrl});
$feed->link($outline->{htmlUrl});
$feed->title($outline->{title});
$feed->tags($containers);
$context->subscription->add($feed);
}
}
1;
__END__
=head1 NAME
Plagger::Plugin::Subscription::OPML - OPML subscription
=head1 SYNOPSIS
- module: Subscription::OPML
config:
url: http://example.com/mySubscriptions.opml
=head1 DESCRIPTION
This plugin creates Subscription by fetching remote OPML file by HTTP
or locally (with C URI). It supports nested folder structure
of OPML subscription.
=head1 AUTHOR
Tatsuhiko Miyagawa
=head1 SEE ALSO
L, L
=cut