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

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

fix permalink stuff again

  • 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
167             if ($item->{guid}) {
168                 my $is_permalink = $item->{guid}->{isPermaLink};
169                 my $guid_url     = "$item->{guid}"; # stringify MagicElement
170                 $entry->permalink($guid_url)
171                     if $guid_url =~ m!^https?://! && $is_permalink eq 'true';
172             }
173
174             $entry->feed_link($feed->link);
175             $entry->id($item->{guid});
176             $entry->body($item->{description});
177
178             $feed->add_entry($entry);
179         }
180
181         $context->update->add($feed);
182     }
183 }
184
185 1;
186
187 __END__
188
189 =head1 NAME
190
191 Plagger::Plugin::Subscription::Bloglines - Bloglines Subscription
192
193 =head1 SYNOPSIS
194
195   - module: Subscription::Bloglines
196     config:
197       username: your-email@account
198       password: your-password
199       mark_read: 1
200
201 =head1 DESCRIPTION
202
203 This plugin allows you to synchronize your subscription using
204 Bloglines Web Services sync API.
205
206 =head1 CONFIGURATION
207
208 =over 4
209
210 =item username, password
211
212 Your username & password to use with Bloglines API.
213
214 =item mark_read
215
216 C<mark_read> specifies whether this plugin I<marks as read> the items
217 you synchronize. With this option set to 0, you will get the
218 duplicated updates everytime you run Plagger, until you mark them
219 unread using Bloglines browser interface. Defaults to 1.
220
221 For people who uses Bloglines browser interface regularly, and use
222 Plagger as a tool to synchronize feed updates to mobile devices (like
223 PSP or iPod), I'd recommend set this option to 0.
224
225 Otherwise, especially for Publish::Gmail plugin users, I recommend set
226 to 1, the default.
227
228 =item fetch_meta
229
230 C<fetch_meta> specifies whether this plugin fetches I<folder>
231 strucuture using listsubs API. With this option on, all feeds under
232 I<Plagger> folder will have I<Plagger> as its tag.
233
234 You can use this tags information using Rules in later phase.
235
236 =back
237
238 =head1 AUTHOR
239
240 Tatsuhiko Miyagawa
241
242 =head1 SEE ALSO
243
244 L<Plagger>, L<WebService::Bloglines>, L<http://www.bloglines.com/>
245
246 =cut
247
Note: See TracBrowser for help on using the browser.