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

Revision 1712 (checked in by nipotan, 14 years ago)

treated for site renewal of frepa

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 Plagger::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} = Plagger::Mechanize->new(cookie_jar => $self->cookie_jar);
28
29     my $feed = Plagger::Feed->new;
30     $feed->aggregator(sub { $self->aggregate(@_) });
31     $context->subscription->add($feed);
32 }
33
34 sub aggregate {
35     my ($self, $context, $args) = @_;
36
37     unless ($self->login(livedoor_id => $self->conf->{livedoor_id}, password => $self->conf->{password})) {
38         $context->log(error => "Login to frepa failed.");
39         return;
40     }
41
42     $context->log(info => 'Login to frepa succeeded.');
43
44     my $feed_type = $self->conf->{feed_type} || [ qw(FriendDiary FriendStatus RecentComment) ];
45     for my $plugin (@$feed_type) {
46         my $plugin = (ref $self || $self) . "::$plugin";
47         $plugin->require or $context->error($@);
48         $self->aggregate_by_plugin($context, $plugin, $args);
49     }
50 }
51
52 sub aggregate_by_plugin {
53     my ($self, $context, $plugin, $args) = @_;
54
55     my $feed = Plagger::Feed->new;
56     $feed->type('frepa');
57     $feed->title($plugin->title);
58     $feed->link($plugin->start_url);
59
60     my $format = DateTime::Format::Strptime->new(pattern => '%Y/%m/%d %H:%M');
61
62     my @msgs = $plugin->get_list($self->{mech}, $self);
63     my $items = $self->conf->{fetch_items} || 20;
64
65     my $i = 0;
66     my $blocked = 0;
67     for my $msg (@msgs) {
68         last if $i++ >= $items;
69
70         my $entry = Plagger::Entry->new;
71         $entry->title($msg->{subject});
72         $entry->link($msg->{link});
73         $entry->author($msg->{name});
74         $entry->date( Plagger::Date->parse($format, $msg->{time}) );
75
76         if ($self->conf->{fetch_body} && !$blocked and $plugin->can('get_detail')) {
77             $context->log(info => "Fetch body from $msg->{link}");
78             my $item = $self->cache->get_callback(
79                 "item-$msg->{link}",
80                 sub {
81                     Time::HiRes::sleep( $self->conf->{fetch_body_interval} || 1.5 );
82                     $plugin->get_detail($msg->{link}, $self->{mech});
83                 },
84                 "1 hour",
85             );
86             if ($item) {
87                 my $body = $item->{description};
88                    $body =~ s!<br>!<br />!g;
89                 $entry->body($body);
90                 $entry->title($item->{subject}); # replace with full title
91             } else {
92                 $context->log(warn => "Fetch body failed. You might be blocked?");
93                 $blocked++;
94             }
95         }
96
97         if ($self->conf->{show_icon} && !$blocked) {
98             my $item = $self->fetch_icon($msg->{user_link});
99             if ($item && $item->{image} !~ /no_photo/) {
100                 $entry->icon({
101                     title => $item->{name},
102                     url   => $item->{image},
103                     link  => $msg->{user_link},
104                 });
105             }
106         }
107
108         $feed->add_entry($entry);
109     }
110
111     $context->update->add($feed);
112 }
113
114 sub fetch_icon {
115     my($self, $url) = @_;
116
117     Plagger->context->log(info => "Fetch icon from $url");
118     $self->cache->get_callback(
119         "icon-$url",
120         sub { $self->get_top($url) },
121         '1 day',
122     );
123 }
124
125 sub login {
126     my $self = shift;
127     my %args = @_;
128
129     my $start_url = 'http://www.frepa.livedoor.com/';
130     my $res = $self->{mech}->get($start_url);
131     return unless $self->{mech}->success;
132
133     if ($self->{mech}->content =~ /loginside/) {
134         unless ($args{livedoor_id} && $args{password}) {
135             Plagger->context->log(error => "Error logging in using existent Cookies. Your User-Agent (" . $self->{mech}->agent . ") should strictly match with the UA used with the Cookies.");
136             return;
137         }
138
139         Plagger->context->log(debug => "cookie not found. logging in");
140         $self->{mech}->submit_form(
141             fields => {
142                 livedoor_id => $args{livedoor_id},
143                 password    => $args{password},
144                 auto_login  => 'on',
145             },
146         );
147         $self->{mech}->submit;
148         return unless $self->{mech}->success;
149         return if $self->{mech}->content =~ /loginside/;
150     }
151
152     return 1;
153 }
154
155 sub get_top {
156     my $self = shift;
157     my $link = shift;
158
159     my $item = {};
160     my $res = $self->{mech}->get($link);
161     return $item unless $self->{mech}->success;
162
163     my $html = decode('euc-jp', $self->{mech}->content);
164
165     chomp( my $re  = decode('utf-8', $self->top_re) );
166     if ($html =~ /$re/s) {
167         $item->{image} = $1;
168         $item->{name}  = $2;
169     }
170
171     return $item;
172 }
173
174 sub top_re {
175     return <<'RE';
176 <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/)[^"]*?\.(?i:jpe?g|gif|png))" /></a>
177 <br /><a href=.+?
178 <div class="phframebtm"><h3>(.*?)..<span>\(\d+\)</span></h3></div>
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 Note that you don't have to supply livedoor_id and password if you set
214 global cookie_jar in your configuration file and the cookie_jar
215 contains a valid login session there, such as:
216
217   global:
218     user_agent:
219       cookies: /path/to/cookies.txt
220
221 See L<Plagger::Cookies> for details.
222
223
224 =head1 AUTHOR
225
226 Kazuhiro Osawa
227
228 Tokuhiro Matsuno
229
230 Tatsuhiko Miyagawa
231
232 =head1 SEE ALSO
233
234 L<Plagger>, L<Plagger::Plugin::CustomFeed::Mixi>, L<Plagger::Mechanize>,
235 L<http://frepa.livedoor.com/>
236
237 =cut
238
Note: See TracBrowser for help on using the browser.