Hatena::Groupsubtech

ういはるかぜの化学

Sunday, October 29, 2006

[]Plagger::Plugin::Filter::Diff 20:08 Plagger::Plugin::Filter::Diff - ういはるかぜの化学 を含むブックマーク はてなブックマーク - Plagger::Plugin::Filter::Diff - ういはるかぜの化学

前回取得したものと今回取得したものの差分をとるフィルタ、というのがあればはてなアンテナアレみたいなのを簡単に作れそうかも。

というか、EntryFullText で asset を書くのが面倒(大量にあるとか)で書いてなくて毎度丸ごとページを取りに行くような場合、毎度丸ごと一ページが出てくるので邪魔だなーと。

で、なんだかんだでぱるる初心者ですがでっち上げてみました><

キャッシュはDB_Fileじゃないほうがいいような希ガス(簡単そうだったDeduped::DB_Fileのコードをそのままマネた)。

package Plagger::Plugin::Filter::Diff;

use strict;
use base qw( Plagger::Plugin );

use DB_File;
use Algorithm::Diff qw( traverse_sequences );

sub register {
    my($self, $context) = @_;
    $context->register_hook(
        $self,
        'plugin.init'        => \&initialize,
        'update.entry.fixup' => \&filter,
    );
}

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

    $self->{path} = $self->conf->{path} || Plagger->context->cache->path_to('Filter-Diff.db');
    $self->{db} = tie my %cache, 'DB_File', $self->{path}, O_RDWR|O_CREAT, 0666, $DB_HASH
        or Plagger->context->error("Can't open DB_File $self->{path}: $!");
}

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

    my $entry = $args->{entry};

    my $body_new = $entry->body ? $entry->body->utf8 : undef;
    my $body_prev;
    my $status = $self->{db}->get($entry->permalink, $body_prev);

    if ($status != 1) {
        Plagger->context->log( debug => "previous entry data found" );

        my @lines = split /^/, $body_new;
        my @lines_prev = split /^/, $body_prev;

        my $body_diffed = '';
        traverse_sequences(\@lines_prev, \@lines,
            {
                DISCARD_B => sub {
                    Plagger->context->log( debug => "new line: $lines[$_[1]]" );
                    $body_diffed .= $lines[$_[1]];
                }
            }
        );
        $entry->body($body_diffed);
    }

    Plagger->context->log( debug => "Save entry data: ".$entry->permalink );
    $self->{db}->put($entry->permalink, $body_new);

}

1;

差分を保持しないので、このままでははてなアンテナは作れないぽ。


Plagger::Cache を使ってみるテスト。こういう用途に使っていいんでしょうか。

package Plagger::Plugin::Filter::Diff;

use strict;
use base qw( Plagger::Plugin );

use Plagger::Cache;

use Algorithm::Diff qw( traverse_sequences );

sub register {
    my($self, $context) = @_;
    $context->register_hook(
        $self,
        'plugin.init'        => \&initialize,
        'update.entry.fixup' => \&filter,
    );
}

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

    my $params = {
        base    => $self->conf->{path} || File::Spec->catfile(Plagger->context->cache->{base}, 'Filter-Diff'),
        expires => $self->conf->{expires},
    };

    $self->{cache} = Plagger::Cache->new($params);
}

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

    my $entry = $args->{entry};

    my $body_new = $entry->body ? $entry->body->utf8 : undef;
    my $body_prev = $self->{cache}->get($entry->permalink);

    if ($body_prev) {
        Plagger->context->log( debug => "previous entry data found" );

        my @lines = split /^/, $body_new;
        my @lines_prev = split /^/, $body_prev;

        my $body_diffed = '';
        traverse_sequences(\@lines_prev, \@lines,
            {
                DISCARD_B => sub {
                    Plagger->context->log( debug => "new line: $lines[$_[1]]" );
                    $body_diffed .= $lines[$_[1]];
                }
            }
        );
        $entry->body($body_diffed);
    }

    Plagger->context->log( debug => "Save entry data: ".$entry->permalink );

    $self->{cache}->set($entry->permalink, $body_new);
}

1;
トラックバック - http://subtech.g.hatena.ne.jp/mayuki/20061029