| Plagger documentation | Contained in the Plagger distribution. |
Plagger::Plugin::Subscription::Bloglines - Bloglines Subscription
- module: Subscription::Bloglines
config:
username: your-email@account
password: your-password
mark_read: 1
This plugin allows you to synchronize your subscription using Bloglines Web Services sync API.
Your username & password to use with Bloglines API.
mark_read specifies whether this plugin marks as read the items
you synchronize. With this option set to 0, you will get the
duplicated updates every time you run Plagger, until you mark them
unread using Bloglines browser interface. Defaults to 1.
For people who uses Bloglines browser interface regularly, and use Plagger as a tool to synchronize feed updates to mobile devices (like PSP or iPod), I'd recommend set this option to 0.
Otherwise, especially for Publish::Gmail plugin users, I recommend set to 1, the default.
fetch_meta specifies whether this plugin fetches folder
structure using listsubs API. With this option on, all feeds under
Plagger folder will have Plagger as its tag.
You can use this tags information using Rules in later phase.
Turn it on when you want to skip Notifier API, which could sometimes be broken and always returns 0 instead of the actual unread count.
Tatsuhiko Miyagawa
| Plagger documentation | Contained in the Plagger distribution. |
package Plagger::Plugin::Subscription::Bloglines; use strict; use base qw( Plagger::Plugin ); our $VERSION = '0.10'; use WebService::Bloglines; sub plugin_id { my $self = shift; $self->class_id . '-' . $self->conf->{username}; } sub register { my($self, $context) = @_; $self->init_bloglines(); if ($self->conf->{no_sync_api}) { $context->register_hook( $self, 'subscription.load' => \&getsubs, ); } else { $context->register_hook( $self, 'subscription.load' => \¬ifier, ); } } sub getsubs { my($self, $context) = @_; my $subscription = $self->{bloglines}->listsubs(); for my $folder ($subscription->folders, 0) { my $subid = $folder ? $folder->{BloglinesSubId} : 0; my $title = $folder ? $folder->{title} : undef; $self->add_subscription($subscription, $subid, $title); } } sub add_subscription { my($self, $subscription, $subid, $title) = @_; my @feeds = $subscription->feeds_in_folder($subid); for my $source (@feeds) { my $feed = Plagger::Feed->new; $feed->title($source->{title}); $feed->link($source->{htmlUrl}); $feed->url($source->{xmlUrl} ); $feed->tags([ $title ]) if $title; Plagger->context->subscription->add($feed); } } sub init_bloglines { my $self = shift; $self->{bloglines} = WebService::Bloglines->new( username => $self->conf->{username}, password => $self->conf->{password}, use_liberal => 1, ); } sub notifier { my($self, $context) = @_; my $to_fetch = $self->conf->{dont_use_notifier_api}; unless ($to_fetch) { my $count = $self->{bloglines}->notify(); $context->log(info => "You have $count unread item(s) on Bloglines."); $to_fetch = $count; } if ($to_fetch) { my $feed = Plagger::Feed->new; $feed->aggregator(sub { $self->sync(@_) }); $context->subscription->add($feed); if ($self->conf->{fetch_meta}) { $self->{bloglines_meta} = $self->cache->get_callback( 'listsubs_meta', sub { $self->fetch_meta($context) }, '1 day', ); } } } sub fetch_meta { my($self, $context) = @_; $self->{folders} = {}; $context->log(info => "call Bloglines listsubs API to get folder structure"); my $subscription = $self->{bloglines}->listsubs(); my $meta; for my $folder ($subscription->folders, 0) { my $subid = ref $folder ? $folder->{BloglinesSubId} : 0; my @feeds = $subscription->feeds_in_folder($subid); for my $feed (@feeds) { $meta->{$feed->{htmlUrl}} = { folder => $folder ? $folder->{title} : undef, xmlUrl => $feed->{xmlUrl}, subid => $feed->{BloglinesSubId}, }; } } $meta; } sub sync { my($self, $context, $args) = @_; my $mark_read = $self->conf->{mark_read}; $mark_read = 1 unless defined $mark_read; my @updates; # catch bad XML feed by Bloglines eval { @updates = $self->{bloglines}->getitems(0, 0); }; if ($@) { $context->log(warn => "Bloglines Sync API returned bad XML. fallbacks to loop mode: $@"); my @feeds = $self->{bloglines}->listsubs()->feeds; for my $feed (@feeds) { if ($feed->{BloglinesUnread}) { $context->log(debug => "Fetch $feed->{BloglinesSubId}"); push @updates, eval { $self->{bloglines}->getitems($feed->{BloglinesSubId}, $mark_read) }; } } } elsif ($mark_read) { # no error found with XML ... call the API again to mark read eval { @updates = $self->{bloglines}->getitems(0, $mark_read); }; } $context->log(info => scalar(@updates) . " feed(s) updated."); for my $update (@updates) { my $source = $update->feed; my $feed = Plagger::Feed->new; $feed->type('bloglines'); $feed->title($source->{title}); $feed->link($source->{link}); $feed->image($source->{image}); $feed->description($source->{description}); $feed->language($source->{language}); $feed->author($source->{webmaster}); $feed->meta->{bloglines_id} = $source->{bloglines}->{siteid}; # under fetch_pfolders option, set folder as tags to feeds if (my $meta = $self->{bloglines_meta}->{$feed->link}) { $feed->tags([ $meta->{folder} ]) if $meta->{folder}; $feed->url($meta->{xmlUrl}); $feed->meta->{bloglines_subid} = $meta->{subid}; } $feed->source_xml($update->{_xml}); for my $item ( $update->items ) { my $entry = Plagger::Entry->new; $entry->title($item->{title}); $entry->author($item->{dc}->{creator}); $entry->tags([ $item->{dc}->{subject} ]) if $item->{dc}->{subject}; $entry->date( Plagger::Date->parse('Mail', $item->{pubDate}) ); $entry->link($item->{link}); if ($item->{guid}) { my $is_permalink = eval { $item->{guid}->{isPermaLink} } || 'false'; my $guid_url = "$item->{guid}"; # stringify MagicElement $entry->permalink($guid_url) if $guid_url =~ m!^https?://! && $is_permalink eq 'true'; } $entry->feed_link($feed->link); $entry->id($item->{guid}); $entry->body($item->{description}); if ($item->{enclosure}) { my $enclosure = Plagger::Enclosure->new; $enclosure->url( URI->new($item->{enclosure}->{url}) ); $enclosure->length($item->{enclosure}->{length}); $enclosure->auto_set_type($item->{enclosure}->{type}); $entry->add_enclosure($enclosure); } $feed->add_entry($entry); } $context->update->add($feed); } } 1; __END__