はちゅにっき

こっちのブログはまったり更新

1日の Twitter の発言を HatenaDiary に書き込む

Hatena::Gropu::Twitter ではその日の Twitter を、日記として POST する方もいらっしゃるようで。
というわけで、やってみよー。
でも、みんなどーやってるんだろう?
と、思ったけれど「それ Plagger でできるよ!」という声がした気がするので、Plagger でやることに。

長文なので先にまとめ

既存の Plugin でそのままやると、1発言が1エントリになってしい相当ウザイので、いろいろ考えた結果
Plagger::Plugin::Publish::Twitter2HatenaDiary (名前はてきとーだよ!)
なるものを書きましたとさ。
そしたら Plagger の勉強にもなったしよかったね。
めでたしめでたし。

Plagger のインストールは?

Debian/lenny への Plagger インストールはsvn からチェックアウトして make するパターンでやりました。
ただし、XML::SAX というモジュールに関しては

debianMySQL - seechickenの日記
http://d.hatena.ne.jp/seechicken/20060509

とか

aptitude で libxml-sax-perl が入らない! (blog.aklaswad.com)
http://blog.aklaswad.com/2006/000071.html

とか

CPANモジュールのアンインストール(改良版) - holidays-l開発ブログ
http://d.hatena.ne.jp/holidays-l/20080824/p1

とかが役に立ちました。
感謝。

はてなダイアリー に POST する

当然 Plugin があるんだろうなー。
と探していたら

Publish-HatenaDiary
http://plagger.org/trac/browser/trunk/plagger/lib/Plagger/Plugin/Publish/HatenaDiary.pm

どうやら標準で入っているらしい。
せっかくなのでソースを眺めてみると、はてなダイアリーの POST に

WWW-HatenaDiary
http://d.hatena.ne.jp/antipop/20080114/1200329868

を利用しているようで。
あれ?でもこのモジュール、はてなダイアリー API じゃないね。
ならば、API を利用している

WebService-Hatena-Diary
http://search.cpan.org/~hakobe/WebService-Hatena-Diary-0.01/lib/WebService/Hatena/Diary.pm

にのせかえたいよね。
インタフェースは共通のようなので、単純に use するモジュールを変えれば終わりだー。
と思っていたら「はてなグループ」には API がないため、今回目標とする、はてなグループの日記に POST することはできないみたい。
というわけで、はてなグループAPI に対応するまでのせかえはおあずけ。
それならば、適当にレシピを書いて、上手くいくか試しに実行!
してみたら、1発言が日記1つとして登録された。。。
これはうざすぎる。
というわけで、誰かやってないかなー。
とぐぐってみるもののmixi に投稿するレシピはあれど、はてなダイアリーは見つからない。。。
う〜ん?なんでだろう?
「こんなのできて当然すぎるだろjk」とかそんな感じなのかなぁ?

なら Plagger の勉強ついでに作っちゃえば?

うん、そうしよう。
Plagger の Plugin なんて作ったこともないけれど、今回は
Publish::HatenaDiary
を継承すれば作れそうだから、結構簡単だよね!きっと。

どうつくる?

というわけで、mixi に投稿するためのレシピを紹介している

Write Life フィードの取得件数を簡単に増減させる方法
http://konton0324.blog54.fc2.com/blog-entry-62.html

1日のTwitterをまとめてMixi日記になげるレシピ - Muibrog
http://d.hatena.ne.jp/toshi123/20070424

を参考にして作成することに。
つまり feed の流れは

  1. Twitter API
  2. Google Reader
  3. Plagger
  4. HatenaDiary

という感じで。
API からの取得を工夫すれば、Google Reader を途中で経由する必要はなさそうだけれども。。。
あと、発言をまとめる方法については、上記のエントリに記載されていたけれど、エントリを連結してしまうのは、なんとなく違和感を感じるので他の方法を考えることに。
Publish::Gmail はバラバラにならずにメールがくるので、publish の段階でエントリをまとめる方法も、調べれば分かりそうだしね。

つくってみよー

Publish::Gmail がバラバラにならないのは、どうやらフックするポイントにあるらしい

mizzy.org - Plagger プラグインの実行フェーズ
http://blog.mizzy.org/articles/2006/09/24/plagger_plugin_phase

