naoyaの日記 RSSフィード

 | 

2006-03-15

しょこたん 23:46

NHK BS2 で 26 日だかにこれであなたもブログ通とかいうしょうもない番組が放映されるようですが、そのゲストというかコメンテーター(?) にしょこたんが出るようですよ全国のファンのみなさん。

Publish::Serializer 23:40

Data::Serializer を使うように変更。config.yml で serializer を指定することでいろんなフォーマットで書き出せる。

  - module: Publish::Serializer
    config:
      serializer: YAML
      dir: /Users/naoya/tmp
      filename: test.yml

シリアライズは Data::Serializer が面倒をみることになり、サブクラスを用意する必要はなくなった。raw_serialize してるので Data::Serializer の圧縮とか暗号オプションとか使えないけども。

package Plagger::Plugin::Publish::Serializer;
use strict;
use warnings;
use base qw (Plagger::Plugin);

use File::Spec;
use IO::File;
use Data::Serializer;

sub serialize {
    my ($self, $data) = @_;
    my $option = $self->conf->{option} || {};
    my $selializer =  Data::Serializer->new(
        serializer => $self->conf->{serializer} || 'Data::Dumper',
    );
    $selializer->raw_serialize($data);
}

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

sub feed2data {
    my ($self, $feed) = @_;
    my $data = {
        feed => {
            title => $feed->title,
            link  => $feed->link,
            generator => join('/', 'Plagger', $Plagger::VERSION),
        }
    };
    for my $entry ($feed->entries) {
        my $eobj = {};
        $eobj->{$_} = $entry->$_ for qw(title link body author tags);
        push @{$data->{feed}->{entries}}, $eobj;
    }
    $data;
}

sub feed {
    my ($self, $context, $args) = @_;
    my $dir = $self->conf->{dir};
    unless (-e $dir && -d _) {
        mkdir $dir, 0755 or $context->error("mkdir $dir: $!");
    }
    my $file = $self->gen_filename($args->{feed}) ||
        $args->{feed}->id . __PACKAGE__->default_file_extention;
    my $path = File::Spec->catfile($dir, $file);
    my $serialized = $self->serialize(
        $self->feed2data($args->{feed})
    );
    my $io = IO::File->new("> $path");
    $io->print($serialized);
    $io->close;
    $context->log(
        info => sprintf(
            "Write to %s: %d entries",
            $path,
            $args->{feed}->count
        )
    );
}

