root/trunk/plagger/lib/Plagger/Plugin/CustomFeed/Frepa.pm

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

Now Plagger::UserAgent? and $plugin->cookie_jar can share cookies data with your browser. No need to set username and password to CustomFeed?::* plugins, etc.

Line 
1 package Plagger::Plugin::CustomFeed::Frepa;
2 use strict;
3 use base qw( Plagger::Plugin );
4
5 use DateTime::Format::Strptime;
6 use Encode;
7 use Time::HiRes;
8 use UNIVERSAL::require;
9 use WWW::Mechanize;
10
11 sub plugin_id {
12     my $self = shift;
13     $self->class_id . '-' . $self->conf->{livedoor_id};
14 }
15
16 sub register {
17     my ($self, $context) = @_;
18     $context->register_hook(
19         $self,
20         'subscription.load' => \&load,
21     );
22 }
23
24 sub load {
25     my ($self, $context) = @_;
26
27     $self->{mech} = WWW::Mechanize->new(cookie_jar => $self->cookie_jar);
28     $self->{mech}->agent_alias( "Windows IE 6" );
29
30     my $feed = Plagger::Feed->new;
31     $feed->aggregator(sub { $self->aggregate(@_) });
32     $context->subscription->add($feed);
33 }
34
35 sub aggregate {
36     my ($self, $context, $args) = @_;
37
38     unless ($self->login(livedoor_id => $self->conf->{livedoor_id}, password => $self->conf->{password})) {
39         $context->log(error => "Login to frepa failed.");
40         return;
41     }
42
43     $context->log(info => 'Login to frepa succeeded.');
44
45     my $feed_type = $self->conf->{feed_type} || [ qw(FriendDiary FriendStatus RecentComment) ];
46     for my $plugin (@$feed_type) {
47         my $plugin = (ref $self || $self) . "::$plugin";
48         $plugin->require or $context->error($@);
49         $self->aggregate_by_plugin($context, $plugin, $args);
50     }
51 }
52
53 sub aggregate_by_plugin {
54     my ($self, $context, $plugin, $args) = @_;
55
56     my $feed = Plagger::Feed->new;
57     $feed->type('frepa');
58     $feed->title($plugin->title);
59     $feed->link($plugin->start_url);
60
61     my $format = DateTime::Format::Strptime->new(pattern => '%Y/%m/%d %H:%M');
62
63     my @msgs = $plugin->get_list($self->{mech}, $self);
64     my $items = $self->conf->{fetch_items} || 20;
65
66     my $i = 0;
67     my $blocked = 0;
68     for my $msg (@msgs) {
69         last if $i++ >= $items;
70
71         my $entry = Plagger::Entry->new;
72         $entry->title($msg->{subject});
73         $entry->link($msg->{link});
74         $entry->author($msg->{name});
75         $entry->date( Plagger::Date->parse($format, $msg->{time}) );
76
77         if ($self->conf->{fetch_body} && !$blocked and $plugin->can('get_detail')) {
78             $context->log(info => "Fetch body from $msg->{link}");
79             my $item = $self->cache->get_callback(
80                 "item-$msg->{link}",
81                 sub {
82                     Time::HiRes::sleep( $self->conf->{fetch_body_interval} || 1.5 );
83                     $plugin->get_detail($msg->{link}, $self->{mech});
84                 },
85                 "1 hour",
86             );
87             if ($item) {
88                 my $body = $item->{description};
89                    $body =~ s!<br>!<br />!g;
90                 $entry->body($body);
91                 $entry->title($item->{subject}); # replace with full title
92             } else {
93                 $context->log(warn => "Fetch body failed. You might be blocked?");
94                 $blocked++;
95             }
96         }
97
98         if ($self->conf->{show_icon} && !$blocked) {
99             my $item = $self->fetch_icon($msg->{user_link});
100             if ($item && $item->{image} !~ /no_photo/) {
101                 $entry->icon({
102                     title => $item->{name},
103                     url   => $item->{image},
104                     link  => $msg->{user_link},
105                 });
106             }
107         }
108
109         $feed->add_entry($entry);
110     }
111
112     $context->update->add($feed);
113 }
114
115 sub fetch_icon {
116     my($self, $url) = @_;
117
118     Plagger->context->log(info => "Fetch icon from $url");
119     $self->cache->get_callback(
120         "icon-$url",
121         sub { $self->get_top($url) },
122         '1 day',
123     );
124 }
125
126 sub login {
127     my $self = shift;
128     my %args = @_;
129
130     my $start_url = 'http://www.frepa.livedoor.com/';
131     my $res = $self->{mech}->get($start_url);
132     return 0 unless $self->{mech}->success;
133
134     open FOO, ">foo";
135     print FOO $self->{mech}->content;
136
137     if ($self->{mech}->content =~ /loginside/) {
138         Plagger->context->log(debug => "cookie not found. logging in");
139         $self->{mech}->submit_form(
140             fields => {
141                 livedoor_id => $args{livedoor_id},
142                 password    => $args{password},
143                 auto_login  => 'on',
144             },
145         );
146         $self->{mech}->submit;
147         return 0 unless $self->{mech}->success;
148         return 0 if $self->{mech}->content =~ /loginside/;
149     }
150
151     return 1;
152 }
153
154 sub get_top {
155     my $self = shift;
156     my $link = shift;
157
158     my $item = {};
159     my $res = $self->{mech}->get($link);
160     return $item unless $self->{mech}->success;
161
162     my $html = decode('euc-jp', $self->{mech}->content);
163
164     chomp( my $re  = decode('utf-8', $self->top_re) );
165     if ($html =~ /$re/s) {
166         $item->{image} = $1;
167         $item->{name}  = $2;
168     }
169
170     return $item;
171 }
172
173 sub top_re {
174     return <<'RE';
175 <a href="http://(?:frepa\.livedoor\.com/.*?/|www\.frepa\.livedoor\.com/)"(?: rel="popup")?><img src="(http://img\d+\.(?:ico\.frepa\.livedoor\.com/member_photo/|bbs\.frepa\.livedoor\.com/community_board/).*?\.(?:jpe?g|JPE?G|gif|GIF|png|PNG))" border="0"></a>
176 </small>
177 .*?
178 <div id="namebody"><small><strong>(.*?)....</strong>
179 RE
180 }
181
182 1;
183
184 __END__
185
186 =head1 NAME
187
188 Plagger::Plugin::CustomFeed::Frepa - Custom feed for livedoor Frepa
189
190 =head1 SYNOPSIS
191
192   - module: CustomFeed::Frepa
193     config:
194       livedoor_id: your-id
195       password: password
196       fetch_body: 1
197       show_icon: 1
198       feed_type:
199         - FriendDiary
200         - FriendStatus
201         - RecentComment
202
203 =head1 DESCRIPTION
204
205 This plugin fetches your friend blog updates from livedoor Frepa
206 (L<http://frepa.livedoor.com/>) and creates a custom feed.
207
208 =head1 CONFIGURATION
209
210 See L<Plagger::Plugin::CustomFeed::Mixi> for C<fetch_body>,
211 C<fetch_body_interval> and C<show_icon>.
212
213 =head1 AUTHOR
214
215 Kazuhiro Osawa
216
217 Tokuhiro Matsuno
218
219 Tatsuhiko Miyagawa
220
221 =head1 SEE ALSO
222
223 L<Plagger>, L<Plagger::Plugin::CustomFeed::Mixi>, L<WWW::Mechanize>,
224 L<http://frepa.livedoor.com/>
225
226 =cut
Note: See TracBrowser for help on using the browser.