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

Revision 277 (checked in by miyagawa, 14 years ago)

oops, typo. Thanks to woremacx

  • 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 (ref($uri) eq 'SCALAR') {
31         $xml = $$uri;
32     }
33     elsif ($uri->scheme =~ /^https?$/) {
34         $context->log(debug => "Fetch remote OPML from $uri");
35
36         my $response = Plagger::UserAgent->new->fetch($uri, $self);
37         if ($response->is_error) {
38             $context->log(error => "GET $uri failed: " .
39                           $response->http_status . " " .
40                           $response->http_response->message);
41         }
42         $xml = $response->content;
43     }
44     elsif ($uri->scheme eq 'file') {
45         $context->log(debug => "Open local OPML file " . $uri->path);
46         open my $fh, '<', $uri->path
47             or $context->error( $uri->path . ": $!" );
48         $xml = join '', <$fh>;
49     }
50     else {
51         $context->error("Unsupported URI scheme: " . $uri->scheme);
52     }
53
54     my $opml = XML::OPML->new;
55     $opml->parse($xml);
56     for my $outline (@{ $opml->outline }) {
57         $self->walk_down($outline, $context, 0, []);
58     }
59 }
60
61 sub walk_down {
62     my($self, $outline, $context, $depth, $containers) = @_;
63
64     if (delete $outline->{opmlvalue}) {
65         my $title = delete $outline->{title};
66         push @$containers, $title if $title ne 'Subscriptions';
67         for my $channel (values %$outline) {
68             $self->walk_down($channel, $context, $depth + 1, $containers);
69         }
70         pop @$containers if $title ne 'Subscriptions';
71     } else {
72         my $feed = Plagger::Feed->new;
73         $feed->url($outline->{xmlUrl});
74         $feed->link($outline->{htmlUrl});
75         $feed->title($outline->{title});
76         $feed->tags($containers);
77         $context->subscription->add($feed);
78     }
79 }
80
81 1;
82
83 __END__
84
85 =head1 NAME
86
87 Plagger::Plugin::Subscription::OPML - OPML subscription
88
89 =head1 SYNOPSIS
90
91   - module: Subscription::OPML
92     config:
93       url: http://example.com/mySubscriptions.opml
94
95 =head1 DESCRIPTION
96
97 This plugin creates Subscription by fetching remote OPML file by HTTP
98 or locally (with C<file://> URI). It supports nested folder structure
99 of OPML subscription.
100
101 =head1 AUTHOR
102
103 Tatsuhiko Miyagawa
104
105 =head1 SEE ALSO
106
107 L<Plagger>, L<XML::OPML>
108
109 =cut
Note: See TracBrowser for help on using the browser.