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

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

fix debug message

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