my %formats = (
    'u' => sub { my $s = $_[0]->url;  $s =~ s!^https?://!!; $s },
    'l' => sub { my $s = $_[0]->link; $s =~ s!^https?://!!; $s },
    't' => sub { $_[0]->title },
    'i' => sub { $_[0]->id },
);

my $format_re = qr/%(u|l|t|i)/;

sub gen_filename {
    my($self, $feed) = @_;

    my $file = $self->conf->{filename} || '';
    $file =~ s{$format_re}{
        $self->safe_filename($formats{$1}->($feed))
    }egx;

    $file;
}

sub safe_filename {
    my($self, $path) = @_;
    $path =~ s![^\w\s]+!_!g;
    $path =~ s!\s+!_!g;
    $path;
}

1;

ただ、Data::Serializer は JSONサポートしてない。そもそもこのプラグインを作ったのはフィードJSON に変換したかったからなのだよママン。

ということで Data::Serializer::JSON を作る。

package Data::Serializer::JSON;
BEGIN { @Data::Serializer::JSON::ISA = qw(Data::Serializer) }

use strict;
use JSON;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

require Exporter;
require AutoLoader;

@ISA = qw(Exporter AutoLoader);
@EXPORT = qw(

);
$VERSION = '0.01';

1;
__END__

=head1 NAME

Data::Serializer::JSON - Creates bridge between Data::Serializer and Storable

=head1 SYNOPSIS

  use Data::Serializer::JSON;

=head1 DESCRIPTION

Module is used internally to Data::Serializer

=head1 AUTHOR

Naoya Ito <naoya@bloghackers.net>

=head1 COPYRIGHT

  This program is free software; you can redistribute it
  and/or modify it under the same terms as Perl itself.

=head1 SEE ALSO

perl(1), Data::Serializer(3), JSON(3).

=cut

sub serialize {
    return JSON->new->objToJson($_[1]);
}

sub deserialize {
    return JSON->new->jsonToObj($_[1]);
}

Data::Serializer の他のクラスの実装に併せて作ってるのでちょっとださいけどまあしゃあない。AutoLoader を使う必要があるので AutoSplit が走るように make を実行したりとかがめんどい

よし、作者にパッチを送ろうとおもったがしかし、Data::Serializer のテストが超わかんない。しょうがないのでテスト放置でついでに JSON::Syck と YAML::Syck も作った。

package Data::Serializer::YAML::Syck;
BEGIN { @Data::Serializer::YAML::Syck::ISA = qw(Data::Serializer) }

use strict;
use YAML::Syck;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

require Exporter;
require AutoLoader;

@ISA = qw(Exporter AutoLoader);
@EXPORT = qw(
	
);
$VERSION = '0.01';

1;
__END__

sub serialize {
    return Dump($_[1]);
}

sub deserialize {
    return Load($_[1]);
}
package Data::Serializer::JSON::Syck;
BEGIN { @Data::Serializer::JSON::Syck::ISA = qw(Data::Serializer) }

use strict;
use JSON::Syck;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

require Exporter;
require AutoLoader;

@ISA = qw(Exporter AutoLoader);
@EXPORT = qw(
	
);
$VERSION = '0.01';

1;
__END__

sub serialize {
    return Dump($_[1]);
}

sub deserialize {
    return Load($_[1]);
}

YAML.pm と比べてもそれぞれ一行しか違わないんだけど。全然 DRY じゃない!

Publish::Serialize 12:35

Data::Serializer 使えばいいとのこと。JSON がないので作るべしと。JSONCPANうpするより作者に送った方がよさそうな雰囲気。

Plagger::Plugin::Publish::Serialize 12:18

ETech から帰る飛行機の中で Hack したやつ。まだ仕上げ切れてない感じですがとりあえず。

  - module: Publish::Serialize
    config:
      driver: JSON
      dir: /Users/naoya/tmp
      filename: test.js

driver を変更すれば出力のフォーマットを変えられる。JSON / YAML / Dumper が指定可能。XML とか Storable とか色々作れそうかも。

YAML ではき出すと

---
feed:
  entries:
    - 
      author: ~
      body: oh my god
      link: http://localhost/1
      tags: []

      title: first entry
    - 
      author: ~
      body: wow! amazing!
      link: http://localhost/2
      tags: []

      title: second entry
  generator: Plagger/0.5.7
  link: http://localhost/
  title: config feed

という具合。なんか tags が [] とかになってるな、なんだこれ。

package Plagger::Plugin::Publish::Serialize;
use strict;
use warnings;
use base qw (Plagger::Plugin);

use Encode;
use File::Spec;
use IO::File;
use UNIVERSAL::require;

sub init {
    my $self = shift;
    $self->SUPER::init(@_);
    my $class = join '::', __PACKAGE__, $self->conf->{driver} || 'YAML';
    $class->require or Plagger->context->error(
        'No Such a Driver: ' . $self->conf->{driver}
    );
    bless $self, $class;
}

sub serialize {
    my ($self, $data) = @_;
    die "I am abstract method";
}

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

sub feed2data {
    my ($self, $feed) = @_;
    my $data = {
        feed => {
            title => $feed->title,
            link  => $feed->link,
            generator => join('/', 'Plagger', $Plagger::VERSION),
        }
    };
    for my $entry ($feed->entries) {
        my $eobj = {};
        $eobj->{$_} = $entry->$_ for qw(title link body author tags);
        push @{$data->{feed}->{entries}}, $eobj;
    }
    $data;
}

sub feed {
    my ($self, $context, $args) = @_;
    my $dir = $self->conf->{dir};
    unless (-e $dir && -d _) {
        mkdir $dir, 0755 or $context->error("mkdir $dir: $!");
    }
    my $file = $self->gen_filename($args->{feed}) ||
        $args->{feed}->id . __PACKAGE__->default_file_extention;
    my $path = File::Spec->catfile($dir, $file);
    my $serialized = $self->serialize(
        $self->feed2data($args->{feed})
    );
    my $io = IO::File->new("> $path");
    $io->print($serialized);
    $io->close;
    $context->log(
        info => sprintf(
            "Write to %s: %d entries",
            $path,
            $args->{feed}->count
        )
    );
}

my %formats = (
    'u' => sub { my $s = $_[0]->url;  $s =~ s!^https?://!!; $s },
    'l' => sub { my $s = $_[0]->link; $s =~ s!^https?://!!; $s },
    't' => sub { $_[0]->title },
    'i' => sub { $_[0]->id },
);

my $format_re = qr/%(u|l|t|i)/;

sub gen_filename {
    my($self, $feed) = @_;

    my $file = $self->conf->{filename} || '';
    $file =~ s{$format_re}{
        $self->safe_filename($formats{$1}->($feed))
    }egx;

    $file;
}

sub safe_filename {
    my($self, $path) = @_;
    $path =~ s![^\w\s]+!_!g;
    $path =~ s!\s+!_!g;
    $path;
}

1;

TODO は

  • feed2data の中で情報が抜け落ちてるものがあるのでそれを処理するようにしないと。
    • feed.date / entry.date とか
  • tags はちゃんと処理できてる?
  • convert メソッドがないざます

あたりかな。

ドライバの実装は serialize をオーバーライドして dump すると。

package Plagger::Plugin::Publish::Serialize::JSON;
use strict;
use warnings;
use base qw (Plagger::Plugin::Publish::Serialize);
use JSON::Syck;

use constant default_file_extention => 'js';

sub serialize {
    my ($self, $data) = @_;
    return JSON::Syck::Dump($data);
}

1;

こんなの。

FF 08:05

Amazon.co.jpからのお知らせ

お客様からご注文いただいた商品を本日発送させていただきました。

ご注文の処理が完了しましたのでお知らせします。

Amazon.co.jpをご利用いただき、ありがとうございました。またのご利用を
お待ちしております。

今回発送する商品は以下のとおりです。
---------------------------------------------------------------------
数量      商品                           価格  発送済み          小計
---------------------------------------------------------------------
1             ファイナルファンタジーXII 特典 ¥7,911      1             ¥7,911
             販売元: Amazon.com Int'l Sales, Inc. -

---------------------------------------------------------------------

きたー。もしかして今日届いちゃったりする?

自宅サーバーからメールが送れない 07:48

どこのメールサーバメールを送っても Connection timed out。変だなー、と思って調べてみるも原因がさっぱり、でたまたま巷で話題になってたのを思い出した。

これのせいかなー。ニフティ回線使ってて自宅サーバーの人はどうしてるんだろ。smtp.nifty.com を指定すればいいのか。

postfix/main.cf

relayhost = smtp.nifty.com

とした。

んで今まで溜まってたメール

$ sudo /usr/sbin/postfix flush

で queue をフラッシュ。うまく送れてるようだ。Outbound 25 Block のことをたまたま聞いたことがあったからよかったけど、そうじゃなかったらめちゃめちゃはまってたくさいなー。怖い怖い。

hori-uchihori-uchi2006/03/15 10:16僕もamazonから来てた!

TigerTiger2006/03/15 12:00全部が全部、2/15に実施ではないということで、ポロッポロッと話題になりますね (^^;

トラックバック - http://naoya.g.hatena.ne.jp/naoya/20060315
 | 
この日記のはてなブックマーク数