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

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

use Plagger::Util to strip HTML

Line 
1 package Plagger::Plugin::Subscription::LivedoorReader;
2 use strict;
3 use base qw( Plagger::Plugin );
4
5 use JSON::Syck;
6 use URI;
7 use URI::QueryParam;
8 use WWW::Mechanize;
9 use Plagger::Util;
10
11 sub plugin_id {
12     my $self = shift;
13     $self->class_id . '-' . $self->conf->{username};
14 }
15
16 sub register {
17     my($self, $context) = @_;
18
19     $self->init_reader;
20     $context->register_hook(
21         $self,
22         'subscription.load' => \&notifier,
23     );
24 }
25
26 sub init_reader {
27     my $self = shift;
28     $self->{mech} = WWW::Mechanize->new(cookie_jar => $self->cache->cookie_jar);
29
30     unless (defined($self->conf->{username}) && defined($self->conf->{password})) {
31         Plagger->context->error("username and/or password is missing");
32     }
33 }
34
35 sub notifier {
36     my($self, $context) = @_;
37
38     $self->{mech}->get("http://rpc.reader.livedoor.com/notify?user=" . $self->conf->{username});
39     my $content = $self->{mech}->content;
40
41     # copied from WebService/Bloglines.pm
42
43     # |A|B| where A is the number of unread items
44     $content =~ /\|([\-\d]+)|(.*)|/
45         or $context->error("Bad Response: $content");
46
47     my($unread, $url) = ($1, $2);
48
49     # A is -1 if the user email address is wrong.
50     if ($unread == -1) {
51         $context->error("Bad username: " . $self->conf->{username});
52     }
53
54     return unless $unread;
55
56     $context->log(info => "You have $unread unread item(s) on livedoor Reader.");
57
58     my $feed = Plagger::Feed->new;
59     $feed->aggregator(sub { $self->sync(@_) });
60     $context->subscription->add($feed);
61 }
62
63 sub sync {
64     my($self, $context, $args) = @_;
65
66     my $mark_read = $self->conf->{mark_read};
67        $mark_read = 1 unless defined $mark_read;
68
69     $self->login_reader();
70
71     my $subs = $self->_request("/api/subs", { unread => 1 });
72
73     for my $sub (@$subs) {
74         $context->log(debug => "get unread items of $sub->{subscribe_id}");
75         my $data = $self->_request("/api/unread", { subscribe_id => $sub->{subscribe_id} });
76         $self->_request("/api/touch_all", { subscribe_id => $sub->{subscribe_id} })
77             if $mark_read;
78
79         my $feed = Plagger::Feed->new;
80         $feed->type('livedoorReader');
81         $feed->title( Plagger::Util::strip_html($data->{channel}->{title}) );
82         $feed->link($data->{channel}->{link});
83         $feed->url($data->{channel}->{feedlink});
84         $feed->image({ url => $data->{channel}->{image} || $sub->{icon} });
85         $feed->meta->{livedoor_reader_id} = $sub->{subscribe_id};
86         $feed->meta->{rate} = $sub->{rate};
87         $feed->add_tag($_) for @{$sub->{tags}};
88         $feed->add_tag($sub->{folder}) if $sub->{folder};
89         $feed->updated( Plagger::Date->from_epoch($sub->{modified_on}) ) if $sub->{modified_on};
90         $feed->description($data->{channel}->{description});
91         $feed->meta->{livedoor_reader_subscribers_count} = $data->{channel}->{subscribers_count};
92
93         for my $item ( @{$data->{items}} ) {
94             my $entry = Plagger::Entry->new;
95             $entry->title($item->{title});
96             $entry->author($item->{author}) if $item->{author};
97             $entry->link($item->{link});
98             # TODO support enclosure
99             $entry->tags([ $item->{category} ]) if $item->{category};
100             $entry->date( Plagger::Date->from_epoch($item->{modified_on}) ); # xxx created_on as well
101             $entry->meta->{livedoor_reader_item_id} = $item->{id};
102             $entry->feed_link($feed->link);
103             $entry->body($item->{body});
104
105             $feed->add_entry($entry);
106         }
107
108         $context->update->add($feed);
109     }
110 }
111
112 sub login_reader {
113     my $self = shift;
114
115     local $^W; # input type="search" warning
116     $self->{mech}->get("http://reader.livedoor.com/reader/");
117
118     if ($self->{mech}->content =~ /name="loginForm"/) {
119         Plagger->context->log(debug => "Logging in to Livedoor Reader");
120         $self->{mech}->submit_form(
121             form_name => 'loginForm',
122             fields => {
123                 livedoor_id => $self->conf->{username},
124                 password    => $self->conf->{password},
125             },
126         );
127
128         if ( $self->{mech}->content =~ /class="headcopy"/ ) {
129             Plagger->context->error("Failed to login using username & password");
130         }
131     }
132 }
133
134 sub _request {
135     my($self, $method, $param) = @_;
136
137     my $uri = URI->new_abs($method, "http://reader.livedoor.com/");
138     $uri->query_param(%$param) if $param;
139
140     $self->{mech}->get($uri->as_string);
141
142     return JSON::Syck::Load($self->{mech}->content);
143 }
144
145 1;
146
147 __END__
148
149 =head1 NAME
150
151 Plagger::Plugin::Subscription::LivedoorReader - Synchronize livedoor Reader with JSON API
152
153 =head1 SYNOPSIS
154
155   - module: Subscription::LivedoorReader
156     config:
157       username: your-livedoor-id
158       password: your-password
159       mark_read: 1
160
161 =head1 DESCRIPTION
162
163 This plugin allows you to synchronize your subscription using Livedoor
164 Reader JSON API.
165
166 =head1 CONFIGURATION
167
168 =over 4
169
170 =item username, password
171
172 Your username & password to use with livedoor Reader.
173
174 =item mark_read
175
176 C<mark_read> specifies whether this plugin I<marks as read> the items
177 you synchronize. With this option set to 0, you will get the
178 duplicated updates everytime you run Plagger, until you mark them
179 unread using Livedoor Reader web interface.
180
181 =back
182
183 =head1 AUTHOR
184
185 Tatsuhiko Miyagawa
186
187 =head1 SEE ALSO
188
189 L<Plagger>, L<Plagger::Plugin::Subscription::Bloglines>, L<http://reader.livedoor.com/>
190
191 =cut
192
Note: See TracBrowser for help on using the browser.