SweetPotato::Plagger このページをアンテナに追加 RSSフィード

2007-03-31

[] Subscription::WWWC  Subscription::WWWC - SweetPotato::Plagger を含むブックマーク はてなブックマーク -  Subscription::WWWC - SweetPotato::Plagger  Subscription::WWWC - SweetPotato::Plagger のブックマークコメント

WWWCのデータディレクトリを読み込み,アイテムごとにフィード化する。

WWWCバージョン1.0.4にて動作確認。それ以前のバージョンについては動作未確認。

Plagger/Plugin/Subscription/WWWC.pm

package Plagger::Plugin::Subscription::WWWC;
use strict;
use base qw( Plagger::Plugin );

use Clone qw( clone );
use Config::Simple;
use Encode;
use File::Spec;
use IO::File;

sub register {
    my ($self, $context) = @_;
    $context->register_hook(
        $self,
        'subscription.load' => \&load,
    );
}

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

    return unless $self->conf->{dir};
    my @leaves = $self->leaves($self->branch($context, $self->conf->{dir}));

    for my $leaf (@leaves) {
        my $feed = Plagger::Feed->new;
        $feed->url($leaf->{check_url});
        $feed->title($leaf->{title});
        $feed->link($leaf->{view_url} || $leaf->{check_url});
        $feed->meta($leaf->{meta});

        $context->subscription->add($feed);
    }
}

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

    # meta
    my $ini = Config::Simple->new(File::Spec->catfile($dir, 'Folder.ini'));
    my $meta = {
        wwwc_check_st => $ini->param('CHECK.CheckSt'),
    };
    undef $ini;

    # dirs
    opendir DIR, $dir or $context->error("can't open directory: $dir");
    my @dirs = map  { $self->branch($context, $_) }
               grep { -d $_ }
               map  { File::Spec->catfile($dir, $_) }
               grep { $_ ne '.' and $_ ne '..' }
               readdir DIR;
    closedir DIR;

    # items
    my $io = IO::File->new(File::Spec->catfile($dir, 'Item.dat'));
    my @items = map { $self->item($_) } $io->getlines;
    $io->close;
    undef $io;

    return {
        meta  => $meta,
        dirs  => \@dirs,
        items => \@items,
    };
}

sub item {
    my ($self, $record) = @_;

    chomp $record;
    my @fields = split /\t/, $record;

    return {
        title     => Encode::decode('cp932', $fields[0]),
        check_url => $fields[1],
        view_url  => $fields[8],
        meta => {
            wwwc_check_st => $fields[12],
        },
    };
}

sub leaves {
    my ($self, $branch) = @_;

    my @leaves = ();
    push @leaves, $self->leaves($_) for @{$branch->{dirs}};
    push @leaves, map {
        my $leaf = clone($_);
        $leaf->{meta}->{wwwc_check_st} ||= $branch->{meta}->{wwwc_check_st};
        $leaf;
    } @{$branch->{items}};

    @leaves;
}

1;

WWWCにおける階層構造は無視される。

各フィードにはメタ情報 wwwc_check_st がセットされる。対応するアイテムがWWWCにおいてチェックされる場合(アイテムそれ自身,およびそれが含まれるディレクトリが,ともに「チェックする」状態の場合)は0が,そうでない場合は1がセットされる。0と1,それぞれが表す状態が直感と異なるのは,WWWCの実装に合わせた結果である。

config.wwwc.yaml

plugins:
  - module: Subscription::WWWC
    config:
      dir: C:\Program Files\WWWC\username\newssite
  - module: Filter::Rule
    rule:
#     expression: !$args->{feed}->meta->{wwwc_check_st}
      expression: $args->{feed}->meta->{wwwc_check_st} == 0

dir にはWWWCのデータディレクトリへのパスを指定する。dir 以下(サブディレクトリも)に含まれる全てのアイテムがフィード化される。

dir には必ずしもルートに相当するデータディレクトリ(上記例では C:\Program Files\WWWC\username がルート)を指定しなくてもよい。

dir に日本語を含むパスを指定する場合のテストは不十分である。自分の環境(Win2k,ActivePerl 5.8.8 Build 819,Plagger 0.7.16)では,configファイルをUTF-8ではなくシフトJISで保存するとうまくいくようである。

WWWCにおいてはチェックされないアイテムに対応するフィード(のエントリ)を除外したい場合は,Filter::Ruleを上記のように使用する。

expressionがうまく動かなかったので書き替えた。

TODO

WWWCのデータディレクトリ解析部だけ別モジュールにして再利用できそう。WWWC2XBELも作りたいなあ。

あとWWWC関連だと,WWWCのフィルタを読み込んでPlaggerで利用するモジュールもあるといいかも。Filter::WWWCかな。

さらにFilter::Diffも合わせれば,既存のデータを移行することなく,しかもWWWCのフィルタ機能を利用した似非はてなアンテナが作れそう。うわー夢が広がるわー。

トラックバック - http://plagger.g.hatena.ne.jp/SweetPotato/20070331