Publish::HatenaDiary は publish.entry を hook しているけれど、これだと、エントリごと、つまり 1Twitte ごと実行されるみたい。
よって、publish.feed を hook すれば feed ごと呼ばれることになり、そこでエントリを結合すればいいってことだよね?
じゃ、Publish::Hatena を継承して作ろう。
あ、継承ではまったけれど

Plaggerで他のプラグインを継承するときの注意というかメモ - 空繰再繰
http://blog.nyarla.net/2007/04/15/1

がすごく役立にたちました。
そんなわけで、完成したのが以下のソース。

package Plagger::Plugin::Publish::Twitter2HatenaDiary;

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

use Encode;


sub register
{
    my ($self, $c) = @_;
    $c->register_hook(
        $self,
        'plugin.init'      => $self->can('initialize'),
        'publish.init'     => $self->can('publish_init'),

        # 'publis.entry' => \&publish_entry
        #  となっていたのでオーバーライド
        'publish.feed'     => $self->can('publish_feed'),
        'publish.finalize' => $self->can('publish_finalize'),
    );
}

sub publish_feed
{
    my($self, $c, $args) = @_;

    return if $args->{feed}->count == 0;

    my $title = $self->conf->{title} || $args->{feed}->title;
    my $body  = $self->templatize('template.tt', $args);

    my $uri = $self->{diary}->create({
        title => encode_utf8($title),
        body  => encode_utf8($body),
    });

    $c->log(debug => "Post entry success: $uri");
}

1;
__END__

あと、asset が必要な設計なので asset も作った。
といっても単純に、feed を foreach して発言をまとめることと
(Template-Toolkit が使われているんだね!)

時刻 発言

となるように書いただけだけれど。

[% FOREACH entry = feed.entries -%]
|*[% entry.date.set_time_zone('Asia/Tokyo').strftime("%H:%M:%S") %]|[% entry.body %]|
[% END %]

はい、終了。
というわけで、簡単な Plugin だけれども、Plugin の作り方や asset、hook などなど、Plagger の中を知るいい機会になりました。

最後に、今うごかしている config.yaml をぺた。
これを crontab で 1日1回実行するようにセット。
あ、Filter::Reverse は

nirvashの日記 - [sbm] del.icio.us to hatebu
http://d.hatena.ne.jp/nirvash/20060511/1147298244

にあるのを利用させていただきました。

# こんな感じの場所にファイルを置いてるよ
global:
 plugin_path:
  - /home/my/plagger/twitter/lib/
 assets_path: /home/my/plagger/twitter/assets
 timezone: Asia/Tokyo

plugins:
 # google のフィードからもってくるよ
 # 詳しくは http://konton0324.blog54.fc2.com/blog-entry-62.html
 - module: Subscription::Config
   config:
    feed:
     - url: http://www.google.com/reader/public/atom/hogehogehogehoge?n=50

 # 重複エントリを POST しない
 #  -> これで、その日(?)の発言だけ拾えないかな?
 # 現在検証中 (たぶん OK っぽい)
 - module: Filter::Rule
   rule:
    module: Deduped
    path: /home/my/plagger/twitter/deduped.log

 # 接頭語になる部分 (自分の Twitter Name) を削る
 - module: Filter::Rule
   rule:
    expression: $args->{entry}->{body} =~ s/<Twitterの名前>: //

 # 新しい発言が上になるよう逆転させる
 #  http://d.hatena.ne.jp/nirvash/20060511/1147298244 にあります。
 - module: Filter::Reverse

 # publish
 # グループを書かなければ、自分の日記に POST されるよ
 - module: Publish::Twitter2HatenaDiary
   config:
    username: <ゆーざめい>
    group: <ぐるーぷ>
    password: <ぱすわーど>
    title: きのうくらいのついったー

追記のメモ

Google Reader のアップデート探索は、読者数が少ないと (1人の場合のみ?)3時間に1回しか巡回しない。
ということは、3時間に20回以上発言すると、このスクリプトだと取りこぼす可能性があるね!
何か対応策を考える?
はてなRSS はどうなんだろう。
それがダメなら自前で store するしかないかな?