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

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

store guid to permalinK

  • Property svn:keywords set to Id Revision
Line 
1 package Plagger::Plugin::Subscription::Bloglines;
2 use strict;
3 use base qw( Plagger::Plugin );
4
5 our $VERSION = '0.10';
6 use WebService::Bloglines;
7
8 sub plugin_id {
9     my $self = shift;
10     $self->class_id . '-' . $self->conf->{username};
11 }
12
13 sub register {
14     my($self, $context) = @_;
15
16     $self->init_bloglines();
17
18     if ($self->conf->{no_sync_api}) {
19         $context->register_hook(
20             $self,
21             'subscription.load' => \&getsubs,
22         );
23     } else {
24         $context->register_hook(
25             $self,
26             'subscription.load' => \&notifier,
27         );
28     }
29 }
30
31 sub getsubs {
32     my($self, $context) = @_;
33     my $subscription = $self->{bloglines}->listsubs();
34
35     for my $folder ($subscription->folders, 0) {
36         my $subid = $folder ? $folder->{BloglinesSubId} : 0;
37         my $title = $folder ? $folder->{title} : undef;
38         $self->add_subscription($subscription, $subid, $title);
39     }
40 }
41
42 sub add_subscription {
43     my($self, $subscription, $subid, $title) = @_;
44
45     my @feeds = $subscription->feeds_in_folder($subid);
46     for my $source (@feeds) {
47         my $feed = Plagger::Feed->new;
48         $feed->title($source->{title});
49         $feed->link($source->{htmlUrl});
50         $feed->url($source->{xmlUrl} );
51         $feed->tags([ $title ]) if $title;
52         Plagger->context->subscription->add($feed);
53     }
54 }
55
56 sub init_bloglines {
57     my $self = shift;
58     $self->{bloglines} = WebService::Bloglines->new(
59         username => $self->conf->{username},
60         password => $self->conf->{password},
61         use_liberal => 1,
62     );
63 }
64
65 sub notifier {
66     my($self, $context) = @_;
67
68     my $count = $self->{bloglines}->notify();
69     $context->log(info => "You have $count unread item(s) on Bloglines.");
70     if ($count) {
71         my $feed = Plagger::Feed->new;
72         $feed->aggregator(sub { $self->sync(@_) });
73         $context->subscription->add($feed);
74
75         if ($self->conf->{fetch_meta}) {
76             $self->{bloglines_meta} = $self->cache->get_callback(
77                 'listsubs_meta',
78                 sub { $self->fetch_meta($context) },
79                 '1 day',
80             );
81         }
82     }
83 }
84
85 sub fetch_meta {
86     my($self, $context) = @_;
87
88     $self->{folders} = {};
89     $context->log(info => "call Bloglines listsubs API to get folder structure");
90
91     my $subscription = $self->{bloglines}->listsubs();
92
93     my $meta;
94     for my $folder ($subscription->folders, 0) {
95         my $subid = ref $folder ? $folder->{BloglinesSubId} : 0;
96         my @feeds = $subscription->feeds_in_folder($subid);
97         for my $feed (@feeds) {
98             $meta->{$feed->{htmlUrl}} = {
99                 folder => $folder ? $folder->{title} : undef,
100                 xmlUrl => $feed->{xmlUrl},
101                 subid  => $feed->{BloglinesSubId},
102             };
103         }
104     }
105
106     $meta;
107 }
108
109 sub sync {
110     my($self, $context, $args) = @_;
111
112     my $mark_read = $self->conf->{mark_read};
113        $mark_read = 1 unless defined $mark_read;
114
115     my @updates;
116
117     # catch bad XML feed by Bloglines
118     eval {
119         @updates = $self->{bloglines}->getitems(0, $mark_read);
120     };
121
122     if ($@) {
123         $context->log(warn => "Bloglines Sync API returned bad XML. fallbacks to loop mode");
124         my @feeds = $self->{bloglines}->listsubs()->feeds;
125         for my $feed (@feeds) {
126             if ($feed->{BloglinesUnread}) {
127                 $context->log(debug => "Fetch $feed->{BloglinesSubId}");
128                 push @updates, eval { $self->{bloglines}->getitems($feed->{BloglinesSubId}, $mark_read) };
129             }
130         }
131     }
132
133     $context->log(info => scalar(@updates) . " feed(s) updated.");
134
135     for my $update (@updates) {
136         my $source = $update->feed;
137
138         my $feed = Plagger::Feed->new;
139         $feed->type('bloglines');
140         $feed->title($source->{title});
141         $feed->link($source->{link});
142         $feed->image($source->{image});
143         $feed->description($source->{description});
144         $feed->language($source->{language});
145         $feed->author($source->{webmaster});
146         $feed->meta->{bloglines_id} = $source->{bloglines}->{siteid};
147
148         # under fetch_pfolders option, set folder as tags to feeds
149         if (my $meta = $self->{bloglines_meta}->{$feed->link}) {
150             $feed->tags([ $meta->{folder} ]) if $meta->{folder};
151             $feed->url($meta->{xmlUrl});
152             $feed->meta->{bloglines_subid} = $meta->{subid};
153         }
154
155         $feed->source_xml($update->{_xml});
156
157         for my $item ( $update->items ) {
158             my $entry = Plagger::Entry->new;
159
160             $entry->title($item->{title});
161             $entry->author($item->{dc}->{creator});
162             $entry->tags([ $item->{dc}->{subject} ])
163                 if $item->{dc}->{subject};
164             $entry->date( Plagger::Date->parse('Mail', $item->{pubDate}) );
165             $entry->link($item->{link});
166             $entry->permalink($item->{guid}) if $item->{guid};
167             $entry->feed_link($feed->link);
168             $entry->id($item->{guid});
169
170             $entry->body($item->{description});
171
172             $feed->add_entry($entry);
173         }
174
175         $context->update->add($feed);
176     }
177 }
178
179 1;
180
181 __END__
182
183 =head1 NAME
184
185 Plagger::Plugin::Subscription::Bloglines - Bloglines Subscription
186
187 =head1 SYNOPSIS
188
189   - module: Subscription::Bloglines
190     config:
191       username: your-email@account
192       password: your-password
193       mark_read: 1
194
195 =head1 DESCRIPTION
196
197 This plugin allows you to synchronize your subscription using
198 Bloglines Web Services sync API.
199
200 =head1 CONFIGURATION
201
202 =over 4
203
204 =item username, password
205
206 Your username & password to use with Bloglines API.
207
208 =item mark_read
209
210 C<mark_read> specifies whether this plugin I<marks as read> the items
211 you synchronize. With this option set to 0, you will get the
212 duplicated updates everytime you run Plagger, until you mark them
213 unread using Bloglines browser interface. Defaults to 1.
214
215 For people who uses Bloglines browser interface regularly, and use
216 Plagger as a tool to synchronize feed updates to mobile devices (like
217 PSP or iPod), I'd recommend set this option to 0.
218
219 Otherwise, especially for Publish::Gmail plugin users, I recommend set
220 to 1, the default.
221
222 =item fetch_meta
223
224 C<fetch_meta> specifies whether this plugin fetches I<folder>
225 strucuture using listsubs API. With this option on, all feeds under
226 I<Plagger> folder will have I<Plagger> as its tag.
227
228 You can use this tags information using Rules in later phase.
229
230 =back
231
232 =head1 AUTHOR
233
234 Tatsuhiko Miyagawa
235
236 =head1 SEE ALSO
237
238 L<Plagger>, L<WebService::Bloglines>, L<http://www.bloglines.com/>
239
240 =cut
241
Note: See TracBrowser for help on using the browser.