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

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

oops, syntax error

  • Property svn:keywords set to Id Revision
Line 
1 package Plagger::Plugin::CustomFeed::Mixi;
2 use strict;
3 use base qw( Plagger::Plugin );
4
5 use DateTime::Format::Strptime;
6 use Encode;
7 use WWW::Mixi;
8 use Time::HiRes;
9
10 sub register {
11     my($self, $context) = @_;
12     $context->register_hook(
13         $self,
14         'subscription.load' => \&load,
15     );
16 }
17
18 sub load {
19     my($self, $context) = @_;
20     $self->{mixi} = WWW::Mixi->new($self->conf->{email}, $self->conf->{password});
21     $self->{mixi}->cookie_jar($self->cache->cookie_jar);
22
23     my $feed = Plagger::Feed->new;
24        $feed->aggregator(sub { $self->aggregate(@_) });
25     $context->subscription->add($feed);
26 }
27
28 sub aggregate {
29     my($self, $context, $args) = @_;
30
31     my $start_url = 'http://mixi.jp/new_friend_diary.pl';
32     my $response  = $self->{mixi}->get($start_url);
33
34     if ($response->content =~ /action=login\.pl/) {
35         $context->log(debug => "Cookie not foud. Logging in");
36         $response = $self->{mixi}->post("http://mixi.jp/login.pl", {
37             next_url => "/new_friend_diary.pl",
38             email    => $self->conf->{email},
39             password => $self->conf->{password},
40             sticky   => 'on',
41         });
42         if (!$response->is_success || $response->content =~ /action=login\.pl/) {
43             $context->log(error => "Login failed.");
44             return;
45         }
46
47         # meta refresh, ugh!
48         if ($response->content =~ m!"0;url=(.*?)"!) {
49             $response = $self->{mixi}->get($1);
50         }
51     }
52
53     my $feed = Plagger::Feed->new;
54     $feed->type('mixi');
55     $feed->title('マイミクシィ最新日記');
56     $feed->link('http://mixi.jp/new_friend_diary.pl');
57
58     my $format = DateTime::Format::Strptime->new(pattern => '%Y/%m/%d %H:%M');
59
60     my @msgs = $self->{mixi}->parse_new_friend_diary($response);
61     my $items = $self->conf->{fetch_items} || 20;
62
63     my $i = 0;
64     my $blocked = 0;
65     for my $msg (@msgs) {
66         next unless $msg->{image}; # external blog
67         last if $i++ >= $items;
68
69         my $entry = Plagger::Entry->new;
70         $entry->title( decode('euc-jp', $msg->{subject}) );
71         $entry->link($msg->{link});
72         $entry->author( decode('euc-jp', $msg->{name}) );
73         $entry->date( Plagger::Date->parse($format, $msg->{time}) );
74
75         if ($self->conf->{show_icon} && !$blocked) {
76             my $owner_id = ($msg->{link} =~ /owner_id=(\d+)/)[0];
77             my $link = "http://mixi.jp/show_friend.pl?id=$owner_id";
78             $context->log(info => "Fetch icon from $link");
79
80             my $item = $self->cache->get_callback(
81                 "outline-$owner_id",
82                 sub {
83                     Time::HiRes::sleep( $self->conf->{fetch_body_interval} || 1.5 );
84                     my($item) = $self->{mixi}->get_show_friend_outline($link);
85                     $item;
86                 },
87                 '12 hours',
88             );
89             if ($item && $item->{image} !~ /no_photo/) {
90                 # prefer smaller image
91                 my $image = $item->{image};
92                    $image =~ s/\.jpg$/s.jpg/;
93                 $entry->icon({
94                     title => decode('euc-jp', $item->{name}),
95                     url   => $image,
96                     link  => $link,
97                 });
98             }
99         }
100
101         if ($self->conf->{fetch_body} && !$blocked && $msg->{link} =~ /view_diary/) {
102             $context->log(info => "Fetch body from $msg->{link}");
103             my $item = $self->cache->get_callback(
104                 "item-$msg->{link}",
105                 sub {
106                     Time::HiRes::sleep( $self->conf->{fetch_body_interval} || 1.5 );
107                     my($item) = $self->{mixi}->get_view_diary($msg->{link});
108                     $item;
109                 },
110                 '1 hour',
111             );
112             if ($item) {
113                 my $body = decode('euc-jp', $item->{description});
114                    $body =~ s!\n!<br />!g;
115                 for my $image (@{ $item->{images} }) {
116                     # xxx this should be $entry->enclosures
117                     $body .= qq(<div><a href="$image->{link}"><img src="$image->{thumb_link}" style="border:0" /></a></div>);
118                 }
119                 $entry->body($body);
120             } else {
121                 $context->log(warn => "Fetch body failed. You might be blocked?");
122                 $blocked++;
123             }
124         }
125
126         $feed->add_entry($entry);
127     }
128
129     $context->update->add($feed);
130 }
131
132 1;
133
134 __END__
135
136 =head1 NAME
137
138 Plagger::Plugin::CustomFeed::Mixi -  Custom feed for mixi.jp
139
140 =head1 SYNOPSIS
141
142     - module: CustomFeed::Mixi
143       config:
144         email: email@example.com
145         password: password
146         fetch_body: 1
147         show_icon: 1
148
149 =head1 DESCRIPTION
150
151 This plugin fetches your friends diary updates from mixi
152 (L<http://mixi.jp/>) and creates a custom feed.
153
154 =head1 CONFIGURATION
155
156 =over 4
157
158 =item email, password
159
160 Credential you need to login to mixi.jp.
161
162 =item fetch_body
163
164 With this option set, this plugin fetches entry body HTML, not just a
165 link to the entry. Defaults to 0.
166
167 =item fetch_body_interval
168
169 With C<fetch_body> option set, your Plagger script is recommended to
170 wait for a little, to avoid mixi.jp throttling. Defaults to 1.5.
171
172 =item show_icon: 1
173
174 With this option set, this plugin fetches users buddy icon from
175 mixi.jp site, which makes the output HTML very user-friendly.
176
177 =back
178
179 =head1 SCREENSHOT
180
181 L<http://blog.bulknews.net/mt/archives/plagger-mixi-icon.gif>
182
183 =head1 AUTHOR
184
185 Tatsuhiko Miyagawa
186
187 =head1 SEE ALSO
188
189 L<Plagger>, L<WWW::Mixi>
190
191 =cut
Note: See TracBrowser for help on using the browser.