root/trunk/plagger/lib/Plagger/Plugin/Subscription/OPML.pm

Revision 106 (checked in by miyagawa, 15 years ago)

Added Odeo plugin. Refs #43

  • Property svn:keywords set to Id Revision
Line 
1 package Plagger::Plugin::Subscription::OPML;
2 use strict;
3 use base qw( Plagger::Plugin );
4
5 use Plagger::UserAgent;
6 use URI;
7 use XML::OPML;
8
9 sub register {
10     my($self, $context) = @_;
11
12     $context->register_hook(
13         $self,
14         'subscription.load' => \&load,
15     );
16 }
17
18 sub load {
19     my($self, $context) = @_;
20     my $uri = URI->new($self->conf->{url})
21         or $context->error("config 'url' is missing");
22
23     $self->load_opml($context, $uri);
24 }
25
26 sub load_opml {
27     my($self, $context, $uri) = @_;
28
29     my $xml;
30     if ($uri->scheme =~ /^https?$/) {
31         $context->log(debug => "Fetch remote OPML from $uri");
32         my $response = Plagger::UserAgent->new->get($uri);
33         unless ($response->is_success) {
34             $context->error("Fetch $uri failed: ". $response->status_line);
35         }
36         $xml = $response->content;
37     }
38     elsif ($uri->scheme eq 'file') {
39         $context->log(debug => "Open local OPML file " . $uri->path);
40         open my $fh, '<', $uri->path
41             or $context->error( $uri->path . ": $!" );
42         $xml = join '', <$fh>;
43     }
44     else {
45         $context->error("Unsupported URI scheme: " . $uri->scheme);
46     }
47
48     my $opml = XML::OPML->new;
49     $opml->parse($xml);
50     for my $outline (@{ $opml->outline }) {
51         $self->walk_down($outline, $context, 0, []);
52     }
53 }
54
55 sub walk_down {
56     my($self, $outline, $context, $depth, $containers) = @_;
57
58     if (delete $outline->{opmlvalue}) {
59         my $title = delete $outline->{title};
60         push @$containers, $title if $title ne 'Subscriptions';
61         for my $channel (values %$outline) {
62             $self->walk_down($channel, $context, $depth + 1, $containers);
63         }
64         pop @$containers if $title ne 'Subscriptions';
65     } else {
66         my $feed = Plagger::Feed->new;
67         $feed->url($outline->{xmlUrl});
68         $feed->link($outline->{htmlUrl});
69         $feed->title($outline->{title});
70         $feed->tags($containers);
71         $context->subscription->add($feed);
72     }
73 }
74
75 1;
76
77 __END__
78
79 =head1 NAME
80
81 Plagger::Plugin::Subscrption::OPML - OPML subscription
82
83 =head1 SYNOPSIS
84
85   - module: Subscription::OPML
86     config:
87       url: http://example.com/mySubscriptions.opml
88
89 =head1 DESCRIPTION
90
91 This plugin creates Subscription by fetching remote OPML file by HTTP
92 or locally (with C<file://> URI). It supports nested folder structure
93 of OPML subscription.
94
95 =head1 AUTHOR
96
97 Tatsuhiko Miyagawa
98
99 =head1 SEE ALSO
100
101 L<Plagger>, L<XML::OPML>
102
103 =cut
Note: See TracBrowser for help on using the browser.