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

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

Added HatenaRSS Subscription using HTML scraper

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