複数のfeedをマージするには

Plaggerを使う場合、以下のyamlを作成すればよい。

plugins:
  - module: Subscription::Config
    config:
      feed:
        - http://www.ibm.com/news/jp/ja/index.rss
        - http://h50205.www5.hp.com/rss/w_new.xml
        - http://wdirect.apple.com/jp/home/2008/ticker.rss

  - module: SmartFeed::All

  - module: Publish::Feed
    config:
      format: RSS
      dir: /tmp
      filename: merged_rss.xml

で、これだと指定した3フィードが時刻の新しい順に並ぶ。
これをたとえば、IBM、HP、Appleの各最新記事、IBM、HP、Appleの各2番目の最新記事、以下同様、という順番にしたいときはどうするか?

Plagger::Feedを読んだら、エントリのソート方法をカスタマイズする手段はまだないようなので、Plagger::Plugin::SmartFeed::Allのサブクラスを作成することにした。

plugins:
  - module: Subscription::Config
    config:
      feed:
        - http://www.ibm.com/news/jp/ja/index.rss
        - http://h50205.www5.hp.com/rss/w_new.xml
        - http://wdirect.apple.com/jp/home/2008/ticker.rss

  - module: SmartFeed::Rotate

  - module: Publish::Feed
    config:
      format: RSS
      dir: /tmp
      filename: rotate_merged_rss.xml

All.pmのサブクラスRotate.pmは以下の通り。

package Plagger::Plugin::SmartFeed::Rotate;
use strict;
use base qw( Plagger::Plugin::SmartFeed::All );

sub feed_finalize {
  my($self, $context, $args) = @_;
  $self->{feed} = rotate_sort($self->{feed});
  $context->update->add($self->{feed}) if $self->{feed}->count;
}
#
# 各ホストを巡回するかたちでソート
#
sub rotate_sort {
  my $feed = shift;
  my @entries = map { $_->[2] }
    sort { $a->[0] <=> $b->[0] || $b->[1] <=> $a->[1] }
    map { [ _seq_by_host($_), $_ ] } $feed->entries;
  $feed->{entries} = \@entries;
  $feed;
}
#
# エントリのホスト別連番とホスト名を返す
#
sub _seq_by_host {
  my $entry = shift;
  our %seq;
  my $u = URI->new($entry->source->url);
  my $host = lc($u->host);
  $seq{$host}++;
  my @a = ($seq{$host}, $host);
}

1;