題名の件をやろうとまず、以下のようなYAMLを書いた。
plugins:
- module: Subscription::Config
config:
feed:
- http://b.hatena.ne.jp/t/shibuya.pm?mode=rss
- module: Publish::OPML
config:
title: Shibuya.pm
filename: shibuya-pm.opml
で実行したけれどOPMLが空っぽ。ソースを追ってBreakEntriesToFeedsが使えそうだったので以下の行を足した。
- module: Filter::BreakEntriesToFeeds
config:
use_entry_title: 1
でも駄目。で、miyagawaさんにメールした。なぜか英語で...余談 : なぜ英語かmiyagawaさんから、「use BreakEntriesToFeeds」と返事が来たけど、「BreakEntriesToFeeds」は1 entryを1 feedに変換する為のプラグインで、subscriptionを変更するものでは無かった。
以前、Web::Scraperについて質問メールを送った。でも反応が無かったので物は試しと英語で書いた。そしたら返事が返って来た。
→ 以後英語... orz
で、書きあげたのが以下のプラグイン
BreakEntriesToSubscriptions.pm
package Plagger::Plugin::Filter::BreakEntriesToSubscriptions;
use strict;
use base qw( Plagger::Plugin );
sub register {
my($self, $context) = @_;
$context->register_hook(
$self,
'update.feed.fixup' => \&break,
);
}
sub break {
my($self, $context, $args) = @_;
for my $entry ($args->{feed}->entries) {
my $feed = $args->{feed}->clone;
$feed->clear_entries;
$feed->add_entry($entry);
$feed->link($entry->link);
$feed->url($entry->link);
eval {
use HTML::TokeParser;
my $agent = Plagger::UserAgent->new;
my $res = $agent->fetch($entry->link, $self);
my $parser = HTML::TokeParser->new(\$res->content);
while (my $token = $parser->get_tag("link")) {
my $attr = $token->[1];
if ($attr->{rel} eq 'alternate'
&& ($attr->{type} eq 'application/rss+xml'
or $attr->{type} eq 'application/atom+xml')) {
$feed->url(URI->new_abs($attr->{href}, $entry->link)-> as_string);
last;
}
}
} if $self->conf->{use_auto_discovery};
$feed->title($entry->title)
if $self->conf->{use_entry_title};
$context->subscription->add($feed);
}
$context->subscription->delete_feed($args->{feed});
}
1;
__END__
=head1 NAME
Plagger::Plugin::Filter::BreakEntriesToSubscriptions - some entry = 1 subscription
=head1 SYNOPSIS
- module: Filter::BreakEntriesToSubscriptions
=head1 DESCRIPTION
This plugin breaks all the subscription entries into a single feed. This is
a fairly hackish plugin but it's helpful for make OPML from feeds.
=head1 CONFIG
=over 4
=item use_entry_title
Use subscription's title as a newly generated feed title. Defaults to 0.
=back
=head1 AUTHOR
Yasuhiro Matsumoto
=head1 THANKS
Tatsuhiko Miyagawa
=head1 SEE ALSO
L<Plagger>
=cut
ドキュメントにも書いた通り、ちょっと(かなり?)hackishなプラグインです。このプラグインを使って
shibuya-pm2opml.yaml
plugins:
- module: Subscription::Config
config:
feed:
- http://b.hatena.ne.jp/t/shibuya.pm?mode=rss
- module: Filter::BreakEntriesToSubscriptions
config:
use_entry_title: 1
use_auto_discovery: 1
- module: Publish::OPML
config:
title: Shibuya.pm
filename: shibuya-pm.opml
こんなYAMLを用意すれば
「Shibuya.pm」のタグが付いている「はてなブックマーク」からオートディスカバリでフィードを取得したOPMLこんなOPMLファイルが出来上がります。
miyagawaさんに感謝
おしまい
※もしかしたらオートディスカバリ出来なかったURL(例えばPDFとか)はOPMLに含めないようにするオプションがいるかも...