CustomFeed::DBIC

(更新) Subscription::DBIC を CustomFeed::DBIC に修正。
(追記) ID DESC 順にソートするように直しました。

データベースにストアされてるフィードからデータを引っこ抜いて入力にするプラグイン。Subscription::DBI にエントリー取得部分を付け足しただけです。Subscription::DBI はエントリー自体は DB から取得してくれませんが、こちらはエントリーも DB から取得します。

フィードやエントリーの取り出し条件を指定する機能があると便利だと思うのけど、いまのところスマートな方法が思いついていません。今は最新のエントリから max_entries 個を取り出します。

Package Plagger::Plugin::CustomFeed::DBIC;
use strict;
use base qw( Plagger::Plugin Class::Accessor::Fast);

__PACKAGE__->mk_accessors(qw/schema/);

sub register {
    my ( $self, $context ) = @_;

    unless ( $self->conf->{schema_class} and $self->conf->{connect_info} ) {
        $context->error('schema_class and connect_info are required');
    }

    $self->conf->{schema_class}->require
        or $context->error(
        qq/Can't load schema class "@{[ $self->conf->{schema_class} ]}", $!/);

    $self->schema( $self->conf->{schema_class}
            ->connect( @{ $self->conf->{connect_info} } ) );

    $context->register_hook( $self, 'subscription.load' => \&load, );

    $self->conf->{max_entries} ||= 10;
}

sub load {
    my ( $self, $context ) = @_;

    my $rs = $self->schema->resultset('Feed')->search();

    while ( my $rs_feed = $rs->next ) {
        my $feed = Plagger::Feed->new;
        $feed->url( $rs_feed->url )     if $rs_feed->url;
        $feed->link( $rs_feed->link )   if $rs_feed->link;
        $feed->title( $rs_feed->title ) if $rs_feed->title;

        eval {
           my $rs_entries = $self->schema->resultset('Entry')->search(
               { feed => $rs_feed->id, },
               { page => 1,
                 rows => $self->conf->{max_entries},
                 order_by => 'id DESC',
               },
           );

           while ( my $rs_entry = $rs_entries->next ) {
               $context->log( debug => "link : " . $rs_entry->link);
               my $entry = Plagger::Entry->new;

               $entry->title($rs_entry->title) if $rs_entry->title;
               $entry->author($rs_entry->author) if $rs_entry->author;
               if (my $rs_tag = $rs_entry->tags) {
                   while (my $tag = $rs_tag->next) {
                       $entry->tags([ $tag->name ]);
                       $feed->tags( [ $tag->name ] );
                   }
               }

               $entry->date($rs_entry->date) if $rs_entry->date;
               $entry->link($rs_entry->link) if $rs_entry->link;
               $entry->feed_link($feed->link) if $feed->link;
               $entry->id($rs_entry->id) if $rs_entry->id;
               $entry->summary($rs_entry->summary) if $rs_entry->summary;
               $entry->body($rs_entry->body) if $rs_entry->body;
               $entry->rate($rs_entry->rate) if $rs_entry->rate;
               $entry->icon($rs_entry->icon) if $rs_entry->icon;
#              $entry->meta($rs_entry->meta) if $rs_entry->meta;
#              $entry->source($rs_entry->source) if $rs_entry->source;
               $feed->add_entry($entry);
           }
        };

        $context->log(debug => "feed has ". $feed->count . " entries");
        $context->update->add($feed);
    }
}
1;
  • レシピ例:DB に貯めたエントリーから100個を RSS 化。
global:
  timezone: Asia/Tokyo

plugins:
  - module: CustomFeed::DBIC
    config:
      schema_class: Plagger::Schema::SQLite
      connect_info: [ 'DBI:SQLite:/home/nirvash/data/comment_filter.db', ]
      max_entries: 100

  - module: Publish::Feed
    config:
      format: RSS
      dir: /home/nirvash/www/rss
      filename: comment_rss.rss

更新頻度が高いデータの場合、RSS リーダーが巡回する前に上書きしてしまうので、こんなことをやっています。LDR で直接読んだらいいのだけど、まだ PlaggerLDR の CGI 版が動かないのでとりあえず。→ CGI 版が動いたのだけど公開用に RSS を作成するのに利用中。