読者です 読者をやめる 読者になる 読者になる

1日のTwitterをまとめてMixi日記になげるレシピ

Twitterをはじめると、mixiの日記を書かなくなることが多い?なんて記事が出てくるくらいTwitterには中毒性があるようで、なら1日のTwitterMixiに投げたら良いじゃん。それPla。というわけでPlaggerでやってみた。< Twitterid:otsuneさんがいってたのをパクリました。すいません。
Frepaへの投稿ならPlagger で Twitter のステータスを Frepa に投稿 - HsbtDiary (2007-04-22)で良いみたいなので、まねして書いてみたら1Twit*1が1つの日記になってしまうので、1日分を夜にまとめてMixiへというのには向いてない。エントリをまとめる方法がわからなかったのでPlaggerのFilterを書いてみた。

Plagger::Plugin::Filter::AssembleEntries.pm (Plagger 0.7.17で動作確認しています)
UTF-8で保存してください。保存したときに\が\(バックスラッシュ)になることがありますが同じなので問題ありません。

package Plagger::Plugin::Filter::AssembleEntries;
use strict;
use base qw( Plagger::Plugin );

use Plagger::Entry;
use utf8;
use Encode;

sub register {
    my($self, $context) = @_;
    $context->register_hook(
        $self,
        'update.entry.fixup' => \&assemble,
        'update.feed.fixup' => \&finalize,
    );
}

sub assemble {
    my($self, $context, $args) = @_;
    my $body = $args->{entry}->body->plaintext;
    my $del_word = $self->conf->{del_word} || undef;
    $body =~ s/$del_word// if($del_word);

    if($self->conf->{timelabel} && $self->conf->{timelabel} =~ /(:?ymd|hms)/){
        my $tz = $self->conf->{timezone} || 'local';
        my $time = $args->{entry}->date->set_time_zone($tz);
        my $label = $time->ymd." ".$time->hms;
        $label = $time->ymd if($self->conf->{timelabel} eq 'ymd');
        $label = $time->hms if($self->conf->{timelabel} eq 'hms');
        push @{$self->conf->{assemble}}, $label." ".$body;
    }else{
        push @{$self->conf->{assemble}}, $body;
    }
}

sub finalize {
    my($self, $context, $args) = @_;
    
    $context->log(debug => "Assembling Entries");
    
    my $title = $self->conf->{title} || "Assembled Entry";
    my $link = $self->conf->{link} || "No Link";
    my $delimiter = $self->conf->{delimiter} || "<br />";
    my $reverse = $self->conf->{reverse} || undef;
    my $empty_msg = $self->conf->{empty_msg} || "This Feed have No Matched Entry.";
    my $tz = $self->conf->{timezone} || 'local';
    
    if(defined $self->conf->{assemble} && $reverse){
        my @rev = reverse @{$self->conf->{assemble}};
        $self->conf->{assemble} = \@rev;
    }

    my $e = Plagger::Entry->new;
    $e->title(_u($title));
    $e->permalink(_u($link));
    
    if(defined @{$self->conf->{assemble}}){
        $e->body(join $delimiter, @{$self->conf->{assemble}});
    }else{
        $e->body($empty_msg);
    }
    $e->date(Plagger::Date->now($tz));

    $args->{feed}->{entries} = [$e];
}

sub _u {
    my $str = shift;
    Encode::_utf8_on($str);
    $str;
}

1;
__END__

=head1 NAME

Plagger::Plugin::Filter::AssembleEntries - Assemble entries in feed

=head1 SYNOPSIS

  - module: Filter::AssembleEntries
    config:
      title: Title of The Assembled Entry
      link: http://example.com/
      delimiter: <br />
      reverse: 1
      timelabel: ymd
      del_word: WORD
      empty_msg: Oops!

=head1 DESCRIPTION

This plugin is to assemble entries in Feed.

=head1 AUTHOR

Toshi

=cut

Feedからエントリの内容を読み込んで一つにまとめてFeedのエントリと差し替えるだけのフィルタ。yamlでひとまとめにするときの区切り文字、順番を逆順にするかどうか、まとめてできたエントリのタイトルとか設定できるようにした。
まとめていく課程でエントリを一時的に$self->conf->{assemble}に入れてるんだけど、これがかっこわるい。これなおしたいけどどうしたらいいのかな?

こんな簡単なFilterだけど書くのに結構時間がかかっちゃいました。でもおかげでPlaggerの中身がだいぶんわかった気になったので、いまPlaにFilterの書き方でもかきたいな。


TwitterからMixiへ投稿するときのyamlはこんな感じ。

plugins:
  - module: Subscription::Config
    config:
      feed:
        - url: http://twitter.com/statuses/user_timeline/ユーザID.atom

  - module: Filter::AssembleEntries
    rule:
      expression: $args->{entry}->date->set_time_zone('Asia/Tokyo')->ymd eq Plagger::Date->now(timezone=>'Asia/Tokyo')->ymd
    config:
      title: 今日のTwitter
      link: http://twitter.com/xxxxxx/
      delimiter: <br />
      reverse: 1
      timelabel: hms
      empty_msg: なにもTwiってないよ。
      del_word: Toshi:

  - module: Publish::MixiDiary
    config:
      username: xxxxx@example.com
      password: password
      interval: 10

Filterのなかにあるexpressionにはルールを書く。上の例だと今日の分だけ指定している。TwitterのFeedは時間がGMT(+00:00)なのでAsia/Tokyoに変換してる。これを昨日の分だけ、かつ誰かに@で話しかけたログとsuVeneのあれさんのHatenaB with twitterからの投稿は取り除くようにすると

expression: $args->{entry}->date->set_time_zone('Asia/Tokyo')->ymd 
            eq Plagger::Date->now(timezone=>'Asia/Tokyo')->subtract(days=>1)->ymd
         && $args->{entry}->body->plaintext !~ /(:?ユーザ名:\s+@|Bookmarking)/

ホントは1行で書いてください。ここでのユーザ名はログイン名じゃなくて設定した名前になっているので注意。これもUTF-8で保存してください。Twitterのフィードは最新20件だけなので、それ以上投稿してると頭の方がなくなります。多い方は1日2回以上回すのがオススメ。
MixiDiary.pmはA FreeBSD GIMPer PlaggerをつかってBlogとMixiの日記を同期させるを使わせていただいてます。うちの環境だと日記作成のところできちんと作成できているのにエラーメッセージがでます。なんでかな?

しかしこれ、激しく車輪の再開発の臭いがする・・・。
もっとスマートなやり方があったら教えてください。

参考サイト

*1:Twitterへの1投稿